| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- #include <assert.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <string.h>
- #include <linux/ptrace.h>
- #include "ply.h"
- struct kprobe {
- };
- 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;
- 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;
- }
- /* argN => (*ctx).REG */
- new = node_vlist(node_keyword('.', 0),
- node_vlist(node_keyword('*', 0),
- node_ident("ctx"),
- NULL),
- node_string(reg),
- NULL);
- return node_replace(n, new);
- }
- 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 int kprobe_probe(prog_t *prog)
- {
- struct kprobe *kp;
- kp = calloc(1, sizeof(*kp));
- assert(kp);
- prog->provider_data = kp;
- return 0;
- }
- provider_t kprobe = {
- .name = "kprobe",
- .rewrite_node = kprobe_rewrite_node,
- .resolve = kprobe_resolve,
- .probe = kprobe_probe,
- };
- __attribute__((constructor))
- static void kprobe_init(void)
- {
- provider_register(&kprobe);
- }
|