From 2af64e88bbf6686edea321f780a45abbc0329560 Mon Sep 17 00:00:00 2001 From: cxl Date: Fri, 3 May 2013 16:40:37 +0000 Subject: [PATCH] Core: GCC Stack trace git-svn-id: svn://ultimatepp.org/upp/trunk@6028 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/Util.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/uppsrc/Core/Util.cpp b/uppsrc/Core/Util.cpp index f11884d16..12d9f25b3 100644 --- a/uppsrc/Core/Util.cpp +++ b/uppsrc/Core/Util.cpp @@ -4,6 +4,11 @@ # include #endif +#if defined(PLATFORM_POSIX) && defined(COMPILER_GCC) +# include +# include +#endif + NAMESPACE_UPP bool PanicMode; @@ -32,6 +37,53 @@ void PanicMessageBox(const char *title, const char *text) } } + +#if defined(PLATFORM_POSIX) && defined(COMPILER_GCC) +void AddStackTrace(char * str, int len) +{ + const size_t max_depth = 100; + void *stack_addrs[max_depth]; + char **stack_strings; + const char msg[] = "\nStack trace:\n"; + + size_t stack_depth = backtrace(stack_addrs, max_depth); + stack_strings = backtrace_symbols(stack_addrs, stack_depth); + + int space = len - strlen(str); + strncat(str, msg, max(space, 0)); + space -= sizeof(msg) - 1; + + for (size_t i = 0; i < stack_depth && space > 0; i++) { + + char * start = strchr(stack_strings[i], '('); + if (start == NULL) continue; + + size_t len; + int stat; + + char * end = strchr(start, '+'); + if (end != NULL) *end = '\0'; + + char * demangled = abi::__cxa_demangle(start+1, NULL, &len, &stat); + + if (stat == 0 && demangled != NULL){ + strncat(str, demangled, max(space, 0)); + space -= len; + }else{ + strncat(str, start, max(space, 0)); + space -= strlen(start); + } + if (demangled != NULL) free(demangled); + + strncat(str, "\n", max(space, 0)); + space -= 1; + } + + free(stack_strings); +} +#endif + + void Panic(const char *msg) { #ifdef PLATFORM_POSIX @@ -83,6 +135,10 @@ void AssertFailed(const char *file, int line, const char *cond) PanicMode = true; char s[2048]; sprintf(s, "Assertion failed in %s, line %d\n%s\n", file, line, cond); +#if defined(PLATFORM_POSIX) && defined(COMPILER_GCC) + AddStackTrace(s, sizeof(s)); +#endif + if(s_assert_hook) (*s_assert_hook)(s); RLOG("****************** ASSERT FAILED: " << s << "\n");