Add llm tool for getting disassembly + profiling data for a symbol.

This commit is contained in:
Bartosz Taudul
2026-05-11 22:23:29 +02:00
parent 22ec55f1d5
commit afcefc7855
6 changed files with 84 additions and 0 deletions

View File

@@ -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"]
}
}
}
]

View File

@@ -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<std::string> 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 )

View File

@@ -1,6 +1,7 @@
#ifndef __TRACYDISASSEMBLY_HPP__
#define __TRACYDISASSEMBLY_HPP__
#include <nlohmann/json.hpp>
#include <stdint.h>
#include <string>
#include <vector>
@@ -134,6 +135,7 @@ struct AddrStatData
DisasmData Disassemble( uint64_t symAddr, const Worker& worker );
std::string FormatDisassemblyLine( const AsmLine& opcode, Worker& worker, std::vector<std::string>& sources, uint64_t symAddr, const AddrStatData& as, const unordered_flat_map<uint64_t, uint32_t>& 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 );

View File

@@ -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<const std::string&>();
}
return "";
}

View File

@@ -10,6 +10,7 @@
#include <regex>
#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.";
}
}

View File

@@ -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 );