Sometimes a function would like to know by whom it was called. And by whom
this "who" was called again. In other words: Sometimes you want to have the
full current call stack. Now there is no official API to get this
information. A function is nothing but binary asm code that tells the CPU
what to do. So the CPU does all the jumping and calling according to the
binary asm code of the current module. Windows is not involved there, so
Windows doesn't know the current call stack either.
Fortunately, every time when calling a function, the x86 CPU pushes the
return address on the stack. So theoretically we only need to browse through
the stack to get all the return addresses. However, the stack does not only
contain valid return addresses, but also LOTS of other stuff like data
pointers, random values and so on. So we have to build a filter than scans
through the stack and gives us only the valid return addresses. That is
easier said than done. Most of the time you'll get 1 valid return address
and 10 additional invalid return addresses, which *look* like being valid.
To solve this problem madStackTrace uses a disassembler and some more tricks
and finally we have a good result. Well, we have no guarantee, that the call
stack is 100% accurate, but in a lot of cases it actually is. In some cases
one or the other invalid stack item is shown, but normally by following the
call stack in your sources you can easily filter them out by yourself.
The most important case where you want to have the current call stack is
when an exception has occured. That's also the main duty of "madStackTrace",
it's internally used by madExcept to get the call stack for the
detailed exception box madExcept wants to show. For a list of what's
contained in "madStackTrace" please look at the
madStackTrace Reference.
The interface of this unit is as easy as it can be: There's just one
function which does all the work and returns a formatted plain text string,
containing the whole callstack of the specified thread.
You can ignore most of the parameters of this function, they're for fine
tuning and are internally used by madExcept. However, the first three
parameters "hideUglyItems", "showRelativeAddrs" and "showRelativeLines"
might be interesting for you, too. With the first one you can tell the stack
tracer to hide all those stack items, for which no line number information
is available. The end result most of the time is a dramatically shorter
stack trace. The second and third options will add relative (to the
beginning of the function) address/line information to the callstack.
 |
type
TStackItem = record
Addr : pointer;
relAddr : dword;
ModuleName : string;
UnitName : string;
Line : integer;
relLine : integer;
FunctionName : string;
end;
TStackTrace = array of TStackItem;
TPStackTrace = ^TStackTrace;
function StackTrace (hideUglyItems : boolean = false;
showRelativeAddrs : boolean = false;
showRelativeLines : boolean = false;
stackTrace : TPStackTrace = nil;
currentAddr : pointer = nil;
isException : boolean = false;
extException : boolean = false;
stackBottom : dword = 0;
stackTop : dword = 0;
creator : pointer = nil;
exceptAddr : TPPointer = nil;
exceptFunc : TPPointer = nil;
exceptFuncAddr : TPPointer = nil;
progressAlert : IProgressAlert = nil;
ebp : dword = 0;
dumbTrace : boolean = false;
bcbTermination : boolean = false;
preparedStack : pointer = nil;
pAbort : TPBoolean = nil;
pCrc1 : TPCardinal = nil;
pCrc2 : TPCardinal = nil;
pDelphiThread : TPBoolean = nil;
pMinDebugInfos : TPDAString = nil;
dontAddTopItem : boolean = false) : string;
0036d58c +004 crashDll.dll CrashDll 9 +0 CrashDllProc
00491d40 +000 CrashApp.exe CrashUnit 30 +0 CrashProc
00491d48 +000 CrashApp.exe CrashUnit 35 +0 TCrashForm.CrashButtonClick
004727c0 +064 CrashApp.exe Controls TControl.Click
0046b048 +01c CrashApp.exe StdCtrls TButton.Click
0046b13c +00c CrashApp.exe StdCtrls TButton.CNCommand
00472628 +188 CrashApp.exe Controls TControl.WndProc
00475533 +157 CrashApp.exe Controls TWinControl.WndProc
0046af0c +06c CrashApp.exe StdCtrls TButtonControl.WndProc
004723f8 +024 CrashApp.exe Controls TControl.Perform
0047566b +023 CrashApp.exe Controls DoControlMsg
00475cc3 +00b CrashApp.exe Controls TWinControl.WMCommand
0048c16c +02c CrashApp.exe Forms TCustomForm.WMCommand
00472628 +188 CrashApp.exe Controls TControl.WndProc
00475533 +157 CrashApp.exe Controls TWinControl.WndProc
0048a1c5 +421 CrashApp.exe Forms TCustomForm.WndProc
004751b0 +02c CrashApp.exe Controls TWinControl.MainWndProc
0045e564 +014 CrashApp.exe Classes StdWndProc
77d1b8fe +044 user32.dll SendMessageW
77d1e900 +016 user32.dll CallWindowProcA
00475617 +0d7 CrashApp.exe Controls TWinControl.DefaultHandler
00476985 +019 CrashApp.exe Controls TWinControl.WMKeyUp
00472628 +188 CrashApp.exe Controls TControl.WndProc
00475533 +157 CrashApp.exe Controls TWinControl.WndProc
0046af0c +06c CrashApp.exe StdCtrls TButtonControl.WndProc
004751b0 +02c CrashApp.exe Controls TWinControl.MainWndProc
0045e564 +014 CrashApp.exe Classes StdWndProc
77d196c2 +00a user32.dll DispatchMessageA
004904db +083 CrashApp.exe Forms TApplication.ProcessMessage
004904fa +00a CrashApp.exe Forms TApplication.HandleMessage
0049071a +096 CrashApp.exe Forms TApplication.Run
0049203b +03b CrashApp.exe CrashApp 14 +3 initialization
|
|