A dynamic tracer for Linux

kprobe.c 1.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #include <assert.h>
  2. #include <errno.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <linux/ptrace.h>
  6. #include "ply.h"
  7. struct kprobe {
  8. };
  9. static inline int is_arg(const char *name)
  10. {
  11. return (strstr(name, "arg") == name)
  12. && (strlen(name) == 4)
  13. && (name[3] >= '0' && name[3] <= '9');
  14. }
  15. static int kprobe_rewrite_arg(prog_t *prog, node_t *n)
  16. {
  17. const char *reg;
  18. int arg = n->ident[3] - '0';
  19. node_t *new;
  20. reg = arch_register_argument(arg);
  21. if (!reg) {
  22. node_print(n, stderr);
  23. fputs(": the location of this argument is unknown\n", stderr);
  24. /* TODO: add ABI mappings for specifying arguments
  25. * passed on the stack. */
  26. return -EINVAL;
  27. }
  28. /* argN => (*ctx).REG */
  29. new = node_vlist(node_keyword('.', 0),
  30. node_vlist(node_keyword('*', 0),
  31. node_ident("ctx"),
  32. NULL),
  33. node_string(reg),
  34. NULL);
  35. return node_replace(n, new);
  36. }
  37. static int kprobe_rewrite_node(prog_t *prog, node_t *n)
  38. {
  39. if ((n->ntype == N_IDENT) && is_arg(n->ident))
  40. return kprobe_rewrite_arg(prog, n);
  41. return 0;
  42. }
  43. static int kprobe_resolve(prog_t *prog, node_t *n)
  44. {
  45. type_t *t;
  46. if (is_arg(n->ident))
  47. t = &t_ulong;
  48. else if (!strcmp(n->ident, "ctx"))
  49. t = type_ptr_of(&t_pt_regs);
  50. else
  51. return -ENOENT;
  52. n->type = t;
  53. return sym_add(prog->locals, n->ident, t, &n->sym);
  54. }
  55. static int kprobe_probe(prog_t *prog)
  56. {
  57. struct kprobe *kp;
  58. kp = calloc(1, sizeof(*kp));
  59. assert(kp);
  60. prog->provider_data = kp;
  61. return 0;
  62. }
  63. provider_t kprobe = {
  64. .name = "kprobe",
  65. .rewrite_node = kprobe_rewrite_node,
  66. .resolve = kprobe_resolve,
  67. .probe = kprobe_probe,
  68. };
  69. __attribute__((constructor))
  70. static void kprobe_init(void)
  71. {
  72. provider_register(&kprobe);
  73. }