From afcefc7855a19829e062b18897eddf88689f8dcc Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 11 May 2026 22:23:29 +0200 Subject: [PATCH] Add llm tool for getting disassembly + profiling data for a symbol. --- profiler/src/llm/tools.json | 17 +++++++++ profiler/src/profiler/TracyDisassembly.cpp | 41 ++++++++++++++++++++++ profiler/src/profiler/TracyDisassembly.hpp | 2 ++ profiler/src/profiler/TracyLlmChat.cpp | 5 +++ profiler/src/profiler/TracyLlmTools.cpp | 18 ++++++++++ profiler/src/profiler/TracyLlmTools.hpp | 1 + 6 files changed, 84 insertions(+) diff --git a/profiler/src/llm/tools.json b/profiler/src/llm/tools.json index 7df6ebf1..91ca13df 100644 --- a/profiler/src/llm/tools.json +++ b/profiler/src/llm/tools.json @@ -183,5 +183,22 @@ "required": ["query"] } } +}, +{ + "type": "function", + "function": { + "name": "symbol_disasm", + "description": "Get disassembly and profiling data for a symbol.", + "parameters": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Symbol name." + } + }, + "required": ["name"] + } + } } ] diff --git a/profiler/src/profiler/TracyDisassembly.cpp b/profiler/src/profiler/TracyDisassembly.cpp index 404ebf9e..d673961c 100644 --- a/profiler/src/profiler/TracyDisassembly.cpp +++ b/profiler/src/profiler/TracyDisassembly.cpp @@ -708,6 +708,47 @@ std::string FormatDisassemblyLine( const AsmLine& opcode, Worker& worker, std::v return line; } +nlohmann::json JsonDisassembly( uint64_t symAddr, Worker& worker, const View& view ) +{ + auto sym = worker.GetSymbolData( symAddr ); + if( !sym ) return nlohmann::json { { "error", "Symbol not found" } }; + if( sym->isInline ) return nlohmann::json { { "error", "Symbol is inline" } }; + + auto data = Disassemble( symAddr, worker ); + if( data.lines.empty() ) return nlohmann::json { { "error", "Disassembly failed" } }; + + const bool limitView = view.m_statRange.active; + AddrStatData as; + GatherIpStats( symAddr, as, worker, limitView, view, nullptr, false ); + auto iptr = worker.GetInlineSymbolList( symAddr, data.codeLen ); + if( iptr ) + { + const auto symEnd = symAddr + data.codeLen; + while( *iptr < symEnd ) + { + GatherIpStats( *iptr, as, worker, limitView, view, nullptr, false ); + iptr++; + } + } + GatherAdditionalIpStats( symAddr, as, worker, limitView, view, nullptr, false ); + + nlohmann::json json = { + { "address", symAddr }, + { "files", nlohmann::json::object() }, + { "hint", "Code lines format is: fileIdx:line:offset:cost:callCost:assembly. To decode file names, access files[fileIdx]." }, + { "symbol", worker.GetString( sym->name ) } + }; + + std::vector sources; + std::string code; + + for( auto& v: data.lines ) code += FormatDisassemblyLine( v, worker, sources, symAddr, as, data.locMap ) + "\n"; + json["code"] = code; + for( size_t i = 0; i < sources.size(); ++i ) json["files"][std::to_string(i)] = sources[i]; + + return json; +} + void GatherIpStats( uint64_t baseAddr, AddrStatData& as, const Worker& worker, bool limitView, const View& view, const char* filename, bool propagateInlines ) { if( limitView ) diff --git a/profiler/src/profiler/TracyDisassembly.hpp b/profiler/src/profiler/TracyDisassembly.hpp index 16e0f1b3..58eea6ad 100644 --- a/profiler/src/profiler/TracyDisassembly.hpp +++ b/profiler/src/profiler/TracyDisassembly.hpp @@ -1,6 +1,7 @@ #ifndef __TRACYDISASSEMBLY_HPP__ #define __TRACYDISASSEMBLY_HPP__ +#include #include #include #include @@ -134,6 +135,7 @@ struct AddrStatData DisasmData Disassemble( uint64_t symAddr, const Worker& worker ); std::string FormatDisassemblyLine( const AsmLine& opcode, Worker& worker, std::vector& sources, uint64_t symAddr, const AddrStatData& as, const unordered_flat_map& locMap ); +nlohmann::json JsonDisassembly( uint64_t symAddr, Worker& worker, const View& view ); void GatherIpStats( uint64_t baseAddr, AddrStatData& as, const Worker& worker, bool limitView, const View& view, const char* filename, bool propagateInlines ); void GatherAdditionalIpStats( uint64_t baseAddr, AddrStatData& as, const Worker& worker, bool limitView, const View& view, const char* filename, bool propagateInlines ); diff --git a/profiler/src/profiler/TracyLlmChat.cpp b/profiler/src/profiler/TracyLlmChat.cpp index 0bef45d9..f735a9be 100644 --- a/profiler/src/profiler/TracyLlmChat.cpp +++ b/profiler/src/profiler/TracyLlmChat.cpp @@ -137,6 +137,11 @@ std::string TracyLlmChat::ToolCallDescription( const nlohmann::json& json ) cons if( it == m_skills.end() ) return ""; return "Learn skill: " + it->description; } + else if( name == "symbol_disasm" ) + { + if( !args.contains( "name" ) ) return ""; + return "Disassemble symbol: " + args["name"].get_ref(); + } return ""; } diff --git a/profiler/src/profiler/TracyLlmTools.cpp b/profiler/src/profiler/TracyLlmTools.cpp index 07b1da14..2eb84f30 100644 --- a/profiler/src/profiler/TracyLlmTools.cpp +++ b/profiler/src/profiler/TracyLlmTools.cpp @@ -10,6 +10,7 @@ #include #include "TracyConfig.hpp" +#include "TracyDisassembly.hpp" #include "TracyLlm.hpp" #include "TracyLlmApi.hpp" #include "TracyLlmTools.hpp" @@ -189,6 +190,10 @@ std::string TracyLlmTools::HandleToolCalls( const std::string& tool, const nlohm { return GetSkill( Param( "name" ) ); } + else if( tool == "symbol_disasm" ) + { + return SymbolDisasm( Param( "name" ) ); + } return "Unknown tool call: " + tool; } catch( const std::exception& e ) @@ -1022,4 +1027,17 @@ std::string TracyLlmTools::GetSkill( const std::string& name ) const return it->content; } +std::string TracyLlmTools::SymbolDisasm( const std::string& name ) const +{ + for( auto& v : m_worker.GetSymbolMap() ) + { + if( strcmp( m_worker.GetString( v.second.name ), name.c_str() ) == 0 ) + { + auto json = JsonDisassembly( v.first, m_worker, m_view ); + return json.dump( -1, ' ', false, nlohmann::json::error_handler_t::replace ); + } + } + return "Symbol not found."; +} + } diff --git a/profiler/src/profiler/TracyLlmTools.hpp b/profiler/src/profiler/TracyLlmTools.hpp index 587f15e1..5c8938ca 100644 --- a/profiler/src/profiler/TracyLlmTools.hpp +++ b/profiler/src/profiler/TracyLlmTools.hpp @@ -65,6 +65,7 @@ private: std::string SourceFile( const std::string& file, uint32_t line, uint32_t context, uint32_t contextBack ) const; std::string SourceSearch( std::string query, bool caseInsensitive, const std::string& path ) const; std::string GetSkill( const std::string& name ) const; + std::string SymbolDisasm( const std::string& name ) const; void ManualEmbeddingsWorker( TracyLlmApi& api );