Stack Trace
Tango offers a built-in ability to get stacktraces and visualize them.
This is performed in the tango.core.stacktrace.* modules.
Support is still in evolution, in general you need to at least compile with debug info (-g) to have the function names. See the platform dependent hints for more info.
Traced Exception
Stack traces can be useful to know where the exception originated and its context. You can activate stack tracing simply with
import tango.core.stacktrace.TraceExceptions;
Then if you print the exception with something like this
e.writeOut((char[] s) { Stdout(s); }); Stdout.flush();
you will see the stacktrace.
Function name
To find the name of a function pointer you can use one of
char[] nameOfFunctionAt(void* addr, char[] buf); char[] nameOfFunctionAt(void * addr);
for delegates you can extract the address with .funcptr
Demangling
tango.core.stacktrace.Demangler has a demangler that can be used to demangle D names.
demangler.demangle(myMangledString);
one can even allocate new demangler with different verbosity levels, or modify the verbosity of the default demangler
System Dependent Hints
Windows
You need to compile without optimizations and with -g to get the stack traces. A dbginfo.dll is needed, but that should be part of windows
Macintosh
Stacktracing works also without -g, but the names are then missing and one should recover them later.
The symbol names are returned, but line numbers are missing.
Tracing might have problems with nested functions (that lead to nested stackframes that interrupt the stacktracing procedure).
Linux
Stacktracing works also without -g, but symbol names are not resolved.
Tracing might have problems with nested functions (that lead to nested stackframes that interrupt the stacktracing procedure).
The function names and addresses can be recovered with the addr2line utility. At the moment there is no easy to use D program to parse a stacktrace, call addr2line and return demangled function names and file/number, a contribution would be appreciated.
Improving stacktracing
The main functions used to get a stack trace are
/// builds a backtrace of addresses, the addresses are addresses of the *next* instruction, /// *return* addresses, the most likely the calling instruction is the one before them /// (stack top excluded) extern(C) size_t rt_addrBacktrace(TraceContext* context, TraceContext *contextOut, size_t*traceBuf,size_t bufLength,int *flags);
and
/// tries to sybolize a frame information, this should try to build the best /// backtrace information, if possible finding the calling context, thus /// if fInfo.exactAddress is false the address might be changed to the one preceding it /// returns true if it managed to at least find the function name extern(C) bool rt_symbolizeFrameInfo(ref Exception.FrameInfo fInfo, TraceContext* context,char[]buf);
both functions can be changed with
extern(C) void rt_setAddrBacktraceFnc(AddrBacktraceFunc f);
and
extern(C) void rt_setSymbolizeFrameInfoFnc(SymbolizeFrameInfoFnc f);
Finally the printing format of a frame function can be changed setting Exception.FrameInfo.defaultFramePrintingFunction.
Improvements are welcome.