From bf7402e8b0e74069f18310a26e7a3166fa90db96 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Thu, 21 Jun 2018 17:07:21 +0200 Subject: [PATCH] Android callstack collection using _Unwind_Backtrace(). --- client/TracyCallstack.cpp | 79 +++++++++++++++++++++++++++++++++++++++ client/TracyCallstack.hpp | 38 +++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/client/TracyCallstack.cpp b/client/TracyCallstack.cpp index e10d9762..5a8d433e 100644 --- a/client/TracyCallstack.cpp +++ b/client/TracyCallstack.cpp @@ -69,6 +69,85 @@ CallstackEntry DecodeCallstackPtr( uint64_t ptr ) return ret; } +#elif defined __ANDROID__ + +CallstackEntry DecodeCallstackPtr( uint64_t ptr ) +{ + CallstackEntry ret; + ret.line = 0; + + char* demangled = nullptr; + const char* symname = nullptr; + const char* symloc = nullptr; + auto vptr = (void*)ptr; + char** sym = nullptr; + ptrdiff_t symoff = 0; + + Dl_info dlinfo; + if( dladdr( vptr, &dlinfo ) ) + { + symloc = dlinfo.dli_fname; + symname = dlinfo.dli_sname; + symoff = (char*)ptr - (char*)dlinfo.dli_saddr; + + if( symname && symname[0] == '_' ) + { + size_t len = 0; + int status; + demangled = abi::__cxa_demangle( symname, nullptr, &len, &status ); + if( status == 0 ) + { + symname = demangled; + } + } + } + + if( !symname ) + { + symname = "[unknown]"; + } + if( !symloc ) + { + symloc = "[unknown]"; + } + + if( symoff == 0 ) + { + const auto namelen = strlen( symname ); + auto name = (char*)tracy_malloc( namelen + 1 ); + memcpy( name, symname, namelen ); + name[namelen] = '\0'; + ret.name = name; + } + else + { + char buf[32]; + sprintf( buf, " + %td", symoff ); + const auto offlen = strlen( buf ); + const auto namelen = strlen( symname ); + auto name = (char*)tracy_malloc( namelen + offlen + 1 ); + memcpy( name, symname, namelen ); + memcpy( name + namelen, buf, offlen ); + name[namelen + offlen] = '\0'; + ret.name = name; + } + + char buf[32]; + sprintf( buf, " [%p]", (void*)ptr ); + const auto addrlen = strlen( buf ); + const auto loclen = strlen( symloc ); + auto loc = (char*)tracy_malloc( loclen + addrlen + 1 ); + memcpy( loc, symloc, loclen ); + memcpy( loc + loclen, buf, addrlen ); + loc[loclen + addrlen] = '\0'; + ret.file = loc; + + if( sym ) free( sym ); + if( demangled ) free( demangled ); + + return ret; +} + #elif defined _GNU_SOURCE CallstackEntry DecodeCallstackPtr( uint64_t ptr ) diff --git a/client/TracyCallstack.hpp b/client/TracyCallstack.hpp index 90fc1104..5d2482df 100644 --- a/client/TracyCallstack.hpp +++ b/client/TracyCallstack.hpp @@ -10,6 +10,9 @@ extern "C" __declspec(dllimport) unsigned short __stdcall RtlCaptureStackBackTra extern "C" __declspec(dllimport) unsigned short __stdcall RtlCaptureStackBackTrace( unsigned long, unsigned long, void**, unsigned long* ); # endif # endif +#elif defined __ANDROID__ +# define TRACY_HAS_CALLSTACK +# include #elif defined _GNU_SOURCE # define TRACY_HAS_CALLSTACK # include @@ -52,6 +55,41 @@ static tracy_force_inline void* Callstack( int depth ) return trace; } +#elif defined __ANDROID__ + +static tracy_force_inline void InitCallstack() {} + +struct BacktraceState +{ + void** current; + void** end; +}; + +static _Unwind_Reason_Code tracy_unwind_callback( struct _Unwind_Context* ctx, void* arg ) +{ + auto state = (BacktraceState*)arg; + uintptr_t pc = _Unwind_GetIP( ctx ); + if( pc ) + { + if( state->current == state->end ) return _URC_END_OF_STACK; + *state->current++ = (void*)pc; + } + return _URC_NO_REASON; +} + +static tracy_force_inline void* Callstack( int depth ) +{ + assert( depth >= 1 && depth < 63 ); + + auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) ); + BacktraceState state = { (void**)(trace+1), (void**)(trace+1+depth) }; + _Unwind_Backtrace( tracy_unwind_callback, &state ); + + *trace = (uintptr_t*)state.current - trace + 1; + + return trace; +} + #elif defined _GNU_SOURCE static tracy_force_inline void InitCallstack() {}