Comment démonter une seule fonction en utilisant objdump?
j'ai un binaire installé sur mon système, et tiens à regarder le démontage d'une fonction donnée. Utiliser de préférence objdump
, mais d'autres solutions seraient également acceptables.
à Partir de cette question j'ai appris que je pourrais être capable de démonter une partie du code si je ne connais que la limite d'adresses. De cette réponse j'ai appris à transformer mes symboles de débogage fractionnés en un seul fichier.
mais même en travaillant sur ce fichier unique, et même en démontant tout le code (i.e. sans adresse de départ ou d'arrêt, mais simple -d
paramètre à objdump
), Je ne vois toujours pas ce symbole où que ce soit. Ce qui est logique dans la mesure où la fonction en question Est statique, donc elle n'est pas exportée. Néanmoins, valgrind
va signaler le nom de la fonction, il doit donc être stocké quelque part.
en regardant les détails des sections de debug, je trouve que nom mentionné dans la section .debug_str
, mais je ne connais pas d'outil qui puisse transformer cela en une plage d'adresses.
6 réponses
je suggère d'utiliser gdb comme approche la plus simple. Vous pouvez même le faire comme une doublure, comme:
gdb -batch -ex 'file /bin/ls' -ex 'disassemble main'
gdb disassemble/rs
pour afficher les octets source et raw ainsi que
avec ce format, il se rapproche vraiment de objdump -S
sortie:
gdb -batch -ex "file $EXECUTABLE" -ex "disassemble/rs $FUNCTION"
A. c:
#include <assert.h>
int myfunc(int i) {
i = i + 2;
i = i * 2;
return i;
}
int main(void) {
assert(myfunc(1) == 6);
assert(myfunc(2) == 8);
return 0;
}
compiler et démonter
gcc -std=c99 -O0 -g a.c
gdb -batch -ex 'file a.out' -ex "disassemble/rs myfunc"
démontage:
Dump of assembler code for function main:
a.c:
1 int main(void) {
0x00000000004004d6 <+0>: 55 push %rbp
0x00000000004004d7 <+1>: 48 89 e5 mov %rsp,%rbp
2 int i;
3 i = 0;
0x00000000004004da <+4>: c7 45 fc 00 00 00 00 movl "151930920"x0,-0x4(%rbp)
4 i = i + 2;
0x00000000004004e1 <+11>: 83 45 fc 02 addl "151930920"x2,-0x4(%rbp)
5 i = i * 2;
0x00000000004004e5 <+15>: d1 65 fc shll -0x4(%rbp)
6 return 0;
0x00000000004004e8 <+18>: b8 00 00 00 00 mov "151930920"x0,%eax
7 }
0x00000000004004ed <+23>: 5d pop %rbp
0x00000000004004ee <+24>: c3 retq
End of assembler dump.
testé sur Ubuntu 16.04, GDB 7.11.1.
objdump + awk solutions de contournement
imprimer le paragraphe comme indiqué à: https://unix.stackexchange.com/questions/82944/how-to-grep-for-text-in-a-file-and-display-the-paragraph-that-has-the-text
objdump -d a.out | awk -v RS= '/^[[:xdigit:]]+ <FUNCTION>/'
p.ex.:
objdump -d a.out | awk -v RS= '/^[[:xdigit:]]+ <myfunc>/'
donne simplement:
000000000000064a <myfunc>:
64a: 55 push %rbp
64b: 48 89 e5 mov %rsp,%rbp
64e: 89 7d fc mov %edi,-0x4(%rbp)
651: 83 45 fc 02 addl "151960920"x2,-0x4(%rbp)
655: d1 65 fc shll -0x4(%rbp)
658: 8b 45 fc mov -0x4(%rbp),%eax
65b: 5d pop %rbp
65c: c3 retq
en utilisant -S
, Je ne pense pas qu'il y ait une méthode infaillible, car les commentaires du code pourraient contenir n'importe quelle séquence possible... Mais les travaux suivants presque tout le temps:
objdump -S a.out | awk '/^[[:xdigit:]]+ <FUNCTION>:$/{flag=1;next}/^[[:xdigit:]]+ <.*>:$/{flag=0}flag'
liste de Diffusion réponses
il ya un fil 2010 sur la liste de diffusion qui dit que ce n'est pas possible: https://sourceware.org/ml/binutils/2010-04/msg00445.html
outre la solution de contournement gdb
proposée par Tom, ils commentent également une autre solution de contournement (pire) de compiler avec -ffunction-section
qui met une fonction par section et puis jeter la section.
Nicolas Clifton lui a donné un WONTFIX https://sourceware.org/ml/binutils/2015-07/msg00004.html , probablement parce que la solution de contournement de GDB couvre que cas d'utilisation.
démonter une seule fonction en utilisant Objdump
j'ai deux solutions:
1. Basé Sur La Ligne De Commande
Cette méthode fonctionne parfaitement et est également très court. J'utilise objdump avec -d et pipe à awk . La sortie démontée ressemble à
000000000000068a <main>:
68a: 55 push %rbp
68b: 48 89 e5 mov %rsp,%rbp
68e: 48 83 ec 20 sub "151900920"x20,%rsp
Un section ou la fonction est séparée par une ligne vide. Par conséquent, changer le FS (séparateur de champ) à newline et le RS (séparateur D'enregistrement) à deux fois newline vous permet de rechercher facilement votre fonction recommandée, car il est tout simplement de trouver dans le champ $1!
objdump -d name_of_your_obj_file | awk -F"\n" -v RS="\n\n" ' ~ /main/'
bien sûr, vous pouvez remplacer principal à n'importe quelle fonction que vous voulez être sortie.
2. Bash Script
j'ai écrit un petit script bash pour ce numéro. Il suffit de le copier et de le sauvegarder comme par exemple dasm fichier.
#!/bin/bash
# Author: abu
# Description: puts disassembled objectfile to std-out
if [ $# = 2 ]; then
sstrg="^[[:xdigit:]]{2,}+.*<>:$"
objdump -d | awk -F"\n" -v RS="\n\n" ' ~ /'"$sstrg"'/'
elif [ $# = 1 ]; then
objdump -d | awk -F"\n" -v RS="\n\n" '{ print }'
else
echo "You have to add argument(s)"
echo "Usage: ""151920920" " arg1 arg2"
echo "Description: print disassembled label to std-out"
echo " arg1: name of object file"
echo " arg2: name of function to be disassembled"
echo " ""151920920" " arg1 ... print labels and their rel. addresses"
fi
modifier le x-access et l'invoquer avec par exemple:
chmod +x dasm
./dasm test main
C'est beaucoup plus rapide qu'invoquer gdb avec un script. À côté de la manière en utilisant objdump sera pas charger le les bibliothèques dans la mémoire et est donc plus sûr!
Vitaly Fadeev a programmé l'autocomplétion de ce script, qui est vraiment une belle fonctionnalité et accélère la dactylographie.
le script se trouve ici .
cela fonctionne comme la solution gdb (en ce qu'elle déplace les offsets vers zéro) sauf qu'elle n'est pas lente (fait le travail en environ 5ms sur mon PC alors que la solution gdb prend environ 150ms):
objdump_func:
#!/bin/sh
# -- function name; rest -- object files
fn=; shift 1
exec objdump -d "$@" |
awk " /^[[:xdigit:]].*<$fn>/,/^$/ { print $0 }" |
awk -F: -F' ' 'NR==1 { offset=strtonum("0x"); print "151900920"; }
NR!=1 { split("151900920",a,":"); rhs=a[2]; n=strtonum("0x"); =sprintf("%x", n-offset); printf "%4s:%s\n", ,rhs }'
pour simplifier l'utilisation de awk pour analyser la sortie d'objdump par rapport à d'autres réponses:
objdump -d filename | sed '/<functionName>:/,/^$/!d'
Bash completion pour ./dasm
symbole Complète des noms de à cette solution (D lang version):
- En tapant
dasm test
, puis en appuyant sur Onglet Onglet , vous obtiendrez une liste de toutes les fonctions. - En tapant
dasm test m
, puis en appuyant sur Onglet Onglet toutes les fonctions commençant par m seront affichées, ou si une seule fonction existe, elle sera autocompletée.
Fichier /etc/bash_completion.d/dasm
:
# bash completion for dasm
_dasm()
{
local cur=${COMP_WORDS[COMP_CWORD]}
if [[ $COMP_CWORD -eq 1 ]] ; then
# files
COMPREPLY=( $( command ls *.o -F 2>/dev/null | grep "^$cur" ) )
elif [[ $COMP_CWORD -eq 2 ]] ; then
# functions
OBJFILE=${COMP_WORDS[COMP_CWORD-1]}
COMPREPLY=( $( command nm --demangle=dlang $OBJFILE | grep " W " | cut -d " " -f 3 | tr "()" " " | grep "$cur" ) )
else
COMPREPLY=($(compgen -W "" -- "$cur"));
fi
}
complete -F _dasm dasm