wake-up-neo.com

Finden Sie heraus, welche Assembly-Anweisung einen Fehler wegen ungültiger Anweisungen verursacht hat, ohne zu debuggen

Beim Ausführen eines Programms, das ich in Assembly geschrieben habe, erhalte ich einen Illegal instruction-Fehler. Gibt es eine Möglichkeit zu wissen, welche Anweisung den Fehler verursacht, ohne zu debuggen, weil die Maschine, auf der ich laufe, keinen Debugger oder Entwicklungssystem hat. Mit anderen Worten, ich kompiliere auf einer Maschine und laufe auf einer anderen. Ich kann mein Programm nicht auf dem Computer testen, den ich kompiliere, da SSE4.2 nicht unterstützt wird. Die Maschine, auf der das Programm läuft, unterstützt dennoch SSE4.2-Anweisungen.

Ich denke, es liegt vielleicht daran, dass ich dem Assembler (YASM) sagen muss, dass er die SSE4.2-Anweisungen erkennt, genau wie wir es mit gcc tun, indem wir ihm das Flag -msse4.2 übergeben. Oder glaubst du, es ist nicht der Grund? Irgendeine Idee, wie man YASM anweist, SSE4.2-Anweisungen zu erkennen?

Vielleicht sollte ich das Signal SIGILL abfangen und dann den SA_SIGINFO dekodieren, um zu sehen, welche Art von illegalen Operationen das Programm ausführt.

25
pythonic

Tatsächlich erhalten Sie häufig einen ungültigen Anweisungsfehler, nicht weil Ihr Programm einen ungültigen Opcode enthält, sondern weil in Ihrem Programm ein Fehler (z. B. ein Pufferüberlauf) vorliegt, der Ihr Programm in eine zufällige Adresse mit einfachen Daten oder in Code springt, aber nicht in der Start des Opcodes.

30
ouah

Vor kurzem erlebte ich einen Absturz aufgrund eines Exit-Statuscodes von 132 (128 + 4: Programm unterbrochen durch ein Signal + unzulässiges Anweisungssignal). So habe ich herausgefunden, welche Anweisung den Absturz verursacht hat.

Zuerst habe ich Core Dumps aktiviert:

$ ulimit -c unlimited

Interessanterweise enthielt der Ordner, von dem aus ich die Binärdatei ausführte, einen Ordner mit dem Namen core. Ich musste Linux anweisen, die PID zum Core-Dump hinzuzufügen:

$ Sudo sysctl -w kernel.core_uses_pid=1

Dann starte ich mein Programm und bekam einen Kern namens core.23650. Ich habe die Binärdatei und den Kern mit gdb geladen.

$ gdb program core.23650

Sobald ich bei gdb war, wurden folgende Informationen angezeigt:

Program terminated with signal SIGILL, Illegal instruction.
#0  0x00007f58e9efd019 in ?? ()

Das bedeutet, dass mein Programm aufgrund einer ungültigen Anweisung im 0x00007f58e9efd019 Adressspeicher abgestürzt ist. Dann wechselte ich zu asm layout, um die zuletzt ausgeführte Anweisung zu überprüfen:

(gdb) layout asm
>|0x7f58e9efd019  vpmaskmovd (%r8),%ymm15,%ymm0
 |0x7f58e9efd01e  vpmaskmovd %ymm0,%ymm15,(%rdi)
 |0x7f58e9efd023  add    $0x4,%rdi
 |0x7f58e9efd027  add    $0x0,%rdi

Die Anweisung vpmaskmovd hat den Fehler verursacht. Anscheinend habe ich versucht, ein Programm für die AVX2-Architektur auf einem System auszuführen, dem die Unterstützung für den AVX2-Befehlssatz fehlt.

$ cat /proc/cpuinfo | grep avx2

Zum Schluss habe ich bestätigt, dass vpmaskmovd nur eine AVX2-Anweisung ist .

21
Diego Pino

Wenn Sie Core-Dumps auf diesem System aktivieren können, führen Sie einfach das Programm aus, lassen Sie es abstürzen, ziehen Sie den Core-Dump vom Zielcomputer auf Ihren Entwicklungscomputer und laden Sie ihn in eine GDB, die zum Debuggen der Zielarchitektur erstellt wurde. Dies sollte Ihnen genau sagen wo der Absturz stattgefunden hat Verwenden Sie einfach den Befehl core von GDB, um die Kerndatei in den Debugger zu laden.

  • So aktivieren Sie Core Dumps auf dem Ziel:

    ulimit -c unlimited
    
  • pseudodateien, die steuern, wie die Kerndatei benannt wird (kategorisieren Sie diese, um die aktuelle Konfiguration anzuzeigen, schreiben Sie ihnen, um die Konfiguration zu ändern):

    /proc/sys/kernel/core_pattern
    /proc/sys/kernel/core_uses_pid
    

Auf meinem System schreibt ein abstürzendes Programm nach dem Aktivieren von Core Dumps eine Datei mit dem Namen "Core" in das Arbeitsverzeichnis. Das ist wahrscheinlich gut genug für Ihre Zwecke, aber wenn Sie den Namen der Core-Dump-Datei ändern, können Sie einen Verlauf der Core-Dumps beibehalten, falls dies erforderlich ist (möglicherweise für ein zeitweiligeres Problem).

11
Michael Burr

Nun ... Natürlich können Sie Trace-Ausdrucke einfügen, um große Bereiche des Codes schnell auszuschließen. Sobald Sie das getan haben, führen Sie z.

$ objdump --disassemble my-crashing-program | less

Dann springen Sie zu z. Die Funktion, die Sie kennen, verursacht den Fehler. Lesen Sie den Code und suchen Sie nach etwas, das seltsam aussieht.

Ich bin nicht ganz sicher, wie objdump illegale Anweisungen anzeigt, aber sie sollten auffallen.

4
unwind

Bei handschriftlichen Assemblys würde ich vermuten, dass ein Stapelverwaltungsproblem zu einer Rückkehr ins Nichts führt. Schreiben Sie eine Debugging-Ausdruckroutine, in der jedes Register gespeichert wird, und fügen Sie am Anfang jeder Funktion einen Aufruf ein.

Dann werden Sie sehen, wie weit Sie kommen ...

(Übrigens, ein guter Editor und ein gutes Verständnis der Makrosyntax des Assemblers sind Lebensretter beim Schreiben von Maschinencode.)

4
DigitalRoss

Das Fehlen einer return-Anweisung am Ende einer Funktion kann dies verursachen.

2
Gabriel