x86/x64 MSVC plugins
26/Jan 2013
Recently I had to write a tiny MSVC plugin to help visualizing one of our structures. It’s been a while since I’ve done it last time, so I started Googling for help. The good news is – it’s now much easier to find information/articles (mostly unofficial). The bad news – there are still many dark corners & I ran into a problem that took me a while to figure out. Our game runs both in 32-bit (x86) & 64-bit mode (x64, we have two executables). I wanted my plugin to work with both, which might be tricky if your structures contain pointers. Example:
1struct Foo
2{
3 void* data;
4 Bar bar;
5};
Now, imagine we’d like to get information about ‘bar’ member (given Foo pointer), offset will be different in x64/x86 builds. Luckily, there’s a method in DEBUGHELPER class that lets us retrieve configuration – GetProcessorType. Sample usage:
1template<typename PtrType>
2struct Foo
3{
4 PtrType data;
5 Bar bar;
6};
7//DEBUGHELPER *pHelper
8enum MPT
9// stolen from https://github.com/dawgfoto/cv2pdb/blob/master/src/dviewhelper/dviewhelper.cpp
10{
11 MPT_X86 = 0,
12 MPT_IA64,
13 MPT_AMD64,
14 MPT_Unknown
15};
16const int cpuType = pHelper->GetProcessorType(pHelper);
17DWORD bytesRead(0);
18const DWORD bytesToRead = (cpuType == MPT_X86 ? sizeof(Foo<uint32>) : sizeof(Foo<__int64>));
19Foo<__int64> foo; // bigger type by default (also -- stricter alignment reqs)
20if (pHelper->ReadDebuggeeMemoryEx(pHelper, pHelper->GetRealAddress(pHelper),
21 bytesToRead, &foo, &bytesRead) != S_OK || bytesRead != bytesToRead)
22{
23 return E_FAIL;
24}
25Bar* bar = &foo.bar;
26if(cpuType == MPT_X86)
27{
28 Foo<uint32>* ff32 = reinterpret_cast<Foo<uint32>* >(&foo);
29 bar = &ff32->bar;
30}
31// Process bar now, it's pointing to a correct location both for 32 & 64 bit builds.
Old comments
Karl Schmidt 2013-01-30 17:51:05
Thanks for sharing! I’m sure this will save someone else a bunch of time and frustration :)