Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions plugin/att/code_printing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ CodeObjDecoderComponent::CodeObjDecoderComponent(
Dwarf_Off cu_offset{0}, next_offset;
size_t header_size;

std::unordered_set<uint64_t> used_addrs;
std::map<uint64_t, std::string> used_addrs;

while (!dwarf_nextcu(dbg.get(), cu_offset, &next_offset, &header_size, nullptr, nullptr,
nullptr)) {
Expand All @@ -142,32 +142,33 @@ CodeObjDecoderComponent::CodeObjDecoderComponent(

if (used_addrs.find(addr) != used_addrs.end())
{
size_t pos = m_line_number_map.lower_bound(addr);
m_line_number_map.data()[pos].str += ' ' + dwarf_line;
used_addrs.at(addr) += ' ' + dwarf_line;
continue;
}

used_addrs.insert(addr);
m_line_number_map.insert(DSourceLine{addr, 0, std::move(dwarf_line)});
used_addrs.emplace(addr, std::move(dwarf_line));
}
}
cu_offset = next_offset;
}
}

// Can throw
disassembly = std::make_unique<DisassemblyInstance>(codeobj_data, codeobj_size, gpu_id);
if (m_line_number_map.size())
{
size_t total_size = 0;
for (size_t i=0; i<m_line_number_map.size()-1; i++)
auto it = used_addrs.begin();
if(it != used_addrs.end())
{
size_t s = m_line_number_map.get(i+1).vaddr - m_line_number_map.get(i).vaddr;
m_line_number_map.data()[i].size = s;
total_size += s;
while(std::next(it) != used_addrs.end())
{
uint64_t delta = std::next(it)->first - it->first;
auto segment = address_range_t{it->first, delta, 0};
m_line_number_map.emplace(segment, std::move(it->second));
it++;
}
auto segment = address_range_t{it->first, codeobj_size - it->first, 0};
m_line_number_map.emplace(segment, std::move(it->second));
}
m_line_number_map.back().size = std::max(total_size, codeobj_size) - total_size;
}

// Can throw
disassembly = std::make_unique<DisassemblyInstance>(codeobj_data, codeobj_size, gpu_id);
try {
m_symbol_map = disassembly->GetKernelMap(); // Can throw
} catch(...) {}
Expand Down Expand Up @@ -209,10 +210,8 @@ CodeObjDecoderComponent::disassemble_instruction(uint64_t faddr, uint64_t vaddr)

const char* cpp_line = nullptr;

try {
const DSourceLine& it = m_line_number_map.find_obj(vaddr);
cpp_line = it.str.data();
} catch(...) {}
auto it = m_line_number_map.find({vaddr, 0, 0});
if(it != m_line_number_map.end()) cpp_line = it->second.data();

size_t size = disassembly->ReadInstruction(faddr, vaddr, cpp_line);
return {disassembly->last_instruction, size};
Expand Down
8 changes: 4 additions & 4 deletions plugin/att/code_printing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class CodeObjDecoderComponent

int m_fd;

cached_ordered_vector<DSourceLine> m_line_number_map;
std::map<address_range_t, std::string> m_line_number_map{};
std::map<uint64_t, SymbolInfo> m_symbol_map{};

std::string m_uri;
Expand Down Expand Up @@ -176,7 +176,7 @@ class CodeobjTableTranslation : protected CodeobjList
{
this->Super::addDecoder(filepath, id, loadbase, memsize, gpu_id);
auto ptr = decoders.at(id);
table.insert({ptr->begin(), static_cast<uint32_t>(ptr->size()), id, 0});
table.insert(address_range_t{ptr->begin(), static_cast<uint32_t>(ptr->size()), id});
}

virtual bool removeDecoder(uint32_t id, uint64_t loadbase)
Expand All @@ -186,8 +186,8 @@ class CodeobjTableTranslation : protected CodeobjList

instruction_info_t get(uint64_t vaddr)
{
auto& addr_range = table.find_codeobj_in_range(vaddr);
return get(addr_range.id, vaddr - addr_range.vbegin);
auto addr_range = table.find_codeobj_in_range(vaddr);
return get(addr_range.id, vaddr - addr_range.addr);
}
instruction_info_t get(uint32_t id, uint64_t offset) { return this->Super::get(id, offset); }

Expand Down
6 changes: 4 additions & 2 deletions plugin/att/disassembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@ std::optional<uint64_t> DisassemblyInstance::va2fo(uint64_t va)

CHECK_VA2FO(
e_ident[EI_ABIVERSION] == 2 || // ELFABIVERSION_AMDGPU_HSA_V4
e_ident[EI_ABIVERSION] == 3, "unexpected ei_abiversion"); // ELFABIVERSION_AMDGPU_HSA_V5
e_ident[EI_ABIVERSION] == 3 || // ELFABIVERSION_AMDGPU_HSA_V5
e_ident[EI_ABIVERSION] == 4, "unexpected ei_abiversion"); // ELFABIVERSION_AMDGPU_HSA_V6

Elf64_Ehdr *ehdr = (Elf64_Ehdr*)buffer.data();
CHECK_VA2FO(ehdr, "ehdr is nullptr");
Expand Down Expand Up @@ -356,7 +357,8 @@ std::vector<std::pair<uint64_t, uint64_t>> DisassemblyInstance::getSegments()

CHECK_VA2FO(
e_ident[EI_ABIVERSION] == 2 || // ELFABIVERSION_AMDGPU_HSA_V4
e_ident[EI_ABIVERSION] == 3, "unexpected ei_abiversion"); // ELFABIVERSION_AMDGPU_HSA_V5
e_ident[EI_ABIVERSION] == 3 || // ELFABIVERSION_AMDGPU_HSA_V5
e_ident[EI_ABIVERSION] == 4, "unexpected ei_abiversion"); // ELFABIVERSION_AMDGPU_HSA_V6

Elf64_Ehdr *ehdr = (Elf64_Ehdr*)buffer.data();
CHECK_VA2FO(ehdr, "ehdr is nullptr");
Expand Down
157 changes: 40 additions & 117 deletions plugin/att/segment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,132 +23,55 @@
#include <vector>
#include <iostream>
#include <random>
#include <unordered_set>
#include <set>
#include <algorithm>

template<typename Type>
class ordered_vector : public std::vector<Type>
struct address_range_t
{
using Super = std::vector<Type>;
public:
void insert(const Type& elem)
{
size_t loc = lower_bound(elem.begin());
if (this->size() && get(loc).begin() < elem.begin())
loc ++;
this->Super::insert(this->begin()+loc, elem);
}
bool remove(const Type& elem)
{
if (!this->size()) return false;
size_t loc = lower_bound(elem.begin());
if (get(loc) != elem) return false;

this->Super::erase(this->begin()+loc);
return true;
}
bool remove(uint64_t elem_begin)
{
if (!this->size()) return false;
size_t loc = lower_bound(elem_begin);
if (get(loc).begin() != elem_begin) return false;

this->Super::erase(this->begin()+loc);
return true;
}
size_t lower_bound(size_t addr) const
{
if (!this->size()) return 0;
return binary_search(addr, 0, this->size()-1);
}

size_t binary_search(size_t addr, size_t s, size_t e) const
{
if (s >= e)
return s;
else if (s+1 == e)
return (get(e).begin() <= addr) ? e : s;

size_t mid = (s+e)/2;
if (get(mid).begin() <= addr)
return binary_search(addr, mid, e);
else
return binary_search(addr, s, mid);
}
const Type& get(size_t i) const { return this->operator[](i); }
uint64_t addr{0};
uint64_t size{0};
uint64_t id{0};

bool operator==(const address_range_t& other) const
{
return (addr >= other.addr && addr < other.addr + other.size) ||
(other.addr >= addr && other.addr < addr + size);
}
bool operator<(const address_range_t& other) const
{
if(*this == other) return false;
return addr < other.addr;
}
bool inrange(uint64_t _addr) const { return addr <= _addr && addr + size > _addr; };
};

/**
* @brief Finds a candidate codeobj for the given vaddr
*/
template<typename Type>
class cached_ordered_vector : public ordered_vector<Type>
*/
class CodeobjTableTranslator : public std::set<address_range_t>
{
using Super = ordered_vector<Type>;
public:
cached_ordered_vector<Type>() { reset(); }

const Type& find_obj(uint64_t addr)
{
if (testCache(addr))
return get(cached_segment);

size_t lb = this->lower_bound(addr);
if (lb >= this->size() || !get(lb).inrange(addr))
throw std::string("segment addr out of range");

cached_segment = lb;
return get(cached_segment);
}

uint64_t find_addr(uint64_t addr) {
return find_obj(addr).begin();
}

bool testCache(uint64_t addr) const {
return this->cached_segment < this->size() && get(cached_segment).inrange(addr);
}

const Type& get(size_t index) const { return this->data()[index]; }

void insert(const Type& elem) { this->Super::insert(elem); }
void insert_list(std::vector<Type> arange)
{
for (auto& elem : arange) push_back(elem);
std::sort(
this->begin(),
this->end(),
[](const Type& a, const Type& b) { return a.begin() < b.begin(); }
);
};
using Super = std::set<address_range_t>;

void reset() { cached_segment = ~0; }
void clear() { reset(); this->Super::clear(); }
bool remove(uint64_t addr) { reset(); return this->Super::remove(addr); }
public:
address_range_t find_codeobj_in_range(uint64_t addr)
{
if(!cached_segment.inrange(addr))
{
auto it = this->find(address_range_t{addr, 0, 0});
if(it == this->end()) throw std::exception();
cached_segment = *it;
}
return cached_segment;
}

void clear_cache() { cached_segment = {}; }
bool remove(const address_range_t& range)
{
clear_cache();
return this->erase(range) != 0;
}
bool remove(uint64_t addr) { return remove(address_range_t{addr, 0, 0}); }

private:
size_t cached_segment = ~0;
};


struct address_range_t
{
uint64_t vbegin;
uint32_t size;
uint32_t id;
uint32_t offset;

bool operator<(const address_range_t& other) const { return vbegin < other.vbegin; }
bool inrange(uint64_t addr) const { return addr >= vbegin && addr < vbegin+size; };
uint64_t begin() const { return vbegin; }
};


/**
* @brief Finds a candidate codeobj for the given vaddr
*/
class CodeobjTableTranslator : public cached_ordered_vector<address_range_t>
{
public:
const address_range_t& find_codeobj_in_range(uint64_t addr) { return this->find_obj(addr); }
address_range_t cached_segment{};
};
2 changes: 1 addition & 1 deletion plugin/att/stitch.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def try_match_swapped(self, i, line, increment):
class PCTranslator:
def __init__(self, insts, code, raw_code, reverse_map, codeservice):
self.codeservice = codeservice

self.insts = insts
self.addrmap = {c[-3] : (c, self.codeservice.GetInstruction(c[-3])[3]) for c in code if c[-3] > 0}

Expand Down