tracy/client/TracyCallstack.hpp

115 lines
2.5 KiB
C++
Raw Normal View History

2018-06-18 23:17:19 +00:00
#ifndef __TRACYCALLSTACK_HPP__
#define __TRACYCALLSTACK_HPP__
2018-06-19 17:49:21 +00:00
#if defined _WIN32 || defined __CYGWIN__
2018-06-18 23:17:19 +00:00
# define TRACY_HAS_CALLSTACK
# ifndef MAXLONG
2018-06-19 17:49:21 +00:00
# ifdef __CYGWIN__
extern "C" __declspec(dllimport) unsigned short __stdcall RtlCaptureStackBackTrace( unsigned int, unsigned int, void**, unsigned int* );
# else
2018-06-18 23:17:19 +00:00
extern "C" __declspec(dllimport) unsigned short __stdcall RtlCaptureStackBackTrace( unsigned long, unsigned long, void**, unsigned long* );
2018-06-19 17:49:21 +00:00
# endif
2018-06-18 23:17:19 +00:00
# endif
#elif defined __ANDROID__
# define TRACY_HAS_CALLSTACK
# include <unwind.h>
2018-06-20 19:45:27 +00:00
#elif defined _GNU_SOURCE
# define TRACY_HAS_CALLSTACK
# include <execinfo.h>
2018-06-18 23:17:19 +00:00
#endif
2018-06-20 19:45:27 +00:00
2018-06-18 23:17:19 +00:00
#ifdef TRACY_HAS_CALLSTACK
2018-06-19 16:49:13 +00:00
#include <assert.h>
2018-06-18 23:17:19 +00:00
#include <stdint.h>
#include <string.h>
#include "../common/TracyAlloc.hpp"
#include "../common/TracyForceInline.hpp"
namespace tracy
{
struct CallstackEntry
{
const char* name;
const char* file;
uint32_t line;
};
2018-06-20 19:45:27 +00:00
CallstackEntry DecodeCallstackPtr( uint64_t ptr );
2018-06-19 17:49:21 +00:00
#if defined _WIN32 || defined __CYGWIN__
2018-06-18 23:17:19 +00:00
void InitCallstack();
2018-06-19 16:49:13 +00:00
static tracy_force_inline void* Callstack( int depth )
2018-06-18 23:17:19 +00:00
{
2018-06-20 15:02:05 +00:00
assert( depth >= 1 && depth < 63 );
2018-06-18 23:17:19 +00:00
2018-06-19 16:49:13 +00:00
auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
const auto num = RtlCaptureStackBackTrace( 0, depth, (void**)( trace+1 ), nullptr );
2018-06-18 23:17:19 +00:00
*trace = num;
2018-06-19 15:27:03 +00:00
return trace;
2018-06-18 23:17:19 +00:00
}
#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;
}
2018-06-20 19:45:27 +00:00
#elif defined _GNU_SOURCE
static tracy_force_inline void InitCallstack() {}
static tracy_force_inline void* Callstack( int depth )
{
assert( depth >= 1 );
auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
const auto num = backtrace( (void**)(trace+1), depth );
*trace = num;
return trace;
}
2018-06-18 23:17:19 +00:00
#endif
}
#endif
#endif