Pergunta

Trabalho em um grande aplicativo e freqüentemente uso o Windbg para diagnosticar problemas com base em um arquivo DMP de um cliente. Escrevi algumas pequenas extensões para o Windbg que se mostraram muito úteis para extrair bits de informações dos arquivos DMP. No meu código de extensão, me peço desreferenciando os objetos da classe C ++ da mesma maneira, repetidamente, manualmente. Por exemplo:

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

Isso funciona bem, mas como escrevi mais extensões, com maior funcionalidade (e acessando objetos mais complicados em nossos arquivos DMP de aplicativos), ansiava por uma solução melhor. Tenho acesso à fonte de nosso próprio aplicativo, é claro, então acho que deve haver uma maneira de copiar um objeto de um arquivo DMP e usar essa memória para criar um objeto real na extensão do depurador em que posso chamar funções ( vinculando -se em DLLs a partir de nosso aplicativo). Isso me pouparia o problema de tirar as coisas do DMP manualmente.

Isso é possível? Tentei coisas óbvias, como criar um novo objeto na extensão, depois sobrescrever -o com uma grande readmórbio diretamente do arquivo DMP. Isso parecia colocar os dados nos campos certos, mas assustou quando tentei chamar uma função. Acho que estou perdendo alguma coisa ... talvez o C ++ puxe um pouco de funky que eu não conheço? Meu código se parece com isso:

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

Acompanhamento: Parece que possivelmente extremamente indicado de EngextCPP é o que eu quero? Alguém usou com sucesso isso? Preciso pesquisar no Google algum código de exemplo, mas não estou tendo muita sorte.

Acompanhamento 2: Estou buscando duas rotas diferentes de investigação sobre isso.
1) Estou olhando para a extremidade, mas parece que essa classe é realmente apenas um ajudante para as chamadas ReadMemory/GetFielfOffset. Sim, isso ajudaria a acelerar muito as coisas, mas realmente não ajuda quando se trata de recriar um objeto de um arquivo DMP. Embora a documentação seja pequena, então eu posso estar entendendo mal algo. 2) Também estou tentando usar o ReadMemory para substituir um objeto criado em minha extensão com dados do arquivo DMP. No entanto, em vez de usar sizeof (*thisclass) como acima, eu estava pensando que escolheria apenas os elementos de dados e deixaria os vtables intocados.

Foi útil?

Solução

Ideia interessante, mas isso teria uma esperança de trabalhar apenas nos objetos mais simples. Por exemplo, se o objeto contiver ponteiros ou referências a outros objetos (ou vtables), eles não copiarão muito bem para um novo espaço de endereço.

No entanto, você poderá obter um objeto 'proxy' para funcionar que, quando você chama os métodos de proxy, eles fazem as chamadas apropriadas para ReadMemory() Para obter as informações. Parece ser um pouco de trabalho, e eu acho que teria que ser mais ou menos um conjunto personalizado de código para cada classe que você queria proxy. Provavelmente há uma maneira melhor de fazer isso, mas foi isso que me veio do topo da minha cabeça.

Outras dicas

Acabei seguindo meu palpite inicial e copiando os dados do arquivo DMP em um novo objeto. Eu fiz isso melhor fazendo objetos de invólucro remoto 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;

};

E na implementação:

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

Esse é o básico, mas adiciono substituições específicas conforme necessário para obter mais informações do arquivo DMP. Essa técnica me permite transmitir esses novos objetos remotos de volta ao nosso código -fonte original para processamento em várias funções de utilidade, porque eles são derivados da classe original.

Com certeza, parece que eu deveria ser capaz de templatizar isso de alguma forma ... mas sempre parece haver alguma razão para que cada classe seja implementada de maneira um pouco diferente, por exemplo, alguns de nossos objetos mais complicados têm alguns vtables, os quais devem ser pulou.

Eu sei que obter despejos de memória sempre foi a maneira de obter informações para o diagnóstico, mas com o ETW é mais fácil e você obtém informações junto com pilhas de chamadas, que incluem chamadas de sistema de informações e código de usuário. A MS tem feito isso por todos os seus produtos, incluindo Windows e vs.net.

É uma maneira não intrusiva de depuração. Fiz a mesma depuração por muito tempo e agora com o ETW sou capaz de resolver a maioria dos problemas dos clientes sem gastar muito tempo dentro do depurador. Estes são meus dois centavos.

Aproximei -me de algo semelhante ao invadir uma extensão de traçador de vazamento de GDI para o Windbg. Usei um contêiner STL para armazenamento de dados no cliente e precisava de uma maneira de atravessar os dados da extensão. Acabei implementando as partes do hash_map de que eu precisava diretamente no lado da extensão usando extremidade que era satisfatória, mas me levou um tempo para descobrir; o)Aqui é o código -fonte.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top