mirror of
				https://github.com/hedge-dev/XenonRecomp.git
				synced 2025-11-04 06:47:09 +00:00 
			
		
		
		
	Symbol table
This commit is contained in:
		@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
@@ -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;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -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
									
								
							
							
						
						
									
										18
									
								
								PowerUtils/ppc_context.h
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										54
									
								
								PowerUtils/section.h
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										39
									
								
								PowerUtils/symbol.h
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										53
									
								
								PowerUtils/symbol_table.h
									
									
									
									
									
										Normal 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;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user