Wie kann ich Objekte basierend auf dem Speicher des Dump -Datei in einer Windbg -Erweiterung erstellen?

StackOverflow https://stackoverflow.com/questions/2573242

Frage

Ich arbeite an einer großen Anwendung und verwende häufig WindBG, um Probleme basierend auf einer DMP -Datei eines Kunden zu diagnostizieren. Ich habe ein paar kleine Erweiterungen für Windbg geschrieben, die sich als sehr nützlich erwiesen haben, um Informationen aus DMP -Dateien herauszuholen. In meinem Erweiterungscode finde ich die C ++ - Klasse -Objekte auf die gleiche Weise, immer wieder von Hand. Zum Beispiel:

Address = GetExpression("somemodule!somesymbol");
ReadMemory(Address, &addressOfPtr, sizeof(addressOfPtr), &cb);

// get the actual address
ReadMemory(addressOfObj, &addressOfObj, sizeof(addressOfObj), &cb);

ULONG offset;
ULONG addressOfField;

GetFieldOffset("somemodule!somesymbolclass", "somefield", &offset);
ReadMemory(addressOfObj+offset, &addressOfField, sizeof(addressOfField), &cb);

Das funktioniert gut, aber wie ich mehr Erweiterungen mit größerer Funktionalität geschrieben habe (und auf kompliziertere Objekte in unseren Anwendungsdateien zugreift) habe ich mich nach einer besseren Lösung gesehnt. Ich habe natürlich Zugriff auf die Quelle unserer eigenen Anwendung. Ich denke also, dass es eine Möglichkeit geben sollte, ein Objekt aus einer DMP -Datei zu kopieren und diesen Speicher zu verwenden, um ein tatsächliches Objekt in der Debugger -Erweiterung zu erstellen, auf die ich Funktionen aufrufen kann (auf den ich Funktionen aufrufen kann ( durch Verknüpfung in DLLs aus unserer Anwendung). Dies würde mir die Mühe ersparen, Dinge von Hand aus der DMP herauszuziehen.

Ist das überhaupt möglich? Ich habe offensichtliche Dinge wie das Erstellen eines neuen Objekts in der Erweiterung ausprobiert und es dann mit einem großen ReadMemory direkt aus der DMP -Datei überschreiben. Dies schien die Daten in die richtigen Felder zu bringen, aber ausgeflippt, als ich versuchte, eine Funktion aufzurufen. Ich denke, mir fehlt etwas ... Vielleicht zieht C ++ ein paar vtable Funky-Ness, von denen ich nichts weiß? Mein Code sieht dem ähnlich aus:

SomeClass* thisClass = SomeClass::New();
ReadMemory(addressOfObj, &(*thisClass), sizeof(*thisClass), &cb);

Follow -up: Es sieht so aus, als wäre möglicherweise extremotypisiert von EngextCpp, was ich will? Hat jemand das erfolgreich benutzt? Ich muss einen Beispiel -Code aufgeben, habe aber nicht viel Glück.

Follow -up 2: Ich verfolge zwei verschiedene Untersuchungswege dazu.
1) Ich suche extremotypisch, aber es scheint, dass diese Klasse wirklich nur ein Helfer für die ReadMemory/GetfieldOffset -Anrufe ist. Ja, es würde helfen, die Dinge viel zu beschleunigen, hilft aber nicht wirklich, wenn es darum geht, ein Objekt aus einer DMP -Datei neu zu erstellen. Obwohl die Dokumentation gering ist, kann ich etwas missverstehen. 2) Ich möchte auch versuchen, ReadMemory zu verwenden, um ein in meiner Erweiterung erstellter Objekt mit Daten aus der DMP -Datei zu überschreiben. Anstatt die Größe (*diese Klasse) wie oben zu verwenden, dachte ich, ich würde nur die Datenelemente auswählen und die Vtables unberührt lassen.

War es hilfreich?

Lösung

Interessante Idee, aber dies hätte die Hoffnung, nur an den einfachsten Objekten zu arbeiten. Wenn das Objekt beispielsweise Zeiger oder Verweise auf andere Objekte (oder VTables) enthält, kopieren diese nicht sehr gut in einen neuen Adressraum.

Möglicherweise können Sie jedoch ein "Proxy" -Objekt zum Arbeiten bringen, das, wenn Sie die Proxy -Methoden aufrufen ReadMemory() Um die Informationen zu erhalten. Dies klingt für ein bisschen Arbeit, und ich würde denken, dass es für jede Klasse, die Sie für den Proxy wollten, mehr oder weniger ein benutzerdefinierter Code -Satz sein müsste. Es gibt wahrscheinlich einen besseren Weg, um das zu tun, aber das ist mir von meinem Kopf zu mir gekommen.

Andere Tipps

Am Ende habe ich meine anfängliche Ahnung befolgt und die Daten aus der DMP -Datei in ein neues Objekt kopiert. Ich habe das besser gemacht, indem ich wie diesen Remote -Wrapper -Objekten erstellt habe:

class SomeClassRemote : public SomeClass
{
protected:
    SomeClassRemote (void);
    SomeClassRemote (ULONG inRemoteAddress);

public:
    static  SomeClassRemote *       New(ULONG inRemoteAddress);
    virtual ~SomeClassRemote (void);

private:

    ULONG                   m_Address;

};

Und in der Implementierung:

SomeClassRemote::SomeClassRemote (ULONG inRemoteAddress)
{
    ULONG cb;

    m_Address = inRemoteAddress;

    // copy in all the data to the new object, skipping the virtual function tables
    ReadMemory(inRemoteAddress + 0x4, (PVOID) ((ULONG)&(*this) +0x4), sizeof(SomeClass) - 4, &cb);
}

SomeClassRemote::SomeClassRemote(void)
{
}

SomeClassRemote::~SomeClassRemote(void)
{
}

SomeClassRemote* SomeClassRemote::New(ULONG inRemoteAddress)
{
    SomeClassRemote*x = new SomeClassRemote(inRemoteAddress);

    return (x);
}

Das sind die Grundlagen, aber dann füge ich nach Bedarf bestimmte Überschreibungen hinzu, um weitere Informationen aus der DMP -Datei zu erhalten. Diese Technik ermöglicht es mir, diese neuen Remote -Objekte in unseren ursprünglichen Quellcode für die Verarbeitung in verschiedenen Dienstprogrammfunktionen zu übergeben, weil sie aus der ursprünglichen Klasse abgeleitet sind.

Es scheint sicher, als sollte ich in der Lage sein, dies irgendwie templatisieren zu können ... aber es scheint immer einen Grund zu geben, dass jede Klasse etwas anders implementiert wird, beispielsweise einige unserer komplizierteren Objekte haben ein paar Vtables, die beide sein müssen übersprungen.

Ich weiß, dass es immer der Weg war, Speichermagnungen zu erhalten, um Informationen für die Diagnose zu erhalten, aber mit ETW ist es viel einfacher und Sie erhalten eine Informationen zusammen mit Anrufstapeln, die Anrufe für Informationssysteme und Benutzercode enthalten. MS hat dies für alle Produkte wie Windows und Vs.NET getan.

Es ist eine nicht störende Art des Debuggens. Ich habe das gleiche Debuggen sehr lange getan und jetzt kann ich mit ETW die meisten Kundenprobleme lösen, ohne viel Zeit im Debugger zu verbringen. Das sind meine zwei Cent.

Ich näherte mich etwas Ähnliches, als ich eine GDI -Leck -Tracer -Erweiterung für Windbg hackte. Ich habe einen STL -Container für die Datenspeicherung im Client verwendet und eine Möglichkeit benötigt, um die Daten aus der Erweiterung zu überqueren. Am Ende habe ich die Teile des Hash_Map implementiert, die ich direkt auf der Verlängerungsseite mit extremotypen brauchte, was zufriedenstellend war, mich aber eine Weile brauchte, um herauszufinden; o)Hier ist der Quellcode.

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