Symbol table

This commit is contained in:
Sajid 2024-09-08 08:32:31 +06:00
parent 36fb31de3a
commit 6d79935928
8 changed files with 186 additions and 48 deletions

View File

@ -4,9 +4,15 @@
int main()
{
// TODO: ELFs, symbols, sections, a lot
const auto file = LoadFile("add.elf");
const auto image = Image::ParseImage(file.data(), file.size()).value();
auto image = Image::ParseImage(file.data(), file.size()).value();
for (const auto& section : image.sections)
{
image.symbols.emplace(section.name, section.base, section.size, Symbol_Section);
}
image.symbols.emplace("_start", image.entry_point, 0x30, Symbol_Function);
for (const auto& section : image.sections)
{
@ -17,8 +23,6 @@ int main()
auto base = section.base;
const auto end = section.base + section.size;
ppc::SetDetail(true);
if (section.flags & SectionFlags_Code)
{
while(base < end)

View File

@ -1,5 +1,5 @@
project("PowerUtils")
add_library(PowerUtils "disasm.h" "disasm.cpp" "file.h" "xex.cpp" "image.h" "image.cpp" "elf.h")
add_library(PowerUtils "disasm.h" "disasm.cpp" "file.h" "xex.cpp" "image.h" "image.cpp" "elf.h" "ppc_context.h" "symbol.h" "symbol_table.h" "section.h")
target_include_directories(PowerUtils PUBLIC .)
target_link_libraries(PowerUtils PUBLIC capstone)

View File

@ -5,21 +5,19 @@
void Image::Map(const std::string_view& name, size_t base, uint32_t size, uint8_t flags, uint8_t* data)
{
sections.emplace_back(std::string(name), this->base + base,
sections.emplace(std::string(name), this->base + base,
size, static_cast<SectionFlags>(flags), data);
}
const void* Image::Find(size_t address) const
{
for (const auto& section : sections)
const auto section = sections.find(address);
if (section == sections.end())
{
if (section == address)
{
return section.data + (address - section.base);
}
return nullptr;
}
return nullptr;
return section->data + (address - section->base);
}
std::expected<Image, int> Image::ParseImage(const uint8_t* data, size_t size)
@ -44,6 +42,7 @@ Image ElfLoadImage(const uint8_t* data, size_t size)
Image image{};
image.size = size;
image.data = std::make_unique<uint8_t[]>(size);
image.entry_point = std::byteswap(header->e_entry);
memcpy(image.data.get(), data, size);
auto stringTableIndex = std::byteswap(header->e_shstrndx);
@ -58,7 +57,7 @@ Image ElfLoadImage(const uint8_t* data, size_t size)
{
if (psections[i].p_type == std::byteswap((Elf32_Word)PT_LOAD))
{
image.base = psections[i].p_vaddr;
image.base = std::byteswap(psections[i].p_vaddr);
break;
}
}
@ -68,7 +67,7 @@ Image ElfLoadImage(const uint8_t* data, size_t size)
for (size_t i = 0; i < numSections; i++)
{
const auto& section = sections[i];
if (section.sh_type == 0)
if (section.sh_type == 0 || section.sh_addr == 0)
{
continue;
}

View File

@ -1,16 +1,10 @@
#pragma once
#include <memory>
#include <string>
#include <vector>
#include <set>
#include <expected>
struct Section;
enum SectionFlags : uint8_t
{
SectionFlags_None = 0,
SectionFlags_Data = 1,
SectionFlags_Code = 2
};
#include <section.h>
#include "symbol_table.h"
struct Image
{
@ -19,7 +13,8 @@ struct Image
uint32_t size{};
size_t entry_point{};
std::vector<Section> sections{};
std::set<Section, SectionComparer> sections{};
SymbolTable symbols{};
/**
* \brief Map data to image by RVA
@ -46,28 +41,4 @@ struct Image
static std::expected<Image, int> ParseImage(const uint8_t* data, size_t size);
};
struct Section
{
std::string name{};
size_t base{};
uint32_t size{};
SectionFlags flags{};
uint8_t* data{};
bool operator<(size_t address) const
{
return address < base;
}
bool operator>(size_t address) const
{
return address >= (base + size);
}
bool operator==(size_t address) const
{
return address >= base && address < base + size;
}
};
Image ElfLoadImage(const uint8_t* data, size_t size);

18
PowerUtils/ppc_context.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <cstdint>
typedef float float128[4];
struct PPCContext
{
uint64_t iar;
uint64_t lr;
uint64_t ctr;
uint32_t xer;
uint32_t cr[8];
uint32_t fpcsr;
uint64_t gpr[32];
double fpr[32];
float128 vpr[128];
};

54
PowerUtils/section.h Normal file
View File

@ -0,0 +1,54 @@
#pragma once
#include <string>
#include <cstdint>
enum SectionFlags : uint8_t
{
SectionFlags_None = 0,
SectionFlags_Data = 1,
SectionFlags_Code = 2
};
struct Section
{
std::string name{};
size_t base{};
uint32_t size{};
SectionFlags flags{};
uint8_t* data{};
bool operator<(size_t address) const
{
return address < base;
}
bool operator>(size_t address) const
{
return address >= (base + size);
}
bool operator==(size_t address) const
{
return address >= base && address < base + size;
}
};
struct SectionComparer
{
using is_transparent = void;
bool operator()(const Section& lhs, size_t rhs) const
{
return rhs > lhs.base + lhs.size;
}
bool operator()(size_t lhs, const Section& rhs) const
{
return lhs < rhs.base;
}
bool operator()(const Section& lhs, const Section& rhs) const
{
return (lhs.base + lhs.size) < rhs.base;
}
};

39
PowerUtils/symbol.h Normal file
View File

@ -0,0 +1,39 @@
#pragma once
#include <string>
#include <cstdint>
enum SymbolType
{
Symbol_None,
Symbol_Section,
Symbol_Function,
Symbol_Comment,
};
struct Symbol
{
std::string name{};
uint32_t address{};
uint32_t size{};
SymbolType type{};
};
struct SymbolComparer
{
using is_transparent = void;
bool operator()(const Symbol& lhs, size_t rhs) const
{
return rhs > lhs.address + lhs.size;
}
bool operator()(size_t lhs, const Symbol& rhs) const
{
return lhs < rhs.address;
}
bool operator()(const Symbol& lhs, const Symbol& rhs) const
{
return (lhs.address + lhs.size) < rhs.address;
}
};

53
PowerUtils/symbol_table.h Normal file
View File

@ -0,0 +1,53 @@
#pragma once
#include "symbol.h"
#include <set>
class SymbolTable : public std::multiset<Symbol, SymbolComparer>
{
public:
const_iterator find(size_t address) const
{
auto iter = std::multiset<Symbol, SymbolComparer>::find(address);
if (iter == end())
{
return iter;
}
size_t closest{ address - iter->address };
auto match = iter;
for (; iter != end(); ++iter)
{
const size_t distance = address - iter->address;
if (distance <= closest)
{
match = iter;
closest = distance;
}
}
return match;
}
iterator find(size_t address)
{
auto iter = std::multiset<Symbol, SymbolComparer>::find(address);
if (iter == end())
{
return iter;
}
size_t closest{ address - iter->address };
auto match = iter;
for (; iter != end(); ++iter)
{
const size_t distance = address - iter->address;
if (distance <= closest)
{
match = iter;
closest = distance;
}
}
return match;
}
};