Instruction pin listing

This commit is contained in:
York Jasper Niebuhr 2025-10-26 13:30:32 +01:00
parent 59eb91dcdf
commit 7d1b68d8ed
10 changed files with 65 additions and 25 deletions

View File

@ -1,8 +1,10 @@
#include <iostream> #include <iostream>
#include <final.h> #include <final.h>
#include <stage0.h> #include <stage0.h>
#include <stage1.h>
#include <safe-input.h> #include <safe-input.h>
#include <pinpoint_config.h>
void on_finish_unit(void* plugin_data, void* user_data) { void on_finish_unit(void* plugin_data, void* user_data) {
/* /*
@ -18,10 +20,15 @@ void on_finish_unit(void* plugin_data, void* user_data) {
for (const auto& [uid, target] : TargetType::all()) for (const auto& [uid, target] : TargetType::all())
std::cout << " Target " << uid << " -> \"" << target.name() << "\" (" << target.size() << ")" << std::endl; std::cout << " Target " << uid << " -> \"" << target.name() << "\" (" << target.size() << ")" << std::endl;
for (const DataPin& dpin : dpins()) { for (const DataPin& dpin : DataPin::all()) {
std::cout << " " << (dpin.global ? "Global" : "Local") << " data pin at symbol \"" std::cout << " " << (dpin.global ? "Global" : "Local") << " data pin at symbol \""
<< dpin.symbol << "\":" << std::endl; << dpin.symbol << "\":" << std::endl;
for (const DataPin::Component& c : dpin.components) for (const DataPin::Component& c : dpin.components)
std::cout << " offset " << c.offset << " (level " << c.level << ") -> target " << c.target << std::endl; std::cout << " offset " << c.offset << " (level " << c.level << ") -> target " << c.target << std::endl;
} }
for (const auto& [uid, ipin] : S1InstructionPin::all()) {
std::cout << " Instruction pin at symbol \"" << SPSLR_PINPOINT_STAGE1_SEPARATOR
<< "_" << uid << "\" -> target " << ipin.target << ", offset " << ipin.offset << std::endl;
}
} }

View File

@ -17,6 +17,7 @@ int plugin_init(struct plugin_name_args* plugin_info, struct plugin_gcc_version*
// Stage 0 -> separates relevant field offsets into function calls // Stage 0 -> separates relevant field offsets into function calls
register_callback(plugin_info->base_name, PLUGIN_START_UNIT, on_start_unit, NULL);
register_callback(plugin_info->base_name, PLUGIN_ATTRIBUTES, on_register_attributes, NULL); register_callback(plugin_info->base_name, PLUGIN_ATTRIBUTES, on_register_attributes, NULL);
register_callback(plugin_info->base_name, PLUGIN_FINISH_TYPE, on_finish_type, NULL); register_callback(plugin_info->base_name, PLUGIN_FINISH_TYPE, on_finish_type, NULL);
register_callback(plugin_info->base_name, PLUGIN_BUILD_COMPONENT_REF, on_preserve_component_ref, NULL); register_callback(plugin_info->base_name, PLUGIN_BUILD_COMPONENT_REF, on_preserve_component_ref, NULL);

View File

@ -1,3 +1,3 @@
target_sources(spslr_pinpoint PRIVATE on_register_attributes.cpp on_finish_type.cpp on_preserve_component_ref.cpp target_sources(spslr_pinpoint PRIVATE on_register_attributes.cpp on_finish_type.cpp on_preserve_component_ref.cpp
on_finish_decl.cpp target.cpp separator.cpp separate_offset_pass.cpp) on_finish_decl.cpp on_start_unit.cpp target.cpp separator.cpp separate_offset_pass.cpp)
target_include_directories(spslr_pinpoint PRIVATE .) target_include_directories(spslr_pinpoint PRIVATE .)

View File

@ -4,7 +4,11 @@
static std::list<DataPin> pins; static std::list<DataPin> pins;
const std::list<DataPin>& dpins() { void DataPin::reset() {
pins.clear();
}
const std::list<DataPin>& DataPin::all() {
return pins; return pins;
} }

View File

@ -0,0 +1,8 @@
#include <stage0.h>
#include <stage1.h>
void on_start_unit(void* plugin_data, void* user_data) {
TargetType::reset();
DataPin::reset();
S1InstructionPin::reset();
}

View File

@ -54,6 +54,7 @@ public:
static const TargetType* find(UID uid); // O(1) static const TargetType* find(UID uid); // O(1)
static bool reference(tree ref, UID& target, std::size_t& offset); static bool reference(tree ref, UID& target, std::size_t& offset);
static const std::unordered_map<UID, TargetType>& all(); static const std::unordered_map<UID, TargetType>& all();
static void reset();
private: private:
friend void on_finish_type(void*, void*); friend void on_finish_type(void*, void*);
bool fetch_fields(bool redo = false); bool fetch_fields(bool redo = false);
@ -79,14 +80,16 @@ struct DataPin {
std::string symbol; std::string symbol;
bool global; bool global;
std::list<Component> components; std::list<Component> components;
};
const std::list<DataPin>& dpins(); static void reset();
static const std::list<DataPin>& all();
};
void on_register_attributes(void* plugin_data, void* user_data); void on_register_attributes(void* plugin_data, void* user_data);
void on_finish_type(void* plugin_data, void* user_data); void on_finish_type(void* plugin_data, void* user_data);
void on_preserve_component_ref(void* plugin_data, void* user_data); void on_preserve_component_ref(void* plugin_data, void* user_data);
void on_finish_decl(void* plugin_data, void* user_data); void on_finish_decl(void* plugin_data, void* user_data);
void on_start_unit(void* plugin_data, void* user_data);
struct separate_offset_pass : gimple_opt_pass { struct separate_offset_pass : gimple_opt_pass {
separate_offset_pass(gcc::context* ctxt); separate_offset_pass(gcc::context* ctxt);

View File

@ -216,6 +216,11 @@ const std::unordered_map<UID, TargetType>& TargetType::all() {
return targets; return targets;
} }
void TargetType::reset() {
targets.clear();
next_uid = 0;
}
static bool foreach_record_field(tree t, std::function<bool(const TargetType::Field&)> callback) { static bool foreach_record_field(tree t, std::function<bool(const TargetType::Field&)> callback) {
if (!t || TREE_CODE(t) != RECORD_TYPE) if (!t || TREE_CODE(t) != RECORD_TYPE)
return false; return false;

View File

@ -4,8 +4,17 @@
#include <pinpoint_error.h> #include <pinpoint_error.h>
#include <pinpoint_config.h> #include <pinpoint_config.h>
static UID next_separator_uid = 0; static UID next_pin_uid = 0;
static std::unordered_map<UID, S1Separator> separators; static std::unordered_map<UID, S1InstructionPin> pins;
const std::unordered_map<UID, S1InstructionPin>& S1InstructionPin::all() {
return pins;
}
void S1InstructionPin::reset() {
pins.clear();
next_pin_uid = 0;
}
static char asm_str_buf[1024]; static char asm_str_buf[1024];
@ -20,14 +29,14 @@ static const char* make_asm_x86_64(UID uid) {
return asm_str_buf; return asm_str_buf;
} }
static const char* make_asm(UID uid, S1Separator::ARCH& arch) { static const char* make_asm(UID uid, S1InstructionPin::ARCH& arch) {
#if defined(__x86_64__) || defined(__amd64__) #if defined(__x86_64__) || defined(__amd64__)
arch = S1Separator::X86_64; arch = S1InstructionPin::X86_64;
return make_asm_x86_64(uid); return make_asm_x86_64(uid);
#else #else
static_assert(false, "Architecture-independent RTL recovery pass is not yet implemented"); static_assert(false, "Architecture-independent RTL recovery pass is not yet implemented");
arch = S1Separator::NONE; arch = S1InstructionPin::NONE;
return make_asm_noarch(uid); return make_asm_noarch(uid);
#endif #endif
} }
@ -39,19 +48,19 @@ static tree make_asm_operand(const char* constraint_text, tree operand_tree) {
return outer_list; return outer_list;
} }
static gimple* make_stage1_separator(tree lhs, UID target, std::size_t offset) { static gimple* make_stage1_pin(tree lhs, UID target, std::size_t offset) {
if (!lhs) if (!lhs)
return nullptr; return nullptr;
UID uid = next_separator_uid++; UID uid = next_pin_uid++;
S1Separator separator; S1InstructionPin pin;
separator.target = target; pin.target = target;
separator.offset = offset; pin.offset = offset;
const char* asm_str = make_asm(uid, separator.arch); const char* asm_str = make_asm(uid, pin.arch);
if (!asm_str) if (!asm_str)
pinpoint_fatal("make_stage1_separator failed to generate asm string"); pinpoint_fatal("make_stage1_pin failed to generate asm string");
tree arg0 = build_int_cst(size_type_node, target); tree arg0 = build_int_cst(size_type_node, target);
tree arg1 = build_int_cst(size_type_node, offset); tree arg1 = build_int_cst(size_type_node, offset);
@ -67,11 +76,11 @@ static gimple* make_stage1_separator(tree lhs, UID target, std::size_t offset) {
if (!new_gasm) if (!new_gasm)
return nullptr; return nullptr;
separators.emplace(uid, separator); pins.emplace(uid, pin);
return new_gasm; return new_gasm;
} }
static void separator_update_ssa_def(function* fn, gimple* old_def, gimple* new_def) { static void pin_update_ssa_def(function* fn, gimple* old_def, gimple* new_def) {
if (!fn || !old_def) if (!fn || !old_def)
return; return;
@ -90,7 +99,7 @@ static void separator_update_ssa_def(function* fn, gimple* old_def, gimple* new_
} }
} }
static void separator_assemble_maybe(function* fn, gimple_stmt_iterator* gsi) { static void pin_assemble_maybe(function* fn, gimple_stmt_iterator* gsi) {
if (!gsi) if (!gsi)
return; return;
@ -104,12 +113,12 @@ static void separator_assemble_maybe(function* fn, gimple_stmt_iterator* gsi) {
if (!is_stage0_separator(stmt, target, offset)) if (!is_stage0_separator(stmt, target, offset))
return; return;
gimple* replacement = make_stage1_separator(gimple_call_lhs(stmt), target, offset); gimple* replacement = make_stage1_pin(gimple_call_lhs(stmt), target, offset);
if (!replacement) if (!replacement)
pinpoint_fatal(); pinpoint_fatal();
gsi_replace(gsi, replacement, true); gsi_replace(gsi, replacement, true);
separator_update_ssa_def(fn, stmt, replacement); pin_update_ssa_def(fn, stmt, replacement);
} }
static const pass_data asm_offset_pass_data = { static const pass_data asm_offset_pass_data = {
@ -130,7 +139,7 @@ unsigned int asm_offset_pass::execute(function* fn) {
basic_block bb; basic_block bb;
FOR_EACH_BB_FN(bb, fn) { FOR_EACH_BB_FN(bb, fn) {
for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi))
separator_assemble_maybe(fn, &gsi); pin_assemble_maybe(fn, &gsi);
} }
return 0; return 0;

View File

@ -3,13 +3,16 @@
#include <stage0.h> #include <stage0.h>
#include <safe-gimple.h> #include <safe-gimple.h>
struct S1Separator { struct S1InstructionPin {
enum ARCH { enum ARCH {
NONE, X86_64 NONE, X86_64
} arch; } arch;
UID target; UID target;
std::size_t offset; std::size_t offset;
static const std::unordered_map<UID, S1InstructionPin>& all();
static void reset();
}; };
struct asm_offset_pass : gimple_opt_pass { struct asm_offset_pass : gimple_opt_pass {

View File

@ -3,7 +3,7 @@
int second_pid(); int second_pid();
int third_pid(); int third_pid();
extern struct task_struct global = { .pid = 42, .comm = "main_global" }; struct task_struct global = { .pid = 42, .comm = "main_global" };
int main(void) int main(void)
{ {