/** Utils to make debugging running application under Windows Copyright 2003 by Roger Rene Kommer (kommer@artefaktur.com) 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 (kommer@artefaktur.com)
@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.
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.
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.
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.
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
pdbutils 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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: http://www.gnu.org/copyleft/lesser.htmlSee Next: @ref support @endif */ /** @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):
@section contributions Contributions The major inspiration for this library comes from Matt Pietrek MSDN article "Improved Error Reporting with DBGHELP 5.1 APIs".
You can read it online here:
http://msdn.microsoft.com/msdnmag/issues/02/03/hood/default.aspx
See Next: @ref requirements
@endif
*/
/**
@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:
http://www.microsoft.com/whdc/ddk/debugging/default.mspx
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
- 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.
- Windows 2000 Server/Workstation:
Windows 2000 also provides a dbghelp.dll, but in a wrong version!
Unfortunately it doesn't work to copy a new dbghelp.dll into the
windows\\system32 directory because the self-healing mechanism of Windows 2000.
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
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.
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.
(For more details please refer to @ref usage).
@subsection windbg WinDbg
Use WinDbg to view the binary dumps.
WinDbg is included in the "Debugging Tools for Windows" and can be downloaded from Microsoft for free:
http://www.microsoft.com/whdc/ddk/debugging/default.mspx
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.
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)
The file your_application.pdb has to reside in the same directory
as your_application.exe.
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').
There 3 ways to deal with this vc60.pdb:
-# Copy vc6.pdb in the same directory of your_application.exe.
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.
-# 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
directory.
@section coding Coding
See more you to integrate pdbutils in your source code:
my_executable_name_2003_09_09_13_59_36.btc
my_executable_name_2003_09_09_13_59_36.dmp
The .btc file is just a plain text file with all stacktraces of all threads
including the local variables.
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:
@code
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:
------------------------------------------------------------------
C:\d\artefaktur\pdbutils\bin\pdbutils_Test.exe:
c:\d\artefaktur\pdbutils\tests\src\pdbutils_test.cpp(111):
reportStack(int tc = 6)
{
The StackFrame:
from the topmost stack frame (inner call) to main or thread starting function.
@code
---------------------------------------------------------------
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;
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
variables.
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.
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:
@code
#define MAX_CALLSTACK 32
class MyException
{
pdbutils::FrameAddress _frameAddresses[MAX_CALLSTACK];
int _frameAddressCount;
public:
MyException()
, _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 |
pdbutils::DbgFrameGetArguments
);
}
};
@endcode
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.
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.
@code
std::vector
Please refer to the examples in std_dbgtypes.cpp and mfc_dbgtypes.cpp as sample
how to program own hooks.
See next: @ref usage_fourthgrade
*/
/**
@page usage_fourthgrade Fourth-Grade Usage: Using pdbutils as reflection mechanism
... to be continued ...
*/
#ifndef win32_pdb_utils_h
#define win32_pdb_utils_h
#include