Good morning,
In this post, I was looking for a way to find CString
entries within a dump, and I still am :-)
It seems possible to find object related entries, based on the first field as mentioned in Windbg's x /2
result. For objects who have virtual methods, this seems to be the __vptr
field (which corresponds with *vftable'
entries), and I'd thought this question to be easy for the particular case of the CString
class.
In the source code (C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\<version>\crt\src\vcruntime\undname.cxx
), I've found following entry:
#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
This makes me wonder if I could use one of the mentioned entries as candidates for the first field of an object. I already have found out that there exists an entry in windbg
's x /2 *!ATL::CStringT*
command, ending by scalar deleting destructor'
, but I don't know if I could use this as a "first field" candidate.
P.s. In case you wonder "But why don't you just try it?", there is the issue that the CStringT
objects, present in my dumpfiles, contain quite some strange characters, which makes it very difficult to see if I'm doing the right thing and see strange but correct characters, or if I'm looking at bogus results.
Thanks in advance
It seems that CString
just encapsulate a pointer and doesn't have have any virtual methods, so no vtable.
Here's a little example:
#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;
}
Put the resulting executable in Windbg and started with world
as parameter.
put a BP and go
0:000> bp ConsoleApplication1!SayHello
0:000> bl
0 e Disable Clear x86 00000000`01041420 0001 (0001) 0:**** ConsoleApplication1!SayHello
0:000> g
BP is hit; just step once to pass over cstring
local var init:
Breakpoint 0 hit
ConsoleApplication1!SayHello:
01041420 55 push ebp
0:000:x86> p
You can use the dt
command (display type) to see what fields are in a type.
Used here to see the cstring
local var:
0:000:x86> dt cstring
Local var @ 0x114f944 Type ATL::CStringT<char,ATL::StrTraitATL<char,ATL::ChTraitsCRT<char> > >
+0x000 m_pszData : 0x01224e20 "world"
There's only one field in a CString
, its name is m_pszData
and it's just a pointer:
0:000:x86> dx -r1 ((ConsoleApplication1!char *)0x1224e20)
((ConsoleApplication1!char *)0x1224e20) : 0x1224e20 : "world" [Type: char *]
sizeof
operator on the local var gives only 4:
0:000:x86> ?? sizeof(cstring)
unsigned int 4
Confirmed with da
:
0:000:x86> dp cstring L4
0114f944 01224e20 3ec0fed1 0114f998 01042bf1
0:000:x86> da 01224e20
01224e20 "world"
You won't be able to find CString
instances in a dump as they are just pointers to data.