Как найти первое поле из объекта / класса?

Доброе утро, В этом посте я искал способ найти CString записи в дампе, а я до сих пор:-)
Кажется возможным найти записи, относящиеся к объекту, на основе первого поля, упомянутого в Windbg. x /2 результат. Для объектов, которые имеют виртуальные методы, это, кажется, __vptr поле (которое соответствует *vftable' записи), и я думал, что этот вопрос будет легким для частного случая CString учебный класс.

В исходном коде (C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\<version>\crt\src\vcruntime\undname.cxx), Я нашел следующую запись:

#if ( !NO_COMPILER_NAMES )
    "`vftable'",                          <--- vftable: the one I'm working with
    "`vbtable'",
    "`vcall'",
    "`typeof'",
    "`local static guard'",
    "`string'",
    "`vbase destructor'",
    "`vector deleting destructor'",
    "`default constructor closure'",
    "`scalar deleting destructor'",
    "`vector constructor iterator'",
    "`vector destructor iterator'",
    "`vector vbase constructor iterator'",
    "`virtual displacement map'",
    "`eh vector constructor iterator'",
    "`eh vector destructor iterator'",
    "`eh vector vbase constructor iterator'",
    "`copy constructor closure'",
    "`udt returning'",
    "`EH", //eh initialized struct
    "`RTTI", //rtti initialized struct
    "`local vftable'",
    "`local vftable constructor closure'",
#endif // !NO_COMPILER_NAMES

Это заставляет меня задуматься, могу ли я использовать одну из упомянутых записей в качестве кандидатов на первое поле объекта. Я уже узнал, что существует запись в windbg"s x /2 *!ATL::CStringT* команда, заканчивающаяся scalar deleting destructor', но я не знаю, смогу ли я использовать это как "первое поле" кандидата.

Ps В случае, если вы задаетесь вопросом "Но почему бы вам просто не попробовать?", Есть проблема, что CStringT объекты, присутствующие в моих дамп-файлах, содержат довольно странные символы, из-за чего очень трудно увидеть, правильно ли я поступаю, и увидеть странные, но правильные символы, или я смотрю на поддельные результаты.

заранее спасибо

1 ответ

Решение

Кажется, что CString просто инкапсулирует указатель и не имеет никаких виртуальных методов, поэтому нет vtable.

Вот небольшой пример:

#include <atlstr.h>

void SayHello(CHAR* arg)
{
    CStringA cstring = arg;

    CStringA message = "Hello " + cstring + "!";

    printf("message: %s", (LPCSTR)message);
}

int main(int argc, CHAR** argv)
{
    if (argc < 2)
        return -1;

    SayHello(argv[1]);

    return 0;
}

Поместите полученный исполняемый файл в Windbg и начните с world в качестве параметра.

поставить БП и идти

0:000> bp ConsoleApplication1!SayHello
0:000> bl
     0 e Disable Clear  x86 00000000`01041420     0001 (0001)  0:**** ConsoleApplication1!SayHello
0:000> g

БП поражен; просто шаг один раз, чтобы пройти cstring локальный var init:

Breakpoint 0 hit
ConsoleApplication1!SayHello:
01041420 55              push    ebp
0:000:x86> p

Вы можете использовать dt команда (тип отображения), чтобы увидеть, какие поля в типе. Используется здесь, чтобы увидеть cstring местный вар:

0:000:x86> dt cstring
Local var @ 0x114f944 Type ATL::CStringT<char,ATL::StrTraitATL<char,ATL::ChTraitsCRT<char> > >
   +0x000 m_pszData        : 0x01224e20  "world"

Там только одно поле в CString, его имя m_pszData и это просто указатель:

0:000:x86> dx -r1 ((ConsoleApplication1!char *)0x1224e20)
((ConsoleApplication1!char *)0x1224e20)                 : 0x1224e20 : "world" [Type: char *]

sizeof Оператор на локальной переменной дает только 4:

0:000:x86> ?? sizeof(cstring)
unsigned int 4

Подтверждено с da:

0:000:x86> dp cstring L4
0114f944  01224e20 3ec0fed1 0114f998 01042bf1

0:000:x86> da 01224e20 
01224e20  "world"

Вы не сможете найти CString экземпляры в дампе, так как они просто указатели на данные.

Другие вопросы по тегам