¿Cómo puedo crear objetos basados ​​en la memoria de archivo de volcado en una extensión de WinDbg?

Trabajo en una aplicación grande y con frecuencia uso WinDbg para diagnosticar problemas basados ​​en un archivo DMP de un cliente. He escrito algunas pequeñas extensiones para WinDbg que han demostrado ser muy útiles para extraer fragmentos de información de archivos DMP. En mi código de extensión me encuentro al desreferenciar objetos de la clase c ++ de la misma manera, una y otra vez, a mano. Por ejemplo:

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

Eso funciona bien, pero como he escrito más extensiones, con mayor funcionalidad (y al acceder a objetos más complicados en nuestros archivos DMP de aplicaciones), he anhelado una mejor solución. Por supuesto, tengo acceso a la fuente de nuestra propia aplicación, así que me imagino que debería haber una manera de copiar un objeto de un archivo DMP y usar esa memoria para crear un objeto real en la extensión del depurador al que puedo llamar funciones ( enlazando en dlls desde nuestra aplicación). Esto me ahorraría la molestia de sacar cosas del DMP a mano.

¿Es esto posible? Intenté cosas obvias como crear un nuevo objeto en la extensión y luego sobrescribirlo con un gran ReadMemory directamente desde el archivo DMP. Esto pareció poner los datos en los campos correctos, pero se asustó cuando intenté llamar a una función. Me imagino que me estoy perdiendo algo … ¿tal vez c ++ saca un poco de diversión que no conozco? Mi código se parece a esto:

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

SEGUIMIENTO: Parece que POSIBLEMENTE ExtRemoteTyped de EngExtCpp es lo que quiero? ¿Alguien ha utilizado con éxito esto? Necesito buscar en Google algún código de ejemplo, pero no estoy teniendo mucha suerte.

SEGUIMIENTO 2: Estoy siguiendo dos vías diferentes de investigación sobre esto.
1) Estoy buscando en ExtRemoteTyped, pero parece que esta clase es realmente un ayudante para las llamadas ReadMemory / GetFieldOffset. Sí, ayudaría a acelerar las cosas, pero realmente no ayuda a la hora de recrear un objeto a partir de un archivo DMP. Aunque la documentación es escasa, podría estar malinterpretando algo. 2) También estoy tratando de usar ReadMemory para sobrescribir un objeto creado en mi extensión con datos del archivo DMP. Sin embargo, en lugar de usar sizeof (* thisClass) como se indicó anteriormente, estaba pensando en que solo seleccionaría los elementos de datos y dejaría los vtables intactos.

Idea interesante, pero esto tendría la esperanza de trabajar solo en los objetos más simples. Por ejemplo, si el objeto contiene punteros o referencias a otros objetos (o vtables), no se copiarán muy bien en un nuevo espacio de direcciones.

Sin embargo, es posible que pueda obtener un objeto ‘proxy’ para que funcione cuando llame a los métodos proxy para que realicen las llamadas apropiadas a ReadMemory() para obtener la información. Esto parece ser una buena cantidad de trabajo, y creo que tendría que ser más o menos un conjunto personalizado de código para cada clase que deseaba representar. Probablemente haya una mejor manera de hacerlo, pero eso es lo que me vino de la cabeza.

Terminé solo siguiendo mi presentimiento inicial, y copiando los datos del archivo dmp en un nuevo objeto. Hice esto mejor haciendo objetos de envoltura remotos como este:

 class SomeClassRemote : public SomeClass { protected: SomeClassRemote (void); SomeClassRemote (ULONG inRemoteAddress); public: static SomeClassRemote * New(ULONG inRemoteAddress); virtual ~SomeClassRemote (void); private: ULONG m_Address; }; 

Y en la implementación:

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

Eso es lo básico, pero luego agrego anulaciones específicas según sea necesario para obtener más información del archivo dmp. Esta técnica me permite devolver estos nuevos objetos remotos a nuestro código fuente original para procesarlos en varias funciones de utilidad, ya que se derivan de la clase original.

Seguro que PARECE que debería poder templar esto de alguna manera … pero siempre parece haber ALGUNA razón por la que cada clase se implementa LIGERAMENTE de manera diferente, por ejemplo, algunos de nuestros objetos más complicados tienen un par de vtables, ambos de los cuales tienen que ser saltado

Sé que obtener volcados de memoria siempre ha sido la forma de obtener información para el diagnóstico, pero con ETW es mucho más fácil y usted obtiene una información junto con las stacks de llamadas que incluyen llamadas al sistema de información y el código de usuario. MS ha estado haciendo esto para todos sus productos, incluyendo Windows y VS.NET.

Es una forma no intrusiva de depuración. He hecho la misma depuración durante mucho tiempo y ahora con ETW puedo resolver la mayoría de los problemas de los clientes sin perder mucho tiempo dentro del depurador. Estos son mis dos centavos.

Me acerqué a algo similar cuando pirateé una extensión del rastreador de fugas gdi para windbg. Utilicé un contenedor STL para el almacenamiento de datos en el cliente y necesitaba una forma de atravesar los datos de la extensión. Terminé implementando las partes del hash_map que necesitaba directamente en el lado de la extensión utilizando ExtRemoteTyped, lo cual fue satisfactorio, pero me tomó un tiempo descubrirlo: o) Aquí está el código fuente.