Comment puis-je créer des objets en fonction de la mémoire de fichier de vidage dans une extension WinDbg?

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

Question

Je travaille sur une grande application et utilise fréquemment WinDbg pour diagnostiquer les problèmes à partir d'un fichier DMP d'un client. Je l'ai écrit quelques petites extensions pour WinDbg qui se sont avérées très utiles pour tirer des éléments d'information sur les fichiers DMP. Dans mon code d'extension je me trouve déréférencement objets de classe C ++ de la même manière, encore et, à la main. Par exemple:

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);

Cela fonctionne bien, mais comme je l'ai écrit plus des extensions, avec une plus grande fonctionnalité (et accéder à des objets plus complexes dans nos applications de fichiers DMP), je l'ai désiré ardemment pour une meilleure solution. J'ai accès à la source de notre propre application bien sûr, donc je figure il devrait y avoir un moyen de copier un objet à partir d'un fichier DMP et utiliser cette mémoire pour créer un objet réel dans l'extension du débogueur que je peux appeler des fonctions ( en liant à dll de notre application). Cela me sauver la peine de tirer les choses du DMP par la main.

Est-ce même possible? J'ai essayé des choses évidentes comme la création d'un nouvel objet dans l'extension, puis avec un écrasant grand ReadMemory directement à partir du fichier DMP. Cela semblait mettre les données dans les champs à droite, mais paniqué quand j'ai essayé d'appeler une fonction. Je me dis que je suis manque quelque chose ... peut-être c ++ tire un peu funky ness vtable que je ne sais pas? Mon code ressemble à ceci:

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

FOLLOWUP: Il ressemble à PROBABLEMENT ExtRemoteTyped de EngExtCpp est ce que je veux? Quelqu'un at-il utilisé avec succès cela? Je dois google jusqu'à quelques exemples de code, mais je suis de ne pas avoir beaucoup de chance.

FOLLOWUP 2:. Je poursuis deux voies d'enquête sur ce
1) Je suis à la recherche dans ExtRemoteTyped, mais il semble que cette classe est vraiment juste une aide pour les appels ReadMemory / GetFieldOffset. Oui, cela aiderait à accélérer les choses beaucoup, mais ne contribue pas vraiment quand il s'agit de recréer un objet à partir d'un fichier DMP. Bien que la documentation est mince, je pourrais donc être mal compris quelque chose. 2) Je cherche aussi à essayer d'utiliser ReadMemory pour remplacer un objet créé dans mon extension avec les données du fichier DMP. Cependant, plutôt que d'utiliser sizeof (* thisClass) comme ci-dessus, je pensais que je ne ferais que choisir les éléments de données, et de laisser les vtables intacte.

Était-ce utile?

La solution

Idée intéressante, mais cela aurait un espoir de travailler uniquement sur la plus simple des objets. Par exemple, si l'objet contient des pointeurs ou des références à d'autres objets (ou vtables), ceux qui ne copiera pas très bien vers un nouvel espace d'adressage.

Cependant, vous pourriez être en mesure d'obtenir un objet « proxy » pour travailler que lorsque vous appelez les méthodes proxy ils font les appels appropriés à ReadMemory() pour obtenir les informations. Cela semble être un peu de travail, et je le pense qu'il devrait être plus ou moins un ensemble personnalisé de code pour chaque classe que vous vouliez proxy. Il y a probablement une meilleure façon de s'y prendre, mais c'est ce qui est venu me le dessus de ma tête.

Autres conseils

J'ai fini juste après mon intuition initiale et la copie sur les données du fichier dmp dans un nouvel objet. Je l'ai fait mieux en faisant des objets wrapper à distance comme ceci:

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

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

private:

    ULONG                   m_Address;

};

Et dans la mise en œuvre:

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);
}

Ce sont les bases, mais j'ajouter des valeurs de remplacement en tant que de besoin pour saisir plus d'informations à partir du fichier dmp. Cette technique me permet de transmettre ces nouveaux objets distants de nouveau dans notre code source d'origine pour le traitement de diverses fonctions d'utilité, car ils sont issus de la classe d'origine.

Il semble que que je devrais pouvoir en quelque sorte ... ce créer des modèles à mais il semble toujours être une raison que chaque classe est mis en œuvre un peu différemment, par exemple, certains de nos objets plus complexes ont un couple vtables, tous deux doivent être sautées.

Je sais obtenir des décharges de mémoire ont toujours été le moyen d'obtenir des informations pour le diagnostic, mais avec ETW son beaucoup plus facile et vous obtenez une information ainsi que des piles d'appels qui comprennent les appels système d'information et le code utilisateur. MS a fait cela pour tous leurs produits, y compris Windows et VS.NET.

Il est un moyen non intrusif de débogage. Je l'ai fait même débogage très longtemps et maintenant avec ETW je suis en mesure de résoudre la plupart des problèmes des clients sans dépenser beaucoup de temps à l'intérieur du débogueur. Ce sont mes deux cents.

Je me suis approché quelque chose de similaire lorsque le piratage d'une extension traceur de fuite pour RDB windbg. J'utilisé un récipient de stl pour le stockage de données dans le client et le besoin d'un moyen pour traverser les données à partir de l'extension. J'ai fini par mettre en œuvre les parties du hash_map je avais besoin directement sur le côté de l'extension à l'aide ExtRemoteTyped qui était satisfaisant, mais m'a pris du temps pour comprendre; o) est le code source.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top