mirror of
https://github.com/wolfpld/tracy
synced 2025-04-29 04:23:51 +00:00
Batch addr2line calls per 1024 addresses and escape paths
addr2line starts failing when given too many addresses to resolve. Batching per 1024 addresses allows not only to see progress but also fixes resolution for images with high number of addresses to resolve. Escaping is also required when image paths have spaces for example.
This commit is contained in:
parent
9074461ffb
commit
f02c6fe4d5
@ -44,57 +44,102 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void escapeShellParam(std::string const& s, std::string& out)
|
||||||
|
{
|
||||||
|
out.reserve( s.size() + 2 );
|
||||||
|
out.push_back( '"' );
|
||||||
|
for( unsigned char c : s )
|
||||||
|
{
|
||||||
|
if( ' ' <= c and c <= '~' and c != '\\' and c != '"' )
|
||||||
|
{
|
||||||
|
out.push_back( c );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.push_back( '\\' );
|
||||||
|
switch( c )
|
||||||
|
{
|
||||||
|
case '"': out.push_back( '"' ); break;
|
||||||
|
case '\\': out.push_back( '\\' ); break;
|
||||||
|
case '\t': out.push_back( 't' ); break;
|
||||||
|
case '\r': out.push_back( 'r' ); break;
|
||||||
|
case '\n': out.push_back( 'n' ); break;
|
||||||
|
default:
|
||||||
|
char const* const hexdig = "0123456789ABCDEF";
|
||||||
|
out.push_back( 'x' );
|
||||||
|
out.push_back( hexdig[c >> 4] );
|
||||||
|
out.push_back( hexdig[c & 0xF] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.push_back( '"' );
|
||||||
|
}
|
||||||
|
|
||||||
bool ResolveSymbols( const std::string& imagePath, const FrameEntryList& inputEntryList,
|
bool ResolveSymbols( const std::string& imagePath, const FrameEntryList& inputEntryList,
|
||||||
SymbolEntryList& resolvedEntries )
|
SymbolEntryList& resolvedEntries )
|
||||||
{
|
{
|
||||||
if (!m_addr2LinePath.length()) return false;
|
if( !m_addr2LinePath.length() ) return false;
|
||||||
|
|
||||||
|
std:: string escapedPath;
|
||||||
|
escapeShellParam( imagePath, escapedPath );
|
||||||
|
|
||||||
// generate a single addr2line cmd line for all addresses in one invocation
|
size_t entryIdx = 0;
|
||||||
std::stringstream ss;
|
while( entryIdx < inputEntryList.size() )
|
||||||
ss << m_addr2LinePath << " -C -f -e " << imagePath << " -a ";
|
|
||||||
for ( const FrameEntry& entry : inputEntryList )
|
|
||||||
{
|
{
|
||||||
ss << " 0x" << std::hex << entry.symbolOffset;
|
const size_t startIdx = entryIdx;
|
||||||
}
|
const size_t batchEndIdx = std::min( inputEntryList.size(), startIdx + (size_t)1024 );
|
||||||
|
|
||||||
std::string resultStr = ExecShellCommand( ss.str().c_str() );
|
printf( "Resolving symbols [%zu-%zu[\n", startIdx, batchEndIdx );
|
||||||
std::stringstream result(resultStr);
|
|
||||||
//printf("executing: '%s' got '%s'\n", ss.str().c_str(), result.str().c_str());
|
|
||||||
|
|
||||||
// The output is 2 lines per entry with the following contents:
|
// generate a single addr2line cmd line for all addresses in one invocation
|
||||||
// hex_address_of_symbol
|
std::stringstream ss;
|
||||||
// symbol_name
|
ss << m_addr2LinePath << " -C -f -e " << escapedPath << " -a ";
|
||||||
// file:line
|
for( ; entryIdx < batchEndIdx; entryIdx++ )
|
||||||
|
|
||||||
for( size_t i = 0; i < inputEntryList.size(); ++i )
|
|
||||||
{
|
|
||||||
const FrameEntry& inputEntry = inputEntryList[i];
|
|
||||||
|
|
||||||
SymbolEntry newEntry;
|
|
||||||
|
|
||||||
std::string addr;
|
|
||||||
std::getline( result, addr );
|
|
||||||
std::getline( result, newEntry.name );
|
|
||||||
if (newEntry.name == "??")
|
|
||||||
{
|
{
|
||||||
newEntry.name = "[unknown] + " + std::to_string(inputEntry.symbolOffset);
|
const FrameEntry& entry = inputEntryList[entryIdx];
|
||||||
|
ss << " 0x" << std::hex << entry.symbolOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fileLine;
|
std::string resultStr = ExecShellCommand( ss.str().c_str() );
|
||||||
std::getline(result, fileLine);
|
std::stringstream result( resultStr );
|
||||||
if ( fileLine != "??:?" )
|
|
||||||
|
//printf("executing: '%s' got '%s'\n", ss.str().c_str(), result.str().c_str());
|
||||||
|
|
||||||
|
// The output is 2 lines per entry with the following contents:
|
||||||
|
// hex_address_of_symbol
|
||||||
|
// symbol_name
|
||||||
|
// file:line
|
||||||
|
|
||||||
|
for( size_t i = startIdx ;i < batchEndIdx; i++ )
|
||||||
{
|
{
|
||||||
size_t pos = fileLine.find_last_of(':');
|
const FrameEntry& inputEntry = inputEntryList[i];
|
||||||
if ( pos != std::string::npos )
|
|
||||||
|
SymbolEntry newEntry;
|
||||||
|
|
||||||
|
std::string addr;
|
||||||
|
std::getline( result, addr );
|
||||||
|
std::getline( result, newEntry.name );
|
||||||
|
if( newEntry.name == "??" )
|
||||||
{
|
{
|
||||||
newEntry.file = fileLine.substr( 0, pos );
|
newEntry.name = "[unknown] + " + std::to_string( inputEntry.symbolOffset );
|
||||||
std::string lineStr = fileLine.substr( pos + 1 );
|
|
||||||
char* after = nullptr;
|
|
||||||
newEntry.line = strtol( lineStr.c_str(), &after, 10 );
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
resolvedEntries.push_back( std::move(newEntry) );
|
std::string fileLine;
|
||||||
|
std::getline( result, fileLine );
|
||||||
|
if( fileLine != "??:?" )
|
||||||
|
{
|
||||||
|
size_t pos = fileLine.find_last_of( ':' );
|
||||||
|
if( pos != std::string::npos )
|
||||||
|
{
|
||||||
|
newEntry.file = fileLine.substr( 0, pos );
|
||||||
|
std::string lineStr = fileLine.substr( pos + 1 );
|
||||||
|
char* after = nullptr;
|
||||||
|
newEntry.line = strtol( lineStr.c_str(), &after, 10 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvedEntries.push_back( std::move( newEntry ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user