Come generare il simbolo di debug di gcc al di fuori del target di compilazione?

So che posso generare il simbolo di debug usando l’opzione -g. Tuttavia il simbolo è incorporato nel file di destinazione. Potrebbe gcc generare un simbolo di debug al di fuori del risultato eseguibile / libreria? Come il file .pdb del compilatore VC ++ di Windows.

È necessario utilizzare objcopy per separare le informazioni di debug :

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

Io uso lo script di bash qui sotto per separare le informazioni di debug in file con estensione .debug in una directory .debug. In questo modo posso tar le librerie e gli eseguibili in un file tar e nelle directory .debug in un altro. Se voglio aggiungere le informazioni di debug in seguito, estraggo semplicemente il file tar di debug e voilà ho informazioni di debug simboliche.

Questo è lo script di 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} " } 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}" 

Compilare con le informazioni di debug:

 gcc -g -o main main.c 

Separa le informazioni di debug:

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

o

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

Elimina le informazioni di debug dal file di origine:

 objcopy --strip-debug main 

o

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

eseguire il debug in modalità debuglink:

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

Puoi anche usare il file exec e il file simbolo separatamente:

 gdb -s main.debug -e main 

o

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

Per dettagli:

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

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

Controlla l’opzione “–only-keep-debug” del comando strip .

Dal link:

L’intenzione è che questa opzione venga utilizzata insieme a –add-gnu-debuglink per creare un eseguibile in due parti. Un binario spogliato che occuperà meno spazio nella RAM e in una distribuzione e il secondo un file di informazioni di debug che è necessario solo se sono richieste capacità di debug.

NOTA: i programmi compilati con livelli di ottimizzazione elevati (-O3, -O4) non possono generare molti simboli di debug per variabili ottimizzate, funzioni in-linea e loop srotolati, indipendentemente dal fatto che i simboli siano incorporati (-g) o estratti (objcopy) in un File ‘.debug’.

Approcci alternativi sono

  1. Incorporare i dati di versioning (VCS, git, svn) nel programma, per eseguibili ottimizzati dal compilatore (-O3, -O4).
  2. Costruisci una seconda versione non ottimizzata dell’eseguibile.

La prima opzione fornisce un mezzo per ribuild il codice di produzione con debug e simboli completi in un secondo momento. Essere in grado di ribuild il codice di produzione originale senza ottimizzazioni è un enorme aiuto per il debug. (NOTA: questo presuppone che il test sia stato eseguito con la versione ottimizzata del programma).

Il tuo sistema di compilazione può creare un file .c caricato con la data di compilazione, il commit e altri dettagli VCS. Ecco un esempio di ‘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 

Dopo aver compilato il programma, puoi individuare il “commit” originale per il tuo codice usando il comando: strings -a my_program | grep VCS 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 

Non resta che controllare il codice originale, ricompilare senza ottimizzazioni e avviare il debug.