how to get stack addresses in libbacktrace API or get symbolicated backtrace from stack addresses
timotheecour opened this issue · comments
-
how to get stack addresses in libbacktrace API? eg same addresses as generated by
backtrace
(https://linux.die.net/man/3/backtrace) -
example use case: see timotheecour/Nim#49 (comment) but there could be more
The libbacktrace library doesn't return stack addresses. I suppose I could add a new function for that, but it's not clear how useful it would be. You might want to look into using libunwind instead, or using _Unwind_Backtrace
with _Unwind_GetCFA
.
You might want to look into using libunwind instead, or using _Unwind_Backtrace with _Unwind_GetCFA.
Well I don't want to lose the other functionality of libbacktrace; seems like getting addresses is a reasonable thing to do since it's also exposed by other tools (eg backtrace
or those).
Actually I have a related question: is there a way to get symbolication using libbacktrace given input stack addresses?
Use case: deferred symbolication, so I can get an array of stack addresses (eg via backtrace
) and then at a subsequent time, symbolicate them using some libbacktrace API?
If so then this feature wouldn't be needed as I would have the 1 to 1 mapping between input stack addresses and what libbacktrace returns for each address as output.
I don't know what it mean to symbolize a stack address. I guess you mean something like "do a stack backtrace until you find the stack frame with that address, and report associated file/line/function information." I don't think that is a feature suitable for libbacktrace. I think that very very few people would use it.
I don't know what it mean to symbolize a stack address
I think symbolize
is a standard term for what I'm describing (eg see https://stackoverflow.com/questions/52695965/how-to-symbolize-stack-traces-of-a-stripped-shared-library)
I guess you mean something like [...]
I think that very very few people would use it.
That's not what I mean. The standard way to symbolize is in 2 steps:
- get stack addresses:
int backtrace(void **buffer, int size);
- symbolize each stack address:
char **backtrace_symbols(void *const *buffer, int size);
This is essentially what's done in D's exception handling (eg see https://github.com/dlang/druntime/blob/master/src/rt/backtrace/dwarf.d)
Doing it in 2 steps is a requirement for implementing exception handling efficiently (among other applications), this allows to symbolize stack addresses only when needed, eg:
try:
fun() # may throw
except Exception as e:
if isDebug: printStackTrace(e)
# maybe re-raise, or handle
in this code we don't want to automatically symbolicate when exception is thrown, because that's expensive and subsequent code may not need it (in this snippet, depending on isDebug
)
So what I mean is: I'd like to use libbacktrace in a deferred mode, replacing backtrace_symbols
above (which has accuracy issues, besides lack of C++ demangling) with some libbacktrace API. This would be needed to implement efficient handling in nim, see status-im/nim-libbacktrace#4
I think that very very few people would use it.
here are use cases for the feature of deferred symbolication:
- exception handling (symbolication in same process at a later time)
- out-of-process symbolication (exactly this: https://stackoverflow.com/questions/52695965/how-to-symbolize-stack-traces-of-a-stripped-shared-library; allows for eg shipping stripped binaries to customers, and doing symbolication in a remote server given input stack addresses from customer logs); or for efficiency purposes instead of obfuscation purposes, when running stripped binaries on a server
- profiling, where we generate stack addresses at sample time intervals, then gather/deduplicate/symbolicate them at the end to produce a human readable profiling report
Maybe we are using different meanings for these terms. As I use the term "stack address", the backtrace
function does not return a stack address. The backtrace
function returns a list of program counter values. These are the same values that libbacktrace returns as the pc
argument passed to the callback routine, either by backtrace_full
or backtrace_simple
. So maybe you are looking for backtrace_simple
followed by a later call to backtrace_pcinfo
.
@timotheecour, I can confirm that it's possible to do what you want by first collecting program counter addresses with backtrace_simple()
and, in a separate step, get debugging info for each of those using backtrace_pcinfo()
.
A small complication is that you may get more than one debugging info set for a given program counter, due to inlined functions and debugging formats like DWARF that have that info, but that's a good thing because it makes your backtrace more useful.
I implemented this two-step scheme here: status-im/nim-libbacktrace@3ff163c
Thanks, I'm still not completely sure what this issue is about, but it sounds like there is a way to do it. So closing this issue. Please comment if you disagree.