mudgangster

Tiny, scriptable MUD client
Log | Files | Refs | README

TracyCallstack.hpp (2452B)


      1 #ifndef __TRACYCALLSTACK_HPP__
      2 #define __TRACYCALLSTACK_HPP__
      3 
      4 #include "TracyCallstack.h"
      5 
      6 #if TRACY_HAS_CALLSTACK == 1
      7 extern "C"
      8 {
      9     typedef unsigned long (__stdcall *t_RtlWalkFrameChain)( void**, unsigned long, unsigned long );
     10     extern t_RtlWalkFrameChain RtlWalkFrameChain;
     11 }
     12 #elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5
     13 #  include <unwind.h>
     14 #elif TRACY_HAS_CALLSTACK >= 3
     15 #  include <execinfo.h>
     16 #endif
     17 
     18 
     19 #ifdef TRACY_HAS_CALLSTACK
     20 
     21 #include <assert.h>
     22 #include <stdint.h>
     23 
     24 #include "../common/TracyAlloc.hpp"
     25 #include "../common/TracyForceInline.hpp"
     26 
     27 namespace tracy
     28 {
     29 
     30 struct CallstackEntry
     31 {
     32     const char* name;
     33     const char* file;
     34     uint32_t line;
     35 };
     36 
     37 struct CallstackEntryData
     38 {
     39     const CallstackEntry* data;
     40     uint8_t size;
     41 };
     42 
     43 const char* DecodeCallstackPtrFast( uint64_t ptr );
     44 CallstackEntryData DecodeCallstackPtr( uint64_t ptr );
     45 void InitCallstack();
     46 
     47 #if TRACY_HAS_CALLSTACK == 1
     48 
     49 static tracy_force_inline void* Callstack( int depth )
     50 {
     51     assert( depth >= 1 && depth < 63 );
     52 
     53     auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
     54     const auto num = RtlWalkFrameChain( (void**)( trace + 1 ), depth, 0 );
     55     *trace = num;
     56 
     57     return trace;
     58 }
     59 
     60 #elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5
     61 
     62 struct BacktraceState
     63 {
     64     void** current;
     65     void** end;
     66 };
     67 
     68 static _Unwind_Reason_Code tracy_unwind_callback( struct _Unwind_Context* ctx, void* arg )
     69 {
     70     auto state = (BacktraceState*)arg;
     71     uintptr_t pc = _Unwind_GetIP( ctx );
     72     if( pc )
     73     {
     74         if( state->current == state->end ) return _URC_END_OF_STACK;
     75         *state->current++ = (void*)pc;
     76     }
     77     return _URC_NO_REASON;
     78 }
     79 
     80 static tracy_force_inline void* Callstack( int depth )
     81 {
     82     assert( depth >= 1 && depth < 63 );
     83 
     84     auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
     85     BacktraceState state = { (void**)(trace+1), (void**)(trace+1+depth) };
     86     _Unwind_Backtrace( tracy_unwind_callback, &state );
     87 
     88     *trace = (uintptr_t*)state.current - trace + 1;
     89 
     90     return trace;
     91 }
     92 
     93 #elif TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6
     94 
     95 static tracy_force_inline void* Callstack( int depth )
     96 {
     97     assert( depth >= 1 );
     98 
     99     auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
    100     const auto num = backtrace( (void**)(trace+1), depth );
    101     *trace = num;
    102 
    103     return trace;
    104 }
    105 
    106 #endif
    107 
    108 }
    109 
    110 #endif
    111 
    112 #endif