Android callstack collection using _Unwind_Backtrace().

This commit is contained in:
Bartosz Taudul 2018-06-21 17:07:21 +02:00
parent 0c13fb818b
commit bf7402e8b0
2 changed files with 117 additions and 0 deletions

View File

@ -69,6 +69,85 @@ CallstackEntry DecodeCallstackPtr( uint64_t ptr )
return ret; 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 #elif defined _GNU_SOURCE
CallstackEntry DecodeCallstackPtr( uint64_t ptr ) CallstackEntry DecodeCallstackPtr( uint64_t ptr )

View File

@ -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* ); extern "C" __declspec(dllimport) unsigned short __stdcall RtlCaptureStackBackTrace( unsigned long, unsigned long, void**, unsigned long* );
# endif # endif
# endif # endif
#elif defined __ANDROID__
# define TRACY_HAS_CALLSTACK
# include <unwind.h>
#elif defined _GNU_SOURCE #elif defined _GNU_SOURCE
# define TRACY_HAS_CALLSTACK # define TRACY_HAS_CALLSTACK
# include <execinfo.h> # include <execinfo.h>
@ -52,6 +55,41 @@ static tracy_force_inline void* Callstack( int depth )
return trace; 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 #elif defined _GNU_SOURCE
static tracy_force_inline void InitCallstack() {} static tracy_force_inline void InitCallstack() {}