¿Cómo generar el símbolo de depuración gcc fuera del objetivo de compilación?

176

Sé que puedo generar el símbolo de depuración usando la opción -g. Sin embargo, el símbolo está incrustado en el archivo de destino. ¿Podría gcc generar un símbolo de depuración fuera del resultado ejecutable / biblioteca? Al igual que el archivo .pdb del compilador VC ++ de Windows.

kcwu
fuente

Respuestas:

184

Debe usar objcopy para separar la información de depuración :

objcopy --only-keep-debug "${tostripfile}" "${debugdir}/${debugfile}"
strip --strip-debug --strip-unneeded "${tostripfile}"
objcopy --add-gnu-debuglink="${debugdir}/${debugfile}" "${tostripfile}"

Utilizo el script bash a continuación para separar la información de depuración en archivos con una extensión .debug en un directorio .debug. De esta manera puedo tar las bibliotecas y ejecutables en un archivo tar y los directorios .debug en otro. Si deseo agregar la información de depuración más adelante, simplemente extraigo el archivo tar de depuración y listo, tengo información de depuración simbólica.

Este es el script bash:

#!/bin/bash

scriptdir=`dirname ${0}`
scriptdir=`(cd ${scriptdir}; pwd)`
scriptname=`basename ${0}`

set -e

function errorexit()
{
  errorcode=${1}
  shift
  echo $@
  exit ${errorcode}
}

function usage()
{
  echo "USAGE ${scriptname} <tostrip>"
}

tostripdir=`dirname "$1"`
tostripfile=`basename "$1"`


if [ -z ${tostripfile} ] ; then
  usage
  errorexit 0 "tostrip must be specified"
fi

cd "${tostripdir}"

debugdir=.debug
debugfile="${tostripfile}.debug"

if [ ! -d "${debugdir}" ] ; then
  echo "creating dir ${tostripdir}/${debugdir}"
  mkdir -p "${debugdir}"
fi
echo "stripping ${tostripfile}, putting debug info into ${debugfile}"
objcopy --only-keep-debug "${tostripfile}" "${debugdir}/${debugfile}"
strip --strip-debug --strip-unneeded "${tostripfile}"
objcopy --add-gnu-debuglink="${debugdir}/${debugfile}" "${tostripfile}"
chmod -x "${debugdir}/${debugfile}"
lothar
fuente
8
Si tiene un problema en la producción y necesita adjuntar el proceso con gdb, ¿podrá proporcionar el archivo de símbolo de depuración a GDB? ¿Y cómo, si es así? thnx
yves Baumes
3
@yves Baumes Simplemente agregue el directorio .debug con los archivos .debug a su caja de producción y GDB debería recogerlos. Después de la sesión de depuración, puede eliminarlos nuevamente.
lothar
Consulte los comentarios de respuesta de @Lance Richardson para ver un ejemplo.
GuruM
77
¿También es posible restaurar el binario original (p. Ej. Binario eliminado + archivo .debug = binario original)?
Paul Praet
1
¿Encuentra algún problema al omitir la --build-idopción de enlazador ?
JWW
110

Compilar con información de depuración:

gcc -g -o main main.c

Separe la información de depuración:

objcopy --only-keep-debug main main.debug

o

cp main main.debug
strip --only-keep-debug main.debug

Elimine la información de depuración del archivo de origen:

objcopy --strip-debug main

o

strip --strip-debug --strip-unneeded main

depuración por modo de enlace de depuración:

objcopy --add-gnu-debuglink main.debug main
gdb main

También puede usar el archivo exec y el archivo de símbolos por separado:

gdb -s main.debug -e main

o

gdb
(gdb) exec-file main
(gdb) symbol-file main.debug

Para detalles:

(gdb) help exec-file
(gdb) help symbol-file

Ref:
https://sourceware.org/gdb/onlinedocs/gdb/Files.html#Files https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html

herodot
fuente
2
Y debe usar objcopy --add-gnu-debuglink main main.debugpara incrustar el nombre del archivo de depuración creado y una suma de verificación. En este caso, gdb intentará encontrar el código de depuración en algunas ubicaciones dependientes de distribución, ya no se necesita ninguna opción.
Lothar
9

Consulte la opción "--only-keep-debug" del comando strip .

Desde el enlace:

La intención es que esta opción se use junto con --add-gnu-debuglink para crear un ejecutable de dos partes. Uno es un binario despojado que ocupará menos espacio en RAM y en una distribución y el segundo un archivo de información de depuración que solo es necesario si se requieren habilidades de depuración.

Lance Richardson
fuente
1
Sí, lo he intentado: gcc -ggdb -o test test.c; prueba cp test.debug; strip --only-keep-debug test.debug; tira de prueba; objcopy --add-gnu-debuglink = test.debug test; Entonces está bien depurar la prueba
zhaorufei
8

NOTA: Los programas compilados con niveles de alta optimización (-O3, -O4) no pueden generar muchos símbolos de depuración para variables optimizadas, funciones alineadas y bucles desenrollados, independientemente de los símbolos que se incrustan (-g) o se extraen (objcopy) en un archivo '.debug'.

Los enfoques alternativos son

  1. Incruste los datos de control de versiones (VCS, git, svn) en el programa, para los ejecutables optimizados del compilador (-O3, -O4).
  2. Cree una segunda versión no optimizada del ejecutable.

La primera opción proporciona un medio para reconstruir el código de producción con depuración completa y símbolos en una fecha posterior. Poder reconstruir el código de producción original sin optimizaciones es una gran ayuda para la depuración. (NOTA: Esto supone que las pruebas se realizaron con la versión optimizada del programa).

Su sistema de compilación puede crear un archivo .c cargado con la fecha de compilación, el compromiso y otros detalles de VCS. Aquí hay un ejemplo de 'make + git':

program: program.o version.o 

program.o: program.cpp program.h 

build_version.o: build_version.c    

build_version.c: 
    @echo "const char *build1=\"VCS: Commit: $(shell git log -1 --pretty=%H)\";" > "$@"
    @echo "const char *build2=\"VCS: Date: $(shell git log -1 --pretty=%cd)\";" >> "$@"
    @echo "const char *build3=\"VCS: Author: $(shell git log -1 --pretty="%an %ae")\";" >> "$@"
    @echo "const char *build4=\"VCS: Branch: $(shell git symbolic-ref HEAD)\";" >> "$@"
    # TODO: Add compiler options and other build details

.TEMPORARY: build_version.c

Después de compilar el programa, puede ubicar el 'commit' original para su código utilizando el comando: strings -a my_program | grep VCS

VCS: PROGRAM_NAME=my_program
VCS: Commit=190aa9cace3b12e2b58b692f068d4f5cf22b0145
VCS: BRANCH=refs/heads/PRJ123_feature_desc
VCS: AUTHOR=Joe Developer  joe.developer@somewhere.com
VCS: COMMIT_DATE=2013-12-19

Todo lo que queda es verificar el código original, volver a compilar sin optimizaciones y comenzar a depurar.

J Jorgenson
fuente
3
-O4Ni siquiera existe.
Hola Ángel
3
Vaya, eso puede ser de los días de mayo 'suncc', donde '-O5' era incluso una opción. Aquí hay un enlace a las opciones gcc4.4.7 -O: gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/…
J Jorgenson
3
Esto no soluciona el problema común de tratar de interpretar un volcado de núcleo que puede no ser fácilmente reproducible. El consejo en esta respuesta es sólido, pero no aborda la pregunta.
David Rodríguez - dribeas
4

Ninguna respuesta hasta ahora menciona eu-strip --strip-debug -f <out.debug> <input>.

  • Esto es proporcionado por elfutilspaquete.
  • El resultado será que el <input>archivo ha sido despojado de símbolos de depuración que ahora están todos dentro <out.debug>.
Unapiedra
fuente