Как я могу создать объекты на основе памяти файла Dump в расширении WINDBG?

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

Вопрос

Я работаю в большом приложении и часто использую WINDBG для диагностики проблем на основе файла DMP от клиента. Я написал несколько небольших расширений для Windbg, которые оказались очень полезными для потянув битов информации из файлов DMP. В моем добавочном коде я одинаково разрабатываю объекты класса C ++ таким же образом, снова и снова, вручную. Например:

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

Это хорошо работает, но, поскольку я написал больше расширений, с большей функциональностью (и доступа к более сложным объектам в наших приложениях DMP файлы), я долгое время для лучшего решения. У меня есть доступ к источнику нашего собственного применения конечно, поэтому я полагаю, что должен быть способ скопировать объект из файла DMP и использовать эту память для создания фактического объекта в расширении отладчика, который я могу вызывать функции ( Связываясь в DLLs из нашего приложения). Это сэкономит мне неприятности, вытягивая вещи из DMP вручную.

Это даже возможно? Я пробовал очевидные вещи, такие как создание нового объекта в расширении, а затем перезаписывать его большим readmory непосредственно из файла DMP. Это, казалось, поставило данные в правильные поля, но избавились, когда я попытался вызвать функцию. Я полагаю, что что-то не хватает ... Может быть, C ++ притягивает некоторую VTable Funky-Ness, о которых я не знаю? Мой код выглядит похоже на это:

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

Продолжайте: похоже, что он, возможно, ExtremoteTyped от EngextCPP - это то, что я хочу? Кто-нибудь успешно использовал это? Мне нужно погладить какой-то пример код, но мне не повезло.

Продолжайте 2: Я преследую два разных маршрута расследования по этому поводу.
1) Я смотрю в ExtremoteTyped, но кажется, что этот класс - это действительно просто помощник для Readmory / GetFieldoffset Callset. Да, это поможет бы ускорить вещи много, но на самом деле не помогает, когда дело доходит до воссоздания объекта из файла DMP. Хотя документация стройная, поэтому я бы что-то не понимал. 2) Я также смотрю пытаться использовать readmory для перезаписания объекта, создаваемого в моем расширении с данными из файла DMP. Однако, вместо того, чтобы использовать SizeOf (* ThatClass), как указано выше, я думал, что вы выберете только элементы данных, и оставьте VTBALS нетронутыми.

Это было полезно?

Решение

Интересная идея, но это будет надежда на работу только на самых простых объектах. Например, если объект содержит указатели или ссылки на другие объекты (или VTBable), те не будут скопированы на новое адресное пространство.

Тем не менее, вы можете получить объект «прокси» для работы, когда вы вызываете методы прокси, они делают соответствующие вызовы на ReadMemory() чтобы получить информацию. Это звучит, чтобы быть справедливой работой, и я думаю, что это должно быть более или менее настроенным набором кода для каждого класса, который вы хотели прокси. Вероятно, есть лучший способ пойти об этом, но это то, что пришло мне с головы.

Другие советы

Я заканчивался после моей начальной дошколы и копировав данные из файла DMP в новый объект. Я сделал это лучше, сделав дистанционные объекты обертки, как это:

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

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

private:

    ULONG                   m_Address;

};

И в реализации:

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

Это основы, но затем добавляю конкретные переопределения при необходимости, чтобы получить дополнительную информацию из файла DMP. Этот метод позволяет мне передать эти новые удаленные объекты обратно в наш оригинальный исходный код для обработки в различных функциях утилит, потому что они получают из исходного класса.

Это наверняка, похоже, я должен быть в состоянии так как-то применять ... но, кажется, кажется, что каждый класс немного по-разному реализуется, например, некоторые из наших более сложных объектов имеют пару Vtable, оба из которых должны быть пропущено.

Я знаю, что получение дамков памяти всегда было способом получить информацию для диагностики, но с ETW его гораздо еще проще, и вы получаете информацию вместе с стеками вызовов, которые включают в себя информацию о системе и пользовательский код. MS делает это для всех своих продуктов, включая Windows и VS.NET.

Это не навязчивый способ отладки. Я сделал ту же отладку в течение очень длительного времени, и теперь с ETW я могу решить большую часть вопросов клиентов, не тратя много времени внутри отладчика. Это мои два цента.

Я подошел к чему-то похожему при взломе утечек GDI утечка для Windbg. Я использовал контейнер STL для хранения данных в клиенте и нужен способ продвижения данных из расширения. Я закончил реализовать части HASH_MAP, который я нуждался непосредственно на склоне к удлинению, используя ExtremoteTyped, которая была удовлетворительной, но меня немного понять; O)Здесь это исходный код.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top