diff --git a/PowerAnalyse/main.cpp b/PowerAnalyse/main.cpp index 45d5cbd..fa45726 100644 --- a/PowerAnalyse/main.cpp +++ b/PowerAnalyse/main.cpp @@ -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) diff --git a/PowerUtils/CMakeLists.txt b/PowerUtils/CMakeLists.txt index 665c788..5629df4 100644 --- a/PowerUtils/CMakeLists.txt +++ b/PowerUtils/CMakeLists.txt @@ -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) \ No newline at end of file diff --git a/PowerUtils/image.cpp b/PowerUtils/image.cpp index 376c0a6..dd93c84 100644 --- a/PowerUtils/image.cpp +++ b/PowerUtils/image.cpp @@ -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(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::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(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; } diff --git a/PowerUtils/image.h b/PowerUtils/image.h index 48f35c4..ec67922 100644 --- a/PowerUtils/image.h +++ b/PowerUtils/image.h @@ -1,16 +1,10 @@ #pragma once #include #include -#include +#include #include - -struct Section; -enum SectionFlags : uint8_t -{ - SectionFlags_None = 0, - SectionFlags_Data = 1, - SectionFlags_Code = 2 -}; +#include +#include "symbol_table.h" struct Image { @@ -19,7 +13,8 @@ struct Image uint32_t size{}; size_t entry_point{}; - std::vector
sections{}; + std::set sections{}; + SymbolTable symbols{}; /** * \brief Map data to image by RVA @@ -46,28 +41,4 @@ struct Image static std::expected 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); diff --git a/PowerUtils/ppc_context.h b/PowerUtils/ppc_context.h new file mode 100644 index 0000000..793dcdf --- /dev/null +++ b/PowerUtils/ppc_context.h @@ -0,0 +1,18 @@ +#pragma once +#include + +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]; +}; diff --git a/PowerUtils/section.h b/PowerUtils/section.h new file mode 100644 index 0000000..b93cdc8 --- /dev/null +++ b/PowerUtils/section.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include + +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; + } +}; diff --git a/PowerUtils/symbol.h b/PowerUtils/symbol.h new file mode 100644 index 0000000..5164743 --- /dev/null +++ b/PowerUtils/symbol.h @@ -0,0 +1,39 @@ +#pragma once +#include +#include + +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; + } +}; diff --git a/PowerUtils/symbol_table.h b/PowerUtils/symbol_table.h new file mode 100644 index 0000000..ac827a6 --- /dev/null +++ b/PowerUtils/symbol_table.h @@ -0,0 +1,53 @@ +#pragma once +#include "symbol.h" +#include + +class SymbolTable : public std::multiset +{ +public: + const_iterator find(size_t address) const + { + auto iter = std::multiset::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::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; + } +};