diff --git a/sched_boundary/sched_boundary.py b/sched_boundary/sched_boundary.py index 0cd5c6b8e4acd9c8301708e2a8bee0419109209d..e3128842cd1b688c0c2e98cbef3208b4b261cbc8 100644 --- a/sched_boundary/sched_boundary.py +++ b/sched_boundary/sched_boundary.py @@ -52,6 +52,14 @@ class GccBugs(object): def array_pointer(decl, str): return GccBugs.array_pointer_re.sub(r'\1 (*\3)[\2]', str) + @staticmethod + def typedef(decl, str): + if isinstance(decl.type.name, gcc.TypeDecl): + name = decl.type.name.name + return str.replace('struct ' + name, name) + else: + return str + @staticmethod def enum_type_name(decl, str): if isinstance(decl.type, gcc.EnumeralType): @@ -60,6 +68,29 @@ class GccBugs(object): else: return str + @staticmethod + def is_val_list(arg): + return isinstance(arg.type, gcc.PointerType) and \ + isinstance(arg.type.dereference, gcc.RecordType) and \ + isinstance(arg.type.dereference.name, gcc.Declaration) and \ + arg.type.dereference.name.is_builtin and \ + arg.type.dereference.name.name == '__va_list_tag' + + @staticmethod + def function_signature(decl): + fn_signature = str(decl.str_decl) + fn_signature = GccBugs.enum_type_name(decl.result, fn_signature) + for arg in decl.arguments: + # special dealing with enum types. enum type will missing enum keyword in func.str_decl + if isinstance(arg.type, gcc.EnumeralType): + arg_type_name = str(arg.type.name) + fn_signature = fn_signature.replace(arg_type_name, 'enum ' + arg_type_name) + # special dealing with builtin types, for example: va_list + elif GccBugs.is_val_list(arg): + fn_signature = fn_signature.replace("struct *", "va_list") + + return fn_signature + # extern type array[] -> extern type array[] @staticmethod def array_size(decl, str): @@ -68,7 +99,7 @@ class GccBugs(object): @staticmethod def fix(decl, str): for bugfix in [GccBugs.array_pointer, GccBugs.enum_type_name, - GccBugs.array_size]: + GccBugs.array_size, GccBugs.typedef]: str = bugfix(decl, str) return str @@ -202,7 +233,7 @@ class SchedBoundaryExtract(SchedBoundary): lines[fn_row_start][fn_col_start:].replace(decl.name, new_name) lines[fn_row_end] = lines[fn_row_end] + '\n' + \ "/* DON'T MODIFY SIGNATURE OF FUNCTION {}, IT'S CALLBACK FUNCTION */\n".format(new_name) + \ - GccBugs.enum_type_name(decl.result, decl.str_decl) + '\n' + GccBugs.function_signature(decl) + '\n' for decl, export, fn_row_start, fn_col_start, fn_row_end, fn_col_end in self.interface_list: fn_export_jump.write(export) diff --git a/src/head_jump.h b/src/head_jump.h index 7fd8ba4bc5095abe3fcdda36bb429c7446b57b7d..4c44466dc47602811cf3a0c2205134c5102f34a0 100644 --- a/src/head_jump.h +++ b/src/head_jump.h @@ -84,14 +84,19 @@ static unsigned long mod_func_size[NR_INTERFACE_FN]; #define JUMP_REMOVE_FUNC(func) \ memcpy((unsigned char *)orig_##func, store_orig_##func, HEAD_LEN) +static inline void do_write_cr0(unsigned long val) +{ + asm volatile("mov %0,%%cr0": "+r" (val) : : "memory"); +} + /* Must be used in stop machine context */ #define JUMP_OPERATION(ops) do { \ unsigned long cr0; \ \ cr0 = read_cr0(); \ - write_cr0(cr0 & 0xfffeffff); \ + do_write_cr0(cr0 & 0xfffeffff); \ jump_##ops(); \ - write_cr0(cr0); \ + do_write_cr0(cr0); \ } while(0) #else /* For ARM64 */ diff --git a/src/stack_check.h b/src/stack_check.h index 20282be59e1967339b4ef3d695aa29ec713700be..3823fe4e4da67bdf87147c7dfeb392fc33c8146c 100644 --- a/src/stack_check.h +++ b/src/stack_check.h @@ -3,6 +3,7 @@ #include #include +#include #include "helper.h" #define MAX_STACK_ENTRIES 100 @@ -43,36 +44,27 @@ static void stack_check_init(void) addr_sort(mod_func_addr, mod_func_size, NR_INTERFACE_FN); } -static int stack_check_fn_insmod(struct stack_trace *trace) +static int stack_check_fn(unsigned long *entries, unsigned int nr_entries, bool install) { - unsigned long address; - int i, idx; - - for (i = 0; i < trace->nr_entries; i++) { - address = trace->entries[i]; - idx = bsearch(vm_func_addr, 0, NR_INTERFACE_FN - 1, address); - if (idx == -1) - continue; - - if (address < vm_func_addr[idx] + vm_func_size[idx]) - return -EAGAIN; + int i, ret; + unsigned long *func_addr; + unsigned long *func_size; + + if (install) { + func_addr = vm_func_addr; + func_size = vm_func_size; + } else { + func_addr = mod_func_addr; + func_size = mod_func_size; } - return 0; -} - -static int stack_check_fn_rmmod(struct stack_trace *trace) -{ - unsigned long address; - int i, idx; + for (i = 0; i < nr_entries; i++) { + int idx; - for (i = 0; i < trace->nr_entries; i++) { - address = trace->entries[i]; - idx = bsearch(mod_func_addr, 0, NR_INTERFACE_FN - 1, address); + idx = bsearch(func_addr, 0, NR_INTERFACE_FN - 1, address); if (idx == -1) - continue; - - if (address < mod_func_addr[idx] + mod_func_size[idx]) + return 0; + if (address < func_addr[idx] + func_size[idx]) return -EAGAIN; } @@ -83,6 +75,9 @@ static int stack_check_fn_rmmod(struct stack_trace *trace) static int stack_check_task(struct task_struct *task, bool install) { unsigned long entries[MAX_STACK_ENTRIES]; + unsigned int nr_entries = 0; + +#ifndef CONFIG_ARCH_STACKWALK struct stack_trace trace; trace.skip = 0; @@ -91,11 +86,12 @@ static int stack_check_task(struct task_struct *task, bool install) trace.entries = entries; save_stack_trace_tsk(task, &trace); + nr_entries = trace.nr_entries; +#else /* CONFIG_ARCH_STACKWALK */ + nr_entries = stack_trace_save_tsk(task, &entries, MAX_STACK_ENTRIES, 0); +#endif /* CONFIG_ARCH_STACKWALK */ - if (install) - return stack_check_fn_insmod(&trace); - else - return stack_check_fn_rmmod(&trace); + return stack_check_fn(entries, nr_entries, install); } static int stack_check(bool install)