mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-26 16:04:34 +00:00
Display disassembly.
This commit is contained in:
parent
b091c0d4a8
commit
4f417854e5
@ -9,17 +9,23 @@
|
||||
#include "TracySourceView.hpp"
|
||||
#include "TracyWorker.hpp"
|
||||
|
||||
#ifdef TRACY_EXTENDED_FONT
|
||||
# include "IconsFontAwesome5.h"
|
||||
#endif
|
||||
|
||||
namespace tracy
|
||||
{
|
||||
|
||||
SourceView::SourceView( ImFont* font )
|
||||
: m_font( font )
|
||||
, m_file( nullptr )
|
||||
, m_targetAddr( 0 )
|
||||
, m_symAddr( 0 )
|
||||
, m_data( nullptr )
|
||||
, m_dataSize( 0 )
|
||||
, m_targetLine( 0 )
|
||||
, m_selectedLine( 0 )
|
||||
, m_showAsm( false )
|
||||
{
|
||||
}
|
||||
|
||||
@ -32,6 +38,7 @@ void SourceView::Open( const char* fileName, int line, uint64_t symAddr, const W
|
||||
{
|
||||
m_targetLine = line;
|
||||
m_selectedLine = line;
|
||||
m_targetAddr = symAddr;
|
||||
m_symAddr = symAddr;
|
||||
|
||||
if( m_file != fileName )
|
||||
@ -71,15 +78,20 @@ void SourceView::Open( const char* fileName, int line, uint64_t symAddr, const W
|
||||
if( *end == '\0' ) break;
|
||||
txt = end;
|
||||
}
|
||||
}
|
||||
|
||||
if( !Disassemble( symAddr, worker ) ) m_showAsm = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SourceView::Disassemble( uint64_t symAddr, const Worker& worker )
|
||||
{
|
||||
m_asm.clear();
|
||||
if( symAddr == 0 ) return;
|
||||
if( symAddr == 0 ) return false;
|
||||
const auto arch = worker.GetCpuArch();
|
||||
if( arch == CpuArchUnknown ) return;
|
||||
if( arch == CpuArchUnknown ) return false;
|
||||
uint32_t len;
|
||||
auto code = worker.GetSymbolCode( symAddr, len );
|
||||
if( !code ) return;
|
||||
if( !code ) return false;
|
||||
csh handle;
|
||||
cs_err rval;
|
||||
switch( arch )
|
||||
@ -100,7 +112,7 @@ void SourceView::Open( const char* fileName, int line, uint64_t symAddr, const W
|
||||
assert( false );
|
||||
break;
|
||||
}
|
||||
if( rval != CS_ERR_OK ) return;
|
||||
if( rval != CS_ERR_OK ) return false;
|
||||
cs_insn* insn;
|
||||
size_t cnt = cs_disasm( handle, (const uint8_t*)code, len, symAddr, 0, &insn );
|
||||
if( cnt > 0 )
|
||||
@ -113,81 +125,163 @@ void SourceView::Open( const char* fileName, int line, uint64_t symAddr, const W
|
||||
cs_free( insn, cnt );
|
||||
}
|
||||
cs_close( &handle );
|
||||
return true;
|
||||
}
|
||||
|
||||
void SourceView::Render( const Worker& worker )
|
||||
{
|
||||
uint32_t iptotal = 0;
|
||||
unordered_flat_map<uint32_t, uint32_t> ipcount;
|
||||
unordered_flat_map<uint64_t, uint32_t> ipcount;
|
||||
auto ipmap = m_symAddr != 0 ? worker.GetSymbolInstructionPointers( m_symAddr ) : nullptr;
|
||||
if( ipmap )
|
||||
{
|
||||
for( auto& ip : *ipmap )
|
||||
if( !m_asm.empty() )
|
||||
{
|
||||
auto frame = worker.GetCallstackFrame( ip.first );
|
||||
if( frame )
|
||||
#ifdef TRACY_EXTENDED_FONT
|
||||
if( SmallCheckbox( ICON_FA_MICROCHIP " Show assembly", &m_showAsm ) )
|
||||
#else
|
||||
if( SmallCheckbox( "Show assembly", &m_showAsm ) )
|
||||
#endif
|
||||
{
|
||||
auto ffn = worker.GetString( frame->data[0].file );
|
||||
if( strcmp( ffn, m_file ) == 0 )
|
||||
if( m_showAsm )
|
||||
{
|
||||
const auto line = frame->data[0].line;
|
||||
auto it = ipcount.find( line );
|
||||
if( it == ipcount.end() )
|
||||
m_targetAddr = m_symAddr;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_targetLine = m_selectedLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( m_showAsm )
|
||||
{
|
||||
for( auto& ip : *ipmap )
|
||||
{
|
||||
auto addr = worker.GetCanonicalPointer( ip.first );
|
||||
assert( ipcount.find( addr ) == ipcount.end() );
|
||||
ipcount.emplace( addr, ip.second );
|
||||
iptotal += ip.second;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( auto& ip : *ipmap )
|
||||
{
|
||||
auto frame = worker.GetCallstackFrame( ip.first );
|
||||
if( frame )
|
||||
{
|
||||
auto ffn = worker.GetString( frame->data[0].file );
|
||||
if( strcmp( ffn, m_file ) == 0 )
|
||||
{
|
||||
ipcount.emplace( line, ip.second );
|
||||
const auto line = frame->data[0].line;
|
||||
auto it = ipcount.find( line );
|
||||
if( it == ipcount.end() )
|
||||
{
|
||||
ipcount.emplace( line, ip.second );
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second += ip.second;
|
||||
}
|
||||
iptotal += ip.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second += ip.second;
|
||||
}
|
||||
iptotal += ip.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto sym = worker.GetSymbolData( m_symAddr );
|
||||
if( sym )
|
||||
{
|
||||
TextFocused( "Showing profiling data for:", worker.GetString( sym->name ) );
|
||||
if( !m_asm.empty() )
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
}
|
||||
TextFocused( "Samples:", RealToString( iptotal ) );
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled( "(%" PRIu32 " samples)", iptotal );
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Symbol:", worker.GetString( sym->name ) );
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::BeginChild( "##sourceView", ImVec2( 0, 0 ), true );
|
||||
if( m_font ) ImGui::PushFont( m_font );
|
||||
const auto nw = ImGui::CalcTextSize( "123,345" ).x;
|
||||
if( m_targetLine != 0 )
|
||||
if( m_showAsm )
|
||||
{
|
||||
int lineNum = 1;
|
||||
for( auto& line : m_lines )
|
||||
if( m_targetAddr != 0 )
|
||||
{
|
||||
if( m_targetLine == lineNum )
|
||||
for( auto& line : m_asm )
|
||||
{
|
||||
m_targetLine = 0;
|
||||
ImGui::SetScrollHereY();
|
||||
if( m_targetAddr == line.addr )
|
||||
{
|
||||
m_targetAddr = 0;
|
||||
ImGui::SetScrollHereY();
|
||||
}
|
||||
RenderAsmLine( line, 0, iptotal );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGuiListClipper clipper( (int)m_asm.size() );
|
||||
while( clipper.Step() )
|
||||
{
|
||||
if( iptotal == 0 )
|
||||
{
|
||||
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
|
||||
{
|
||||
RenderAsmLine( m_asm[i], 0, 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
|
||||
{
|
||||
auto& line = m_asm[i];
|
||||
auto it = ipcount.find( line.addr );
|
||||
const auto ipcnt = it == ipcount.end() ? 0 : it->second;
|
||||
RenderAsmLine( line, ipcnt, iptotal );
|
||||
}
|
||||
}
|
||||
}
|
||||
RenderLine( line, lineNum++, 0, iptotal );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGuiListClipper clipper( m_lines.size() );
|
||||
while( clipper.Step() )
|
||||
if( m_targetLine != 0 )
|
||||
{
|
||||
if( iptotal == 0 )
|
||||
int lineNum = 1;
|
||||
for( auto& line : m_lines )
|
||||
{
|
||||
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
|
||||
if( m_targetLine == lineNum )
|
||||
{
|
||||
RenderLine( m_lines[i], i+1, 0, 0 );
|
||||
m_targetLine = 0;
|
||||
ImGui::SetScrollHereY();
|
||||
}
|
||||
RenderLine( line, lineNum++, 0, iptotal );
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGuiListClipper clipper( (int)m_lines.size() );
|
||||
while( clipper.Step() )
|
||||
{
|
||||
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
|
||||
if( iptotal == 0 )
|
||||
{
|
||||
auto it = ipcount.find( i+1 );
|
||||
const auto ipcnt = it == ipcount.end() ? 0 : it->second;
|
||||
RenderLine( m_lines[i], i+1, ipcnt, iptotal );
|
||||
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
|
||||
{
|
||||
RenderLine( m_lines[i], i+1, 0, 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
|
||||
{
|
||||
auto it = ipcount.find( i+1 );
|
||||
const auto ipcnt = it == ipcount.end() ? 0 : it->second;
|
||||
RenderLine( m_lines[i], i+1, ipcnt, iptotal );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -240,4 +334,54 @@ void SourceView::RenderLine( const Line& line, int lineNum, uint32_t ipcnt, uint
|
||||
draw->AddLine( wpos + ImVec2( 0, ty+2 ), wpos + ImVec2( w, ty+2 ), 0x08FFFFFF );
|
||||
}
|
||||
|
||||
void SourceView::RenderAsmLine( const AsmLine& line, uint32_t ipcnt, uint32_t iptotal )
|
||||
{
|
||||
const auto ty = ImGui::GetFontSize();
|
||||
auto draw = ImGui::GetWindowDrawList();
|
||||
const auto w = ImGui::GetWindowWidth();
|
||||
const auto wpos = ImGui::GetCursorScreenPos();
|
||||
if( line.addr == m_symAddr )
|
||||
{
|
||||
draw->AddRectFilled( wpos, wpos + ImVec2( w, ty+1 ), 0xFF333322 );
|
||||
}
|
||||
|
||||
if( iptotal != 0 )
|
||||
{
|
||||
if( ipcnt == 0 )
|
||||
{
|
||||
ImGui::TextUnformatted( " " );
|
||||
}
|
||||
else
|
||||
{
|
||||
char tmp[16];
|
||||
auto end = PrintFloat( tmp, tmp+16, 100.f * ipcnt / iptotal, 2 );
|
||||
memcpy( end, "%", 2 );
|
||||
end++;
|
||||
const auto sz = end - tmp;
|
||||
char buf[16];
|
||||
memset( buf, ' ', 7-sz );
|
||||
memcpy( buf + 7 - sz, tmp, sz+1 );
|
||||
ImGui::TextUnformatted( buf );
|
||||
}
|
||||
ImGui::SameLine( 0, ty );
|
||||
}
|
||||
|
||||
char buf[256];
|
||||
sprintf( buf, "%" PRIx64, line.addr );
|
||||
const auto asz = strlen( buf );
|
||||
memset( buf+asz, ' ', 16-asz );
|
||||
buf[16] = '\0';
|
||||
TextDisabledUnformatted( buf );
|
||||
ImGui::SameLine( 0, ty );
|
||||
|
||||
const auto msz = line.mnemonic.size();
|
||||
memcpy( buf, line.mnemonic.c_str(), msz );
|
||||
memset( buf+msz, ' ', 16-msz );
|
||||
memcpy( buf+16, line.operands.c_str(), line.operands.size() + 1 );
|
||||
ImGui::TextUnformatted( buf );
|
||||
|
||||
draw->AddLine( wpos + ImVec2( 0, ty+2 ), wpos + ImVec2( w, ty+2 ), 0x08FFFFFF );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -32,14 +32,19 @@ public:
|
||||
|
||||
private:
|
||||
void RenderLine( const Line& line, int lineNum, uint32_t ipcnt, uint32_t iptotal );
|
||||
void RenderAsmLine( const AsmLine& line, uint32_t ipcnt, uint32_t iptotal );
|
||||
|
||||
bool Disassemble( uint64_t symAddr, const Worker& worker );
|
||||
|
||||
ImFont* m_font;
|
||||
const char* m_file;
|
||||
uint64_t m_symAddr;
|
||||
uint64_t m_targetAddr;
|
||||
char* m_data;
|
||||
size_t m_dataSize;
|
||||
int m_targetLine;
|
||||
int m_selectedLine;
|
||||
bool m_showAsm;
|
||||
|
||||
std::vector<Line> m_lines;
|
||||
std::vector<AsmLine> m_asm;
|
||||
|
Loading…
Reference in New Issue
Block a user