Making labels globally unique

This commit is contained in:
York Jasper Niebuhr 2026-04-03 20:35:11 +02:00
parent ce7e75ecc9
commit 273bf2e461
15 changed files with 152 additions and 257 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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>" */

View File

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

View File

@ -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");
} }

View File

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

View File

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

View File

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

View File

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