From da3361ec233ced99714dd1cd772b953e26f361e9 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Wed, 25 Aug 2004 04:08:43 +0000 Subject: [PATCH] fix exception backtraces not always resolving --- .../src/archutils/Unix/BacktraceNames.cpp | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/stepmania/src/archutils/Unix/BacktraceNames.cpp b/stepmania/src/archutils/Unix/BacktraceNames.cpp index 79b1a09686..de60674786 100644 --- a/stepmania/src/archutils/Unix/BacktraceNames.cpp +++ b/stepmania/src/archutils/Unix/BacktraceNames.cpp @@ -99,9 +99,31 @@ void BacktraceNames::FromAddr( const void *p ) { Address = (int) p; + /* + * When calling a function that doesn't return, gcc will truncate a function. + * This results in our return addresses lying just beyond the end of a function. + * Those addresses are correct; our backtrace addresses are usually a list of + * return addresses (that's the same thing you'll see in gdb). dladdr won't work, + * because they're not actually within the bounds of the function. + * + * A generic fix for this would be to adjust the backtrace to be a list of + * places where control was lost, instead of where it'll come back to; to point + * to the CALL instead of just beyond the CALL. That's hard to do generically; + * the stack only contains the return pointers. (Some archs don't even contain + * that: on archs where gcc has to manually store the return address--by pushing + * the IP--it will omit the push when calling a function that never returns.) + * + * Let's try the address we're given, and if that fails to find a symbol, try + * moving up a few bytes. This usually makes "__cxa_throw, std::terminate, + * gsignal" stacks come out right. It probably won't work if there's no space + * between one function and the next, because the first lookup will succeed. + */ Dl_info di; - if( !dladdr(p, &di) ) - return; + if( !dladdr(p, &di) || di.dli_sname == NULL ) + { + if( !dladdr( ((char *) p) - 8, &di) ) + return; + } Symbol = di.dli_sname; File = di.dli_fname;