The main feature of the upcoming 2.4 version of Profiler is the initial support for the PDB format. Our code doesn’t rely on the Microsoft DIA SDK and thus works also on OS X and Linux.
Since the PDB format is undocumented, this task would’ve been extremely difficult without the fantastic work on PDBs of the never too much revered Sven B. Schreiber.
Let’s open a PDB file.
As you can see the streams in the PDB can be explored. The TPI stream (the one describing types) offers further inspection.
All the types contained in the PDB can be exported to a Profiler header by pressing Ctrl+R and executing the ‘Dump types to header’ action.
Now the types can be used from both the hex editor and the Python SDK.
We can explore the dumped header by using, as usual, the Header Manager tool.
The type showed above in the hex editor is simple. So let’s look what a more complex PDB type may look like.
<r id='CWnd' type='class' size='84'> <b> <b type='CCmdTarget' offset='0' access='public'/> </b> <m id='_GetBaseClass' type='CRuntimeClass * ()'/> <s id='classCWnd' type='CRuntimeClass const'/> <m id='GetThisClass' type='CRuntimeClass * ()'/> <m id='GetRuntimeClass' type='CRuntimeClass * ()'/> <m id='CreateObject' type='CObject * ()'/> <m id='GetCurrentMessage' type='tagMSG const * ()'/> <f id='m_hWnd' type='HWND__ *' offset='32'/> <m id='operator struct HWND__ *' type='HWND__ * ()'/> <m id='operator==' type='int32 (CWnd const *)'/> <m id='operator!=' type='int32 (CWnd const *)'/> <m id='GetSafeHwnd' type='HWND__ * ()'/> <m id='GetStyle' type='unsigned int ()'/> <m id='GetExStyle' type='unsigned int ()'/> <m id='ModifyStyle' type='int32 (HWND__ *, unsigned int, unsigned int, uint32)'/> <m id='ModifyStyle' type='int32 (unsigned int, unsigned int, uint32)'/> <m id='ModifyStyleEx' type='int32 (HWND__ *, unsigned int, unsigned int, uint32)'/> <m id='ModifyStyleEx' type='int32 (unsigned int, unsigned int, uint32)'/> <m id='GetOwner' type='CWnd * ()'/> <m id='SetOwner' type='void (CWnd *)'/> <m id='GetWindowInfo' type='int32 (tagWINDOWINFO *)'/> <m id='GetTitleBarInfo' type='int32 (tagTITLEBARINFO *)'/> <m id='CWnd' type='void (CWnd const *)'/> <m id='CWnd' type='void (HWND__ *)'/> <m id='CWnd' type='void ()'/> <m id='FromHandle' type='CWnd * (HWND__ *)'/> <m id='FromHandlePermanent' type='CWnd * (HWND__ *)'/> <m id='DeleteTempMap' type='void ()'/> <!-- etc. --> </r>
The PDB code is also exposed to the SDK. This is a small snippet of code, which dumps all the types to a text buffer and then displays them in a text view.
from Pro.Core import * from Pro.UI import * from Pro.PDB import * def showPDBTypes(): ctx = proContext() out = proTextStream() out.setIndentSize(4) obj = ctx.currentScanProvider().getObject() tpi = obj.GetStreamObject(PDB_STREAM_ID_TPI) tpihdr = obj.TPIHeader(tpi) tiMin = tpihdr.Num("tiMin") tiMax = tpihdr.Num("tiMax") tctx = obj.CreateTypeContext(tpi) for ti in range(tiMin, tiMax): tctx.DumpType(out, ti) view = ctx.createView(ProView.Type_Text, "PDB Test") view.setLanguage("XML") view.setText(out.buffer) ctx.addView(view) showPDBTypes()
In order to dump all types to a single header, you can use the DumpAllToHeader method.