diff --git a/TracyClient.cpp b/TracyClient.cpp index afe6f9d8..17b14ccd 100644 --- a/TracyClient.cpp +++ b/TracyClient.cpp @@ -14,12 +14,14 @@ #ifdef TRACY_ENABLE #include "client/TracyProfiler.cpp" +#include "client/TracyCallstack.cpp" #include "common/tracy_lz4.cpp" #include "common/TracySocket.cpp" #include "client/tracy_rpmalloc.cpp" #ifdef _MSC_VER # pragma comment(lib, "ws2_32.lib") +# pragma comment(lib, "dbghelp.lib") #endif #endif diff --git a/client/TracyCallstack.cpp b/client/TracyCallstack.cpp new file mode 100644 index 00000000..b3ad73f6 --- /dev/null +++ b/client/TracyCallstack.cpp @@ -0,0 +1,85 @@ +#include "TracyCallstack.hpp" + +#ifdef TRACY_HAS_CALLSTACK + +#ifdef _WIN32 +# ifndef MAXLONG +enum { SYMOPT_LOAD_LINES = 0x00000010 }; +typedef struct _SYMBOL_INFO +{ + unsigned long SizeOfStruct; + unsigned long TypeIndex; + unsigned long long Reserved[2]; + unsigned long Index; + unsigned long Size; + unsigned long long ModBase; + unsigned long Flags; + unsigned long long Value; + unsigned long long Address; + unsigned long Register; + unsigned long Scope; + unsigned long Tag; + unsigned long NameLen; + unsigned long MaxNameLen; + char Name[1]; +} SYMBOL_INFO; +typedef struct _IMAGEHLP_LINE64 +{ + unsigned long SizeOfStruct; + void* Key; + unsigned LineNumber; + char* FileName; + unsigned long long Address; +} IMAGEHLP_LINE64; +extern "C" __declspec(dllimport) void* __stdcall GetCurrentProcess(); +extern "C" __declspec(dllimport) int __stdcall SymInitialize( void*, const char*, int ); +extern "C" __declspec(dllimport) unsigned long __stdcall SymSetOptions( unsigned long ); +extern "C" __declspec(dllimport) int __stdcall SymFromAddr( void*, unsigned long long, unsigned long long*, SYMBOL_INFO* ); +extern "C" __declspec(dllimport) int __stdcall SymGetLineFromAddr64( void*, unsigned long long, unsigned long*, IMAGEHLP_LINE64* ); +# else +# include +# endif +#endif + +namespace tracy +{ + +void InitCallstack() +{ + SymInitialize( GetCurrentProcess(), nullptr, true ); + SymSetOptions( SYMOPT_LOAD_LINES ); +} + +CallstackEntry DecodeCallstackPtr( uint64_t ptr ) +{ + CallstackEntry ret; + + const auto proc = GetCurrentProcess(); + + char buf[sizeof( SYMBOL_INFO ) + 255]; + auto si = (SYMBOL_INFO*)buf; + si->SizeOfStruct = sizeof( SYMBOL_INFO ); + si->MaxNameLen = 255; + + SymFromAddr( proc, ptr, nullptr, si ); + + auto name = (char*)tracy_malloc( si->NameLen + 1 ); + memcpy( name, si->Name, si->NameLen ); + name[si->NameLen] = '\0'; + + ret.name = name; + + IMAGEHLP_LINE64 line; + unsigned long displacement = 0; + line.SizeOfStruct = sizeof( IMAGEHLP_LINE64 ); + SymGetLineFromAddr64( proc, ptr, &displacement, &line ); + + ret.file = line.FileName; + ret.line = line.LineNumber; + + return ret; +} + +} + +#endif diff --git a/client/TracyCallstack.hpp b/client/TracyCallstack.hpp new file mode 100644 index 00000000..5a53d7b7 --- /dev/null +++ b/client/TracyCallstack.hpp @@ -0,0 +1,52 @@ +#ifndef __TRACYCALLSTACK_HPP__ +#define __TRACYCALLSTACK_HPP__ + +#ifdef _WIN32 +# define TRACY_HAS_CALLSTACK +# ifndef MAXLONG +extern "C" __declspec(dllimport) unsigned short __stdcall RtlCaptureStackBackTrace( unsigned long, unsigned long, void**, unsigned long* ); +# endif +#endif + +#ifdef TRACY_HAS_CALLSTACK + +#include +#include + +#include "../common/TracyAlloc.hpp" +#include "../common/TracyForceInline.hpp" + +namespace tracy +{ + +struct CallstackEntry +{ + const char* name; + const char* file; + uint32_t line; +}; + +#ifdef _WIN32 + +void InitCallstack(); +CallstackEntry DecodeCallstackPtr( uint64_t ptr ); + +tracy_force_inline const char* Callstack() +{ + enum { StackDepth = 24 }; + static_assert( StackDepth <= 63, "Stack depth can't be greater than 63." ); + + auto trace = (uint64_t*)tracy_malloc( ( 1 + StackDepth ) * sizeof( uint64_t ) ); + const auto num = RtlCaptureStackBackTrace( 0, StackDepth, (void**)( trace+1 ), nullptr ); + *trace = num; + + return (const char*)trace; +} + +#endif + +} + +#endif + +#endif diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index b0398f07..3505cb20 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -25,6 +25,7 @@ #include "../common/TracySocket.hpp" #include "../common/TracySystem.hpp" #include "tracy_rpmalloc.hpp" +#include "TracyCallstack.hpp" #include "TracyScoped.hpp" #include "TracyProfiler.hpp" #include "TracyThread.hpp" @@ -214,6 +215,10 @@ Profiler::Profiler() new(s_thread) Thread( LaunchWorker, this ); SetThreadName( s_thread->Handle(), "Tracy Profiler" ); +#ifdef TRACY_HAS_CALLSTACK + InitCallstack(); +#endif + m_timeBegin.store( GetTime(), std::memory_order_relaxed ); }