software engineer &        architecture


Produkt PDBUtils

Debugging Tool für Javalike Stacktraces und Lokale Variablen für VC6/VC7 auf Produktionssystemen.

Position:Softwareentwicklung, Projekt- und Entwicklungsleitung
Technologien:C++, VC, Debugging


PDBUtils is part of the ACDK source package. See pdbutils.h.


From Header:

  Utils to make debugging running application under Windows
  Copyright 2003 by Roger Rene Kommer ( 

  dbgutils The sources either can be in a shared library (.dll) or
  has to be linked directly to the executable. 
  Compiling dbgutils as static library (.lib) won't work!

  Requirements dbghelp.h .dll .lib from microsoft

  @mainpage PDBUtils Documentation 
  Copyright 2003 by Roger Rene Kommer (<p>

  @section intro What is PDBUtils
  PDBUtils add debugging and reflection mechanism to any VC 6 program.
  You (or another developer) had coded an application but you had too less time
  to test the application with all needed unit tests, stress tests, integration
  tests and so on, because your customer urgently need your application.<br>
  So your application installed on the customer production machine
  crashes occasionally (once the day, the week, the month) and you have no idea
  what iss going wrong, because on customers machine no debugger is installed.<p>

  PDBUtils is to designed to help in such a situation. Just linking your application
  with pdbutils.dll and insert one call into your main method you can receive
  a binary or 'source-level' text post mortem dump of the faulting application with
  all information available you normally also receive when your application was run
  under a debugger.<p>
  So you hopefully be able to identify the faulty code, fix it, provide
  a more stable version of your application and make your customer happy.
  @subsection debugging_features Debugging Features
  In case the application tends to crash DDBUtils can be used to generate binary and text dumps
  of the current scope for all threads with all current functions calls, parameter, local and global data types.
  The text dump is a text file with a listing of all threads with functions calls, parameter types an values
  and the local variables of the functions.<p>

  The binary dump creates a "CrashDump" which can be viewed with WinDbg, a free Source GUI-Debugger from Microsoft.

  @subsection throwable Enrich Exceptions classes with stack traces
    On Java an exception can provide the call stack from the point where
    the exception was thrown. With PDBUtils this is also available for 
    VC 6/7 Windows applications. It will be explained in @ref usage_secondgrade.

  @subsection premortem_debugging Create snapshot from application
    The post mortem debugging dumps are also available at normal runtime.
    It is possible to dump the state a single thread or all threads into readable
    text file. This makes sense, if the application may not crashed yet, but
    some assertion failed or run in a dead lock situtation.

  @subsection reflection_mechanism Using reflection
    On runtime you can receive reflection information on every valid memory
    address including nested user defined types and dynamic structures (using
    pointers). For example can this reflection mechanism can used to render any data
    structure into log-files.
  @section content Content
@if pdbutils_lgpl
      <li> @ref license </li>
      <li> @ref support </li>

    -<li> @ref requirements</li>
    <li> @ref usage</li>
      <li> @ref usage_firstgrade</li>
      <li> @ref usage_secondgrade</li>
      <li> @ref usage_thirdgrade</li>
      <li> @ref usage_fourthgrade</li>
      <li> <a class="el" HREF="modules.html"> Modules</A></li>
      <li> <a class="el" HREF="namespaces.html"> Namespace</A></li>

  @if pdbutils_lgpl
  @page license License

  Copyright (C) 2003 by Roger Rene Kommer

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
See also:
  See Next: @ref support

  @if pdbutils_lgpl
  @page support Support and Dowloads
  You can obtain support at my project page for ACDK (which is not directly related
  to pdbutils):<br><br>

  You can download the most current version on:<br>

  I'm also reachable via email:<p>
  @section contributions Contributions
    The major inspiration for this library comes from Matt Pietrek MSDN article
    "Improved Error Reporting with DBGHELP 5.1 APIs".<p>
    You can read it online here:<br><p>
  See Next: @ref requirements

  @page requirements Requirements
  @section dbghelp DbgHelp Library
    Before you can compile pdutils you need the DbgHelp files provided
    by Microsoft. The dbhhelp are included in the Debugging Tools for Windows:<br><p>

    Install WinDbg with complete SDK files using custom settings.
    Finally you need following files from the Debugging Tools for Windows:
    - Debugging Tools for Windows\dbghelp.dll
    - Debugging Tools for Windows\sdk\inc\dbghelp.h
    - Debugging Tools for Windows\sdk\lib\dbghelp.lib<p>

    - Copy the dbghelp.h and dbghelp.lib into the pdbutls\ext directory.
    - Copy the dbghelp.dll into your binary directory of the application
      which uses pdutils.

  @section platform Platforms
    - Windows XP Profession: Works with VC 6 and VC 7/.NET
    - Windows XP Home: Not tested
    - Windows 2003 Server: Using VC7/.NET on Windows 2003 works.<br>
    - Windows 2000 Server/Workstation: 
      Windows 2000 also provides a dbghelp.dll, but in a wrong version!<br>
      Unfortunately  it doesn't work to copy a new dbghelp.dll into the 
      windows\\system32 directory because the self-healing mechanism of Windows 2000.<p>
      The only solution I know is to copy the dbghelp.dll of Windows XP into the same directory of 
      the created application which uses the pdbutils.dll.
    - Windows NT 4, Windows 95, Windows 98: Not tested<br>
      Microsoft provides a dbghelp.dll for these older version of their OS, but 
      unfortunatelly only in a outdated version.
      But using the dbghelp of Windows XP and copy it into the system32 directory
      seems to be working.

  @section compiler Compiler Settings
    To use PDBUtils the application have to be compiled with debugging information.
  @section Installation Installation
  @subsection pdb_files .pdb files
    The VC compiler stores the debugging information in a separate file with the file suffix .pdb.<br>
    If the application should be installed outside the compile directory the corresponding .pdb file 
    has to be copied into the same directory of the executable file.<p>
    (For more details please refer to @ref usage).
  @subsection windbg WinDbg
    Use WinDbg to view the binary dumps.<br>
    WinDbg is included in the "Debugging Tools for Windows" and can be downloaded from Microsoft for free:<p>

    Although it is possible to load binary dump with VC 7/.NET (via File / Open Solution / Dump Files)
    I haven't found any way to view the dump with the call stack, local variables, etc.<p>

  See Next: @ref usage
  @page usage Usage
  @section compiling Compiling with pdbutils.
    You need to adjust the compiler setting for your executable:
    - In the C/C++ settings set debugging format Program Database
    - In the Linker settings select usage of generated program database file 
      (which generates the executable.pdb).
    - In the Linker settings select Microsoft debug format.

  @section deployment Deployment
    To deploy your executable using the pdbutils you have
    to copy:
    - dbghelp.dll (this is not needed on Windows XP and Windows 2003)
    - pdbutils.dll
    - your_dlls.dll (optional)
    - your_dlls.pdb (optional)
    - your_application.exe
    - your_application.pdb
    - vc60.pdb (see below)<br>

    The file your_application.pdb has to reside in the same directory
    as your_application.exe.<p>
    Using Visual Studio 6 unfortunately pdbutils doesn't need only the executable.pdb but also
    the file vc60.pdb. This file is generated in the object directory (by default 'Debug').<p>
    There 3 ways to deal with this vc60.pdb:

    -# Copy vc6.pdb in the same directory of your_application.exe.<br>
      Of course this has the disadvantage, that only one executable can make use
      of pdbutils.
    -# Replicate the identical directory structure (including drive letter) on your target machine
       including the directory of your_application.exe and Debug\vc60.pdb.<br>
    -# Create in the directory of your your_application.exe a directory named
       your_application_pdbs and copy all pdb's (your_application.pdb, vc60.pdb and dll pdb's) in this

  @section coding Coding
  See more you to integrate pdbutils in your source code:
  <li> @ref usage_firstgrade </li>
  <li> @ref usage_secondgrade </li>
  <li> @ref usage_thirdgrade </li>
  <li> @ref usage_fourthgrade </li>
  @page usage_firstgrade First-Grade Usage: Making CrashDumps
    The most simple way to use pdbutils in your project is to include following code 
    into your main.cpp of your application:
      // your headers
      #include <pdbutils.h>
      // more code

      int main(int argc, char* argv[])
        // your code here
    In the case your application will crash (because invalid pointer access, uncatched exceptions, etc.)
    the pdbutils will create in the directory of the binaries following files:
    The .btc file is just a plain text file with all stacktraces of all threads
    including the local variables.<p>
    The .dmp file is a binary dump file, which can be loaded with WinDbg.
    @section usage_firstgrade_btc_format The .btc format
      Following sample:

      Exception information:
Exception code: C0000005
ACCESS_VIOLATION// reason because the application crashes 
Fault address:  00401484 1 1156 C:\d\artefaktur\pdbutils\bin\pdbutils_Test.exe

Registers:// if you are an assembler freak it may useable for you
EAX: 0
EBX: 0
ECX: 6
EDX: 3745256
ESI: 26803832
EDI: 26803572
CS:EIP: 27:4199556
SS:ESP: 26803436:26803584
DS: 35
ES: 35
FS: 56
GS: 0
Flags: 66195
Crashing Thread: 
reportStack(int tc = 6)
  <Unknown>* iptr(0x00000000) <invalid pointer>; // the underlying code is null pointer dereferencing
// etc.

    The Threads:

ThreadID: 1936  ThreadHandle: 00000058 // thread identifier
C:\d\artefaktur\pdbutils\bin\pdbutils_Test.exe: // start of StackFrame, see below 
foo2(TestStruct* s(0x00CFFE4C)   TestStruct  = {

    The StackFrame:
    from the topmost stack frame (inner call) to main or thread starting function.
C:\d\artefaktur\pdbutils\bin\pdbutils_Test.exe: // module name (dll or exe)
C:\d\artefaktur\pdbutils\tests\src\pdbutils_Test.cpp(162): // source code position
foo(int tc = 6)// function including parameters
// start of local variables
  TestStruct ts = {
    char* _text = (0x004BAA50) "Just A Test";
    int _ivar = 41;
    int _ivarArray[3] = {
      [0] int  = 1;
      [1] int  = 2;
      [2] int  = 3;
    SubStruct _substruct = {
      int _subI = 2;
    TestStruct::MyUnion _myUnion = {
      int i = 41;
      <Unknown>* c(0x00000029) <invalid pointer>;
    int _myEnum = 1;
    <Unknown>* _thisPtr(0x00000000) <invalid pointer>;
} // end of function
// next stack frame
bar(int i = 42, char* text = (0x0055A04C) "This is Text", int tc = 1)

    See next: @ref usage_secondgrade
  @page usage_secondgrade Second-Grade Usage: Creating BackTraces
  Beside Creating Dumps in case of a crash of the application pdbutils is 
  also able to create text base information of the current state of an application.

  @section create_dump Creating Dumps manually

  With the method pdbutils::createDump you can create dump manually.
  void pdbutils::createDump(const char *filename=0, int crashdumpflags = DbgCrashDumpCreateAllDump, int skipCount=1)
  With the parameter crashdumpflags - a combination DbgCrashDumpOptions bits - of you can 
  control what information you want to dump.<p>

  For example by default the global Variable will not be dumped (If you link C++ standard library or MFC library,
  there will be really many global variables), but with the flag DbgFrameGetGlobals you can also dump these 

  The variable skipCount is to control the number of frames from the top, which should not be dumped.
  This is useful if you want to create a dump inside the constructor of an exception and you don't want
  to display the constructor method itself in the dump.

  Please refer to the API documentation for usage of the parameters.

  @section create_backtrace Creating BackTrace
    In Java you have the possibility to receive a BackTrace for the throwing point of an exception.
    With pdbutils::getBackTrace you can receive the same information.<p>

    For performance reason it is reasonably not to call pdbutils::getBackTrace() in every exception
    class constructor, but only save the FrameAddresses of the current call stack in the constructor
    of the exception class with the call pdbutils::getProgramCounters.

    Here some sample code:
    #define MAX_CALLSTACK 32
    class MyException
      pdbutils::FrameAddress _frameAddresses[MAX_CALLSTACK];
      int _frameAddressCount;
      , _frameAddressCount(0)
        memset(_frameAddresses, 0, sizeof(_frameAddresses));
        // take snapshot of the current thread call stack
        _frameAddressCount = pdbutils::getProgramCounters(_frameAddresses, MAX_CALLSTACK);

      // replace with your favorite String class 
      String getBackTrace() const
       // returns declaration (without variable content) of the stack
       // skip topmost stack frames (which is MyException::MyException())
        return pdbutils::renderBackTrace(_frameAddresses + 1, _frameAddressCount - 1, 
                                         pdbutils::DbgFrameGetFuncName |
                                         pdbutils::DbgFrameGetLibary |
                                         pdbutils::DbgFrameGetSourcePos |

  See next: @ref usage_thirdgrade
  @page usage_thirdgrade Third-Grade Usage: Customizing Type Rendering
  For better parsing the DbgType hooks can rearrange 
           a parsed DbgType.<p>

           For example a std::vector with T* _First and T* _Last 
           as range description only one the pointer of _First will
           point to a valid element.<p>
           std::vector<int> = {
            int* _First = 42;
            int* _Last = <invalid pointer>;
            int* _End = <invalid pointer>;

           The hooking function can rearange and fetch more sub variables.
           In the example of std::vector all pointers between >= _First and
           < _Last and represent std::vector as 'normal' vector with size
           and all elements.
           !std::vector<int> = {
             int size = 3;
             int capacity = 11;
             int data[] = {
              [0] = 42;
              [1] = 43;
              [2] = 44;
          Another sample of the DbgHook is to simplify types. std::string is
          normally an ugly template named :
                  std::basic_string<char,std::char_traits<char>,std::allocator<char> >
                    {  std::allocator<char> allocator = {  };
                  char* _Ptr = (0x00393119) "of";
                  int _Len = 2;
                  int _Res = 31;
          The simplified version is:
          !std::string  = (0x00393119) "of";

          If a hook change something in the DbgType it should rename the
          type with a leading '!'.<p>

          Please refer to the examples in std_dbgtypes.cpp and mfc_dbgtypes.cpp as sample
          how to program own hooks.<p>
    See next: @ref usage_fourthgrade
  @page usage_fourthgrade Fourth-Grade Usage: Using pdbutils as reflection mechanism
        ... to be continued ...
Last modified 2012-12-09 16:17 by rkommer By Artefaktur, Ing. Bureau Kommer