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


176

So di poter generare il simbolo di debug usando l'opzione -g. Tuttavia, il simbolo è incorporato nel file di destinazione. Gcc potrebbe generare un simbolo di debug al di fuori dell'eseguibile / libreria dei risultati? Come ha fatto il file .pdb del compilatore Windows VC ++.

Risposte:


184

È 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}"

Uso lo script bash di seguito per separare le informazioni di debug in file con estensione .debug in una directory .debug. In questo modo posso tarare le librerie e gli eseguibili in un file tar e le 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 simboliche di debug.

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

8
Se hai un problema di produzione e devi collegare il processo con gdb, sarai in grado di fornire il file di simboli di debug a GDB? E come, se è così? thnx
yves Baumes,

3
@yves Baumes Basta aggiungere la directory .debug con i file .debug nella casella di produzione e GDB dovrebbe prenderli. Dopo la sessione di debug è possibile rimuoverli di nuovo.
lothar,

Fai riferimento a @Lance Richardson per rispondere ai commenti per un esempio.
GuruM,

7
È anche possibile ripristinare il file binario originale (ad es. Binario messo a nudo + file .debug = binario originale)?
Paul Praet,

1
Hai riscontrato problemi con l'omissione --build-iddell'opzione linker ?
jww

110

Compila con informazioni di debug:

gcc -g -o main main.c

Separare le informazioni di debug:

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

o

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

Rimuovi le informazioni di debug dal file di origine:

objcopy --strip-debug main

o

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

debug in modalità debuglink:

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

Puoi anche usare separatamente il file exec e il file dei simboli:

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


2
E dovresti usare objcopy --add-gnu-debuglink main main.debugper incorporare il nome del file di debug creato e un checksum. In questo caso gdb proverà a trovare il codice di debug stesso in alcune posizioni dipendenti dalla distribuzione, non è più necessaria alcuna opzione -s.
Lothar,

9

Dai un'occhiata all'opzione "--only-keep-debug" del comando strip .

Dal link:

L'intenzione è che questa opzione verrà usata insieme a --add-gnu-debuglink per creare un eseguibile in due parti. Uno è un binario stripped che occuperà meno spazio nella RAM e in una distribuzione e il secondo un file di informazioni di debug che è necessario solo se sono necessarie capacità di debug.


1
Sì, l'ho provato: gcc -ggdb -o test test.c; cp test test.debug; strip --only-keep-debug test.debug; striscia di prova; objcopy --add-gnu-debuglink = test test.debug; Quindi va bene il test di debug
zhaorufei,

8

NOTA: i programmi compilati con livelli di ottimizzazione elevati (-O3, -O4) non possono generare molti simboli di debug per variabili ottimizzate, funzioni allineate e cicli non srotolati, indipendentemente dai simboli 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. Crea una seconda versione non ottimizzata dell'eseguibile.

La prima opzione fornisce un mezzo per ricostruire il codice di produzione con il debug completo e simboli in un secondo momento. Essere in grado di ricostruire il codice di produzione originale senza ottimizzazioni è di grande aiuto per il debug. (NOTA: ciò 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, è possibile individuare l'originale 'commit' per il codice utilizzando il 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

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


3
-O4non esiste nemmeno.
Ciao Angelo

3
Oops, che potrebbe essere dai giorni di 'suncc', dove '-O5' era persino un'opzione. Ecco un link alle opzioni gcc4.4.7 -O: gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/…
J Jorgenson,

3
Questo non affronta il problema comune del tentativo di interpretare un dump principale che potrebbe non essere facilmente riproducibile. Il consiglio in questa risposta è valido, ma non affronta la domanda.
David Rodríguez - dribeas,

4

Nessuna risposta finora menziona eu-strip --strip-debug -f <out.debug> <input>.

  • Questo è fornito dal elfutilspacchetto.
  • Il risultato sarà che il <input>file è stato rimosso dai simboli di debug che ora sono tutti dentro <out.debug>.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.