#include "symbol_collection.h" #include "accumulation.h" #include #define SPSLR_PINPOINT_CU_UID_LABEL "__spslr_cu_" /* suffixed with "" */ 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; } bool associate_symbols() { // Fetch symbols for each accumulated CU for (auto& [cu_uid, cu] : units) { if (!local_syms.contains(cu_uid)) { std::cerr << "Could not find symbols for unit UID " << cu_uid << std::endl; return false; } const LocalSymtab& lsyms = local_syms.at(cu_uid); for (auto& [ipin_sym, ipin] : cu.ipins) { if (!lsyms.symbols.contains(ipin_sym)) { std::cerr << "Unable to locate symbol \"" << ipin_sym << "\" in unit " << cu_uid << std::endl; return false; } ipin.hit.emplace(); ipin.hit->vaddr = lsyms.symbols.at(ipin_sym); ipin.hit->imm_offset = 0; ipin.hit->imm_size = 0; } for (auto& [dpin_sym, dpin] : cu.dpins) { if (!lsyms.symbols.contains(dpin_sym)) { std::cerr << "Unable to locate symbol \"" << dpin_sym << "\" in unit " << cu_uid << std::endl; return false; } dpin.hit.emplace(); dpin.hit->vaddr = lsyms.symbols.at(dpin_sym); } } // Fetch global symbols for global dpins for (auto& [dpin_sym, dpin] : global_dpins) { if (!global_syms.symbols.contains(dpin_sym)) { std::cerr << "Unable to locate global symbol \"" << dpin_sym << "\"" << std::endl; return false; } dpin.hit.emplace(); dpin.hit->vaddr = global_syms.symbols.at(dpin_sym); } return true; }