Fix demangling of functions with names >64KB.

This commit is contained in:
Bartosz Taudul 2022-07-20 01:21:43 +02:00
parent f52ac31468
commit 7dc95bf3a8
No known key found for this signature in database
GPG Key ID: B7FE2008B7575DF3

View File

@ -1,3 +1,4 @@
#include <limits>
#include <new> #include <new>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -53,15 +54,26 @@ extern "C"
#endif #endif
#if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 5 || TRACY_HAS_CALLSTACK == 6 #if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 5 || TRACY_HAS_CALLSTACK == 6
extern "C" int ___tracy_demangle( const char* mangled, char* out, size_t len ); // If you want to use your own demangling functionality (e.g. for another language),
// define TRACY_DEMANGLE and provide your own implementation of the __tracy_demangle
// function. The input parameter is a function name. The demangle function must
// identify whether this name is mangled, and fail if it is not. Failure is indicated
// by returning nullptr. If demangling succeeds, a pointer to the C string containing
// demangled function must be returned. The demangling function is responsible for
// managing memory for this string. It is expected that it will be internally reused.
// When a call to ___tracy_demangle is made, previous contents of the string memory
// do not need to be preserved. Function may return string of any length, but the
// profiler can choose to truncate it.
extern "C" const char* ___tracy_demangle( const char* mangled );
#ifndef TRACY_DEMANGLE #ifndef TRACY_DEMANGLE
extern "C" int ___tracy_demangle( const char* mangled, char* out, size_t len ) extern "C" const char* ___tracy_demangle( const char* mangled )
{ {
if( !mangled || mangled[0] != '_' ) return 0; static size_t tmp_len = 64*1024;
static char* tmp_ptr = (char*)malloc( tmp_len );
if( !mangled || mangled[0] != '_' ) return nullptr;
int status; int status;
abi::__cxa_demangle( mangled, out, &len, &status ); return abi::__cxa_demangle( mangled, tmp_ptr, &tmp_len, &status );
return status == 0;
} }
#endif #endif
#endif #endif
@ -862,9 +874,6 @@ CallstackSymbolData DecodeCodeAddress( uint64_t ptr )
static int CallstackDataCb( void* /*data*/, uintptr_t pc, uintptr_t lowaddr, const char* fn, int lineno, const char* function ) static int CallstackDataCb( void* /*data*/, uintptr_t pc, uintptr_t lowaddr, const char* fn, int lineno, const char* function )
{ {
enum { DemangleBufLen = 64*1024 };
char demangled[DemangleBufLen];
cb_data[cb_num].symLen = 0; cb_data[cb_num].symLen = 0;
cb_data[cb_num].symAddr = (uint64_t)lowaddr; cb_data[cb_num].symAddr = (uint64_t)lowaddr;
@ -879,20 +888,22 @@ static int CallstackDataCb( void* /*data*/, uintptr_t pc, uintptr_t lowaddr, con
{ {
symname = dlinfo.dli_sname; symname = dlinfo.dli_sname;
symoff = (char*)pc - (char*)dlinfo.dli_saddr; symoff = (char*)pc - (char*)dlinfo.dli_saddr;
if( ___tracy_demangle( symname, demangled, DemangleBufLen ) ) symname = demangled; const char* demangled = ___tracy_demangle( symname );
if( demangled ) symname = demangled;
} }
if( !symname ) symname = "[unknown]"; if( !symname ) symname = "[unknown]";
if( symoff == 0 ) if( symoff == 0 )
{ {
cb_data[cb_num].name = CopyStringFast( symname ); const auto len = std::min<size_t>( strlen( symname ), std::numeric_limits<uint16_t>::max() );
cb_data[cb_num].name = CopyStringFast( symname, len );
} }
else else
{ {
char buf[32]; char buf[32];
const auto offlen = sprintf( buf, " + %td", symoff ); const auto offlen = sprintf( buf, " + %td", symoff );
const auto namelen = strlen( symname ); const auto namelen = std::min<size_t>( strlen( symname ), std::numeric_limits<uint16_t>::max() - offlen );
auto name = (char*)tracy_malloc_fast( namelen + offlen + 1 ); auto name = (char*)tracy_malloc_fast( namelen + offlen + 1 );
memcpy( name, symname, namelen ); memcpy( name, symname, namelen );
memcpy( name + namelen, buf, offlen ); memcpy( name + namelen, buf, offlen );
@ -910,12 +921,14 @@ static int CallstackDataCb( void* /*data*/, uintptr_t pc, uintptr_t lowaddr, con
{ {
function = "[unknown]"; function = "[unknown]";
} }
else if( ___tracy_demangle( function, demangled, DemangleBufLen ) ) else
{ {
function = demangled; const char* demangled = ___tracy_demangle( function );
if( demangled ) function = demangled;
} }
cb_data[cb_num].name = CopyStringFast( function ); const auto len = std::min<size_t>( strlen( function ), std::numeric_limits<uint16_t>::max() );
cb_data[cb_num].name = CopyStringFast( function, len );
cb_data[cb_num].file = CopyStringFast( fn ); cb_data[cb_num].file = CopyStringFast( fn );
cb_data[cb_num].line = lineno; cb_data[cb_num].line = lineno;
} }
@ -1048,9 +1061,6 @@ CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
static CallstackEntry cb; static CallstackEntry cb;
cb.line = 0; cb.line = 0;
enum { DemangleBufLen = 64*1024 };
char demangled[DemangleBufLen];
const char* symname = nullptr; const char* symname = nullptr;
const char* symloc = nullptr; const char* symloc = nullptr;
auto vptr = (void*)ptr; auto vptr = (void*)ptr;
@ -1064,7 +1074,8 @@ CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
symname = dlinfo.dli_sname; symname = dlinfo.dli_sname;
symoff = (char*)ptr - (char*)dlinfo.dli_saddr; symoff = (char*)ptr - (char*)dlinfo.dli_saddr;
symaddr = dlinfo.dli_saddr; symaddr = dlinfo.dli_saddr;
if( ___tracy_demangle( symname, demangled, DemangleBufLen ) ) symname = demangled; const char* demangled = ___tracy_demangle( symname );
if( demangled ) symname = demangled;
} }
if( !symname ) symname = "[unknown]"; if( !symname ) symname = "[unknown]";
@ -1072,13 +1083,14 @@ CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
if( symoff == 0 ) if( symoff == 0 )
{ {
cb.name = CopyString( symname ); const auto len = std::min<size_t>( strlen( symname ), std::numeric_limits<uint16_t>::max() );
cb.name = CopyString( symname, len );
} }
else else
{ {
char buf[32]; char buf[32];
const auto offlen = sprintf( buf, " + %td", symoff ); const auto offlen = sprintf( buf, " + %td", symoff );
const auto namelen = strlen( symname ); const auto namelen = std::min<size_t>( strlen( symname ), std::numeric_limits<uint16_t>::max() - offlen );
auto name = (char*)tracy_malloc( namelen + offlen + 1 ); auto name = (char*)tracy_malloc( namelen + offlen + 1 );
memcpy( name, symname, namelen ); memcpy( name, symname, namelen );
memcpy( name + namelen, buf, offlen ); memcpy( name + namelen, buf, offlen );