A dynamic tracer for Linux

kprobe.c 1.8KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. new->type = n->type;
  36. new->list->type = &t_void;
  37. new->list->next->type = &t_pt_regs;
  38. new->list->next->list->type = &t_void;
  39. new->list->next->list->next->type = type_ptr_of(&t_pt_regs);
  40. return node_replace(n, new);
  41. }
  42. static int kprobe_rewrite_node(prog_t *prog, node_t *n)
  43. {
  44. if ((n->ntype == N_IDENT) && is_arg(n->ident))
  45. return kprobe_rewrite_arg(prog, n);
  46. return 0;
  47. }
  48. static int kprobe_resolve(prog_t *prog, node_t *n)
  49. {
  50. type_t *t;
  51. if (is_arg(n->ident))
  52. t = &t_ulong;
  53. else if (!strcmp(n->ident, "ctx"))
  54. t = type_ptr_of(&t_pt_regs);
  55. else
  56. return -ENOENT;
  57. n->type = t;
  58. return sym_add(prog->locals, n->ident, t, &n->sym);
  59. }
  60. static int kprobe_probe(prog_t *prog)
  61. {
  62. struct kprobe *kp;
  63. kp = calloc(1, sizeof(*kp));
  64. assert(kp);
  65. prog->provider_data = kp;
  66. return 0;
  67. }
  68. provider_t kprobe = {
  69. .name = "kprobe",
  70. .rewrite_node = kprobe_rewrite_node,
  71. .resolve = kprobe_resolve,
  72. .probe = kprobe_probe,
  73. };
  74. __attribute__((constructor))
  75. static void kprobe_init(void)
  76. {
  77. provider_register(&kprobe);
  78. }