Pinpoint plugin asm_offset pass - ssa trouble

This commit is contained in:
York Jasper Niebuhr 2025-10-25 16:16:53 +02:00
parent 6c1183edc5
commit ef755456da
4 changed files with 101 additions and 3 deletions

View File

@ -2,3 +2,4 @@
#define SPSLR_ATTRIBUTE "spslr"
#define SPSLR_PINPOINT_STAGE0_SEPARATOR "__spslr_offsetof"
#define SPSLR_PINPOINT_STAGE1_SEPARATOR "__spslr_pin" /* suffixed with "_<uid>" */

View File

@ -1,8 +1,95 @@
#include <stage1.h>
#include <stage0.h>
#include <unordered_map>
#include <pinpoint_error.h>
#include <pinpoint_config.h>
static UID next_separator_uid = 0;
static std::unordered_map<UID, S1Separator> separators;
static char asm_str_buf[1024];
static const char* make_asm_noarch(UID uid) {
snprintf(asm_str_buf, sizeof(asm_str_buf), SPSLR_PINPOINT_STAGE1_SEPARATOR "_%lu:", uid);
return nullptr;
}
static const char* make_asm_x86_64(UID uid) {
// Asm has 1 output (%0) and 2 inputs for target (%1) and offset (%2)
snprintf(asm_str_buf, sizeof(asm_str_buf), SPSLR_PINPOINT_STAGE1_SEPARATOR "_%lu: mov %2, %0", uid);
return asm_str_buf;
}
static const char* make_asm(UID uid, S1Separator::ARCH& arch) {
#if defined(__x86_64__) || defined(__amd64__)
arch = S1Separator::X86_64;
return make_asm_x86_64(uid);
#else
arch = S1Separator::NONE;
return make_asm_noarch(uid);
#endif
}
static tree make_asm_operand(const char* constraint_text, tree operand_tree) {
tree constraint_str = build_string(strlen (constraint_text) + 1, constraint_text);
tree inner_list = build_tree_list(integer_zero_node, constraint_str);
tree outer_list = build_tree_list(inner_list, operand_tree);
return outer_list;
}
static gimple* make_stage1_separator(tree lhs, UID target, std::size_t offset) {
if (!lhs)
return nullptr;
UID uid = next_separator_uid++;
S1Separator separator;
separator.target = target;
separator.offset = offset;
const char* asm_str = make_asm(uid, separator.arch);
if (!asm_str)
pinpoint_fatal("make_stage1_separator failed to generate asm string");
tree arg0 = build_int_cst(size_type_node, target);
tree arg1 = build_int_cst(size_type_node, offset);
vec<tree, va_gc>* outputs = NULL;
vec<tree, va_gc>* inputs = NULL;
vec_safe_push(outputs, make_asm_operand("=r", lhs));
vec_safe_push(inputs, make_asm_operand("i", arg0));
vec_safe_push(inputs, make_asm_operand("i", arg1));
gasm* new_gasm = gimple_build_asm_vec(ggc_strdup(asm_str), inputs, outputs, NULL, NULL);
if (!new_gasm)
return nullptr;
SSA_NAME_DEF_STMT(lhs) = new_gasm;
separators.emplace(uid, separator);
return new_gasm;
}
static void separator_assemble_maybe(gimple_stmt_iterator* gsi) {
// TODO
if (!gsi)
return;
gimple* stmt = gsi_stmt(*gsi);
if (!stmt)
return;
UID target;
std::size_t offset;
if (!is_stage0_separator(stmt, target, offset))
return;
gimple* replacement = make_stage1_separator(gimple_call_lhs(stmt), target, offset);
if (!replacement)
pinpoint_fatal();
gsi_replace(gsi, replacement, true);
}
static const pass_data asm_offset_pass_data = {

View File

@ -1,7 +1,17 @@
#pragma once
#include <stage0.h>
#include <safe-gimple.h>
struct S1Separator {
enum ARCH {
NONE, X86_64
} arch;
UID target;
std::size_t offset;
};
struct asm_offset_pass : gimple_opt_pass {
asm_offset_pass(gcc::context* ctxt);
unsigned int execute(function* fn) override;

View File

@ -1,4 +1,4 @@
add_executable(subject main.c)
add_dependencies(subject spslr_pinpoint spslr_finalize spslr_selfpatch)
target_link_libraries(subject PRIVATE spslr_selfpatch)
target_compile_options(subject PRIVATE -fplugin=$<TARGET_FILE:spslr_pinpoint> -fdump-tree-separate_offset)
target_compile_options(subject PRIVATE -fplugin=$<TARGET_FILE:spslr_pinpoint> -fdump-tree-separate_offset -fdump-tree-asm_offset)