Frage

Ich möchte in der Lage sein zu erkennen, wenn eine Speicherschreibadresse auftritt - zum Beispiel durch einen Rückruf an einen Interrupt angebracht Einstellung. Wer weiß, wie?

Ich möchte in der Lage sein, dies zur Laufzeit tun (möglicherweise gdb hat diese Funktion, aber meine besonderen Anwendung verursacht gdb Absturz).

War es hilfreich?

Lösung

Wenn Sie abfangen wollen, schreibt auf einen Bereich von Adressen, können Sie mprotect() zu markieren, den Speicher in Frage als nicht beschreibbar, und installieren, um ein Signal-Handler sigaction() fängt die resultierenden SIGSEGV, tun Sie Ihre Protokollierung oder was auch immer und markieren Sie die Seite als beschreibbar wieder.

Andere Tipps

Was Sie brauchen, ist der Zugang zu dem X86 Debug-Register: http://en.wikipedia.org/wiki / Debug_register

Sie werden die Unterbrechungsadresse in einem der DR0 bis DR3 festlegen müssen, und dann die Bedingung (Daten schreiben) in DR7. Der Interrupt wird auftreten, und Sie können Ihren Debug-Code ausführen DR6 zu lesen und finden, was den Haltepunkt verursacht wird.

Wenn GDB nicht funktioniert, haben Sie vielleicht einen einfacheren / kleinen Debugger versuchen wie http: // Source. net / projects / minibug / -. wenn das nicht funktioniert, können Sie zumindest den Code gehen und verstehen, wie die Debug-Hardware selbst auf dem Prozessor verwenden,

Außerdem gibt es eine große IBM-Entwickler Ressource auf die Beherrschung Linux-Debugging-Techniken, die einige zusätzliche Optionen bieten sollte:

http://www.ibm.com/developerworks/linux/library / l-debug /

Ein recht guter Artikel über dies zu tun ist Fenster hier ist (ich weiß, Sie auf Linux laufen lassen, aber andere könnten zusammen auf diese Frage kommen will sie in den Fenstern zu tun):

http://www.codeproject.com/KB/debug/hardwarebreakpoint.aspx

-Adam

hat GDB diese Funktion hat: es ist Hardware Beobachtungspunkte genannt, und es ist sehr gut auf Linux unterstützt / x86:

(gdb) watch *(int *)0x12345678

Wenn Ihre Anwendung GDB abstürzt, bauen aktuelle GDB von CVS Kopf .

Wenn die GDB fehlschlägt, Datei eines GDB Fehler .

Die Chancen stehen wir GDB beheben können schneller, als Sie um SIGSEGV Handler (vorausgesetzt, einen guten Testfall) hacken und Korrekturen zu GDB helfen Ihnen bei zukünftigen Problemen auch.

mprotect hat einen Nachteil: Ihre Speicher muss Seitengrenze ausgerichtet sein. Ich hatte meinen problematischen Speicher auf dem Stapel und war nicht in der Lage mprotect () zu verwenden.

Wie Adam sagte, was Sie wollen, ist das Debug-Register zu manipulieren. Am Fenster, habe ich dies: http://www.morearty.com/code/breakpoint/ und es funktionierte großartig. Ich portierte es auch auf Mach-O (Mac OS X), und es funktionierte auch super. Es war auch einfach, weil Mach-O hat thread_set_state (), die zu SetThreadContext entspricht ().

Das Problem mit Linux ist, dass es nicht solche Äquivalente hat. Ich fand ptrace, aber ich dachte, das kann es nicht sein, es ist etwas einfacher sein. Aber es ist nicht. Noch. Ich denke, sie auf einem hw_breakpoint API arbeiten sowohl für den Kernel und User-Space. (Siehe http://lwn.net/Articles/317153/ )

Aber wenn ich fand diese: http://blogs.oracle.com/nike/entry / memory_debugger_for_linux ich es ausprobiert und es war nicht so schlimm. Die ptrace Methode funktioniert durch ein „außerhalb Prozess“ wirkt als „Debugger“, sich an Ihrem Programm, neue Werte für die Debug-Register eingespritzt wird, und endet mit Ihrem Programm mit einer neuen hw Unterbrechungs Satz fort. Die Sache ist, können Sie dieses „außerhalb Prozess“ selbst erstellen mithilfe von fork (), (ich hatte keinen Erfolg mit einem Pthread) und tun Sie diese einfachen Schritte inline in Ihrem Code.

Der addwatchpoint Code muss angepasst werden, um mit 64-Bit-Linux zu arbeiten, aber das ändert sich gerade USER_DR7 usw. offsetof (struct Benutzer, u_debugreg [7]). Eine andere Sache ist, dass nach einer PTRACE_ATTACH, müssen Sie für die Debuggee warten, um tatsächlich zu stoppen. Aber statt retrying ein POKEUSER in einem langen Schleife, die richtige Sache zu tun, würde eine waitpid sein () auf Ihrem pid.

Der einzige Haken mit der ptrace Methode ist, dass das Programm nur einen „Debugger“ zu einem Zeitpunkt gebunden hat. So fügen Sie eine ptrace wird fehlschlagen, wenn Ihr Programm bereits unter gdb Steuerung ausgeführt wird. Aber genau wie das Beispiel-Code der Fall ist, können Sie einen Signal-Handler für SIGTRAP registrieren, ohne gdb laufen, und wenn Sie das Signal zu fangen, geben Sie ein Besetzt Warteschleife für GDB zu befestigen. Von dort können Sie sehen, wer versucht, Ihr Gedächtnis zu schreiben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top