diff --git a/plugin/main.cpp b/plugin/main.cpp index e49eb8c..8fe440a 100644 --- a/plugin/main.cpp +++ b/plugin/main.cpp @@ -198,11 +198,11 @@ void scan_stmt_for_offsetof(const char *funcname, gimple_stmt_iterator *gsi) { gassign *as = gimple_build_assign(lhs, val); gsi_replace(gsi, as, true); - /* - TODO -> type_str contains "struct " but target set does not + if (strncmp(type_str, "struct ", 7) == 0) + type_str = type_str + 7; + if (!is_target(type_str)) - return; - */ + return; // Insert label MemberAccessInfo info; @@ -279,24 +279,28 @@ struct gimplabels_pass : gimple_opt_pass { ? IDENTIFIER_POINTER(DECL_NAME(fun->decl)) : ""; - std::cout << std::endl << "Handling function \"" << funcname << "\"..." << std::endl; + constexpr bool verbose = false; + std::size_t base_access_count = g_member_accesses.size(); + std::cout << (verbose ? "\n" : "") << "Handling function \"" << funcname << "\"..." << std::endl; // Iteration über alle Grundblöcke und Anweisungen basic_block bb; FOR_EACH_BB_FN(bb, fun) { for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) { gimple *stmt = gsi_stmt(gsi); - print_gimple_stmt (stdout, stmt, 0, TDF_NONE); + if (verbose) + print_gimple_stmt (stdout, stmt, 0, TDF_NONE); scan_stmt_for_offsetof(funcname, &gsi); for (unsigned i = 0; i < gimple_num_ops(stmt); ++i) { tree op = gimple_op(stmt, i); - plugin_debug_tree(op); + if (verbose) + plugin_debug_tree(op); scan_tree_for_components(op, funcname, &gsi); } } } - std::cout << "Number of accesses: " << g_member_accesses.size() << std::endl; + std::cout << " Number of accesses: " << (g_member_accesses.size() - base_access_count) << std::endl; return 0; } }; diff --git a/subject/main.c b/subject/main.c index 094b98c..7b2f6aa 100644 --- a/subject/main.c +++ b/subject/main.c @@ -1,39 +1,80 @@ +// test_task_struct.c #include -#include -#include +#include // for offsetof #define container_of(ptr, type, member) ({ \ - const typeof(((type*)0)->member)* __mptr = (ptr); \ - (type*)((char*)__mptr - offsetof(type, member)); }) + const typeof(((type*)0)->member)* __mptr = (ptr); \ + (type*)((char*)__mptr - offsetof(type, member)); }) -struct A; -struct B; - -struct A { - char m0; - int m1; - struct B* m2; +// Minimal doubly linked list +struct list_head { + struct list_head *next, *prev; }; -struct B { - int m0; - char m1; - short m2; - struct A* m3; - float m4; - struct A m5; - struct B* m6; +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__((slr)); -int main(int argc, char** argv) { - struct A a = { 'x', 52, NULL }; - struct B b = { 1, 2, 3, NULL, 4.f, a, NULL }; +int main(void) +{ + struct list_head task_list; + INIT_LIST_HEAD(&task_list); - b.m2 = 42; + struct task_struct t1 = { .pid = 1, .comm = "init" }; + struct task_struct t2 = { .pid = 2, .comm = "kthreadd" }; + struct task_struct t3 = { .pid = 3, .comm = "worker" }; - struct B* someB = (struct B*)malloc(sizeof(struct B)); - float* someB_m4 = &someB->m4; - container_of(someB_m4, struct B, m4)->m1 = 'x'; // the "sub 0x..." is currently not recognized via ADDR_EXPR + INIT_LIST_HEAD(&t1.tasks); + INIT_LIST_HEAD(&t2.tasks); + INIT_LIST_HEAD(&t3.tasks); - return 0; + list_add_tail(&t1.tasks, &task_list); + list_add_tail(&t2.tasks, &task_list); + list_add_tail(&t3.tasks, &task_list); + + printf("Task list:\n"); + + struct list_head *pos; + list_for_each(pos, &task_list) { + struct task_struct *task = list_entry(pos, struct task_struct, tasks); + printf(" pid=%d, comm=%s\n", task->pid, task->comm); + } + + return 0; } +