diff --git a/cli/cmd/root.go b/cli/cmd/root.go index d908319..90a7346 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -281,7 +281,6 @@ func persistentPreRunEFunc(command *cobra.Command, args []string) error { mconfig.DumpHex = gconfig.DumpHex mconfig.ShowTime = gconfig.ShowTime mconfig.ShowUid = gconfig.ShowUid - mconfig.Next = gconfig.Next // 1. hook uprobe mconfig.InitStackUprobeConfig() @@ -393,9 +392,15 @@ func runFunc(command *cobra.Command, args []string) { var modNames []string if mconfig.BrkAddr != 0 { - modNames = []string{module.MODULE_NAME_BRK} + modNames = append(modNames, module.MODULE_NAME_BRK) + } else if gconfig.SysCall != "" { + modNames = append(modNames, module.MODULE_NAME_PERF) + modNames = append(modNames, module.MODULE_NAME_SYSCALL) + } else if len(gconfig.HookPoint) > 0 { + modNames = append(modNames, module.MODULE_NAME_PERF) + modNames = append(modNames, module.MODULE_NAME_STACK) } else { - modNames = []string{module.MODULE_NAME_PERF, module.MODULE_NAME_STACK} + Logger.Fatal("hook nothing, plz set -w/--point or -s/--syscall or --brk") } for _, modName := range modNames { // 现在合并成只有一个模块了 所以直接通过名字获取 @@ -618,6 +623,4 @@ func init() { // syscall hook rootCmd.PersistentFlags().StringVarP(&gconfig.SysCall, "syscall", "s", "", "filter syscalls") rootCmd.PersistentFlags().StringVar(&gconfig.NoSysCall, "no-syscall", "", "syscall black list, max 20") - // 新的数据读取方案 - rootCmd.PersistentFlags().BoolVar(&gconfig.Next, "next", false, "next version") } diff --git a/src/common/buffer.h b/src/common/buffer.h index f0679d3..23d6e63 100644 --- a/src/common/buffer.h +++ b/src/common/buffer.h @@ -216,32 +216,7 @@ static __always_inline str_buf_t *make_str_buf() { return bpf_map_lookup_elem(&str_buf_map, &id); } -static __always_inline u32 strcmp_by_map(arg_filter_t *filter_config, buf_t *string_p) { - u32 str_len = 256; - if (str_len > filter_config->oldstr_len) { - str_len = filter_config->oldstr_len; - } - str_buf_t* str_value = make_str_buf(); - if (str_value == NULL) { - return 0; - } - if (str_len > 0) { - // 必须重置 - __builtin_memset(str_value->str_val, 0, sizeof(str_value->str_val)); - bpf_probe_read(str_value->str_val, str_len, string_p->buf); - } - // map的key最好是一个不变的内容 否则会引起一些奇怪的冲突 - bpf_map_update_elem(&str_buf, &filter_config->oldstr_val, &str_len, BPF_ANY); - u32* str_len_value = bpf_map_lookup_elem(&str_buf, str_value); - - if (str_len_value == NULL) { - return 0; - } - bpf_map_delete_elem(&str_buf, str_value); - return 1; -} - -static __always_inline u32 next_strcmp_by_map(op_ctx_t* op_ctx, next_arg_filter_t *filter) { +static __always_inline u32 strcmp_by_map(op_ctx_t* op_ctx, arg_filter_t *filter) { str_buf_t* str_value = make_str_buf(); if (unlikely(str_value == NULL)) return 0; __builtin_memset(str_value->str_val, 0, sizeof(str_value->str_val)); diff --git a/src/maps.h b/src/maps.h index 40d35cb..cd8e5cc 100644 --- a/src/maps.h +++ b/src/maps.h @@ -39,16 +39,14 @@ BPF_HASH(common_filter, u32, common_filter_t, 1); BPF_HASH(common_list, u32, u32, 1024); BPF_HASH(thread_filter, thread_name_t, u32, 40); -BPF_HASH(arg_filter, u32, arg_filter_t, 40); -BPF_HASH(next_arg_filter, u64, next_arg_filter_t, 40); +BPF_HASH(arg_filter, u64, arg_filter_t, 40); BPF_HASH(str_buf, str_buf_t, u32, 256); BPF_ARRAY(str_buf_gen, str_buf_t, 1); -BPF_LRU_HASH(str_buf_map, u64, str_buf_t, 1024); -BPF_ARRAY(match_ctx_gen, match_ctx_t, 1); -BPF_LRU_HASH(match_ctx_map, u64, match_ctx_t, 1024); +BPF_LRU_HASH(str_buf_map, u64, str_buf_t, 256); BPF_PERCPU_ARRAY(event_data_map, event_data_t, 1); BPF_PERCPU_ARRAY(op_ctx_map, op_ctx_t, 2); BPF_HASH(op_list, u32, op_config_t, 256); +BPF_HASH(uprobe_point_args, u32, point_args_t, 6); BPF_HASH(sysenter_point_args, u32, point_args_t, 512); BPF_HASH(sysexit_point_args, u32, point_args_t, 512); BPF_ARRAY(base_config, config_entry_t, 1); diff --git a/src/stack.c b/src/stack.c index 83e6372..10017bb 100644 --- a/src/stack.c +++ b/src/stack.c @@ -7,19 +7,6 @@ #include "utils.h" -typedef struct uprobe_point_args_t { - u32 count; - point_arg point_args[MAX_POINT_ARG_COUNT]; -} uprobe_point_args; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, u32); - __type(value, struct uprobe_point_args_t); - __uint(max_entries, 512); -} uprobe_point_args_map SEC(".maps"); - - SEC("raw_tracepoint/sched_process_fork") int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx) { @@ -37,39 +24,31 @@ int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx) u32 child_ns_tgid = get_task_ns_tgid(child); u32* pid = bpf_map_lookup_elem(&child_parent_map, &parent_ns_pid); - if (pid == NULL) { - return 0; - } + if (unlikely(pid == NULL)) return 0; + if (*pid == parent_ns_pid){ ret = bpf_map_update_elem(&child_parent_map, &child_ns_pid, &parent_ns_pid, BPF_ANY); } else { bpf_printk("[stack] parent pid from map:%d\n", *pid); } - return 0; } -static __always_inline u32 probe_stack_warp(struct pt_regs* ctx, u32 args_key) { - +static __always_inline u32 probe_stack_warp(struct pt_regs* ctx, u32 point_key) { program_data_t p = {}; if (!init_program_data(&p, ctx)) return 0; if (!should_trace(&p)) return 0; - - struct uprobe_point_args_t* uprobe_point_args = bpf_map_lookup_elem(&uprobe_point_args_map, &args_key); - if (uprobe_point_args == NULL) { - return 0; - } + point_args_t* point_args = bpf_map_lookup_elem(&uprobe_point_args, &point_key); + if (unlikely(point_args == NULL)) return 0; u32 filter_key = 0; common_filter_t* filter = bpf_map_lookup_elem(&common_filter, &filter_key); - if (filter == NULL) { - return 0; - } + if (unlikely(filter == NULL)) return 0; - save_to_submit_buf(p.event, (void *) &args_key, sizeof(u32), 0); + save_to_submit_buf(p.event, (void *) &filter_key, sizeof(u32), 0); u64 lr = 0; if(filter->is_32bit) { bpf_probe_read_kernel(&lr, sizeof(lr), &ctx->regs[14]); @@ -79,44 +58,29 @@ static __always_inline u32 probe_stack_warp(struct pt_regs* ctx, u32 args_key) { bpf_probe_read_kernel(&lr, sizeof(lr), &ctx->regs[30]); save_to_submit_buf(p.event, (void *) &lr, sizeof(u64), 1); } - u64 pc = 0; u64 sp = 0; - bpf_probe_read_kernel(&pc, sizeof(pc), &ctx->pc); bpf_probe_read_kernel(&sp, sizeof(sp), &ctx->sp); - save_to_submit_buf(p.event, (void *) &pc, sizeof(u64), 2); - save_to_submit_buf(p.event, (void *) &sp, sizeof(u64), 3); + save_to_submit_buf(p.event, (void *) &sp, sizeof(u64), 2); + u64 pc = 0; + bpf_probe_read_kernel(&pc, sizeof(pc), &ctx->pc); + save_to_submit_buf(p.event, (void *) &pc, sizeof(u64), 3); - u32 point_arg_count = MAX_POINT_ARG_COUNT; - if (uprobe_point_args->count <= point_arg_count) { - point_arg_count = uprobe_point_args->count; - } + int ctx_index = 0; + op_ctx_t* op_ctx = bpf_map_lookup_elem(&op_ctx_map, &ctx_index); + if (unlikely(op_ctx == NULL)) return 0; + __builtin_memset((void *)op_ctx, 0, sizeof(op_ctx)); + + op_ctx->reg_0 = READ_KERN(ctx->regs[0]); + op_ctx->save_index = 4; + op_ctx->op_key_index = 0; + + read_args(p, point_args, op_ctx, ctx); - u32 next_arg_index = 4; - u64 reg_0 = READ_KERN(ctx->regs[0]); - for (int i = 0; i < point_arg_count; i++) { - struct point_arg_t* point_arg = (struct point_arg_t*) &uprobe_point_args->point_args[i]; - if (point_arg->read_index == REG_ARM64_MAX) { - continue; - } - u64 arg_ptr = get_arg_ptr(ctx, point_arg, i, reg_0); - - // 先保存参数值本身 - save_to_submit_buf(p.event, (void *)&arg_ptr, sizeof(u64), (u8)next_arg_index); - next_arg_index += 1; - - if (point_arg->point_flag != UPROBE_ENTER_READ) { - continue; - } - if (arg_ptr == 0) { - continue; - } - u32 read_count = get_read_count(ctx, point_arg); - next_arg_index = read_arg(p, point_arg, arg_ptr, read_count, next_arg_index); - if (point_arg->tmp_index == FILTER_INDEX_SKIP) { - point_arg->tmp_index = 0; - return 0; - } + if (op_ctx->skip_flag) { + op_ctx->skip_flag = 0; + return 0; } + events_perf_submit(&p, UPROBE_ENTER); if (filter->signal > 0) { bpf_send_signal(filter->signal); @@ -126,16 +90,16 @@ static __always_inline u32 probe_stack_warp(struct pt_regs* ctx, u32 args_key) { SEC("uprobe/stack_0") int probe_stack_0(struct pt_regs* ctx) { - u32 args_key = 0; - return probe_stack_warp(ctx, args_key); + u32 point_key = 0; + return probe_stack_warp(ctx, point_key); } #define PROBE_STACK(name) \ SEC("uprobe/stack_##name") \ int probe_stack_##name(struct pt_regs* ctx) \ { \ - u32 args_key = name; \ - return probe_stack_warp(ctx, args_key); \ + u32 point_key = name; \ + return probe_stack_warp(ctx, point_key); \ } // PROBE_STACK(0); diff --git a/src/syscall.c b/src/syscall.c index fb8663d..7559826 100644 --- a/src/syscall.c +++ b/src/syscall.c @@ -8,253 +8,6 @@ #include "common/context.h" #include "common/filtering.h" -typedef struct syscall_point_args_t { - u32 nr; - u32 count; - point_arg point_args[MAX_POINT_ARG_COUNT]; - point_arg point_arg_ret; -} syscall_point_args; - -// syscall_point_args_map 的 key 就是 nr -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, u32); - __type(value, struct syscall_point_args_t); - __uint(max_entries, 512); -} syscall_point_args_map SEC(".maps"); - -static __always_inline bool __is_str_prefix(const char *str, const char *prefix, int siz) -{ - for (int i = 0; i < siz && prefix[i]; i++) - if (str[i] != prefix[i]) - return false; - return true; -} - -static __always_inline u32 read_args(program_data_t p, point_args_t* point_args, op_ctx_t* op_ctx, struct pt_regs* regs) { - int zero = 0; - // op_config_t* op = NULL; - op_config_t* op = bpf_map_lookup_elem(&op_list, &zero); - for (int i = 0; i < MAX_OP_COUNT; i++) { - if (op != NULL && op_ctx->post_code != OP_SKIP) { - op_ctx->op_code = op_ctx->post_code; - op_ctx->post_code = OP_SKIP; - } else { - if (op_ctx->op_key_index >= MAX_OP_COUNT) return 0; - u32 op_key = point_args->op_key_list[op_ctx->op_key_index]; - // bpf_printk("[stackplz] op_key:%d\n", op_key); - op = bpf_map_lookup_elem(&op_list, &op_key); - if (unlikely(op == NULL)) return 0; - op_ctx->op_code = op->code; - op_ctx->post_code = op->post_code; - op_ctx->op_key_index += 1; - } - // bpf_printk("[stackplz] index:%d value:%ld\n", op_ctx->op_key_index, op->value); - // bpf_printk("[stackplz] code:%d pre_code:%d post_code:%d\n", op->code, op->pre_code, op->post_code); - // bpf_printk("[stackplz] %d op_code:%d\n", i, op_ctx->op_code); - if (op_ctx->op_code == OP_SKIP) break; - switch (op_ctx->op_code) { - case OP_RESET_CTX: - op_ctx->break_count = 0; - op_ctx->reg_index = 0; - op_ctx->read_addr = 0; - op_ctx->read_len = 0; - op_ctx->reg_value = 0; - op_ctx->pointer_value = 0; - break; - case OP_SET_REG_INDEX: - op_ctx->reg_index = op->value; - break; - case OP_SET_READ_LEN: - op_ctx->read_len = op->value; - break; - case OP_SET_READ_LEN_REG_VALUE: - if (op_ctx->read_len > op_ctx->reg_value) { - op_ctx->read_len = op_ctx->reg_value; - } - break; - case OP_SET_READ_LEN_POINTER_VALUE: - // bpf_printk("[stackplz] OP_SET_READ_LEN_POINTER_VALUE old_len:%d new_len:%d\n", op_ctx->read_len, op_ctx->pointer_value); - if (op_ctx->read_len > op_ctx->pointer_value) { - op_ctx->read_len = op_ctx->pointer_value; - } - break; - case OP_SET_READ_COUNT: - op_ctx->read_len *= op->value; - break; - case OP_ADD_OFFSET: - // bpf_printk("[stackplz] OP_ADD_OFFSET ptr:0x%lx add:%d\n", op_ctx->read_addr, op->value); - op_ctx->read_addr += op->value; - break; - case OP_SUB_OFFSET: - // bpf_printk("[stackplz] OP_SUB_OFFSET ptr:0x%lx sub:%d\n", op_ctx->read_addr, op->value); - op_ctx->read_addr -= op->value; - break; - case OP_MOVE_REG_VALUE: - op_ctx->read_addr = op_ctx->reg_value; - break; - case OP_MOVE_POINTER_VALUE: - op_ctx->read_addr = op_ctx->pointer_value; - break; - case OP_MOVE_TMP_VALUE: - op_ctx->read_addr = op_ctx->tmp_value; - break; - case OP_SET_TMP_VALUE: - op_ctx->tmp_value = op_ctx->read_addr; - break; - case OP_FOR_BREAK: - if (op_ctx->loop_count == 0) { - op_ctx->loop_index = op_ctx->op_key_index; - } - if (op_ctx->loop_count >= op_ctx->break_count) { - op_ctx->loop_count = 0; - op_ctx->break_count = 0; - op_ctx->loop_index = 0; - } else { - op_ctx->loop_count += 1; - op_ctx->op_key_index = op_ctx->loop_index; - } - break; - case OP_SET_BREAK_COUNT: - op_ctx->break_count = MAX_LOOP_COUNT; - if (op_ctx->break_count > op->value) { - op_ctx->break_count = op->value; - } - break; - case OP_SET_BREAK_COUNT_REG_VALUE: - op_ctx->break_count = MAX_LOOP_COUNT; - if (op_ctx->break_count > op_ctx->reg_value) { - op_ctx->break_count = op_ctx->reg_value; - } - break; - case OP_SET_BREAK_COUNT_POINTER_VALUE: - op_ctx->break_count = MAX_LOOP_COUNT; - if (op_ctx->break_count > op_ctx->pointer_value) { - op_ctx->break_count = op_ctx->pointer_value; - } - break; - case OP_SAVE_ADDR: - // bpf_printk("[stackplz] OP_SAVE_ADDR val:0x%lx idx:%d\n", op_ctx->read_addr, op_ctx->save_index); - save_to_submit_buf(p.event, (void *)&op_ctx->read_addr, sizeof(op_ctx->read_addr), op_ctx->save_index); - op_ctx->save_index += 1; - break; - case OP_READ_REG: - if (op->pre_code == OP_SET_REG_INDEX) { - op_ctx->reg_index = op->value; - } - // make ebpf verifier happy - if (op_ctx->reg_index >= REG_ARM64_MAX) { - return 0; - } - if (op_ctx->reg_index == 0) { - op_ctx->reg_value = op_ctx->reg_0; - } else { - op_ctx->reg_value = READ_KERN(regs->regs[op_ctx->reg_index]); - } - break; - case OP_SAVE_REG: - save_to_submit_buf(p.event, (void *)&op_ctx->reg_value, sizeof(op_ctx->reg_value), op_ctx->save_index); - op_ctx->save_index += 1; - break; - case OP_READ_POINTER: - if (op->pre_code == OP_ADD_OFFSET) { - bpf_probe_read_user(&op_ctx->pointer_value, sizeof(op_ctx->pointer_value), (void*)(op_ctx->read_addr + op->value)); - } else if (op->pre_code == OP_SUB_OFFSET) { - bpf_probe_read_user(&op_ctx->pointer_value, sizeof(op_ctx->pointer_value), (void*)(op_ctx->read_addr - op->value)); - } else { - bpf_probe_read_user(&op_ctx->pointer_value, sizeof(op_ctx->pointer_value), (void*)op_ctx->read_addr); - } - break; - case OP_SAVE_POINTER: - save_to_submit_buf(p.event, (void *)&op_ctx->pointer_value, sizeof(op_ctx->pointer_value), op_ctx->save_index); - op_ctx->save_index += 1; - break; - case OP_SAVE_STRUCT: - // fix memory tag - op_ctx->read_addr = op_ctx->read_addr & 0xffffffffff; - if (op->pre_code == OP_SET_READ_COUNT) { - op_ctx->read_len *= op->value; - } - if (op_ctx->read_len > MAX_BYTES_ARR_SIZE) { - op_ctx->read_len = MAX_BYTES_ARR_SIZE; - } - // bpf_printk("[stackplz] OP_SAVE_STRUCT ptr:0x%lx len:%d\n", op_ctx->read_addr, op_ctx->read_len); - int save_struct_status = save_bytes_to_buf(p.event, (void *)(op_ctx->read_addr), op_ctx->read_len, op_ctx->save_index); - if (save_struct_status == 0) { - // 保存失败的情况 比如是一个非法的地址 那么就填一个空的 buf - // 那么只会保存 save_index 和 size -> [save_index][size][] - // ? 这里的处理方法好像不对 应该没问题 因为失败的时候 buf_off 没有变化 - save_bytes_to_buf(p.event, 0, 0, op_ctx->save_index); - } - op_ctx->save_index += 1; - break; - case OP_FILTER_STRING: { - // 这里会受到循环次数的限制 - // 实测 384 可以 512 不行 除非有什么更好的优化方法 - op_ctx->skip_flag = 1; // 这里是 apply_filter 的意思 - next_arg_filter_t* filter = bpf_map_lookup_elem(&next_arg_filter, &op->value); - if (unlikely(filter == NULL)) return 0; - bool is_match = next_strcmp_by_map(op_ctx, filter); - if (filter->filter_type == WHITELIST_FILTER && is_match) { - op_ctx->match_whitelist = 1; - } else if (filter->filter_type == BLACKLIST_FILTER && is_match) { - op_ctx->match_blacklist = 1; - } - break; - } - case OP_SAVE_STRING: - // fix memory tag - op_ctx->read_addr = op_ctx->read_addr & 0xffffffffff; - u32 old_off = p.event->buf_off; - int save_string_status = save_str_to_buf(p.event, (void*) op_ctx->read_addr, op_ctx->save_index); - if (save_string_status == 0) { - // 失败的情况存一个空数据 暂时没有遇到 有待测试 - save_bytes_to_buf(p.event, 0, 0, op_ctx->save_index); - } else { - op_ctx->str_len = p.event->buf_off - (old_off + sizeof(int) + 1); - } - op_ctx->save_index += 1; - break; - case OP_SAVE_PTR_STRING: - { - u64 ptr = op_ctx->read_addr & 0xffffffffff; - bpf_probe_read_user(&ptr, sizeof(ptr), (void*) ptr); - save_to_submit_buf(p.event, (void *)&ptr, sizeof(ptr), op_ctx->save_index); - op_ctx->save_index += 1; - // 每次取出后使用前都要 fix 很坑 - ptr = ptr & 0xffffffffff; - int status = save_str_to_buf(p.event, (void*) ptr, op_ctx->save_index); - if (status == 0) { - save_bytes_to_buf(p.event, 0, 0, op_ctx->save_index); - // 为读取字符串数组设计的 - op_ctx->loop_count = op_ctx->break_count; - } - op_ctx->save_index += 1; - break; - } - default: - // bpf_printk("[stackplz] unknown op code:%d\n", op->code); - break; - } - if (op_ctx->match_blacklist) break; - } - - // 跳过逻辑: - // 1. 不与任何白名单规则匹配,跳过 - // 2. 与任意黑名单规则之一匹配,跳过 - if (op_ctx->skip_flag == 1) { - if (op_ctx->match_whitelist == 0 || op_ctx->match_blacklist == 1) { - op_ctx->skip_flag = 1; - } else { - op_ctx->skip_flag = 0; - } - op_ctx->match_whitelist = 0; - op_ctx->match_blacklist = 0; - } - - return 0; -} - SEC("raw_tracepoint/sched_process_fork") int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx) { @@ -288,9 +41,8 @@ int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx) // bpf_printk("[syscall] parent_ns_pid:%d child_ns_pid:%d\n", parent_ns_pid, child_ns_pid); u32* pid = bpf_map_lookup_elem(&child_parent_map, &parent_ns_pid); - if (pid == NULL) { - return 0; - } + if (unlikely(pid == NULL)) return 0; + if (*pid == parent_ns_pid){ // map中取出的父进程pid 这里fork产生子进程的pid相同 // 说明这个进程是我们自己添加的 @@ -307,7 +59,7 @@ int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx) } SEC("raw_tracepoint/sys_enter") -int next_raw_syscalls_sys_enter(struct bpf_raw_tracepoint_args* ctx) { +int raw_syscalls_sys_enter(struct bpf_raw_tracepoint_args* ctx) { program_data_t p = {}; if (!init_program_data(&p, ctx)) return 0; @@ -320,32 +72,23 @@ int next_raw_syscalls_sys_enter(struct bpf_raw_tracepoint_args* ctx) { u32 sysno = (u32)syscallno; // 先根据调用号确定有没有对应的参数获取方案 没有直接结束 point_args_t* point_args = bpf_map_lookup_elem(&sysenter_point_args, &sysno); - if (point_args == NULL) { - // bpf_printk("[syscall] unsupport nr:%d\n", sysno); - return 0; - } + if (unlikely(point_args == NULL)) return 0; u32 filter_key = 0; common_filter_t* filter = bpf_map_lookup_elem(&common_filter, &filter_key); - if (filter == NULL) { - return 0; - } + if (unlikely(filter == NULL)) return 0; if (filter->trace_mode == TRACE_COMMON) { // 非 追踪全部syscall模式 u32 sysno_whitelist_key = sysno + SYS_WHITELIST_START; u32 *sysno_whitelist_value = bpf_map_lookup_elem(&common_list, &sysno_whitelist_key); - if (sysno_whitelist_value == NULL) { - return 0; - } + if (unlikely(sysno_whitelist_value == NULL)) return 0; } // 黑名单同样对 追踪全部syscall模式 有效 u32 sysno_blacklist_key = sysno + SYS_BLACKLIST_START; u32 *sysno_blacklist_value = bpf_map_lookup_elem(&common_list, &sysno_blacklist_key); - if (sysno_blacklist_value != NULL) { - return 0; - } + if (unlikely(sysno_blacklist_value != NULL)) return 0; // 保存寄存器应该放到所有过滤完成之后 args_t saved_regs = {}; @@ -371,12 +114,12 @@ int next_raw_syscalls_sys_enter(struct bpf_raw_tracepoint_args* ctx) { bpf_probe_read_kernel(&lr, sizeof(lr), ®s->regs[30]); save_to_submit_buf(p.event, (void *) &lr, sizeof(u64), 1); } - u64 pc = 0; u64 sp = 0; - bpf_probe_read_kernel(&pc, sizeof(pc), ®s->pc); bpf_probe_read_kernel(&sp, sizeof(sp), ®s->sp); - save_to_submit_buf(p.event, (void *) &pc, sizeof(u64), 2); - save_to_submit_buf(p.event, (void *) &sp, sizeof(u64), 3); + save_to_submit_buf(p.event, (void *) &sp, sizeof(u64), 2); + u64 pc = 0; + bpf_probe_read_kernel(&pc, sizeof(pc), ®s->pc); + save_to_submit_buf(p.event, (void *) &pc, sizeof(u64), 3); int ctx_index = 0; op_ctx_t* op_ctx = bpf_map_lookup_elem(&op_ctx_map, &ctx_index); @@ -405,7 +148,7 @@ int next_raw_syscalls_sys_enter(struct bpf_raw_tracepoint_args* ctx) { } SEC("raw_tracepoint/sys_exit") -int next_raw_syscalls_sys_exit(struct bpf_raw_tracepoint_args* ctx) { +int raw_syscalls_sys_exit(struct bpf_raw_tracepoint_args* ctx) { program_data_t p = {}; if (!init_program_data(&p, ctx)) @@ -419,15 +162,11 @@ int next_raw_syscalls_sys_exit(struct bpf_raw_tracepoint_args* ctx) { u32 sysno = (u32)syscallno; point_args_t* point_args = bpf_map_lookup_elem(&sysexit_point_args, &sysno); - if (point_args == NULL) { - return 0; - } + if (unlikely(point_args == NULL)) return 0; u32 filter_key = 0; common_filter_t* filter = bpf_map_lookup_elem(&common_filter, &filter_key); - if (filter == NULL) { - return 0; - } + if (unlikely(filter == NULL)) return 0; args_t saved_regs; if (load_args(&saved_regs, SYSCALL_ENTER) != 0) { @@ -442,17 +181,13 @@ int next_raw_syscalls_sys_exit(struct bpf_raw_tracepoint_args* ctx) { // 非 追踪全部syscall模式 u32 sysno_whitelist_key = sysno + SYS_WHITELIST_START; u32 *sysno_whitelist_value = bpf_map_lookup_elem(&common_list, &sysno_whitelist_key); - if (sysno_whitelist_value == NULL) { - return 0; - } + if (unlikely(sysno_whitelist_value == NULL)) return 0; } // 黑名单同样对 追踪全部syscall模式 有效 u32 sysno_blacklist_key = sysno + SYS_BLACKLIST_START; u32 *sysno_blacklist_value = bpf_map_lookup_elem(&common_list, &sysno_blacklist_key); - if (sysno_blacklist_value != NULL) { - return 0; - } + if (unlikely(sysno_blacklist_value != NULL)) return 0; // 保存系统调用号 save_to_submit_buf(p.event, (void *) &sysno, sizeof(u32), 0); @@ -481,214 +216,6 @@ int next_raw_syscalls_sys_exit(struct bpf_raw_tracepoint_args* ctx) { return 0; } -SEC("raw_tracepoint/sys_enter") -int raw_syscalls_sys_enter(struct bpf_raw_tracepoint_args* ctx) { - - // 除了实现对指定进程的系统调用跟踪 也要将其产生的子进程 加入追踪范围 - // 为了实现这个目的 fork 系统调用结束之后 应当检查其 父进程是否归属于当前被追踪的进程 - - program_data_t p = {}; - if (!init_program_data(&p, ctx)) - return 0; - - if (!should_trace(&p)) - return 0; - - struct pt_regs *regs = (struct pt_regs *)(ctx->args[0]); - u64 syscallno = READ_KERN(regs->syscallno); - u32 sysno = (u32)syscallno; - // 先根据调用号确定有没有对应的参数获取方案 没有直接结束 - struct syscall_point_args_t* syscall_point_args = bpf_map_lookup_elem(&syscall_point_args_map, &sysno); - if (syscall_point_args == NULL) { - // bpf_printk("[syscall] unsupport nr:%d\n", sysno); - return 0; - } - - u32 filter_key = 0; - common_filter_t* filter = bpf_map_lookup_elem(&common_filter, &filter_key); - if (filter == NULL) { - return 0; - } - - if (filter->trace_mode == TRACE_COMMON) { - // 非 追踪全部syscall模式 - u32 sysno_whitelist_key = sysno + SYS_WHITELIST_START; - u32 *sysno_whitelist_value = bpf_map_lookup_elem(&common_list, &sysno_whitelist_key); - if (sysno_whitelist_value == NULL) { - return 0; - } - } - - // 黑名单同样对 追踪全部syscall模式 有效 - u32 sysno_blacklist_key = sysno + SYS_BLACKLIST_START; - u32 *sysno_blacklist_value = bpf_map_lookup_elem(&common_list, &sysno_blacklist_key); - if (sysno_blacklist_value != NULL) { - return 0; - } - - // 保存寄存器应该放到所有过滤完成之后 - args_t args = {}; - args.args[0] = READ_KERN(regs->regs[0]); - args.args[1] = READ_KERN(regs->regs[1]); - args.args[2] = READ_KERN(regs->regs[2]); - args.args[3] = READ_KERN(regs->regs[3]); - args.args[4] = READ_KERN(regs->regs[4]); - args.args[5] = READ_KERN(regs->regs[5]); - save_args(&args, SYSCALL_ENTER); - - // event->context 已经有进程的信息了 - save_to_submit_buf(p.event, (void *) &sysno, sizeof(u32), 0); - - // 先获取 lr sp pc 并发送 这样可以尽早计算调用来源情况 - // READ_KERN 好像有问题 - u64 lr = 0; - if(filter->is_32bit) { - bpf_probe_read_kernel(&lr, sizeof(lr), ®s->regs[14]); - save_to_submit_buf(p.event, (void *) &lr, sizeof(u64), 1); - } - else { - bpf_probe_read_kernel(&lr, sizeof(lr), ®s->regs[30]); - save_to_submit_buf(p.event, (void *) &lr, sizeof(u64), 1); - } - u64 pc = 0; - u64 sp = 0; - bpf_probe_read_kernel(&pc, sizeof(pc), ®s->pc); - bpf_probe_read_kernel(&sp, sizeof(sp), ®s->sp); - save_to_submit_buf(p.event, (void *) &pc, sizeof(u64), 2); - save_to_submit_buf(p.event, (void *) &sp, sizeof(u64), 3); - - u32 point_arg_count = MAX_POINT_ARG_COUNT; - if (syscall_point_args->count <= point_arg_count) { - point_arg_count = syscall_point_args->count; - } - - u32 next_arg_index = 4; - u64 reg_0 = READ_KERN(regs->regs[0]); - for (int i = 0; i < point_arg_count; i++) { - struct point_arg_t* point_arg = (struct point_arg_t*) &syscall_point_args->point_args[i]; - if (point_arg->read_index == REG_ARM64_MAX) { - continue; - } - u64 arg_ptr = get_arg_ptr(regs, point_arg, i, reg_0); - - // 先保存参数值本身 - save_to_submit_buf(p.event, (void *)&arg_ptr, sizeof(u64), (u8)next_arg_index); - next_arg_index += 1; - - if (point_arg->point_flag != SYS_ENTER) { - continue; - } - if (arg_ptr == 0) { - continue; - } - u32 read_count = get_read_count(regs, point_arg); - next_arg_index = read_arg(p, point_arg, arg_ptr, read_count, next_arg_index); - if (point_arg->tmp_index == FILTER_INDEX_SKIP) { - point_arg->tmp_index = 0; - args.flag = 1; - save_args(&args, SYSCALL_ENTER); - return 0; - } - } - events_perf_submit(&p, SYSCALL_ENTER); - if (filter->signal > 0) { - bpf_send_signal(filter->signal); - } - return 0; -} - -SEC("raw_tracepoint/sys_exit") -int raw_syscalls_sys_exit(struct bpf_raw_tracepoint_args* ctx) { - - program_data_t p = {}; - if (!init_program_data(&p, ctx)) - return 0; - - if (!should_trace(&p)) - return 0; - - struct pt_regs *regs = (struct pt_regs *)(ctx->args[0]); - u64 syscallno = READ_KERN(regs->syscallno); - u32 sysno = (u32)syscallno; - - struct syscall_point_args_t* syscall_point_args = bpf_map_lookup_elem(&syscall_point_args_map, &sysno); - if (syscall_point_args == NULL) { - return 0; - } - - u32 filter_key = 0; - common_filter_t* filter = bpf_map_lookup_elem(&common_filter, &filter_key); - if (filter == NULL) { - return 0; - } - - args_t saved_args; - if (load_args(&saved_args, SYSCALL_ENTER) != 0) { - return 0; - } - del_args(SYSCALL_ENTER); - if (saved_args.flag == 1) { - return 0; - } - - if (filter->trace_mode == TRACE_COMMON) { - // 非 追踪全部syscall模式 - u32 sysno_whitelist_key = sysno + SYS_WHITELIST_START; - u32 *sysno_whitelist_value = bpf_map_lookup_elem(&common_list, &sysno_whitelist_key); - if (sysno_whitelist_value == NULL) { - return 0; - } - } - - // 黑名单同样对 追踪全部syscall模式 有效 - u32 sysno_blacklist_key = sysno + SYS_BLACKLIST_START; - u32 *sysno_blacklist_value = bpf_map_lookup_elem(&common_list, &sysno_blacklist_key); - if (sysno_blacklist_value != NULL) { - return 0; - } - - u32 next_arg_index = 0; - save_to_submit_buf(p.event, (void *) &sysno, sizeof(u32), (u8)next_arg_index); - next_arg_index += 1; - - u32 point_arg_count = MAX_POINT_ARG_COUNT; - if (syscall_point_args->count <= point_arg_count) { - point_arg_count = syscall_point_args->count; - } - u64 reg_0 = saved_args.args[0]; - for (int i = 0; i < point_arg_count; i++) { - struct point_arg_t* point_arg = (struct point_arg_t*) &syscall_point_args->point_args[i]; - if (point_arg->read_index == REG_ARM64_MAX) { - continue; - } - u64 arg_ptr = get_arg_ptr(regs, point_arg, i, reg_0); - - // 先保存参数值本身 - save_to_submit_buf(p.event, (void *)&arg_ptr, sizeof(u64), (u8)next_arg_index); - next_arg_index += 1; - - if (point_arg->point_flag != SYS_EXIT) { - continue; - } - if (arg_ptr == 0) { - continue; - } - u32 read_count = get_read_count(regs, point_arg); - next_arg_index = read_arg(p, point_arg, arg_ptr, read_count, next_arg_index); - } - - // 读取返回值 - u64 ret = READ_KERN(regs->regs[0]); - // 保存之 - save_to_submit_buf(p.event, (void *) &ret, sizeof(ret), (u8)next_arg_index); - next_arg_index += 1; - // 取返回值的参数配置 并尝试进一步读取 - struct point_arg_t* point_arg = (struct point_arg_t*) &syscall_point_args->point_arg_ret; - next_arg_index = read_arg(p, point_arg, ret, 0, next_arg_index); - // 发送数据 - events_perf_submit(&p, SYSCALL_EXIT); - return 0; -} // bpf_printk debug use // echo 1 > /sys/kernel/tracing/tracing_on diff --git a/src/types.h b/src/types.h index 5b2449d..daa7a59 100644 --- a/src/types.h +++ b/src/types.h @@ -16,35 +16,20 @@ typedef struct args { u32 flag; } args_t; -typedef struct match_ctx { - u32 apply_filter; - u32 match_whitelist; - u32 match_blacklist; -} match_ctx_t; - typedef struct thread_name { char name[16]; } thread_name_t; -typedef struct arg_filter { - u32 filter_type; - u32 filter_index; - u64 num_val; - char oldstr_val[256]; - u32 oldstr_len; - char newstr_val[256]; - u32 newstr_len; -} arg_filter_t; typedef struct str_buf { char str_val[256]; } str_buf_t; -typedef struct next_arg_filter { +typedef struct arg_filter { u32 filter_type; char str_val[256]; u32 str_len; -} next_arg_filter_t; +} arg_filter_t; enum arg_filter_e { diff --git a/src/utils.h b/src/utils.h index 29cf718..54ec20f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -11,12 +11,6 @@ #include "common/consts.h" #include "common/buffer.h" -#define MAX_IOV_COUNT 6 -#define MAX_POINT_ARG_COUNT 10 - -#define FILTER_INDEX_NONE 0x0 -#define FILTER_INDEX_SKIP 0x1234 - typedef struct point_arg_t { u32 point_flag; u32 filter_idx[MAX_FILTER_COUNT]; @@ -30,269 +24,228 @@ typedef struct point_arg_t { u32 tmp_index; } point_arg; -static __always_inline match_ctx_t *make_match_ctx() { - u32 zero = 0; - struct match_ctx_t *match_ctx = bpf_map_lookup_elem(&match_ctx_gen, &zero); - if (match_ctx == NULL) return NULL; - u64 id = bpf_get_current_pid_tgid(); - bpf_map_update_elem(&match_ctx_map, &id, match_ctx, BPF_ANY); - return bpf_map_lookup_elem(&match_ctx_map, &id); -} - -static __always_inline u32 get_read_count(struct pt_regs* ctx, struct point_arg_t* point_arg) { - // 以寄存器值作为读取大小 只包含 x0-x28 fp寄存器就是x29 所以不包含在内 - // 或者以预设 read_count 作为读取大小 - // 这里还可以改进一下 read_count 本身有上限 可以设为一个大于上限的值 - // 即先比较 发现大于上限 那么减去特定值 作为 item_countindex - // 这样可以实际省去 item_countindex - u32 read_count = 0; - if (point_arg->item_countindex >= REG_ARM64_X0 && point_arg->item_countindex < REG_ARM64_X29) { - read_count = READ_KERN(ctx->regs[point_arg->item_countindex]); - } else { - read_count = point_arg->read_count; - } - return read_count; -} - -static __always_inline u64 get_arg_ptr(struct pt_regs* ctx, struct point_arg_t* point_arg, int arg_index, u64 reg_0) { - // REG_ARM64_MAX 意味着需要跳过 但在调用本函数前就应该进行判断 - // REG_ARM64_ABS 意味着 read_offset 作为 绝对地址 用于后续读取 - // REG_ARM64_X0 有关的比较是因为 sys_exit 完成后要读取执行前的寄存器 - u64 ptr = point_arg->read_offset; - if (point_arg->read_index == REG_ARM64_ABS) { - /* return ptr; */ - } else if (point_arg->read_index == REG_ARM64_INDEX) { - if (arg_index == REG_ARM64_X0) { - ptr += reg_0; - } else if (arg_index <= REG_ARM64_LR) { - ptr += READ_KERN(ctx->regs[arg_index]); - } else { - ptr = 0; // never - } - } else if (point_arg->read_index == REG_ARM64_MAX) { - ptr = 0; // never - } else if (point_arg->read_index == REG_ARM64_PC) { - ptr += READ_KERN(ctx->pc); - } else if (point_arg->read_index == REG_ARM64_SP) { - ptr += READ_KERN(ctx->sp); - } else if (point_arg->read_index <= REG_ARM64_LR) { - if (point_arg->read_index == REG_ARM64_X0) { - ptr += reg_0; - } else { - ptr += READ_KERN(ctx->regs[point_arg->read_index]); - } - } else { - ptr = 0; // never - } - return ptr; -} - -static __always_inline u32 save_bytes_with_len(program_data_t p, u64 ptr, u32 read_len, u32 next_arg_index) { - if (read_len > MAX_BUF_READ_SIZE) { - read_len = MAX_BUF_READ_SIZE; - } - int status = save_bytes_to_buf(p.event, (void *)(ptr & 0xffffffffff), read_len, next_arg_index); - if (status == 0) { - buf_t *zero_p = get_buf(ZERO_BUF_IDX); - if (zero_p == NULL) { - return next_arg_index; - } - save_bytes_to_buf(p.event, &zero_p->buf[0], read_len, next_arg_index); - } - next_arg_index += 1; - return next_arg_index; -} - -static __always_inline u32 read_ptr_arg(program_data_t p, struct point_arg_t* point_arg, u64 ptr, u32 read_count, u32 next_arg_index) { - // 这些都是常规的 指针 + 结构体 按照读取结构体的方式读取即可 - if (point_arg->alias_type == TYPE_PTHREAD_ATTR) { - // 结构体类型 直接读取对应大小的数据 具体转换交给前端 - u32 struct_size = MAX_BYTES_ARR_SIZE; - if (point_arg->read_count <= struct_size) { - struct_size = point_arg->read_count; - } - // 修复 MTE 读取可能不正常的情况 - int status = save_bytes_to_buf(p.event, (void *)(ptr & 0xffffffffff), struct_size, next_arg_index); - if (status == 0) { - // 保存失败的情况 比如 ptr 是一个非法的地址 ... - buf_t *zero_p = get_buf(ZERO_BUF_IDX); - if (zero_p == NULL) { - return next_arg_index; - } - // 这个时候填充一个全0的内容进去 不然前端不好解析 - save_bytes_to_buf(p.event, &zero_p->buf[0], struct_size, next_arg_index); - next_arg_index += 1; +static __always_inline u32 read_args(program_data_t p, point_args_t* point_args, op_ctx_t* op_ctx, struct pt_regs* regs) { + int zero = 0; + // op_config_t* op = NULL; + op_config_t* op = bpf_map_lookup_elem(&op_list, &zero); + for (int i = 0; i < MAX_OP_COUNT; i++) { + if (op != NULL && op_ctx->post_code != OP_SKIP) { + op_ctx->op_code = op_ctx->post_code; + op_ctx->post_code = OP_SKIP; } else { - next_arg_index += 1; - } - return next_arg_index; - } - return next_arg_index; -} - -static __always_inline u32 read_arg(program_data_t p, struct point_arg_t* point_arg, u64 ptr, u32 read_count, u32 next_arg_index) { - point_arg->tmp_index = FILTER_INDEX_NONE; - if (ptr == 0) { - return next_arg_index; - } - - if (point_arg->base_type == TYPE_POINTER) { - // 指针类型 通常读一下对应指针的数据即可 后续记得考虑兼容下32位 - // 读取指针所指向位置的值 并且保存 - u64 addr = 0; - bpf_probe_read_user(&addr, sizeof(addr), (void*) ptr); - save_to_submit_buf(p.event, (void *) &addr, sizeof(u64), next_arg_index); - next_arg_index += 1; - if (addr == 0) { - return next_arg_index; - } - // 指针的指针 暂时没有这个需求 - // next_arg_index = read_ptr_arg(p, point_arg, addr, read_count, next_arg_index); - return next_arg_index; - } - if (point_arg->base_type == TYPE_NONE) { - return next_arg_index; - } - if (point_arg->base_type == TYPE_NUM) { - // 这种具体类型转换交给前端做 - return next_arg_index; - } - if (point_arg->base_type == TYPE_STRING) { - u32 buf_off = 0; - buf_t *string_p = get_buf(STRING_BUF_IDX); - if (string_p == NULL) { - return next_arg_index; - } - __builtin_memset((void *) string_p, 0, sizeof(string_p)); - int status = bpf_probe_read_user(&string_p->buf[buf_off], MAX_STRING_SIZE, (void *)ptr); - if (status < 0) { - // MTE 其实也正常读取到了 - bpf_probe_read_user_str(&string_p->buf[buf_off], MAX_STRING_SIZE, (void *)ptr); + if (op_ctx->op_key_index >= MAX_OP_COUNT) return 0; + u32 op_key = point_args->op_key_list[op_ctx->op_key_index]; + // bpf_printk("[stackplz] op_key:%d\n", op_key); + op = bpf_map_lookup_elem(&op_list, &op_key); + if (unlikely(op == NULL)) return 0; + op_ctx->op_code = op->code; + op_ctx->post_code = op->post_code; + op_ctx->op_key_index += 1; } - // Q: 这里为什么不直接定义变量呢 - // A: 经过测试,发现直接定义变量 + 循环中赋值 + 循环中/外比较 => 会导致 argument list too long - // A: 但是从map中拿一个结构体出来不会受到影响,要注意的是记得每次重置结构体内容 - match_ctx_t* match_ctx = make_match_ctx(); - if (match_ctx == NULL) { - return next_arg_index; - } - match_ctx->apply_filter = 0; - match_ctx->match_blacklist = 0; - match_ctx->match_whitelist = 0; - for (int j = 0; j < MAX_FILTER_COUNT; j++) { - u32 filter_idx = point_arg->filter_idx[j]; - if (filter_idx != FILTER_INDEX_NONE) { - match_ctx->apply_filter = 1; - arg_filter_t* filter_config = bpf_map_lookup_elem(&arg_filter, &filter_idx); - // 按照设计这里必须不为NULL - if (filter_config == NULL) { - return next_arg_index; + // bpf_printk("[stackplz] index:%d value:%ld\n", op_ctx->op_key_index, op->value); + // bpf_printk("[stackplz] code:%d pre_code:%d post_code:%d\n", op->code, op->pre_code, op->post_code); + // bpf_printk("[stackplz] %d op_code:%d\n", i, op_ctx->op_code); + if (op_ctx->op_code == OP_SKIP) break; + switch (op_ctx->op_code) { + case OP_RESET_CTX: + op_ctx->break_count = 0; + op_ctx->reg_index = 0; + op_ctx->read_addr = 0; + op_ctx->read_len = 0; + op_ctx->reg_value = 0; + op_ctx->pointer_value = 0; + break; + case OP_SET_REG_INDEX: + op_ctx->reg_index = op->value; + break; + case OP_SET_READ_LEN: + op_ctx->read_len = op->value; + break; + case OP_SET_READ_LEN_REG_VALUE: + if (op_ctx->read_len > op_ctx->reg_value) { + op_ctx->read_len = op_ctx->reg_value; } - // 借助map来比较字符串: - // 1. 将读已经取到的字符串复制filter_config预设长度的内容到临时变量字符串 - // 2. 将该临时变量字符串作为key,字符串长度作为value更新到map中 - // 3. 以filter_config预设的字符串作为key,从map中取出值 - // 4. 能取到说明两个字符串相同,否则不匹配 - u32 startswith = strcmp_by_map(filter_config, string_p); - if (filter_config->filter_type == WHITELIST_FILTER && startswith == 1){ - match_ctx->match_whitelist = 1; - } else if (filter_config->filter_type == BLACKLIST_FILTER && startswith == 1){ - match_ctx->match_blacklist = 1; - } else if (filter_config->filter_type == REPLACE_FILTER && startswith == 1){ - // 将替换的参数 视作白名单处理 - match_ctx->match_whitelist = 1; - // replace 是替换内容的操作 实际上不影响过滤 - // 这里注意写入有一个截断符 由用户态完成处理 实际上让长度+1即可 - // u32 str_len = 256; - // if (str_len > filter_config->newstr_len) { - // str_len = filter_config->newstr_len; - // } - // 经过测试 bpf_probe_write_user 的 len 参数不能是动态的 - // 即使通过 if 设定一个上限也不行 - int write_status = bpf_probe_write_user((void *)(ptr & 0xffffffffff), filter_config->newstr_val, sizeof(filter_config->newstr_val)); - // bpf_printk("[syscall] ptr:0x%lx status:%d filter_index:%d\n", ptr, write_status, filter_config->filter_index); - // bpf_printk("[syscall] ptr:0x%lx old:%s\n", ptr, filter_config->newstr_val); - // bpf_printk("[syscall] ptr:0x%lx new:%s\n", ptr, string_p->buf); + break; + case OP_SET_READ_LEN_POINTER_VALUE: + // bpf_printk("[stackplz] OP_SET_READ_LEN_POINTER_VALUE old_len:%d new_len:%d\n", op_ctx->read_len, op_ctx->pointer_value); + if (op_ctx->read_len > op_ctx->pointer_value) { + op_ctx->read_len = op_ctx->pointer_value; } + break; + case OP_SET_READ_COUNT: + op_ctx->read_len *= op->value; + break; + case OP_ADD_OFFSET: + // bpf_printk("[stackplz] OP_ADD_OFFSET ptr:0x%lx add:%d\n", op_ctx->read_addr, op->value); + op_ctx->read_addr += op->value; + break; + case OP_SUB_OFFSET: + // bpf_printk("[stackplz] OP_SUB_OFFSET ptr:0x%lx sub:%d\n", op_ctx->read_addr, op->value); + op_ctx->read_addr -= op->value; + break; + case OP_MOVE_REG_VALUE: + op_ctx->read_addr = op_ctx->reg_value; + break; + case OP_MOVE_POINTER_VALUE: + op_ctx->read_addr = op_ctx->pointer_value; + break; + case OP_MOVE_TMP_VALUE: + op_ctx->read_addr = op_ctx->tmp_value; + break; + case OP_SET_TMP_VALUE: + op_ctx->tmp_value = op_ctx->read_addr; + break; + case OP_FOR_BREAK: + if (op_ctx->loop_count == 0) { + op_ctx->loop_index = op_ctx->op_key_index; + } + if (op_ctx->loop_count >= op_ctx->break_count) { + op_ctx->loop_count = 0; + op_ctx->break_count = 0; + op_ctx->loop_index = 0; + } else { + op_ctx->loop_count += 1; + op_ctx->op_key_index = op_ctx->loop_index; + } + break; + case OP_SET_BREAK_COUNT: + op_ctx->break_count = MAX_LOOP_COUNT; + if (op_ctx->break_count > op->value) { + op_ctx->break_count = op->value; + } + break; + case OP_SET_BREAK_COUNT_REG_VALUE: + op_ctx->break_count = MAX_LOOP_COUNT; + if (op_ctx->break_count > op_ctx->reg_value) { + op_ctx->break_count = op_ctx->reg_value; + } + break; + case OP_SET_BREAK_COUNT_POINTER_VALUE: + op_ctx->break_count = MAX_LOOP_COUNT; + if (op_ctx->break_count > op_ctx->pointer_value) { + op_ctx->break_count = op_ctx->pointer_value; + } + break; + case OP_SAVE_ADDR: + // bpf_printk("[stackplz] OP_SAVE_ADDR val:0x%lx idx:%d\n", op_ctx->read_addr, op_ctx->save_index); + save_to_submit_buf(p.event, (void *)&op_ctx->read_addr, sizeof(op_ctx->read_addr), op_ctx->save_index); + op_ctx->save_index += 1; + break; + case OP_READ_REG: + if (op->pre_code == OP_SET_REG_INDEX) { + op_ctx->reg_index = op->value; + } + // make ebpf verifier happy + if (op_ctx->reg_index >= REG_ARM64_MAX) { + return 0; + } + if (op_ctx->reg_index == 0) { + op_ctx->reg_value = op_ctx->reg_0; + } else { + op_ctx->reg_value = READ_KERN(regs->regs[op_ctx->reg_index]); + } + break; + case OP_SAVE_REG: + save_to_submit_buf(p.event, (void *)&op_ctx->reg_value, sizeof(op_ctx->reg_value), op_ctx->save_index); + op_ctx->save_index += 1; + break; + case OP_READ_POINTER: + if (op->pre_code == OP_ADD_OFFSET) { + bpf_probe_read_user(&op_ctx->pointer_value, sizeof(op_ctx->pointer_value), (void*)(op_ctx->read_addr + op->value)); + } else if (op->pre_code == OP_SUB_OFFSET) { + bpf_probe_read_user(&op_ctx->pointer_value, sizeof(op_ctx->pointer_value), (void*)(op_ctx->read_addr - op->value)); + } else { + bpf_probe_read_user(&op_ctx->pointer_value, sizeof(op_ctx->pointer_value), (void*)op_ctx->read_addr); + } + break; + case OP_SAVE_POINTER: + save_to_submit_buf(p.event, (void *)&op_ctx->pointer_value, sizeof(op_ctx->pointer_value), op_ctx->save_index); + op_ctx->save_index += 1; + break; + case OP_SAVE_STRUCT: + // fix memory tag + op_ctx->read_addr = op_ctx->read_addr & 0xffffffffff; + if (op->pre_code == OP_SET_READ_COUNT) { + op_ctx->read_len *= op->value; + } + if (op_ctx->read_len > MAX_BYTES_ARR_SIZE) { + op_ctx->read_len = MAX_BYTES_ARR_SIZE; + } + // bpf_printk("[stackplz] OP_SAVE_STRUCT ptr:0x%lx len:%d\n", op_ctx->read_addr, op_ctx->read_len); + int save_struct_status = save_bytes_to_buf(p.event, (void *)(op_ctx->read_addr), op_ctx->read_len, op_ctx->save_index); + if (save_struct_status == 0) { + // 保存失败的情况 比如是一个非法的地址 那么就填一个空的 buf + // 那么只会保存 save_index 和 size -> [save_index][size][] + // ? 这里的处理方法好像不对 应该没问题 因为失败的时候 buf_off 没有变化 + save_bytes_to_buf(p.event, 0, 0, op_ctx->save_index); + } + op_ctx->save_index += 1; + break; + case OP_FILTER_STRING: { + // 这里会受到循环次数的限制 + // 实测 384 可以 512 不行 除非有什么更好的优化方法 + op_ctx->skip_flag = 1; // 这里是 apply_filter 的意思 + arg_filter_t* filter = bpf_map_lookup_elem(&arg_filter, &op->value); + if (unlikely(filter == NULL)) return 0; + bool is_match = strcmp_by_map(op_ctx, filter); + if (filter->filter_type == WHITELIST_FILTER && is_match) { + op_ctx->match_whitelist = 1; + } else if (filter->filter_type == BLACKLIST_FILTER && is_match) { + op_ctx->match_blacklist = 1; + } + break; } - } - // 跳过逻辑: - // 1. 不与任何白名单规则匹配,跳过 - // 2. 与任意黑名单规则之一匹配,跳过 - if (match_ctx->apply_filter == 1) { - if (match_ctx->match_whitelist == 0 || match_ctx->match_blacklist == 1) { - point_arg->tmp_index = FILTER_INDEX_SKIP; - return next_arg_index; - } - } - save_str_to_buf(p.event, &string_p->buf[buf_off], next_arg_index); - next_arg_index += 1; - return next_arg_index; - } - if (point_arg->base_type == TYPE_STRING_ARR) { - save_str_arr_to_buf(p.event, (const char *const *) ptr /*ptr*/, next_arg_index); - next_arg_index += 1; - return next_arg_index; - } - - // 为了获取到具体的数据 进行特别处理 - // 单次提交不超过 ARGS_BUF_SIZE 所以 MAX_IOV_COUNT 最大设置为6 6 * 4096 + ... < ARGS_BUF_SIZE - // 对于 process_vm_readv/process_vm_writev 远程进程间传递数据 实际读取其中一个 iov 即可 - if (point_arg->base_type == TYPE_STRUCT && point_arg->alias_type == TYPE_IOVEC) { - save_to_submit_buf(p.event, (void *)&read_count, sizeof(u32), next_arg_index); - next_arg_index += 1; - for (int iov_index = 0; iov_index < MAX_IOV_COUNT; iov_index++) { - if (iov_index >= read_count) { - continue; - } - struct iovec iovec_ptr; - int errno = bpf_probe_read_user(&iovec_ptr, sizeof(iovec_ptr), (void*) ptr); - if (errno == 0) { - save_to_submit_buf(p.event, (void *)&iovec_ptr, sizeof(iovec_ptr), next_arg_index); - next_arg_index += 1; - u32 max_read_len = MAX_BUF_READ_SIZE; - if (iovec_ptr.iov_len <= max_read_len) { - max_read_len = iovec_ptr.iov_len; + case OP_SAVE_STRING: + // fix memory tag + op_ctx->read_addr = op_ctx->read_addr & 0xffffffffff; + u32 old_off = p.event->buf_off; + int save_string_status = save_str_to_buf(p.event, (void*) op_ctx->read_addr, op_ctx->save_index); + if (save_string_status == 0) { + // 失败的情况存一个空数据 暂时没有遇到 有待测试 + save_bytes_to_buf(p.event, 0, 0, op_ctx->save_index); + } else { + op_ctx->str_len = p.event->buf_off - (old_off + sizeof(int) + 1); } - next_arg_index = save_bytes_with_len(p, (u64)iovec_ptr.iov_base, max_read_len, next_arg_index); - } else { - // 可能有失败的情况 - buf_t *zero_p = get_buf(ZERO_BUF_IDX); - if (zero_p == NULL) { - return next_arg_index; + op_ctx->save_index += 1; + break; + case OP_SAVE_PTR_STRING: + { + u64 ptr = op_ctx->read_addr & 0xffffffffff; + bpf_probe_read_user(&ptr, sizeof(ptr), (void*) ptr); + save_to_submit_buf(p.event, (void *)&ptr, sizeof(ptr), op_ctx->save_index); + op_ctx->save_index += 1; + // 每次取出后使用前都要 fix 很坑 + ptr = ptr & 0xffffffffff; + int status = save_str_to_buf(p.event, (void*) ptr, op_ctx->save_index); + if (status == 0) { + save_bytes_to_buf(p.event, 0, 0, op_ctx->save_index); + // 为读取字符串数组设计的 + op_ctx->loop_count = op_ctx->break_count; } - save_bytes_to_buf(p.event, &zero_p->buf[0], MAX_BUF_READ_SIZE, next_arg_index); - next_arg_index += 1; + op_ctx->save_index += 1; + break; } - ptr = ptr + sizeof(iovec_ptr); + default: + // bpf_printk("[stackplz] unknown op code:%d\n", op->code); + break; } - return next_arg_index; + if (op_ctx->match_blacklist) break; } - if (point_arg->base_type == TYPE_STRUCT || point_arg->base_type == TYPE_ARRAY) { - // 结构体类型 直接读取对应大小的数据 具体转换交给前端 - u32 max_read_len = MAX_BYTES_ARR_SIZE; - read_count = read_count * point_arg->item_persize; - if (read_count <= max_read_len) { - max_read_len = read_count; - } - // 修复 MTE 读取可能不正常的情况 - int status = save_bytes_to_buf(p.event, (void *)(ptr & 0xffffffffff), max_read_len, next_arg_index); - if (status == 0) { - // 保存失败的情况 比如 ptr 是一个非法的地址 ... - buf_t *zero_p = get_buf(ZERO_BUF_IDX); - if (zero_p == NULL) { - return next_arg_index; - } - // 这个时候填充一个全0的内容进去 不然前端不好解析 - save_bytes_to_buf(p.event, &zero_p->buf[0], max_read_len, next_arg_index); - next_arg_index += 1; + // 跳过逻辑: + // 1. 不与任何白名单规则匹配,跳过 + // 2. 与任意黑名单规则之一匹配,跳过 + if (op_ctx->skip_flag == 1) { + if (op_ctx->match_whitelist == 0 || op_ctx->match_blacklist == 1) { + op_ctx->skip_flag = 1; } else { - next_arg_index += 1; + op_ctx->skip_flag = 0; } - return next_arg_index; + op_ctx->match_whitelist = 0; + op_ctx->match_blacklist = 0; } - return next_arg_index; + + return 0; } char __license[] SEC("license") = "GPL"; diff --git a/user/next/argtype/argtype_base.go b/user/argtype/argtype_base.go similarity index 99% rename from user/next/argtype/argtype_base.go rename to user/argtype/argtype_base.go index feb81db..48b73b1 100644 --- a/user/next/argtype/argtype_base.go +++ b/user/argtype/argtype_base.go @@ -4,7 +4,7 @@ import ( "bytes" "encoding/binary" "fmt" - . "stackplz/user/next/common" + . "stackplz/user/common" "stackplz/user/util" "strconv" "unsafe" diff --git a/user/next/argtype/argtype_complex.go b/user/argtype/argtype_complex.go similarity index 97% rename from user/next/argtype/argtype_complex.go rename to user/argtype/argtype_complex.go index bb92482..2284295 100644 --- a/user/next/argtype/argtype_complex.go +++ b/user/argtype/argtype_complex.go @@ -5,7 +5,7 @@ import ( "encoding/binary" "fmt" "reflect" - . "stackplz/user/next/common" + . "stackplz/user/common" "stackplz/user/util" "strings" "syscall" @@ -362,8 +362,21 @@ func r_BUFFER_X2() IArgType { return at } -func r_BUFFER_LEN(length uint32) IArgType { +func R_BUFFER_REG(reg_index uint32) IArgType { + at := RegisterNew(fmt.Sprintf("buffer_reg_%d", reg_index), BUFFER) + at.CleanOpList() + at.AddOp(OPC_SET_READ_LEN.NewValue(uint64(MAX_BUF_READ_SIZE))) + at.AddOp(BuildReadRegLen(uint64(reg_index))) + at.AddOp(OPC_SAVE_STRUCT) + return at +} + +func R_BUFFER_LEN(length uint32) IArgType { + if length > MAX_BUF_READ_SIZE { + panic(fmt.Sprintf("max buf read size:%d, provided:%d", MAX_BUF_READ_SIZE, length)) + } at := RegisterNew(fmt.Sprintf("buffer_len_%d", length), BUFFER) + at.CleanOpList() at.SetSize(length) at.AddOp(OPC_SET_READ_LEN.NewValue(uint64(length))) at.AddOp(OPC_SAVE_STRUCT) diff --git a/user/next/argtype/argtype_flags.go b/user/argtype/argtype_flags.go similarity index 99% rename from user/next/argtype/argtype_flags.go rename to user/argtype/argtype_flags.go index 1d96bb3..b3c136e 100644 --- a/user/next/argtype/argtype_flags.go +++ b/user/argtype/argtype_flags.go @@ -2,7 +2,7 @@ package argtype import ( "fmt" - . "stackplz/user/next/common" + . "stackplz/user/common" "strings" ) diff --git a/user/next/argtype/config_struct.go b/user/argtype/config_struct.go similarity index 100% rename from user/next/argtype/config_struct.go rename to user/argtype/config_struct.go diff --git a/user/next/argtype/const.go b/user/argtype/const.go similarity index 100% rename from user/next/argtype/const.go rename to user/argtype/const.go diff --git a/user/next/argtype/iargtype.go b/user/argtype/iargtype.go similarity index 99% rename from user/next/argtype/iargtype.go rename to user/argtype/iargtype.go index cc7e24c..7862ce0 100644 --- a/user/next/argtype/iargtype.go +++ b/user/argtype/iargtype.go @@ -3,7 +3,7 @@ package argtype import ( "bytes" "fmt" - . "stackplz/user/next/common" + . "stackplz/user/common" ) type IArgType interface { diff --git a/user/next/argtype/op_helper.go b/user/argtype/op_helper.go similarity index 100% rename from user/next/argtype/op_helper.go rename to user/argtype/op_helper.go diff --git a/user/next/common/const.go b/user/common/const.go similarity index 100% rename from user/next/common/const.go rename to user/common/const.go diff --git a/user/config/config_const.go b/user/config/config_const.go index 8cd5143..19e21b7 100644 --- a/user/config/config_const.go +++ b/user/config/config_const.go @@ -1,5 +1,13 @@ package config +const ( + EBPF_PROG_NONE uint32 = iota + EBPF_SYS_ENTER + EBPF_SYS_EXIT + EBPF_SYS_ALL + EBPF_UPROBE_ENTER +) + const MAX_COUNT = 1024 const MAX_FILTER_COUNT = 6 @@ -13,151 +21,151 @@ const ( // TRACE_STAT ) -const MAX_LOOP_COUNT = 6 -const MAX_BUF_READ_SIZE uint32 = 4096 +// const MAX_LOOP_COUNT = 6 +// const MAX_BUF_READ_SIZE uint32 = 4096 -const ( - REG_ARM64_X0 uint32 = iota - REG_ARM64_X1 - REG_ARM64_X2 - REG_ARM64_X3 - REG_ARM64_X4 - REG_ARM64_X5 - REG_ARM64_X6 - REG_ARM64_X7 - REG_ARM64_X8 - REG_ARM64_X9 - REG_ARM64_X10 - REG_ARM64_X11 - REG_ARM64_X12 - REG_ARM64_X13 - REG_ARM64_X14 - REG_ARM64_X15 - REG_ARM64_X16 - REG_ARM64_X17 - REG_ARM64_X18 - REG_ARM64_X19 - REG_ARM64_X20 - REG_ARM64_X21 - REG_ARM64_X22 - REG_ARM64_X23 - REG_ARM64_X24 - REG_ARM64_X25 - REG_ARM64_X26 - REG_ARM64_X27 - REG_ARM64_X28 - REG_ARM64_X29 - REG_ARM64_LR - REG_ARM64_SP - REG_ARM64_PC - REG_ARM64_MAX - REG_ARM64_INDEX - REG_ARM64_ABS -) +// const ( +// REG_ARM64_X0 uint32 = iota +// REG_ARM64_X1 +// REG_ARM64_X2 +// REG_ARM64_X3 +// REG_ARM64_X4 +// REG_ARM64_X5 +// REG_ARM64_X6 +// REG_ARM64_X7 +// REG_ARM64_X8 +// REG_ARM64_X9 +// REG_ARM64_X10 +// REG_ARM64_X11 +// REG_ARM64_X12 +// REG_ARM64_X13 +// REG_ARM64_X14 +// REG_ARM64_X15 +// REG_ARM64_X16 +// REG_ARM64_X17 +// REG_ARM64_X18 +// REG_ARM64_X19 +// REG_ARM64_X20 +// REG_ARM64_X21 +// REG_ARM64_X22 +// REG_ARM64_X23 +// REG_ARM64_X24 +// REG_ARM64_X25 +// REG_ARM64_X26 +// REG_ARM64_X27 +// REG_ARM64_X28 +// REG_ARM64_X29 +// REG_ARM64_LR +// REG_ARM64_SP +// REG_ARM64_PC +// REG_ARM64_MAX +// REG_ARM64_INDEX +// REG_ARM64_ABS +// ) + +// type FlagOp struct { +// Name string +// Value int32 +// } + +// var PermissionFlags []FlagOp = []FlagOp{ +// {"S_IFMT", int32(00170000)}, +// {"S_IFSOCK", int32(0140000)}, +// {"S_IFLNK", int32(0120000)}, +// {"S_IFREG", int32(0100000)}, +// {"S_IFBLK", int32(0060000)}, +// {"S_IFDIR", int32(0040000)}, +// {"S_IFCHR", int32(0020000)}, +// {"S_IFIFO", int32(0010000)}, +// {"S_ISUID", int32(0004000)}, +// {"S_ISGID", int32(0002000)}, +// {"S_ISVTX", int32(0001000)}, + +// {"S_IRWXU", int32(00700)}, +// {"S_IRUSR", int32(00400)}, +// {"S_IWUSR", int32(00200)}, +// {"S_IXUSR", int32(00100)}, + +// {"S_IRWXG", int32(00070)}, +// {"S_IRGRP", int32(00040)}, +// {"S_IWGRP", int32(00020)}, +// {"S_IXGRP", int32(00010)}, + +// {"S_IRWXO", int32(00007)}, +// {"S_IROTH", int32(00004)}, +// {"S_IWOTH", int32(00002)}, +// {"S_IXOTH", int32(00001)}, +// } + +// var ProtFlags []FlagOp = []FlagOp{ +// {"PROT_READ", int32(0x1)}, +// {"PROT_WRITE", int32(0x2)}, +// {"PROT_EXEC", int32(0x4)}, +// {"PROT_SEM", int32(0x8)}, +// // {"PROT_NONE", int32(0x0)}, +// {"PROT_GROWSDOWN", int32(0x01000000)}, +// {"PROT_GROWSUP", int32(0x02000000)}, +// } + +// var FileFlags []FlagOp = []FlagOp{ +// // https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/include/uapi/asm-generic/fcntl.h +// {"O_ACCMODE", int32(00000003)}, +// // {"O_RDONLY", int32(00000000)}, +// {"O_WRONLY", int32(00000001)}, +// {"O_RDWR", int32(00000002)}, +// {"O_CREAT", int32(00000100)}, +// {"O_EXCL", int32(00000200)}, +// {"O_NOCTTY", int32(00000400)}, +// {"O_TRUNC", int32(00001000)}, +// {"O_APPEND", int32(00002000)}, +// {"O_NONBLOCK", int32(00004000)}, +// {"O_DSYNC", int32(00010000)}, +// {"FASYNC", int32(00020000)}, +// // {"O_DIRECT", int32(00040000)}, +// // {"O_LARGEFILE", int32(00100000)}, +// // {"O_DIRECTORY", int32(00200000)}, +// // {"O_NOFOLLOW", int32(00400000)}, +// {"O_NOATIME", int32(01000000)}, +// {"O_CLOEXEC", int32(02000000)}, +// // 注意不同架构的 flag 定义不一样 +// // https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/arch/arm64/include/uapi/asm/fcntl.h +// {"O_DIRECTORY", int32(00040000)}, +// {"O_NOFOLLOW", int32(00100000)}, +// {"O_DIRECT", int32(00200000)}, +// {"O_LARGEFILE", int32(00400000)}, +// } + +// var MapFlags []FlagOp = []FlagOp{ +// {"MAP_SHARED", int32(0x01)}, +// {"MAP_PRIVATE", int32(0x02)}, +// {"MAP_SHARED_VALIDATE", int32(0x03)}, +// {"MAP_TYPE", int32(0x0f)}, +// {"MAP_FIXED", int32(0x10)}, +// {"MAP_ANONYMOUS", int32(0x20)}, +// {"MAP_POPULATE", int32(0x008000)}, +// {"MAP_NONBLOCK", int32(0x010000)}, +// {"MAP_STACK", int32(0x020000)}, +// {"MAP_HUGETLB", int32(0x040000)}, +// {"MAP_SYNC", int32(0x080000)}, +// {"MAP_FIXED_NOREPLACE", int32(0x100000)}, +// {"MAP_UNINITIALIZED", int32(0x4000000)}, +// } + +// var MreapFlags []FlagOp = []FlagOp{ +// {"MREMAP_MAYMOVE", 1}, +// {"MREMAP_FIXED", 2}, +// {"MREMAP_DONTUNMAP", 4}, +// } + +// var SocketTypes []FlagOp = []FlagOp{ +// {"SOCK_STREAM", int32(1)}, +// {"SOCK_DGRAM", int32(2)}, +// {"SOCK_RAW", int32(3)}, +// {"SOCK_RDM", int32(4)}, +// {"SOCK_SEQPACKET", int32(5)}, +// {"SOCK_DCCP", int32(6)}, +// {"SOCK_PACKET", int32(10)}, -type FlagOp struct { - Name string - Value int32 -} - -var PermissionFlags []FlagOp = []FlagOp{ - {"S_IFMT", int32(00170000)}, - {"S_IFSOCK", int32(0140000)}, - {"S_IFLNK", int32(0120000)}, - {"S_IFREG", int32(0100000)}, - {"S_IFBLK", int32(0060000)}, - {"S_IFDIR", int32(0040000)}, - {"S_IFCHR", int32(0020000)}, - {"S_IFIFO", int32(0010000)}, - {"S_ISUID", int32(0004000)}, - {"S_ISGID", int32(0002000)}, - {"S_ISVTX", int32(0001000)}, - - {"S_IRWXU", int32(00700)}, - {"S_IRUSR", int32(00400)}, - {"S_IWUSR", int32(00200)}, - {"S_IXUSR", int32(00100)}, - - {"S_IRWXG", int32(00070)}, - {"S_IRGRP", int32(00040)}, - {"S_IWGRP", int32(00020)}, - {"S_IXGRP", int32(00010)}, - - {"S_IRWXO", int32(00007)}, - {"S_IROTH", int32(00004)}, - {"S_IWOTH", int32(00002)}, - {"S_IXOTH", int32(00001)}, -} - -var ProtFlags []FlagOp = []FlagOp{ - {"PROT_READ", int32(0x1)}, - {"PROT_WRITE", int32(0x2)}, - {"PROT_EXEC", int32(0x4)}, - {"PROT_SEM", int32(0x8)}, - // {"PROT_NONE", int32(0x0)}, - {"PROT_GROWSDOWN", int32(0x01000000)}, - {"PROT_GROWSUP", int32(0x02000000)}, -} - -var FileFlags []FlagOp = []FlagOp{ - // https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/include/uapi/asm-generic/fcntl.h - {"O_ACCMODE", int32(00000003)}, - // {"O_RDONLY", int32(00000000)}, - {"O_WRONLY", int32(00000001)}, - {"O_RDWR", int32(00000002)}, - {"O_CREAT", int32(00000100)}, - {"O_EXCL", int32(00000200)}, - {"O_NOCTTY", int32(00000400)}, - {"O_TRUNC", int32(00001000)}, - {"O_APPEND", int32(00002000)}, - {"O_NONBLOCK", int32(00004000)}, - {"O_DSYNC", int32(00010000)}, - {"FASYNC", int32(00020000)}, - // {"O_DIRECT", int32(00040000)}, - // {"O_LARGEFILE", int32(00100000)}, - // {"O_DIRECTORY", int32(00200000)}, - // {"O_NOFOLLOW", int32(00400000)}, - {"O_NOATIME", int32(01000000)}, - {"O_CLOEXEC", int32(02000000)}, - // 注意不同架构的 flag 定义不一样 - // https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/arch/arm64/include/uapi/asm/fcntl.h - {"O_DIRECTORY", int32(00040000)}, - {"O_NOFOLLOW", int32(00100000)}, - {"O_DIRECT", int32(00200000)}, - {"O_LARGEFILE", int32(00400000)}, -} - -var MapFlags []FlagOp = []FlagOp{ - {"MAP_SHARED", int32(0x01)}, - {"MAP_PRIVATE", int32(0x02)}, - {"MAP_SHARED_VALIDATE", int32(0x03)}, - {"MAP_TYPE", int32(0x0f)}, - {"MAP_FIXED", int32(0x10)}, - {"MAP_ANONYMOUS", int32(0x20)}, - {"MAP_POPULATE", int32(0x008000)}, - {"MAP_NONBLOCK", int32(0x010000)}, - {"MAP_STACK", int32(0x020000)}, - {"MAP_HUGETLB", int32(0x040000)}, - {"MAP_SYNC", int32(0x080000)}, - {"MAP_FIXED_NOREPLACE", int32(0x100000)}, - {"MAP_UNINITIALIZED", int32(0x4000000)}, -} - -var MreapFlags []FlagOp = []FlagOp{ - {"MREMAP_MAYMOVE", 1}, - {"MREMAP_FIXED", 2}, - {"MREMAP_DONTUNMAP", 4}, -} - -var SocketTypes []FlagOp = []FlagOp{ - {"SOCK_STREAM", int32(1)}, - {"SOCK_DGRAM", int32(2)}, - {"SOCK_RAW", int32(3)}, - {"SOCK_RDM", int32(4)}, - {"SOCK_SEQPACKET", int32(5)}, - {"SOCK_DCCP", int32(6)}, - {"SOCK_PACKET", int32(10)}, - - {"SOCK_CLOEXEC", int32(02000000)}, - {"SOCK_NONBLOCK", int32(00004000)}, -} +// {"SOCK_CLOEXEC", int32(02000000)}, +// {"SOCK_NONBLOCK", int32(00004000)}, +// } diff --git a/user/config/config_filter.go b/user/config/config_filter.go index 3fc44c5..d111240 100644 --- a/user/config/config_filter.go +++ b/user/config/config_filter.go @@ -2,7 +2,7 @@ package config import ( "fmt" - "stackplz/user/next/common" + "stackplz/user/common" ) type ConfigMap struct { @@ -35,10 +35,8 @@ type ArgFilter struct { Filter_type uint32 Filter_index uint32 Num_val uint64 - OldStr_val [256]byte - OldStr_len uint32 - NewStr_val [256]byte - NewStr_len uint32 + Str_val [256]byte + Str_len uint32 } func (this *ArgFilter) Match(name string) bool { @@ -48,15 +46,15 @@ func (this *ArgFilter) Match(name string) bool { return name == fmt.Sprintf("f%d", this.Filter_index-1) } -func (this *ArgFilter) ToNext() NextArgFilter { - t := NextArgFilter{} +func (this *ArgFilter) ToEbpfValue() EArgFilter { + t := EArgFilter{} t.Filter_type = this.Filter_type - t.Str_len = this.OldStr_len - t.Str_val = this.OldStr_val + t.Str_len = this.Str_len + t.Str_val = this.Str_val return t } -type NextArgFilter struct { +type EArgFilter struct { Filter_type uint32 Str_val [common.MAX_STRCMP_LEN]byte Str_len uint32 diff --git a/user/config/config_global.go b/user/config/config_global.go index b342921..b29f727 100644 --- a/user/config/config_global.go +++ b/user/config/config_global.go @@ -44,7 +44,6 @@ type GlobalConfig struct { ExternalBTF string SysCall string NoSysCall string - Next bool } func NewGlobalConfig() *GlobalConfig { diff --git a/user/config/config_module.go b/user/config/config_module.go index eafe9df..a22a72e 100644 --- a/user/config/config_module.go +++ b/user/config/config_module.go @@ -6,8 +6,8 @@ import ( "log" "os" "regexp" - "stackplz/user/next/common" - next_config "stackplz/user/next/config" + "stackplz/user/argtype" + . "stackplz/user/common" "stackplz/user/util" "strconv" "strings" @@ -19,7 +19,7 @@ type StackUprobeConfig struct { arg_filter *[]ArgFilter LibName string LibPath string - Points []UprobeArgs + Points []*UprobeArgs } func ParseStrAsNum(v string) (uint64, error) { @@ -31,7 +31,7 @@ func ParseStrAsNum(v string) (uint64, error) { return op_value, nil } -func (this *StackUprobeConfig) ParseArgType(arg_str string) (ArgType, error) { +func (this *StackUprobeConfig) ParseArgType(arg_str string, point_arg *PointArg) error { // ./stackplz -n icu.nullptr.nativetest -l libc.so -w 0x5B950[*int:x20,*int:x20+4] -w 0x5B7BC[*int:x20,*int:x20+4] // ./stackplz -n com.xingin.xhs -l libart.so -w 0x4B8A74[str:x22,str:x8] --tname com.xingin.xhs --reg x28 // str @@ -39,10 +39,9 @@ func (this *StackUprobeConfig) ParseArgType(arg_str string) (ArgType, error) { // buf:64:sp+0x20-0x8 // 解析为单个参数的读取配置 -> 在何处读、读取类型 var err error = nil - var arg_type ArgType var to_ptr bool = false var type_name string = "" - var arg_index string = "" + var read_op_str string = "" var arg_filter string = "" var items []string // 参数是否为指针 @@ -58,9 +57,9 @@ func (this *StackUprobeConfig) ParseArgType(arg_str string) (ArgType, error) { type_name = items[0] } else if len(items) == 2 { type_name = items[0] - arg_index = items[1] + read_op_str = items[1] } else { - return arg_type, errors.New(fmt.Sprintf("parse arg_str:%s failed, err:%v", arg_str, err)) + return errors.New(fmt.Sprintf("parse arg_str:%s failed, err:%v", arg_str, err)) } // 提取参数过滤规则 filter_items := strings.SplitN(type_name, ".", 2) @@ -70,77 +69,81 @@ func (this *StackUprobeConfig) ParseArgType(arg_str string) (ArgType, error) { } switch type_name { case "int": - arg_type = EXP_INT + if to_ptr { + point_arg.SetTypeIndex(INT_PTR) + } else { + point_arg.SetTypeIndex(INT) + } case "uint": - arg_type = UINT32 + if to_ptr { + point_arg.SetTypeIndex(UINT_PTR) + } else { + point_arg.SetTypeIndex(UINT) + } case "int64": - arg_type = INT64 + point_arg.SetTypeIndex(INT64) case "uint64": - arg_type = UINT64 + point_arg.SetTypeIndex(UINT64) case "str": - arg_type = STRING + point_arg.SetTypeIndex(STRING) filter_names := strings.Split(arg_filter, ".") - for i, filter_name := range filter_names { - if i >= MAX_FILTER_COUNT { - break - } + for _, filter_name := range filter_names { for _, arg_filter := range *this.arg_filter { if arg_filter.Match(filter_name) { - arg_type.FilterIdx[i] = arg_filter.Filter_index + point_arg.AddFilterIndex(arg_filter.Filter_index) } } } + point_arg.SetGroupType(EBPF_UPROBE_ENTER) case "ptr": - arg_type = POINTER + point_arg.SetTypeIndex(POINTER) case "buf": - arg_type = BUFFER_T.NewReadCount(256) // 对于 buf 类型 其参数读取索引位于最后 - buf_items := strings.SplitN(arg_index, ":", 2) + // 0x89ab[buf:64,int] 命中hook点时读取 x0 处64字节数据 读取 x1 值 + // 0x89ab[buf:64:sp+0x20-0x8] 命中hook点时读取 sp+0x20-0x8 处64字节数据 + // 0x89ab[buf:x1:sp+0x20-0x8] 命中hook点时读取 sp+0x20-0x8 处x1寄存器大小字节数据 + // 命令行读取的时候默认读取大小为 256 可以指定为比这个更大的数 但是不能超过 4096 + at := argtype.R_BUFFER_LEN(256) + buf_items := strings.SplitN(read_op_str, ":", 2) var size_str = "" if len(buf_items) == 1 { size_str = buf_items[0] - arg_index = "" + read_op_str = "" } else if len(buf_items) == 2 { size_str = buf_items[0] - arg_index = buf_items[1] + read_op_str = buf_items[1] } else { - return arg_type, errors.New(fmt.Sprintf("parse buf arg_str:%s failed", arg_str)) + return errors.New(fmt.Sprintf("parse buf arg_str:%s failed", arg_str)) } - if size_str == "" { - break - } - // base 指定为 0 的时候 会自动判断是不是16进制 但必须有 0x/0X 前缀 - size, err := strconv.ParseUint(size_str, 0, 32) - if err == nil { - arg_type.SetReadCount(uint32(size)) - } else { - count_index, err := ParseAsReg(size_str) - if err != nil { - return arg_type, errors.New(fmt.Sprintf("parse size_str:%s as hex/reg failed, arg_str:%s", size_str, arg_str)) + if size_str != "" { + // base 指定为 0 的时候 会自动判断是不是16进制 但必须有 0x/0X 前缀 + size, err := strconv.ParseUint(size_str, 0, 32) + if err == nil { + // 以指定长度作为读取大小 + at = argtype.R_BUFFER_LEN(uint32(size)) + } else { + // 以寄存器的值作为读取大小 + at = argtype.R_BUFFER_REG(GetRegIndex(size_str)) } - arg_type.SetCountIndex(count_index) } - case "pattr": - arg_type = PTHREAD_ATTR + point_arg.SetTypeIndex(at.GetTypeIndex()) + // 这个设定用于指示是否进一步读取和解析 + point_arg.SetGroupType(EBPF_UPROBE_ENTER) default: - err = errors.New(fmt.Sprintf("unsupported arg_type:%s", items[0])) + err = errors.New(fmt.Sprintf("unsupported type:%s", items[0])) } if err != nil { - return arg_type, err + return err } - if to_ptr { - // 实际上应该视作一个结构体 - arg_type = arg_type.NewBaseType(TYPE_STRUCT) - } - if arg_index != "" { - arg_index, read_offset := ParseArgIndex(arg_index) - read_index, err := ParseAsReg(arg_index) - if err != nil { - return arg_type, err - } - arg_type.SetReadIndex(read_index) + + if read_op_str != "" { + // read_op_str 0x12345[str:sp+0x20-0x8(+8(+16))] + // 即一系列 加、减、取指针 操作作为要读取类型的地址 + // 后续写一个解析规则来处理 + reg_name, read_offset := ParseArgIndex(read_op_str) + point_arg.SetRegIndex(GetRegIndex(reg_name)) if read_offset != "" { - var offset uint64 = 0 + var offset int64 = 0 if strings.HasPrefix(read_offset, "+") { op_add_items := strings.Split(read_offset, "+") for _, v := range op_add_items { @@ -151,17 +154,17 @@ func (this *StackUprobeConfig) ParseArgType(arg_str string) (ArgType, error) { op_sub_items := strings.Split(v, "-") op_value, err := ParseStrAsNum(op_sub_items[0]) if err != nil { - return arg_type, err + return err } - offset += op_value + offset += int64(op_value) if len(op_sub_items) > 1 { for _, v2 := range op_sub_items[1:] { v2 = strings.TrimSpace(v2) op_value, err := ParseStrAsNum(v2) if err != nil { - return arg_type, err + return err } - offset -= op_value + offset -= int64(op_value) } } } @@ -175,28 +178,31 @@ func (this *StackUprobeConfig) ParseArgType(arg_str string) (ArgType, error) { op_add_items := strings.Split(v, "+") op_value, err := ParseStrAsNum(op_add_items[0]) if err != nil { - return arg_type, err + return err } - offset -= op_value + offset -= int64(op_value) if len(op_add_items) > 1 { for _, v2 := range op_add_items[1:] { v2 = strings.TrimSpace(v2) op_value, err := ParseStrAsNum(v2) if err != nil { - return arg_type, err + return err } - offset += op_value + offset += int64(op_value) } } } } else { - return arg_type, errors.New(fmt.Sprintf("parse read_offset:%s failed", read_offset)) + return errors.New(fmt.Sprintf("parse read_offset:%s failed", read_offset)) + } + if offset > 0 { + point_arg.AddExtraOp(argtype.OPC_ADD_OFFSET.NewValue(uint64(offset))) + } else if offset < 0 { + point_arg.AddExtraOp(argtype.OPC_ADD_OFFSET.NewValue(uint64(offset))) } - arg_type.SetReadOffset(offset) } } - // fmt.Println("arg_type", arg_type.String()) - return arg_type, err + return err } func (this *StackUprobeConfig) IsEnable() bool { @@ -217,20 +223,17 @@ func (this *StackUprobeConfig) Parse_HookPoint(configs []string) (err error) { // strstr+0x0[str,str] 命中 strstr + 0x0 时将x0和x1读取为字符串 // write[int,buf:128,int] 命中 write 时将x0读取为int、x1读取为字节数组、x2读取为int - // 0x89ab[buf:64,int] 命中hook点时读取 x0 处64字节数据 读取 x1 值 - // 0x89ab[buf:64:sp+0x20-0x8] 命中hook点时读取 sp+0x20-0x8 处64字节数据 - // 0x89ab[buf:x1:sp+0x20-0x8] 命中hook点时读取 sp+0x20-0x8 处x1寄存器大小字节数据 for point_index, config_str := range configs { reg := regexp.MustCompile(`(\w+)(\+0x[[:xdigit:]]+)?(\[.+?\])?`) match := reg.FindStringSubmatch(config_str) if len(match) > 0 { - hook_point := UprobeArgs{} + hook_point := &UprobeArgs{} hook_point.Index = uint32(point_index) hook_point.Offset = 0x0 hook_point.LibPath = this.LibPath sym_or_off := match[1] - hook_point.PointName = sym_or_off + hook_point.Name = sym_or_off if strings.HasPrefix(sym_or_off, "0x") { offset, err := strconv.ParseUint(strings.TrimPrefix(sym_or_off, "0x"), 16, 64) if err != nil { @@ -256,13 +259,11 @@ func (this *StackUprobeConfig) Parse_HookPoint(configs []string) (err error) { args := strings.Split(hook_point.ArgsStr, ",") for arg_index, arg_str := range args { arg_name := fmt.Sprintf("arg_%d", arg_index) - arg := PointArg{arg_name, UPROBE_ENTER_READ, INT, "???"} - arg_type, err := this.ParseArgType(arg_str) - if err != nil { + point_arg := NewUprobePointArg(arg_name, POINTER, uint32(arg_index)) + if err := this.ParseArgType(arg_str, point_arg); err != nil { return err } - arg.ArgType = arg_type - hook_point.Args = append(hook_point.Args, arg) + hook_point.PointArgs = append(hook_point.PointArgs, point_arg) } } this.Points = append(this.Points, hook_point) @@ -278,16 +279,14 @@ type PointFilter struct { } type SyscallConfig struct { - logger *log.Logger - debug bool - arg_filter *[]ArgFilter - next_arg_filter *[]NextArgFilter - Enable bool - TraceMode uint32 - SyscallPointArgs []*SyscallPointArgs_T - NextPointArgs []*next_config.SyscallPoint - SysWhitelist []uint32 - SysBlacklist []uint32 + logger *log.Logger + debug bool + arg_filter *[]ArgFilter + Enable bool + TraceMode uint32 + PointArgs []*SyscallPoint + SysWhitelist []uint32 + SysBlacklist []uint32 } func (this *SyscallConfig) SetDebug(debug bool) { @@ -375,21 +374,11 @@ func (this *SyscallConfig) Parse_SysWhitelist(gconfig *GlobalConfig) { } } for _, v := range unique_items { - var index_items []uint32 - var next_index_items [][]uint32 + var index_items [][]uint32 syscall_name := v items := strings.SplitN(syscall_name, ":", 2) if len(items) == 2 { syscall_name = items[0] - filter_names := strings.Split(items[1], ".") - // 改成map好点 - for _, filter_name := range filter_names { - for _, arg_filter := range *this.arg_filter { - if arg_filter.Match(filter_name) { - index_items = append(index_items, arg_filter.Filter_index) - } - } - } filter_groups := strings.Split(items[1], "|") for _, filter_group := range filter_groups { @@ -402,60 +391,40 @@ func (this *SyscallConfig) Parse_SysWhitelist(gconfig *GlobalConfig) { } } } - next_index_items = append(next_index_items, items) - } - } - point := GetWatchPointByName(syscall_name) - nr_point, ok := (point).(*SysCallArgs) - if !ok { - panic(fmt.Sprintf("cast [%s] watchpoint to SysCallArgs failed", syscall_name)) - } - - point_args := nr_point.GetConfig() - for i := 0; i < len(point_args.ArgTypes); i++ { - t := &point_args.ArgTypes[i] - if t.ArgType == STRING { - for j := 0; j < MAX_FILTER_COUNT; j++ { - if j < len(index_items) { - t.FilterIdx[j] = index_items[j] - } - } + index_items = append(index_items, items) } } - if gconfig.Next { - point := next_config.GetSyscallPointByName(syscall_name) - for i, items := range next_index_items { - str_a_idx := 0 - for _, point_arg := range point.EnterPointArgs { - if point_arg.TypeIndex == common.STRING { - if str_a_idx == i { - for _, filter_index := range items { - if point_arg.ReadMore() { - point_arg.AddFilterIndex(filter_index) - } + point := GetSyscallPointByName(syscall_name) + for i, items := range index_items { + str_a_idx := 0 + for _, point_arg := range point.EnterPointArgs { + if point_arg.TypeIndex == STRING { + if str_a_idx == i { + for _, filter_index := range items { + if point_arg.ReadMore() { + point_arg.AddFilterIndex(filter_index) } } - str_a_idx += 1 } + str_a_idx += 1 } - str_b_idx := 0 - for _, point_arg := range point.ExitPointArgs { - if point_arg.TypeIndex == common.STRING { - if str_b_idx == i { - for _, filter_index := range items { - if point_arg.ReadMore() { - point_arg.AddFilterIndex(filter_index) - } + } + str_b_idx := 0 + for _, point_arg := range point.ExitPointArgs { + if point_arg.TypeIndex == STRING { + if str_b_idx == i { + for _, filter_index := range items { + if point_arg.ReadMore() { + point_arg.AddFilterIndex(filter_index) } } - str_b_idx += 1 } + str_b_idx += 1 } } - this.NextPointArgs = append(this.NextPointArgs, point) } - this.SyscallPointArgs = append(this.SyscallPointArgs, point_args) - this.SysWhitelist = append(this.SysWhitelist, uint32(nr_point.NR)) + this.PointArgs = append(this.PointArgs, point) + this.SysWhitelist = append(this.SysWhitelist, uint32(point.Nr)) } } @@ -465,12 +434,8 @@ func (this *SyscallConfig) Parse_SysBlacklist(text string) { } items := strings.Split(text, ",") for _, v := range items { - point := GetWatchPointByName(v) - nr_point, ok := (point).(*SysCallArgs) - if !ok { - panic(fmt.Sprintf("cast [%s] watchpoint to SysCallArgs failed", v)) - } - this.SysBlacklist = append(this.SysBlacklist, uint32(nr_point.NR)) + point := GetSyscallPointByName(v) + this.SysBlacklist = append(this.SysBlacklist, uint32(point.Nr)) } } @@ -481,21 +446,13 @@ func (this *SyscallConfig) IsEnable() bool { func (this *SyscallConfig) Info() string { var whitelist []string for _, v := range this.SysWhitelist { - point := GetWatchPointByNR(v) - nr_point, ok := (point).(*SysCallArgs) - if !ok { - panic(fmt.Sprintf("cast [%d] watchpoint to SysCallArgs failed", v)) - } - whitelist = append(whitelist, nr_point.Name()) + point := GetSyscallPointByNR(v) + whitelist = append(whitelist, point.Name) } var blacklist []string for _, v := range this.SysBlacklist { - point := GetWatchPointByNR(v) - nr_point, ok := (point).(*SysCallArgs) - if !ok { - panic(fmt.Sprintf("cast [%d] watchpoint to SysCallArgs failed", v)) - } - blacklist = append(blacklist, nr_point.Name()) + point := GetSyscallPointByNR(v) + blacklist = append(blacklist, point.Name) } return fmt.Sprintf("whitelist:[%s];blacklist:[%s]", strings.Join(whitelist, ","), strings.Join(blacklist, ",")) } @@ -538,7 +495,6 @@ type ModuleConfig struct { DumpHex bool ShowTime bool ShowUid bool - Next bool Name string StackUprobeConf *StackUprobeConfig @@ -652,34 +608,16 @@ func (this *ModuleConfig) Parse_ArgFilter(arg_filter []string) { if len(str_old) > 256 { panic(fmt.Sprintf("string is to long, max length is 256")) } - arg_filter.OldStr_len = uint32(len(str_old)) - copy(arg_filter.OldStr_val[:], str_old) + arg_filter.Str_len = uint32(len(str_old)) + copy(arg_filter.Str_val[:], str_old) case "b", "black": arg_filter.Filter_type = BLACKLIST_FILTER str_old := []byte(items[1]) if len(str_old) > 256 { panic(fmt.Sprintf("string is to long, max length is 256")) } - arg_filter.OldStr_len = uint32(len(str_old)) - copy(arg_filter.OldStr_val[:], str_old) - case "r", "replace": - r_items := strings.SplitN(items[1], ":::", 2) - if len(r_items) != 2 { - panic(fmt.Sprintf("parse replace ArgFilterRule failed, filter_str:%s", filter_str)) - } - arg_filter.Filter_type = REPLACE_FILTER - str_old := []byte(r_items[0]) - str_new := []byte(r_items[1]) - str_new = append(str_new, byte(0)) - if len(str_old) > 256 || len(str_new) > 256 { - panic(fmt.Sprintf("string is to long, max length is 256")) - } - arg_filter.OldStr_len = uint32(len(str_old)) - copy(arg_filter.OldStr_val[:], str_old) - // 注意这里长度 +1 是为了能写入一个 \0 - // 由于写用户态的函数必须提前指定长度 所以这里 NewStr_len 没有其作用 - arg_filter.NewStr_len = uint32(len(str_new) + 1) - copy(arg_filter.NewStr_val[:], str_new) + arg_filter.Str_len = uint32(len(str_old)) + copy(arg_filter.Str_val[:], str_old) default: panic(fmt.Sprintf("parse ArgFilterRule failed, filter_str:%s", filter_str)) } diff --git a/user/next/config/point_arg.go b/user/config/config_point_arg.go similarity index 76% rename from user/next/config/point_arg.go rename to user/config/config_point_arg.go index 5f36579..d2314cb 100644 --- a/user/next/config/point_arg.go +++ b/user/config/config_point_arg.go @@ -2,15 +2,15 @@ package config import ( "bytes" - "stackplz/user/next/argtype" - "stackplz/user/next/common" - . "stackplz/user/next/common" + "stackplz/user/argtype" + . "stackplz/user/common" ) type PointArg struct { Name string RegIndex uint32 TypeIndex uint32 + ExtraOpList []uint32 FilterIndexList []uint32 PointType uint32 GroupType uint32 @@ -20,6 +20,14 @@ func (this *PointArg) SetRegIndex(reg_index uint32) { this.RegIndex = reg_index } +func (this *PointArg) SetTypeIndex(type_index uint32) { + this.TypeIndex = type_index +} + +func (this *PointArg) AddExtraOp(op *argtype.OpConfig) { + this.ExtraOpList = append(this.ExtraOpList, op.Index) +} + func (this *PointArg) AddFilterIndex(filter_index uint32) { this.FilterIndexList = append(this.FilterIndexList, filter_index) } @@ -49,10 +57,14 @@ func (this *PointArg) GetOpList() []uint32 { } op_list = append(op_list, argtype.Add_READ_SAVE_REG(uint64(this.RegIndex)).Index) op_list = append(op_list, argtype.OPC_MOVE_REG_VALUE.Index) + if len(this.ExtraOpList) > 0 { + // 在基址的基础上做出系列 加、减、取指针 然后读取对应的类型 + panic("...") + } if this.ReadMore() { for _, op_key := range argtype.GetOpKeyList(this.TypeIndex) { op_list = append(op_list, op_key) - if this.TypeIndex == common.STRING { + if this.TypeIndex == STRING { for _, v := range this.FilterIndexList { filter_op := argtype.OPC_FILTER_STRING.NewValue(uint64(v)) op_list = append(op_list, filter_op.Index) @@ -90,3 +102,11 @@ func B(arg_name string, type_index uint32) *PointArg { func C(arg_name string, type_index uint32) *PointArg { return NewPointArg(arg_name, type_index, EBPF_SYS_ALL) } +func NewUprobePointArg(arg_name string, type_index, reg_index uint32) *PointArg { + point_arg := PointArg{} + point_arg.Name = arg_name + point_arg.RegIndex = reg_index + point_arg.TypeIndex = type_index + point_arg.PointType = EBPF_UPROBE_ENTER + return &point_arg +} diff --git a/user/config/config_syscall.go b/user/config/config_syscall.go index 2546107..d7fb200 100644 --- a/user/config/config_syscall.go +++ b/user/config/config_syscall.go @@ -1,548 +1,440 @@ package config -import ( - "encoding/binary" - "strings" - "syscall" - "unsafe" -) +// const ( +// TYPE_NONE uint32 = iota +// TYPE_NUM +// TYPE_EXP_INT +// TYPE_INT +// TYPE_UINT +// TYPE_INT8 +// TYPE_INT16 +// TYPE_UINT8 +// TYPE_UINT16 +// TYPE_INT32 +// TYPE_UINT32 +// TYPE_INT64 +// TYPE_UINT64 +// TYPE_STRING +// TYPE_STRING_ARR +// TYPE_POINTER +// TYPE_STRUCT +// TYPE_TIMESPEC +// TYPE_STAT +// TYPE_STATFS +// TYPE_SIGACTION +// TYPE_UTSNAME +// TYPE_SOCKADDR +// TYPE_RUSAGE +// TYPE_IOVEC +// TYPE_EPOLLEVENT +// TYPE_SIGSET +// TYPE_POLLFD +// TYPE_SYSINFO +// TYPE_SIGINFO +// TYPE_MSGHDR +// TYPE_ITIMERSPEC +// TYPE_STACK_T +// TYPE_TIMEVAL +// TYPE_TIMEZONE +// TYPE_PTHREAD_ATTR +// TYPE_ARRAY +// TYPE_ARRAY_INT32 +// TYPE_ARRAY_UINT32 +// TYPE_BUFFER +// ) -type SysCallArgs struct { - NR uint32 - PointArgs -} +// // func A(arg_name string, arg_type ArgType) PArg { +// // return PArg{arg_name, SYS_ENTER, arg_type, "???"} +// // } -type SArgs = SysCallArgs +// // func B(arg_name string, arg_type ArgType) PArg { +// // return PArg{arg_name, SYS_EXIT, arg_type, "???"} +// // } -type SyscallPointArgs_T struct { - NR uint32 - Count uint32 - ArgTypes [MAX_POINT_ARG_COUNT]FilterArgType - ArgTypeRet FilterArgType -} +// var NONE = AT(TYPE_NONE, TYPE_NONE, 0) -func (this *SysCallArgs) ParseFlag(value int32) string { - // 借助这个函数对 flags 进行解析 增强可读性 - var ops []FlagOp - switch this.PointArgs.PointName { - case "openat": - ops = FileFlags - case "mmap": - ops = MapFlags - case "mremap": - ops = MreapFlags - default: - return "" - } - return this.ParseOp(value, &ops) -} +// var EXP_INT = AT(TYPE_EXP_INT, TYPE_NUM, uint32(unsafe.Sizeof(int32(0)))) +// var INT = AT(TYPE_INT, TYPE_NUM, uint32(unsafe.Sizeof(int(0)))) +// var UINT = AT(TYPE_UINT, TYPE_NUM, uint32(unsafe.Sizeof(uint(0)))) +// var INT16 = AT(TYPE_INT16, TYPE_NUM, uint32(unsafe.Sizeof(int16(0)))) +// var UINT16 = AT(TYPE_UINT16, TYPE_NUM, uint32(unsafe.Sizeof(uint16(0)))) +// var INT32 = AT(TYPE_INT32, TYPE_NUM, uint32(unsafe.Sizeof(int32(0)))) +// var UINT32 = AT(TYPE_UINT32, TYPE_NUM, uint32(unsafe.Sizeof(uint32(0)))) +// var INT64 = AT(TYPE_INT64, TYPE_NUM, uint32(unsafe.Sizeof(int64(0)))) +// var UINT64 = AT(TYPE_UINT64, TYPE_NUM, uint32(unsafe.Sizeof(uint64(0)))) -func (this *SysCallArgs) ParseType(value int32) string { - var ops []FlagOp - switch this.PointArgs.PointName { - case "socket", "socketpair": - ops = SocketTypes - default: - return "" - } - return this.ParseOp(value, &ops) -} +// // typedef short unsigned int umode_t; +// var UMODE_T = UINT16.Clone() -func (this *SysCallArgs) ParseProt(value int32) string { - var ops []FlagOp - switch this.PointArgs.PointName { - case "mmap": - ops = ProtFlags - default: - return "" - } - return this.ParseOp(value, &ops) -} +// // unsigned long +// var ULONG = UINT64.Clone() -func (this *SysCallArgs) ParseMode(value int32) string { - var ops []FlagOp - switch this.PointArgs.PointName { - case "openat": - ops = PermissionFlags - default: - return "" - } - return this.ParseOp(value, &ops) -} +// var STRING = AT(TYPE_STRING, TYPE_STRING, uint32(unsafe.Sizeof(uint64(0)))) +// var STRING_ARR = AT(TYPE_STRING_ARR, TYPE_STRING_ARR, uint32(unsafe.Sizeof(uint64(0)))) +// var POINTER = AT(TYPE_POINTER, TYPE_POINTER, uint32(unsafe.Sizeof(uint64(0)))) +// var TIMESPEC = AT(TYPE_TIMESPEC, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Timespec{}))) +// var STAT = AT(TYPE_STAT, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Stat_t{}))) +// var STATFS = AT(TYPE_STATFS, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Statfs_t{}))) +// var SIGACTION = AT(TYPE_SIGACTION, TYPE_STRUCT, uint32(unsafe.Sizeof(Sigaction{}))) +// var UTSNAME = AT(TYPE_UTSNAME, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Utsname{}))) +// var SOCKADDR = AT(TYPE_SOCKADDR, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.RawSockaddrUnix{}))) +// var RUSAGE = AT(TYPE_RUSAGE, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Rusage{}))) +// var IOVEC = AT(TYPE_IOVEC, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Iovec{}))) +// var EPOLLEVENT = AT(TYPE_EPOLLEVENT, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.EpollEvent{}))) +// var SYSINFO = AT(TYPE_SYSINFO, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Sysinfo_t{}))) +// var SIGINFO = AT(TYPE_SIGINFO, TYPE_STRUCT, uint32(unsafe.Sizeof(SigInfo{}))) +// var MSGHDR = AT(TYPE_MSGHDR, TYPE_STRUCT, uint32(unsafe.Sizeof(Msghdr{}))) +// var ITIMERSPEC = AT(TYPE_ITIMERSPEC, TYPE_STRUCT, uint32(unsafe.Sizeof(ItTmerspec{}))) +// var STACK_T = AT(TYPE_STACK_T, TYPE_STRUCT, uint32(unsafe.Sizeof(Stack_t{}))) +// var TIMEVAL = AT(TYPE_TIMEVAL, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Timeval{}))) +// var TIMEZONE = AT(TYPE_TIMEZONE, TYPE_STRUCT, uint32(unsafe.Sizeof(TimeZone_t{}))) +// var PTHREAD_ATTR = AT(TYPE_PTHREAD_ATTR, TYPE_STRUCT, uint32(binary.Size(Pthread_attr_t{}))) -func (this *SysCallArgs) ParseOp(value int32, ops *[]FlagOp) string { - var info []string - for _, op := range *ops { - if value&op.Value == op.Value { - info = append(info, op.Name) - } - } - if len(info) > 0 { - return "(" + strings.Join(info, "|") + ")" - } else { - return "" - } -} +// // 注意 ARRAY_T read_count item_persize 均为 1 +// var ARRAY_T = AT(TYPE_ARRAY, TYPE_ARRAY, 1) -func (this *SysCallArgs) GetConfig() *SyscallPointArgs_T { - var point_arg_types [MAX_POINT_ARG_COUNT]FilterArgType - for i := 0; i < MAX_POINT_ARG_COUNT; i++ { - if i+1 > len(this.Args) { - for j := 0; j < MAX_FILTER_COUNT; j++ { - point_arg_types[i].ArgType.FilterIdx[j] = FILTER_INDEX_NONE - } - } else { - point_arg_types[i].PointFlag = this.Args[i].PointFlag - point_arg_types[i].ArgType = this.Args[i].ArgType - } - } - var point_arg_type_ret FilterArgType - point_arg_type_ret.PointFlag = this.Ret.PointFlag - point_arg_type_ret.ArgType = this.Ret.ArgType - config := &SyscallPointArgs_T{ - NR: this.NR, - Count: uint32(len(this.Args)), - ArgTypes: point_arg_types, - ArgTypeRet: point_arg_type_ret, - } - return config -} +// // 常规数组 +// // item_persize 就是数组元素的大小 +// // read_count 则根据具体需要设定 +// var INT32_ARR = ARRAY_T.NewArrayArgType(TYPE_ARRAY_INT32, uint32(unsafe.Sizeof(int32(0)))) +// var UINT32_ARR = ARRAY_T.NewArrayArgType(TYPE_ARRAY_UINT32, uint32(unsafe.Sizeof(uint32(0)))) -const ( - TYPE_NONE uint32 = iota - TYPE_NUM - TYPE_EXP_INT - TYPE_INT - TYPE_UINT - TYPE_INT8 - TYPE_INT16 - TYPE_UINT8 - TYPE_UINT16 - TYPE_INT32 - TYPE_UINT32 - TYPE_INT64 - TYPE_UINT64 - TYPE_STRING - TYPE_STRING_ARR - TYPE_POINTER - TYPE_STRUCT - TYPE_TIMESPEC - TYPE_STAT - TYPE_STATFS - TYPE_SIGACTION - TYPE_UTSNAME - TYPE_SOCKADDR - TYPE_RUSAGE - TYPE_IOVEC - TYPE_EPOLLEVENT - TYPE_SIGSET - TYPE_POLLFD - TYPE_SYSINFO - TYPE_SIGINFO - TYPE_MSGHDR - TYPE_ITIMERSPEC - TYPE_STACK_T - TYPE_TIMEVAL - TYPE_TIMEZONE - TYPE_PTHREAD_ATTR - TYPE_ARRAY - TYPE_ARRAY_INT32 - TYPE_ARRAY_UINT32 - TYPE_BUFFER -) +// // 特定类型的数组 +// // 例如 pipe2 的 pipefd 参数 是一个 int[2] +// // 那么设定 read_count 为2 +// var PIPEFD_T = INT32_ARR.NewReadCount(2) +// var SOCKET_SV = INT32_ARR.NewReadCount(2) -func A(arg_name string, arg_type ArgType) PArg { - return PArg{arg_name, SYS_ENTER, arg_type, "???"} -} +// // buffer数组 +// // 单个元素长度都是 1 +// // 但是为了在输出结果的时候进行区分 重置其类型 +// var BUFFER_T = ARRAY_T.NewAliasType(TYPE_BUFFER) -func B(arg_name string, arg_type ArgType) PArg { - return PArg{arg_name, SYS_EXIT, arg_type, "???"} -} +// // BUFFER 的一个特点 其长度可能由某个参数所控制 +// var READ_BUFFER_T = BUFFER_T.NewCountIndex(2) +// var WRITE_BUFFER_T = BUFFER_T.NewCountIndex(2) +// var MPROTECT_BUFFER_T = BUFFER_T.NewCountIndex(1) -var NONE = AT(TYPE_NONE, TYPE_NONE, 0) +// var IOVEC_T = IOVEC.NewCountIndex(2) -var EXP_INT = AT(TYPE_EXP_INT, TYPE_NUM, uint32(unsafe.Sizeof(int32(0)))) -var INT = AT(TYPE_INT, TYPE_NUM, uint32(unsafe.Sizeof(int(0)))) -var UINT = AT(TYPE_UINT, TYPE_NUM, uint32(unsafe.Sizeof(uint(0)))) -var INT16 = AT(TYPE_INT16, TYPE_NUM, uint32(unsafe.Sizeof(int16(0)))) -var UINT16 = AT(TYPE_UINT16, TYPE_NUM, uint32(unsafe.Sizeof(uint16(0)))) -var INT32 = AT(TYPE_INT32, TYPE_NUM, uint32(unsafe.Sizeof(int32(0)))) -var UINT32 = AT(TYPE_UINT32, TYPE_NUM, uint32(unsafe.Sizeof(uint32(0)))) -var INT64 = AT(TYPE_INT64, TYPE_NUM, uint32(unsafe.Sizeof(int64(0)))) -var UINT64 = AT(TYPE_UINT64, TYPE_NUM, uint32(unsafe.Sizeof(uint64(0)))) +// // 64 位下这个是 unsigned long sig[_NSIG_WORDS] +// // #define _NSIG 64 +// // #define _NSIG_BPW __BITS_PER_LONG -> 64 或者 32 +// // #define _NSIG_WORDS (_NSIG / _NSIG_BPW) +// // unsigned long -> 4 +// var SIGSET = AT(TYPE_SIGSET, TYPE_STRUCT, 4*1) +// var POLLFD = AT(TYPE_POLLFD, TYPE_STRUCT, uint32(unsafe.Sizeof(Pollfd{}))) -// typedef short unsigned int umode_t; -var UMODE_T = UINT16.Clone() +// func init() { +// // 结构体成员相关 某些参数的成员是指针类型的情况 +// // Register(&PArgs{"sockaddr", []PArg{{"sockfd",EXP_INT}, {"addr", SOCKADDR}, {"addrlen", UINT32}}}) -// unsigned long -var ULONG = UINT64.Clone() - -var STRING = AT(TYPE_STRING, TYPE_STRING, uint32(unsafe.Sizeof(uint64(0)))) -var STRING_ARR = AT(TYPE_STRING_ARR, TYPE_STRING_ARR, uint32(unsafe.Sizeof(uint64(0)))) -var POINTER = AT(TYPE_POINTER, TYPE_POINTER, uint32(unsafe.Sizeof(uint64(0)))) -var TIMESPEC = AT(TYPE_TIMESPEC, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Timespec{}))) -var STAT = AT(TYPE_STAT, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Stat_t{}))) -var STATFS = AT(TYPE_STATFS, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Statfs_t{}))) -var SIGACTION = AT(TYPE_SIGACTION, TYPE_STRUCT, uint32(unsafe.Sizeof(Sigaction{}))) -var UTSNAME = AT(TYPE_UTSNAME, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Utsname{}))) -var SOCKADDR = AT(TYPE_SOCKADDR, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.RawSockaddrUnix{}))) -var RUSAGE = AT(TYPE_RUSAGE, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Rusage{}))) -var IOVEC = AT(TYPE_IOVEC, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Iovec{}))) -var EPOLLEVENT = AT(TYPE_EPOLLEVENT, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.EpollEvent{}))) -var SYSINFO = AT(TYPE_SYSINFO, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Sysinfo_t{}))) -var SIGINFO = AT(TYPE_SIGINFO, TYPE_STRUCT, uint32(unsafe.Sizeof(SigInfo{}))) -var MSGHDR = AT(TYPE_MSGHDR, TYPE_STRUCT, uint32(unsafe.Sizeof(Msghdr{}))) -var ITIMERSPEC = AT(TYPE_ITIMERSPEC, TYPE_STRUCT, uint32(unsafe.Sizeof(ItTmerspec{}))) -var STACK_T = AT(TYPE_STACK_T, TYPE_STRUCT, uint32(unsafe.Sizeof(Stack_t{}))) -var TIMEVAL = AT(TYPE_TIMEVAL, TYPE_STRUCT, uint32(unsafe.Sizeof(syscall.Timeval{}))) -var TIMEZONE = AT(TYPE_TIMEZONE, TYPE_STRUCT, uint32(unsafe.Sizeof(TimeZone_t{}))) -var PTHREAD_ATTR = AT(TYPE_PTHREAD_ATTR, TYPE_STRUCT, uint32(binary.Size(Pthread_attr_t{}))) - -// 注意 ARRAY_T read_count item_persize 均为 1 -var ARRAY_T = AT(TYPE_ARRAY, TYPE_ARRAY, 1) - -// 常规数组 -// item_persize 就是数组元素的大小 -// read_count 则根据具体需要设定 -var INT32_ARR = ARRAY_T.NewArrayArgType(TYPE_ARRAY_INT32, uint32(unsafe.Sizeof(int32(0)))) -var UINT32_ARR = ARRAY_T.NewArrayArgType(TYPE_ARRAY_UINT32, uint32(unsafe.Sizeof(uint32(0)))) - -// 特定类型的数组 -// 例如 pipe2 的 pipefd 参数 是一个 int[2] -// 那么设定 read_count 为2 -var PIPEFD_T = INT32_ARR.NewReadCount(2) -var SOCKET_SV = INT32_ARR.NewReadCount(2) - -// buffer数组 -// 单个元素长度都是 1 -// 但是为了在输出结果的时候进行区分 重置其类型 -var BUFFER_T = ARRAY_T.NewAliasType(TYPE_BUFFER) - -// BUFFER 的一个特点 其长度可能由某个参数所控制 -var READ_BUFFER_T = BUFFER_T.NewCountIndex(2) -var WRITE_BUFFER_T = BUFFER_T.NewCountIndex(2) -var MPROTECT_BUFFER_T = BUFFER_T.NewCountIndex(1) - -var IOVEC_T = IOVEC.NewCountIndex(2) - -// 64 位下这个是 unsigned long sig[_NSIG_WORDS] -// #define _NSIG 64 -// #define _NSIG_BPW __BITS_PER_LONG -> 64 或者 32 -// #define _NSIG_WORDS (_NSIG / _NSIG_BPW) -// unsigned long -> 4 -var SIGSET = AT(TYPE_SIGSET, TYPE_STRUCT, 4*1) -var POLLFD = AT(TYPE_POLLFD, TYPE_STRUCT, uint32(unsafe.Sizeof(Pollfd{}))) - -func init() { - // 结构体成员相关 某些参数的成员是指针类型的情况 - // Register(&PArgs{"sockaddr", []PArg{{"sockfd",EXP_INT}, {"addr", SOCKADDR}, {"addrlen", UINT32}}}) - - // syscall相关 - Register(&SArgs{0, PA("io_setup", []PArg{A("nr_events", UINT), A("ctx_idp", POINTER)})}) - Register(&SArgs{1, PA("io_destroy", []PArg{A("ctx", POINTER)})}) - Register(&SArgs{2, PA("io_submit", []PArg{A("ctx_id", POINTER), A("nr", UINT64), A("iocbpp", POINTER)})}) - Register(&SArgs{3, PA("io_cancel", []PArg{A("ctx_id", POINTER), A("iocb", POINTER), A("result", POINTER)})}) - Register(&SArgs{4, PA("io_getevents", []PArg{A("ctx_id", POINTER), A("min_nr", UINT64), A("nr", UINT64), A("events", POINTER), A("timeout", TIMESPEC)})}) - Register(&SArgs{5, PA("setxattr", []PArg{A("pathname", STRING), A("name", STRING), A("value", POINTER), A("size", INT), A("flags", EXP_INT)})}) - Register(&SArgs{6, PA("lsetxattr", []PArg{A("pathname", STRING), A("name", STRING), A("value", POINTER), A("size", INT), A("flags", EXP_INT)})}) - Register(&SArgs{7, PA("fsetxattr", []PArg{A("fd", EXP_INT), A("name", STRING), A("value", POINTER), A("size", INT), A("flags", EXP_INT)})}) - Register(&SArgs{8, PA("getxattr", []PArg{A("path", STRING), A("name", STRING), A("value", POINTER), A("size", INT)})}) - Register(&SArgs{9, PA("lgetxattr", []PArg{A("path", STRING), A("name", STRING), A("value", POINTER), A("size", INT)})}) - Register(&SArgs{10, PA("fgetxattr", []PArg{A("fd", EXP_INT), A("name", STRING), A("value", POINTER), A("size", INT)})}) - Register(&SArgs{11, PA("listxattr", []PArg{A("pathname", STRING), A("list", STRING), A("size", INT)})}) - Register(&SArgs{12, PA("llistxattr", []PArg{A("pathname", STRING), A("list", STRING), A("size", INT)})}) - Register(&SArgs{13, PA("flistxattr", []PArg{A("fd", EXP_INT), A("list", STRING), A("size", INT)})}) - Register(&SArgs{14, PA("removexattr", []PArg{A("pathname", STRING), A("name", STRING)})}) - Register(&SArgs{15, PA("lremovexattr", []PArg{A("pathname", STRING), A("name", STRING)})}) - Register(&SArgs{16, PA("fremovexattr", []PArg{A("fd", EXP_INT), A("name", STRING)})}) - Register(&SArgs{17, PA("getcwd", []PArg{B("buf", STRING), A("size", UINT64)})}) - Register(&SArgs{18, PA("lookup_dcookie", []PArg{A("cookie", INT), B("buffer", STRING), A("len", INT)})}) - Register(&SArgs{19, PA("eventfd2", []PArg{A("initval", INT), A("flags", EXP_INT)})}) - Register(&SArgs{20, PAI("epoll_create1", []PArg{A("flags", EXP_INT)})}) - Register(&SArgs{21, PAI("epoll_ctl", []PArg{A("epfd", INT), A("op", INT), A("fd", EXP_INT), A("event", EPOLLEVENT)})}) - Register(&SArgs{22, PAI("epoll_pwait", []PArg{A("epfd", INT), A("events", POINTER), A("maxevents", INT), A("timeout", INT), A("sigmask", SIGSET)})}) - Register(&SArgs{23, PAI("dup", []PArg{A("oldfd", EXP_INT)})}) - Register(&SArgs{24, PAI("dup3", []PArg{A("oldfd", EXP_INT), A("newfd", EXP_INT), A("flags", EXP_INT)})}) - Register(&SArgs{25, PA("fcntl", []PArg{A("fd", EXP_INT), A("cmd", INT), A("arg", INT)})}) - Register(&SArgs{26, PA("inotify_init1", []PArg{A("flags", EXP_INT)})}) - Register(&SArgs{27, PA("inotify_add_watch", []PArg{A("fd", EXP_INT), A("pathname", STRING), A("mask", INT)})}) - Register(&SArgs{28, PA("inotify_rm_watch", []PArg{A("fd", EXP_INT), A("wd", INT)})}) - Register(&SArgs{29, PA("ioctl", []PArg{A("fd", EXP_INT), A("request", UINT64), A("arg0", INT), A("arg1", INT), A("arg2", INT), A("arg3", INT)})}) - Register(&SArgs{30, PA("ioprio_set", []PArg{A("which", INT), A("who", INT), A("ioprio", INT)})}) - Register(&SArgs{31, PA("ioprio_get", []PArg{A("which", INT), A("who", INT)})}) - Register(&SArgs{32, PA("flock", []PArg{A("fd", EXP_INT), A("operation", INT)})}) - Register(&SArgs{33, PA("mknodat", []PArg{A("dfd", INT), A("filename", STRING), A("mode", UMODE_T), A("dev", INT)})}) - Register(&SArgs{34, PA("mkdirat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("mode", UMODE_T)})}) - Register(&SArgs{35, PA("unlinkat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{36, PA("symlinkat", []PArg{A("target", STRING), A("newdirfd", INT), A("linkpath", STRING)})}) - Register(&SArgs{37, PA("linkat", []PArg{A("olddirfd", INT), A("oldpath", STRING), A("newdirfd", INT), A("newpath", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{38, PA("renameat", []PArg{A("olddirfd", INT), A("oldpath", STRING), A("newdirfd", INT), A("newpath", STRING)})}) - Register(&SArgs{39, PA("umount2", []PArg{A("target", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{40, PA("mount", []PArg{A("source", INT), A("target", STRING), A("filesystemtype", STRING), A("mountflags", INT), A("data", POINTER)})}) - Register(&SArgs{41, PA("pivot_root", []PArg{A("new_root", STRING), A("put_old", STRING)})}) - Register(&SArgs{42, PA("nfsservctl", []PArg{A("cmd", INT), A("argp", POINTER), A("resp", POINTER)})}) - Register(&SArgs{43, PA("statfs", []PArg{A("path", STRING), B("buf", STATFS)})}) - Register(&SArgs{44, PA("fstatfs", []PArg{A("fd", EXP_INT), B("buf", STATFS)})}) - Register(&SArgs{45, PA("truncate", []PArg{A("path", STRING), A("length", INT)})}) - Register(&SArgs{46, PA("ftruncate", []PArg{A("fd", EXP_INT), A("length", INT)})}) - Register(&SArgs{47, PA("fallocate", []PArg{A("fd", EXP_INT), A("mode", EXP_INT), A("offset", INT), A("len", INT)})}) - Register(&SArgs{48, PA("faccessat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("flags", EXP_INT), A("mode", EXP_INT)})}) - Register(&SArgs{49, PA("chdir", []PArg{A("path", STRING)})}) - Register(&SArgs{50, PA("fchdir", []PArg{A("fd", EXP_INT)})}) - Register(&SArgs{51, PA("chroot", []PArg{A("path", STRING)})}) - Register(&SArgs{52, PA("fchmod", []PArg{A("fd", EXP_INT), A("mode", UMODE_T)})}) - Register(&SArgs{53, PA("fchmodat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("mode", UMODE_T), A("flags", EXP_INT)})}) - Register(&SArgs{54, PA("fchownat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("owner", INT), A("group", INT), A("flags", EXP_INT)})}) - Register(&SArgs{55, PA("fchown", []PArg{A("fd", EXP_INT), A("owner", INT), A("group", INT)})}) - Register(&SArgs{56, PAI("openat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("flags", EXP_INT), A("mode", UMODE_T)})}) - Register(&SArgs{57, PA("close", []PArg{A("fd", EXP_INT)})}) - Register(&SArgs{58, PA("vhangup", []PArg{})}) - Register(&SArgs{59, PA("pipe2", []PArg{B("pipefd", PIPEFD_T), A("flags", EXP_INT)})}) - Register(&SArgs{60, PA("quotactl", []PArg{A("cmd", INT), A("special", STRING), A("id", INT), A("addr", INT)})}) - Register(&SArgs{61, PA("getdents64", []PArg{A("fd", EXP_INT), B("dirp", POINTER), A("count", INT)})}) - Register(&SArgs{62, PA("lseek", []PArg{A("fd", EXP_INT), A("offset", INT), A("whence", INT)})}) - Register(&SArgs{63, PA("read", []PArg{A("fd", EXP_INT), B("buf", READ_BUFFER_T), A("count", INT)})}) - Register(&SArgs{64, PA("write", []PArg{A("fd", EXP_INT), A("buf", WRITE_BUFFER_T), A("count", INT)})}) - Register(&SArgs{65, PA("readv", []PArg{A("fd", EXP_INT), B("iov", IOVEC_T), A("iovcnt", INT)})}) - Register(&SArgs{66, PA("writev", []PArg{A("fd", EXP_INT), A("iov", IOVEC_T), A("iovcnt", INT)})}) - Register(&SArgs{67, PA("pread64", []PArg{A("fd", EXP_INT), B("buf", READ_BUFFER_T), A("count", INT), A("offset", INT)})}) - Register(&SArgs{68, PA("pwrite64", []PArg{A("fd", EXP_INT), A("buf", WRITE_BUFFER_T), A("count", INT), A("offset", INT)})}) - Register(&SArgs{69, PA("preadv", []PArg{A("fd", EXP_INT), B("iov", IOVEC_T), A("iovcnt", INT), A("offset", INT)})}) - Register(&SArgs{70, PA("pwritev", []PArg{A("fd", EXP_INT), A("iov", IOVEC_T), A("iovcnt", INT), A("offset", INT)})}) - Register(&SArgs{71, PA("sendfile", []PArg{A("out_fd", INT), A("in_fd", INT), A("offset", INT), A("count", INT)})}) - Register(&SArgs{72, PA("pselect6", []PArg{A("n", INT), A("inp", POINTER), A("outp", POINTER), A("exp", POINTER), A("tsp", TIMESPEC), A("sig", POINTER)})}) - Register(&SArgs{73, PA("ppoll", []PArg{A("fds", POLLFD), A("nfds", INT), A("tmo_p", TIMESPEC), A("sigmask", INT)})}) - Register(&SArgs{74, PA("signalfd4", []PArg{A("ufd", INT), A("user_mask", POINTER), A("sizemask", INT), A("flags", EXP_INT)})}) - Register(&SArgs{75, PA("vmsplice", []PArg{A("fd", EXP_INT), A("uiov", IOVEC_T), A("nr_segs", INT), A("flags", EXP_INT)})}) - Register(&SArgs{76, PA("splice", []PArg{A("fd_in", INT), A("off_in", INT), A("fd_out", INT), A("off_out", INT), A("len", INT), A("flags", EXP_INT)})}) - Register(&SArgs{77, PA("tee", []PArg{A("fdin", INT), A("fdout", INT), A("len", INT), A("flags", EXP_INT)})}) - Register(&SArgs{78, PA("readlinkat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), B("buf", STRING), A("bufsiz", INT)})}) - Register(&SArgs{79, PA("newfstatat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), B("statbuf", STAT), A("flags", EXP_INT)})}) - Register(&SArgs{80, PA("fstat", []PArg{A("fd", EXP_INT), B("statbuf", STAT)})}) - Register(&SArgs{81, PArgs{"sync", B("ret", NONE), []PArg{}}}) - Register(&SArgs{82, PA("fsync", []PArg{A("fd", EXP_INT)})}) - Register(&SArgs{83, PA("fdatasync", []PArg{A("fd", EXP_INT)})}) - Register(&SArgs{84, PA("sync_file_range", []PArg{A("fd", EXP_INT), A("offset", INT), A("nbytes", INT), A("flags", EXP_INT)})}) - Register(&SArgs{85, PA("timerfd_create", []PArg{A("clockid", INT), A("flags", EXP_INT)})}) - Register(&SArgs{86, PA("timerfd_settime", []PArg{A("fd", EXP_INT), A("flags", EXP_INT), A("new_value", ITIMERSPEC), A("old_value", ITIMERSPEC)})}) - Register(&SArgs{87, PA("timerfd_gettime", []PArg{A("fd", EXP_INT), B("curr_value", ITIMERSPEC)})}) - Register(&SArgs{88, PA("utimensat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("times", ITIMERSPEC), A("flags", EXP_INT)})}) - Register(&SArgs{89, PA("acct", []PArg{A("name", STRING)})}) - Register(&SArgs{90, PA("capget", []PArg{A("header", POINTER), A("dataptr", POINTER)})}) - Register(&SArgs{91, PA("capset", []PArg{A("header", POINTER), A("data", POINTER)})}) - Register(&SArgs{92, PA("personality", []PArg{A("personality", INT)})}) - Register(&SArgs{93, PArgs{"exit", B("ret", NONE), []PArg{A("status", INT)}}}) - Register(&SArgs{94, PArgs{"exit_group", B("ret", NONE), []PArg{A("status", INT)}}}) - Register(&SArgs{95, PA("waitid", []PArg{A("which", INT), A("upid", INT), A("infop", SIGINFO), A("options", INT), A("ru", RUSAGE)})}) - Register(&SArgs{96, PA("set_tid_address", []PArg{A("tidptr", POINTER)})}) - Register(&SArgs{97, PA("unshare", []PArg{A("unshare_flags", INT)})}) - Register(&SArgs{98, PA("futex", []PArg{A("uaddr", INT), A("futex_op", INT), A("val", INT), A("timeout", TIMESPEC)})}) - Register(&SArgs{99, PA("set_robust_list", []PArg{A("head", POINTER), A("len", INT)})}) - Register(&SArgs{100, PA("get_robust_list", []PArg{A("pid", INT), A("head_ptr", POINTER), A("len_ptr", INT)})}) - Register(&SArgs{101, PA("nanosleep", []PArg{A("req", TIMESPEC), A("rem", TIMESPEC)})}) - Register(&SArgs{102, PA("getitimer", []PArg{A("which", INT), A("value", POINTER)})}) - Register(&SArgs{103, PA("setitimer", []PArg{A("which", INT), A("value", POINTER), A("ovalue", POINTER)})}) - Register(&SArgs{104, PA("kexec_load", []PArg{A("entry", INT), A("nr_segments", INT), A("segments", POINTER), A("flags", EXP_INT)})}) - Register(&SArgs{105, PA("init_module", []PArg{A("umod", POINTER), A("len", INT), A("uargs", STRING)})}) - Register(&SArgs{106, PA("delete_module", []PArg{A("name_user", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{107, PA("timer_create", []PArg{A("which_clock", INT), A("timer_event_spec", POINTER), A("created_timer_id", INT)})}) - Register(&SArgs{108, PA("timer_gettime", []PArg{A("timer_id", INT), A("setting", POINTER)})}) - Register(&SArgs{109, PA("timer_getoverrun", []PArg{A("timer_id", INT)})}) - Register(&SArgs{110, PA("timer_settime", []PArg{A("timer_id", INT), A("flags", EXP_INT), A("new_setting", POINTER), A("old_setting", POINTER)})}) - Register(&SArgs{111, PA("timer_delete", []PArg{A("timer_id", INT)})}) - Register(&SArgs{112, PA("clock_settime", []PArg{A("clockid", INT), A("tp", TIMESPEC)})}) - Register(&SArgs{113, PA("clock_gettime", []PArg{A("clockid", INT), B("tp", TIMESPEC)})}) - Register(&SArgs{114, PA("clock_getres", []PArg{A("clockid", INT), B("res", TIMESPEC)})}) - Register(&SArgs{115, PA("clock_nanosleep", []PArg{A("clockid", INT), A("flags", EXP_INT), A("request", TIMESPEC), B("remain", TIMESPEC)})}) - Register(&SArgs{116, PA("syslog", []PArg{A("type", INT), A("bufp", STRING), A("len", INT)})}) - Register(&SArgs{117, PA("ptrace", []PArg{A("request", INT), A("pid", EXP_INT), A("addr", POINTER), A("data", POINTER)})}) - Register(&SArgs{118, PA("sched_setparam", []PArg{A("pid", INT), A("param", POINTER)})}) - Register(&SArgs{119, PA("sched_setscheduler", []PArg{A("pid", INT), A("policy", INT), A("param", POINTER)})}) - Register(&SArgs{120, PA("sched_getscheduler", []PArg{A("pid", INT)})}) - Register(&SArgs{121, PA("sched_getparam", []PArg{A("pid", INT), B("param", POINTER)})}) - Register(&SArgs{122, PA("sched_setaffinity", []PArg{A("pid", INT), A("cpusetsize", INT), A("mask", POINTER)})}) - Register(&SArgs{123, PA("sched_getaffinity", []PArg{A("pid", INT), A("cpusetsize", INT), B("mask", POINTER)})}) - Register(&SArgs{124, PA("sched_yield", []PArg{})}) - Register(&SArgs{125, PA("sched_get_priority_max", []PArg{A("policy", INT)})}) - Register(&SArgs{126, PA("sched_get_priority_min", []PArg{A("policy", INT)})}) - Register(&SArgs{127, PA("sched_rr_get_interval", []PArg{A("pid", INT), A("interval", TIMESPEC)})}) - Register(&SArgs{128, PA("restart_syscall", []PArg{})}) - Register(&SArgs{129, PA("kill", []PArg{A("pid", INT), A("sig", INT)})}) - Register(&SArgs{130, PA("tkill", []PArg{A("tid", INT), A("sig", INT)})}) - Register(&SArgs{131, PA("tgkill", []PArg{A("tgid", INT), A("tid", INT), A("sig", INT)})}) - Register(&SArgs{132, PA("sigaltstack", []PArg{A("ss", STACK_T), A("old_ss", STACK_T)})}) - Register(&SArgs{133, PA("rt_sigsuspend", []PArg{A("mask", SIGSET)})}) - Register(&SArgs{134, PA("rt_sigaction", []PArg{A("signum", INT), A("act", SIGACTION), A("oldact", SIGACTION)})}) - Register(&SArgs{135, PA("rt_sigprocmask", []PArg{A("how", INT), A("set", UINT64), A("oldset", UINT64), A("sigsetsize", INT)})}) - Register(&SArgs{136, PA("rt_sigpending", []PArg{A("uset", POINTER), A("sigsetsize", INT)})}) - Register(&SArgs{137, PA("rt_sigtimedwait", []PArg{A("uthese", POINTER), A("uinfo", SIGINFO), A("uts", TIMESPEC), A("sigsetsize", INT)})}) - Register(&SArgs{138, PA("rt_sigqueueinfo", []PArg{A("pid", INT), A("sig", INT), A("uinfo", SIGINFO)})}) - Register(&SArgs{139, PA("rt_sigreturn", []PArg{A("mask", INT)})}) - Register(&SArgs{140, PA("setpriority", []PArg{A("which", INT), A("who", INT), A("prio", INT)})}) - Register(&SArgs{141, PA("getpriority", []PArg{A("which", INT), A("who", INT)})}) - Register(&SArgs{142, PA("reboot", []PArg{A("magic1", INT), A("magic2", INT), A("cmd", INT), A("arg", POINTER)})}) - Register(&SArgs{143, PA("setregid", []PArg{A("rgid", INT), A("egid", INT)})}) - Register(&SArgs{144, PA("setgid", []PArg{A("gid", INT)})}) - Register(&SArgs{145, PA("setreuid", []PArg{A("ruid", INT), A("euid", INT)})}) - Register(&SArgs{146, PA("setuid", []PArg{A("uid", INT)})}) - Register(&SArgs{147, PA("setresuid", []PArg{A("ruid", INT), A("euid", INT), A("suid", INT)})}) - Register(&SArgs{148, PA("getresuid", []PArg{A("ruidp", INT), A("euidp", INT), A("suidp", INT)})}) - Register(&SArgs{149, PA("setresgid", []PArg{A("rgid", INT), A("egid", INT), A("sgid", INT)})}) - Register(&SArgs{150, PA("getresgid", []PArg{A("rgidp", INT), A("egidp", INT), A("sgidp", INT)})}) - Register(&SArgs{151, PA("setfsuid", []PArg{A("uid", INT)})}) - Register(&SArgs{152, PA("setfsgid", []PArg{A("gid", INT)})}) - Register(&SArgs{153, PA("times", []PArg{A("tbuf", POINTER)})}) - Register(&SArgs{154, PA("setpgid", []PArg{A("pid", INT), A("pgid", INT)})}) - Register(&SArgs{155, PA("getpgid", []PArg{A("pid", INT)})}) - Register(&SArgs{156, PA("getsid", []PArg{A("pid", INT)})}) - Register(&SArgs{157, PA("setsid", []PArg{})}) - Register(&SArgs{158, PA("getgroups", []PArg{A("gidsetsize", INT), A("grouplist", INT)})}) - Register(&SArgs{159, PA("setgroups", []PArg{A("gidsetsize", INT), A("grouplist", INT)})}) - Register(&SArgs{160, PA("uname", []PArg{B("buf", UTSNAME)})}) - Register(&SArgs{161, PA("sethostname", []PArg{A("name", STRING), A("len", INT)})}) - Register(&SArgs{162, PA("setdomainname", []PArg{A("name", STRING), A("len", INT)})}) - Register(&SArgs{163, PA("getrlimit", []PArg{A("resource", INT), B("rlim", POINTER)})}) - Register(&SArgs{164, PA("setrlimit", []PArg{A("resource", UTSNAME), A("rlim", POINTER)})}) - Register(&SArgs{165, PA("getrusage", []PArg{A("who", INT), B("usage", RUSAGE)})}) - Register(&SArgs{166, PA("umask", []PArg{A("mode", EXP_INT)})}) - Register(&SArgs{167, PA("prctl", []PArg{A("option", INT), A("arg2", UINT64), A("arg3", UINT64), A("arg4", UINT64), A("arg5", UINT64)})}) - Register(&SArgs{168, PA("getcpu", []PArg{A("cpup", INT), A("nodep", INT), A("unused", POINTER)})}) - Register(&SArgs{169, PA("gettimeofday", []PArg{B("tv", TIMEVAL), B("tz", TIMEZONE)})}) - Register(&SArgs{170, PA("settimeofday", []PArg{A("tv", TIMEVAL), A("tz", TIMEZONE)})}) - Register(&SArgs{171, PA("adjtimex", []PArg{A("txc_p", POINTER)})}) - Register(&SArgs{172, PA("getpid", []PArg{})}) - Register(&SArgs{173, PA("getppid", []PArg{})}) - Register(&SArgs{174, PA("getuid", []PArg{})}) - Register(&SArgs{175, PA("geteuid", []PArg{})}) - Register(&SArgs{176, PA("getgid", []PArg{})}) - Register(&SArgs{177, PA("getegid", []PArg{})}) - Register(&SArgs{178, PA("gettid", []PArg{})}) - Register(&SArgs{179, PA("sysinfo", []PArg{B("info", SYSINFO)})}) - Register(&SArgs{180, PA("mq_open", []PArg{A("u_name", STRING), A("oflag", INT), A("mode", UMODE_T), A("u_attr", POINTER)})}) - Register(&SArgs{181, PA("mq_unlink", []PArg{A("u_name", STRING)})}) - Register(&SArgs{182, PA("mq_timedsend", []PArg{A("mqdes", INT), A("u_msg_ptr", STRING), A("msg_len", INT), A("msg_prio", INT), A("u_abs_timeout", TIMESPEC)})}) - Register(&SArgs{183, PA("mq_timedreceive", []PArg{A("mqdes", INT), A("u_msg_ptr", STRING), A("msg_len", INT), A("u_msg_prio", INT), A("u_abs_timeout", TIMESPEC)})}) - Register(&SArgs{184, PA("mq_notify", []PArg{A("mqdes", INT), A("u_notification", POINTER)})}) - Register(&SArgs{185, PA("mq_getsetattr", []PArg{A("mqdes", INT), A("u_mqstat", POINTER), A("u_omqstat", POINTER)})}) - Register(&SArgs{186, PA("msgget", []PArg{A("key", INT), A("msgflg", INT)})}) - Register(&SArgs{187, PA("msgctl", []PArg{A("msqid", INT), A("cmd", INT), A("buf", POINTER)})}) - Register(&SArgs{188, PA("msgrcv", []PArg{A("msqid", INT), A("msgp", POINTER), A("msgsz", INT), A("msgtyp", UINT64), A("msgflg", INT)})}) - Register(&SArgs{189, PA("msgsnd", []PArg{A("msqid", INT), A("msgp", POINTER), A("msgsz", INT), A("msgflg", INT)})}) - Register(&SArgs{190, PA("semget", []PArg{A("key", INT), A("nsems", INT), A("semflg", INT)})}) - Register(&SArgs{191, PA("semctl", []PArg{A("semid", INT), A("semnum", INT), A("cmd", INT), A("arg", INT)})}) - Register(&SArgs{192, PA("semtimedop", []PArg{A("semid", INT), A("tsops", POINTER), A("nsops", INT), A("timeout", TIMESPEC)})}) - Register(&SArgs{193, PA("semop", []PArg{A("semid", INT), A("tsops", POINTER), A("nsops", INT)})}) - Register(&SArgs{194, PA("shmget", []PArg{A("key", INT), A("size", INT), A("shmflg", INT)})}) - Register(&SArgs{195, PA("shmctl", []PArg{A("shmid", INT), A("cmd", INT), A("buf", POINTER)})}) - Register(&SArgs{196, PA("shmat", []PArg{A("shmid", INT), A("shmaddr", POINTER), A("shmflg", INT)})}) - Register(&SArgs{197, PA("shmdt", []PArg{A("shmaddr", POINTER)})}) - Register(&SArgs{198, PAI("socket", []PArg{A("domain", EXP_INT), A("type", EXP_INT), A("protocol", EXP_INT)})}) - Register(&SArgs{199, PAI("socketpair", []PArg{A("domain", EXP_INT), A("type", EXP_INT), A("protocol", EXP_INT), B("sv", SOCKET_SV)})}) - Register(&SArgs{200, PAI("bind", []PArg{A("sockfd", EXP_INT), A("addr", SOCKADDR), A("addrlen", EXP_INT)})}) - Register(&SArgs{201, PAI("listen", []PArg{A("sockfd", EXP_INT), A("backlog", INT)})}) - Register(&SArgs{202, PAI("accept", []PArg{A("sockfd", EXP_INT), A("addr", SOCKADDR), A("addrlen", EXP_INT)})}) - Register(&SArgs{203, PAI("connect", []PArg{A("sockfd", EXP_INT), A("addr", SOCKADDR), A("addrlen", EXP_INT)})}) - Register(&SArgs{204, PAI("getsockname", []PArg{A("sockfd", EXP_INT), B("addr", SOCKADDR), A("addrlen", EXP_INT)})}) - Register(&SArgs{205, PAI("getpeername", []PArg{A("sockfd", EXP_INT), B("addr", SOCKADDR), A("addrlen", EXP_INT)})}) - Register(&SArgs{206, PAI("sendto", []PArg{A("sockfd", EXP_INT), A("buf", READ_BUFFER_T), A("len", INT), A("flags", EXP_INT), A("dest_addr", SOCKADDR), A("addrlen", EXP_INT)})}) - Register(&SArgs{207, PAI("recvfrom", []PArg{A("sockfd", EXP_INT), B("buf", WRITE_BUFFER_T), A("len", INT), A("flags", EXP_INT)})}) - Register(&SArgs{208, PAI("setsockopt", []PArg{A("sockfd", EXP_INT), A("level", INT), A("optname", INT), A("optval", INT), A("optlen", INT)})}) - Register(&SArgs{209, PAI("getsockopt", []PArg{A("sockfd", EXP_INT), A("level", INT), A("optname", INT), B("optval", INT), A("optlen", POINTER)})}) - Register(&SArgs{210, PAI("shutdown", []PArg{A("sockfd", EXP_INT), A("how", INT)})}) - Register(&SArgs{211, PAI("sendmsg", []PArg{A("sockfd", EXP_INT), A("msg", MSGHDR), A("flags", EXP_INT)})}) - Register(&SArgs{212, PAI("recvmsg", []PArg{A("sockfd", EXP_INT), B("msg", MSGHDR), A("flags", EXP_INT)})}) - Register(&SArgs{213, PAI("readahead", []PArg{A("fd", EXP_INT), A("offset", INT), A("count", INT)})}) - Register(&SArgs{214, PA("brk", []PArg{A("brk", INT)})}) - Register(&SArgs{215, PAI("munmap", []PArg{A("addr", INT64), A("length", INT)})}) - Register(&SArgs{216, PA("mremap", []PArg{A("old_address", POINTER), A("old_size", INT), A("new_size", INT), A("flags", EXP_INT)})}) - Register(&SArgs{217, PA("add_key", []PArg{A("_type", STRING), A("_description", STRING), A("_payload", POINTER), A("plen", INT), A("ringid", INT)})}) - Register(&SArgs{218, PA("request_key", []PArg{A("_type", STRING), A("_description", STRING), A("_callout_info", STRING), A("destringid", INT)})}) - Register(&SArgs{219, PA("keyctl", []PArg{A("option", INT), A("arg2", INT), A("arg3", INT), A("arg4", INT), A("arg5", INT)})}) - Register(&SArgs{220, PA("clone", []PArg{A("fn", POINTER), A("stack", POINTER), A("flags", EXP_INT), A("arg0", INT), A("arg1", INT), A("arg2", INT)})}) - Register(&SArgs{221, PA("execve", []PArg{A("pathname", STRING), A("argv", STRING_ARR), A("envp", STRING_ARR)})}) - Register(&SArgs{222, PA("mmap", []PArg{B("addr", POINTER), A("length", INT), A("prot", EXP_INT), A("flags", EXP_INT), A("fd", EXP_INT), A("offset", INT)})}) - Register(&SArgs{223, PA("fadvise64", []PArg{A("fd", EXP_INT), A("offset", INT), A("len", INT), A("advice", INT)})}) - Register(&SArgs{224, PA("swapon", []PArg{A("specialfile", STRING), A("swap_flags", INT)})}) - Register(&SArgs{225, PA("swapoff", []PArg{A("specialfile", STRING)})}) - Register(&SArgs{226, PAI("mprotect", []PArg{A("addr", POINTER), A("length", INT), A("prot", EXP_INT)})}) - Register(&SArgs{227, PA("msync", []PArg{A("addr", POINTER), A("length", INT), A("flags", EXP_INT)})}) - Register(&SArgs{228, PA("mlock", []PArg{A("start", INT), A("len", INT)})}) - Register(&SArgs{229, PA("munlock", []PArg{A("start", INT), A("len", INT)})}) - Register(&SArgs{230, PA("mlockall", []PArg{A("flags", EXP_INT)})}) - Register(&SArgs{231, PA("munlockall", []PArg{})}) - Register(&SArgs{232, PA("mincore", []PArg{A("start", INT), A("len", INT), A("vec", STRING)})}) - Register(&SArgs{233, PA("madvise", []PArg{A("addr", POINTER), A("len", INT), A("advice", INT)})}) - Register(&SArgs{234, PA("remap_file_pages", []PArg{A("start", INT), A("size", INT), A("prot", EXP_INT), A("pgoff", INT), A("flags", EXP_INT)})}) - Register(&SArgs{235, PA("mbind", []PArg{A("start", ULONG), A("len", ULONG), A("mode", ULONG), A("nmask", INT), A("maxnode", INT), A("flags", EXP_INT)})}) - Register(&SArgs{236, PA("get_mempolicy", []PArg{A("policy", INT), A("nmask", INT), A("maxnode", INT), A("addr", INT), A("flags", EXP_INT)})}) - Register(&SArgs{237, PA("set_mempolicy", []PArg{A("mode", EXP_INT), A("nmask", INT), A("maxnode", INT)})}) - Register(&SArgs{238, PA("migrate_pages", []PArg{A("pid", INT), A("maxnode", INT), A("old_nodes", INT), A("new_nodes", INT)})}) - Register(&SArgs{239, PA("move_pages", []PArg{A("pid", INT), A("nr_pages", INT), A("pages", POINTER), A("nodes", INT), A("status", INT), A("flags", EXP_INT)})}) - Register(&SArgs{240, PA("rt_tgsigqueueinfo", []PArg{A("tgid", INT), A("tid", INT), A("sig", INT), A("siginfo", SIGINFO)})}) - Register(&SArgs{241, PA("perf_event_open", []PArg{A("attr_uptr", POINTER), A("pid", INT), A("cpu", INT), A("group_fd", INT), A("flags", EXP_INT)})}) - Register(&SArgs{242, PAI("accept4", []PArg{A("sockfd", EXP_INT), A("addr", SOCKADDR), A("addrlen", EXP_INT), A("flags", EXP_INT)})}) - Register(&SArgs{243, PA("recvmmsg", []PArg{A("fd", EXP_INT), A("mmsg", POINTER), A("vlen", INT), A("flags", EXP_INT), A("timeout", TIMESPEC)})}) - Register(&SArgs{260, PA("wait4", []PArg{A("pid", INT), A("wstatus", POINTER), A("options", INT), B("rusage", RUSAGE)})}) - Register(&SArgs{261, PA("prlimit64", []PArg{A("pid", INT), A("resource", INT), A("new_rlim", POINTER), A("old_rlim", POINTER)})}) - Register(&SArgs{262, PA("fanotify_init", []PArg{A("flags", EXP_INT), A("event_f_flags", INT)})}) - Register(&SArgs{263, PA("fanotify_mark", []PArg{A("fanotify_fd", INT), A("flags", EXP_INT), A("mask", UINT64), A("dfd", INT), A("pathname", STRING)})}) - Register(&SArgs{264, PA("name_to_handle_at", []PArg{A("dfd", INT), A("name", STRING), A("handle", POINTER), A("mnt_id", INT), A("flag", INT)})}) - Register(&SArgs{265, PA("open_by_handle_at", []PArg{A("mountdirfd", INT), A("handle", POINTER), A("flags", EXP_INT)})}) - Register(&SArgs{266, PA("clock_adjtime", []PArg{A("which_clock", INT), A("utx", POINTER)})}) - Register(&SArgs{267, PA("syncfs", []PArg{A("fd", EXP_INT)})}) - Register(&SArgs{268, PA("setns", []PArg{A("fd", EXP_INT), A("flags", EXP_INT)})}) - Register(&SArgs{269, PA("sendmmsg", []PArg{A("fd", EXP_INT), A("mmsg", POINTER), A("vlen", INT), A("flags", EXP_INT)})}) - // 虽然处于内核 但是实测无法跨进程读取数据 所以对于这两个系统调用 只能获取 local_iov 的内容 - Register(&SArgs{270, PAI("process_vm_readv", []PArg{A("pid", EXP_INT), B("local_iov", IOVEC_T), A("liovcnt", INT), A("remote_iov", POINTER), A("riovcnt", INT), A("flags", EXP_INT)})}) - Register(&SArgs{271, PAI("process_vm_writev", []PArg{A("pid", EXP_INT), A("local_iov", IOVEC_T), A("liovcnt", INT), B("remote_iov", POINTER), A("riovcnt", INT), A("flags", EXP_INT)})}) - Register(&SArgs{272, PA("kcmp", []PArg{A("pid1", INT), A("pid2", INT), A("type", INT), A("idx1", INT), A("idx2", INT)})}) - Register(&SArgs{273, PA("finit_module", []PArg{A("fd", EXP_INT), A("uargs", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{274, PA("sched_setattr", []PArg{A("pid", INT), A("uattr", POINTER), A("flags", EXP_INT)})}) - Register(&SArgs{275, PA("sched_getattr", []PArg{A("pid", INT), A("uattr", POINTER), A("usize", INT), A("flags", EXP_INT)})}) - Register(&SArgs{276, PA("renameat2", []PArg{A("olddirfd", INT), A("oldpath", STRING), A("newdirfd", INT), A("newpath", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{277, PA("seccomp", []PArg{A("operation", INT), A("flags", EXP_INT), A("args", POINTER)})}) - Register(&SArgs{278, PA("getrandom", []PArg{B("buf", POINTER), A("buflen", INT), A("flags", EXP_INT)})}) - Register(&SArgs{279, PA("memfd_create", []PArg{A("name", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{280, PA("bpf", []PArg{A("cmd", INT), A("attr", POINTER), A("size", INT)})}) - Register(&SArgs{281, PA("execveat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("argv", STRING_ARR), A("envp", STRING_ARR), A("flags", EXP_INT)})}) - Register(&SArgs{282, PA("userfaultfd", []PArg{A("flags", EXP_INT)})}) - Register(&SArgs{283, PA("membarrier", []PArg{A("cmd", INT), A("flags", POINTER), A("cpu_id", INT)})}) - Register(&SArgs{284, PA("mlock2", []PArg{A("start", INT), A("len", INT), A("flags", EXP_INT)})}) - Register(&SArgs{285, PA("copy_file_range", []PArg{A("fd_in", INT), A("off_in", INT), A("fd_out", INT), A("off_out", INT), A("len", INT), A("flags", EXP_INT)})}) - Register(&SArgs{286, PA("preadv2", []PArg{A("fd", EXP_INT), A("vec", POINTER), A("vlen", INT), A("pos_l", INT), A("pos_h", INT), A("flags", EXP_INT)})}) - Register(&SArgs{287, PA("pwritev2", []PArg{A("fd", EXP_INT), A("vec", POINTER), A("vlen", INT), A("pos_l", INT), A("pos_h", INT), A("flags", EXP_INT)})}) - Register(&SArgs{288, PA("pkey_mprotect", []PArg{B("addr", POINTER), A("length", INT), A("prot", EXP_INT), A("pkey", INT)})}) - Register(&SArgs{289, PA("pkey_alloc", []PArg{A("flags", EXP_INT), A("init_val", INT)})}) - Register(&SArgs{290, PA("pkey_free", []PArg{A("pkey", INT)})}) - Register(&SArgs{291, PA("statx", []PArg{A("dfd", INT), A("filename", STRING), A("flags", EXP_INT), A("mask", INT), A("buffer", POINTER)})}) - Register(&SArgs{292, PA("io_pgetevents", []PArg{A("ctx_id", POINTER), A("min_nr", UINT64), A("nr", UINT64), A("events", POINTER), A("timeout", TIMESPEC), A("usig", POINTER)})}) - Register(&SArgs{293, PA("rseq", []PArg{A("rseq", POINTER), A("rseq_len", INT), A("flags", EXP_INT), A("sig", INT)})}) - Register(&SArgs{294, PA("kexec_file_load", []PArg{A("kernel_fd", INT), A("initrd_fd", INT), A("cmdline_len", INT), A("cmdline_ptr", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{424, PA("pidfd_send_signal", []PArg{A("pidfd", INT), A("sig", INT), A("info", SIGINFO), A("flags", EXP_INT)})}) - Register(&SArgs{425, PA("io_uring_setup", []PArg{A("entries", INT), A("params", POINTER)})}) - Register(&SArgs{426, PA("io_uring_enter", []PArg{A("fd", EXP_INT), A("to_submit", INT), A("min_complete", INT), A("flags", EXP_INT), A("argp", POINTER), A("argsz", INT)})}) - Register(&SArgs{427, PA("io_uring_register", []PArg{A("fd", EXP_INT), A("opcode", INT), A("arg", POINTER), A("nr_args", INT)})}) - Register(&SArgs{428, PA("open_tree", []PArg{A("dfd", INT), A("filename", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{429, PA("move_mount", []PArg{A("from_dfd", INT), A("from_pathname", STRING), A("to_dfd", INT), A("to_pathname", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{430, PA("fsopen", []PArg{A("_fs_name", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{431, PA("fsconfig", []PArg{A("fd", EXP_INT), A("cmd", INT), A("_key", STRING), A("_value", POINTER), A("aux", INT)})}) - Register(&SArgs{432, PA("fsmount", []PArg{A("fs_fd", INT), A("flags", EXP_INT), A("attr_flags", INT)})}) - Register(&SArgs{433, PA("fspick", []PArg{A("dfd", INT), A("path", STRING), A("flags", EXP_INT)})}) - Register(&SArgs{434, PA("pidfd_open", []PArg{A("pid", INT), A("flags", EXP_INT)})}) - Register(&SArgs{435, PA("clone3", []PArg{A("uargs", POINTER), A("size", INT)})}) - Register(&SArgs{436, PA("close_range", []PArg{A("fd", EXP_INT), A("max_fd", INT), A("flags", EXP_INT)})}) - Register(&SArgs{437, PA("openat2", []PArg{A("dfd", INT), A("filename", STRING), A("how", POINTER), A("usize", INT)})}) - Register(&SArgs{438, PA("pidfd_getfd", []PArg{A("pidfd", INT), A("fd", EXP_INT), A("flags", EXP_INT)})}) - Register(&SArgs{439, PA("faccessat2", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("flags", EXP_INT), A("mode", EXP_INT)})}) - Register(&SArgs{440, PA("process_madvise", []PArg{A("pidfd", INT), A("vec", POINTER), A("vlen", INT), A("behavior", INT), A("flags", EXP_INT)})}) - Register(&SArgs{441, PAI("epoll_pwait2", []PArg{A("epfd", INT), A("events", POINTER), A("maxevents", INT), A("timeout", TIMESPEC), A("sigmask", POINTER), A("sigsetsize", INT)})}) - Register(&SArgs{442, PA("mount_setattr", []PArg{A("dfd", INT), A("path", STRING), A("flags", EXP_INT), A("uattr", POINTER), A("usize", INT)})}) - Register(&SArgs{443, PA("quotactl_fd", []PArg{A("fd", EXP_INT), A("cmd", INT), A("id", INT), A("addr", POINTER)})}) - Register(&SArgs{444, PA("landlock_create_ruleset", []PArg{A("attr", POINTER), A("size", INT), A("flags", EXP_INT)})}) - Register(&SArgs{445, PA("landlock_add_rule", []PArg{A("ruleset_fd", INT), A("rule_type", INT), A("rule_attr", POINTER), A("flags", EXP_INT)})}) - Register(&SArgs{446, PA("landlock_restrict_self", []PArg{A("ruleset_fd", INT), A("flags", EXP_INT)})}) - Register(&SArgs{447, PA("memfd_secret", []PArg{A("flags", EXP_INT)})}) - Register(&SArgs{448, PA("process_mrelease", []PArg{A("pidfd", INT), A("flags", EXP_INT)})}) - Register(&SArgs{449, PA("futex_waitv", []PArg{A("waiters", POINTER), A("nr_futexes", INT), A("flags", EXP_INT), A("timeout", TIMESPEC), A("clockid", INT)})}) - Register(&SArgs{450, PA("set_mempolicy_home_node", []PArg{A("start", INT), A("len", INT), A("home_node", INT), A("flags", EXP_INT)})}) -} +// // syscall相关 +// Register(&SArgs{0, PA("io_setup", []PArg{A("nr_events", UINT), A("ctx_idp", POINTER)})}) +// Register(&SArgs{1, PA("io_destroy", []PArg{A("ctx", POINTER)})}) +// Register(&SArgs{2, PA("io_submit", []PArg{A("ctx_id", POINTER), A("nr", UINT64), A("iocbpp", POINTER)})}) +// Register(&SArgs{3, PA("io_cancel", []PArg{A("ctx_id", POINTER), A("iocb", POINTER), A("result", POINTER)})}) +// Register(&SArgs{4, PA("io_getevents", []PArg{A("ctx_id", POINTER), A("min_nr", UINT64), A("nr", UINT64), A("events", POINTER), A("timeout", TIMESPEC)})}) +// Register(&SArgs{5, PA("setxattr", []PArg{A("pathname", STRING), A("name", STRING), A("value", POINTER), A("size", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{6, PA("lsetxattr", []PArg{A("pathname", STRING), A("name", STRING), A("value", POINTER), A("size", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{7, PA("fsetxattr", []PArg{A("fd", EXP_INT), A("name", STRING), A("value", POINTER), A("size", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{8, PA("getxattr", []PArg{A("path", STRING), A("name", STRING), A("value", POINTER), A("size", INT)})}) +// Register(&SArgs{9, PA("lgetxattr", []PArg{A("path", STRING), A("name", STRING), A("value", POINTER), A("size", INT)})}) +// Register(&SArgs{10, PA("fgetxattr", []PArg{A("fd", EXP_INT), A("name", STRING), A("value", POINTER), A("size", INT)})}) +// Register(&SArgs{11, PA("listxattr", []PArg{A("pathname", STRING), A("list", STRING), A("size", INT)})}) +// Register(&SArgs{12, PA("llistxattr", []PArg{A("pathname", STRING), A("list", STRING), A("size", INT)})}) +// Register(&SArgs{13, PA("flistxattr", []PArg{A("fd", EXP_INT), A("list", STRING), A("size", INT)})}) +// Register(&SArgs{14, PA("removexattr", []PArg{A("pathname", STRING), A("name", STRING)})}) +// Register(&SArgs{15, PA("lremovexattr", []PArg{A("pathname", STRING), A("name", STRING)})}) +// Register(&SArgs{16, PA("fremovexattr", []PArg{A("fd", EXP_INT), A("name", STRING)})}) +// Register(&SArgs{17, PA("getcwd", []PArg{B("buf", STRING), A("size", UINT64)})}) +// Register(&SArgs{18, PA("lookup_dcookie", []PArg{A("cookie", INT), B("buffer", STRING), A("len", INT)})}) +// Register(&SArgs{19, PA("eventfd2", []PArg{A("initval", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{20, PAI("epoll_create1", []PArg{A("flags", EXP_INT)})}) +// Register(&SArgs{21, PAI("epoll_ctl", []PArg{A("epfd", INT), A("op", INT), A("fd", EXP_INT), A("event", EPOLLEVENT)})}) +// Register(&SArgs{22, PAI("epoll_pwait", []PArg{A("epfd", INT), A("events", POINTER), A("maxevents", INT), A("timeout", INT), A("sigmask", SIGSET)})}) +// Register(&SArgs{23, PAI("dup", []PArg{A("oldfd", EXP_INT)})}) +// Register(&SArgs{24, PAI("dup3", []PArg{A("oldfd", EXP_INT), A("newfd", EXP_INT), A("flags", EXP_INT)})}) +// Register(&SArgs{25, PA("fcntl", []PArg{A("fd", EXP_INT), A("cmd", INT), A("arg", INT)})}) +// Register(&SArgs{26, PA("inotify_init1", []PArg{A("flags", EXP_INT)})}) +// Register(&SArgs{27, PA("inotify_add_watch", []PArg{A("fd", EXP_INT), A("pathname", STRING), A("mask", INT)})}) +// Register(&SArgs{28, PA("inotify_rm_watch", []PArg{A("fd", EXP_INT), A("wd", INT)})}) +// Register(&SArgs{29, PA("ioctl", []PArg{A("fd", EXP_INT), A("request", UINT64), A("arg0", INT), A("arg1", INT), A("arg2", INT), A("arg3", INT)})}) +// Register(&SArgs{30, PA("ioprio_set", []PArg{A("which", INT), A("who", INT), A("ioprio", INT)})}) +// Register(&SArgs{31, PA("ioprio_get", []PArg{A("which", INT), A("who", INT)})}) +// Register(&SArgs{32, PA("flock", []PArg{A("fd", EXP_INT), A("operation", INT)})}) +// Register(&SArgs{33, PA("mknodat", []PArg{A("dfd", INT), A("filename", STRING), A("mode", UMODE_T), A("dev", INT)})}) +// Register(&SArgs{34, PA("mkdirat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("mode", UMODE_T)})}) +// Register(&SArgs{35, PA("unlinkat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{36, PA("symlinkat", []PArg{A("target", STRING), A("newdirfd", INT), A("linkpath", STRING)})}) +// Register(&SArgs{37, PA("linkat", []PArg{A("olddirfd", INT), A("oldpath", STRING), A("newdirfd", INT), A("newpath", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{38, PA("renameat", []PArg{A("olddirfd", INT), A("oldpath", STRING), A("newdirfd", INT), A("newpath", STRING)})}) +// Register(&SArgs{39, PA("umount2", []PArg{A("target", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{40, PA("mount", []PArg{A("source", INT), A("target", STRING), A("filesystemtype", STRING), A("mountflags", INT), A("data", POINTER)})}) +// Register(&SArgs{41, PA("pivot_root", []PArg{A("new_root", STRING), A("put_old", STRING)})}) +// Register(&SArgs{42, PA("nfsservctl", []PArg{A("cmd", INT), A("argp", POINTER), A("resp", POINTER)})}) +// Register(&SArgs{43, PA("statfs", []PArg{A("path", STRING), B("buf", STATFS)})}) +// Register(&SArgs{44, PA("fstatfs", []PArg{A("fd", EXP_INT), B("buf", STATFS)})}) +// Register(&SArgs{45, PA("truncate", []PArg{A("path", STRING), A("length", INT)})}) +// Register(&SArgs{46, PA("ftruncate", []PArg{A("fd", EXP_INT), A("length", INT)})}) +// Register(&SArgs{47, PA("fallocate", []PArg{A("fd", EXP_INT), A("mode", EXP_INT), A("offset", INT), A("len", INT)})}) +// Register(&SArgs{48, PA("faccessat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("flags", EXP_INT), A("mode", EXP_INT)})}) +// Register(&SArgs{49, PA("chdir", []PArg{A("path", STRING)})}) +// Register(&SArgs{50, PA("fchdir", []PArg{A("fd", EXP_INT)})}) +// Register(&SArgs{51, PA("chroot", []PArg{A("path", STRING)})}) +// Register(&SArgs{52, PA("fchmod", []PArg{A("fd", EXP_INT), A("mode", UMODE_T)})}) +// Register(&SArgs{53, PA("fchmodat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("mode", UMODE_T), A("flags", EXP_INT)})}) +// Register(&SArgs{54, PA("fchownat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("owner", INT), A("group", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{55, PA("fchown", []PArg{A("fd", EXP_INT), A("owner", INT), A("group", INT)})}) +// Register(&SArgs{56, PAI("openat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("flags", EXP_INT), A("mode", UMODE_T)})}) +// Register(&SArgs{57, PA("close", []PArg{A("fd", EXP_INT)})}) +// Register(&SArgs{58, PA("vhangup", []PArg{})}) +// Register(&SArgs{59, PA("pipe2", []PArg{B("pipefd", PIPEFD_T), A("flags", EXP_INT)})}) +// Register(&SArgs{60, PA("quotactl", []PArg{A("cmd", INT), A("special", STRING), A("id", INT), A("addr", INT)})}) +// Register(&SArgs{61, PA("getdents64", []PArg{A("fd", EXP_INT), B("dirp", POINTER), A("count", INT)})}) +// Register(&SArgs{62, PA("lseek", []PArg{A("fd", EXP_INT), A("offset", INT), A("whence", INT)})}) +// Register(&SArgs{63, PA("read", []PArg{A("fd", EXP_INT), B("buf", READ_BUFFER_T), A("count", INT)})}) +// Register(&SArgs{64, PA("write", []PArg{A("fd", EXP_INT), A("buf", WRITE_BUFFER_T), A("count", INT)})}) +// Register(&SArgs{65, PA("readv", []PArg{A("fd", EXP_INT), B("iov", IOVEC_T), A("iovcnt", INT)})}) +// Register(&SArgs{66, PA("writev", []PArg{A("fd", EXP_INT), A("iov", IOVEC_T), A("iovcnt", INT)})}) +// Register(&SArgs{67, PA("pread64", []PArg{A("fd", EXP_INT), B("buf", READ_BUFFER_T), A("count", INT), A("offset", INT)})}) +// Register(&SArgs{68, PA("pwrite64", []PArg{A("fd", EXP_INT), A("buf", WRITE_BUFFER_T), A("count", INT), A("offset", INT)})}) +// Register(&SArgs{69, PA("preadv", []PArg{A("fd", EXP_INT), B("iov", IOVEC_T), A("iovcnt", INT), A("offset", INT)})}) +// Register(&SArgs{70, PA("pwritev", []PArg{A("fd", EXP_INT), A("iov", IOVEC_T), A("iovcnt", INT), A("offset", INT)})}) +// Register(&SArgs{71, PA("sendfile", []PArg{A("out_fd", INT), A("in_fd", INT), A("offset", INT), A("count", INT)})}) +// Register(&SArgs{72, PA("pselect6", []PArg{A("n", INT), A("inp", POINTER), A("outp", POINTER), A("exp", POINTER), A("tsp", TIMESPEC), A("sig", POINTER)})}) +// Register(&SArgs{73, PA("ppoll", []PArg{A("fds", POLLFD), A("nfds", INT), A("tmo_p", TIMESPEC), A("sigmask", INT)})}) +// Register(&SArgs{74, PA("signalfd4", []PArg{A("ufd", INT), A("user_mask", POINTER), A("sizemask", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{75, PA("vmsplice", []PArg{A("fd", EXP_INT), A("uiov", IOVEC_T), A("nr_segs", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{76, PA("splice", []PArg{A("fd_in", INT), A("off_in", INT), A("fd_out", INT), A("off_out", INT), A("len", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{77, PA("tee", []PArg{A("fdin", INT), A("fdout", INT), A("len", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{78, PA("readlinkat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), B("buf", STRING), A("bufsiz", INT)})}) +// Register(&SArgs{79, PA("newfstatat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), B("statbuf", STAT), A("flags", EXP_INT)})}) +// Register(&SArgs{80, PA("fstat", []PArg{A("fd", EXP_INT), B("statbuf", STAT)})}) +// Register(&SArgs{81, PArgs{"sync", B("ret", NONE), []PArg{}}}) +// Register(&SArgs{82, PA("fsync", []PArg{A("fd", EXP_INT)})}) +// Register(&SArgs{83, PA("fdatasync", []PArg{A("fd", EXP_INT)})}) +// Register(&SArgs{84, PA("sync_file_range", []PArg{A("fd", EXP_INT), A("offset", INT), A("nbytes", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{85, PA("timerfd_create", []PArg{A("clockid", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{86, PA("timerfd_settime", []PArg{A("fd", EXP_INT), A("flags", EXP_INT), A("new_value", ITIMERSPEC), A("old_value", ITIMERSPEC)})}) +// Register(&SArgs{87, PA("timerfd_gettime", []PArg{A("fd", EXP_INT), B("curr_value", ITIMERSPEC)})}) +// Register(&SArgs{88, PA("utimensat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("times", ITIMERSPEC), A("flags", EXP_INT)})}) +// Register(&SArgs{89, PA("acct", []PArg{A("name", STRING)})}) +// Register(&SArgs{90, PA("capget", []PArg{A("header", POINTER), A("dataptr", POINTER)})}) +// Register(&SArgs{91, PA("capset", []PArg{A("header", POINTER), A("data", POINTER)})}) +// Register(&SArgs{92, PA("personality", []PArg{A("personality", INT)})}) +// Register(&SArgs{93, PArgs{"exit", B("ret", NONE), []PArg{A("status", INT)}}}) +// Register(&SArgs{94, PArgs{"exit_group", B("ret", NONE), []PArg{A("status", INT)}}}) +// Register(&SArgs{95, PA("waitid", []PArg{A("which", INT), A("upid", INT), A("infop", SIGINFO), A("options", INT), A("ru", RUSAGE)})}) +// Register(&SArgs{96, PA("set_tid_address", []PArg{A("tidptr", POINTER)})}) +// Register(&SArgs{97, PA("unshare", []PArg{A("unshare_flags", INT)})}) +// Register(&SArgs{98, PA("futex", []PArg{A("uaddr", INT), A("futex_op", INT), A("val", INT), A("timeout", TIMESPEC)})}) +// Register(&SArgs{99, PA("set_robust_list", []PArg{A("head", POINTER), A("len", INT)})}) +// Register(&SArgs{100, PA("get_robust_list", []PArg{A("pid", INT), A("head_ptr", POINTER), A("len_ptr", INT)})}) +// Register(&SArgs{101, PA("nanosleep", []PArg{A("req", TIMESPEC), A("rem", TIMESPEC)})}) +// Register(&SArgs{102, PA("getitimer", []PArg{A("which", INT), A("value", POINTER)})}) +// Register(&SArgs{103, PA("setitimer", []PArg{A("which", INT), A("value", POINTER), A("ovalue", POINTER)})}) +// Register(&SArgs{104, PA("kexec_load", []PArg{A("entry", INT), A("nr_segments", INT), A("segments", POINTER), A("flags", EXP_INT)})}) +// Register(&SArgs{105, PA("init_module", []PArg{A("umod", POINTER), A("len", INT), A("uargs", STRING)})}) +// Register(&SArgs{106, PA("delete_module", []PArg{A("name_user", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{107, PA("timer_create", []PArg{A("which_clock", INT), A("timer_event_spec", POINTER), A("created_timer_id", INT)})}) +// Register(&SArgs{108, PA("timer_gettime", []PArg{A("timer_id", INT), A("setting", POINTER)})}) +// Register(&SArgs{109, PA("timer_getoverrun", []PArg{A("timer_id", INT)})}) +// Register(&SArgs{110, PA("timer_settime", []PArg{A("timer_id", INT), A("flags", EXP_INT), A("new_setting", POINTER), A("old_setting", POINTER)})}) +// Register(&SArgs{111, PA("timer_delete", []PArg{A("timer_id", INT)})}) +// Register(&SArgs{112, PA("clock_settime", []PArg{A("clockid", INT), A("tp", TIMESPEC)})}) +// Register(&SArgs{113, PA("clock_gettime", []PArg{A("clockid", INT), B("tp", TIMESPEC)})}) +// Register(&SArgs{114, PA("clock_getres", []PArg{A("clockid", INT), B("res", TIMESPEC)})}) +// Register(&SArgs{115, PA("clock_nanosleep", []PArg{A("clockid", INT), A("flags", EXP_INT), A("request", TIMESPEC), B("remain", TIMESPEC)})}) +// Register(&SArgs{116, PA("syslog", []PArg{A("type", INT), A("bufp", STRING), A("len", INT)})}) +// Register(&SArgs{117, PA("ptrace", []PArg{A("request", INT), A("pid", EXP_INT), A("addr", POINTER), A("data", POINTER)})}) +// Register(&SArgs{118, PA("sched_setparam", []PArg{A("pid", INT), A("param", POINTER)})}) +// Register(&SArgs{119, PA("sched_setscheduler", []PArg{A("pid", INT), A("policy", INT), A("param", POINTER)})}) +// Register(&SArgs{120, PA("sched_getscheduler", []PArg{A("pid", INT)})}) +// Register(&SArgs{121, PA("sched_getparam", []PArg{A("pid", INT), B("param", POINTER)})}) +// Register(&SArgs{122, PA("sched_setaffinity", []PArg{A("pid", INT), A("cpusetsize", INT), A("mask", POINTER)})}) +// Register(&SArgs{123, PA("sched_getaffinity", []PArg{A("pid", INT), A("cpusetsize", INT), B("mask", POINTER)})}) +// Register(&SArgs{124, PA("sched_yield", []PArg{})}) +// Register(&SArgs{125, PA("sched_get_priority_max", []PArg{A("policy", INT)})}) +// Register(&SArgs{126, PA("sched_get_priority_min", []PArg{A("policy", INT)})}) +// Register(&SArgs{127, PA("sched_rr_get_interval", []PArg{A("pid", INT), A("interval", TIMESPEC)})}) +// Register(&SArgs{128, PA("restart_syscall", []PArg{})}) +// Register(&SArgs{129, PA("kill", []PArg{A("pid", INT), A("sig", INT)})}) +// Register(&SArgs{130, PA("tkill", []PArg{A("tid", INT), A("sig", INT)})}) +// Register(&SArgs{131, PA("tgkill", []PArg{A("tgid", INT), A("tid", INT), A("sig", INT)})}) +// Register(&SArgs{132, PA("sigaltstack", []PArg{A("ss", STACK_T), A("old_ss", STACK_T)})}) +// Register(&SArgs{133, PA("rt_sigsuspend", []PArg{A("mask", SIGSET)})}) +// Register(&SArgs{134, PA("rt_sigaction", []PArg{A("signum", INT), A("act", SIGACTION), A("oldact", SIGACTION)})}) +// Register(&SArgs{135, PA("rt_sigprocmask", []PArg{A("how", INT), A("set", UINT64), A("oldset", UINT64), A("sigsetsize", INT)})}) +// Register(&SArgs{136, PA("rt_sigpending", []PArg{A("uset", POINTER), A("sigsetsize", INT)})}) +// Register(&SArgs{137, PA("rt_sigtimedwait", []PArg{A("uthese", POINTER), A("uinfo", SIGINFO), A("uts", TIMESPEC), A("sigsetsize", INT)})}) +// Register(&SArgs{138, PA("rt_sigqueueinfo", []PArg{A("pid", INT), A("sig", INT), A("uinfo", SIGINFO)})}) +// Register(&SArgs{139, PA("rt_sigreturn", []PArg{A("mask", INT)})}) +// Register(&SArgs{140, PA("setpriority", []PArg{A("which", INT), A("who", INT), A("prio", INT)})}) +// Register(&SArgs{141, PA("getpriority", []PArg{A("which", INT), A("who", INT)})}) +// Register(&SArgs{142, PA("reboot", []PArg{A("magic1", INT), A("magic2", INT), A("cmd", INT), A("arg", POINTER)})}) +// Register(&SArgs{143, PA("setregid", []PArg{A("rgid", INT), A("egid", INT)})}) +// Register(&SArgs{144, PA("setgid", []PArg{A("gid", INT)})}) +// Register(&SArgs{145, PA("setreuid", []PArg{A("ruid", INT), A("euid", INT)})}) +// Register(&SArgs{146, PA("setuid", []PArg{A("uid", INT)})}) +// Register(&SArgs{147, PA("setresuid", []PArg{A("ruid", INT), A("euid", INT), A("suid", INT)})}) +// Register(&SArgs{148, PA("getresuid", []PArg{A("ruidp", INT), A("euidp", INT), A("suidp", INT)})}) +// Register(&SArgs{149, PA("setresgid", []PArg{A("rgid", INT), A("egid", INT), A("sgid", INT)})}) +// Register(&SArgs{150, PA("getresgid", []PArg{A("rgidp", INT), A("egidp", INT), A("sgidp", INT)})}) +// Register(&SArgs{151, PA("setfsuid", []PArg{A("uid", INT)})}) +// Register(&SArgs{152, PA("setfsgid", []PArg{A("gid", INT)})}) +// Register(&SArgs{153, PA("times", []PArg{A("tbuf", POINTER)})}) +// Register(&SArgs{154, PA("setpgid", []PArg{A("pid", INT), A("pgid", INT)})}) +// Register(&SArgs{155, PA("getpgid", []PArg{A("pid", INT)})}) +// Register(&SArgs{156, PA("getsid", []PArg{A("pid", INT)})}) +// Register(&SArgs{157, PA("setsid", []PArg{})}) +// Register(&SArgs{158, PA("getgroups", []PArg{A("gidsetsize", INT), A("grouplist", INT)})}) +// Register(&SArgs{159, PA("setgroups", []PArg{A("gidsetsize", INT), A("grouplist", INT)})}) +// Register(&SArgs{160, PA("uname", []PArg{B("buf", UTSNAME)})}) +// Register(&SArgs{161, PA("sethostname", []PArg{A("name", STRING), A("len", INT)})}) +// Register(&SArgs{162, PA("setdomainname", []PArg{A("name", STRING), A("len", INT)})}) +// Register(&SArgs{163, PA("getrlimit", []PArg{A("resource", INT), B("rlim", POINTER)})}) +// Register(&SArgs{164, PA("setrlimit", []PArg{A("resource", UTSNAME), A("rlim", POINTER)})}) +// Register(&SArgs{165, PA("getrusage", []PArg{A("who", INT), B("usage", RUSAGE)})}) +// Register(&SArgs{166, PA("umask", []PArg{A("mode", EXP_INT)})}) +// Register(&SArgs{167, PA("prctl", []PArg{A("option", INT), A("arg2", UINT64), A("arg3", UINT64), A("arg4", UINT64), A("arg5", UINT64)})}) +// Register(&SArgs{168, PA("getcpu", []PArg{A("cpup", INT), A("nodep", INT), A("unused", POINTER)})}) +// Register(&SArgs{169, PA("gettimeofday", []PArg{B("tv", TIMEVAL), B("tz", TIMEZONE)})}) +// Register(&SArgs{170, PA("settimeofday", []PArg{A("tv", TIMEVAL), A("tz", TIMEZONE)})}) +// Register(&SArgs{171, PA("adjtimex", []PArg{A("txc_p", POINTER)})}) +// Register(&SArgs{172, PA("getpid", []PArg{})}) +// Register(&SArgs{173, PA("getppid", []PArg{})}) +// Register(&SArgs{174, PA("getuid", []PArg{})}) +// Register(&SArgs{175, PA("geteuid", []PArg{})}) +// Register(&SArgs{176, PA("getgid", []PArg{})}) +// Register(&SArgs{177, PA("getegid", []PArg{})}) +// Register(&SArgs{178, PA("gettid", []PArg{})}) +// Register(&SArgs{179, PA("sysinfo", []PArg{B("info", SYSINFO)})}) +// Register(&SArgs{180, PA("mq_open", []PArg{A("u_name", STRING), A("oflag", INT), A("mode", UMODE_T), A("u_attr", POINTER)})}) +// Register(&SArgs{181, PA("mq_unlink", []PArg{A("u_name", STRING)})}) +// Register(&SArgs{182, PA("mq_timedsend", []PArg{A("mqdes", INT), A("u_msg_ptr", STRING), A("msg_len", INT), A("msg_prio", INT), A("u_abs_timeout", TIMESPEC)})}) +// Register(&SArgs{183, PA("mq_timedreceive", []PArg{A("mqdes", INT), A("u_msg_ptr", STRING), A("msg_len", INT), A("u_msg_prio", INT), A("u_abs_timeout", TIMESPEC)})}) +// Register(&SArgs{184, PA("mq_notify", []PArg{A("mqdes", INT), A("u_notification", POINTER)})}) +// Register(&SArgs{185, PA("mq_getsetattr", []PArg{A("mqdes", INT), A("u_mqstat", POINTER), A("u_omqstat", POINTER)})}) +// Register(&SArgs{186, PA("msgget", []PArg{A("key", INT), A("msgflg", INT)})}) +// Register(&SArgs{187, PA("msgctl", []PArg{A("msqid", INT), A("cmd", INT), A("buf", POINTER)})}) +// Register(&SArgs{188, PA("msgrcv", []PArg{A("msqid", INT), A("msgp", POINTER), A("msgsz", INT), A("msgtyp", UINT64), A("msgflg", INT)})}) +// Register(&SArgs{189, PA("msgsnd", []PArg{A("msqid", INT), A("msgp", POINTER), A("msgsz", INT), A("msgflg", INT)})}) +// Register(&SArgs{190, PA("semget", []PArg{A("key", INT), A("nsems", INT), A("semflg", INT)})}) +// Register(&SArgs{191, PA("semctl", []PArg{A("semid", INT), A("semnum", INT), A("cmd", INT), A("arg", INT)})}) +// Register(&SArgs{192, PA("semtimedop", []PArg{A("semid", INT), A("tsops", POINTER), A("nsops", INT), A("timeout", TIMESPEC)})}) +// Register(&SArgs{193, PA("semop", []PArg{A("semid", INT), A("tsops", POINTER), A("nsops", INT)})}) +// Register(&SArgs{194, PA("shmget", []PArg{A("key", INT), A("size", INT), A("shmflg", INT)})}) +// Register(&SArgs{195, PA("shmctl", []PArg{A("shmid", INT), A("cmd", INT), A("buf", POINTER)})}) +// Register(&SArgs{196, PA("shmat", []PArg{A("shmid", INT), A("shmaddr", POINTER), A("shmflg", INT)})}) +// Register(&SArgs{197, PA("shmdt", []PArg{A("shmaddr", POINTER)})}) +// Register(&SArgs{198, PAI("socket", []PArg{A("domain", EXP_INT), A("type", EXP_INT), A("protocol", EXP_INT)})}) +// Register(&SArgs{199, PAI("socketpair", []PArg{A("domain", EXP_INT), A("type", EXP_INT), A("protocol", EXP_INT), B("sv", SOCKET_SV)})}) +// Register(&SArgs{200, PAI("bind", []PArg{A("sockfd", EXP_INT), A("addr", SOCKADDR), A("addrlen", EXP_INT)})}) +// Register(&SArgs{201, PAI("listen", []PArg{A("sockfd", EXP_INT), A("backlog", INT)})}) +// Register(&SArgs{202, PAI("accept", []PArg{A("sockfd", EXP_INT), A("addr", SOCKADDR), A("addrlen", EXP_INT)})}) +// Register(&SArgs{203, PAI("connect", []PArg{A("sockfd", EXP_INT), A("addr", SOCKADDR), A("addrlen", EXP_INT)})}) +// Register(&SArgs{204, PAI("getsockname", []PArg{A("sockfd", EXP_INT), B("addr", SOCKADDR), A("addrlen", EXP_INT)})}) +// Register(&SArgs{205, PAI("getpeername", []PArg{A("sockfd", EXP_INT), B("addr", SOCKADDR), A("addrlen", EXP_INT)})}) +// Register(&SArgs{206, PAI("sendto", []PArg{A("sockfd", EXP_INT), A("buf", READ_BUFFER_T), A("len", INT), A("flags", EXP_INT), A("dest_addr", SOCKADDR), A("addrlen", EXP_INT)})}) +// Register(&SArgs{207, PAI("recvfrom", []PArg{A("sockfd", EXP_INT), B("buf", WRITE_BUFFER_T), A("len", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{208, PAI("setsockopt", []PArg{A("sockfd", EXP_INT), A("level", INT), A("optname", INT), A("optval", INT), A("optlen", INT)})}) +// Register(&SArgs{209, PAI("getsockopt", []PArg{A("sockfd", EXP_INT), A("level", INT), A("optname", INT), B("optval", INT), A("optlen", POINTER)})}) +// Register(&SArgs{210, PAI("shutdown", []PArg{A("sockfd", EXP_INT), A("how", INT)})}) +// Register(&SArgs{211, PAI("sendmsg", []PArg{A("sockfd", EXP_INT), A("msg", MSGHDR), A("flags", EXP_INT)})}) +// Register(&SArgs{212, PAI("recvmsg", []PArg{A("sockfd", EXP_INT), B("msg", MSGHDR), A("flags", EXP_INT)})}) +// Register(&SArgs{213, PAI("readahead", []PArg{A("fd", EXP_INT), A("offset", INT), A("count", INT)})}) +// Register(&SArgs{214, PA("brk", []PArg{A("brk", INT)})}) +// Register(&SArgs{215, PAI("munmap", []PArg{A("addr", INT64), A("length", INT)})}) +// Register(&SArgs{216, PA("mremap", []PArg{A("old_address", POINTER), A("old_size", INT), A("new_size", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{217, PA("add_key", []PArg{A("_type", STRING), A("_description", STRING), A("_payload", POINTER), A("plen", INT), A("ringid", INT)})}) +// Register(&SArgs{218, PA("request_key", []PArg{A("_type", STRING), A("_description", STRING), A("_callout_info", STRING), A("destringid", INT)})}) +// Register(&SArgs{219, PA("keyctl", []PArg{A("option", INT), A("arg2", INT), A("arg3", INT), A("arg4", INT), A("arg5", INT)})}) +// Register(&SArgs{220, PA("clone", []PArg{A("fn", POINTER), A("stack", POINTER), A("flags", EXP_INT), A("arg0", INT), A("arg1", INT), A("arg2", INT)})}) +// Register(&SArgs{221, PA("execve", []PArg{A("pathname", STRING), A("argv", STRING_ARR), A("envp", STRING_ARR)})}) +// Register(&SArgs{222, PA("mmap", []PArg{B("addr", POINTER), A("length", INT), A("prot", EXP_INT), A("flags", EXP_INT), A("fd", EXP_INT), A("offset", INT)})}) +// Register(&SArgs{223, PA("fadvise64", []PArg{A("fd", EXP_INT), A("offset", INT), A("len", INT), A("advice", INT)})}) +// Register(&SArgs{224, PA("swapon", []PArg{A("specialfile", STRING), A("swap_flags", INT)})}) +// Register(&SArgs{225, PA("swapoff", []PArg{A("specialfile", STRING)})}) +// Register(&SArgs{226, PAI("mprotect", []PArg{A("addr", POINTER), A("length", INT), A("prot", EXP_INT)})}) +// Register(&SArgs{227, PA("msync", []PArg{A("addr", POINTER), A("length", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{228, PA("mlock", []PArg{A("start", INT), A("len", INT)})}) +// Register(&SArgs{229, PA("munlock", []PArg{A("start", INT), A("len", INT)})}) +// Register(&SArgs{230, PA("mlockall", []PArg{A("flags", EXP_INT)})}) +// Register(&SArgs{231, PA("munlockall", []PArg{})}) +// Register(&SArgs{232, PA("mincore", []PArg{A("start", INT), A("len", INT), A("vec", STRING)})}) +// Register(&SArgs{233, PA("madvise", []PArg{A("addr", POINTER), A("len", INT), A("advice", INT)})}) +// Register(&SArgs{234, PA("remap_file_pages", []PArg{A("start", INT), A("size", INT), A("prot", EXP_INT), A("pgoff", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{235, PA("mbind", []PArg{A("start", ULONG), A("len", ULONG), A("mode", ULONG), A("nmask", INT), A("maxnode", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{236, PA("get_mempolicy", []PArg{A("policy", INT), A("nmask", INT), A("maxnode", INT), A("addr", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{237, PA("set_mempolicy", []PArg{A("mode", EXP_INT), A("nmask", INT), A("maxnode", INT)})}) +// Register(&SArgs{238, PA("migrate_pages", []PArg{A("pid", INT), A("maxnode", INT), A("old_nodes", INT), A("new_nodes", INT)})}) +// Register(&SArgs{239, PA("move_pages", []PArg{A("pid", INT), A("nr_pages", INT), A("pages", POINTER), A("nodes", INT), A("status", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{240, PA("rt_tgsigqueueinfo", []PArg{A("tgid", INT), A("tid", INT), A("sig", INT), A("siginfo", SIGINFO)})}) +// Register(&SArgs{241, PA("perf_event_open", []PArg{A("attr_uptr", POINTER), A("pid", INT), A("cpu", INT), A("group_fd", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{242, PAI("accept4", []PArg{A("sockfd", EXP_INT), A("addr", SOCKADDR), A("addrlen", EXP_INT), A("flags", EXP_INT)})}) +// Register(&SArgs{243, PA("recvmmsg", []PArg{A("fd", EXP_INT), A("mmsg", POINTER), A("vlen", INT), A("flags", EXP_INT), A("timeout", TIMESPEC)})}) +// Register(&SArgs{260, PA("wait4", []PArg{A("pid", INT), A("wstatus", POINTER), A("options", INT), B("rusage", RUSAGE)})}) +// Register(&SArgs{261, PA("prlimit64", []PArg{A("pid", INT), A("resource", INT), A("new_rlim", POINTER), A("old_rlim", POINTER)})}) +// Register(&SArgs{262, PA("fanotify_init", []PArg{A("flags", EXP_INT), A("event_f_flags", INT)})}) +// Register(&SArgs{263, PA("fanotify_mark", []PArg{A("fanotify_fd", INT), A("flags", EXP_INT), A("mask", UINT64), A("dfd", INT), A("pathname", STRING)})}) +// Register(&SArgs{264, PA("name_to_handle_at", []PArg{A("dfd", INT), A("name", STRING), A("handle", POINTER), A("mnt_id", INT), A("flag", INT)})}) +// Register(&SArgs{265, PA("open_by_handle_at", []PArg{A("mountdirfd", INT), A("handle", POINTER), A("flags", EXP_INT)})}) +// Register(&SArgs{266, PA("clock_adjtime", []PArg{A("which_clock", INT), A("utx", POINTER)})}) +// Register(&SArgs{267, PA("syncfs", []PArg{A("fd", EXP_INT)})}) +// Register(&SArgs{268, PA("setns", []PArg{A("fd", EXP_INT), A("flags", EXP_INT)})}) +// Register(&SArgs{269, PA("sendmmsg", []PArg{A("fd", EXP_INT), A("mmsg", POINTER), A("vlen", INT), A("flags", EXP_INT)})}) +// // 虽然处于内核 但是实测无法跨进程读取数据 所以对于这两个系统调用 只能获取 local_iov 的内容 +// Register(&SArgs{270, PAI("process_vm_readv", []PArg{A("pid", EXP_INT), B("local_iov", IOVEC_T), A("liovcnt", INT), A("remote_iov", POINTER), A("riovcnt", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{271, PAI("process_vm_writev", []PArg{A("pid", EXP_INT), A("local_iov", IOVEC_T), A("liovcnt", INT), B("remote_iov", POINTER), A("riovcnt", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{272, PA("kcmp", []PArg{A("pid1", INT), A("pid2", INT), A("type", INT), A("idx1", INT), A("idx2", INT)})}) +// Register(&SArgs{273, PA("finit_module", []PArg{A("fd", EXP_INT), A("uargs", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{274, PA("sched_setattr", []PArg{A("pid", INT), A("uattr", POINTER), A("flags", EXP_INT)})}) +// Register(&SArgs{275, PA("sched_getattr", []PArg{A("pid", INT), A("uattr", POINTER), A("usize", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{276, PA("renameat2", []PArg{A("olddirfd", INT), A("oldpath", STRING), A("newdirfd", INT), A("newpath", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{277, PA("seccomp", []PArg{A("operation", INT), A("flags", EXP_INT), A("args", POINTER)})}) +// Register(&SArgs{278, PA("getrandom", []PArg{B("buf", POINTER), A("buflen", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{279, PA("memfd_create", []PArg{A("name", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{280, PA("bpf", []PArg{A("cmd", INT), A("attr", POINTER), A("size", INT)})}) +// Register(&SArgs{281, PA("execveat", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("argv", STRING_ARR), A("envp", STRING_ARR), A("flags", EXP_INT)})}) +// Register(&SArgs{282, PA("userfaultfd", []PArg{A("flags", EXP_INT)})}) +// Register(&SArgs{283, PA("membarrier", []PArg{A("cmd", INT), A("flags", POINTER), A("cpu_id", INT)})}) +// Register(&SArgs{284, PA("mlock2", []PArg{A("start", INT), A("len", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{285, PA("copy_file_range", []PArg{A("fd_in", INT), A("off_in", INT), A("fd_out", INT), A("off_out", INT), A("len", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{286, PA("preadv2", []PArg{A("fd", EXP_INT), A("vec", POINTER), A("vlen", INT), A("pos_l", INT), A("pos_h", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{287, PA("pwritev2", []PArg{A("fd", EXP_INT), A("vec", POINTER), A("vlen", INT), A("pos_l", INT), A("pos_h", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{288, PA("pkey_mprotect", []PArg{B("addr", POINTER), A("length", INT), A("prot", EXP_INT), A("pkey", INT)})}) +// Register(&SArgs{289, PA("pkey_alloc", []PArg{A("flags", EXP_INT), A("init_val", INT)})}) +// Register(&SArgs{290, PA("pkey_free", []PArg{A("pkey", INT)})}) +// Register(&SArgs{291, PA("statx", []PArg{A("dfd", INT), A("filename", STRING), A("flags", EXP_INT), A("mask", INT), A("buffer", POINTER)})}) +// Register(&SArgs{292, PA("io_pgetevents", []PArg{A("ctx_id", POINTER), A("min_nr", UINT64), A("nr", UINT64), A("events", POINTER), A("timeout", TIMESPEC), A("usig", POINTER)})}) +// Register(&SArgs{293, PA("rseq", []PArg{A("rseq", POINTER), A("rseq_len", INT), A("flags", EXP_INT), A("sig", INT)})}) +// Register(&SArgs{294, PA("kexec_file_load", []PArg{A("kernel_fd", INT), A("initrd_fd", INT), A("cmdline_len", INT), A("cmdline_ptr", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{424, PA("pidfd_send_signal", []PArg{A("pidfd", INT), A("sig", INT), A("info", SIGINFO), A("flags", EXP_INT)})}) +// Register(&SArgs{425, PA("io_uring_setup", []PArg{A("entries", INT), A("params", POINTER)})}) +// Register(&SArgs{426, PA("io_uring_enter", []PArg{A("fd", EXP_INT), A("to_submit", INT), A("min_complete", INT), A("flags", EXP_INT), A("argp", POINTER), A("argsz", INT)})}) +// Register(&SArgs{427, PA("io_uring_register", []PArg{A("fd", EXP_INT), A("opcode", INT), A("arg", POINTER), A("nr_args", INT)})}) +// Register(&SArgs{428, PA("open_tree", []PArg{A("dfd", INT), A("filename", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{429, PA("move_mount", []PArg{A("from_dfd", INT), A("from_pathname", STRING), A("to_dfd", INT), A("to_pathname", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{430, PA("fsopen", []PArg{A("_fs_name", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{431, PA("fsconfig", []PArg{A("fd", EXP_INT), A("cmd", INT), A("_key", STRING), A("_value", POINTER), A("aux", INT)})}) +// Register(&SArgs{432, PA("fsmount", []PArg{A("fs_fd", INT), A("flags", EXP_INT), A("attr_flags", INT)})}) +// Register(&SArgs{433, PA("fspick", []PArg{A("dfd", INT), A("path", STRING), A("flags", EXP_INT)})}) +// Register(&SArgs{434, PA("pidfd_open", []PArg{A("pid", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{435, PA("clone3", []PArg{A("uargs", POINTER), A("size", INT)})}) +// Register(&SArgs{436, PA("close_range", []PArg{A("fd", EXP_INT), A("max_fd", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{437, PA("openat2", []PArg{A("dfd", INT), A("filename", STRING), A("how", POINTER), A("usize", INT)})}) +// Register(&SArgs{438, PA("pidfd_getfd", []PArg{A("pidfd", INT), A("fd", EXP_INT), A("flags", EXP_INT)})}) +// Register(&SArgs{439, PA("faccessat2", []PArg{A("dirfd", EXP_INT), A("pathname", STRING), A("flags", EXP_INT), A("mode", EXP_INT)})}) +// Register(&SArgs{440, PA("process_madvise", []PArg{A("pidfd", INT), A("vec", POINTER), A("vlen", INT), A("behavior", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{441, PAI("epoll_pwait2", []PArg{A("epfd", INT), A("events", POINTER), A("maxevents", INT), A("timeout", TIMESPEC), A("sigmask", POINTER), A("sigsetsize", INT)})}) +// Register(&SArgs{442, PA("mount_setattr", []PArg{A("dfd", INT), A("path", STRING), A("flags", EXP_INT), A("uattr", POINTER), A("usize", INT)})}) +// Register(&SArgs{443, PA("quotactl_fd", []PArg{A("fd", EXP_INT), A("cmd", INT), A("id", INT), A("addr", POINTER)})}) +// Register(&SArgs{444, PA("landlock_create_ruleset", []PArg{A("attr", POINTER), A("size", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{445, PA("landlock_add_rule", []PArg{A("ruleset_fd", INT), A("rule_type", INT), A("rule_attr", POINTER), A("flags", EXP_INT)})}) +// Register(&SArgs{446, PA("landlock_restrict_self", []PArg{A("ruleset_fd", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{447, PA("memfd_secret", []PArg{A("flags", EXP_INT)})}) +// Register(&SArgs{448, PA("process_mrelease", []PArg{A("pidfd", INT), A("flags", EXP_INT)})}) +// Register(&SArgs{449, PA("futex_waitv", []PArg{A("waiters", POINTER), A("nr_futexes", INT), A("flags", EXP_INT), A("timeout", TIMESPEC), A("clockid", INT)})}) +// Register(&SArgs{450, PA("set_mempolicy_home_node", []PArg{A("start", INT), A("len", INT), A("home_node", INT), A("flags", EXP_INT)})}) +// } diff --git a/user/next/config/config_syscall_aarch64.go b/user/config/config_syscall_aarch64.go similarity index 98% rename from user/next/config/config_syscall_aarch64.go rename to user/config/config_syscall_aarch64.go index 4454ad5..cbbf242 100644 --- a/user/next/config/config_syscall_aarch64.go +++ b/user/config/config_syscall_aarch64.go @@ -4,26 +4,11 @@ import ( "bytes" "encoding/binary" "fmt" - "stackplz/user/next/argtype" - . "stackplz/user/next/common" + "stackplz/user/argtype" + . "stackplz/user/common" "strings" ) -type PointOpKeyConfig struct { - OpCount uint32 - OpKeyList [MAX_OP_COUNT]uint32 -} - -func (this *PointOpKeyConfig) AddPointArg(point_arg *PointArg) { - for _, op_key := range point_arg.GetOpList() { - this.OpKeyList[this.OpCount] = op_key - this.OpCount++ - if this.OpCount == MAX_OP_COUNT { - panic("PointOpKeyConfig->AddPointArg failed, need increase MAX_OP_COUNT") - } - } -} - type SyscallPoint struct { Nr uint32 Name string @@ -147,6 +132,10 @@ func GetAllPoints() []*SyscallPoint { return aarch64_syscall_points.GetAllPoints() } +func GetALLOpList() map[uint32]argtype.BaseOpConfig { + return argtype.GetALLOpList() +} + var aarch64_syscall_points = SyscallPoints{} func R(nr uint32, name string, point_args ...*PointArg) { diff --git a/user/config/config_uprobe.go b/user/config/config_uprobe.go index 43c2a2d..baacd6b 100644 --- a/user/config/config_uprobe.go +++ b/user/config/config_uprobe.go @@ -2,40 +2,61 @@ package config import ( "fmt" + "stackplz/user/argtype" ) type UprobeArgs struct { Index uint32 LibPath string + Name string Symbol string SymOffset uint64 Offset uint64 ArgsStr string - PointArgs + PointArgs []*PointArg } -type UPointTypes struct { - Count uint32 - ArgTypes [MAX_POINT_ARG_COUNT]FilterArgType +func (this *UprobeArgs) GetConfig() PointOpKeyConfig { + config := PointOpKeyConfig{} + for _, point_arg := range this.PointArgs { + config.AddPointArg(point_arg) + } + // this.DumpOpList("uprobe_"+this.Name, config.OpKeyList[:]) + return config } -func (this *UprobeArgs) GetConfig() UPointTypes { - // 当前这样传递配置的方式比较耗时 - var point_arg_types [MAX_POINT_ARG_COUNT]FilterArgType - for i := 0; i < MAX_POINT_ARG_COUNT; i++ { - if i+1 > len(this.Args) { - break +func (this *UprobeArgs) DumpOpList(tag string, op_list []uint32) { + fmt.Printf("[DumpOpList] %s Name:%s Count:%d\n", tag, this.Name, len(op_list)) + for index, op_index := range op_list { + if op_index == 0 { + continue } - point_arg_types[i].PointFlag = this.Args[i].PointFlag - point_arg_types[i].ArgType = this.Args[i].ArgType - } - config := UPointTypes{ - Count: uint32(len(this.Args)), - ArgTypes: point_arg_types, + fmt.Printf("idx:%3d op_key:%3d %s\n", index, op_index, argtype.OPM.GetOpInfo(op_index)) } - return config } +// type UPointTypes struct { +// Count uint32 +// ArgTypes [MAX_POINT_ARG_COUNT]FilterArgType +// } + +// func (this *UprobeArgs) GetConfig() UPointTypes { +// // 当前这样传递配置的方式比较耗时 +// var point_arg_types [MAX_POINT_ARG_COUNT]FilterArgType +// for i := 0; i < MAX_POINT_ARG_COUNT; i++ { +// if i+1 > len(this.Args) { +// break +// } +// point_arg_types[i].PointFlag = this.Args[i].PointFlag +// point_arg_types[i].ArgType = this.Args[i].ArgType +// } +// config := UPointTypes{ +// Count: uint32(len(this.Args)), +// ArgTypes: point_arg_types, +// } +// return config +// } + func (this *UprobeArgs) String() string { if this.Symbol == "" { return fmt.Sprintf("[%s + 0x%x] %s", this.LibPath, this.Offset, this.ArgsStr) @@ -44,4 +65,4 @@ func (this *UprobeArgs) String() string { } } -type UArgs = UprobeArgs +// type UArgs = UprobeArgs diff --git a/user/config/config_watchpoint.go b/user/config/config_watchpoint.go index 67d649c..af0bbb0 100644 --- a/user/config/config_watchpoint.go +++ b/user/config/config_watchpoint.go @@ -1,315 +1,309 @@ package config -import ( - "encoding/json" - "fmt" - "strconv" -) - -// 结合其他项目构想一种新的方案 便于后续增补各类结构体的数据解析 -// 而不是依赖配置文件去转换 某种程度上来说 硬编码反而是更好的选择 - -const MAX_IOV_COUNT = 6 -const MAX_POINT_ARG_COUNT = 10 - -const FILTER_INDEX_NONE uint32 = 0x0 -const FILTER_INDEX_SKIP uint32 = 0x1234 - -const ( - FORBIDDEN uint32 = iota - SYS_ENTER_EXIT - SYS_ENTER - SYS_EXIT - UPROBE_ENTER_READ -) - -type ArgType struct { - FilterIdx [MAX_FILTER_COUNT]uint32 - ReadIndex uint32 - ReadOffset uint32 - BaseType uint32 - AliasType uint32 - ReadCount uint32 - ItemPerSize uint32 - ItemCountIndex uint32 - tmp_index uint32 -} - -type IWatchPoint interface { - Name() string - Format() string - ParseType(int32) string - ParseFlag(int32) string - ParseProt(int32) string - ParseMode(int32) string - Clone() IWatchPoint -} - -type PointArgs struct { - PointName string - Ret PointArg - Args []PointArg -} - -type PArgs = PointArgs - -type FilterArgType struct { - PointFlag uint32 - ArgType -} - -type PointArg struct { - ArgName string - PointFlag uint32 - ArgType - ArgValue string -} - -type PArg = PointArg - -func (this *PointArg) SetValue(value string) { - this.ArgValue = value -} - -func (this *PointArg) AppendValue(value string) { - this.ArgValue += value -} - -func (this *PointArg) Format(p IWatchPoint, value uint64) string { - switch this.ArgType { - case UMODE_T: - value_fixed := int32(uint16(value)) - this.ArgValue = fmt.Sprintf("%s=0o%03s", this.ArgName, strconv.FormatInt(int64(value_fixed), 8)) - return this.ArgValue - } - switch this.AliasType { - case TYPE_EXP_INT: - value_fixed := int32(value) - switch this.ArgName { - case "flags": - this.ArgValue = fmt.Sprintf("%s=0x%x%s", this.ArgName, value_fixed, p.ParseFlag(value_fixed)) - case "prot": - this.ArgValue = fmt.Sprintf("%s=0x%x%s", this.ArgName, value_fixed, p.ParseProt(value_fixed)) - case "type": - this.ArgValue = fmt.Sprintf("%s=0x%x%s", this.ArgName, value_fixed, p.ParseType(value_fixed)) - default: - this.ArgValue = fmt.Sprintf("%s=%d", this.ArgName, value_fixed) - } - case TYPE_INT64: - value_fixed := int64(value) - if value_fixed <= 0 { - this.ArgValue = fmt.Sprintf("%s=%d", this.ArgName, value_fixed) - } else { - this.ArgValue = fmt.Sprintf("%s=0x%x", this.ArgName, value_fixed) - } - case TYPE_UINT32: - value_fixed := uint32(value) - this.ArgValue = fmt.Sprintf("%s=0x%x", this.ArgName, value_fixed) - default: - this.ArgValue = fmt.Sprintf("%s=0x%x", this.ArgName, value) - } - return this.ArgValue -} - -func (this *ArgType) SetBaseType(base_type uint32) { - this.BaseType = base_type -} - -func (this *ArgType) SetReadCount(read_count uint32) { - this.ReadCount = read_count -} - -func (this *ArgType) SetCountIndex(index uint32) { - this.ItemCountIndex = index -} - -func (this *ArgType) SetReadIndex(index uint32) { - this.ReadIndex = index -} - -func (this *ArgType) SetReadOffset(offset uint64) { - this.ReadOffset = uint32(offset) -} - -func (this *ArgType) SetItemPerSize(persize uint32) { - this.ItemPerSize = persize -} - -func (this *ArgType) ToPtr() ArgType { - at := this.Clone() - at.BaseType = TYPE_POINTER - return at -} - -func (this *ArgType) NewBaseType(base_type uint32) ArgType { - at := this.Clone() - at.BaseType = base_type - return at -} - -func (this *ArgType) NewAliasType(alias_type uint32) ArgType { - at := this.Clone() - at.AliasType = alias_type - return at -} - -func (this *ArgType) NewReadCount(read_count uint32) ArgType { - at := this.Clone() - at.ReadCount = read_count - return at -} - -func (this *ArgType) NewCountIndex(index uint32) ArgType { - at := this.Clone() - at.ItemCountIndex = index - return at -} - -func (this *ArgType) NewReadIndex(index uint32) ArgType { - at := this.Clone() - at.ReadIndex = index - return at -} - -func (this *ArgType) NewReadOffset(offset uint64) ArgType { - at := this.Clone() - at.ReadOffset = uint32(offset) - return at -} - -func (this *ArgType) NewItemPerSize(persize uint32) ArgType { - at := this.Clone() - at.ItemPerSize = persize - return at -} - -func (this *ArgType) NewArrayArgType(alias_type, persize uint32) ArgType { - at := this.Clone() - at.AliasType = alias_type - at.ItemPerSize = persize - return at -} - -func (this *ArgType) String() string { - var s string = "" - s += fmt.Sprintf("read_index:%d, base_type:%d alias_type:%d ", this.ReadIndex, this.BaseType, this.AliasType) - s += fmt.Sprintf("read_count:%d per:%d count_index:%d ", this.ReadCount, this.ItemPerSize, this.ItemCountIndex) - s += fmt.Sprintf("off:%d", this.ReadOffset) - return s -} - -func (this *ArgType) Clone() ArgType { - // 在涉及到类型变更的时候 记得先调用这个 - at := ArgType{} - copy(at.FilterIdx[:], this.FilterIdx[:]) - at.ReadIndex = this.ReadIndex - at.ReadOffset = this.ReadOffset - at.BaseType = this.BaseType - at.AliasType = this.AliasType - at.ReadCount = this.ReadCount - at.ItemPerSize = this.ItemPerSize - at.ItemCountIndex = this.ItemCountIndex - at.tmp_index = this.tmp_index - return at -} - -func AT(arg_alias_type, arg_base_type, read_count uint32) ArgType { - var tmp_idx [MAX_FILTER_COUNT]uint32 - for i := 0; i < MAX_FILTER_COUNT; i++ { - tmp_idx[i] = FILTER_INDEX_NONE - } - return ArgType{tmp_idx, REG_ARM64_INDEX, 0, arg_base_type, arg_alias_type, read_count, 1, REG_ARM64_MAX, 0} -} - -func PA(nr string, args []PArg) PArgs { - return PArgs{nr, B("ret", UINT64), args} -} - -func PAI(nr string, args []PArg) PArgs { - return PArgs{nr, B("ret", EXP_INT), args} -} - -func (this *PointArgs) Clone() IWatchPoint { - args := new(PointArgs) - args.PointName = this.PointName - args.Ret = this.Ret - args.Args = this.Args - return args -} - -func (this *PointArgs) Format() string { - args, err := json.Marshal(this.Args) - if err != nil { - panic(fmt.Sprintf("Args Format err:%v", err)) - } - return fmt.Sprintf("[%s] %d %s", this.PointName, len(this.Args), args) -} - -func (this *PointArgs) Name() string { - return this.PointName -} -func (this *PointArgs) ParseFlag(value int32) string { - panic("PointArgs.ParseFlag() not implemented yet") -} -func (this *PointArgs) ParseProt(value int32) string { - panic("PointArgs.ParseProt() not implemented yet") -} -func (this *PointArgs) ParseMode(value int32) string { - panic("PointArgs.ParseMode() not implemented yet") -} -func (this *PointArgs) ParseType(value int32) string { - panic("PointArgs.ParseType() not implemented yet") -} - -func NewWatchPoint(name string) IWatchPoint { - point := &PointArgs{} - point.PointName = name - return point -} - -func NewSysCallWatchPoint(name string) IWatchPoint { - point := &SysCallArgs{} - return point -} - -func Register(p IWatchPoint) { - if p == nil { - panic("Register watchpoint is nil") - } - name := p.Name() - if _, dup := watchpoints[name]; dup { - panic(fmt.Sprintf("Register called twice for watchpoint %s", name)) - } - watchpoints[name] = p - // 给 syscall 单独维护一个 map 这样便于在解析的时候快速获取 point 配置 - nr_point, ok := (p).(*SysCallArgs) - if ok { - if _, dup := nrwatchpoints[nr_point.NR]; dup { - panic(fmt.Sprintf("Register called twice for nrwatchpoints %s", name)) - } - nrwatchpoints[nr_point.NR] = nr_point - } -} - -func GetAllWatchPoints() map[string]IWatchPoint { - return watchpoints -} - -func GetWatchPointByNR(nr uint32) IWatchPoint { - m, f := nrwatchpoints[nr] - if f { - return m - } - return nil -} - -func GetWatchPointByName(pointName string) IWatchPoint { - m, f := watchpoints[pointName] - if f { - return m - } - return nil -} - -var watchpoints = make(map[string]IWatchPoint) -var nrwatchpoints = make(map[uint32]IWatchPoint) +// // 结合其他项目构想一种新的方案 便于后续增补各类结构体的数据解析 +// // 而不是依赖配置文件去转换 某种程度上来说 硬编码反而是更好的选择 + +// const MAX_IOV_COUNT = 6 +// const MAX_POINT_ARG_COUNT = 10 + +// const FILTER_INDEX_NONE uint32 = 0x0 +// const FILTER_INDEX_SKIP uint32 = 0x1234 + +// const ( +// FORBIDDEN uint32 = iota +// SYS_ENTER_EXIT +// SYS_ENTER +// SYS_EXIT +// UPROBE_ENTER_READ +// ) + +// type ArgType struct { +// FilterIdx [MAX_FILTER_COUNT]uint32 +// ReadIndex uint32 +// ReadOffset uint32 +// BaseType uint32 +// AliasType uint32 +// ReadCount uint32 +// ItemPerSize uint32 +// ItemCountIndex uint32 +// tmp_index uint32 +// } + +// type IWatchPoint interface { +// Name() string +// Format() string +// ParseType(int32) string +// ParseFlag(int32) string +// ParseProt(int32) string +// ParseMode(int32) string +// Clone() IWatchPoint +// } + +// type PointArgs struct { +// PointName string +// Ret PointArg +// Args []PointArg +// } + +// type PArgs = PointArgs + +// type FilterArgType struct { +// PointFlag uint32 +// ArgType +// } + +// type PointArg struct { +// ArgName string +// PointFlag uint32 +// ArgType +// ArgValue string +// } + +// type PArg = PointArg + +// func (this *PointArg) SetValue(value string) { +// this.ArgValue = value +// } + +// func (this *PointArg) AppendValue(value string) { +// this.ArgValue += value +// } + +// func (this *PointArg) Format(p IWatchPoint, value uint64) string { +// switch this.ArgType { +// case UMODE_T: +// value_fixed := int32(uint16(value)) +// this.ArgValue = fmt.Sprintf("%s=0o%03s", this.ArgName, strconv.FormatInt(int64(value_fixed), 8)) +// return this.ArgValue +// } +// switch this.AliasType { +// case TYPE_EXP_INT: +// value_fixed := int32(value) +// switch this.ArgName { +// case "flags": +// this.ArgValue = fmt.Sprintf("%s=0x%x%s", this.ArgName, value_fixed, p.ParseFlag(value_fixed)) +// case "prot": +// this.ArgValue = fmt.Sprintf("%s=0x%x%s", this.ArgName, value_fixed, p.ParseProt(value_fixed)) +// case "type": +// this.ArgValue = fmt.Sprintf("%s=0x%x%s", this.ArgName, value_fixed, p.ParseType(value_fixed)) +// default: +// this.ArgValue = fmt.Sprintf("%s=%d", this.ArgName, value_fixed) +// } +// case TYPE_INT64: +// value_fixed := int64(value) +// if value_fixed <= 0 { +// this.ArgValue = fmt.Sprintf("%s=%d", this.ArgName, value_fixed) +// } else { +// this.ArgValue = fmt.Sprintf("%s=0x%x", this.ArgName, value_fixed) +// } +// case TYPE_UINT32: +// value_fixed := uint32(value) +// this.ArgValue = fmt.Sprintf("%s=0x%x", this.ArgName, value_fixed) +// default: +// this.ArgValue = fmt.Sprintf("%s=0x%x", this.ArgName, value) +// } +// return this.ArgValue +// } + +// func (this *ArgType) SetBaseType(base_type uint32) { +// this.BaseType = base_type +// } + +// func (this *ArgType) SetReadCount(read_count uint32) { +// this.ReadCount = read_count +// } + +// func (this *ArgType) SetCountIndex(index uint32) { +// this.ItemCountIndex = index +// } + +// func (this *ArgType) SetReadIndex(index uint32) { +// this.ReadIndex = index +// } + +// func (this *ArgType) SetReadOffset(offset uint64) { +// this.ReadOffset = uint32(offset) +// } + +// func (this *ArgType) SetItemPerSize(persize uint32) { +// this.ItemPerSize = persize +// } + +// func (this *ArgType) ToPtr() ArgType { +// at := this.Clone() +// at.BaseType = TYPE_POINTER +// return at +// } + +// func (this *ArgType) NewBaseType(base_type uint32) ArgType { +// at := this.Clone() +// at.BaseType = base_type +// return at +// } + +// func (this *ArgType) NewAliasType(alias_type uint32) ArgType { +// at := this.Clone() +// at.AliasType = alias_type +// return at +// } + +// func (this *ArgType) NewReadCount(read_count uint32) ArgType { +// at := this.Clone() +// at.ReadCount = read_count +// return at +// } + +// func (this *ArgType) NewCountIndex(index uint32) ArgType { +// at := this.Clone() +// at.ItemCountIndex = index +// return at +// } + +// func (this *ArgType) NewReadIndex(index uint32) ArgType { +// at := this.Clone() +// at.ReadIndex = index +// return at +// } + +// func (this *ArgType) NewReadOffset(offset uint64) ArgType { +// at := this.Clone() +// at.ReadOffset = uint32(offset) +// return at +// } + +// func (this *ArgType) NewItemPerSize(persize uint32) ArgType { +// at := this.Clone() +// at.ItemPerSize = persize +// return at +// } + +// func (this *ArgType) NewArrayArgType(alias_type, persize uint32) ArgType { +// at := this.Clone() +// at.AliasType = alias_type +// at.ItemPerSize = persize +// return at +// } + +// func (this *ArgType) String() string { +// var s string = "" +// s += fmt.Sprintf("read_index:%d, base_type:%d alias_type:%d ", this.ReadIndex, this.BaseType, this.AliasType) +// s += fmt.Sprintf("read_count:%d per:%d count_index:%d ", this.ReadCount, this.ItemPerSize, this.ItemCountIndex) +// s += fmt.Sprintf("off:%d", this.ReadOffset) +// return s +// } + +// func (this *ArgType) Clone() ArgType { +// // 在涉及到类型变更的时候 记得先调用这个 +// at := ArgType{} +// copy(at.FilterIdx[:], this.FilterIdx[:]) +// at.ReadIndex = this.ReadIndex +// at.ReadOffset = this.ReadOffset +// at.BaseType = this.BaseType +// at.AliasType = this.AliasType +// at.ReadCount = this.ReadCount +// at.ItemPerSize = this.ItemPerSize +// at.ItemCountIndex = this.ItemCountIndex +// at.tmp_index = this.tmp_index +// return at +// } + +// func AT(arg_alias_type, arg_base_type, read_count uint32) ArgType { +// var tmp_idx [MAX_FILTER_COUNT]uint32 +// for i := 0; i < MAX_FILTER_COUNT; i++ { +// tmp_idx[i] = FILTER_INDEX_NONE +// } +// return ArgType{tmp_idx, REG_ARM64_INDEX, 0, arg_base_type, arg_alias_type, read_count, 1, REG_ARM64_MAX, 0} +// } + +// func PA(nr string, args []PArg) PArgs { +// return PArgs{nr, B("ret", UINT64), args} +// } + +// func PAI(nr string, args []PArg) PArgs { +// return PArgs{nr, B("ret", EXP_INT), args} +// } + +// func (this *PointArgs) Clone() IWatchPoint { +// args := new(PointArgs) +// args.PointName = this.PointName +// args.Ret = this.Ret +// args.Args = this.Args +// return args +// } + +// func (this *PointArgs) Format() string { +// args, err := json.Marshal(this.Args) +// if err != nil { +// panic(fmt.Sprintf("Args Format err:%v", err)) +// } +// return fmt.Sprintf("[%s] %d %s", this.PointName, len(this.Args), args) +// } + +// func (this *PointArgs) Name() string { +// return this.PointName +// } +// func (this *PointArgs) ParseFlag(value int32) string { +// panic("PointArgs.ParseFlag() not implemented yet") +// } +// func (this *PointArgs) ParseProt(value int32) string { +// panic("PointArgs.ParseProt() not implemented yet") +// } +// func (this *PointArgs) ParseMode(value int32) string { +// panic("PointArgs.ParseMode() not implemented yet") +// } +// func (this *PointArgs) ParseType(value int32) string { +// panic("PointArgs.ParseType() not implemented yet") +// } + +// func NewWatchPoint(name string) IWatchPoint { +// point := &PointArgs{} +// point.PointName = name +// return point +// } + +// func NewSysCallWatchPoint(name string) IWatchPoint { +// point := &SysCallArgs{} +// return point +// } + +// func Register(p IWatchPoint) { +// if p == nil { +// panic("Register watchpoint is nil") +// } +// name := p.Name() +// if _, dup := watchpoints[name]; dup { +// panic(fmt.Sprintf("Register called twice for watchpoint %s", name)) +// } +// watchpoints[name] = p +// // 给 syscall 单独维护一个 map 这样便于在解析的时候快速获取 point 配置 +// nr_point, ok := (p).(*SysCallArgs) +// if ok { +// if _, dup := nrwatchpoints[nr_point.NR]; dup { +// panic(fmt.Sprintf("Register called twice for nrwatchpoints %s", name)) +// } +// nrwatchpoints[nr_point.NR] = nr_point +// } +// } + +// func GetAllWatchPoints() map[string]IWatchPoint { +// return watchpoints +// } + +// func GetWatchPointByNR(nr uint32) IWatchPoint { +// m, f := nrwatchpoints[nr] +// if f { +// return m +// } +// return nil +// } + +// func GetWatchPointByName(pointName string) IWatchPoint { +// m, f := watchpoints[pointName] +// if f { +// return m +// } +// return nil +// } + +// var watchpoints = make(map[string]IWatchPoint) +// var nrwatchpoints = make(map[uint32]IWatchPoint) diff --git a/user/config/iconfig.go b/user/config/iconfig.go index 80d8e56..4ba66a1 100644 --- a/user/config/iconfig.go +++ b/user/config/iconfig.go @@ -1,9 +1,9 @@ package config import ( - "errors" "fmt" "log" + . "stackplz/user/common" ) type IConfig interface { @@ -68,11 +68,25 @@ var RegsMagicMap map[string]uint32 = map[string]uint32{ "pc": REG_ARM64_PC, } -func ParseAsReg(reg string) (uint32, error) { +func GetRegIndex(reg string) uint32 { value, ok := RegsMagicMap[reg] - if ok { - return value, nil - } else { - return 0, errors.New(fmt.Sprintf("ParseAsReg failed =>%s<=", reg)) + if !ok { + panic(fmt.Sprintf("ParseAsReg failed =>%s<=", reg)) + } + return value +} + +type PointOpKeyConfig struct { + OpCount uint32 + OpKeyList [MAX_OP_COUNT]uint32 +} + +func (this *PointOpKeyConfig) AddPointArg(point_arg *PointArg) { + for _, op_key := range point_arg.GetOpList() { + this.OpKeyList[this.OpCount] = op_key + this.OpCount++ + if this.OpCount == MAX_OP_COUNT { + panic("PointOpKeyConfig->AddPointArg failed, need increase MAX_OP_COUNT") + } } } diff --git a/user/event/event_context.go b/user/event/event_context.go index dfb5415..d255896 100644 --- a/user/event/event_context.go +++ b/user/event/event_context.go @@ -6,11 +6,11 @@ import ( "encoding/json" "errors" "fmt" + "stackplz/user/common" "stackplz/user/config" "stackplz/user/util" "strconv" "strings" - "time" "golang.org/x/sys/unix" ) @@ -85,57 +85,57 @@ type ContextEvent struct { UnwindBuffer *UnwindBuf } -func (this *ContextEvent) ParseArgArray(point_arg *config.PointArg) string { - // 数组本质上是作为 struct 处理的 - var arg config.Arg_str - if err := binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { - panic(err) - } - switch point_arg.AliasType { - case config.TYPE_BUFFER: - payload := make([]byte, arg.Len) - if err := binary.Read(this.buf, binary.LittleEndian, &payload); err != nil { - panic(err) - } - if this.mconf.DumpHex { - return arg.HexFormat(payload, this.mconf.Color) - } else { - return arg.Format(payload) - } - case config.TYPE_ARRAY_INT32: - arr := make([]int32, point_arg.ReadCount) - if err := binary.Read(this.buf, binary.LittleEndian, arr); err != nil { - panic(err) - } - return util.ArrayFormat(arr) - case config.TYPE_ARRAY_UINT32: - arr := make([]uint32, point_arg.ReadCount) - if err := binary.Read(this.buf, binary.LittleEndian, arr); err != nil { - panic(err) - } - return util.ArrayFormat(arr) - default: - panic(fmt.Sprintf("unsupported array type:%d", point_arg.AliasType)) - } -} +// func (this *ContextEvent) ParseArgArray(point_arg *config.PointArg) string { +// // 数组本质上是作为 struct 处理的 +// var arg config.Arg_str +// if err := binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { +// panic(err) +// } +// switch point_arg.AliasType { +// case config.TYPE_BUFFER: +// payload := make([]byte, arg.Len) +// if err := binary.Read(this.buf, binary.LittleEndian, &payload); err != nil { +// panic(err) +// } +// if this.mconf.DumpHex { +// return arg.HexFormat(payload, this.mconf.Color) +// } else { +// return arg.Format(payload) +// } +// case config.TYPE_ARRAY_INT32: +// arr := make([]int32, point_arg.ReadCount) +// if err := binary.Read(this.buf, binary.LittleEndian, arr); err != nil { +// panic(err) +// } +// return util.ArrayFormat(arr) +// case config.TYPE_ARRAY_UINT32: +// arr := make([]uint32, point_arg.ReadCount) +// if err := binary.Read(this.buf, binary.LittleEndian, arr); err != nil { +// panic(err) +// } +// return util.ArrayFormat(arr) +// default: +// panic(fmt.Sprintf("unsupported array type:%d", point_arg.AliasType)) +// } +// } -func (this *ContextEvent) ParseArgStruct(buf *bytes.Buffer, arg config.ArgFormatter) string { - if err := binary.Read(buf, binary.LittleEndian, arg); err != nil { - this.logger.Printf("ContextEvent EventId:%d RawSample:\n%s", this.EventId, util.HexDump(this.rec.RawSample, util.COLORRED)) - time.Sleep(5 * 100 * time.Millisecond) - panic(err) - } - return arg.Format() -} +// func (this *ContextEvent) ParseArgStruct(buf *bytes.Buffer, arg config.ArgFormatter) string { +// if err := binary.Read(buf, binary.LittleEndian, arg); err != nil { +// this.logger.Printf("ContextEvent EventId:%d RawSample:\n%s", this.EventId, util.HexDump(this.rec.RawSample, util.COLORRED)) +// time.Sleep(5 * 100 * time.Millisecond) +// panic(err) +// } +// return arg.Format() +// } -func (this *ContextEvent) ParseArgStructHex(buf *bytes.Buffer, arg config.ArgHexFormatter) string { - if err := binary.Read(buf, binary.LittleEndian, arg); err != nil { - this.logger.Printf("ContextEvent EventId:%d RawSample:\n%s", this.EventId, util.HexDump(this.rec.RawSample, util.COLORRED)) - time.Sleep(5 * 100 * time.Millisecond) - panic(err) - } - return arg.HexFormat() -} +// func (this *ContextEvent) ParseArgStructHex(buf *bytes.Buffer, arg config.ArgHexFormatter) string { +// if err := binary.Read(buf, binary.LittleEndian, arg); err != nil { +// this.logger.Printf("ContextEvent EventId:%d RawSample:\n%s", this.EventId, util.HexDump(this.rec.RawSample, util.COLORRED)) +// time.Sleep(5 * 100 * time.Millisecond) +// panic(err) +// } +// return arg.HexFormat() +// } func (this *ContextEvent) GetOffset(addr uint64) string { return maps_helper.GetOffset(this.Pid, addr) @@ -261,190 +261,190 @@ func (this *ContextEvent) Clone() IEventStruct { return event } -func (this *ContextEvent) ParseArgByType(point_arg *config.PointArg, ptr config.Arg_reg) { - if ptr.Address == 0 { - point_arg.AppendValue("(NULL)") - return - } - // 这个函数先处理基础类型 +// func (this *ContextEvent) ParseArgByType(point_arg *config.PointArg, ptr config.Arg_reg) { +// if ptr.Address == 0 { +// point_arg.AppendValue("(NULL)") +// return +// } +// // 这个函数先处理基础类型 - if point_arg.BaseType == config.TYPE_POINTER { - point_arg.SetValue("") - point_arg.AppendValue(fmt.Sprintf("*0x%x%s", ptr.Address, this.ParseArg(point_arg))) - } else if point_arg.BaseType == config.TYPE_ARRAY { - point_arg.AppendValue(this.ParseArgArray(point_arg)) - } else { - // 这种一般就是特殊类型 获取结构体了 - point_arg.AppendValue(this.ParseArg(point_arg)) - } -} -func (this *ContextEvent) ParseArg(point_arg *config.PointArg) string { - var err error - switch point_arg.AliasType { - case config.TYPE_NONE: - panic("AliasType TYPE_NONE can not be here") - case config.TYPE_NUM: - panic("AliasType TYPE_NUM can not be here") - case config.TYPE_EXP_INT: - // 只有基础类型为 STRUCT 才会走这里 - var arg config.Arg_str - if err := binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { - panic(err) - } - var result int32 - if err = binary.Read(this.buf, binary.LittleEndian, &result); err != nil { - panic(err) - } - return fmt.Sprintf("(%d)", result) - case config.TYPE_UINT32: - var arg config.Arg_str - if err := binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { - panic(err) - } - var result uint32 - if err = binary.Read(this.buf, binary.LittleEndian, &result); err != nil { - panic(err) - } - return fmt.Sprintf("(%d)", result) - case config.TYPE_INT64: - var arg config.Arg_str - if err := binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { - panic(err) - } - var result int64 - if err = binary.Read(this.buf, binary.LittleEndian, &result); err != nil { - panic(err) - } - return fmt.Sprintf("(%d)", result) - case config.TYPE_UINT64: - var arg config.Arg_str - if err := binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { - panic(err) - } - var result uint64 - if err = binary.Read(this.buf, binary.LittleEndian, &result); err != nil { - panic(err) - } - return fmt.Sprintf("(%d)", result) - case config.TYPE_STRING: - var arg config.Arg_str - if err = binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { - panic(err) - } - payload := make([]byte, arg.Len) - if err = binary.Read(this.buf, binary.LittleEndian, &payload); err != nil { - panic(err) - } - return fmt.Sprintf("(%s)", util.B2STrim(payload)) - case config.TYPE_STRING_ARR: - var arg_str_arr config.Arg_str_arr - if err = binary.Read(this.buf, binary.LittleEndian, &arg_str_arr); err != nil { - panic(err) - } - var str_arr []string - for i := 0; i < int(arg_str_arr.Count); i++ { - var len uint32 - if err = binary.Read(this.buf, binary.LittleEndian, &len); err != nil { - panic(err) - } - payload := make([]byte, len) - if err = binary.Read(this.buf, binary.LittleEndian, &payload); err != nil { - panic(err) - } - str_arr = append(str_arr, util.B2STrim(payload)) - } - return fmt.Sprintf("[%s]", strings.Join(str_arr, ", ")) - case config.TYPE_POINTER: - // 先解析参数寄存器本身的值 - var ptr_value config.Arg_reg - // 再解析参数寄存器指向地址的值 - if err = binary.Read(this.buf, binary.LittleEndian, &ptr_value); err != nil { - panic(err) - } - return fmt.Sprintf("(0x%x)", ptr_value.Address) - case config.TYPE_SIGSET: - var sigs [8]uint32 - if err = binary.Read(this.buf, binary.LittleEndian, &sigs); err != nil { - panic(err) - } - var fmt_sigs []string - for i := 0; i < len(sigs); i++ { - fmt_sigs = append(fmt_sigs, fmt.Sprintf("0x%x", sigs[i])) - } - return fmt.Sprintf("(sigs=[%s])", strings.Join(fmt_sigs, ",")) - case config.TYPE_POLLFD: - return this.ParseArgStruct(this.buf, &config.Arg_Pollfd{}) - case config.TYPE_STRUCT: - payload := make([]byte, point_arg.ReadCount) - if err = binary.Read(this.buf, binary.LittleEndian, &payload); err != nil { - panic(err) - } - return fmt.Sprintf("([hex]%x)", payload) - case config.TYPE_TIMEZONE: - return this.ParseArgStruct(this.buf, &config.Arg_TimeZone_t{}) - case config.TYPE_PTHREAD_ATTR: - return this.ParseArgStruct(this.buf, &config.Arg_Pthread_attr_t{}) - case config.TYPE_TIMEVAL: - return this.ParseArgStruct(this.buf, &config.Arg_Timeval{}) - case config.TYPE_TIMESPEC: - return this.ParseArgStruct(this.buf, &config.Arg_Timespec{}) - case config.TYPE_STAT: - return this.ParseArgStruct(this.buf, &config.Arg_Stat_t{}) - case config.TYPE_STATFS: - return this.ParseArgStruct(this.buf, &config.Arg_Statfs_t{}) - case config.TYPE_SIGACTION: - return this.ParseArgStruct(this.buf, &config.Arg_Sigaction{}) - case config.TYPE_UTSNAME: - return this.ParseArgStruct(this.buf, &config.Arg_Utsname{}) - case config.TYPE_SOCKADDR: - return this.ParseArgStruct(this.buf, &config.Arg_RawSockaddrUnix{}) - case config.TYPE_RUSAGE: - return this.ParseArgStruct(this.buf, &config.Arg_Rusage{}) - case config.TYPE_IOVEC: - var iovcnt config.Arg_iovcnt - if err = binary.Read(this.buf, binary.LittleEndian, &iovcnt); err != nil { - panic(err) - } - var iov_read_count int = config.MAX_IOV_COUNT - if int(iovcnt.Value) < iov_read_count { - iov_read_count = int(iovcnt.Value) - } - var result []string - for i := 0; i < iov_read_count; i++ { - var arg config.Arg_Iovec_t - if err = binary.Read(this.buf, binary.LittleEndian, &arg.Arg_Iovec); err != nil { - panic(err) - } - var iov_buf config.Arg_str - if err = binary.Read(this.buf, binary.LittleEndian, &iov_buf); err != nil { - panic(err) - } - payload := make([]byte, iov_buf.Len) - if err = binary.Read(this.buf, binary.LittleEndian, &payload); err != nil { - panic(err) - } - arg.Payload = payload - result = append(result, arg.Format()) - } - return "\n\t" + strings.Join(result, "\n\t") + "\n" - case config.TYPE_EPOLLEVENT: - return this.ParseArgStruct(this.buf, &config.Arg_EpollEvent{}) - case config.TYPE_SYSINFO: - return this.ParseArgStruct(this.buf, &config.Arg_Sysinfo_t{}) - case config.TYPE_SIGINFO: - return this.ParseArgStruct(this.buf, &config.Arg_SigInfo{}) - case config.TYPE_MSGHDR: - return this.ParseArgStruct(this.buf, &config.Arg_Msghdr{}) - case config.TYPE_ITIMERSPEC: - return this.ParseArgStruct(this.buf, &config.Arg_ItTmerspec{}) - case config.TYPE_STACK_T: - return this.ParseArgStruct(this.buf, &config.Arg_Stack_t{}) - case config.TYPE_BUFFER: - return this.ParseArgArray(point_arg) - default: - panic(fmt.Sprintf("unknown point_arg.AliasType %d", point_arg.AliasType)) - } -} +// if point_arg.BaseType == config.TYPE_POINTER { +// point_arg.SetValue("") +// point_arg.AppendValue(fmt.Sprintf("*0x%x%s", ptr.Address, this.ParseArg(point_arg))) +// } else if point_arg.BaseType == config.TYPE_ARRAY { +// point_arg.AppendValue(this.ParseArgArray(point_arg)) +// } else { +// // 这种一般就是特殊类型 获取结构体了 +// point_arg.AppendValue(this.ParseArg(point_arg)) +// } +// } +// func (this *ContextEvent) ParseArg(point_arg *config.PointArg) string { +// var err error +// switch point_arg.AliasType { +// case config.TYPE_NONE: +// panic("AliasType TYPE_NONE can not be here") +// case config.TYPE_NUM: +// panic("AliasType TYPE_NUM can not be here") +// case config.TYPE_EXP_INT: +// // 只有基础类型为 STRUCT 才会走这里 +// var arg config.Arg_str +// if err := binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { +// panic(err) +// } +// var result int32 +// if err = binary.Read(this.buf, binary.LittleEndian, &result); err != nil { +// panic(err) +// } +// return fmt.Sprintf("(%d)", result) +// case config.TYPE_UINT32: +// var arg config.Arg_str +// if err := binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { +// panic(err) +// } +// var result uint32 +// if err = binary.Read(this.buf, binary.LittleEndian, &result); err != nil { +// panic(err) +// } +// return fmt.Sprintf("(%d)", result) +// case config.TYPE_INT64: +// var arg config.Arg_str +// if err := binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { +// panic(err) +// } +// var result int64 +// if err = binary.Read(this.buf, binary.LittleEndian, &result); err != nil { +// panic(err) +// } +// return fmt.Sprintf("(%d)", result) +// case config.TYPE_UINT64: +// var arg config.Arg_str +// if err := binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { +// panic(err) +// } +// var result uint64 +// if err = binary.Read(this.buf, binary.LittleEndian, &result); err != nil { +// panic(err) +// } +// return fmt.Sprintf("(%d)", result) +// case config.TYPE_STRING: +// var arg config.Arg_str +// if err = binary.Read(this.buf, binary.LittleEndian, &arg); err != nil { +// panic(err) +// } +// payload := make([]byte, arg.Len) +// if err = binary.Read(this.buf, binary.LittleEndian, &payload); err != nil { +// panic(err) +// } +// return fmt.Sprintf("(%s)", util.B2STrim(payload)) +// case config.TYPE_STRING_ARR: +// var arg_str_arr config.Arg_str_arr +// if err = binary.Read(this.buf, binary.LittleEndian, &arg_str_arr); err != nil { +// panic(err) +// } +// var str_arr []string +// for i := 0; i < int(arg_str_arr.Count); i++ { +// var len uint32 +// if err = binary.Read(this.buf, binary.LittleEndian, &len); err != nil { +// panic(err) +// } +// payload := make([]byte, len) +// if err = binary.Read(this.buf, binary.LittleEndian, &payload); err != nil { +// panic(err) +// } +// str_arr = append(str_arr, util.B2STrim(payload)) +// } +// return fmt.Sprintf("[%s]", strings.Join(str_arr, ", ")) +// case config.TYPE_POINTER: +// // 先解析参数寄存器本身的值 +// var ptr_value config.Arg_reg +// // 再解析参数寄存器指向地址的值 +// if err = binary.Read(this.buf, binary.LittleEndian, &ptr_value); err != nil { +// panic(err) +// } +// return fmt.Sprintf("(0x%x)", ptr_value.Address) +// case config.TYPE_SIGSET: +// var sigs [8]uint32 +// if err = binary.Read(this.buf, binary.LittleEndian, &sigs); err != nil { +// panic(err) +// } +// var fmt_sigs []string +// for i := 0; i < len(sigs); i++ { +// fmt_sigs = append(fmt_sigs, fmt.Sprintf("0x%x", sigs[i])) +// } +// return fmt.Sprintf("(sigs=[%s])", strings.Join(fmt_sigs, ",")) +// case config.TYPE_POLLFD: +// return this.ParseArgStruct(this.buf, &config.Arg_Pollfd{}) +// case config.TYPE_STRUCT: +// payload := make([]byte, point_arg.ReadCount) +// if err = binary.Read(this.buf, binary.LittleEndian, &payload); err != nil { +// panic(err) +// } +// return fmt.Sprintf("([hex]%x)", payload) +// case config.TYPE_TIMEZONE: +// return this.ParseArgStruct(this.buf, &config.Arg_TimeZone_t{}) +// case config.TYPE_PTHREAD_ATTR: +// return this.ParseArgStruct(this.buf, &config.Arg_Pthread_attr_t{}) +// case config.TYPE_TIMEVAL: +// return this.ParseArgStruct(this.buf, &config.Arg_Timeval{}) +// case config.TYPE_TIMESPEC: +// return this.ParseArgStruct(this.buf, &config.Arg_Timespec{}) +// case config.TYPE_STAT: +// return this.ParseArgStruct(this.buf, &config.Arg_Stat_t{}) +// case config.TYPE_STATFS: +// return this.ParseArgStruct(this.buf, &config.Arg_Statfs_t{}) +// case config.TYPE_SIGACTION: +// return this.ParseArgStruct(this.buf, &config.Arg_Sigaction{}) +// case config.TYPE_UTSNAME: +// return this.ParseArgStruct(this.buf, &config.Arg_Utsname{}) +// case config.TYPE_SOCKADDR: +// return this.ParseArgStruct(this.buf, &config.Arg_RawSockaddrUnix{}) +// case config.TYPE_RUSAGE: +// return this.ParseArgStruct(this.buf, &config.Arg_Rusage{}) +// case config.TYPE_IOVEC: +// var iovcnt config.Arg_iovcnt +// if err = binary.Read(this.buf, binary.LittleEndian, &iovcnt); err != nil { +// panic(err) +// } +// var iov_read_count int = config.MAX_IOV_COUNT +// if int(iovcnt.Value) < iov_read_count { +// iov_read_count = int(iovcnt.Value) +// } +// var result []string +// for i := 0; i < iov_read_count; i++ { +// var arg config.Arg_Iovec_t +// if err = binary.Read(this.buf, binary.LittleEndian, &arg.Arg_Iovec); err != nil { +// panic(err) +// } +// var iov_buf config.Arg_str +// if err = binary.Read(this.buf, binary.LittleEndian, &iov_buf); err != nil { +// panic(err) +// } +// payload := make([]byte, iov_buf.Len) +// if err = binary.Read(this.buf, binary.LittleEndian, &payload); err != nil { +// panic(err) +// } +// arg.Payload = payload +// result = append(result, arg.Format()) +// } +// return "\n\t" + strings.Join(result, "\n\t") + "\n" +// case config.TYPE_EPOLLEVENT: +// return this.ParseArgStruct(this.buf, &config.Arg_EpollEvent{}) +// case config.TYPE_SYSINFO: +// return this.ParseArgStruct(this.buf, &config.Arg_Sysinfo_t{}) +// case config.TYPE_SIGINFO: +// return this.ParseArgStruct(this.buf, &config.Arg_SigInfo{}) +// case config.TYPE_MSGHDR: +// return this.ParseArgStruct(this.buf, &config.Arg_Msghdr{}) +// case config.TYPE_ITIMERSPEC: +// return this.ParseArgStruct(this.buf, &config.Arg_ItTmerspec{}) +// case config.TYPE_STACK_T: +// return this.ParseArgStruct(this.buf, &config.Arg_Stack_t{}) +// case config.TYPE_BUFFER: +// return this.ParseArgArray(point_arg) +// default: +// panic(fmt.Sprintf("unknown point_arg.AliasType %d", point_arg.AliasType)) +// } +// } func (this *ContextEvent) GetStackTrace(s string) string { if this.mconf.RegName != "" { @@ -461,13 +461,13 @@ func (this *ContextEvent) GetStackTrace(s string) string { if strings.HasPrefix(this.mconf.RegName, "x") { parts := strings.SplitN(this.mconf.RegName, "x", 2) regno, _ := strconv.ParseUint(parts[1], 10, 32) - if regno >= 0 && regno <= uint64(config.REG_ARM64_X29) { + if regno >= 0 && regno <= uint64(common.REG_ARM64_X29) { // 取到对应的寄存器值 regvalue = tmp_regs[regno] has_reg_value = true } } else if this.mconf.RegName == "lr" { - regvalue = tmp_regs[config.REG_ARM64_LR] + regvalue = tmp_regs[common.REG_ARM64_LR] has_reg_value = true } if has_reg_value { @@ -489,12 +489,12 @@ func (this *ContextEvent) GetStackTrace(s string) string { tmp_regs = this.RegsBuffer.Regs } regs := make(map[string]string) - for regno := 0; regno <= int(config.REG_ARM64_X29); regno++ { + for regno := 0; regno <= int(common.REG_ARM64_X29); regno++ { regs[fmt.Sprintf("x%d", regno)] = fmt.Sprintf("0x%x", tmp_regs[regno]) } - regs["lr"] = fmt.Sprintf("0x%x", tmp_regs[config.REG_ARM64_LR]) - regs["sp"] = fmt.Sprintf("0x%x", tmp_regs[config.REG_ARM64_SP]) - regs["pc"] = fmt.Sprintf("0x%x", tmp_regs[config.REG_ARM64_PC]) + regs["lr"] = fmt.Sprintf("0x%x", tmp_regs[common.REG_ARM64_LR]) + regs["sp"] = fmt.Sprintf("0x%x", tmp_regs[common.REG_ARM64_SP]) + regs["pc"] = fmt.Sprintf("0x%x", tmp_regs[common.REG_ARM64_PC]) regs_info, err := json.Marshal(regs) if err != nil { regs_info = make([]byte, 0) diff --git a/user/event/event_mmap2.go b/user/event/event_mmap2.go index 5a71bce..75c92fe 100644 --- a/user/event/event_mmap2.go +++ b/user/event/event_mmap2.go @@ -9,6 +9,7 @@ import ( "io" "io/ioutil" "log" + "stackplz/user/common" "stackplz/user/config" "stackplz/user/util" "strings" @@ -195,10 +196,10 @@ func (this *MapsHelper) GetStack(pid uint32, ubuf *UnwindBuf) (info string, err // perf_output_sample_ustack dump获取到的栈空间数据 起始地址就是 sp stack_buf := bytes.NewReader(ubuf.Data[:]) - fp := ubuf.Regs[config.REG_ARM64_X29] - // lr := ubuf.Regs[config.REG_ARM64_LR] - sp := ubuf.Regs[config.REG_ARM64_SP] - pc := ubuf.Regs[config.REG_ARM64_PC] + fp := ubuf.Regs[common.REG_ARM64_X29] + // lr := ubuf.Regs[common.REG_ARM64_LR] + sp := ubuf.Regs[common.REG_ARM64_SP] + pc := ubuf.Regs[common.REG_ARM64_PC] // 栈解析结果 // var stack_arr []uint64 var stack_infos []string diff --git a/user/event/event_next_raw_syscalls.go b/user/event/event_next_raw_syscalls.go deleted file mode 100644 index 6be6f61..0000000 --- a/user/event/event_next_raw_syscalls.go +++ /dev/null @@ -1,158 +0,0 @@ -package event - -import ( - "encoding/binary" - "encoding/json" - "fmt" - "stackplz/user/config" - next_config "stackplz/user/next/config" - "stackplz/user/util" -) - -type NextSyscallEvent struct { - ContextEvent - UUID string - RegsBuffer RegsBuf - UnwindBuffer UnwindBuf - nr_point *config.SysCallArgs - nr_point_next *next_config.SyscallPoint - nr config.Arg_nr - lr config.Arg_reg - sp config.Arg_reg - pc config.Arg_reg - ret uint64 - arg_str string -} - -func (this *NextSyscallEvent) ParseEvent() (IEventStruct, error) { - data_e, err := this.ContextEvent.ParseEvent() - if err != nil { - panic("...") - } - if data_e == nil { - if err := this.ParseContext(); err != nil { - panic(fmt.Sprintf("NextSyscallEvent.ParseContext() err:%v", err)) - } - return this, nil - } - return data_e, nil -} - -func (this *NextSyscallEvent) ParseContext() (err error) { - // 处理参数 常规参数的构成 是 索引 + 值 - if err = binary.Read(this.buf, binary.LittleEndian, &this.nr); err != nil { - panic(err) - } - this.nr_point_next = next_config.GetSyscallPointByNR(this.nr.Value) - - // this.logger.Printf("ParseContext EventId:%d RawSample:\n%s", this.EventId, util.HexDump(this.rec.RawSample, util.COLORRED)) - - if this.EventId == SYSCALL_ENTER { - if err = binary.Read(this.buf, binary.LittleEndian, &this.lr); err != nil { - panic(err) - } - if err = binary.Read(this.buf, binary.LittleEndian, &this.pc); err != nil { - panic(err) - } - if err = binary.Read(this.buf, binary.LittleEndian, &this.sp); err != nil { - panic(err) - } - this.arg_str = this.nr_point_next.ParseEnterPoint(this.buf) - } else if this.EventId == SYSCALL_EXIT { - this.arg_str = this.nr_point_next.ParseExitPoint(this.buf) - } else { - panic(fmt.Sprintf("NextSyscallEvent.ParseContext() failed, EventId:%d", this.EventId)) - } - this.ParsePadding() - err = this.ParseContextStack() - if err != nil { - panic(fmt.Sprintf("ParseContextStack err:%v", err)) - } - return nil -} - -func (this *NextSyscallEvent) GetUUID() string { - s := fmt.Sprintf("%d|%d|%s", this.Pid, this.Tid, util.B2STrim(this.Comm[:])) - if this.mconf.ShowTime { - s = fmt.Sprintf("%d|%s", this.Ts, s) - } - if this.mconf.ShowUid { - s = fmt.Sprintf("%d|%s", this.Uid, s) - } - return s -} - -func (this *NextSyscallEvent) JsonString(stack_str string) string { - if this.EventId == SYSCALL_ENTER { - v := config.SyscallFmt{} - v.Ts = this.Ts - v.Event = "sys_enter" - v.HostTid = this.HostTid - v.HostPid = this.HostPid - v.Tid = this.Tid - v.Pid = this.Pid - v.Uid = this.Uid - v.Comm = util.B2STrim(this.Comm[:]) - v.Argnum = this.Argnum - v.Stack = stack_str - v.NR = this.nr_point.PointName - v.LR = fmt.Sprintf("0x%x", this.lr.Address) - v.SP = fmt.Sprintf("0x%x", this.sp.Address) - v.PC = fmt.Sprintf("0x%x", this.pc.Address) - v.Arg_str = this.arg_str - data, err := json.Marshal(v) - if err != nil { - panic(err) - } - return string(data) - } else { - v := config.SyscallExitFmt{} - v.Ts = this.Ts - v.Event = "sys_exit" - v.HostTid = this.HostTid - v.HostPid = this.HostPid - v.Tid = this.Tid - v.Pid = this.Pid - v.Uid = this.Uid - v.Comm = util.B2STrim(this.Comm[:]) - v.Argnum = this.Argnum - v.Stack = stack_str - v.NR = this.nr_point.PointName - v.Arg_str = this.arg_str - data, err := json.Marshal(v) - if err != nil { - panic(err) - } - return string(data) - } -} - -func (this *NextSyscallEvent) String() string { - stack_str := "" - if this.EventId == SYSCALL_ENTER { - stack_str = this.GetStackTrace(stack_str) - } - // if this.mconf.FmtJson { - // return this.JsonString(stack_str) - // } - var base_str string - base_str = fmt.Sprintf("[%s] %s%s", this.GetUUID(), this.nr_point_next.Name, this.arg_str) - if this.EventId == SYSCALL_ENTER { - var lr_str string - var pc_str string - if this.mconf.GetOff { - lr_str = fmt.Sprintf("LR:0x%x(%s)", this.lr.Address, this.GetOffset(this.lr.Address)) - pc_str = fmt.Sprintf("PC:0x%x(%s)", this.pc.Address, this.GetOffset(this.pc.Address)) - } else { - lr_str = fmt.Sprintf("LR:0x%x", this.lr.Address) - pc_str = fmt.Sprintf("PC:0x%x", this.pc.Address) - } - base_str = fmt.Sprintf("%s %s %s SP:0x%x", base_str, lr_str, pc_str, this.sp.Address) - } - return base_str + stack_str -} - -func (this *NextSyscallEvent) Clone() IEventStruct { - event := new(NextSyscallEvent) - return event -} diff --git a/user/event/event_raw_syscalls.go b/user/event/event_raw_syscalls.go index b81d6cd..4a3f9ac 100644 --- a/user/event/event_raw_syscalls.go +++ b/user/event/event_raw_syscalls.go @@ -5,112 +5,21 @@ import ( "encoding/json" "fmt" "stackplz/user/config" - next_config "stackplz/user/next/config" "stackplz/user/util" - "strings" ) type SyscallEvent struct { ContextEvent - UUID string - RegsBuffer RegsBuf - UnwindBuffer UnwindBuf - nr_point *config.SysCallArgs - nr_point_next *next_config.SyscallPoint - nr config.Arg_nr - lr config.Arg_reg - sp config.Arg_reg - pc config.Arg_reg - ret uint64 - arg_str string -} - -func (this *SyscallEvent) ParseContextSysEnter() (err error) { - if err = binary.Read(this.buf, binary.LittleEndian, &this.lr); err != nil { - panic(err) - } - if err = binary.Read(this.buf, binary.LittleEndian, &this.pc); err != nil { - panic(err) - } - if err = binary.Read(this.buf, binary.LittleEndian, &this.sp); err != nil { - panic(err) - } - // 根据调用号解析剩余参数 - point := config.GetWatchPointByNR(this.nr.Value) - nr_point, ok := (point).(*config.SysCallArgs) - if !ok { - panic(fmt.Sprintf("cast nr[%d] point to SysCallArgs failed", this.nr.Value)) - } - this.nr_point = nr_point - var results []string - for _, point_arg := range this.nr_point.Args { - var ptr config.Arg_reg - if err = binary.Read(this.buf, binary.LittleEndian, &ptr); err != nil { - panic(err) - } - if point_arg.BaseType == config.TYPE_NUM { - results = append(results, point_arg.Format(this.nr_point, ptr.Address)) - continue - } - base_arg_str := fmt.Sprintf("%s=0x%x", point_arg.ArgName, ptr.Address) - point_arg.SetValue(base_arg_str) - // 这一类参数要等执行结束后读取 这里只获取参数所对应的寄存器值就可以了 - if point_arg.PointFlag == config.SYS_EXIT { - results = append(results, point_arg.ArgValue) - continue - } - this.ParseArgByType(&point_arg, ptr) - results = append(results, point_arg.ArgValue) - } - this.arg_str = "(" + strings.Join(results, ", ") + ")" - return nil -} - -func (this *SyscallEvent) ParseContextSysExit() (err error) { - point := config.GetWatchPointByNR(this.nr.Value) - nr_point, ok := (point).(*config.SysCallArgs) - if !ok { - panic(fmt.Sprintf("cast nr[%d] point to SysCallArgs failed", this.nr.Value)) - } - this.nr_point = nr_point - var results []string - for _, point_arg := range this.nr_point.Args { - var ptr config.Arg_reg - if err = binary.Read(this.buf, binary.LittleEndian, &ptr); err != nil { - panic(fmt.Sprintf("binary.Read %d %s err:%v", this.nr.Value, util.B2STrim(this.Comm[:]), err)) - } - if point_arg.BaseType == config.TYPE_NUM { - results = append(results, point_arg.Format(this.nr_point, ptr.Address)) - continue - } - base_arg_str := fmt.Sprintf("%s=0x%x", point_arg.ArgName, ptr.Address) - point_arg.SetValue(base_arg_str) - if point_arg.PointFlag != config.SYS_EXIT { - results = append(results, point_arg.ArgValue) - continue - } - this.ParseArgByType(&point_arg, ptr) - results = append(results, point_arg.ArgValue) - } - // 处理返回参数 - var ptr config.Arg_reg - if err = binary.Read(this.buf, binary.LittleEndian, &ptr); err != nil { - panic(err) - } - point_arg := this.nr_point.Ret - if point_arg.BaseType == config.TYPE_NUM { - point_arg.SetValue(point_arg.Format(this.nr_point, ptr.Address)) - } else { - point_arg.SetValue(fmt.Sprintf("0x%x", ptr.Address)) - } - if point_arg.BaseType != config.TYPE_NUM { - this.ParseArgByType(&point_arg, ptr) - } - if len(results) == 0 { - results = append(results, "(void)") - } - this.arg_str = fmt.Sprintf("(%s => %s)", point_arg.ArgValue, strings.Join(results, ", ")) - return nil + UUID string + RegsBuffer RegsBuf + UnwindBuffer UnwindBuf + nr_point *config.SyscallPoint + nr config.Arg_nr + lr config.Arg_reg + sp config.Arg_reg + pc config.Arg_reg + ret uint64 + arg_str string } func (this *SyscallEvent) ParseEvent() (IEventStruct, error) { @@ -132,13 +41,23 @@ func (this *SyscallEvent) ParseContext() (err error) { if err = binary.Read(this.buf, binary.LittleEndian, &this.nr); err != nil { panic(err) } + this.nr_point = config.GetSyscallPointByNR(this.nr.Value) + + // this.logger.Printf("ParseContext EventId:%d RawSample:\n%s", this.EventId, util.HexDump(this.rec.RawSample, util.COLORRED)) if this.EventId == SYSCALL_ENTER { - // 是否有不执行 sys_exit 的情况 ? - // 有的调用耗时 也有可能 暂时还是把执行结果分开输出吧 - this.ParseContextSysEnter() + if err = binary.Read(this.buf, binary.LittleEndian, &this.lr); err != nil { + panic(err) + } + if err = binary.Read(this.buf, binary.LittleEndian, &this.sp); err != nil { + panic(err) + } + if err = binary.Read(this.buf, binary.LittleEndian, &this.pc); err != nil { + panic(err) + } + this.arg_str = this.nr_point.ParseEnterPoint(this.buf) } else if this.EventId == SYSCALL_EXIT { - this.ParseContextSysExit() + this.arg_str = this.nr_point.ParseExitPoint(this.buf) } else { panic(fmt.Sprintf("SyscallEvent.ParseContext() failed, EventId:%d", this.EventId)) } @@ -174,7 +93,7 @@ func (this *SyscallEvent) JsonString(stack_str string) string { v.Comm = util.B2STrim(this.Comm[:]) v.Argnum = this.Argnum v.Stack = stack_str - v.NR = this.nr_point.PointName + v.NR = this.nr_point.Name v.LR = fmt.Sprintf("0x%x", this.lr.Address) v.SP = fmt.Sprintf("0x%x", this.sp.Address) v.PC = fmt.Sprintf("0x%x", this.pc.Address) @@ -196,7 +115,7 @@ func (this *SyscallEvent) JsonString(stack_str string) string { v.Comm = util.B2STrim(this.Comm[:]) v.Argnum = this.Argnum v.Stack = stack_str - v.NR = this.nr_point.PointName + v.NR = this.nr_point.Name v.Arg_str = this.arg_str data, err := json.Marshal(v) if err != nil { @@ -206,30 +125,16 @@ func (this *SyscallEvent) JsonString(stack_str string) string { } } -func (this *SyscallEvent) NextString() string { - var base_str string - base_str = fmt.Sprintf("[%s] nr:%s%s", this.GetUUID(), this.nr_point_next.Name, this.arg_str) - if this.EventId == SYSCALL_ENTER { - lr_str := fmt.Sprintf("LR:0x%x", this.lr.Address) - pc_str := fmt.Sprintf("PC:0x%x", this.pc.Address) - base_str = fmt.Sprintf("%s %s %s SP:0x%x", base_str, lr_str, pc_str, this.sp.Address) - } - return base_str -} - func (this *SyscallEvent) String() string { - if this.mconf.Next { - return this.NextString() - } stack_str := "" if this.EventId == SYSCALL_ENTER { stack_str = this.GetStackTrace(stack_str) } - if this.mconf.FmtJson { - return this.JsonString(stack_str) - } + // if this.mconf.FmtJson { + // return this.JsonString(stack_str) + // } var base_str string - base_str = fmt.Sprintf("[%s] nr:%s%s", this.GetUUID(), this.nr_point.PointName, this.arg_str) + base_str = fmt.Sprintf("[%s] %s%s", this.GetUUID(), this.nr_point.Name, this.arg_str) if this.EventId == SYSCALL_ENTER { var lr_str string var pc_str string @@ -242,7 +147,6 @@ func (this *SyscallEvent) String() string { } base_str = fmt.Sprintf("%s %s %s SP:0x%x", base_str, lr_str, pc_str, this.sp.Address) } - return base_str + stack_str } diff --git a/user/event/event_uprobe.go b/user/event/event_uprobe.go index 9ce16ca..c144178 100644 --- a/user/event/event_uprobe.go +++ b/user/event/event_uprobe.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "encoding/json" "fmt" + "stackplz/user/argtype" "stackplz/user/config" "stackplz/user/util" "strings" @@ -35,37 +36,38 @@ func (this *UprobeEvent) ParseEvent() (IEventStruct, error) { } func (this *UprobeEvent) ParseContext() (err error) { + if this.EventId != UPROBE_ENTER { + panic(fmt.Sprintf("UprobeEvent.ParseContext() failed, EventId:%d", this.EventId)) + } + + // this.logger.Printf("ParseContext EventId:%d RawSample:\n%s", this.EventId, util.HexDump(this.rec.RawSample, util.COLORRED)) + if err = binary.Read(this.buf, binary.LittleEndian, &this.probe_index); err != nil { panic(err) } if err = binary.Read(this.buf, binary.LittleEndian, &this.lr); err != nil { panic(err) } - if err = binary.Read(this.buf, binary.LittleEndian, &this.pc); err != nil { + if err = binary.Read(this.buf, binary.LittleEndian, &this.sp); err != nil { panic(err) } - if err = binary.Read(this.buf, binary.LittleEndian, &this.sp); err != nil { + if err = binary.Read(this.buf, binary.LittleEndian, &this.pc); err != nil { panic(err) } // 根据预设索引解析参数 if (this.probe_index.Value + 1) > uint32(len(this.mconf.StackUprobeConf.Points)) { panic(fmt.Sprintf("probe_index %d bigger than points", this.probe_index.Value)) } - this.uprobe_point = &this.mconf.StackUprobeConf.Points[this.probe_index.Value] + this.uprobe_point = this.mconf.StackUprobeConf.Points[this.probe_index.Value] + var results []string - for _, point_arg := range this.uprobe_point.Args { - var ptr config.Arg_reg - if err = binary.Read(this.buf, binary.LittleEndian, &ptr); err != nil { + for _, point_arg := range this.uprobe_point.PointArgs { + var ptr argtype.Arg_reg + if err := binary.Read(this.buf, binary.LittleEndian, &ptr); err != nil { panic(err) } - base_arg_str := fmt.Sprintf("%s=0x%x", point_arg.ArgName, ptr.Address) - point_arg.SetValue(base_arg_str) - if point_arg.BaseType == config.TYPE_NUM { - results = append(results, point_arg.ArgValue) - continue - } - this.ParseArgByType(&point_arg, ptr) - results = append(results, point_arg.ArgValue) + arg_fmt := point_arg.Parse(ptr.Address, this.buf, config.EBPF_UPROBE_ENTER) + results = append(results, fmt.Sprintf("%s=%s", point_arg.Name, arg_fmt)) } this.arg_str = "(" + strings.Join(results, ", ") + ")" this.ParsePadding() @@ -131,7 +133,7 @@ func (this *UprobeEvent) String() string { } var s string - s = fmt.Sprintf("[%s] %s%s %s %s SP:0x%x", this.GetUUID(), this.uprobe_point.PointName, this.arg_str, lr_str, pc_str, this.sp.Address) + s = fmt.Sprintf("[%s] %s%s %s %s SP:0x%x", this.GetUUID(), this.uprobe_point.Name, this.arg_str, lr_str, pc_str, this.sp.Address) return s + stack_str } diff --git a/user/module/stack.go b/user/module/stack.go index f7f29b2..2f43bb4 100644 --- a/user/module/stack.go +++ b/user/module/stack.go @@ -11,8 +11,6 @@ import ( "stackplz/assets" "stackplz/user/config" "stackplz/user/event" - "stackplz/user/next/argtype" - next_config "stackplz/user/next/config" "stackplz/user/util" "strings" "unsafe" @@ -38,11 +36,7 @@ func (this *MStack) Init(ctx context.Context, logger *log.Logger, conf config.IC this.Module.SetChild(this) this.eventMaps = make([]*ebpf.Map, 0, 2) this.eventFuncMaps = make(map[*ebpf.Map]event.IEventStruct) - if this.mconf.SysCallConf.Enable { - this.hookBpfFile = "syscall.o" - } else { - this.hookBpfFile = "stack.o" - } + this.hookBpfFile = "stack.o" return nil } @@ -95,33 +89,6 @@ func (this *MStack) setupManager() error { probes = append(probes, stack_probe) } - if this.mconf.SysCallConf.IsEnable() { - // syscall hook 配置 - var sys_enter_probe *manager.Probe - var sys_exit_probe *manager.Probe - if this.mconf.Next { - sys_enter_probe = &manager.Probe{ - Section: "raw_tracepoint/sys_enter", - EbpfFuncName: "next_raw_syscalls_sys_enter", - } - sys_exit_probe = &manager.Probe{ - Section: "raw_tracepoint/sys_exit", - EbpfFuncName: "next_raw_syscalls_sys_exit", - } - } else { - sys_enter_probe = &manager.Probe{ - Section: "raw_tracepoint/sys_enter", - EbpfFuncName: "raw_syscalls_sys_enter", - } - sys_exit_probe = &manager.Probe{ - Section: "raw_tracepoint/sys_exit", - EbpfFuncName: "raw_syscalls_sys_exit", - } - } - probes = append(probes, sys_enter_probe) - probes = append(probes, sys_exit_probe) - } - this.bpfManager = &manager.Manager{ Probes: probes, Maps: maps, @@ -180,12 +147,6 @@ func (this *MStack) Clone() IModule { } func (this *MStack) start() error { - - // 先判断有是只hook其中一个 还是两个都要 - if !this.mconf.StackUprobeConf.IsEnable() && !this.mconf.SysCallConf.IsEnable() { - return errors.New("hook nothing") - } - // 初始化uprobe相关设置 err := this.setupManager() if err != nil { @@ -372,36 +333,11 @@ func (this *MStack) update_arg_filter() { panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) } // w/white b/black - // ./stackplz -n com.starbucks.cn -s openat:f0 -f w:/system/framework/oat -o tmp.log - // ./stackplz -n com.starbucks.cn -s openat:f0.f1.f2 -f w:/system -f w:/dev -f b:/system/lib64 -o tmp.log - // ./stackplz -n com.starbucks.cn,iso -s execve,openat:f0 -f r:/system/bin/su:::/system/bin/zz -o tmp_s.log - // ./stackplz -n com.starbucks.cn,iso -w popen[str.f0.f1] -f r:mount:::mounx -f "r:which su:::which zz" -o tmp_w.log - // r/replace 文本替换逻辑会比较复杂 应该考虑分离 - for _, filter := range this.mconf.ArgFilterRule { - filter_key := filter.Filter_index - filter_value := filter - err = bpf_map.Update(unsafe.Pointer(&filter_key), unsafe.Pointer(&filter_value), ebpf.UpdateAny) - if err != nil { - panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) - } - } - if this.mconf.Debug { - this.logger.Printf("update %s success", map_name) - } -} - -func (this *MStack) update_next_arg_filter() { - map_name := "next_arg_filter" - bpf_map, err := this.FindMap(map_name) - if err != nil { - panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) - } - // w/white b/black // 对于返回值以特定字符串开头的进行过滤 如果要对非首个字符串参数做过滤 那么通过 | 标识占位 // ./stackplz -n com.termux -s "openat:f0.f2,readlinkat:|f1" -f w:/data -f w:/apex -f w:/dev for _, filter := range this.mconf.ArgFilterRule { filter_key := uint64(filter.Filter_index) - filter_value := filter.ToNext() + filter_value := filter.ToEbpfValue() err = bpf_map.Update(unsafe.Pointer(&filter_key), unsafe.Pointer(&filter_value), ebpf.UpdateAny) if err != nil { panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) @@ -412,94 +348,13 @@ func (this *MStack) update_next_arg_filter() { } } -func (this *MStack) update_syscall_point_args() { - map_name := "syscall_point_args_map" - bpf_map, err := this.FindMap(map_name) - if err != nil { - panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) - } - if this.mconf.SysCallConf.TraceMode == config.TRACE_ALL { - points := config.GetAllWatchPoints() - for nr_name, point := range points { - nr_point, ok := (point).(*config.SysCallArgs) - if !ok { - panic(fmt.Sprintf("cast [%s] point to SysCallArgs failed", nr_name)) - } - err := bpf_map.Update(unsafe.Pointer(&nr_point.NR), unsafe.Pointer(nr_point.GetConfig()), ebpf.UpdateAny) - if err != nil { - panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) - } - } - } else { - for _, point_args := range this.mconf.SysCallConf.SyscallPointArgs { - err := bpf_map.Update(unsafe.Pointer(&point_args.NR), unsafe.Pointer(point_args), ebpf.UpdateAny) - if err != nil { - panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) - } - } - } - - if this.mconf.Debug { - this.logger.Printf("update %s success", map_name) - } - -} - -func (this *MStack) update_sysenter_point_args() { - map_name := "sysenter_point_args" - bpf_map, err := this.FindMap(map_name) - if err != nil { - panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) - } - var syscall_Points []*next_config.SyscallPoint - if this.mconf.SysCallConf.TraceMode == config.TRACE_ALL { - syscall_Points = next_config.GetAllPoints() - } else { - syscall_Points = this.mconf.SysCallConf.NextPointArgs - } - for _, syscall_point := range syscall_Points { - point_config := syscall_point.GetEnterConfig() - err := bpf_map.Update(unsafe.Pointer(&syscall_point.Nr), unsafe.Pointer(&point_config), ebpf.UpdateAny) - if err != nil { - panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) - } - } - if this.mconf.Debug { - this.logger.Printf("update %s success", map_name) - } -} - -func (this *MStack) update_sysexit_point_args() { - map_name := "sysexit_point_args" - bpf_map, err := this.FindMap(map_name) - if err != nil { - panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) - } - var syscall_Points []*next_config.SyscallPoint - if this.mconf.SysCallConf.TraceMode == config.TRACE_ALL { - syscall_Points = next_config.GetAllPoints() - } else { - syscall_Points = this.mconf.SysCallConf.NextPointArgs - } - for _, syscall_point := range syscall_Points { - point_config := syscall_point.GetExitConfig() - err := bpf_map.Update(unsafe.Pointer(&syscall_point.Nr), unsafe.Pointer(&point_config), ebpf.UpdateAny) - if err != nil { - panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) - } - } - if this.mconf.Debug { - this.logger.Printf("update %s success", map_name) - } -} - func (this *MStack) update_op_list() { map_name := "op_list" bpf_map, err := this.FindMap(map_name) if err != nil { panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) } - for op_key, op_config := range argtype.GetALLOpList() { + for op_key, op_config := range config.GetALLOpList() { err := bpf_map.Update(unsafe.Pointer(&op_key), unsafe.Pointer(&op_config), ebpf.UpdateAny) if err != nil { panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) @@ -511,38 +366,12 @@ func (this *MStack) update_op_list() { } } -func (this *MStack) update_syscall_config() { - if !this.mconf.SysCallConf.IsEnable() { - return - } - this.update_syscall_point_args() - this.update_common_list(this.mconf.SysCallConf.SysWhitelist, util.SYS_WHITELIST_START) - this.update_common_list(this.mconf.SysCallConf.SysBlacklist, util.SYS_BLACKLIST_START) - if this.mconf.Debug { - this.logger.Printf("SysCallConf:%s", this.mconf.SysCallConf.Info()) - } -} - -func (this *MStack) update_next_syscall_config() { - if !this.mconf.SysCallConf.IsEnable() { - return - } - this.update_sysenter_point_args() - this.update_sysexit_point_args() - this.update_op_list() - this.update_common_list(this.mconf.SysCallConf.SysWhitelist, util.SYS_WHITELIST_START) - this.update_common_list(this.mconf.SysCallConf.SysBlacklist, util.SYS_BLACKLIST_START) - if this.mconf.Debug { - this.logger.Printf("SysCallConf:%s", this.mconf.SysCallConf.Info()) - } -} - func (this *MStack) update_stack_config() { if !this.mconf.StackUprobeConf.IsEnable() { return } - map_name := "uprobe_point_args_map" - bpf_map, err := this.FindMap("uprobe_point_args_map") + map_name := "uprobe_point_args" + bpf_map, err := this.FindMap(map_name) if err != nil { panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) } @@ -565,47 +394,20 @@ func (this *MStack) updateFilter() (err error) { this.update_child_parent() this.update_thread_filter() this.update_stack_config() - if this.mconf.Next { - this.update_next_arg_filter() - this.update_next_syscall_config() - } else { - this.update_arg_filter() - this.update_syscall_config() - } + this.update_arg_filter() + this.update_op_list() return nil } func (this *MStack) initDecodeFun() error { - EventsMap, err := this.FindMap("events") if err != nil { return err } - this.eventMaps = append(this.eventMaps, EventsMap) - // 重新看了下这里的逻辑 发现这部分并没有起作用 - // stack 这个模块 确实会收到许多不通类型的事件 - // 但是处理数据的时候应该先进入绑定事件的处理函数 在处理函数内再调用父一级的处理函数 - // commonEvent := &event.CommonEvent{} - // commonEvent.SetConf(this.mconf) - // this.eventFuncMaps[EventsMap] = commonEvent - this.eventMaps = append(this.eventMaps, EventsMap) // 根据设置添加 map 不然即使不使用的map也会创建缓冲区 - if this.mconf.StackUprobeConf.IsEnable() { - uprobestackEvent := &event.UprobeEvent{} - this.eventFuncMaps[EventsMap] = uprobestackEvent - } - - if this.mconf.SysCallConf.IsEnable() { - if this.mconf.Next { - syscallEvent := &event.NextSyscallEvent{} - this.eventFuncMaps[EventsMap] = syscallEvent - } else { - syscallEvent := &event.SyscallEvent{} - this.eventFuncMaps[EventsMap] = syscallEvent - } - } - + uprobestackEvent := &event.UprobeEvent{} + this.eventFuncMaps[EventsMap] = uprobestackEvent return nil } diff --git a/user/module/syscall.go b/user/module/syscall.go new file mode 100644 index 0000000..c44ecff --- /dev/null +++ b/user/module/syscall.go @@ -0,0 +1,457 @@ +package module + +import ( + "bytes" + "context" + "errors" + "fmt" + "log" + "math" + "path/filepath" + "stackplz/assets" + "stackplz/user/config" + "stackplz/user/event" + "stackplz/user/util" + "strings" + "unsafe" + + "github.com/cilium/ebpf" + "github.com/cilium/ebpf/btf" + manager "github.com/ehids/ebpfmanager" + "golang.org/x/sys/unix" +) + +type MSyscall struct { + Module + bpfManager *manager.Manager + bpfManagerOptions manager.Options + eventFuncMaps map[*ebpf.Map]event.IEventStruct + eventMaps []*ebpf.Map + + hookBpfFile string +} + +func (this *MSyscall) Init(ctx context.Context, logger *log.Logger, conf config.IConfig) error { + this.Module.Init(ctx, logger, conf) + this.Module.SetChild(this) + this.eventMaps = make([]*ebpf.Map, 0, 2) + this.eventFuncMaps = make(map[*ebpf.Map]event.IEventStruct) + this.hookBpfFile = "syscall.o" + + return nil +} + +func (this *MSyscall) GetConf() config.IConfig { + return this.mconf +} + +func (this *MSyscall) setupManager() error { + maps := []*manager.Map{} + probes := []*manager.Probe{} + + events_map := &manager.Map{ + Name: "events", + } + maps = append(maps, events_map) + + fork_probe := &manager.Probe{ + Section: "raw_tracepoint/sched_process_fork", + EbpfFuncName: "tracepoint__sched__sched_process_fork", + } + probes = append(probes, fork_probe) + + // syscall hook 配置 + sys_enter_probe := &manager.Probe{ + Section: "raw_tracepoint/sys_enter", + EbpfFuncName: "raw_syscalls_sys_enter", + } + sys_exit_probe := &manager.Probe{ + Section: "raw_tracepoint/sys_exit", + EbpfFuncName: "raw_syscalls_sys_exit", + } + probes = append(probes, sys_enter_probe) + probes = append(probes, sys_exit_probe) + + this.bpfManager = &manager.Manager{ + Probes: probes, + Maps: maps, + } + return nil +} + +func (this *MSyscall) setupManagerOptions() { + // 对于没有开启 CONFIG_DEBUG_INFO_BTF 的加载额外的 btf.Spec + if this.mconf.ExternalBTF != "" { + byteBuf, err := assets.Asset("user/assets/" + this.mconf.ExternalBTF) + if err != nil { + this.logger.Fatalf("[setupManagerOptions] failed, err:%v", err) + return + } + spec, err := btf.LoadSpecFromReader((bytes.NewReader(byteBuf))) + + this.bpfManagerOptions = manager.Options{ + DefaultKProbeMaxActive: 512, + VerifierOptions: ebpf.CollectionOptions{ + Programs: ebpf.ProgramOptions{ + LogSize: 2097152, + KernelTypes: spec, + }, + }, + RLimit: &unix.Rlimit{ + Cur: math.MaxUint64, + Max: math.MaxUint64, + }, + } + } else { + this.bpfManagerOptions = manager.Options{ + DefaultKProbeMaxActive: 512, + VerifierOptions: ebpf.CollectionOptions{ + Programs: ebpf.ProgramOptions{ + LogSize: 2097152, + }, + }, + RLimit: &unix.Rlimit{ + Cur: math.MaxUint64, + Max: math.MaxUint64, + }, + } + } +} + +func (this *MSyscall) Start() error { + return this.start() +} + +func (this *MSyscall) Clone() IModule { + mod := new(MSyscall) + mod.name = this.name + mod.mType = this.mType + return mod +} + +func (this *MSyscall) start() error { + // 初始化相关设置 + err := this.setupManager() + if err != nil { + return err + } + this.setupManagerOptions() + + // 从assets中获取eBPF程序的二进制数据 + var bpfFileName = filepath.Join("user/assets", this.hookBpfFile) + byteBuf, err := assets.Asset(bpfFileName) + + if err != nil { + return fmt.Errorf("%s\tcouldn't find asset %v .", this.Name(), err) + } + + // 初始化 bpfManager 这一步耗时超过 1.5s + if err = this.bpfManager.InitWithOptions(bytes.NewReader(byteBuf), this.bpfManagerOptions); err != nil { + return fmt.Errorf("couldn't init manager %v", err) + } + + // 启动 bpfManager + if err = this.bpfManager.Start(); err != nil { + return fmt.Errorf("couldn't start bootstrap manager %v .", err) + } + + // 通过更新 BPF_MAP_TYPE_HASH 类型的 map 实现过滤设定的同步 + err = this.updateFilter() + if err != nil { + return err + } + + // 加载map信息,设置eventFuncMaps,给不同的事件指定处理事件数据的函数 + err = this.initDecodeFun() + if err != nil { + return err + } + + return nil +} + +func (this *MSyscall) update_map(map_name string, filter_key uint32, filter_value interface{}) { + bpf_map, err := this.FindMap(map_name) + if err != nil { + panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) + } + err = bpf_map.Update(unsafe.Pointer(&filter_key), filter_value, ebpf.UpdateAny) + if err != nil { + panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) + } + if this.mconf.Debug { + this.logger.Printf("update %s success", map_name) + } +} + +func (this *MSyscall) update_base_config() { + // 更新 base_config 用作基础的过滤 比如排除 stackplz 自身相关的调用 + var filter_key uint32 = 0 + map_name := "base_config" + filter_value := this.mconf.GetConfigMap() + this.update_map(map_name, filter_key, unsafe.Pointer(&filter_value)) +} + +func (this *MSyscall) update_common_list(items []uint32, offset uint32) { + map_name := "common_list" + bpf_map, err := this.FindMap(map_name) + if err != nil { + panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) + } + for _, v := range items { + v += offset + err := bpf_map.Update(unsafe.Pointer(&v), unsafe.Pointer(&v), ebpf.UpdateAny) + if err != nil { + panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) + } + } + if this.mconf.Debug { + p, ok := util.START_OFFSETS[offset] + if !ok { + panic(fmt.Sprintf("offset%d invalid", offset)) + } + this.logger.Printf("update %s success, count:%d offset:%s", map_name, len(items), p) + } +} + +func (this *MSyscall) list2string(items []uint32) string { + var results []string + for _, v := range items { + results = append(results, fmt.Sprintf("%d", v)) + } + return strings.Join(results, ",") +} + +func (this *MSyscall) update_common_filter() { + this.update_common_list(this.mconf.UidWhitelist, util.UID_WHITELIST_START) + this.update_common_list(this.mconf.UidBlacklist, util.UID_BLACKLIST_START) + this.update_common_list(this.mconf.PidWhitelist, util.PID_WHITELIST_START) + this.update_common_list(this.mconf.PidBlacklist, util.PID_BLACKLIST_START) + this.update_common_list(this.mconf.TidWhitelist, util.TID_WHITELIST_START) + this.update_common_list(this.mconf.TidBlacklist, util.TID_BLACKLIST_START) + this.logger.Printf("uid => whitelist:[%s];blacklist:[%s]", this.list2string(this.mconf.UidWhitelist), this.list2string(this.mconf.UidBlacklist)) + this.logger.Printf("pid => whitelist:[%s];blacklist:[%s]", this.list2string(this.mconf.PidWhitelist), this.list2string(this.mconf.PidBlacklist)) + this.logger.Printf("tid => whitelist:[%s];blacklist:[%s]", this.list2string(this.mconf.TidWhitelist), this.list2string(this.mconf.TidBlacklist)) + var filter_key uint32 = 0 + map_name := "common_filter" + filter_value := this.mconf.GetCommonFilter() + this.update_map(map_name, filter_key, unsafe.Pointer(&filter_value)) +} + +func (this *MSyscall) update_child_parent() { + // 这个可以合并到 common_list 后面改进 + map_name := "child_parent_map" + for _, v := range this.mconf.PidWhitelist { + this.update_map(map_name, v, unsafe.Pointer(&v)) + } +} + +func (this *MSyscall) update_thread_filter() { + map_name := "thread_filter" + bpf_map, err := this.FindMap(map_name) + if err != nil { + panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) + } + + var thread_blacklist []string = []string{ + "RenderThread", + "FinalizerDaemon", + "RxCachedThreadS", + "mali-cmar-backe", + "mali-utility-wo", + "mali-mem-purge", + "mali-hist-dump", + "mali-event-hand", + "hwuiTask0", + "hwuiTask1", + "NDK MediaCodec_", + } + + for _, v := range thread_blacklist { + if len(v) > 16 { + panic(fmt.Sprintf("[%s] thread name max len is 16", v)) + } + filter_value := THREAD_NAME_BLACKLIST + filter_key := config.ThreadFilter{} + copy(filter_key.ThreadName[:], v) + err = bpf_map.Update(unsafe.Pointer(&filter_key), unsafe.Pointer(&filter_value), ebpf.UpdateAny) + if err != nil { + panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) + } + } + for _, v := range this.mconf.TNameBlacklist { + if len(v) > 16 { + panic(fmt.Sprintf("[%s] thread name max len is 16", v)) + } + filter_value := THREAD_NAME_BLACKLIST + filter_key := config.ThreadFilter{} + copy(filter_key.ThreadName[:], v) + err = bpf_map.Update(unsafe.Pointer(&filter_key), unsafe.Pointer(&filter_value), ebpf.UpdateAny) + if err != nil { + panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) + } + } + for _, v := range this.mconf.TNameWhitelist { + if len(v) > 16 { + panic(fmt.Sprintf("[%s] thread name max len is 16", v)) + } + filter_value := THREAD_NAME_WHITELIST + filter_key := config.ThreadFilter{} + copy(filter_key.ThreadName[:], v) + err = bpf_map.Update(unsafe.Pointer(&filter_key), unsafe.Pointer(&filter_value), ebpf.UpdateAny) + if err != nil { + panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) + } + } + + if this.mconf.Debug { + this.logger.Printf("update %s success", map_name) + } +} + +func (this *MSyscall) update_arg_filter() { + map_name := "arg_filter" + bpf_map, err := this.FindMap(map_name) + if err != nil { + panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) + } + // w/white b/black + // 对于返回值以特定字符串开头的进行过滤 如果要对非首个字符串参数做过滤 那么通过 | 标识占位 + // ./stackplz -n com.termux -s "openat:f0.f2,readlinkat:|f1" -f w:/data -f w:/apex -f w:/dev + for _, filter := range this.mconf.ArgFilterRule { + filter_key := uint64(filter.Filter_index) + filter_value := filter.ToEbpfValue() + err = bpf_map.Update(unsafe.Pointer(&filter_key), unsafe.Pointer(&filter_value), ebpf.UpdateAny) + if err != nil { + panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) + } + } + if this.mconf.Debug { + this.logger.Printf("update %s success", map_name) + } +} + +func (this *MSyscall) update_sysenter_point_args() { + map_name := "sysenter_point_args" + bpf_map, err := this.FindMap(map_name) + if err != nil { + panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) + } + var syscall_Points []*config.SyscallPoint + if this.mconf.SysCallConf.TraceMode == config.TRACE_ALL { + syscall_Points = config.GetAllPoints() + } else { + syscall_Points = this.mconf.SysCallConf.PointArgs + } + for _, syscall_point := range syscall_Points { + point_config := syscall_point.GetEnterConfig() + err := bpf_map.Update(unsafe.Pointer(&syscall_point.Nr), unsafe.Pointer(&point_config), ebpf.UpdateAny) + if err != nil { + panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) + } + } + if this.mconf.Debug { + this.logger.Printf("update %s success", map_name) + } +} + +func (this *MSyscall) update_sysexit_point_args() { + map_name := "sysexit_point_args" + bpf_map, err := this.FindMap(map_name) + if err != nil { + panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) + } + var syscall_Points []*config.SyscallPoint + if this.mconf.SysCallConf.TraceMode == config.TRACE_ALL { + syscall_Points = config.GetAllPoints() + } else { + syscall_Points = this.mconf.SysCallConf.PointArgs + } + for _, syscall_point := range syscall_Points { + point_config := syscall_point.GetExitConfig() + err := bpf_map.Update(unsafe.Pointer(&syscall_point.Nr), unsafe.Pointer(&point_config), ebpf.UpdateAny) + if err != nil { + panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) + } + } + if this.mconf.Debug { + this.logger.Printf("update %s success", map_name) + } +} + +func (this *MSyscall) update_op_list() { + map_name := "op_list" + bpf_map, err := this.FindMap(map_name) + if err != nil { + panic(fmt.Sprintf("find [%s] failed, err:%v", map_name, err)) + } + for op_key, op_config := range config.GetALLOpList() { + err := bpf_map.Update(unsafe.Pointer(&op_key), unsafe.Pointer(&op_config), ebpf.UpdateAny) + if err != nil { + panic(fmt.Sprintf("update [%s] failed, err:%v", map_name, err)) + } + } + + if this.mconf.Debug { + this.logger.Printf("update %s success", map_name) + } +} + +func (this *MSyscall) updateFilter() (err error) { + this.update_base_config() + this.update_common_filter() + this.update_child_parent() + this.update_thread_filter() + this.update_arg_filter() + this.update_sysenter_point_args() + this.update_sysexit_point_args() + this.update_op_list() + this.update_common_list(this.mconf.SysCallConf.SysWhitelist, util.SYS_WHITELIST_START) + this.update_common_list(this.mconf.SysCallConf.SysBlacklist, util.SYS_BLACKLIST_START) + if this.mconf.Debug { + this.logger.Printf("SysCallConf:%s", this.mconf.SysCallConf.Info()) + } + + return nil +} + +func (this *MSyscall) initDecodeFun() error { + + EventsMap, err := this.FindMap("events") + if err != nil { + return err + } + this.eventMaps = append(this.eventMaps, EventsMap) + + syscallEvent := &event.SyscallEvent{} + this.eventFuncMaps[EventsMap] = syscallEvent + + return nil +} + +func (this *MSyscall) FindMap(map_name string) (*ebpf.Map, error) { + em, found, err := this.bpfManager.GetMap(map_name) + if err != nil { + return em, err + } + if !found { + return em, errors.New(fmt.Sprintf("cannot find map:%s", map_name)) + } + return em, err +} + +func (this *MSyscall) Events() []*ebpf.Map { + return this.eventMaps +} + +func (this *MSyscall) DecodeFun(em *ebpf.Map) (event.IEventStruct, bool) { + fun, found := this.eventFuncMaps[em] + return fun, found +} + +func init() { + mod := &MSyscall{} + mod.name = MODULE_NAME_SYSCALL + mod.mType = PROBE_TYPE_TRACEPOINT + Register(mod) +} diff --git a/user/next/config/const.go b/user/next/config/const.go deleted file mode 100644 index 536f5e4..0000000 --- a/user/next/config/const.go +++ /dev/null @@ -1,8 +0,0 @@ -package config - -const ( - EBPF_PROG_NONE uint32 = iota - EBPF_SYS_ENTER - EBPF_SYS_EXIT - EBPF_SYS_ALL -)