A dynamic tracer for Linux

kprobe.c 2.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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 int kprobe_ir_prologue(prog_t *prog)
  10. {
  11. sym_t *ctx = sym_get(prog->locals, "ctx");
  12. if (!ctx)
  13. return 0;
  14. irs_alloc_reg(&ctx->irs, prog->ir);
  15. /* kernel sets r1 to the address of the context */
  16. ir_emit_insn(prog->ir, MOV(0, 0), ctx->irs.reg, BPF_REG_1);
  17. return 0;
  18. }
  19. static inline int is_arg(const char *name)
  20. {
  21. return (strstr(name, "arg") == name)
  22. && (strlen(name) == 4)
  23. && (name[3] >= '0' && name[3] <= '9');
  24. }
  25. static int kprobe_rewrite_arg(prog_t *prog, node_t *n)
  26. {
  27. const char *reg;
  28. int arg = n->ident[3] - '0';
  29. node_t *new, *ctx;
  30. reg = arch_register_argument(arg);
  31. if (!reg) {
  32. node_print(n, stderr);
  33. fputs(": the location of this argument is unknown\n", stderr);
  34. /* TODO: add ABI mappings for specifying arguments
  35. * passed on the stack. */
  36. return -EINVAL;
  37. }
  38. ctx = node_ident("ctx");
  39. /* argN => (*ctx).REG */
  40. new = node_vlist(node_keyword('.', 0),
  41. node_vlist(node_keyword('*', 0),
  42. ctx,
  43. NULL),
  44. node_string(reg),
  45. NULL);
  46. ctx->type = type_ptr_of(&t_pt_regs);
  47. new->type = n->type;
  48. new->list->type = &t_void;
  49. new->list->next->type = &t_pt_regs;
  50. new->list->next->list->type = &t_void;
  51. node_replace(n, new);
  52. return sym_add(prog->locals, ctx->ident, ctx->type, &ctx->sym);
  53. }
  54. static int kprobe_rewrite_node(prog_t *prog, node_t *n)
  55. {
  56. if ((n->ntype == N_IDENT) && is_arg(n->ident))
  57. return kprobe_rewrite_arg(prog, n);
  58. return 0;
  59. }
  60. static int kprobe_resolve(prog_t *prog, node_t *n)
  61. {
  62. type_t *t;
  63. if (is_arg(n->ident))
  64. t = &t_ulong;
  65. else if (!strcmp(n->ident, "ctx"))
  66. t = type_ptr_of(&t_pt_regs);
  67. else
  68. return -ENOENT;
  69. n->type = t;
  70. return sym_add(prog->locals, n->ident, t, &n->sym);
  71. }
  72. static int kprobe_probe(prog_t *prog)
  73. {
  74. struct kprobe *kp;
  75. kp = calloc(1, sizeof(*kp));
  76. assert(kp);
  77. prog->provider_data = kp;
  78. return 0;
  79. }
  80. provider_t kprobe = {
  81. .name = "kprobe",
  82. .ir_prologue = kprobe_ir_prologue,
  83. .rewrite_node = kprobe_rewrite_node,
  84. .resolve = kprobe_resolve,
  85. .probe = kprobe_probe,
  86. };
  87. __attribute__((constructor))
  88. static void kprobe_init(void)
  89. {
  90. provider_register(&kprobe);
  91. }