x86/x64 MSVC plugins

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

More Reading
Older// Junkers