WinDbg zeigt keine Registerwerte an

8

Im Grunde ist dies die gleiche Frage, die gestellt wurde hier .

Beim Ausführen des Kernel-Debugging eines Computers mit Windows 7 oder älter, mit WinDbg Version 6.2 und höher, zeigt der Debugger nichts im Registerfenster an. Wenn Sie auf die Schaltfläche Customize... klicken, wird in einem Meldungsfeld Registers are not yet known angezeigt.

Gleichzeitig führt die Ausgabe des Befehls r dazu, dass perfekt gültige Registerwerte ausgedruckt werden.

Was ist der Grund für dieses Verhalten, und kann es behoben werden?

    
Michael Bikovitsky 12.03.2016, 17:52
quelle

1 Antwort

14

TL; DR : Ich habe eine Erweiterungs-DLL geschrieben, die den Fehler behebt. Verfügbar hier .

Das Problem

Um das Problem zu verstehen, müssen wir zuerst verstehen, dass WinDbg im Grunde nur ein Frontend für die Windows Symbolic Debugger Engine von Microsoft ist, implementiert in dbgeng.dll . Andere Frontends enthalten die Befehlszeilen kd.exe (Kernel-Debugger) und cdb.exe (Benutzermodus-Debugger).

Die Engine implementiert alles, was wir von einem Debugger erwarten: Arbeiten mit Symboldateien, Lesen und Schreiben von Speicher und Registern, Setzen von Breakpoints usw. Die Engine stellt dann all diese Funktionalität über COM-ähnliche Schnittstellen zur Verfügung (sie implementieren IUnknown, sind es aber nicht) registrierte Komponenten). So können wir beispielsweise unseren eigenen Debugger schreiben (wie zB diese Person hat).

Mit diesem Wissen können wir nun eine fundierte Schätzung machen, wie WinDbg die Werte der Register auf der Zielmaschine erhält.

Die Engine macht die IDebugRegisters Schnittstelle zur Manipulation von Registern. Diese Schnittstelle deklariert die Methode GetValues für Abrufen der Werte mehrerer Register auf einmal. Aber woher weiß WinDbg, wie viele Register vorhanden sind? Deshalb haben wir die Methode GetNumberRegisters .

Um die Werte aller Register auf dem Ziel zu erhalten, müssen wir also so etwas machen:

  1. Rufen Sie IDebugRegisters::GetNumberRegisters auf, um die Gesamtzahl der Register zu erhalten.
  2. Rufen Sie IDebugRegisters::GetValues mit dem Parameter Count auf die Gesamtzahl der Register, den Parameter Indices auf NULL und den Parameter Start auf 0 .
  3. auf

Ein kleines Problem: Der zweite Aufruf scheitert mit E_INVALIDARG .

Ehm, entschuldigen Sie? Wie kann es scheitern? Besonders rätselhaft ist die Dokumentation für diesen Rückgabewert:

  

Der Wert des Index eines Registers ist größer als die Anzahl der Register auf dem Zielrechner.

Aber ich habe Sie nur gefragt, wie viele Register es gibt, also wie kann dieser Wert außerhalb des Bereichs liegen? Okay, lassen Sie uns die Dokumente trotzdem weiterlesen, vielleicht wird etwas klar:

  

Wenn der Rückgabewert nicht S_OK ist, wurden möglicherweise einige der Register gelesen . Wenn auf das Ziel nicht zugegriffen werden konnte, lautet der Rückgabetyp E_UNEXPECTED und Werte sind unverändert. Andernfalls enthalten die Werte Teilergebnisse und die Register, die nicht gelesen werden konnten, haben den Typ DEBUG_VALUE_INVALID.

(Betonung meiner.)

Aha! Vielleicht konnte der Motor eines der Register nicht lesen! Aber welcher? Stellt sich heraus, dass der Motor im Register xcr0 gedrosselt wird. Aus dem Intel 64 und IA-32 Architectures Software-Entwicklerhandbuch :

  

Das erweiterte Steuerregister XCR0 enthält eine Statuskomponenten-Bitmap, die die Benutzerzustandskomponenten angibt, für die die Software den Feature-Code XSAVE zur Verwaltung aktiviert hat. Wenn das Bit, das einer Zustandskomponente entspricht, in XCR0 gelöscht ist, werden Anweisungen in dem XSAVE -Featureset unabhängig von dem Wert der Befehlsmaske nicht an dieser Zustandskomponente arbeiten.

Okay, das Register steuert die Operation der XSAVE Anweisung, die den Zustand der erweiterten Funktionen der CPU speichert (wie XMM und AVX). Laut dem letzten Kommentar auf der Seite benötigt diese Anleitung einige Unterstützung vom Betriebssystem. Obwohl der Kommentar besagt, dass Windows 7 (auf dem die VM, auf der ich getestet habe, ausgeführt wurde) diese Anweisung unterstützt, scheint das vorliegende Problem trotzdem mit dem Betriebssystem zu tun zu haben, da wenn das Ziel Windows 8 ist, alles einwandfrei funktioniert / p>

Es ist wirklich unklar, ob der Fehler innerhalb der Debugger-Engine liegt, die mehr Register meldet, als Werte abrufen kann, oder innerhalb von WinDbg, die keine -Werte anzeigt, wenn die Engine ausfällt um alle von ihnen zu erzeugen.

Die Lösung

Wir könnten natürlich in den sauren Apfel beißen und nur eine ältere Version von WinDbg zum Debuggen älterer Windows-Versionen verwenden. Aber wo ist die Herausforderung darin?

Stattdessen präsentiere ich Ihnen eine Debugger-Erweiterung , die dieses Problem löst. Dies geschieht, indem man (mit Hilfe von dieser Bibliothek ) die relevanten Debugger-Engine-Methoden einhängt und S_OK zurückgibt, wenn dies der einzige ist Registrieren, dass fehlgeschlagen war xcr0 . Andernfalls verbreitet es den Fehler.Die Erweiterung unterstützt das Entfernen von Runtime. Wenn Sie Probleme haben, können Sie die Hooks immer deaktivieren.

Das ist es, viel Spaß!

    
Michael Bikovitsky 12.03.2016, 17:52
quelle

Tags und Links