Callstack, map2dbg
--------------------
(c) 2000 Lucian Wischik
These two programs let you print a callstack from your debug routines
in C++Builder programs. This is helpful for diagnosing bugs and crashes.
This makes remote debugging easier (when a client a thousand kilometers
away experiences erratic crashes in your program). The programs also
allow the standard DrWatson utility to extract more information about
your program after a crash.
Technically, their main contribution is to bring MS-compatible debug
files to Borland-generated executables, and to show you how you can
manipulate this information in your own code.
The files and their source code are completely free. You may do with
them what you wish. However, if you make any useful changes, please
let me know so I can incorporate them in future releases!
The stackwalk routines owe a great deal to Felix Kasza's stackwalk
example code at
http://www.mvps.org/win32/misc/stackwalk.html
He has a wide range of other example code there. Visit his site! You will
benefit greatly! The DBG-writing routines owe a lot to Matt Pietrik's
"Under the Hood" article in the March1999 Microsoft Systems Journal, at
http://msdn.microsoft.com/library/periodic/period99/hood0399.htm
QUICK START
Run the program calldemo.exe and click the button. That shows you
what can be achieved.
Launch BCB, Components|InstallPackage, and install map2dbgexp.bpl.
(That's because ms-dbg info is needed for the callstack to work.
You can disable it by unchecking Help|Generate-msdbg.)
Write your own program and add CALLDEMO\CALLSTACK.CPP and .H. Call
AnsiString s = dcallstack();
inside your program to retrieve the current call-stack.
The Help|Generate-MsDbg happens automatically upon compilation of
your program. If you'd prefer, you can instead use the command-line
program map2dbg.exe manually, every time after you've compiled.
DISCUSSION
Microsoft implemented a "imagehlp" library to provide call-stacks and
symbol information. They use it in DrWatson, and you can use it in
your own programs. It requires debug information, either in the
executable or "stripped out" in a separate debug file. Most Microsoft
programs come with stripped-out .DBG files. If a user chooses to put
the DBG file in the program directory, then symbol information becomes
available; if not, then it isn't.
Unfortunately, DrWatson and the imagehlp library require MS-compatible
debug information. And Borland generates non-compatible information.
We need a way to convert from borland-format to ms-format. I wrote
a routine "MAP2DBG" which takes a Borland-generated .MAP file,
and generates the appropriate .DBG file, and marks the executable
with a flag saying that the debug-information has been stripped out.
There is a second problem. Every time you recompile your program,
making a new executable, that flag gets lost! And without the flag,
the system believes that all the debug-information is in the .exe
not the .dbg, and so it ignores the .dbg totally. My solution was
an expert which automatically marks it as debug-stripped every
time it compiles. Or, use the command map2dbg /nomap file.exe.
There is a third problem. The imagehlp library provides a standard
way to change header information in an executable (e.g. to mark it
as debug-stripped). But these standard routines fail to work on
Borland-generated executables, claiming that they're not valid.
Therefore I had to write mark-as-stripped routines from scratch.
This also affected the loading of debug symbols. Again, we can't
use imagehlp to automatically load all the symbols, because it doesn't
believe that the BCB-generated executable is valid. Instead, we
have to explicitly enumerate all loaded modules (using toolhelp
or psapi as appropriate) and load the symbols for each module
individually.
To generate the dbg file merely requires the corresponding map file.
It does not require Project|Options|Linker|CreateDebugInformation.
It does not require UseDebugLibraries. It works fine whether you
use the dynamic-RTL or the static, and it works fine whether you
build with runtime packages or without.
The directory MAP2DBG contains source code for the conversion utility.
Comments in the map2dbg.cpp file explain the file-format of a
simple .dbg file. STRIPPER contains the source code for the expert
and isn't very interesting. The example in CALLDEMO is the one you
should look at and copy into your own programs.
NOTES
I haven't tested this much at all. I've only run it on Win2000.
If you use it in your own programs succesfully, please let me know!
If there are bugs, or limitations, or irritations, please let me know!
Email me at
[email protected] or go to my web site www.wischik.com/lu/programmer
to look for updates.