externals: update tracy

This commit is contained in:
Gamer64 2024-11-14 17:50:02 +01:00
parent 8f138bd7f5
commit 17422ff2c7
23 changed files with 590 additions and 168 deletions

10
externals/tracy/README.md vendored Normal file
View File

@ -0,0 +1,10 @@
Mandarine uses [Tracy Profiler](https://github.com/wolfpld/tracy) as its profiling app, which requires an external program to interact with. It can be found on the Tracy Profiler [Releases](https://github.com/wolfpld/tracy/releases) page.
To update the Tracy Profiler dependency:
* Delete the `public` folder
* Navigate to the main Tracy Profiler project page:
[https://github.com/wolfpld/tracy](https://github.com/wolfpld/tracy)
* Copy the `public` folder from the Tracy Profiler page into this directory
**NOTE**: The code included here may be too new to be supported by the latest stable release of Tracy Profiler. If that is the case, until the project releases an updated stable binary, download a [build artifact](https://github.com/wolfpld/tracy/actions) instead.

View File

@ -30,6 +30,7 @@
#include "client/TracyDxt1.cpp" #include "client/TracyDxt1.cpp"
#include "client/TracyAlloc.cpp" #include "client/TracyAlloc.cpp"
#include "client/TracyOverride.cpp" #include "client/TracyOverride.cpp"
#include "client/TracyKCore.cpp"
#if defined(TRACY_HAS_CALLSTACK) #if defined(TRACY_HAS_CALLSTACK)
# if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6 # if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6

View File

@ -137,7 +137,8 @@ public:
private: private:
tracy::FastVector<ImageEntry> m_images; tracy::FastVector<ImageEntry> m_images;
bool m_updated; bool m_updated = false;
bool m_haveMainImageName = false;
static int Callback( struct dl_phdr_info* info, size_t size, void* data ) static int Callback( struct dl_phdr_info* info, size_t size, void* data )
{ {
@ -155,26 +156,13 @@ private:
image->m_startAddress = startAddress; image->m_startAddress = startAddress;
image->m_endAddress = endAddress; image->m_endAddress = endAddress;
const char* imageName = nullptr; // the base executable name isn't provided when iterating with dl_iterate_phdr,
// the base executable name isn't provided when iterating with dl_iterate_phdr, get it with dladdr() // we will have to patch the executable image name outside this callback
if( info->dlpi_name && info->dlpi_name[0] != '\0' ) if( info->dlpi_name && info->dlpi_name[0] != '\0' )
{ {
imageName = info->dlpi_name; size_t sz = strlen( info->dlpi_name ) + 1;
}
else
{
Dl_info dlInfo;
if( dladdr( (void *)info->dlpi_addr, &dlInfo ) )
{
imageName = dlInfo.dli_fname;
}
}
if( imageName )
{
size_t sz = strlen( imageName ) + 1;
image->m_name = (char*)tracy_malloc( sz ); image->m_name = (char*)tracy_malloc( sz );
memcpy( image->m_name, imageName, sz ); memcpy( image->m_name, info->dlpi_name, sz );
} }
else else
{ {
@ -200,9 +188,42 @@ private:
{ {
std::sort( m_images.begin(), m_images.end(), std::sort( m_images.begin(), m_images.end(),
[]( const ImageEntry& lhs, const ImageEntry& rhs ) { return lhs.m_startAddress > rhs.m_startAddress; } ); []( const ImageEntry& lhs, const ImageEntry& rhs ) { return lhs.m_startAddress > rhs.m_startAddress; } );
// patch the main executable image name here, as calling dl_* functions inside the dl_iterate_phdr callback might cause deadlocks
UpdateMainImageName();
} }
} }
void UpdateMainImageName()
{
if( m_haveMainImageName )
{
return;
}
for( ImageEntry& entry : m_images )
{
if( entry.m_name == nullptr )
{
Dl_info dlInfo;
if( dladdr( (void *)entry.m_startAddress, &dlInfo ) )
{
if( dlInfo.dli_fname )
{
size_t sz = strlen( dlInfo.dli_fname ) + 1;
entry.m_name = (char*)tracy_malloc( sz );
memcpy( entry.m_name, dlInfo.dli_fname, sz );
}
}
// we only expect one entry to be null for the main executable entry
break;
}
}
m_haveMainImageName = true;
}
const ImageEntry* GetImageForAddressImpl( void* address ) const const ImageEntry* GetImageForAddressImpl( void* address ) const
{ {
auto it = std::lower_bound( m_images.begin(), m_images.end(), address, auto it = std::lower_bound( m_images.begin(), m_images.end(), address,
@ -223,6 +244,7 @@ private:
} }
m_images.clear(); m_images.clear();
m_haveMainImageName = false;
} }
}; };
#endif //#ifdef TRACY_USE_IMAGE_CACHE #endif //#ifdef TRACY_USE_IMAGE_CACHE
@ -762,6 +784,7 @@ static FastVector<DebugInfo>* s_di_known;
struct KernelSymbol struct KernelSymbol
{ {
uint64_t addr; uint64_t addr;
uint32_t size;
const char* name; const char* name;
const char* mod; const char* mod;
}; };
@ -773,10 +796,11 @@ static void InitKernelSymbols()
{ {
FILE* f = fopen( "/proc/kallsyms", "rb" ); FILE* f = fopen( "/proc/kallsyms", "rb" );
if( !f ) return; if( !f ) return;
tracy::FastVector<KernelSymbol> tmpSym( 1024 ); tracy::FastVector<KernelSymbol> tmpSym( 512 * 1024 );
size_t linelen = 16 * 1024; // linelen must be big enough to prevent reallocs in getline() size_t linelen = 16 * 1024; // linelen must be big enough to prevent reallocs in getline()
auto linebuf = (char*)tracy_malloc( linelen ); auto linebuf = (char*)tracy_malloc( linelen );
ssize_t sz; ssize_t sz;
size_t validCnt = 0;
while( ( sz = getline( &linebuf, &linelen, f ) ) != -1 ) while( ( sz = getline( &linebuf, &linelen, f ) ) != -1 )
{ {
auto ptr = linebuf; auto ptr = linebuf;
@ -809,7 +833,7 @@ static void InitKernelSymbols()
} }
if( addr == 0 ) continue; if( addr == 0 ) continue;
ptr++; ptr++;
if( *ptr != 'T' && *ptr != 't' ) continue; const bool valid = *ptr == 'T' || *ptr == 't';
ptr += 2; ptr += 2;
const auto namestart = ptr; const auto namestart = ptr;
while( *ptr != '\t' && *ptr != '\n' ) ptr++; while( *ptr != '\t' && *ptr != '\n' ) ptr++;
@ -824,20 +848,28 @@ static void InitKernelSymbols()
modend = ptr; modend = ptr;
} }
auto strname = (char*)tracy_malloc_fast( nameend - namestart + 1 ); char* strname = nullptr;
char* strmod = nullptr;
if( valid )
{
validCnt++;
strname = (char*)tracy_malloc_fast( nameend - namestart + 1 );
memcpy( strname, namestart, nameend - namestart ); memcpy( strname, namestart, nameend - namestart );
strname[nameend-namestart] = '\0'; strname[nameend-namestart] = '\0';
char* strmod = nullptr;
if( modstart ) if( modstart )
{ {
strmod = (char*)tracy_malloc_fast( modend - modstart + 1 ); strmod = (char*)tracy_malloc_fast( modend - modstart + 1 );
memcpy( strmod, modstart, modend - modstart ); memcpy( strmod, modstart, modend - modstart );
strmod[modend-modstart] = '\0'; strmod[modend-modstart] = '\0';
} }
}
auto sym = tmpSym.push_next(); auto sym = tmpSym.push_next();
sym->addr = addr; sym->addr = addr;
sym->size = 0;
sym->name = strname; sym->name = strname;
sym->mod = strmod; sym->mod = strmod;
} }
@ -845,11 +877,22 @@ static void InitKernelSymbols()
fclose( f ); fclose( f );
if( tmpSym.empty() ) return; if( tmpSym.empty() ) return;
std::sort( tmpSym.begin(), tmpSym.end(), []( const KernelSymbol& lhs, const KernelSymbol& rhs ) { return lhs.addr > rhs.addr; } ); std::sort( tmpSym.begin(), tmpSym.end(), []( const KernelSymbol& lhs, const KernelSymbol& rhs ) { return lhs.addr < rhs.addr; } );
s_kernelSymCnt = tmpSym.size(); for( size_t i=0; i<tmpSym.size()-1; i++ )
s_kernelSym = (KernelSymbol*)tracy_malloc_fast( sizeof( KernelSymbol ) * s_kernelSymCnt ); {
memcpy( s_kernelSym, tmpSym.data(), sizeof( KernelSymbol ) * s_kernelSymCnt ); if( tmpSym[i].name ) tmpSym[i].size = tmpSym[i+1].addr - tmpSym[i].addr;
TracyDebug( "Loaded %zu kernel symbols\n", s_kernelSymCnt ); }
s_kernelSymCnt = validCnt;
s_kernelSym = (KernelSymbol*)tracy_malloc_fast( sizeof( KernelSymbol ) * validCnt );
auto dst = s_kernelSym;
for( auto& v : tmpSym )
{
if( v.name ) *dst++ = v;
}
assert( dst == s_kernelSym + validCnt );
TracyDebug( "Loaded %zu kernel symbols (%zu code sections)\n", tmpSym.size(), validCnt );
} }
#endif #endif
@ -858,8 +901,7 @@ char* NormalizePath( const char* path )
if( path[0] != '/' ) return nullptr; if( path[0] != '/' ) return nullptr;
const char* ptr = path; const char* ptr = path;
const char* end = path; const char* end = path + strlen( path );
while( *end ) end++;
char* res = (char*)tracy_malloc( end - ptr + 1 ); char* res = (char*)tracy_malloc( end - ptr + 1 );
size_t rsz = 0; size_t rsz = 0;
@ -1250,13 +1292,13 @@ CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
#ifdef __linux #ifdef __linux
else if( s_kernelSym ) else if( s_kernelSym )
{ {
auto it = std::lower_bound( s_kernelSym, s_kernelSym + s_kernelSymCnt, ptr, []( const KernelSymbol& lhs, const uint64_t& rhs ) { return lhs.addr > rhs; } ); auto it = std::lower_bound( s_kernelSym, s_kernelSym + s_kernelSymCnt, ptr, []( const KernelSymbol& lhs, const uint64_t& rhs ) { return lhs.addr + lhs.size < rhs; } );
if( it != s_kernelSym + s_kernelSymCnt ) if( it != s_kernelSym + s_kernelSymCnt )
{ {
cb_data[0].name = CopyStringFast( it->name ); cb_data[0].name = CopyStringFast( it->name );
cb_data[0].file = CopyStringFast( "<kernel>" ); cb_data[0].file = CopyStringFast( "<kernel>" );
cb_data[0].line = 0; cb_data[0].line = 0;
cb_data[0].symLen = 0; cb_data[0].symLen = it->size;
cb_data[0].symAddr = it->addr; cb_data[0].symAddr = it->addr;
return { cb_data, 1, it->mod ? it->mod : "<kernel>" }; return { cb_data, 1, it->mod ? it->mod : "<kernel>" };
} }

View File

@ -0,0 +1,121 @@
#ifdef __linux__
#include <algorithm>
#include <assert.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include "TracyDebug.hpp"
#include "TracyKCore.hpp"
#include "../common/TracyAlloc.hpp"
#if !defined(__GLIBC__) && !defined(__WORDSIZE)
// include __WORDSIZE headers for musl
# include <bits/reg.h>
#endif
namespace tracy
{
using elf_half = uint16_t;
using elf_word = uint32_t;
using elf_sword = int32_t;
#if __WORDSIZE == 32
using elf_addr = uint32_t;
using elf_off = uint32_t;
using elf_xword = uint32_t;
#else
using elf_addr = uint64_t;
using elf_off = uint64_t;
using elf_xword = uint64_t;
#endif
struct elf_ehdr
{
unsigned char e_ident[16];
elf_half e_type;
elf_half e_machine;
elf_word e_version;
elf_addr e_entry;
elf_off e_phoff;
elf_off e_shoff;
elf_word e_flags;
elf_half e_ehsize;
elf_half e_phentsize;
elf_half e_phnum;
elf_half e_shentsize;
elf_half e_shnum;
elf_half e_shstrndx;
};
struct elf_phdr
{
elf_word p_type;
elf_word p_flags;
elf_off p_offset;
elf_addr p_vaddr;
elf_addr p_paddr;
elf_xword p_filesz;
elf_xword p_memsz;
uint64_t p_align; // include 32-bit-only flags field for 32-bit compatibility
};
KCore::KCore()
: m_offsets( 16 )
{
m_fd = open( "/proc/kcore", O_RDONLY );
if( m_fd == -1 ) return;
elf_ehdr ehdr;
if( read( m_fd, &ehdr, sizeof( ehdr ) ) != sizeof( ehdr ) ) goto err;
assert( ehdr.e_phentsize == sizeof( elf_phdr ) );
for( elf_half i=0; i<ehdr.e_phnum; i++ )
{
elf_phdr phdr;
if( lseek( m_fd, ehdr.e_phoff + i * ehdr.e_phentsize, SEEK_SET ) == -1 ) goto err;
if( read( m_fd, &phdr, sizeof( phdr ) ) != sizeof( phdr ) ) goto err;
if( phdr.p_type != 1 ) continue;
auto ptr = m_offsets.push_next();
ptr->start = phdr.p_vaddr;
ptr->size = phdr.p_memsz;
ptr->offset = phdr.p_offset;
}
std::sort( m_offsets.begin(), m_offsets.end(), []( const Offset& lhs, const Offset& rhs ) { return lhs.start < rhs.start; } );
TracyDebug( "KCore: %zu segments found\n", m_offsets.size() );
return;
err:
close( m_fd );
m_fd = -1;
}
KCore::~KCore()
{
if( m_fd != -1 ) close( m_fd );
}
void* KCore::Retrieve( uint64_t addr, uint64_t size ) const
{
if( m_fd == -1 ) return nullptr;
auto it = std::lower_bound( m_offsets.begin(), m_offsets.end(), addr, []( const Offset& lhs, uint64_t rhs ) { return lhs.start + lhs.size < rhs; } );
if( it == m_offsets.end() ) return nullptr;
if( addr + size > it->start + it->size ) return nullptr;
if( lseek( m_fd, it->offset + addr - it->start, SEEK_SET ) == -1 ) return nullptr;
auto ptr = tracy_malloc( size );
if( read( m_fd, ptr, size ) != ssize_t( size ) )
{
tracy_free( ptr );
return nullptr;
}
return ptr;
}
}
#endif

View File

@ -0,0 +1,37 @@
#ifndef __TRACYKCORE_HPP__
#define __TRACYKCORE_HPP__
#ifdef __linux__
#include <stdint.h>
#include "TracyFastVector.hpp"
namespace tracy
{
class KCore
{
struct Offset
{
uint64_t start;
uint64_t size;
uint64_t offset;
};
public:
KCore();
~KCore();
void* Retrieve( uint64_t addr, uint64_t size ) const;
private:
int m_fd;
FastVector<Offset> m_offsets;
};
}
#endif
#endif

View File

@ -271,8 +271,19 @@ static bool EnsureReadable( uintptr_t address )
MappingInfo* mapping = LookUpMapping(address); MappingInfo* mapping = LookUpMapping(address);
return mapping && EnsureReadable( *mapping ); return mapping && EnsureReadable( *mapping );
} }
#elif defined WIN32
#endif // defined __ANDROID__ static bool EnsureReadable( uintptr_t address )
{
MEMORY_BASIC_INFORMATION memInfo;
VirtualQuery( reinterpret_cast<void*>( address ), &memInfo, sizeof( memInfo ) );
return memInfo.Protect != PAGE_NOACCESS;
}
#else
static bool EnsureReadable( uintptr_t address )
{
return true;
}
#endif
#ifndef TRACY_DELAYED_INIT #ifndef TRACY_DELAYED_INIT
@ -297,7 +308,7 @@ struct ThreadHandleWrapper
static inline void CpuId( uint32_t* regs, uint32_t leaf ) static inline void CpuId( uint32_t* regs, uint32_t leaf )
{ {
memset(regs, 0, sizeof(uint32_t) * 4); memset(regs, 0, sizeof(uint32_t) * 4);
#if defined _WIN32 #if defined _MSC_VER
__cpuidex( (int*)regs, leaf, 0 ); __cpuidex( (int*)regs, leaf, 0 );
#else #else
__get_cpuid( leaf, regs, regs+1, regs+2, regs+3 ); __get_cpuid( leaf, regs, regs+1, regs+2, regs+3 );
@ -1421,6 +1432,11 @@ Profiler::Profiler()
CalibrateDelay(); CalibrateDelay();
ReportTopology(); ReportTopology();
#ifdef __linux__
m_kcore = (KCore*)tracy_malloc( sizeof( KCore ) );
new(m_kcore) KCore();
#endif
#ifndef TRACY_NO_EXIT #ifndef TRACY_NO_EXIT
const char* noExitEnv = GetEnvVar( "TRACY_NO_EXIT" ); const char* noExitEnv = GetEnvVar( "TRACY_NO_EXIT" );
if( noExitEnv && noExitEnv[0] == '1' ) if( noExitEnv && noExitEnv[0] == '1' )
@ -1568,6 +1584,11 @@ Profiler::~Profiler()
EndCallstack(); EndCallstack();
#endif #endif
#ifdef __linux__
m_kcore->~KCore();
tracy_free( m_kcore );
#endif
tracy_free( m_lz4Buf ); tracy_free( m_lz4Buf );
tracy_free( m_buffer ); tracy_free( m_buffer );
LZ4_freeStream( (LZ4_stream_t*)m_stream ); LZ4_freeStream( (LZ4_stream_t*)m_stream );
@ -3357,6 +3378,17 @@ void Profiler::HandleSymbolQueueItem( const SymbolQueueItem& si )
} }
} }
} }
#elif defined __linux__
void* data = m_kcore->Retrieve( si.ptr, si.extra );
if( data )
{
TracyLfqPrepare( QueueType::SymbolCodeMetadata );
MemWrite( &item->symbolCodeMetadata.symbol, si.ptr );
MemWrite( &item->symbolCodeMetadata.ptr, (uint64_t)data );
MemWrite( &item->symbolCodeMetadata.size, (uint32_t)si.extra );
TracyLfqCommit;
break;
}
#endif #endif
TracyLfqPrepare( QueueType::AckSymbolCodeNotAvailable ); TracyLfqPrepare( QueueType::AckSymbolCodeNotAvailable );
TracyLfqCommit; TracyLfqCommit;
@ -3441,9 +3473,24 @@ bool Profiler::HandleServerQuery()
SendString( ptr, "Main thread", 11, QueueType::ThreadName ); SendString( ptr, "Main thread", 11, QueueType::ThreadName );
} }
else else
{
auto t = GetThreadNameData( (uint32_t)ptr );
if( t )
{
SendString( ptr, t->name, QueueType::ThreadName );
if( t->groupHint != 0 )
{
TracyLfqPrepare( QueueType::ThreadGroupHint );
MemWrite( &item->threadGroupHint.thread, (uint32_t)ptr );
MemWrite( &item->threadGroupHint.groupHint, t->groupHint );
TracyLfqCommit;
}
}
else
{ {
SendString( ptr, GetThreadName( (uint32_t)ptr ), QueueType::ThreadName ); SendString( ptr, GetThreadName( (uint32_t)ptr ), QueueType::ThreadName );
} }
}
break; break;
case ServerQuerySourceLocation: case ServerQuerySourceLocation:
SendSourceLocation( ptr ); SendSourceLocation( ptr );
@ -3680,6 +3727,7 @@ void Profiler::ReportTopology()
struct CpuData struct CpuData
{ {
uint32_t package; uint32_t package;
uint32_t die;
uint32_t core; uint32_t core;
uint32_t thread; uint32_t thread;
}; };
@ -3698,6 +3746,12 @@ void Profiler::ReportTopology()
auto res = _GetLogicalProcessorInformationEx( RelationProcessorPackage, packageInfo, &psz ); auto res = _GetLogicalProcessorInformationEx( RelationProcessorPackage, packageInfo, &psz );
assert( res ); assert( res );
DWORD dsz = 0;
_GetLogicalProcessorInformationEx( RelationProcessorDie, nullptr, &dsz );
auto dieInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)tracy_malloc( dsz );
res = _GetLogicalProcessorInformationEx( RelationProcessorDie, dieInfo, &dsz );
assert( res );
DWORD csz = 0; DWORD csz = 0;
_GetLogicalProcessorInformationEx( RelationProcessorCore, nullptr, &csz ); _GetLogicalProcessorInformationEx( RelationProcessorCore, nullptr, &csz );
auto coreInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)tracy_malloc( csz ); auto coreInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)tracy_malloc( csz );
@ -3709,6 +3763,7 @@ void Profiler::ReportTopology()
const uint32_t numcpus = sysinfo.dwNumberOfProcessors; const uint32_t numcpus = sysinfo.dwNumberOfProcessors;
auto cpuData = (CpuData*)tracy_malloc( sizeof( CpuData ) * numcpus ); auto cpuData = (CpuData*)tracy_malloc( sizeof( CpuData ) * numcpus );
memset( cpuData, 0, sizeof( CpuData ) * numcpus );
for( uint32_t i=0; i<numcpus; i++ ) cpuData[i].thread = i; for( uint32_t i=0; i<numcpus; i++ ) cpuData[i].thread = i;
int idx = 0; int idx = 0;
@ -3729,6 +3784,24 @@ void Profiler::ReportTopology()
idx++; idx++;
} }
idx = 0;
ptr = dieInfo;
while( (char*)ptr < ((char*)dieInfo) + dsz )
{
assert( ptr->Relationship == RelationProcessorDie );
// FIXME account for GroupCount
auto mask = ptr->Processor.GroupMask[0].Mask;
int core = 0;
while( mask != 0 )
{
if( mask & 1 ) cpuData[core].die = idx;
core++;
mask >>= 1;
}
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((char*)ptr) + ptr->Size);
idx++;
}
idx = 0; idx = 0;
ptr = coreInfo; ptr = coreInfo;
while( (char*)ptr < ((char*)coreInfo) + csz ) while( (char*)ptr < ((char*)coreInfo) + csz )
@ -3753,6 +3826,7 @@ void Profiler::ReportTopology()
TracyLfqPrepare( QueueType::CpuTopology ); TracyLfqPrepare( QueueType::CpuTopology );
MemWrite( &item->cpuTopology.package, data.package ); MemWrite( &item->cpuTopology.package, data.package );
MemWrite( &item->cpuTopology.die, data.die );
MemWrite( &item->cpuTopology.core, data.core ); MemWrite( &item->cpuTopology.core, data.core );
MemWrite( &item->cpuTopology.thread, data.thread ); MemWrite( &item->cpuTopology.thread, data.thread );
@ -3788,12 +3862,20 @@ void Profiler::ReportTopology()
fclose( f ); fclose( f );
cpuData[i].package = uint32_t( atoi( buf ) ); cpuData[i].package = uint32_t( atoi( buf ) );
cpuData[i].thread = i; cpuData[i].thread = i;
sprintf( path, "%s%i/topology/core_id", basePath, i ); sprintf( path, "%s%i/topology/core_id", basePath, i );
f = fopen( path, "rb" ); f = fopen( path, "rb" );
read = fread( buf, 1, 1024, f ); read = fread( buf, 1, 1024, f );
buf[read] = '\0'; buf[read] = '\0';
fclose( f ); fclose( f );
cpuData[i].core = uint32_t( atoi( buf ) ); cpuData[i].core = uint32_t( atoi( buf ) );
sprintf( path, "%s%i/topology/die_id", basePath, i );
f = fopen( path, "rb" );
read = fread( buf, 1, 1024, f );
buf[read] = '\0';
fclose( f );
cpuData[i].die = uint32_t( atoi( buf ) );
} }
for( int i=0; i<numcpus; i++ ) for( int i=0; i<numcpus; i++ )
@ -3802,6 +3884,7 @@ void Profiler::ReportTopology()
TracyLfqPrepare( QueueType::CpuTopology ); TracyLfqPrepare( QueueType::CpuTopology );
MemWrite( &item->cpuTopology.package, data.package ); MemWrite( &item->cpuTopology.package, data.package );
MemWrite( &item->cpuTopology.die, data.die );
MemWrite( &item->cpuTopology.core, data.core ); MemWrite( &item->cpuTopology.core, data.core );
MemWrite( &item->cpuTopology.thread, data.thread ); MemWrite( &item->cpuTopology.thread, data.thread );
@ -3892,15 +3975,12 @@ void Profiler::HandleSymbolCodeQuery( uint64_t symbol, uint32_t size )
} }
else else
{ {
#ifdef __ANDROID__
// On Android it's common for code to be in mappings that are only executable
// but not readable.
if( !EnsureReadable( symbol ) ) if( !EnsureReadable( symbol ) )
{ {
AckSymbolCodeNotAvailable(); AckSymbolCodeNotAvailable();
return; return;
} }
#endif
SendLongString( symbol, (const char*)symbol, size, QueueType::SymbolCode ); SendLongString( symbol, (const char*)symbol, size, QueueType::SymbolCode );
} }
} }
@ -4680,7 +4760,7 @@ TRACY_API int ___tracy_connected( void )
} }
#ifdef TRACY_FIBERS #ifdef TRACY_FIBERS
TRACY_API void ___tracy_fiber_enter( const char* fiber ){ tracy::Profiler::EnterFiber( fiber ); } TRACY_API void ___tracy_fiber_enter( const char* fiber ){ tracy::Profiler::EnterFiber( fiber, 0 ); }
TRACY_API void ___tracy_fiber_leave( void ){ tracy::Profiler::LeaveFiber(); } TRACY_API void ___tracy_fiber_leave( void ){ tracy::Profiler::LeaveFiber(); }
#endif #endif

View File

@ -10,6 +10,7 @@
#include "tracy_concurrentqueue.h" #include "tracy_concurrentqueue.h"
#include "tracy_SPSCQueue.h" #include "tracy_SPSCQueue.h"
#include "TracyCallstack.hpp" #include "TracyCallstack.hpp"
#include "TracyKCore.hpp"
#include "TracySysPower.hpp" #include "TracySysPower.hpp"
#include "TracySysTime.hpp" #include "TracySysTime.hpp"
#include "TracyFastVector.hpp" #include "TracyFastVector.hpp"
@ -27,7 +28,7 @@
# include <mach/mach_time.h> # include <mach/mach_time.h>
#endif #endif
#if ( defined _WIN32 || ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 ) || ( defined TARGET_OS_IOS && TARGET_OS_IOS == 1 ) ) #if ( (defined _WIN32 && !(defined _M_ARM64 || defined _M_ARM)) || ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 ) || ( defined TARGET_OS_IOS && TARGET_OS_IOS == 1 ) )
# define TRACY_HW_TIMER # define TRACY_HW_TIMER
#endif #endif
@ -674,11 +675,12 @@ public:
} }
#ifdef TRACY_FIBERS #ifdef TRACY_FIBERS
static tracy_force_inline void EnterFiber( const char* fiber ) static tracy_force_inline void EnterFiber( const char* fiber, int32_t groupHint )
{ {
TracyQueuePrepare( QueueType::FiberEnter ); TracyQueuePrepare( QueueType::FiberEnter );
MemWrite( &item->fiberEnter.time, GetTime() ); MemWrite( &item->fiberEnter.time, GetTime() );
MemWrite( &item->fiberEnter.fiber, (uint64_t)fiber ); MemWrite( &item->fiberEnter.fiber, (uint64_t)fiber );
MemWrite( &item->fiberEnter.groupHint, groupHint );
TracyQueueCommit( fiberEnter ); TracyQueueCommit( fiberEnter );
} }
@ -995,6 +997,7 @@ private:
struct { struct {
struct sigaction pwr, ill, fpe, segv, pipe, bus, abrt; struct sigaction pwr, ill, fpe, segv, pipe, bus, abrt;
} m_prevSignal; } m_prevSignal;
KCore* m_kcore;
#endif #endif
bool m_crashHandlerInstalled; bool m_crashHandlerInstalled;

View File

@ -126,7 +126,7 @@ public:
TracyQueueCommit( zoneTextFatThread ); TracyQueueCommit( zoneTextFatThread );
} }
tracy_force_inline void TextFmt( const char* fmt, ... ) void TextFmt( const char* fmt, ... )
{ {
if( !m_active ) return; if( !m_active ) return;
#ifdef TRACY_ON_DEMAND #ifdef TRACY_ON_DEMAND
@ -165,7 +165,7 @@ public:
TracyQueueCommit( zoneTextFatThread ); TracyQueueCommit( zoneTextFatThread );
} }
tracy_force_inline void NameFmt( const char* fmt, ... ) void NameFmt( const char* fmt, ... )
{ {
if( !m_active ) return; if( !m_active ) return;
#ifdef TRACY_ON_DEMAND #ifdef TRACY_ON_DEMAND

View File

@ -16,16 +16,25 @@
namespace tracy namespace tracy
{ {
static constexpr int GetSamplingFrequency() static int GetSamplingFrequency()
{ {
int samplingHz = TRACY_SAMPLING_HZ;
auto env = GetEnvVar( "TRACY_SAMPLING_HZ" );
if( env )
{
int val = atoi( env );
if( val > 0 ) samplingHz = val;
}
#if defined _WIN32 #if defined _WIN32
return TRACY_SAMPLING_HZ > 8000 ? 8000 : ( TRACY_SAMPLING_HZ < 1 ? 1 : TRACY_SAMPLING_HZ ); return samplingHz > 8000 ? 8000 : ( samplingHz < 1 ? 1 : samplingHz );
#else #else
return TRACY_SAMPLING_HZ > 1000000 ? 1000000 : ( TRACY_SAMPLING_HZ < 1 ? 1 : TRACY_SAMPLING_HZ ); return samplingHz > 1000000 ? 1000000 : ( samplingHz < 1 ? 1 : samplingHz );
#endif #endif
} }
static constexpr int GetSamplingPeriod() static int GetSamplingPeriod()
{ {
return 1000000000 / GetSamplingFrequency(); return 1000000000 / GetSamplingFrequency();
} }
@ -321,7 +330,7 @@ static void SetupVsync()
#endif #endif
} }
static constexpr int GetSamplingInterval() static int GetSamplingInterval()
{ {
return GetSamplingPeriod() / 100; return GetSamplingPeriod() / 100;
} }

View File

@ -781,7 +781,7 @@ rpmalloc_set_main_thread(void) {
static void static void
_rpmalloc_spin(void) { _rpmalloc_spin(void) {
#if defined(_MSC_VER) #if defined(_MSC_VER) && !(defined(_M_ARM) || defined(_M_ARM64))
_mm_pause(); _mm_pause();
#elif defined(__x86_64__) || defined(__i386__) #elif defined(__x86_64__) || defined(__i386__)
__asm__ volatile("pause" ::: "memory"); __asm__ volatile("pause" ::: "memory");
@ -793,8 +793,7 @@ _rpmalloc_spin(void) {
#elif defined(__sparc__) #elif defined(__sparc__)
__asm__ volatile("rd %ccr, %g0 \n\trd %ccr, %g0 \n\trd %ccr, %g0"); __asm__ volatile("rd %ccr, %g0 \n\trd %ccr, %g0 \n\trd %ccr, %g0");
#else #else
struct timespec ts = {0}; std::this_thread::yield();
nanosleep(&ts, 0);
#endif #endif
} }

View File

@ -9,7 +9,7 @@ namespace tracy
constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; } constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; }
enum : uint32_t { ProtocolVersion = 66 }; enum : uint32_t { ProtocolVersion = 69 };
enum : uint16_t { BroadcastVersion = 3 }; enum : uint16_t { BroadcastVersion = 3 };
using lz4sz_t = uint32_t; using lz4sz_t = uint32_t;

View File

@ -108,6 +108,7 @@ enum class QueueType : uint8_t
SingleStringData, SingleStringData,
SecondStringData, SecondStringData,
MemNamePayload, MemNamePayload,
ThreadGroupHint,
StringData, StringData,
ThreadName, ThreadName,
PlotName, PlotName,
@ -259,6 +260,7 @@ struct QueueFiberEnter
int64_t time; int64_t time;
uint64_t fiber; // ptr uint64_t fiber; // ptr
uint32_t thread; uint32_t thread;
int32_t groupHint;
}; };
struct QueueFiberLeave struct QueueFiberLeave
@ -477,6 +479,12 @@ struct QueueMemNamePayload
uint64_t name; uint64_t name;
}; };
struct QueueThreadGroupHint
{
uint32_t thread;
int32_t groupHint;
};
struct QueueMemAlloc struct QueueMemAlloc
{ {
int64_t time; int64_t time;
@ -639,6 +647,7 @@ struct QueueSourceCodeNotAvailable
struct QueueCpuTopology struct QueueCpuTopology
{ {
uint32_t package; uint32_t package;
uint32_t die;
uint32_t core; uint32_t core;
uint32_t thread; uint32_t thread;
}; };
@ -732,6 +741,7 @@ struct QueueItem
QueueMemAlloc memAlloc; QueueMemAlloc memAlloc;
QueueMemFree memFree; QueueMemFree memFree;
QueueMemNamePayload memName; QueueMemNamePayload memName;
QueueThreadGroupHint threadGroupHint;
QueueCallstackFat callstackFat; QueueCallstackFat callstackFat;
QueueCallstackFatThread callstackFatThread; QueueCallstackFatThread callstackFatThread;
QueueCallstackAllocFat callstackAllocFat; QueueCallstackAllocFat callstackAllocFat;
@ -868,6 +878,7 @@ static constexpr size_t QueueDataSize[] = {
sizeof( QueueHeader ), // single string data sizeof( QueueHeader ), // single string data
sizeof( QueueHeader ), // second string data sizeof( QueueHeader ), // second string data
sizeof( QueueHeader ) + sizeof( QueueMemNamePayload ), sizeof( QueueHeader ) + sizeof( QueueMemNamePayload ),
sizeof( QueueHeader ) + sizeof( QueueThreadGroupHint ),
// keep all QueueStringTransfer below // keep all QueueStringTransfer below
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // string data sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // string data
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // thread name sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // thread name

View File

@ -101,12 +101,6 @@ TRACY_API uint32_t GetThreadHandleImpl()
} }
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
struct ThreadNameData
{
uint32_t id;
const char* name;
ThreadNameData* next;
};
std::atomic<ThreadNameData*>& GetThreadNameData(); std::atomic<ThreadNameData*>& GetThreadNameData();
#endif #endif
@ -134,6 +128,11 @@ void ThreadNameMsvcMagic( const THREADNAME_INFO& info )
#endif #endif
TRACY_API void SetThreadName( const char* name ) TRACY_API void SetThreadName( const char* name )
{
SetThreadNameWithHint( name, 0 );
}
TRACY_API void SetThreadNameWithHint( const char* name, int32_t groupHint )
{ {
#if defined _WIN32 #if defined _WIN32
# ifdef TRACY_UWP # ifdef TRACY_UWP
@ -205,6 +204,7 @@ TRACY_API void SetThreadName( const char* name )
buf[sz] = '\0'; buf[sz] = '\0';
auto data = (ThreadNameData*)tracy_malloc_fast( sizeof( ThreadNameData ) ); auto data = (ThreadNameData*)tracy_malloc_fast( sizeof( ThreadNameData ) );
data->id = detail::GetThreadHandleImpl(); data->id = detail::GetThreadHandleImpl();
data->groupHint = groupHint;
data->name = buf; data->name = buf;
data->next = GetThreadNameData().load( std::memory_order_relaxed ); data->next = GetThreadNameData().load( std::memory_order_relaxed );
while( !GetThreadNameData().compare_exchange_weak( data->next, data, std::memory_order_release, std::memory_order_relaxed ) ) {} while( !GetThreadNameData().compare_exchange_weak( data->next, data, std::memory_order_release, std::memory_order_relaxed ) ) {}
@ -212,6 +212,22 @@ TRACY_API void SetThreadName( const char* name )
#endif #endif
} }
#ifdef TRACY_ENABLE
ThreadNameData* GetThreadNameData( uint32_t id )
{
auto ptr = GetThreadNameData().load( std::memory_order_relaxed );
while( ptr )
{
if( ptr->id == id )
{
return ptr;
}
ptr = ptr->next;
}
return nullptr;
}
#endif
TRACY_API const char* GetThreadName( uint32_t id ) TRACY_API const char* GetThreadName( uint32_t id )
{ {
static char buf[256]; static char buf[256];

View File

@ -14,6 +14,16 @@ TRACY_API uint32_t GetThreadHandleImpl();
} }
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
struct ThreadNameData
{
uint32_t id;
int32_t groupHint;
const char* name;
ThreadNameData* next;
};
ThreadNameData* GetThreadNameData( uint32_t id );
TRACY_API uint32_t GetThreadHandle(); TRACY_API uint32_t GetThreadHandle();
#else #else
static inline uint32_t GetThreadHandle() static inline uint32_t GetThreadHandle()
@ -23,6 +33,7 @@ static inline uint32_t GetThreadHandle()
#endif #endif
TRACY_API void SetThreadName( const char* name ); TRACY_API void SetThreadName( const char* name );
TRACY_API void SetThreadNameWithHint( const char* name, int32_t groupHint );
TRACY_API const char* GetThreadName( uint32_t id ); TRACY_API const char* GetThreadName( uint32_t id );
TRACY_API const char* GetEnvVar( const char* name ); TRACY_API const char* GetEnvVar( const char* name );

View File

@ -6,8 +6,8 @@ namespace tracy
namespace Version namespace Version
{ {
enum { Major = 0 }; enum { Major = 0 };
enum { Minor = 10 }; enum { Minor = 11 };
enum { Patch = 0 }; enum { Patch = 2 };
} }
} }

View File

@ -725,8 +725,8 @@ struct dwarf_data
struct dwarf_data *next; struct dwarf_data *next;
/* The data for .gnu_debugaltlink. */ /* The data for .gnu_debugaltlink. */
struct dwarf_data *altlink; struct dwarf_data *altlink;
/* The base address for this file. */ /* The base address mapping for this file. */
uintptr_t base_address; struct libbacktrace_base_address base_address;
/* A sorted list of address ranges. */ /* A sorted list of address ranges. */
struct unit_addrs *addrs; struct unit_addrs *addrs;
/* Number of address ranges in list. */ /* Number of address ranges in list. */
@ -1947,8 +1947,9 @@ update_pcrange (const struct attr* attr, const struct attr_val* val,
static int static int
add_low_high_range (struct backtrace_state *state, add_low_high_range (struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections, const struct dwarf_sections *dwarf_sections,
uintptr_t base_address, int is_bigendian, struct libbacktrace_base_address base_address,
struct unit *u, const struct pcrange *pcrange, int is_bigendian, struct unit *u,
const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state, int (*add_range) (struct backtrace_state *state,
void *rdata, uintptr_t lowpc, void *rdata, uintptr_t lowpc,
uintptr_t highpc, uintptr_t highpc,
@ -1983,8 +1984,8 @@ add_low_high_range (struct backtrace_state *state,
/* Add in the base address of the module when recording PC values, /* Add in the base address of the module when recording PC values,
so that we can look up the PC directly. */ so that we can look up the PC directly. */
lowpc += base_address; lowpc = libbacktrace_add_base (lowpc, base_address);
highpc += base_address; highpc = libbacktrace_add_base (highpc, base_address);
return add_range (state, rdata, lowpc, highpc, error_callback, data, vec); return add_range (state, rdata, lowpc, highpc, error_callback, data, vec);
} }
@ -1996,7 +1997,7 @@ static int
add_ranges_from_ranges ( add_ranges_from_ranges (
struct backtrace_state *state, struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections, const struct dwarf_sections *dwarf_sections,
uintptr_t base_address, int is_bigendian, struct libbacktrace_base_address base_address, int is_bigendian,
struct unit *u, uintptr_t base, struct unit *u, uintptr_t base,
const struct pcrange *pcrange, const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state, void *rdata, int (*add_range) (struct backtrace_state *state, void *rdata,
@ -2042,10 +2043,11 @@ add_ranges_from_ranges (
base = (uintptr_t) high; base = (uintptr_t) high;
else else
{ {
if (!add_range (state, rdata, uintptr_t rl, rh;
(uintptr_t) low + base + base_address,
(uintptr_t) high + base + base_address, rl = libbacktrace_add_base ((uintptr_t) low + base, base_address);
error_callback, data, vec)) rh = libbacktrace_add_base ((uintptr_t) high + base, base_address);
if (!add_range (state, rdata, rl, rh, error_callback, data, vec))
return 0; return 0;
} }
} }
@ -2063,7 +2065,7 @@ static int
add_ranges_from_rnglists ( add_ranges_from_rnglists (
struct backtrace_state *state, struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections, const struct dwarf_sections *dwarf_sections,
uintptr_t base_address, int is_bigendian, struct libbacktrace_base_address base_address, int is_bigendian,
struct unit *u, uintptr_t base, struct unit *u, uintptr_t base,
const struct pcrange *pcrange, const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state, void *rdata, int (*add_range) (struct backtrace_state *state, void *rdata,
@ -2146,9 +2148,10 @@ add_ranges_from_rnglists (
u->addrsize, is_bigendian, index, u->addrsize, is_bigendian, index,
error_callback, data, &high)) error_callback, data, &high))
return 0; return 0;
if (!add_range (state, rdata, low + base_address, if (!add_range (state, rdata,
high + base_address, error_callback, data, libbacktrace_add_base (low, base_address),
vec)) libbacktrace_add_base (high, base_address),
error_callback, data, vec))
return 0; return 0;
} }
break; break;
@ -2165,7 +2168,7 @@ add_ranges_from_rnglists (
error_callback, data, &low)) error_callback, data, &low))
return 0; return 0;
length = read_uleb128 (&rnglists_buf); length = read_uleb128 (&rnglists_buf);
low += base_address; low = libbacktrace_add_base (low, base_address);
if (!add_range (state, rdata, low, low + length, if (!add_range (state, rdata, low, low + length,
error_callback, data, vec)) error_callback, data, vec))
return 0; return 0;
@ -2179,8 +2182,9 @@ add_ranges_from_rnglists (
low = read_uleb128 (&rnglists_buf); low = read_uleb128 (&rnglists_buf);
high = read_uleb128 (&rnglists_buf); high = read_uleb128 (&rnglists_buf);
if (!add_range (state, rdata, low + base + base_address, if (!add_range (state, rdata,
high + base + base_address, libbacktrace_add_base (low + base, base_address),
libbacktrace_add_base (high + base, base_address),
error_callback, data, vec)) error_callback, data, vec))
return 0; return 0;
} }
@ -2197,9 +2201,10 @@ add_ranges_from_rnglists (
low = (uintptr_t) read_address (&rnglists_buf, u->addrsize); low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
high = (uintptr_t) read_address (&rnglists_buf, u->addrsize); high = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
if (!add_range (state, rdata, low + base_address, if (!add_range (state, rdata,
high + base_address, error_callback, data, libbacktrace_add_base (low, base_address),
vec)) libbacktrace_add_base (high, base_address),
error_callback, data, vec))
return 0; return 0;
} }
break; break;
@ -2211,7 +2216,7 @@ add_ranges_from_rnglists (
low = (uintptr_t) read_address (&rnglists_buf, u->addrsize); low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
length = (uintptr_t) read_uleb128 (&rnglists_buf); length = (uintptr_t) read_uleb128 (&rnglists_buf);
low += base_address; low = libbacktrace_add_base (low, base_address);
if (!add_range (state, rdata, low, low + length, if (!add_range (state, rdata, low, low + length,
error_callback, data, vec)) error_callback, data, vec))
return 0; return 0;
@ -2239,7 +2244,7 @@ add_ranges_from_rnglists (
static int static int
add_ranges (struct backtrace_state *state, add_ranges (struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections, const struct dwarf_sections *dwarf_sections,
uintptr_t base_address, int is_bigendian, struct libbacktrace_base_address base_address, int is_bigendian,
struct unit *u, uintptr_t base, const struct pcrange *pcrange, struct unit *u, uintptr_t base, const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state, void *rdata, int (*add_range) (struct backtrace_state *state, void *rdata,
uintptr_t lowpc, uintptr_t highpc, uintptr_t lowpc, uintptr_t highpc,
@ -2275,7 +2280,8 @@ add_ranges (struct backtrace_state *state,
read, 0 if there is some error. */ read, 0 if there is some error. */
static int static int
find_address_ranges (struct backtrace_state *state, uintptr_t base_address, find_address_ranges (struct backtrace_state *state,
struct libbacktrace_base_address base_address,
struct dwarf_buf *unit_buf, struct dwarf_buf *unit_buf,
const struct dwarf_sections *dwarf_sections, const struct dwarf_sections *dwarf_sections,
int is_bigendian, struct dwarf_data *altlink, int is_bigendian, struct dwarf_data *altlink,
@ -2430,7 +2436,8 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
on success, 0 on failure. */ on success, 0 on failure. */
static int static int
build_address_map (struct backtrace_state *state, uintptr_t base_address, build_address_map (struct backtrace_state *state,
struct libbacktrace_base_address base_address,
const struct dwarf_sections *dwarf_sections, const struct dwarf_sections *dwarf_sections,
int is_bigendian, struct dwarf_data *altlink, int is_bigendian, struct dwarf_data *altlink,
backtrace_error_callback error_callback, void *data, backtrace_error_callback error_callback, void *data,
@ -2649,7 +2656,7 @@ add_line (struct backtrace_state *state, struct dwarf_data *ddata,
/* Add in the base address here, so that we can look up the PC /* Add in the base address here, so that we can look up the PC
directly. */ directly. */
ln->pc = pc + ddata->base_address; ln->pc = libbacktrace_add_base (pc, ddata->base_address);
ln->filename = filename; ln->filename = filename;
ln->lineno = lineno; ln->lineno = lineno;
@ -4329,7 +4336,7 @@ dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
static struct dwarf_data * static struct dwarf_data *
build_dwarf_data (struct backtrace_state *state, build_dwarf_data (struct backtrace_state *state,
uintptr_t base_address, struct libbacktrace_base_address base_address,
const struct dwarf_sections *dwarf_sections, const struct dwarf_sections *dwarf_sections,
int is_bigendian, int is_bigendian,
struct dwarf_data *altlink, struct dwarf_data *altlink,
@ -4387,7 +4394,7 @@ build_dwarf_data (struct backtrace_state *state,
int int
backtrace_dwarf_add (struct backtrace_state *state, backtrace_dwarf_add (struct backtrace_state *state,
uintptr_t base_address, struct libbacktrace_base_address base_address,
const struct dwarf_sections *dwarf_sections, const struct dwarf_sections *dwarf_sections,
int is_bigendian, int is_bigendian,
struct dwarf_data *fileline_altlink, struct dwarf_data *fileline_altlink,

View File

@ -643,7 +643,7 @@ elf_symbol_search (const void *vkey, const void *ventry)
static int static int
elf_initialize_syminfo (struct backtrace_state *state, elf_initialize_syminfo (struct backtrace_state *state,
uintptr_t base_address, struct libbacktrace_base_address base_address,
const unsigned char *symtab_data, size_t symtab_size, const unsigned char *symtab_data, size_t symtab_size,
const unsigned char *strtab, size_t strtab_size, const unsigned char *strtab, size_t strtab_size,
backtrace_error_callback error_callback, backtrace_error_callback error_callback,
@ -709,7 +709,8 @@ elf_initialize_syminfo (struct backtrace_state *state,
= *(const b_elf_addr *) (opd->data + (sym->st_value - opd->addr)); = *(const b_elf_addr *) (opd->data + (sym->st_value - opd->addr));
else else
elf_symbols[j].address = sym->st_value; elf_symbols[j].address = sym->st_value;
elf_symbols[j].address += base_address; elf_symbols[j].address =
libbacktrace_add_base (elf_symbols[j].address, base_address);
elf_symbols[j].size = sym->st_size; elf_symbols[j].size = sym->st_size;
++j; ++j;
} }
@ -1200,14 +1201,7 @@ elf_fetch_bits_backward (const unsigned char **ppin,
val = *pval; val = *pval;
if (unlikely (pin <= pinend)) if (unlikely (pin <= pinend))
{
if (bits == 0)
{
elf_uncompress_failed ();
return 0;
}
return 1; return 1;
}
pin -= 4; pin -= 4;
@ -5712,10 +5706,10 @@ elf_uncompress_lzma_block (const unsigned char *compressed,
/* Block header CRC. */ /* Block header CRC. */
computed_crc = elf_crc32 (0, compressed + block_header_offset, computed_crc = elf_crc32 (0, compressed + block_header_offset,
block_header_size - 4); block_header_size - 4);
stream_crc = (compressed[off] stream_crc = ((uint32_t)compressed[off]
| (compressed[off + 1] << 8) | ((uint32_t)compressed[off + 1] << 8)
| (compressed[off + 2] << 16) | ((uint32_t)compressed[off + 2] << 16)
| (compressed[off + 3] << 24)); | ((uint32_t)compressed[off + 3] << 24));
if (unlikely (computed_crc != stream_crc)) if (unlikely (computed_crc != stream_crc))
{ {
elf_uncompress_failed (); elf_uncompress_failed ();
@ -6222,10 +6216,10 @@ elf_uncompress_lzma_block (const unsigned char *compressed,
return 0; return 0;
} }
computed_crc = elf_crc32 (0, uncompressed, uncompressed_offset); computed_crc = elf_crc32 (0, uncompressed, uncompressed_offset);
stream_crc = (compressed[off] stream_crc = ((uint32_t)compressed[off]
| (compressed[off + 1] << 8) | ((uint32_t)compressed[off + 1] << 8)
| (compressed[off + 2] << 16) | ((uint32_t)compressed[off + 2] << 16)
| (compressed[off + 3] << 24)); | ((uint32_t)compressed[off + 3] << 24));
if (computed_crc != stream_crc) if (computed_crc != stream_crc)
{ {
elf_uncompress_failed (); elf_uncompress_failed ();
@ -6325,10 +6319,10 @@ elf_uncompress_lzma (struct backtrace_state *state,
/* Next comes a CRC of the stream flags. */ /* Next comes a CRC of the stream flags. */
computed_crc = elf_crc32 (0, compressed + 6, 2); computed_crc = elf_crc32 (0, compressed + 6, 2);
stream_crc = (compressed[8] stream_crc = ((uint32_t)compressed[8]
| (compressed[9] << 8) | ((uint32_t)compressed[9] << 8)
| (compressed[10] << 16) | ((uint32_t)compressed[10] << 16)
| (compressed[11] << 24)); | ((uint32_t)compressed[11] << 24));
if (unlikely (computed_crc != stream_crc)) if (unlikely (computed_crc != stream_crc))
{ {
elf_uncompress_failed (); elf_uncompress_failed ();
@ -6369,10 +6363,10 @@ elf_uncompress_lzma (struct backtrace_state *state,
/* Before that is a footer CRC. */ /* Before that is a footer CRC. */
computed_crc = elf_crc32 (0, compressed + offset, 6); computed_crc = elf_crc32 (0, compressed + offset, 6);
stream_crc = (compressed[offset - 4] stream_crc = ((uint32_t)compressed[offset - 4]
| (compressed[offset - 3] << 8) | ((uint32_t)compressed[offset - 3] << 8)
| (compressed[offset - 2] << 16) | ((uint32_t)compressed[offset - 2] << 16)
| (compressed[offset - 1] << 24)); | ((uint32_t)compressed[offset - 1] << 24));
if (unlikely (computed_crc != stream_crc)) if (unlikely (computed_crc != stream_crc))
{ {
elf_uncompress_failed (); elf_uncompress_failed ();
@ -6428,10 +6422,10 @@ elf_uncompress_lzma (struct backtrace_state *state,
/* Next is a CRC of the index. */ /* Next is a CRC of the index. */
computed_crc = elf_crc32 (0, compressed + index_offset, computed_crc = elf_crc32 (0, compressed + index_offset,
offset - index_offset); offset - index_offset);
stream_crc = (compressed[offset] stream_crc = ((uint32_t)compressed[offset]
| (compressed[offset + 1] << 8) | ((uint32_t)compressed[offset + 1] << 8)
| (compressed[offset + 2] << 16) | ((uint32_t)compressed[offset + 2] << 16)
| (compressed[offset + 3] << 24)); | ((uint32_t)compressed[offset + 3] << 24));
if (unlikely (computed_crc != stream_crc)) if (unlikely (computed_crc != stream_crc))
{ {
elf_uncompress_failed (); elf_uncompress_failed ();
@ -6524,7 +6518,8 @@ backtrace_uncompress_lzma (struct backtrace_state *state,
static int static int
elf_add (struct backtrace_state *state, const char *filename, int descriptor, elf_add (struct backtrace_state *state, const char *filename, int descriptor,
const unsigned char *memory, size_t memory_size, const unsigned char *memory, size_t memory_size,
uintptr_t base_address, struct elf_ppc64_opd_data *caller_opd, struct libbacktrace_base_address base_address,
struct elf_ppc64_opd_data *caller_opd,
backtrace_error_callback error_callback, void *data, backtrace_error_callback error_callback, void *data,
fileline *fileline_fn, int *found_sym, int *found_dwarf, fileline *fileline_fn, int *found_sym, int *found_dwarf,
struct dwarf_data **fileline_entry, int exe, int debuginfo, struct dwarf_data **fileline_entry, int exe, int debuginfo,
@ -6867,7 +6862,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
} }
} }
if (!gnu_debugdata_view_valid if (!debuginfo
&& !gnu_debugdata_view_valid
&& strcmp (name, ".gnu_debugdata") == 0) && strcmp (name, ".gnu_debugdata") == 0)
{ {
if (!elf_get_view (state, descriptor, memory, memory_size, if (!elf_get_view (state, descriptor, memory, memory_size,
@ -7425,6 +7421,7 @@ phdr_callback (struct PhdrIterate *info, void *pdata)
const char *filename; const char *filename;
int descriptor; int descriptor;
int does_not_exist; int does_not_exist;
struct libbacktrace_base_address base_address;
fileline elf_fileline_fn; fileline elf_fileline_fn;
int found_dwarf; int found_dwarf;
@ -7454,7 +7451,8 @@ phdr_callback (struct PhdrIterate *info, void *pdata)
return 0; return 0;
} }
if (elf_add (pd->state, filename, descriptor, NULL, 0, info->dlpi_addr, NULL, base_address.m = info->dlpi_addr;
if (elf_add (pd->state, filename, descriptor, NULL, 0, base_address, NULL,
pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym, pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,
&found_dwarf, NULL, 0, 0, NULL, 0)) &found_dwarf, NULL, 0, 0, NULL, 0))
{ {
@ -7471,7 +7469,7 @@ phdr_callback (struct PhdrIterate *info, void *pdata)
static int elf_iterate_phdr_and_add_new_files(phdr_data *pd) static int elf_iterate_phdr_and_add_new_files(phdr_data *pd)
{ {
assert(s_phdrData.empty()); assert(s_phdrData.empty());
// dl_iterate_phdr, will only add entries for elf files loaded in a previouly unseen range // dl_iterate_phdr, will only add entries for elf files loaded in a previously unseen range
dl_iterate_phdr(phdr_callback_mock, nullptr); dl_iterate_phdr(phdr_callback_mock, nullptr);
if(s_phdrData.size() == 0) if(s_phdrData.size() == 0)
@ -7543,11 +7541,21 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
fileline elf_fileline_fn = elf_nodebug; fileline elf_fileline_fn = elf_nodebug;
struct phdr_data pd; struct phdr_data pd;
ret = elf_add (state, filename, descriptor, NULL, 0, 0, NULL, error_callback,
data, &elf_fileline_fn, &found_sym, &found_dwarf, NULL, 1, 0, /* When using fdpic we must use dl_iterate_phdr for all modules, including
NULL, 0); the main executable, so that we can get the right base address
mapping. */
if (!libbacktrace_using_fdpic ())
{
struct libbacktrace_base_address zero_base_address;
memset (&zero_base_address, 0, sizeof zero_base_address);
ret = elf_add (state, filename, descriptor, NULL, 0, zero_base_address,
NULL, error_callback, data, &elf_fileline_fn, &found_sym,
&found_dwarf, NULL, 1, 0, NULL, 0);
if (!ret) if (!ret)
return 0; return 0;
}
pd.state = state; pd.state = state;
pd.error_callback = error_callback; pd.error_callback = error_callback;

View File

@ -333,10 +333,44 @@ struct dwarf_sections
struct dwarf_data; struct dwarf_data;
/* The load address mapping. */
#if defined(__FDPIC__) && defined(HAVE_DL_ITERATE_PHDR) && (defined(HAVE_LINK_H) || defined(HAVE_SYS_LINK_H))
#ifdef HAVE_LINK_H
#include <link.h>
#endif
#ifdef HAVE_SYS_LINK_H
#include <sys/link.h>
#endif
#define libbacktrace_using_fdpic() (1)
struct libbacktrace_base_address
{
struct elf32_fdpic_loadaddr m;
};
#define libbacktrace_add_base(pc, base) \
((uintptr_t) (__RELOC_POINTER ((pc), (base).m)))
#else /* not _FDPIC__ */
#define libbacktrace_using_fdpic() (0)
struct libbacktrace_base_address
{
uintptr_t m;
};
#define libbacktrace_add_base(pc, base) ((pc) + (base).m)
#endif /* not _FDPIC__ */
/* Add file/line information for a DWARF module. */ /* Add file/line information for a DWARF module. */
extern int backtrace_dwarf_add (struct backtrace_state *state, extern int backtrace_dwarf_add (struct backtrace_state *state,
uintptr_t base_address, struct libbacktrace_base_address base_address,
const struct dwarf_sections *dwarf_sections, const struct dwarf_sections *dwarf_sections,
int is_bigendian, int is_bigendian,
struct dwarf_data *fileline_altlink, struct dwarf_data *fileline_altlink,

View File

@ -274,12 +274,14 @@ struct macho_nlist_64
/* Value found in nlist n_type field. */ /* Value found in nlist n_type field. */
#define MACH_O_N_EXT 0x01 /* Extern symbol */
#define MACH_O_N_ABS 0x02 /* Absolute symbol */
#define MACH_O_N_SECT 0x0e /* Defined in section */
#define MACH_O_N_TYPE 0x0e /* Mask for type bits */
#define MACH_O_N_STAB 0xe0 /* Stabs debugging symbol */ #define MACH_O_N_STAB 0xe0 /* Stabs debugging symbol */
#define MACH_O_N_TYPE 0x0e /* Mask for type bits */
/* Values found after masking with MACH_O_N_TYPE. */
#define MACH_O_N_UNDF 0x00 /* Undefined symbol */
#define MACH_O_N_ABS 0x02 /* Absolute symbol */
#define MACH_O_N_SECT 0x0e /* Defined in section from n_sect field */
/* Information we keep for a Mach-O symbol. */ /* Information we keep for a Mach-O symbol. */
@ -316,8 +318,9 @@ static const char * const dwarf_section_names[DEBUG_MAX] =
/* Forward declaration. */ /* Forward declaration. */
static int macho_add (struct backtrace_state *, const char *, int, off_t, static int macho_add (struct backtrace_state *, const char *, int, off_t,
const unsigned char *, uintptr_t, int, const unsigned char *, struct libbacktrace_base_address,
backtrace_error_callback, void *, fileline *, int *); int, backtrace_error_callback, void *, fileline *,
int *);
/* A dummy callback function used when we can't find any debug info. */ /* A dummy callback function used when we can't find any debug info. */
@ -495,10 +498,10 @@ macho_defined_symbol (uint8_t type)
{ {
if ((type & MACH_O_N_STAB) != 0) if ((type & MACH_O_N_STAB) != 0)
return 0; return 0;
if ((type & MACH_O_N_EXT) != 0)
return 0;
switch (type & MACH_O_N_TYPE) switch (type & MACH_O_N_TYPE)
{ {
case MACH_O_N_UNDF:
return 0;
case MACH_O_N_ABS: case MACH_O_N_ABS:
return 1; return 1;
case MACH_O_N_SECT: case MACH_O_N_SECT:
@ -512,7 +515,7 @@ macho_defined_symbol (uint8_t type)
static int static int
macho_add_symtab (struct backtrace_state *state, int descriptor, macho_add_symtab (struct backtrace_state *state, int descriptor,
uintptr_t base_address, int is_64, struct libbacktrace_base_address base_address, int is_64,
off_t symoff, unsigned int nsyms, off_t stroff, off_t symoff, unsigned int nsyms, off_t stroff,
unsigned int strsize, unsigned int strsize,
backtrace_error_callback error_callback, void *data) backtrace_error_callback error_callback, void *data)
@ -627,7 +630,7 @@ macho_add_symtab (struct backtrace_state *state, int descriptor,
if (name[0] == '_') if (name[0] == '_')
++name; ++name;
macho_symbols[j].name = name; macho_symbols[j].name = name;
macho_symbols[j].address = value + base_address; macho_symbols[j].address = libbacktrace_add_base (value, base_address);
++j; ++j;
} }
@ -760,7 +763,8 @@ macho_syminfo (struct backtrace_state *state, uintptr_t addr,
static int static int
macho_add_fat (struct backtrace_state *state, const char *filename, macho_add_fat (struct backtrace_state *state, const char *filename,
int descriptor, int swapped, off_t offset, int descriptor, int swapped, off_t offset,
const unsigned char *match_uuid, uintptr_t base_address, const unsigned char *match_uuid,
struct libbacktrace_base_address base_address,
int skip_symtab, uint32_t nfat_arch, int is_64, int skip_symtab, uint32_t nfat_arch, int is_64,
backtrace_error_callback error_callback, void *data, backtrace_error_callback error_callback, void *data,
fileline *fileline_fn, int *found_sym) fileline *fileline_fn, int *found_sym)
@ -862,7 +866,8 @@ macho_add_fat (struct backtrace_state *state, const char *filename,
static int static int
macho_add_dsym (struct backtrace_state *state, const char *filename, macho_add_dsym (struct backtrace_state *state, const char *filename,
uintptr_t base_address, const unsigned char *uuid, struct libbacktrace_base_address base_address,
const unsigned char *uuid,
backtrace_error_callback error_callback, void *data, backtrace_error_callback error_callback, void *data,
fileline* fileline_fn) fileline* fileline_fn)
{ {
@ -980,7 +985,7 @@ macho_add_dsym (struct backtrace_state *state, const char *filename,
static int static int
macho_add (struct backtrace_state *state, const char *filename, int descriptor, macho_add (struct backtrace_state *state, const char *filename, int descriptor,
off_t offset, const unsigned char *match_uuid, off_t offset, const unsigned char *match_uuid,
uintptr_t base_address, int skip_symtab, struct libbacktrace_base_address base_address, int skip_symtab,
backtrace_error_callback error_callback, void *data, backtrace_error_callback error_callback, void *data,
fileline *fileline_fn, int *found_sym) fileline *fileline_fn, int *found_sym)
{ {
@ -1242,7 +1247,7 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
c = _dyld_image_count (); c = _dyld_image_count ();
for (i = 0; i < c; ++i) for (i = 0; i < c; ++i)
{ {
uintptr_t base_address; struct libbacktrace_base_address base_address;
const char *name; const char *name;
int d; int d;
fileline mff; fileline mff;
@ -1266,7 +1271,7 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
continue; continue;
} }
base_address = _dyld_get_image_vmaddr_slide (i); base_address.m = _dyld_get_image_vmaddr_slide (i);
mff = macho_nodebug; mff = macho_nodebug;
if (!macho_add (state, name, d, 0, NULL, base_address, 0, if (!macho_add (state, name, d, 0, NULL, base_address, 0,
@ -1321,10 +1326,12 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
void *data, fileline *fileline_fn) void *data, fileline *fileline_fn)
{ {
fileline macho_fileline_fn; fileline macho_fileline_fn;
struct libbacktrace_base_address zero_base_address;
int found_sym; int found_sym;
macho_fileline_fn = macho_nodebug; macho_fileline_fn = macho_nodebug;
if (!macho_add (state, filename, descriptor, 0, NULL, 0, 0, memset (&zero_base_address, 0, sizeof zero_base_address);
if (!macho_add (state, filename, descriptor, 0, NULL, zero_base_address, 0,
error_callback, data, &macho_fileline_fn, &found_sym)) error_callback, data, &macho_fileline_fn, &found_sym))
return 0; return 0;

View File

@ -119,6 +119,7 @@
#define TracySetProgramName(x) #define TracySetProgramName(x)
#define TracyFiberEnter(x) #define TracyFiberEnter(x)
#define TracyFiberEnterHint(x,y)
#define TracyFiberLeave #define TracyFiberLeave
#else #else
@ -139,6 +140,7 @@
# define ZoneTransient( varname, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), nullptr, 0, TRACY_CALLSTACK, active ) # define ZoneTransient( varname, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), nullptr, 0, TRACY_CALLSTACK, active )
# define ZoneTransientN( varname, name, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), TRACY_CALLSTACK, active ) # define ZoneTransientN( varname, name, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), TRACY_CALLSTACK, active )
# define ZoneTransientNC( varname, name, color, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), color, TRACY_CALLSTACK, active )
#else #else
# define ZoneNamed( varname, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), active ) # define ZoneNamed( varname, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), active )
# define ZoneNamedN( varname, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), active ) # define ZoneNamedN( varname, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,TracyLine), active )
@ -147,6 +149,7 @@
# define ZoneTransient( varname, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), nullptr, 0, active ) # define ZoneTransient( varname, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), nullptr, 0, active )
# define ZoneTransientN( varname, name, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), active ) # define ZoneTransientN( varname, name, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), active )
# define ZoneTransientNC( varname, name, color, active ) tracy::ScopedZone varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), color, active )
#endif #endif
#define ZoneScoped ZoneNamed( ___tracy_scoped_zone, true ) #define ZoneScoped ZoneNamed( ___tracy_scoped_zone, true )
@ -287,7 +290,8 @@
#define TracySetProgramName( name ) tracy::GetProfiler().SetProgramName( name ); #define TracySetProgramName( name ) tracy::GetProfiler().SetProgramName( name );
#ifdef TRACY_FIBERS #ifdef TRACY_FIBERS
# define TracyFiberEnter( fiber ) tracy::Profiler::EnterFiber( fiber ) # define TracyFiberEnter( fiber ) tracy::Profiler::EnterFiber( fiber, 0 )
# define TracyFiberEnterHint( fiber, groupHint ) tracy::Profiler::EnterFiber( fiber, groupHint )
# define TracyFiberLeave tracy::Profiler::LeaveFiber() # define TracyFiberLeave tracy::Profiler::LeaveFiber()
#endif #endif

View File

@ -188,6 +188,13 @@ static tracy_force_inline void SendLuaCallstack( lua_State* L, uint32_t depth )
TracyQueueCommit( callstackAllocFatThread ); TracyQueueCommit( callstackAllocFatThread );
} }
static inline void LuaShortenSrc( char* dst, const char* src )
{
size_t l = std::min( (size_t)255, strlen( src ) );
memcpy( dst, src, l );
dst[l] = 0;
}
static inline int LuaZoneBeginS( lua_State* L ) static inline int LuaZoneBeginS( lua_State* L )
{ {
#ifdef TRACY_ON_DEMAND #ifdef TRACY_ON_DEMAND
@ -207,7 +214,9 @@ static inline int LuaZoneBeginS( lua_State* L )
lua_Debug dbg; lua_Debug dbg;
lua_getstack( L, 1, &dbg ); lua_getstack( L, 1, &dbg );
lua_getinfo( L, "Snl", &dbg ); lua_getinfo( L, "Snl", &dbg );
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src ); char src[256];
LuaShortenSrc( src, dbg.source );
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src );
TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLocCallstack ); TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLocCallstack );
MemWrite( &item->zoneBegin.time, Profiler::GetTime() ); MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
@ -237,8 +246,10 @@ static inline int LuaZoneBeginNS( lua_State* L )
lua_getstack( L, 1, &dbg ); lua_getstack( L, 1, &dbg );
lua_getinfo( L, "Snl", &dbg ); lua_getinfo( L, "Snl", &dbg );
size_t nsz; size_t nsz;
char src[256];
LuaShortenSrc( src, dbg.source );
const auto name = lua_tolstring( L, 1, &nsz ); const auto name = lua_tolstring( L, 1, &nsz );
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src, name, nsz ); const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src, name, nsz );
TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLocCallstack ); TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLocCallstack );
MemWrite( &item->zoneBegin.time, Profiler::GetTime() ); MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
@ -264,7 +275,9 @@ static inline int LuaZoneBegin( lua_State* L )
lua_Debug dbg; lua_Debug dbg;
lua_getstack( L, 1, &dbg ); lua_getstack( L, 1, &dbg );
lua_getinfo( L, "Snl", &dbg ); lua_getinfo( L, "Snl", &dbg );
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src ); char src[256];
LuaShortenSrc( src, dbg.source );
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src );
TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLoc ); TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLoc );
MemWrite( &item->zoneBegin.time, Profiler::GetTime() ); MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
@ -290,8 +303,10 @@ static inline int LuaZoneBeginN( lua_State* L )
lua_getstack( L, 1, &dbg ); lua_getstack( L, 1, &dbg );
lua_getinfo( L, "Snl", &dbg ); lua_getinfo( L, "Snl", &dbg );
size_t nsz; size_t nsz;
char src[256];
LuaShortenSrc( src, dbg.source );
const auto name = lua_tolstring( L, 1, &nsz ); const auto name = lua_tolstring( L, 1, &nsz );
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src, name, nsz ); const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src, name, nsz );
TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLoc ); TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLoc );
MemWrite( &item->zoneBegin.time, Profiler::GetTime() ); MemWrite( &item->zoneBegin.time, Profiler::GetTime() );

View File

@ -373,9 +373,9 @@ namespace tracy {
using TracyCLCtx = tracy::OpenCLCtx*; using TracyCLCtx = tracy::OpenCLCtx*;
#define TracyCLContext(context, device) tracy::CreateCLContext(context, device); #define TracyCLContext(ctx, device) tracy::CreateCLContext(ctx, device);
#define TracyCLDestroy(ctx) tracy::DestroyCLContext(ctx); #define TracyCLDestroy(ctx) tracy::DestroyCLContext(ctx);
#define TracyCLContextName(context, name, size) ctx->Name(name, size); #define TracyCLContextName(ctx, name, size) ctx->Name(name, size);
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK #if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
# define TracyCLNamedZone(ctx, varname, name, active) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active ); # define TracyCLNamedZone(ctx, varname, name, active) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active );
# define TracyCLNamedZoneC(ctx, varname, name, color, active) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active ); # define TracyCLNamedZoneC(ctx, varname, name, color, active) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active );

View File

@ -218,7 +218,9 @@ public:
WriteInitialItem( physdev, tcpu, tgpu ); WriteInitialItem( physdev, tcpu, tgpu );
m_res = (int64_t*)tracy_malloc( sizeof( int64_t ) * m_queryCount ); // We need the buffer to be twice as large for availability values
size_t resSize = sizeof( int64_t ) * m_queryCount * 2;
m_res = (int64_t*)tracy_malloc( resSize );
} }
#endif #endif
@ -283,17 +285,22 @@ public:
} }
if( VK_FUNCTION_WRAPPER( vkGetQueryPoolResults( m_device, m_query, wrappedTail, cnt, sizeof( int64_t ) * m_queryCount, m_res, sizeof( int64_t ), VK_QUERY_RESULT_64_BIT ) == VK_NOT_READY ) ) VK_FUNCTION_WRAPPER( vkGetQueryPoolResults( m_device, m_query, wrappedTail, cnt, sizeof( int64_t ) * m_queryCount * 2, m_res, sizeof( int64_t ) * 2, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT ) );
{
m_oldCnt = cnt;
return;
}
for( unsigned int idx=0; idx<cnt; idx++ ) for( unsigned int idx=0; idx<cnt; idx++ )
{ {
int64_t avail = m_res[idx * 2 + 1];
if( avail == 0 )
{
m_oldCnt = cnt - idx;
cnt = idx;
break;
}
auto item = Profiler::QueueSerial(); auto item = Profiler::QueueSerial();
MemWrite( &item->hdr.type, QueueType::GpuTime ); MemWrite( &item->hdr.type, QueueType::GpuTime );
MemWrite( &item->gpuTime.gpuTime, m_res[idx] ); MemWrite( &item->gpuTime.gpuTime, m_res[idx * 2] );
MemWrite( &item->gpuTime.queryId, uint16_t( wrappedTail + idx ) ); MemWrite( &item->gpuTime.queryId, uint16_t( wrappedTail + idx ) );
MemWrite( &item->gpuTime.context, m_context ); MemWrite( &item->gpuTime.context, m_context );
Profiler::QueueSerialFinish(); Profiler::QueueSerialFinish();
@ -410,11 +417,11 @@ private:
}; };
uint64_t ts[2]; uint64_t ts[2];
uint64_t deviation[NumProbes]; uint64_t deviation[NumProbes];
for( int i=0; i<NumProbes; i++ ) { for( size_t i=0; i<NumProbes; i++ ) {
m_vkGetCalibratedTimestampsEXT( m_device, 2, spec, ts, deviation + i ); m_vkGetCalibratedTimestampsEXT( m_device, 2, spec, ts, deviation + i );
} }
uint64_t minDeviation = deviation[0]; uint64_t minDeviation = deviation[0];
for( int i=1; i<NumProbes; i++ ) { for( size_t i=1; i<NumProbes; i++ ) {
if ( minDeviation > deviation[i] ) { if ( minDeviation > deviation[i] ) {
minDeviation = deviation[i]; minDeviation = deviation[i];
} }