Ci sono due modi per fare questo per un file oggetto specifico:
- L'opzione
-ffunction-sections
-gcc
incarica esso per creare una sezione separata ELF per ogni funzione nel file sorgente in fase di compilazione.
- La tabella dei simboli contiene il nome della sezione, l'indirizzo iniziale e le dimensioni di una determinata funzione; che può essere inserito in
objdump
tramite gli argomenti --start-address
/--stop-address
.
Il primo esempio:
$ readelf -S t.o | grep ' .text.'
[ 1] .text PROGBITS 0000000000000000 00000040
[ 4] .text.foo PROGBITS 0000000000000000 00000040
[ 6] .text.bar PROGBITS 0000000000000000 00000060
[ 9] .text.foo2 PROGBITS 0000000000000000 000000c0
[11] .text.munch PROGBITS 0000000000000000 00000110
[14] .text.startup.mai PROGBITS 0000000000000000 00000180
Questo è stato compilato con -ffunction-sections
e ci sono quattro funzioni, foo()
, bar()
, foo2()
e munch()
nel mio file oggetto. Posso smontare separatamente in questo modo:
$ objdump -w -d --section=.text.foo t.o
t.o: file format elf64-x86-64
Disassembly of section .text.foo:
0000000000000000 <foo>:
0: 48 83 ec 08 sub $0x8,%rsp
4: 8b 3d 00 00 00 00 mov 0(%rip),%edi # a <foo+0xa>
a: 31 f6 xor %esi,%esi
c: 31 c0 xor %eax,%eax
e: e8 00 00 00 00 callq 13 <foo+0x13>
13: 85 c0 test %eax,%eax
15: 75 01 jne 18 <foo+0x18>
17: 90 nop
18: 48 83 c4 08 add $0x8,%rsp
1c: c3 retq
L'altra opzione può essere utilizzata come questo (nm
discariche voci della tabella dei simboli):
$ nm -f sysv t.o | grep bar
bar |0000000000000020| T | FUNC|0000000000000026| |.text
$ objdump -w -d --start-address=0x20 --stop-address=0x46 t.o --section=.text
t.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000020 <bar>:
20: 48 83 ec 08 sub $0x8,%rsp
24: 8b 3d 00 00 00 00 mov 0(%rip),%edi # 2a <bar+0xa>
2a: 31 f6 xor %esi,%esi
2c: 31 c0 xor %eax,%eax
2e: e8 00 00 00 00 callq 33 <bar+0x13>
33: 85 c0 test %eax,%eax
35: 75 01 jne 38 <bar+0x18>
37: 90 nop
38: bf 3f 00 00 00 mov $0x3f,%edi
3d: 48 83 c4 08 add $0x8,%rsp
41: e9 00 00 00 00 jmpq 46 <bar+0x26>
In questo caso, l'opzione -ffunction-sections
non ha stato utilizzato, quindi l'offset iniziale della funzione non è zero e non è nella sua sezione separata (ma in .text
).
Attenzione però durante lo smontaggio file oggetto ...
Questo non è esattamente ciò che si vuole, perché, per i file oggetto, gli obiettivi call
(così come gli indirizzi di variabili globali) non vengono risolti - non è possibile vedere qui che foo
chiama printf
, perché la risoluzione di tale livello a livello binario avviene solo al momento del collegamento. La fonte di assemblaggio avrebbe il call printf
in là comunque.L'informazione che questo callq
è effettivamente nel file oggetto, ma separata dal codice (si trova nella cosiddetta sezione di riposizionamento che elenca le posizioni nel file oggetto da "riparare" dal linker); il disassemblatore non può risolvere questo.
Alcuni IDE consentono di impostare un punto di interruzione e visualizzare il codice assembly generato da tale funzione. Si chiama la finestra * disassembly *. Questo dovrebbe fare quello che stai cercando - stai usando un IDE? – Aaron
Preferisco compilare (con ottimizzazioni), quindi disassemblare, devi capire che il compilatore lascerà alcune istruzioni incomplete per gli indirizzi esterni e così via, ma è più facile leggere IMO che usare -S. gcc -O2 -c ciao.c -o ciao.o, objdump -D ciao.o –
Vai qui: http://gcc.godbolt.org/ incolla la funzione, seleziona il compilatore, molto utile. – harold