Making labels globally unique
This commit is contained in:
parent
ce7e75ecc9
commit
273bf2e461
@ -9,7 +9,6 @@ namespace fs = std::filesystem;
|
|||||||
static std::size_t next_global_target_uid = 0;
|
static std::size_t next_global_target_uid = 0;
|
||||||
|
|
||||||
std::unordered_map<std::size_t, TARGET> targets;
|
std::unordered_map<std::size_t, TARGET> targets;
|
||||||
std::unordered_map<std::string, DPIN> global_dpins;
|
|
||||||
std::unordered_map<std::string, CU> units;
|
std::unordered_map<std::string, CU> units;
|
||||||
|
|
||||||
static bool global_target_field_cmp(const TARGET& a, const TARGET& b) {
|
static bool global_target_field_cmp(const TARGET& a, const TARGET& b) {
|
||||||
@ -54,8 +53,8 @@ ipin <label> <target uid> <field offset> <immediate size>
|
|||||||
ipin <label> <target uid> <field offset> <immediate size>
|
ipin <label> <target uid> <field offset> <immediate size>
|
||||||
ipin <label> <target uid> <field offset> <immediate size>
|
ipin <label> <target uid> <field offset> <immediate size>
|
||||||
...
|
...
|
||||||
dpin <local/global> <symbol> <offset> <level> <target uid>
|
dpin <symbol> <offset> <level> <target uid>
|
||||||
dpin <local/global> <symbol> <offset> <level> <target uid>
|
dpin <symbol> <offset> <level> <target uid>
|
||||||
...
|
...
|
||||||
*/
|
*/
|
||||||
static bool accumulate_file(const fs::path& path) {
|
static bool accumulate_file(const fs::path& path) {
|
||||||
@ -163,6 +162,11 @@ static bool accumulate_file(const fs::path& path) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cu.local_targets.contains(ipin.local_target)) {
|
||||||
|
std::cerr << "Ipin references target that has not yet been parsed!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cu.ipins.contains(ipin.symbol)) {
|
if (cu.ipins.contains(ipin.symbol)) {
|
||||||
std::cerr << "Duplicate ipin for symbol \"" << ipin.symbol << "\"!" << std::endl;
|
std::cerr << "Duplicate ipin for symbol \"" << ipin.symbol << "\"!" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -172,47 +176,25 @@ static bool accumulate_file(const fs::path& path) {
|
|||||||
continue;
|
continue;
|
||||||
} else if (type == "dpin") {
|
} else if (type == "dpin") {
|
||||||
std::string symbol;
|
std::string symbol;
|
||||||
std::string scope;
|
|
||||||
DPIN::COMPONENT comp;
|
DPIN::COMPONENT comp;
|
||||||
std::size_t local_target;
|
|
||||||
|
|
||||||
if (!(iss >> scope) || !(iss >> symbol) || !(iss >> comp.offset) ||
|
if (!(iss >> symbol) || !(iss >> comp.offset) ||
|
||||||
!(iss >> comp.level) || !(iss >> local_target)) {
|
!(iss >> comp.level) || !(iss >> comp.target)) {
|
||||||
std::cerr << "Failed to parse dpin declaration!" << std::endl;
|
std::cerr << "Failed to parse dpin declaration!" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scope == "l" || scope == "L") {
|
|
||||||
if (!cu.dpins.contains(symbol))
|
if (!cu.dpins.contains(symbol))
|
||||||
cu.dpins.emplace(symbol, DPIN{ .symbol=symbol });
|
cu.dpins.emplace(symbol, DPIN{ .symbol=symbol });
|
||||||
|
|
||||||
DPIN& dpin = cu.dpins.at(symbol);
|
DPIN& dpin = cu.dpins.at(symbol);
|
||||||
|
|
||||||
if (!cu.local_targets.contains(local_target)) {
|
if (!cu.local_targets.contains(comp.target)) {
|
||||||
std::cerr << "Local datapin references target that has not yet been parsed!" << std::endl;
|
std::cerr << "Dpin references target that has not yet been parsed!" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
comp.target = local_target;
|
|
||||||
dpin.components.push_back(comp);
|
dpin.components.push_back(comp);
|
||||||
} else if (scope == "g" || scope == "G") {
|
|
||||||
if (!global_dpins.contains(symbol))
|
|
||||||
global_dpins.emplace(symbol, DPIN{ .symbol=symbol });
|
|
||||||
|
|
||||||
DPIN& dpin = global_dpins.at(symbol);
|
|
||||||
|
|
||||||
if (!cu.local_targets.contains(local_target)) {
|
|
||||||
std::cerr << "Global datapin references target that has not yet been parsed!" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
comp.target = cu.local_targets.at(local_target);
|
|
||||||
dpin.components.push_back(comp);
|
|
||||||
} else {
|
|
||||||
std::cerr << "Unexpected scope of dpin (\"" << scope << "\"), expected \"l\" or \"g\"!" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Invalid spslr file line beginning: \"" << type << "\"" << std::endl;
|
std::cerr << "Invalid spslr file line beginning: \"" << type << "\"" << std::endl;
|
||||||
|
|||||||
@ -28,7 +28,7 @@ struct DPIN {
|
|||||||
struct COMPONENT {
|
struct COMPONENT {
|
||||||
std::size_t offset;
|
std::size_t offset;
|
||||||
std::size_t level;
|
std::size_t level;
|
||||||
std::size_t target; // local pin -> local target, global pin -> global target
|
std::size_t target; // local pin -> local target
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string symbol;
|
std::string symbol;
|
||||||
@ -58,7 +58,6 @@ struct CU {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern std::unordered_map<std::size_t, TARGET> targets;
|
extern std::unordered_map<std::size_t, TARGET> targets;
|
||||||
extern std::unordered_map<std::string, DPIN> global_dpins;
|
|
||||||
extern std::unordered_map<std::string, CU> units;
|
extern std::unordered_map<std::string, CU> units;
|
||||||
|
|
||||||
bool accumulate(const std::string& spslr_dir);
|
bool accumulate(const std::string& spslr_dir);
|
||||||
|
|||||||
@ -15,7 +15,6 @@
|
|||||||
/*
|
/*
|
||||||
Notes:
|
Notes:
|
||||||
Datapins for same var/symbol are randomized in order of their level, from bottom of nest to top
|
Datapins for same var/symbol are randomized in order of their level, from bottom of nest to top
|
||||||
The CU uid symbol helps differentiating between e.g. "file.c" and "sub/file.c" (symbtab has no idea)
|
|
||||||
Between CUs, types with the same name HAVE TO HAVE the same layout -> randomized together
|
Between CUs, types with the same name HAVE TO HAVE the same layout -> randomized together
|
||||||
To begin with, anonymous types are not allowed for randomization (later solved with hash(type) instead of name)!
|
To begin with, anonymous types are not allowed for randomization (later solved with hash(type) instead of name)!
|
||||||
*/
|
*/
|
||||||
@ -103,16 +102,6 @@ int main(int argc, char** argv) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure all ipins were located
|
|
||||||
for (auto& [cu_uid, cu] : units) {
|
|
||||||
for (auto& [_, ipin] : cu.ipins) {
|
|
||||||
if (!ipin.hit.has_value()) {
|
|
||||||
std::cerr << "Encountered ipin without vaddr!" << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find __spslr_program as anchor of relative addressing in patcher program
|
// Find __spslr_program as anchor of relative addressing in patcher program
|
||||||
if (!global_syms.symbols.contains("__spslr_program")) {
|
if (!global_syms.symbols.contains("__spslr_program")) {
|
||||||
std::cerr << "Unable to locate \"__spslr_program\"!" << std::endl;
|
std::cerr << "Unable to locate \"__spslr_program\"!" << std::endl;
|
||||||
@ -261,7 +250,7 @@ bool assemble_patcher_program(uint64_t vaddr_pivot, std::vector<uint8_t>& progra
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Dump dpins with addresses relative to vaddr_pivot and components ordered by level
|
// Dump dpins with addresses relative to vaddr_pivot and components ordered by level
|
||||||
auto append_dpin = [&](const DPIN& dpin) -> bool {
|
auto append_dpin = [&](const CU& cu, const DPIN& dpin) -> bool {
|
||||||
std::list<DPIN::COMPONENT> sorted_components = dpin.components;
|
std::list<DPIN::COMPONENT> sorted_components = dpin.components;
|
||||||
sorted_components.sort([](const DPIN::COMPONENT& a, const DPIN::COMPONENT& b) {
|
sorted_components.sort([](const DPIN::COMPONENT& a, const DPIN::COMPONENT& b) {
|
||||||
return a.level > b.level; // Descending order
|
return a.level > b.level; // Descending order
|
||||||
@ -270,7 +259,9 @@ bool assemble_patcher_program(uint64_t vaddr_pivot, std::vector<uint8_t>& progra
|
|||||||
for (const DPIN::COMPONENT& comp : sorted_components) {
|
for (const DPIN::COMPONENT& comp : sorted_components) {
|
||||||
inst.opcode = SPSLR_DPATCH;
|
inst.opcode = SPSLR_DPATCH;
|
||||||
inst.op0.dpatch_ptr = dpin.hit->vaddr + comp.offset - vaddr_pivot;
|
inst.op0.dpatch_ptr = dpin.hit->vaddr + comp.offset - vaddr_pivot;
|
||||||
inst.op1.dpatch_target = comp.target;
|
inst.op1.dpatch_target = cu.local_targets.at(comp.target);
|
||||||
|
|
||||||
|
std::cout << "DPIN found at 0x" << std::hex << dpin.hit->vaddr << std::dec << std::endl;
|
||||||
|
|
||||||
if (!append_inst(inst))
|
if (!append_inst(inst))
|
||||||
return false;
|
return false;
|
||||||
@ -279,7 +270,7 @@ bool assemble_patcher_program(uint64_t vaddr_pivot, std::vector<uint8_t>& progra
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dump all local pins
|
// Dump all pins
|
||||||
for (const auto& [cu_uid, cu] : units) {
|
for (const auto& [cu_uid, cu] : units) {
|
||||||
for (const auto& [ipin_sym, ipin] : cu.ipins) {
|
for (const auto& [ipin_sym, ipin] : cu.ipins) {
|
||||||
if (!append_ipin(cu, ipin))
|
if (!append_ipin(cu, ipin))
|
||||||
@ -287,21 +278,11 @@ bool assemble_patcher_program(uint64_t vaddr_pivot, std::vector<uint8_t>& progra
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [dpin_sym, dpin] : cu.dpins) {
|
for (const auto& [dpin_sym, dpin] : cu.dpins) {
|
||||||
DPIN global_dpin = dpin;
|
if (!append_dpin(cu, dpin))
|
||||||
for (DPIN::COMPONENT& comp : global_dpin.components)
|
|
||||||
comp.target = cu.local_targets.at(comp.target);
|
|
||||||
|
|
||||||
if (!append_dpin(global_dpin))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump global dpins
|
|
||||||
for (const auto& [dpin_sym, dpin] : global_dpins) {
|
|
||||||
if (!append_dpin(dpin))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit patcher program
|
// Exit patcher program
|
||||||
inst.opcode = SPSLR_EXIT;
|
inst.opcode = SPSLR_EXIT;
|
||||||
if (!append_inst(inst))
|
if (!append_inst(inst))
|
||||||
|
|||||||
@ -3,125 +3,62 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#define SPSLR_PINPOINT_CU_UID_LABEL "__spslr_cu_" /* suffixed with "<uid>" */
|
|
||||||
|
|
||||||
using namespace LIEF::ELF;
|
using namespace LIEF::ELF;
|
||||||
|
|
||||||
GlobalSymtab global_syms;
|
GlobalSymtab global_syms;
|
||||||
std::unordered_map<std::string, LocalSymtab> local_syms;
|
|
||||||
|
|
||||||
bool collect_symbols(const std::unique_ptr<LIEF::ELF::Binary>& bin) {
|
bool collect_symbols(const std::unique_ptr<LIEF::ELF::Binary>& bin) {
|
||||||
if (!bin)
|
if (!bin)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool cu_uid_found = false;
|
global_syms.symbols.clear();
|
||||||
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()) {
|
for (const Symbol& sym : bin->symbols()) {
|
||||||
if (sym.type() == Symbol::TYPE::FILE) {
|
|
||||||
if (!finish_cu_symbols())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sym.name().empty())
|
if (sym.name().empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sym.type() != Symbol::TYPE::OBJECT && sym.type() != Symbol::TYPE::NOTYPE)
|
if (sym.type() != Symbol::TYPE::OBJECT &&
|
||||||
|
sym.type() != Symbol::TYPE::NOTYPE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (sym.binding() != Symbol::BINDING::GLOBAL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
VADDR vaddr = sym.value();
|
VADDR vaddr = sym.value();
|
||||||
|
|
||||||
if (sym.binding() == Symbol::BINDING::GLOBAL) {
|
|
||||||
if (global_syms.symbols.contains(sym.name())) {
|
if (global_syms.symbols.contains(sym.name())) {
|
||||||
std::cerr << "Duplicate global symbol \"" << sym.name() << "\"!" << std::endl;
|
std::cerr << "Duplicate global symbol \"" << sym.name() << "\"!" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
global_syms.symbols.emplace(sym.name(), vaddr);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool associate_symbols() {
|
bool associate_symbols() {
|
||||||
// Fetch symbols for each accumulated CU
|
|
||||||
for (auto& [cu_uid, cu] : units) {
|
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) {
|
for (auto& [ipin_sym, ipin] : cu.ipins) {
|
||||||
if (!lsyms.symbols.contains(ipin_sym)) {
|
if (!global_syms.symbols.contains(ipin_sym)) {
|
||||||
std::cerr << "Unable to locate symbol \"" << ipin_sym << "\" in unit " << cu_uid << std::endl;
|
std::cerr << "Unable to locate global ipin symbol \"" << ipin_sym << "\"" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ipin.hit.emplace();
|
ipin.hit.emplace();
|
||||||
ipin.hit->vaddr = lsyms.symbols.at(ipin_sym);
|
ipin.hit->vaddr = global_syms.symbols.at(ipin_sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& [dpin_sym, dpin] : cu.dpins) {
|
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)) {
|
if (!global_syms.symbols.contains(dpin_sym)) {
|
||||||
std::cerr << "Unable to locate global symbol \"" << dpin_sym << "\"" << std::endl;
|
std::cerr << "Unable to locate global dpin symbol \"" << dpin_sym << "\"" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dpin.hit.emplace();
|
dpin.hit.emplace();
|
||||||
dpin.hit->vaddr = global_syms.symbols.at(dpin_sym);
|
dpin.hit->vaddr = global_syms.symbols.at(dpin_sym);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,13 +10,7 @@ struct GlobalSymtab {
|
|||||||
std::unordered_map<std::string, VADDR> symbols;
|
std::unordered_map<std::string, VADDR> symbols;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LocalSymtab {
|
|
||||||
std::string cu;
|
|
||||||
std::unordered_map<std::string, VADDR> symbols;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern GlobalSymtab global_syms;
|
extern GlobalSymtab global_syms;
|
||||||
extern std::unordered_map<std::string, LocalSymtab> local_syms;
|
|
||||||
|
|
||||||
bool collect_symbols(const std::unique_ptr<LIEF::ELF::Binary>& bin);
|
bool collect_symbols(const std::unique_ptr<LIEF::ELF::Binary>& bin);
|
||||||
bool associate_symbols();
|
bool associate_symbols();
|
||||||
|
|||||||
@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
void on_finish_unit(void* plugin_data, void* user_data);
|
void on_finish_unit(void* plugin_data, void* user_data);
|
||||||
|
|
||||||
void set_src_dir(const char* dir);
|
void set_meta_dir(const char* dir);
|
||||||
void set_dst_dir(const char* dir);
|
bool has_meta_dir();
|
||||||
|
const char* get_meta_dir();
|
||||||
|
|
||||||
bool has_src_dir();
|
bool init_src_file();
|
||||||
bool has_dst_dir();
|
const char* get_src_file();
|
||||||
|
|
||||||
const char* get_src_dir();
|
bool init_cu_hash();
|
||||||
const char* get_dst_dir();
|
const char* get_cu_hash();
|
||||||
|
|||||||
@ -12,96 +12,83 @@
|
|||||||
#include <pinpoint_config.h>
|
#include <pinpoint_config.h>
|
||||||
#include <pinpoint_error.h>
|
#include <pinpoint_error.h>
|
||||||
|
|
||||||
static bool src_dir_known = false, dst_dir_known = false;
|
static std::string src_file, cu_hash;
|
||||||
static std::string src_dir, dst_dir;
|
|
||||||
|
|
||||||
void set_src_dir(const char* dir) {
|
static bool meta_dir_known = false;
|
||||||
if (!dir) {
|
static std::string meta_dir;
|
||||||
src_dir_known = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
src_dir = std::string{ dir };
|
|
||||||
src_dir_known = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_dst_dir(const char* dir) {
|
|
||||||
if (!dir) {
|
|
||||||
dst_dir_known = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst_dir = std::string{ dir };
|
|
||||||
dst_dir_known = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_src_dir() {
|
|
||||||
return src_dir_known;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_dst_dir() {
|
|
||||||
return dst_dir_known;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* get_src_dir() {
|
|
||||||
if (!src_dir_known)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return src_dir.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* get_dst_dir() {
|
|
||||||
if (!dst_dir_known)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return dst_dir.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::filesystem::path relative_src_path() {
|
|
||||||
const char* src_root = get_src_dir();
|
|
||||||
if (!src_root)
|
|
||||||
pinpoint_fatal("relative_src_path is missing the source root path");
|
|
||||||
|
|
||||||
|
bool init_src_file() {
|
||||||
if (!main_input_filename)
|
if (!main_input_filename)
|
||||||
pinpoint_fatal("relative_src_path is missing the current source file path");
|
return false;
|
||||||
|
|
||||||
std::filesystem::path abs_current_src = std::filesystem::absolute(main_input_filename);
|
std::filesystem::path srcp = std::filesystem::weakly_canonical(
|
||||||
std::filesystem::path abs_root_src = std::filesystem::absolute(src_root);
|
std::filesystem::absolute(main_input_filename)
|
||||||
return std::filesystem::relative(abs_current_src, abs_root_src);
|
);
|
||||||
|
src_file = srcp.string();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::filesystem::path spslr_output_file(const std::filesystem::path& infile) {
|
const char* get_src_file() {
|
||||||
const char* dst_root = get_dst_dir();
|
return src_file.c_str();
|
||||||
if (!dst_root)
|
|
||||||
pinpoint_fatal("spslr_output_file is missing the destination root path");
|
|
||||||
|
|
||||||
std::filesystem::path abs_root_dst = std::filesystem::absolute(dst_root);
|
|
||||||
return (abs_root_dst / infile).string() + SPSLR_PINFILE_EXTENSION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string calculate_cu_uid(const std::filesystem::path& infile) {
|
bool init_cu_hash() {
|
||||||
unsigned char md5_digest[16];
|
unsigned char md5_digest[16];
|
||||||
|
const char* s = get_src_file();
|
||||||
const char* infile_cstr = infile.c_str();
|
md5_buffer(s, strlen(s), md5_digest);
|
||||||
md5_buffer(infile_cstr, strlen(infile_cstr), md5_digest);
|
|
||||||
|
|
||||||
char md5_digest_hex[33] = {};
|
char md5_digest_hex[33] = {};
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
sprintf(md5_digest_hex + i * 2, "%02x", md5_digest[i]);
|
sprintf(md5_digest_hex + i * 2, "%02x", md5_digest[i]);
|
||||||
|
|
||||||
return std::string{ md5_digest_hex };
|
cu_hash = std::string{md5_digest_hex};
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_cu_uid_label(const std::string& uid) {
|
const char* get_cu_hash() {
|
||||||
char label[128];
|
return cu_hash.c_str();
|
||||||
snprintf(label, sizeof(label), SPSLR_PINPOINT_CU_UID_LABEL "%s", uid.c_str());
|
|
||||||
|
|
||||||
fprintf(asm_out_file, "%s:\n", label);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::ofstream open_spslr_output_file(const std::filesystem::path& p) {
|
void set_meta_dir(const char* dir) {
|
||||||
std::filesystem::create_directories(p.parent_path());
|
if (!dir) {
|
||||||
std::ofstream out(p);
|
meta_dir_known = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_dir = std::string{ dir };
|
||||||
|
meta_dir_known = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_meta_dir() {
|
||||||
|
return meta_dir_known;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* get_meta_dir() {
|
||||||
|
if (!meta_dir_known)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return meta_dir.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emit_dpin_alias_labels() {
|
||||||
|
for (const DataPin& dpin : DataPin::all()) {
|
||||||
|
if (dpin.pin_symbol.empty() || dpin.symbol.empty())
|
||||||
|
pinpoint_fatal("emit_dpin_alias_labels got incomplete data pin");
|
||||||
|
|
||||||
|
fprintf(asm_out_file, ".globl %s\n", dpin.pin_symbol.c_str());
|
||||||
|
fprintf(asm_out_file, ".set %s, %s\n", dpin.pin_symbol.c_str(), dpin.symbol.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::ofstream open_spslr_output_file() {
|
||||||
|
std::filesystem::path metadir { get_meta_dir() };
|
||||||
|
std::filesystem::path metafile { std::string{ get_cu_hash() } + SPSLR_PINFILE_EXTENSION };
|
||||||
|
|
||||||
|
std::filesystem::create_directories(metadir);
|
||||||
|
|
||||||
|
std::cout << "Dumping meta data to " << (metadir / metafile) << std::endl;
|
||||||
|
|
||||||
|
std::ofstream out(metadir / metafile);
|
||||||
if (!out)
|
if (!out)
|
||||||
pinpoint_fatal("open_spslr_output_file failed to open spslr dump file");
|
pinpoint_fatal("open_spslr_output_file failed to open spslr dump file");
|
||||||
|
|
||||||
@ -109,20 +96,19 @@ static std::ofstream open_spslr_output_file(const std::filesystem::path& p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void on_finish_unit(void* plugin_data, void* user_data) {
|
void on_finish_unit(void* plugin_data, void* user_data) {
|
||||||
std::filesystem::path infile = relative_src_path();
|
std::string cu_uid = get_cu_hash();
|
||||||
std::filesystem::path outfile = spslr_output_file(infile);
|
|
||||||
|
|
||||||
std::string cu_uid = calculate_cu_uid(infile);
|
// Emit globally unique data pin label for each static object to be randomized
|
||||||
|
|
||||||
emit_cu_uid_label(cu_uid);
|
emit_dpin_alias_labels();
|
||||||
|
|
||||||
// Dump all accumulated data to spslr file
|
// Dump all accumulated data to spslr file
|
||||||
|
|
||||||
std::ofstream out = open_spslr_output_file(outfile);
|
std::ofstream out = open_spslr_output_file();
|
||||||
|
|
||||||
// Header associates data with compilation unit
|
// Header associates data with compilation unit
|
||||||
|
|
||||||
out << "SPSLR " << infile.string() << " " << cu_uid << std::endl;
|
out << "SPSLR " << get_src_file() << " " << cu_uid << std::endl;
|
||||||
|
|
||||||
// Dump all target structs
|
// Dump all target structs
|
||||||
|
|
||||||
@ -145,8 +131,8 @@ void on_finish_unit(void* plugin_data, void* user_data) {
|
|||||||
|
|
||||||
for (const DataPin& dpin : DataPin::all()) {
|
for (const DataPin& dpin : DataPin::all()) {
|
||||||
for (const DataPin::Component& c : dpin.components) {
|
for (const DataPin::Component& c : dpin.components) {
|
||||||
// dpin <local/global> <symbol> <offset> <level> <target uid>
|
// dpin <symbol> <offset> <level> <target uid>
|
||||||
out << "dpin " << (dpin.global ? "g" : "l") << " " << dpin.symbol << " "
|
out << "dpin " << " " << dpin.pin_symbol << " "
|
||||||
<< c.offset << " " << c.level << " " << c.target << std::endl;
|
<< c.offset << " " << c.level << " " << c.target << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,19 +17,12 @@ int plugin_init(struct plugin_name_args* plugin_info, struct plugin_gcc_version*
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < plugin_info->argc; ++i) {
|
for (int i = 0; i < plugin_info->argc; ++i) {
|
||||||
if (!strcmp(plugin_info->argv[i].key, "srcdir"))
|
if (!strcmp(plugin_info->argv[i].key, "metadir"))
|
||||||
set_src_dir(plugin_info->argv[i].value);
|
set_meta_dir(plugin_info->argv[i].value);
|
||||||
else if (!strcmp(plugin_info->argv[i].key, "dstdir"))
|
|
||||||
set_dst_dir(plugin_info->argv[i].value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_src_dir()) {
|
if (!has_meta_dir()) {
|
||||||
std::cerr << "spslr_pinpoint -> missing source directory argument" << std::endl;
|
std::cerr << "spslr_pinpoint -> missing meta directory argument" << std::endl;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!has_dst_dir()) {
|
|
||||||
std::cerr << "spslr_pinpoint -> missing destination directory argument" << std::endl;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
#define SPSLR_ATTRIBUTE "spslr"
|
#define SPSLR_ATTRIBUTE "spslr"
|
||||||
#define SPSLR_PINPOINT_STAGE0_SEPARATOR "__spslr_offsetof"
|
#define SPSLR_PINPOINT_STAGE0_SEPARATOR "__spslr_offsetof"
|
||||||
#define SPSLR_PINPOINT_CU_UID_LABEL "__spslr_cu_" /* suffixed with "<uid>" */
|
|
||||||
#define SPSLR_PINFILE_EXTENSION ".spslr"
|
#define SPSLR_PINFILE_EXTENSION ".spslr"
|
||||||
#define SPSLR_PINPOINT_STAGE2_PIN "__spslr_ipin_" /* suffixed with "<uid>" */
|
#define SPSLR_PINPOINT_STAGE2_PIN "__spslr_ipin_" /* suffixed with "<cuhash>_<uid>" */
|
||||||
|
#define SPSLR_PINPOINT_DPIN "__spslr_dpin_" /* suffixed with "<cuhash>_<uid>" */
|
||||||
|
|||||||
@ -1,17 +1,27 @@
|
|||||||
#include <stage0.h>
|
#include <stage0.h>
|
||||||
|
#include <final.h>
|
||||||
|
|
||||||
#include <pinpoint_error.h>
|
#include <pinpoint_error.h>
|
||||||
|
#include <pinpoint_config.h>
|
||||||
|
|
||||||
|
static UID next_dpin_uid = 0;
|
||||||
static std::list<DataPin> pins;
|
static std::list<DataPin> pins;
|
||||||
|
|
||||||
void DataPin::reset() {
|
void DataPin::reset() {
|
||||||
pins.clear();
|
pins.clear();
|
||||||
|
next_dpin_uid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::list<DataPin>& DataPin::all() {
|
const std::list<DataPin>& DataPin::all() {
|
||||||
return pins;
|
return pins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string make_dpin_symbol() {
|
||||||
|
return std::string(SPSLR_PINPOINT_DPIN) +
|
||||||
|
std::string(get_cu_hash()) + "_" +
|
||||||
|
std::to_string(next_dpin_uid++);
|
||||||
|
}
|
||||||
|
|
||||||
static bool compile_datapin(tree type, DataPin& pin, std::size_t offset = 0, std::size_t level = 0) {
|
static bool compile_datapin(tree type, DataPin& pin, std::size_t offset = 0, std::size_t level = 0) {
|
||||||
bool res = false;
|
bool res = false;
|
||||||
|
|
||||||
@ -59,7 +69,7 @@ static void on_static_var(tree var) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
DECL_PRESERVE_P(var) = 1;
|
DECL_PRESERVE_P(var) = 1;
|
||||||
pin.global = static_cast<bool>(TREE_PUBLIC(var));
|
// pin.global = static_cast<bool>(TREE_PUBLIC(var));
|
||||||
|
|
||||||
tree symbol_tree = DECL_ASSEMBLER_NAME(var);
|
tree symbol_tree = DECL_ASSEMBLER_NAME(var);
|
||||||
const char* symbol;
|
const char* symbol;
|
||||||
@ -67,6 +77,7 @@ static void on_static_var(tree var) {
|
|||||||
pinpoint_fatal("on_static_var failed to get symbol of static variable");
|
pinpoint_fatal("on_static_var failed to get symbol of static variable");
|
||||||
|
|
||||||
pin.symbol = std::string{ symbol };
|
pin.symbol = std::string{ symbol };
|
||||||
|
pin.pin_symbol = make_dpin_symbol();
|
||||||
pins.emplace_back(std::move(pin));
|
pins.emplace_back(std::move(pin));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,18 @@
|
|||||||
#include <stage0.h>
|
#include <stage0.h>
|
||||||
#include <stage1.h>
|
#include <stage1.h>
|
||||||
#include <stage2.h>
|
#include <stage2.h>
|
||||||
|
#include <final.h>
|
||||||
|
|
||||||
|
#include <pinpoint_error.h>
|
||||||
|
|
||||||
void on_start_unit(void* plugin_data, void* user_data) {
|
void on_start_unit(void* plugin_data, void* user_data) {
|
||||||
TargetType::reset();
|
TargetType::reset();
|
||||||
DataPin::reset();
|
DataPin::reset();
|
||||||
s2_pins_reset();
|
s2_pins_reset();
|
||||||
|
|
||||||
|
if (!init_src_file())
|
||||||
|
pinpoint_fatal("spslr_pinpoint failed to get source file name");
|
||||||
|
|
||||||
|
if (!init_cu_hash())
|
||||||
|
pinpoint_fatal("spslr_pinpoint failed to initialize CU hash");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,8 +78,8 @@ struct DataPin {
|
|||||||
UID target;
|
UID target;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string symbol;
|
std::string symbol; // potentially local object symbol
|
||||||
bool global;
|
std::string pin_symbol; // global alias symbol
|
||||||
std::list<Component> components;
|
std::list<Component> components;
|
||||||
|
|
||||||
static void reset();
|
static void reset();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include <stage2.h>
|
#include <stage2.h>
|
||||||
#include <stage1.h>
|
#include <stage1.h>
|
||||||
|
#include <final.h>
|
||||||
#include <pinpoint_config.h>
|
#include <pinpoint_config.h>
|
||||||
#include <pinpoint_error.h>
|
#include <pinpoint_error.h>
|
||||||
|
|
||||||
@ -182,16 +183,18 @@ static bool x86_64_encode_mov_imm32_to_reg(unsigned regno, EncodedReg& out) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string make_final_x86_64_asm(UID pin_uid, const EncodedReg& enc, std::size_t imm) {
|
static std::string make_final_x86_64_asm(const std::string& sym, const EncodedReg& enc, std::size_t imm) {
|
||||||
char buf[256];
|
char buf[512];
|
||||||
std::snprintf(
|
std::snprintf(
|
||||||
buf, sizeof(buf),
|
buf, sizeof(buf),
|
||||||
|
".globl %s\n"
|
||||||
".byte 0x%02x, 0xC7, 0x%02x\n"
|
".byte 0x%02x, 0xC7, 0x%02x\n"
|
||||||
SPSLR_PINPOINT_STAGE2_PIN "%lu:\n"
|
"%s:\n"
|
||||||
".long %zu",
|
".long %zu",
|
||||||
|
sym.c_str(),
|
||||||
enc.rex,
|
enc.rex,
|
||||||
enc.modrm,
|
enc.modrm,
|
||||||
static_cast<unsigned long>(pin_uid),
|
sym.c_str(),
|
||||||
imm
|
imm
|
||||||
);
|
);
|
||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
@ -224,9 +227,12 @@ static bool lower_stage1_marker_insn(rtx_insn* insn) {
|
|||||||
if (it == pins.end())
|
if (it == pins.end())
|
||||||
pinpoint_fatal("stage2: internal error after s2_pin_allocate");
|
pinpoint_fatal("stage2: internal error after s2_pin_allocate");
|
||||||
|
|
||||||
it->second.symbol = std::string(SPSLR_PINPOINT_STAGE2_PIN) + std::to_string(pin_uid);
|
it->second.symbol =
|
||||||
|
std::string(SPSLR_PINPOINT_STAGE2_PIN) +
|
||||||
|
std::string(get_cu_hash()) + "_" +
|
||||||
|
std::to_string(pin_uid);
|
||||||
|
|
||||||
std::string final_asm = make_final_x86_64_asm(pin_uid, enc, offset);
|
std::string final_asm = make_final_x86_64_asm(it->second.symbol, enc, offset);
|
||||||
|
|
||||||
ASM_OPERANDS_TEMPLATE(asm_src) = ggc_strdup(final_asm.c_str());
|
ASM_OPERANDS_TEMPLATE(asm_src) = ggc_strdup(final_asm.c_str());
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
3
plan.txt
3
plan.txt
@ -1,6 +1,3 @@
|
|||||||
Make labels globally unique
|
|
||||||
- Use hash of object file path to identify CU
|
|
||||||
|
|
||||||
Collect alignment data on struct members
|
Collect alignment data on struct members
|
||||||
Fix bit fields and dynamic size fields (at end of structs) in place
|
Fix bit fields and dynamic size fields (at end of structs) in place
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,7 @@ target_include_directories(subject PRIVATE .)
|
|||||||
add_dependencies(subject spslr_pinpoint spslr_finalize spslr_selfpatch)
|
add_dependencies(subject spslr_pinpoint spslr_finalize spslr_selfpatch)
|
||||||
target_link_libraries(subject PRIVATE spslr_selfpatch)
|
target_link_libraries(subject PRIVATE spslr_selfpatch)
|
||||||
target_compile_options(subject PRIVATE -O1 -fplugin=$<TARGET_FILE:spslr_pinpoint> -fdump-tree-separate_offset -fdump-tree-asm_offset
|
target_compile_options(subject PRIVATE -O1 -fplugin=$<TARGET_FILE:spslr_pinpoint> -fdump-tree-separate_offset -fdump-tree-asm_offset
|
||||||
-fplugin-arg-spslr_pinpoint-srcdir=${CMAKE_CURRENT_SOURCE_DIR}
|
-fplugin-arg-spslr_pinpoint-metadir=${CMAKE_CURRENT_BINARY_DIR}/spslr)
|
||||||
-fplugin-arg-spslr_pinpoint-dstdir=${CMAKE_CURRENT_BINARY_DIR}/spslr)
|
|
||||||
|
|
||||||
# Apply spslr_finalizer to subject
|
# Apply spslr_finalizer to subject
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user