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 <final.h>
#include <stage0.h>
#include <stage1.h>
#include <safe-input.h>
#include <pinpoint_config.h>
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())
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 \""
<< dpin.symbol << "\":" << std::endl;
for (const DataPin::Component& c : dpin.components)
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
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_FINISH_TYPE, on_finish_type, 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
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 .)

View File

@ -4,7 +4,11 @@
static std::list<DataPin> pins;
const std::list<DataPin>& dpins() {
void DataPin::reset() {
pins.clear();
}
const std::list<DataPin>& DataPin::all() {
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 bool reference(tree ref, UID& target, std::size_t& offset);
static const std::unordered_map<UID, TargetType>& all();
static void reset();
private:
friend void on_finish_type(void*, void*);
bool fetch_fields(bool redo = false);
@ -79,14 +80,16 @@ struct DataPin {
std::string symbol;
bool global;
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_finish_type(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_start_unit(void* plugin_data, void* user_data);
struct separate_offset_pass : gimple_opt_pass {
separate_offset_pass(gcc::context* ctxt);

View File

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

View File

@ -4,8 +4,17 @@
#include <pinpoint_error.h>
#include <pinpoint_config.h>
static UID next_separator_uid = 0;
static std::unordered_map<UID, S1Separator> separators;
static UID next_pin_uid = 0;
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];
@ -20,14 +29,14 @@ static const char* make_asm_x86_64(UID uid) {
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__)
arch = S1Separator::X86_64;
arch = S1InstructionPin::X86_64;
return make_asm_x86_64(uid);
#else
static_assert(false, "Architecture-independent RTL recovery pass is not yet implemented");
arch = S1Separator::NONE;
arch = S1InstructionPin::NONE;
return make_asm_noarch(uid);
#endif
}
@ -39,19 +48,19 @@ static tree make_asm_operand(const char* constraint_text, tree operand_tree) {
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)
return nullptr;
UID uid = next_separator_uid++;
UID uid = next_pin_uid++;
S1Separator separator;
separator.target = target;
separator.offset = offset;
S1InstructionPin pin;
pin.target = target;
pin.offset = offset;
const char* asm_str = make_asm(uid, separator.arch);
const char* asm_str = make_asm(uid, pin.arch);
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 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)
return nullptr;
separators.emplace(uid, separator);
pins.emplace(uid, pin);
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)
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)
return;
@ -104,12 +113,12 @@ static void separator_assemble_maybe(function* fn, gimple_stmt_iterator* gsi) {
if (!is_stage0_separator(stmt, target, offset))
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)
pinpoint_fatal();
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 = {
@ -130,7 +139,7 @@ unsigned int asm_offset_pass::execute(function* fn) {
basic_block bb;
FOR_EACH_BB_FN(bb, fn) {
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;

View File

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

View File

@ -3,7 +3,7 @@
int second_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)
{