Finalizer scanning for symbols

This commit is contained in:
York Jasper Niebuhr 2025-10-27 20:05:19 +01:00
parent 222e3c570d
commit a55009342f
5 changed files with 133 additions and 7 deletions

View File

@ -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)

View File

@ -2,7 +2,10 @@
#include <string>
#include <getopt.h>
#include <LIEF/LIEF.hpp>
#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<LIEF::ELF::Binary> 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)
*/

View File

@ -0,0 +1,93 @@
#include "symbol_collection.h"
#include <iostream>
#define SPSLR_PINPOINT_CU_UID_LABEL "__spslr_cu_" /* suffixed with "<uid>" */
/*
struct GlobalSymtab {
std::unordered_map<std::string, VADDR> symbols;
};
struct LocalSymtab {
std::string cu;
std::unordered_map<std::string, VADDR> symbols;
};
*/
using namespace LIEF::ELF;
GlobalSymtab global_syms;
std::unordered_map<std::string, LocalSymtab> local_syms;
bool collect_symbols(const std::unique_ptr<LIEF::ELF::Binary>& 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;
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <LIEF/LIEF.hpp>
#include <string>
#include <unordered_map>
#include <cstdint>
using VADDR = uint64_t;
struct GlobalSymtab {
std::unordered_map<std::string, VADDR> symbols;
};
struct LocalSymtab {
std::string cu;
std::unordered_map<std::string, VADDR> symbols;
};
extern GlobalSymtab global_syms;
extern std::unordered_map<std::string, LocalSymtab> local_syms;
bool collect_symbols(const std::unique_ptr<LIEF::ELF::Binary>& bin);

View File

@ -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