Aaron Lerch recently wrote about a funny name for an exported function he saw exported from DBGHELP.DLL, itoldyouso. Aaron showed a small section of the Dependency Walker output, which piqued my curiosity. Below is a larger screen shot. Does anything strike you interesting in the exported functions?
DBGHELP.DLL has a few documented WinDBG extension commands in it, such as !sym and !dh, which set up symbol loading diagnostics and dump module PE headers, respectively. Seeing that itoldyouso was lowercase that got me wondering if it were an undocumented WinDBG extension command. Firing up WinDBG and giving !itoldyouso a whirl, produced the following:
0:000> !itoldyouso
!IToldYouSo <module> [symbol]
!IToldYouSo tests the validity of a module against a symbol file.
The module can be specified by either its name or base address.
If a symbol file is not specified, then the loaded symbol is tested.
Otherwise, if a pdb or dbg symbol file path is specified, it is tested
against the loaded module.
That’s pretty neat! If you’ve got several .PDB files for a module, you can use !itoldyouso (or !chksym, which does the same action) to see which one is the exact match. By the way, if you don’t have matching PDB symbols for a particular binary you can force WinDBG to load any symbols with the .symopt (Set Symbols Options) command and passing 0x40 as the option. That sets the SYMOPT_LOAD_ANYTHING flag to the symbol loader. Note that Visual Studio will only load the exact matching PDB symbols and there’s no way to change that behavior.
In the screen capture above, you can probably see some other undocumented WinDBG extension commands. If you have ever looked at the DBGHELP.DLL documentation you can see that some of the names are related to the Microsoft symbol format. Nearly all the undocumented commands exported by DBGHELP.DLL look like they are for assisting the WinDBG developers with debugging symbol handling or stack walking.
There is only one other command that were useful to us mere mortal developers, !lmi, which takes a module name on the command line and produces detailed output on the module and the loaded symbol file.
0:001> !lmi bugslayerutil
Loaded Module Info: [bugslayerutil]
Module: BugslayerUtil
Base Address: 60000000
Image Name: C:DevBugslayerUtil.dll
Machine Type: 332 (I386)
Time Stamp: 47152fb2 Tue Oct 16 14:40:02 2007
Size: 30000
CheckSum: 354ba
Characteristics: 2102
Debug Data Dirs: Type Size VA Pointer
CODEVIEW 52, 268e8, 268e8 RSDS –
GUID: {5073F855-EEAC-4DC0-96DD-A84C85CF439F}
Age: 1, Pdb: c:DevBugslayerUtil.pdb
Image Type: FILE – Image read successfully from debugger.
C:DevBugslayerUtil.dll
Symbol Type: PDB – Symbols loaded successfully from image path.
C:DevBugslayerUtil.pdb
Compiler: Resource – front end [0.0 bld 0] –
back end [8.0 bld 50727]
Load Report: private symbols & lines, not source indexed
C:DevBugslayerUtil.pdb
Thanks Aaron for pointing out a funny function name!