diff --git a/server/TracySourceView.cpp b/server/TracySourceView.cpp index cbbb805c..aa15e2cc 100644 --- a/server/TracySourceView.cpp +++ b/server/TracySourceView.cpp @@ -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 ipcount; + unordered_flat_map 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; isecond; + 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; isecond; - RenderLine( m_lines[i], i+1, ipcnt, iptotal ); + for( auto i=clipper.DisplayStart; isecond; + 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 ); +} + + } diff --git a/server/TracySourceView.hpp b/server/TracySourceView.hpp index b7be9859..cba6afc5 100644 --- a/server/TracySourceView.hpp +++ b/server/TracySourceView.hpp @@ -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 m_lines; std::vector m_asm;