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!