Die Verwendung von gdb für einstufigen Assembler-Code außerhalb der angegebenen ausführbaren Datei führt zu dem Fehler "Grenzen der aktuellen Funktion können nicht gefunden werden".

83

Ich bin außerhalb der ausführbaren Zieldatei von gdb und habe nicht einmal einen Stapel, der diesem Ziel entspricht. Ich möchte sowieso in einem Schritt arbeiten, damit ich überprüfen kann, was in meinem Assemblycode vor sich geht, da ich kein Experte für x86-Assembly bin. Leider weigert sich gdb, dieses einfache Debuggen auf Assembly-Ebene durchzuführen. Es ermöglicht mir, einen geeigneten Haltepunkt festzulegen und anzuhalten, aber sobald ich versuche, einen Schritt weiter zu machen, meldet gdb den Fehler "Grenzen der aktuellen Funktion können nicht gefunden werden" und die EIP ändert sich nicht.

Weitere Details:

Der Maschinencode wurde durch gcc asm-Anweisungen generiert und von der Ausgabe von objdump -d in den Kernelspeicher kopiert, in dem er ausgeführt wird. Es würde mir nichts ausmachen, einen einfachen Loader zu verwenden, um meinen Objektcode an eine verschobene Adresse zu laden, aber denken Sie daran, dass das Laden in einem Kernelmodul erfolgen muss.

Ich nehme an, eine andere Alternative wäre, ein gefälschtes Kernelmodul oder eine Debug-Info-Datei zu erstellen, die an gdb weitergegeben wird, um zu glauben, dass dieser Bereich im Programmcode enthalten ist. gdb funktioniert gut auf der ausführbaren Kernel-Datei selbst.

(Für diejenigen, die es wirklich wissen möchten, füge ich zur Laufzeit Code in den Linux-Kernel-Datenbereich innerhalb einer VMware-VM ein und debugge ihn vom GDB-Remote-Debugging des Kernels über den integrierten GDB-Stub von VMware Workstation. Hinweis: Ich schreibe keinen Kernel Exploits; Ich bin ein Sicherheitsstudent, der einen Prototyp schreibt.)

(Ich kann für jede Anweisung in meiner Assembly einen Haltepunkt festlegen. Dies funktioniert, wird jedoch nach einer Weile recht mühsam, da die Größe der x86-Assemblyanweisungen variiert und sich der Speicherort der Assembly bei jedem Neustart ändert.)

Paul
quelle
Die cleveren Leute von ksplice.com fügen Daten und Code in den Kernel ein, indem sie "gefälschte" Kernelmodule zusammensetzen und laden. Und wenn sie es können, warum kannst du es nicht? ;-)
ephemient

Antworten:

113

Sie können stepioder nexti(was mit sioder abgekürzt werden kann ni) verwenden, um Ihren Maschinencode zu durchlaufen.

R Samuel Klatchko
quelle
1
Beeindruckend. Rückblickend weiß ich nicht, wie ich stepi vergessen habe. Ich denke, ich habe nur angenommen, weil gdb keinen Quellcode hatte, würde dieser Schritt zu Montageanweisungen zurückkehren.
Paul
1
Hinweis: Für Assembly-Programme können Sie häufig nicht "break main" oder "run" eingeben. Geben Sie stattdessen "layout asm" und "start" ein. Ich habe dies durch das Lesen der folgenden Nachricht erhalten, aber jemand anderes, der diesen Beitrag liest, ist möglicherweise nicht so geduldig.
Dmitry
1
@Dmitry startist gleichbedeutend mit tbreak maingefolgt von run(Anmerkung: tbreakanstelle von break)
Ruslan
150

Statt gdblaufen gdbtui. Oder gdbmit dem -tuiSchalter laufen . Oder drücken Sie C-x C-anach der Eingabe gdb. Jetzt befinden Sie sich im TUI- Modus von GDB .

Geben Sie layout asmdie Eingabetaste ein , um die obere Fensteranzeige zu erstellen. Dies folgt automatisch Ihrem Anweisungszeiger. Sie können jedoch auch Frames ändern oder beim Debuggen einen Bildlauf durchführen. Drücken Sie C-x sSingleKey - Modus zu gelangen, wo run continue up down finishusw. zu einem einzigen Tasten abgekürzt, so dass Sie sehr schnell durch das Programm zu gehen.

   + --------------------------------------------- -------------------------- +
B +> | 0x402670 <main>% r15 | drücken
   | 0x402672 <main + 2> mov% edi,% r15d |
   | 0x402675 <main + 5>% r14 drücken |
   | 0x402677 <main + 7>% r13 drücken |
   | 0x402679 <main + 9> mov% rsi,% r13 |
   | 0x40267c <main + 12>% r12 drücken |
   | 0x40267e <main + 14>% rbp drücken |
   | 0x40267f <main + 15>% rbx drücken |
   | 0x402680 <main + 16> sub $ 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) |
   + --------------------------------------------- -------------------------- +
untergeordneter Prozess 21518 In: Hauptzeile: ?? PC: 0x402670
(gdb) Datei / opt / j64-602 / bin / jconsole
Lesen von Symbolen aus /opt/j64-602/bin/jconsole...done.
(keine Debugging-Symbole gefunden) ... fertig.
(gdb) layout asm
(gdb) starten
(gdb)
kurzlebig
quelle
26

Das Nützlichste, was Sie hier tun können, ist display/i $pc, bevor Sie das verwenden, stepiwas bereits in der Antwort von R Samuel Klatchko vorgeschlagen wurde. Dies weist gdb an, die aktuelle Anweisung jedes Mal kurz vor dem Drucken der Eingabeaufforderung zu zerlegen. Dann können Sie einfach weiter die Eingabetaste drücken, um den stepiBefehl zu wiederholen .

(Siehe meine Antwort auf eine andere Frage für weitere Einzelheiten - der Kontext dieser Frage war anders, aber das Prinzip ist das gleiche.)

Matthew Slattery
quelle