The open source OpenXR runtime
at main 142 lines 3.2 kB view raw
1#ifndef __TRACYCALLSTACK_HPP__ 2#define __TRACYCALLSTACK_HPP__ 3 4#include "../common/TracyApi.h" 5#include "../common/TracyForceInline.hpp" 6#include "TracyCallstack.h" 7 8#if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5 9# include <unwind.h> 10#elif TRACY_HAS_CALLSTACK >= 3 11# include <execinfo.h> 12#endif 13 14 15#ifndef TRACY_HAS_CALLSTACK 16 17namespace tracy 18{ 19static tracy_force_inline void* Callstack( int depth ) { return nullptr; } 20} 21 22#else 23 24#ifdef TRACY_DEBUGINFOD 25# include <elfutils/debuginfod.h> 26#endif 27 28#include <assert.h> 29#include <stdint.h> 30 31#include "../common/TracyAlloc.hpp" 32 33namespace tracy 34{ 35 36struct CallstackSymbolData 37{ 38 const char* file; 39 uint32_t line; 40 bool needFree; 41 uint64_t symAddr; 42}; 43 44struct CallstackEntry 45{ 46 const char* name; 47 const char* file; 48 uint32_t line; 49 uint32_t symLen; 50 uint64_t symAddr; 51}; 52 53struct CallstackEntryData 54{ 55 const CallstackEntry* data; 56 uint8_t size; 57 const char* imageName; 58}; 59 60CallstackSymbolData DecodeSymbolAddress( uint64_t ptr ); 61const char* DecodeCallstackPtrFast( uint64_t ptr ); 62CallstackEntryData DecodeCallstackPtr( uint64_t ptr ); 63void InitCallstack(); 64void InitCallstackCritical(); 65void EndCallstack(); 66const char* GetKernelModulePath( uint64_t addr ); 67 68#ifdef TRACY_DEBUGINFOD 69const uint8_t* GetBuildIdForImage( const char* image, size_t& size ); 70debuginfod_client* GetDebuginfodClient(); 71#endif 72 73#if TRACY_HAS_CALLSTACK == 1 74 75extern "C" 76{ 77 typedef unsigned long (__stdcall *___tracy_t_RtlWalkFrameChain)( void**, unsigned long, unsigned long ); 78 TRACY_API extern ___tracy_t_RtlWalkFrameChain ___tracy_RtlWalkFrameChain; 79} 80 81static tracy_force_inline void* Callstack( int depth ) 82{ 83 assert( depth >= 1 && depth < 63 ); 84 auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) ); 85 const auto num = ___tracy_RtlWalkFrameChain( (void**)( trace + 1 ), depth, 0 ); 86 *trace = num; 87 return trace; 88} 89 90#elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5 91 92struct BacktraceState 93{ 94 void** current; 95 void** end; 96}; 97 98static _Unwind_Reason_Code tracy_unwind_callback( struct _Unwind_Context* ctx, void* arg ) 99{ 100 auto state = (BacktraceState*)arg; 101 uintptr_t pc = _Unwind_GetIP( ctx ); 102 if( pc ) 103 { 104 if( state->current == state->end ) return _URC_END_OF_STACK; 105 *state->current++ = (void*)pc; 106 } 107 return _URC_NO_REASON; 108} 109 110static tracy_force_inline void* Callstack( int depth ) 111{ 112 assert( depth >= 1 && depth < 63 ); 113 114 auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) ); 115 BacktraceState state = { (void**)(trace+1), (void**)(trace+1+depth) }; 116 _Unwind_Backtrace( tracy_unwind_callback, &state ); 117 118 *trace = (uintptr_t*)state.current - trace + 1; 119 120 return trace; 121} 122 123#elif TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6 124 125static tracy_force_inline void* Callstack( int depth ) 126{ 127 assert( depth >= 1 ); 128 129 auto trace = (uintptr_t*)tracy_malloc( ( 1 + (size_t)depth ) * sizeof( uintptr_t ) ); 130 const auto num = (size_t)backtrace( (void**)(trace+1), depth ); 131 *trace = num; 132 133 return trace; 134} 135 136#endif 137 138} 139 140#endif 141 142#endif