Как найти первое поле из объекта / класса? - PullRequest
0 голосов
/ 02 июля 2018

Доброе утро, В этом посте я искал способ найти CString записей в дампе, и я до сих пор: -)
Кажется возможным найти записи, относящиеся к объекту, основываясь на первом поле, как указано в результате x /2 Windbg. Для объектов, которые имеют виртуальные методы, это, кажется, поле __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 x /2 *!ATL::CStringT* есть запись, оканчивающаяся на scalar deleting destructor', но я не знаю, смогу ли я использовать это в качестве кандидата "первого поля".

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

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

1 Ответ

0 голосов
/ 02 июля 2018

Кажется, что 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 локальную переменную 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 экземпляров в дампе, так как они всего лишь указатели на данные.

...