2013-04-30 7 views
6

Sto imparando come un file C è compilato per codice macchina. So che posso generare assembly da gcc con il flag -S, tuttavia produce anche molto codice da fare con main() e printf() che al momento non mi interessa.Esiste un modo per stampare l'assemblaggio di una singola funzione in isolamento?

C'è un modo per ottenere gcc o clang a "compilare" una funzione di isolamento e di uscita il montaggio?

I.e. ottenere l'assemblea per il seguente c in isolamento:

int add(int a, int b) { 
    return a + b; 
} 
+0

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

+0

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 –

+3

Vai qui: http://gcc.godbolt.org/ incolla la funzione, seleziona il compilatore, molto utile. – harold

risposta

7

Ci sono due modi per fare questo per un file oggetto specifico:

  1. L'opzione -ffunction-sections-gcc incarica esso per creare una sezione separata ELF per ogni funzione nel file sorgente in fase di compilazione.
  2. 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.

+0

Vedo, solo fyi per chiunque altro, è possibile utilizzare "gcc -ffunction-sections -c test.c" per compilare un file sorgente in un file oggetto. grazie ~ – ashleysmithgpu

0

Il modo migliore per andare sarebbe quello di copiare la funzione in un unico file temp.c C e compilarlo con la bandiera -c in questo modo: gcc -c -S temp.c -o temp.s

Dovrebbe produrre un codice di assemblaggio più stretto senza altre distrazioni (ad eccezione dell'intestazione e del piè di pagina).

Problemi correlati