Calculate jump table.

This commit is contained in:
Bartosz Taudul 2020-04-04 02:25:12 +02:00
parent 27c125f23b
commit 3711a66592
2 changed files with 86 additions and 0 deletions

View File

@ -8,6 +8,7 @@
#include "TracyFilesystem.hpp"
#include "TracyImGui.hpp"
#include "TracyPrint.hpp"
#include "TracySort.hpp"
#include "TracySourceView.hpp"
#include "TracyWorker.hpp"
@ -100,6 +101,8 @@ void SourceView::Open( const char* fileName, int line, uint64_t baseAddr, uint64
bool SourceView::Disassemble( uint64_t symAddr, const Worker& worker )
{
m_asm.clear();
m_jumpTable.clear();
m_maxJumpLevel = 0;
if( symAddr == 0 ) return false;
const auto arch = worker.GetCpuArch();
if( arch == CpuArchUnknown ) return false;
@ -174,10 +177,81 @@ bool SourceView::Disassemble( uint64_t symAddr, const Worker& worker )
assert( false );
break;
}
if( jumpAddr != 0 )
{
const auto min = std::min( jumpAddr, op.address );
const auto max = std::max( jumpAddr, op.address );
auto it = m_jumpTable.find( jumpAddr );
if( it == m_jumpTable.end() )
{
m_jumpTable.emplace( jumpAddr, JumpData { min, max, 0, { op.address } } );
}
else
{
if( it->second.min > min ) it->second.min = min;
else if( it->second.max < max ) it->second.max = max;
it->second.source.emplace_back( op.address );
}
}
}
m_asm.emplace_back( AsmLine { op.address, jumpAddr, op.mnemonic, op.op_str } );
}
cs_free( insn, cnt );
if( !m_jumpTable.empty() )
{
struct JumpRange
{
uint64_t target;
uint64_t len;
};
std::vector<JumpRange> jumpRange;
jumpRange.reserve( m_jumpTable.size() );
for( auto& v : m_jumpTable )
{
pdqsort_branchless( v.second.source.begin(), v.second.source.end() );
jumpRange.emplace_back( JumpRange { v.first, v.second.max - v.second.min } );
}
pdqsort_branchless( jumpRange.begin(), jumpRange.end(), []( const auto& l, const auto& r ) { return l.len < r.len; } );
std::vector<std::vector<std::pair<uint64_t, uint64_t>>> levelRanges;
for( auto& v : jumpRange )
{
auto it = m_jumpTable.find( v.target );
assert( it != m_jumpTable.end() );
int level = 0;
for(;;)
{
assert( levelRanges.size() >= level );
if( levelRanges.size() == level )
{
it->second.level = level;
levelRanges.push_back( { { it->second.min, it->second.max } } );
break;
}
else
{
bool validFit = true;
auto& lr = levelRanges[level];
for( auto& range : lr )
{
assert( !( it->second.min >= range.first && it->second.max <= range.second ) );
if( it->second.min <= range.second && it->second.max >= range.first )
{
validFit = false;
break;
}
}
if( validFit )
{
it->second.level = level;
lr.emplace_back( it->second.min, it->second.max );
break;
}
level++;
}
}
if( level > m_maxJumpLevel ) m_maxJumpLevel = level;
}
}
}
cs_close( &handle );
m_codeLen = len;

View File

@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include "tracy_robin_hood.h"
#include "TracyDecayValue.hpp"
struct ImFont;
@ -29,6 +30,14 @@ class SourceView
std::string operands;
};
struct JumpData
{
uint64_t min;
uint64_t max;
int level;
std::vector<uint64_t> source;
};
public:
SourceView( ImFont* font );
~SourceView();
@ -61,6 +70,9 @@ private:
std::vector<Line> m_lines;
std::vector<AsmLine> m_asm;
unordered_flat_map<uint64_t, JumpData> m_jumpTable;
int m_maxJumpLevel;
};
}