A dynamic tracer for Linux

kprobe.c 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include <assert.h>
  2. #include <errno.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <linux/ptrace.h>
  6. #include "func.h"
  7. #include "node.h"
  8. #include "ply.h"
  9. #include "sym.h"
  10. #include "type.h"
  11. struct kprobe {
  12. };
  13. /* static int kprobe_ir_prologue(prog_t *prog) */
  14. /* { */
  15. /* sym_t *ctx = sym_get(prog->locals, "ctx"); */
  16. /* if (!ctx) */
  17. /* return 0; */
  18. /* irs_alloc_reg(&ctx->irs, prog->ir); */
  19. /* /\* kernel sets r1 to the address of the context *\/ */
  20. /* ir_emit_insn(prog->ir, MOV(0, 0), ctx->irs.reg, BPF_REG_1); */
  21. /* return 0; */
  22. /* } */
  23. static inline int is_arg(const char *name)
  24. {
  25. return (strstr(name, "arg") == name)
  26. && (strlen(name) == 4)
  27. && (name[3] >= '0' && name[3] <= '9');
  28. }
  29. /* static int kprobe_rewrite_arg(prog_t *prog, node_t *n) */
  30. /* { */
  31. /* const char *reg; */
  32. /* int arg = n->ident[3] - '0'; */
  33. /* node_t *new, *ctx; */
  34. /* reg = arch_register_argument(arg); */
  35. /* if (!reg) { */
  36. /* node_print(n, stderr); */
  37. /* fputs(": the location of this argument is unknown\n", stderr); */
  38. /* /\* TODO: add ABI mappings for specifying arguments */
  39. /* * passed on the stack. *\/ */
  40. /* return -EINVAL; */
  41. /* } */
  42. /* ctx = node_ident("ctx"); */
  43. /* /\* argN => (*ctx).REG *\/ */
  44. /* new = node_vlist(node_keyword('.', 0), */
  45. /* node_vlist(node_keyword('*', 0), */
  46. /* ctx, */
  47. /* NULL), */
  48. /* node_string(reg), */
  49. /* NULL); */
  50. /* ctx->type = type_ptr_of(&t_pt_regs); */
  51. /* new->type = n->type; */
  52. /* new->list->type = &t_void; */
  53. /* new->list->next->type = &t_pt_regs; */
  54. /* new->list->next->list->type = &t_void; */
  55. /* node_replace(n, new); */
  56. /* return sym_add(prog->locals, ctx->ident, ctx->type, &ctx->sym); */
  57. /* } */
  58. /* static int kprobe_rewrite_node(prog_t *prog, node_t *n) */
  59. /* { */
  60. /* if ((n->ntype == N_IDENT) && is_arg(n->ident)) */
  61. /* return kprobe_rewrite_arg(prog, n); */
  62. /* return 0; */
  63. /* } */
  64. /* static int kprobe_resolve(prog_t *prog, node_t *n) */
  65. /* { */
  66. /* type_t *t; */
  67. /* if (is_arg(n->ident)) */
  68. /* t = &t_ulong; */
  69. /* else if (!strcmp(n->ident, "ctx")) */
  70. /* t = type_ptr_of(&t_pt_regs); */
  71. /* else */
  72. /* return -ENOENT; */
  73. /* n->type = t; */
  74. /* return sym_add(prog->locals, n->ident, t, &n->sym); */
  75. /* } */
  76. static const struct func kprobe_arg_func = {
  77. .name = "argN",
  78. /* for now, in the future we could read dwarf symbols to
  79. * figure out the real type. */
  80. .type = &t_ulong,
  81. .static_ret = 1,
  82. };
  83. static int kprobe_sym_alloc(struct prog *prog, struct node *n)
  84. {
  85. const struct func *func = NULL;
  86. int err;
  87. switch (n->ntype) {
  88. case N_EXPR:
  89. break;
  90. case N_IDENT:
  91. if (is_arg(n->ident.name))
  92. func = &kprobe_arg_func;
  93. break;
  94. default:
  95. break;
  96. }
  97. if (!func)
  98. return -ENOENT;
  99. err = func_static_validate(func, n);
  100. if (err)
  101. return err;
  102. n->sym = sym_alloc(prog->locals, n, func);
  103. if (func->static_ret)
  104. n->sym->type = func_return_type(func);
  105. return 0;
  106. }
  107. static int kprobe_probe(struct prog *prog)
  108. {
  109. struct kprobe *kp;
  110. kp = calloc(1, sizeof(*kp));
  111. assert(kp);
  112. prog->provider_data = kp;
  113. return 0;
  114. }
  115. struct provider kprobe = {
  116. .name = "kprobe",
  117. /* .ir_prologue = kprobe_ir_prologue, */
  118. /* .rewrite_node = kprobe_rewrite_node, */
  119. /* .resolve = kprobe_resolve, */
  120. .sym_alloc = kprobe_sym_alloc,
  121. .probe = kprobe_probe,
  122. };
  123. __attribute__((constructor))
  124. static void kprobe_init(void)
  125. {
  126. provider_register(&kprobe);
  127. }