Made subject multi-CU

This commit is contained in:
York Jasper Niebuhr 2025-10-25 23:40:13 +02:00
parent d7b07df8b7
commit ecfeed59ee
11 changed files with 203 additions and 69 deletions

View File

@ -1,29 +1,26 @@
#include <iostream>
/*
<o>.spslr.targets:
target <uid> <size> <field count>
<sourcefile>.spslr:
SPSLR_FINALIZE_HEADER <CU filename> <CU uid symbol>
target <hash> <local uid> <size> <field count>
f <offset> <size> <flags>
f <offset> <size> <flags>
...
<o>.spslr.ipins:
(prefix __spslr_pin)
0 <target uid> <field offset>
1 <target uid> <field offset>
2 <target uid> <field offset>
ipin <label> <target uid> <field offset>
ipin <label> <target uid> <field offset>
ipin <label> <target uid> <field offset>
...
dpin <symbol> <offset> <level> <target uid>
dpin <symbol> <offset> <level> <target uid>
...
<o>.spslr.dpins:
myVar1 2 <strip true/false>
<offset> <lvl> <target uid>
<offset> <lvl> <target uid>
myVar2 1 <strip true/false>
<offset> <lvl> <target uid>
...
Datapins are randomized in order of their level, from bottom of nest to top
Datapin strip flag is set if it would not have been preserved in symtab without pinpoint plugin
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 hash are considered to be the same type
*/

View File

@ -19,6 +19,7 @@ int plugin_init(struct plugin_name_args* plugin_info, struct plugin_gcc_version*
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);
register_callback(plugin_info->base_name, PLUGIN_FINISH_DECL, on_finish_decl, NULL);
struct register_pass_info separate_offset_pass_info;
separate_offset_pass_info.pass = new separate_offset_pass(nullptr);

View File

@ -0,0 +1,9 @@
#include <safe-gcc-plugin.h>
#ifndef SAFEGCC_INPUT_H
#define SAFEGCC_INPUT_H
#include <input.h>
#include <libiberty.h>
#endif

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.cpp separator.cpp separate_offset_pass.cpp)
on_finish_decl.cpp target.cpp separator.cpp separate_offset_pass.cpp)
target_include_directories(spslr_pinpoint PRIVATE .)

View File

@ -0,0 +1,93 @@
#include <iostream> // TODO
#include <stage0.h>
#include <pinpoint_error.h>
#include <safe-input.h>
static std::list<DataPin> pins;
const std::list<DataPin>& dpins() {
return pins;
}
/*
struct DataPin {
struct Component {
std::size_t offset;
std::size_t level;
UID target;
};
std::string symbol;
std::list<Component> components;
};
*/
/*
bool type_matches(tree t, hash_set<tree> *target_types)
{
if (!t) return false;
t = TYPE_MAIN_VARIANT(t);
if (target_types->contains(t))
return true;
if (TREE_CODE(t) == RECORD_TYPE || TREE_CODE(t) == UNION_TYPE)
{
for (tree field = TYPE_FIELDS(t); field; field = TREE_CHAIN(field))
{
if (TREE_CODE(field) == FIELD_DECL)
{
tree ftype = TREE_TYPE(field);
if (type_matches(ftype, target_types))
return true;
}
}
}
return false;
}
*/
static bool compile_datapin(tree type, DataPin& pin) {
// TODO
return true;
}
static void on_static_var(tree var) {
tree type = TREE_TYPE(var);
if (!type)
return;
DataPin pin;
if (!compile_datapin(type, pin))
return;
DECL_PRESERVE_P(var) = 1;
DECL_VISIBILITY(var) = VISIBILITY_DEFAULT;
DECL_VISIBILITY_SPECIFIED(var) = 1;
tree symbol_tree = DECL_ASSEMBLER_NAME(var);
const char* symbol;
if (!symbol_tree || !(symbol = IDENTIFIER_POINTER(symbol_tree)))
pinpoint_fatal("on_static_var failed to get symbol of static variable");
pin.symbol = std::string{ symbol };
pins.emplace_back(std::move(pin));
// TODO
std::cout << "Pinned: \"" << symbol << "\" (" << lbasename(main_input_filename) << ")" << std::endl;
}
void on_finish_decl(void* plugin_data, void* user_data) {
tree decl = (tree)plugin_data;
if (TREE_CODE(decl) != VAR_DECL)
return;
if (!TREE_STATIC(decl) || DECL_EXTERNAL(decl))
return;
on_static_var(decl);
}

View File

@ -2,6 +2,7 @@
#include <cstddef>
#include <map>
#include <string>
#include <list>
#include <limits>
#include <safe-tree.h>
@ -64,9 +65,23 @@ tree make_stage0_ast_separator(UID target, std::size_t offset);
gimple* make_stage0_gimple_separator(tree lhs, UID target, std::size_t offset);
bool is_stage0_separator(gimple* stmt, UID& target, std::size_t& offset);
struct DataPin {
struct Component {
std::size_t offset;
std::size_t level;
UID target;
};
std::string symbol;
std::list<Component> components;
};
const std::list<DataPin>& dpins();
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);
struct separate_offset_pass : gimple_opt_pass {
separate_offset_pass(gcc::context* ctxt);

View File

@ -1,4 +1,5 @@
add_executable(subject main.c)
add_executable(subject main.c second.c sub/second.c)
target_include_directories(subject PRIVATE .)
add_dependencies(subject spslr_pinpoint spslr_finalize 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)

View File

@ -1,54 +1,9 @@
// test_task_struct.c
#include <stdio.h>
#include <stddef.h> // for offsetof
#include "task_struct.h"
#define container_of(ptr, type, member) ({ \
const typeof(((type*)0)->member)* __mptr = (ptr); \
(type*)((char*)__mptr - offsetof(type, member)); })
int second_pid();
int third_pid();
// Minimal doubly linked list
struct list_head {
struct list_head *next, *prev;
};
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
// A small struct like the Linux kernel's task_struct
struct task_struct {
int pid;
const char *comm;
struct list_head tasks; // linkage for global task list
} __attribute__((spslr));
struct task_struct global = { .pid = 42, .comm = "main_global" };
int main(void)
{
@ -77,6 +32,6 @@ int main(void)
size_t myOffset = ((size_t)&((struct task_struct*)0)->tasks); // BROKEN, relevancy for kernel unknown
return 0;
return second_pid() * third_pid();
}

7
subject/second.c Normal file
View File

@ -0,0 +1,7 @@
#include "task_struct.h"
static struct task_struct global = { .pid = 43, .comm = "third_global" };
int third_pid() {
return global.pid;
}

7
subject/sub/second.c Normal file
View File

@ -0,0 +1,7 @@
#include "task_struct.h"
static struct task_struct global = { .pid = 0, .comm = "second_global" };
int second_pid() {
return global.pid;
}

49
subject/task_struct.h Normal file
View File

@ -0,0 +1,49 @@
#include <stdio.h>
#include <stddef.h>
#define container_of(ptr, type, member) ({ \
const typeof(((type*)0)->member)* __mptr = (ptr); \
(type*)((char*)__mptr - offsetof(type, member)); })
// Minimal doubly linked list
struct list_head {
struct list_head *next, *prev;
};
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
// A small struct like the Linux kernel's task_struct
struct task_struct {
int pid;
const char *comm;
struct list_head tasks; // linkage for global task list
} __attribute__((spslr));