it-swarm.com.de

Wie pausiert GDB eine Ausführung?

Wie Sie vielleicht wissen, können wir GDB verwenden und Haltepunkte für unseren Code festlegen, um die Ausführung für das Debuggen anzuhalten.

Meine Frage ist, wie GDB einen Prozess anhält und Sie den Inhalt von Registern beispielsweise mit i r Anzeigen lassen können. Werden diese Register nicht ständig von anderen Betriebssystemprozessen verwendet? Wie werden sie nicht überschrieben?

Ist es nur eine Momentaufnahme des Inhalts und keine Live-Daten?

16
Joe

Es variiert geringfügig mit der Architektur, aber die wichtigen Punkte gelten fast universell:

  • Durch die Unterbrechung der Wartung wird der CPU-Status (einschließlich der Register) vor dem Ausführen des ISR im Speicher gespeichert und beim Beenden des ISR wiederhergestellt.

  • Wenn eine Interrupt-Serviceroutine den Inhalt des Speicherorts austauscht, in dem diese Register gespeichert sind, kann sie einen Kontextwechsel ausführen. Jeder Thread hat einen Speicherbereich, in dem seine Register gespeichert werden, wenn der Thread nicht ausgeführt wird.

  • Der Kontextwechsel wird von einem Thread-Scheduler gesteuert, der berücksichtigt, ob ein Thread auf E/A, Synchronisation, Priorität, Signalübermittlung usw. wartet. Oft wird eine Suspend-Anzahl berücksichtigt im.

  • Der Debugger kann die Anzahl der Suspens erhöhen, wodurch sichergestellt wird, dass der Thread nicht ausgeführt werden kann. Dann kann es die gespeicherte Kopie der Register des Threads überprüfen (und ändern).

24
Ben Voigt

Lassen Sie mich zusätzlich zu den großartigen Informationen von @BenVoigt einige Ergänzungen vornehmen:

Ein Haltepunkt wird vom Debugger festgelegt, indem ein Maschinencodewert (eine Anweisung oder ein Teil einer Anweisung) in dem zu debuggenden Prozess durch eine bestimmte Trap-Anweisung an der Stelle im Code ersetzt wird, die der gewünschten (Quell-) Zeile entspricht, an der unterbrochen werden soll. Diese spezielle Trap-Anweisung ist als Haltepunkt gedacht - der Debugger weiß das und das Betriebssystem auch.

Wenn der zu debuggende Prozess/Thread die Trap-Anweisung trifft, die den Prozess auslöst, beschreibt @Ben, der die Hälfte eines Kontext-Swaps enthält, der den aktuell ausgeführten Thread (einschließlich des Speicherns seines CPU-Status im Speicher) für eine mögliche spätere Wiederaufnahme aussetzt. Da es sich bei diesem Trap um einen Haltepunkt-Trap handelt, hält das Betriebssystem den zu debuggenden Prozess mithilfe eines von @Ben beschriebenen Mechanismus angehalten und benachrichtigt den Debugger und setzt ihn schließlich fort.

Der Debugger verwendet dann Systemaufrufe, um auf den gespeicherten Status des angehaltenen Prozesses/Threads zuzugreifen, der debuggt wird.

Um die fehlerhafte Codezeile auszuführen (fortzusetzen) (die jetzt den jeweiligen Trap-Befehl enthält), stellt der Debugger den ursprünglichen Maschinencode-Wert wieder her, den er mit dem Breakpoint-Trap-Befehl überschrieben hat, und setzt möglicherweise einen anderen Trap an einer anderen Stelle (z. B. wenn ein einzelner Schritt ausgeführt wird). oder der Benutzer erstellt neue Haltepunkte) und markiert den Prozess/Thread als ausführbar, möglicherweise unter Verwendung eines Mechanismus, wie er von @Ben beschrieben wird.

Tatsächliche Details können insofern komplizierter sein, als das Aufrechterhalten eines Haltepunkts mit langer Laufzeit, der getroffen wird, bedeutet, dass Sie beispielsweise die Haltepunktfalle gegen echten Code austauschen, damit die Zeile ausgeführt werden kann, und dann den Haltepunkt wieder eintauschen ...

Werden diese Register nicht ständig von anderen Betriebssystemprozessen verwendet? Wie werden sie nicht überschrieben?

Wie @Ben beschreibt, wird die bereits vorhandene Funktion zum Anhalten/Fortsetzen von Threads (das Umschalten/Austauschen von Kontexten von Multitasking ) verwendet, mit der Prozessoren mithilfe von Time Slicing von mehreren Prozessen/Threads gemeinsam genutzt werden können.

Ist es nur eine Momentaufnahme des Inhalts und keine Live-Daten?

Es ist beides. Da der Thread, der den Haltepunkt erreicht hat, angehalten ist, handelt es sich um eine Momentaufnahme der Live-Daten (CPU-Register usw.) zum Zeitpunkt der Unterbrechung und der Autorisierender Master der CPU-Registerwerte, die im Prozessor wiederhergestellt werden sollen, falls der Thread fortgesetzt wird. Wenn Sie die Benutzeroberfläche des Debuggers zum Lesen und/oder Ändern der CPU-Register (des zu debuggenden Prozesses) verwenden, wird dieser Snapshot/Master mithilfe von Systemaufrufen gelesen und/oder geändert.

14
Erik Eidt

Genau genommen pausiert gdb selbst, zumindest in den meisten typischen Fällen, die Ausführung nicht. Stattdessen fragt gdb das Betriebssystem und das Betriebssystem unterbricht die Ausführung.

Das mag zunächst wie eine Unterscheidung ohne Unterschied erscheinen - aber ehrlich gesagt gibt es wirklich einen Unterschied. Der Unterschied besteht darin, dass diese Fähigkeit bereits in das typische Betriebssystem integriert ist, da sie die Ausführung des Threads ohnehin anhalten und neu starten muss - wenn die Ausführung eines Threads nicht geplant ist (z. B. wenn eine Ressource benötigt wird) ist derzeit nicht verfügbar) Das Betriebssystem muss es anhalten, bis die Ausführung geplant werden kann.

Zu diesem Zweck hat das Betriebssystem normalerweise einen Speicherblock für jeden Thread reserviert, um den aktuellen Status des Computers zu speichern. Wenn ein Thread angehalten werden muss, wird der aktuelle Status des Computers in diesem Bereich gespeichert. Wenn ein Thread fortgesetzt werden muss, wird der Status des Computers in diesem Bereich wiederhergestellt.

Wenn der Debugger einen Thread anhalten muss, muss das Betriebssystem diesen Thread genauso anhalten wie aus anderen Gründen. Um den Status des angehaltenen Threads zu lesen, überprüft der Debugger den gespeicherten Status des Threads. Wenn Sie den Status ändern, schreibt der Debugger in den gespeicherten Status und wird dann wirksam, wenn der Thread fortgesetzt wird.

5
Jerry Coffin