diff --git a/finalize/CMakeLists.txt b/finalize/CMakeLists.txt index 7bb8957..ab0d620 100644 --- a/finalize/CMakeLists.txt +++ b/finalize/CMakeLists.txt @@ -1,5 +1,5 @@ find_package(LIEF REQUIRED) -add_executable(spslr_finalize finalize.cpp accumulation.cpp) +add_executable(spslr_finalize finalize.cpp accumulation.cpp symbol_collection.cpp) target_link_libraries(spslr_finalize PRIVATE LIEF::LIEF) set_target_properties(spslr_finalize PROPERTIES CXX_STANDARD 20 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS NO) diff --git a/finalize/finalize.cpp b/finalize/finalize.cpp index 18cf070..9636031 100644 --- a/finalize/finalize.cpp +++ b/finalize/finalize.cpp @@ -2,7 +2,10 @@ #include #include +#include + #include "accumulation.h" +#include "symbol_collection.h" /* Notes: @@ -75,13 +78,21 @@ int main(int argc, char** argv) { std::cout << "Gathered a total of " << targets.size() << " distinct targets from " << units.size() << " compilation units!" << std::endl; + std::unique_ptr bin = LIEF::ELF::Parser::parse(bin_file); + if (!bin) { + std::cerr << "Failed to parse binary \"" << bin_file << "\"!" << std::endl; + return 1; + } + + if (!collect_symbols(bin)) { + std::cerr << "Failed to collect symbols from \"" << bin_file << "\"!" << std::endl; + return 1; + } + // TODO /* - 1. Loop over all symbols of the binary - -> associate blocks via CU uid symbol - -> find __spslr_program symbol (spslr vaddr pivot) - 2. Find virtual address and file address for all pins - 3. Emit patcher program into final executable and set __spslr_program + 1. Find virtual address and file address for all pins + 2. Emit patcher program into final executable and set __spslr_program -> make all patcher addresses relative to &__spslr_program -> dpatch entries ordered by level (high levels/nest depths first) */ diff --git a/finalize/symbol_collection.cpp b/finalize/symbol_collection.cpp new file mode 100644 index 0000000..025b43d --- /dev/null +++ b/finalize/symbol_collection.cpp @@ -0,0 +1,93 @@ +#include "symbol_collection.h" + +#include + +#define SPSLR_PINPOINT_CU_UID_LABEL "__spslr_cu_" /* suffixed with "" */ + +/* +struct GlobalSymtab { + std::unordered_map symbols; +}; + +struct LocalSymtab { + std::string cu; + std::unordered_map symbols; +}; +*/ + +using namespace LIEF::ELF; + +GlobalSymtab global_syms; +std::unordered_map local_syms; + +bool collect_symbols(const std::unique_ptr& bin) { + if (!bin) + return false; + + bool cu_uid_found = false; + LocalSymtab tmp_local_syms; + + auto finish_cu_symbols = [&]() -> bool { + if (cu_uid_found) { + if (local_syms.contains(tmp_local_syms.cu)) { + std::cerr << "Duplicate CU UID -> " << tmp_local_syms.cu << std::endl; + return false; + } + + local_syms.emplace(tmp_local_syms.cu, std::move(tmp_local_syms)); + } + + tmp_local_syms.cu.clear(); + tmp_local_syms.symbols.clear(); + cu_uid_found = false; + return true; + }; + + for (const Symbol& sym : bin->symbols()) { + if (sym.type() == Symbol::TYPE::FILE) { + if (!finish_cu_symbols()) + return false; + } + + if (sym.name().empty()) + continue; + + if (sym.type() != Symbol::TYPE::OBJECT && sym.type() != Symbol::TYPE::NOTYPE) + continue; + + VADDR vaddr = sym.value(); + + if (sym.binding() == Symbol::BINDING::GLOBAL) { + if (global_syms.symbols.contains(sym.name())) { + std::cerr << "Duplicate global symbol \"" << sym.name() << "\"!" << std::endl; + return false; + } + + global_syms.symbols.emplace(sym.name(), vaddr); + continue; + } + + if (sym.binding() != Symbol::BINDING::LOCAL) + continue; + + if (sym.name().starts_with(SPSLR_PINPOINT_CU_UID_LABEL)) { + tmp_local_syms.cu = sym.name().substr(std::strlen(SPSLR_PINPOINT_CU_UID_LABEL)); + cu_uid_found = true; + continue; + } + + if (tmp_local_syms.symbols.contains(sym.name())) { + std::cerr << "Duplicate local symbol \"" << sym.name() << "\"!" << std::endl; + return false; + } + + tmp_local_syms.symbols.emplace(sym.name(), vaddr); + continue; + } + + if (!finish_cu_symbols()) + return false; + + return true; +} + diff --git a/finalize/symbol_collection.h b/finalize/symbol_collection.h new file mode 100644 index 0000000..4f73882 --- /dev/null +++ b/finalize/symbol_collection.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include +#include +#include + +using VADDR = uint64_t; + +struct GlobalSymtab { + std::unordered_map symbols; +}; + +struct LocalSymtab { + std::string cu; + std::unordered_map symbols; +}; + +extern GlobalSymtab global_syms; +extern std::unordered_map local_syms; + +bool collect_symbols(const std::unique_ptr& bin); + diff --git a/selfpatch/src/selfpatch.c b/selfpatch/src/selfpatch.c index 2b744ee..0e1687e 100644 --- a/selfpatch/src/selfpatch.c +++ b/selfpatch/src/selfpatch.c @@ -13,7 +13,7 @@ With ASLR, there are 2 options to make it function correctly: 1. Make sure __spslr_program is relocated with program image shift (preferred) 2. __spslr_program = spslr_ptr_absolute((uint64_t)__spslr_program) and postprocessor inserts relative value (kinda weird) */ -static const uint8_t* __spslr_program = NULL; +const uint8_t* __spslr_program = NULL; static void* spslr_ptr_absolute(uint64_t relative) { // To allow ASLR, all patcher addresses are relative to &__spslr_program