L'utilizzo di gdb in un codice assembly a passaggio singolo al di fuori dell'eseguibile specificato causa l'errore "impossibile trovare i limiti della funzione corrente"


88

Sono fuori dall'eseguibile di destinazione di gdb e non ho nemmeno uno stack che corrisponda a tale destinazione. Voglio comunque eseguire un singolo passaggio, in modo da poter verificare cosa sta succedendo nel mio codice assembly, perché non sono un esperto di assembly x86. Sfortunatamente, gdb si rifiuta di eseguire questo semplice debug a livello di assembly. Mi consente di impostare e fermarmi su un punto di interruzione appropriato, ma non appena provo a eseguire un singolo passaggio in avanti, gdb segnala l'errore "Impossibile trovare i limiti della funzione corrente" e l'EIP non cambia.

Dettagli aggiuntivi:

Il codice macchina è stato generato dalle istruzioni gcc asm e l'ho copiato nella posizione di memoria del kernel dove è in esecuzione, dall'output di objdump -d. Non mi dispiacerebbe un modo semplice per utilizzare un caricatore per caricare il mio codice oggetto su un indirizzo riposizionato, ma tieni presente che il caricamento deve essere eseguito in un modulo del kernel.

Suppongo che un'altra alternativa sarebbe quella di produrre un falso modulo del kernel o un file di informazioni di debug da dare a gdb, per fargli credere che quest'area sia all'interno del codice del programma. gdb funziona bene sullo stesso eseguibile del kernel.

(Per coloro che lo vogliono davvero sapere, sto inserendo codice in fase di esecuzione nello spazio dati del kernel Linux all'interno di una VM VMware e lo sto eseguendo da gdb debug remoto del kernel tramite lo stub gdb integrato di VMware Workstation. Nota non sto scrivendo kernel exploit; Sono uno studente laureato in sicurezza che scrive un prototipo.)

(Posso impostare un punto di interruzione su ogni istruzione all'interno del mio assembly. Funziona ma diventerebbe piuttosto laborioso dopo un po ', poiché la dimensione delle istruzioni di assembly x86 varia e la posizione dell'assembly cambierà ogni volta che riavvio.)


Le persone intelligenti di ksplice.com inseriscono dati e codice nel kernel assemblando moduli del kernel "falsi" e caricandoli. E se loro possono farlo, perché non puoi? ;-)
effimero

Risposte:


118

È possibile utilizzare stepio nexti(che può essere abbreviato in sio ni) per scorrere il codice macchina.


1
Wow. In retrospettiva non so come mi sono dimenticato di Stepi. Immagino di aver semplicemente dato per scontato perché gdb non aveva il codice sorgente che il passaggio sarebbe tornato alle istruzioni di assemblaggio.
Paul

1
nota: spesso non è possibile digitare "break main", "run" per i programmi assembly. Digita invece "layout asm", "start". L'ho capito leggendo il messaggio qui sotto, ma qualcun altro che sta leggendo questo post potrebbe non essere così paziente.
Dmitry

1
@Dmitry startequivale a tbreak mainseguito da run(nota: tbreakinvece di break)
Ruslan

154

Invece di gdbcorrere gdbtui. Oppure corri gdbcon l' -tuiinterruttore. Oppure premere C-x C-adopo aver inserito gdb. Ora sei nella modalità TUI di GDB .

Invio layout asmper creare il gruppo di visualizzazione della finestra superiore: questo seguirà automaticamente il puntatore dell'istruzione, sebbene sia anche possibile modificare i frame o scorrere durante il debug. Premere C-x sper accedere alla modalità SingleKey, dove run continue up down finishecc. Sono abbreviati in un singolo tasto, consentendo di scorrere rapidamente il programma.

   + ------------------------------------------------- -------------------------- +
B +> | 0x402670 <main> push% r15 |
   | 0x402672 <main + 2> mov% edi,% r15d |
   | 0x402675 <main + 5> push% r14 |
   | 0x402677 <main + 7> push% r13 |
   | 0x402679 <main + 9> mov% rsi,% r13 |
   | 0x40267c <main + 12> push% r12 |
   | 0x40267e <main + 14> push% rbp |
   | 0x40267f <main + 15> push% rbx |
   | 0x402680 <principale + 16> secondario $ 0x438,% rsp |
   | 0x402687 <main + 23> mov (% rsi),% rdi |
   | 0x40268a <main + 26> movq $ 0x402a10,0x400 (% rsp) |
   | 0x402696 <main + 38> movq $ 0x0,0x408 (% rsp) |
   | 0x4026a2 <main + 50> movq $ 0x402510,0x410 (% rsp) |
   + ------------------------------------------------- -------------------------- +
processo figlio 21518 In: main Line: ?? PC: 0x402670
(gdb) file / opt / j64-602 / bin / jconsole
Lettura dei simboli da /opt/j64-602/bin/jconsole...done.
(nessun simbolo di debug trovato) ... fatto.
(gdb) layout asm
(gdb) start
(gdb)

26

La cosa più utile che puoi fare qui è display/i $pc, prima di utilizzare stepicome già suggerito nella risposta di R. Samuel Klatchko. Questo dice a gdb di disassemblare l'istruzione corrente appena prima di stampare il prompt ogni volta; quindi puoi continuare a premere Invio per ripetere il filestepi comando.

(Vedi la mia risposta a un'altra domanda per maggiori dettagli: il contesto di quella domanda era diverso, ma il principio è lo stesso.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.