1
0
mirror of https://github.com/wolfpld/tracy.git synced 2025-03-20 07:40:02 +08:00

Display disassembly.

This commit is contained in:
Bartosz Taudul 2020-03-25 22:53:05 +01:00
parent b091c0d4a8
commit 4f417854e5
2 changed files with 188 additions and 39 deletions

View File

@ -9,17 +9,23 @@
#include "TracySourceView.hpp" #include "TracySourceView.hpp"
#include "TracyWorker.hpp" #include "TracyWorker.hpp"
#ifdef TRACY_EXTENDED_FONT
# include "IconsFontAwesome5.h"
#endif
namespace tracy namespace tracy
{ {
SourceView::SourceView( ImFont* font ) SourceView::SourceView( ImFont* font )
: m_font( font ) : m_font( font )
, m_file( nullptr ) , m_file( nullptr )
, m_targetAddr( 0 )
, m_symAddr( 0 ) , m_symAddr( 0 )
, m_data( nullptr ) , m_data( nullptr )
, m_dataSize( 0 ) , m_dataSize( 0 )
, m_targetLine( 0 ) , m_targetLine( 0 )
, m_selectedLine( 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_targetLine = line;
m_selectedLine = line; m_selectedLine = line;
m_targetAddr = symAddr;
m_symAddr = symAddr; m_symAddr = symAddr;
if( m_file != fileName ) 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; if( *end == '\0' ) break;
txt = end; txt = end;
} }
if( !Disassemble( symAddr, worker ) ) m_showAsm = false;
}
} }
bool SourceView::Disassemble( uint64_t symAddr, const Worker& worker )
{
m_asm.clear(); m_asm.clear();
if( symAddr == 0 ) return; if( symAddr == 0 ) return false;
const auto arch = worker.GetCpuArch(); const auto arch = worker.GetCpuArch();
if( arch == CpuArchUnknown ) return; if( arch == CpuArchUnknown ) return false;
uint32_t len; uint32_t len;
auto code = worker.GetSymbolCode( symAddr, len ); auto code = worker.GetSymbolCode( symAddr, len );
if( !code ) return; if( !code ) return false;
csh handle; csh handle;
cs_err rval; cs_err rval;
switch( arch ) switch( arch )
@ -100,7 +112,7 @@ void SourceView::Open( const char* fileName, int line, uint64_t symAddr, const W
assert( false ); assert( false );
break; break;
} }
if( rval != CS_ERR_OK ) return; if( rval != CS_ERR_OK ) return false;
cs_insn* insn; cs_insn* insn;
size_t cnt = cs_disasm( handle, (const uint8_t*)code, len, symAddr, 0, &insn ); size_t cnt = cs_disasm( handle, (const uint8_t*)code, len, symAddr, 0, &insn );
if( cnt > 0 ) if( cnt > 0 )
@ -113,14 +125,45 @@ void SourceView::Open( const char* fileName, int line, uint64_t symAddr, const W
cs_free( insn, cnt ); cs_free( insn, cnt );
} }
cs_close( &handle ); cs_close( &handle );
return true;
} }
void SourceView::Render( const Worker& worker ) void SourceView::Render( const Worker& worker )
{ {
uint32_t iptotal = 0; 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; auto ipmap = m_symAddr != 0 ? worker.GetSymbolInstructionPointers( m_symAddr ) : nullptr;
if( ipmap ) if( ipmap )
{
if( !m_asm.empty() )
{
#ifdef TRACY_EXTENDED_FONT
if( SmallCheckbox( ICON_FA_MICROCHIP " Show assembly", &m_showAsm ) )
#else
if( SmallCheckbox( "Show assembly", &m_showAsm ) )
#endif
{
if( m_showAsm )
{
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 ) for( auto& ip : *ipmap )
{ {
@ -144,18 +187,68 @@ void SourceView::Render( const Worker& worker )
} }
} }
} }
}
auto sym = worker.GetSymbolData( m_symAddr ); auto sym = worker.GetSymbolData( m_symAddr );
if( sym ) if( sym )
{ {
TextFocused( "Showing profiling data for:", worker.GetString( sym->name ) ); if( !m_asm.empty() )
{
ImGui::SameLine(); ImGui::SameLine();
ImGui::TextDisabled( "(%" PRIu32 " samples)", iptotal ); ImGui::Spacing();
ImGui::SameLine();
}
TextFocused( "Samples:", RealToString( iptotal ) );
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
TextFocused( "Symbol:", worker.GetString( sym->name ) );
} }
} }
ImGui::BeginChild( "##sourceView", ImVec2( 0, 0 ), true ); ImGui::BeginChild( "##sourceView", ImVec2( 0, 0 ), true );
if( m_font ) ImGui::PushFont( m_font ); if( m_font ) ImGui::PushFont( m_font );
const auto nw = ImGui::CalcTextSize( "123,345" ).x; const auto nw = ImGui::CalcTextSize( "123,345" ).x;
if( m_showAsm )
{
if( m_targetAddr != 0 )
{
for( auto& line : m_asm )
{
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 );
}
}
}
}
}
else
{
if( m_targetLine != 0 ) if( m_targetLine != 0 )
{ {
int lineNum = 1; int lineNum = 1;
@ -171,7 +264,7 @@ void SourceView::Render( const Worker& worker )
} }
else else
{ {
ImGuiListClipper clipper( m_lines.size() ); ImGuiListClipper clipper( (int)m_lines.size() );
while( clipper.Step() ) while( clipper.Step() )
{ {
if( iptotal == 0 ) if( iptotal == 0 )
@ -192,6 +285,7 @@ void SourceView::Render( const Worker& worker )
} }
} }
} }
}
if( m_font ) ImGui::PopFont(); if( m_font ) ImGui::PopFont();
ImGui::EndChild(); ImGui::EndChild();
} }
@ -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 ); 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 );
}
} }

View File

@ -32,14 +32,19 @@ public:
private: private:
void RenderLine( const Line& line, int lineNum, uint32_t ipcnt, uint32_t iptotal ); 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; ImFont* m_font;
const char* m_file; const char* m_file;
uint64_t m_symAddr; uint64_t m_symAddr;
uint64_t m_targetAddr;
char* m_data; char* m_data;
size_t m_dataSize; size_t m_dataSize;
int m_targetLine; int m_targetLine;
int m_selectedLine; int m_selectedLine;
bool m_showAsm;
std::vector<Line> m_lines; std::vector<Line> m_lines;
std::vector<AsmLine> m_asm; std::vector<AsmLine> m_asm;