Instruction pin listing
This commit is contained in:
parent
59eb91dcdf
commit
7d1b68d8ed
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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 .)
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
pinpoint/stage0/on_start_unit.cpp
Normal file
8
pinpoint/stage0/on_start_unit.cpp
Normal 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();
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user