2009-08-06 16 views
50

Sto provando a disassemblare un programma per vedere un'istruzione di assemblaggio syscall (l'istruzione INT, credo) e il gestore con GDB e ho scritto un piccolo programma (vedi sotto) per esso che apre e chiude un file. Sono stato in grado di seguire la chiamata per fopen con GDB fino a quando non ha eseguito una chiamata. Quando ho provato a comunicare a GDB "disassembla 0x ...." (indirizzo della chiamata) ha risposto con "Nessuna funzione contiene l'indirizzo specificato". E 'possibile forzare GDB a smontare (o visualizzarlo in assembler nel miglior modo possibile) quell'indirizzo di memoria? Se é cosi, come?Come posso forzare il GDB a smontare?

#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    FILE* f; 
    f = fopen("main.c", "r"); 
    if (!f) { 
     perror("open"); 
     return -1; 
    } 
fclose(f); 
return 0; 
} 
+2

fopen() non è una chiamata di sistema, è una chiamata alla libreria standard C. E perché pensi che una chiamata di sistema debba essere effettuata tramite un'istruzione INT? –

+0

Potrei sbagliarmi, ma ci è stato insegnato che le chiamate fopen alla fine portano a una chiamata di sistema al kernel per aprire il file e restituire un descrittore di file? – Patrick

+1

Patrick: Sì, ma non ha bisogno di farlo in modo diretto. Normalmente chiama la funzione libc che quindi entra nel kernel. Ma chiamare il kernel può essere fatto non solo con int (questo è lento) ma con syscall/sysenter a seconda dell'architettura del processore ... – k3a

risposta

40

Vuoi solo smontare il tuo attuale principale? Se è così provare questo:

(gdb) info line main 
(gdb) disas STARTADDRESS ENDADDRESS 

Come così:

[email protected] /cygdrive/c/prog/dsa 
$ gcc-3.exe -g main.c 

[email protected] /cygdrive/c/prog/dsa 
$ gdb a.exe 
GNU gdb 6.8.0.20080328-cvs (cygwin-special) 
... 
(gdb) info line main 
Line 3 of "main.c" starts at address 0x401050 <main> and ends at 0x401075 <main+ 
(gdb) disas 0x401050 0x401075 
Dump of assembler code from 0x401050 to 0x401075: 
0x00401050 <main+0>: push %ebp 
0x00401051 <main+1>: mov %esp,%ebp 
0x00401053 <main+3>: sub $0x18,%esp 
0x00401056 <main+6>: and $0xfffffff0,%esp 
0x00401059 <main+9>: mov $0x0,%eax 
0x0040105e <main+14>: add $0xf,%eax 
0x00401061 <main+17>: add $0xf,%eax 
0x00401064 <main+20>: shr $0x4,%eax 
0x00401067 <main+23>: shl $0x4,%eax 
0x0040106a <main+26>: mov %eax,-0xc(%ebp) 
0x0040106d <main+29>: mov -0xc(%ebp),%eax 
0x00401070 <main+32>: call 0x4010c4 <_alloca> 
End of assembler dump. 

non vedo la chiamata di interrupt di sistema tuttavia. (è passato un po 'di tempo dall'ultima volta che ho provato a fare una chiamata di sistema in assembly. INT 21h, infine ricordo

+0

ok, allora proverò a cercare INT 21h in futuro. Grazie per questo suggerimento. Ma quello che volevo provare è seguire la sequenza chiamata originata da fopen() (non vederla nel tuo codice ...) 'down' finché non vedrò il comando INT. – Patrick

+1

Gestito - La strada da percorrere è utilizzare sia la risposta che quella di Falaina. Ho dovuto compilarlo staticamente con gcc --static main.c e quindi usare gdb/objdump per andare in profondità nella libreria C. In definitiva, ha generato una chiamata a __open_nocancel, che ha fatto un * INT 0x80 *. Grazie a entrambi voi – Patrick

+4

Nota: la sintassi 'disas 0x4010010 0x401075' almeno nella versione gdb 7.7 non funzionerà. Piuttosto lo scrivi come 'disas 0x401050,0x401075'. Probabilmente potresti anche voler aggiungere il prefisso «/ m» per mostrare un codice sorgente in giro: 'disas \ m 0x401050,0x401075' –

28

Questa non è la risposta diretta alla tua domanda, ma dal momento che sembra voler solo smontare il binario , forse si potrebbe utilizzare objdump:

objdump -d program 

Questo dovrebbe dare il suo lo smontaggio è possibile aggiungere -S se lo vuoi sorgente annotato

+0

⁺¹ per '-S', non sapevo che potesse includere il codice sorgente. –

6

è possibile forzare gcc ad emettere direttamente al codice assembly con l'aggiunta di.. l'interruttore -S

gcc -S hello.c 
83

Sì, smontare non è il miglior comando da usare qui. Il comando che si desidera è "x/i" (esaminare come le istruzioni):

(gdb) x/i 0xdeadbeef 
+3

GRAZIE! Aggiunta di questo testo per aiutare gli altri a trovare questo suggerimento: questa è l'istruzione da utilizzare per disassemblare il blob binario, smontare la ROM, esaminare le istruzioni in un file di immagine binario, ecc. Scrivere un piccolo programma C per fread() il blob binario in un buffer. Quindi fai 'x/i' sul buffer. – user188012

+0

@ user188012 se si desidera disassemblare un blob binario, un modo più semplice per farlo è utilizzare un disassemblatore autonomo come ndisasm o simile. –

+0

È possibile utilizzare: x/i $ pc per ottenere le istruzioni per il PC che è l'indirizzo dell'istruzione corrente – k3a

3

Se tutto ciò che si desidera è di vedere lo smontaggio con la chiamata INTC, utilizzare objdump -d come qualcuno ha detto, ma utilizzare il - opzione statica durante la compilazione. Altrimenti la funzione fopen non è compilata nell'elf e viene collegata in fase di esecuzione.

7

fopen() è una funzione di libreria C e quindi non vedrai alcuna istruzione syscall nel tuo codice, solo una normale chiamata di funzione. Ad un certo punto, chiama open (2), ma lo fa tramite un trampolino. C'è semplicemente un salto alla pagina VDSO, che viene fornita dal kernel ad ogni processo. Il VDSO fornisce quindi il codice per effettuare la chiamata di sistema. Sui processori moderni, verranno utilizzate le istruzioni SYSCALL o SYSENTER, ma è anche possibile utilizzare INT 80h sui processori x86.

1

Non è necessario utilizzare gdb. GCC lo farà.

gcc -S foo.c 

Questo creerà foo.s che è l'assieme.

gcc -m32 -c -g -Wa,-a,-ad foo.c > foo.lst 

La versione precedente creerà un file di elenco che ha sia la C che l'assieme generato da essa. GCC FAQ

1

gdb smontare ha un/m per includere il codice sorgente insieme alle istruzioni. Questo è equivalente a objdump -S, con l'ulteriore vantaggio di limitarsi a una sola funzione (o gamma di indirizzi) di interesse.

Problemi correlati