Comment générer un symbole de débogage gcc en dehors de la cible de construction?

176

Je sais que je peux générer un symbole de débogage en utilisant l'option -g. Cependant, le symbole est incorporé dans le fichier cible. Gcc peut-il générer un symbole de débogage en dehors de l'exécutable / bibliothèque de résultats? Comme le fichier .pdb du compilateur Windows VC ++ l'a fait.

kcwu
la source

Réponses:

184

Vous devez utiliser objcopy pour séparer les informations de débogage :

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

J'utilise le script bash ci-dessous pour séparer les informations de débogage en fichiers avec une extension .debug dans un répertoire .debug. De cette façon, je peux tarer les bibliothèques et les exécutables dans un fichier tar et les répertoires .debug dans un autre. Si je veux ajouter les informations de débogage plus tard, j'extrais simplement le fichier tar de débogage et voilà, j'ai des informations de débogage symboliques.

Voici le 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
la source
8
Si vous rencontrez un problème en production et devez attacher le processus avec gdb, serez-vous en mesure de fournir le fichier de symboles de débogage à GDB? Et comment, si oui? thnx
yves Baumes
3
@yves Baumes Ajoutez simplement le répertoire .debug avec les fichiers .debug à votre boîte de production et GDB devrait les récupérer. Après la session de débogage, vous pouvez les supprimer à nouveau.
lothar
Reportez-vous aux commentaires de @Lance Richardson pour un exemple.
GuruM
7
Est-il également possible de restaurer le binaire d'origine (par exemple binaire dépouillé + fichier .debug = binaire d'origine)?
Paul Praet
1
Trouvez-vous des problèmes avec l'omission de l' --build-idoption de l'éditeur de liens ?
jww
110

Compilez avec les informations de débogage:

gcc -g -o main main.c

Séparez les informations de débogage:

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

ou

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

Supprimez les informations de débogage du fichier d'origine:

objcopy --strip-debug main

ou

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

débogage par mode debuglink:

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

Vous pouvez également utiliser séparément le fichier exécutable et le fichier symbole:

gdb -s main.debug -e main

ou

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

Pour plus de détails:

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

Réf:
https://sourceware.org/gdb/onlinedocs/gdb/Files.html#Files https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html

hérodote
la source
2
Et vous devriez utiliser objcopy --add-gnu-debuglink main main.debugpour incorporer le nom du fichier de débogage créé et une somme de contrôle. Dans ce cas, gdb essaiera de trouver le code de débogage lui-même dans quelques emplacements dépendants de la distribution, aucune option -s n'est plus nécessaire.
Lothar
9

Découvrez l'option "--only-keep-debug" de la bande commande .

Depuis le lien:

L'intention est que cette option soit utilisée en conjonction avec --add-gnu-debuglink pour créer un exécutable en deux parties. L'un est un binaire dépouillé qui occupera moins d'espace dans la RAM et dans une distribution et le second un fichier d'informations de débogage qui n'est nécessaire que si des capacités de débogage sont nécessaires.

Lance Richardson
la source
1
Oui, je l'ai essayé: gcc -ggdb -o test test.c; cp test test.debug; strip --only-keep-debug test.debug; test de bandelette; objcopy --add-gnu-debuglink = test.debug test; Ensuite, vous
pouvez
8

REMARQUE: les programmes compilés avec des niveaux d'optimisation élevés (-O3, -O4) ne peuvent pas générer de nombreux symboles de débogage pour les variables optimisées, les fonctions intégrées et les boucles déroulées, quels que soient les symboles incorporés (-g) ou extraits (objcopy) dans un Fichier '.debug'.

D'autres approches sont

  1. Incorporez les données de contrôle de version (VCS, git, svn) dans le programme, pour les exécutables optimisés pour le compilateur (-O3, -O4).
  2. Construisez une 2ème version non optimisée de l'exécutable.

La première option fournit un moyen de reconstruire le code de production avec un débogage complet et des symboles à une date ultérieure. Être capable de reconstruire le code de production d'origine sans optimisation est une aide considérable pour le débogage. (REMARQUE: cela suppose que le test a été effectué avec la version optimisée du programme).

Votre système de construction peut créer un fichier .c chargé avec la date de compilation, la validation et d'autres détails du VCS. Voici un exemple '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

Une fois le programme compilé, vous pouvez localiser le 'commit' d'origine de votre code en utilisant la commande: 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

Il ne reste plus qu'à extraire le code d'origine, à recompiler sans optimisations et à démarrer le débogage.

J Jorgenson
la source
3
-O4n'existe même pas.
Hi-Angel
3
Oups, cela peut être de mai jours «suncc», où «-O5» était même une option. Voici un lien vers les options gcc4.4.7 -O: gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc
J Jorgenson
3
Cela ne résout pas le problème courant d'essayer d'interpréter un vidage de mémoire qui peut ne pas être facilement reproductible. Le conseil dans cette réponse est valable, mais il ne répond pas à la question.
David Rodríguez - dribeas
4

Aucune réponse à ce jour mentionne eu-strip --strip-debug -f <out.debug> <input>.

  • Ceci est fourni par elfutilspackage.
  • Le résultat sera que le <input>fichier a été dépouillé des symboles de débogage qui sont maintenant tous inclus <out.debug>.
Unapiedra
la source