#include #include #include #include #include #include "func.h" #include "node.h" #include "ply.h" #include "sym.h" #include "type.h" struct kprobe { }; /* static int kprobe_ir_prologue(prog_t *prog) */ /* { */ /* sym_t *ctx = sym_get(prog->locals, "ctx"); */ /* if (!ctx) */ /* return 0; */ /* irs_alloc_reg(&ctx->irs, prog->ir); */ /* /\* kernel sets r1 to the address of the context *\/ */ /* ir_emit_insn(prog->ir, MOV(0, 0), ctx->irs.reg, BPF_REG_1); */ /* return 0; */ /* } */ static inline int is_arg(const char *name) { return (strstr(name, "arg") == name) && (strlen(name) == 4) && (name[3] >= '0' && name[3] <= '9'); } /* static int kprobe_rewrite_arg(prog_t *prog, node_t *n) */ /* { */ /* const char *reg; */ /* int arg = n->ident[3] - '0'; */ /* node_t *new, *ctx; */ /* reg = arch_register_argument(arg); */ /* if (!reg) { */ /* node_print(n, stderr); */ /* fputs(": the location of this argument is unknown\n", stderr); */ /* /\* TODO: add ABI mappings for specifying arguments */ /* * passed on the stack. *\/ */ /* return -EINVAL; */ /* } */ /* ctx = node_ident("ctx"); */ /* /\* argN => (*ctx).REG *\/ */ /* new = node_vlist(node_keyword('.', 0), */ /* node_vlist(node_keyword('*', 0), */ /* ctx, */ /* NULL), */ /* node_string(reg), */ /* NULL); */ /* ctx->type = type_ptr_of(&t_pt_regs); */ /* new->type = n->type; */ /* new->list->type = &t_void; */ /* new->list->next->type = &t_pt_regs; */ /* new->list->next->list->type = &t_void; */ /* node_replace(n, new); */ /* return sym_add(prog->locals, ctx->ident, ctx->type, &ctx->sym); */ /* } */ /* static int kprobe_rewrite_node(prog_t *prog, node_t *n) */ /* { */ /* if ((n->ntype == N_IDENT) && is_arg(n->ident)) */ /* return kprobe_rewrite_arg(prog, n); */ /* return 0; */ /* } */ /* static int kprobe_resolve(prog_t *prog, node_t *n) */ /* { */ /* type_t *t; */ /* if (is_arg(n->ident)) */ /* t = &t_ulong; */ /* else if (!strcmp(n->ident, "ctx")) */ /* t = type_ptr_of(&t_pt_regs); */ /* else */ /* return -ENOENT; */ /* n->type = t; */ /* return sym_add(prog->locals, n->ident, t, &n->sym); */ /* } */ static const struct func kprobe_arg_func = { .name = "argN", /* for now, in the future we could read dwarf symbols to * figure out the real type. */ .type = &t_ulong, .static_ret = 1, }; static int kprobe_sym_alloc(struct prog *prog, struct node *n) { const struct func *func = NULL; int err; switch (n->ntype) { case N_EXPR: break; case N_IDENT: if (is_arg(n->ident.name)) func = &kprobe_arg_func; break; default: break; } if (!func) return -ENOENT; err = func_static_validate(func, n); if (err) return err; n->sym = sym_alloc(prog->locals, n, func); if (func->static_ret) n->sym->type = func_return_type(func); return 0; } static int kprobe_probe(struct prog *prog) { struct kprobe *kp; kp = calloc(1, sizeof(*kp)); assert(kp); prog->provider_data = kp; return 0; } struct provider kprobe = { .name = "kprobe", /* .ir_prologue = kprobe_ir_prologue, */ /* .rewrite_node = kprobe_rewrite_node, */ /* .resolve = kprobe_resolve, */ .sym_alloc = kprobe_sym_alloc, .probe = kprobe_probe, }; __attribute__((constructor)) static void kprobe_init(void) { provider_register(&kprobe); }