A dynamic tracer for Linux

ir.h 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #ifndef _PLY_IR_H
  2. #define _PLY_IR_H
  3. #include <stdint.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <linux/bpf.h>
  7. #define INSN(_code, _dst, _src, _off, _imm) \
  8. ((struct bpf_insn) { \
  9. .code = _code, \
  10. .dst_reg = _dst, \
  11. .src_reg = _src, \
  12. .off = _off, \
  13. .imm = _imm \
  14. })
  15. #define MOV(_dst, _src) INSN(BPF_ALU64 | BPF_MOV | BPF_X, _dst, _src, 0, 0)
  16. #define MOV_IMM(_dst, _imm) INSN(BPF_ALU64 | BPF_MOV | BPF_K, _dst, 0, 0, _imm)
  17. #define EXIT INSN(BPF_JMP | BPF_EXIT, 0, 0, 0, 0)
  18. #define CALL(_imm) INSN(BPF_JMP | BPF_CALL, 0, 0, 0, _imm)
  19. #define JMP(_op, _dst, _src, _off) INSN(BPF_JMP | BPF_OP((_op)) | BPF_X, _dst, _src, _off, 0)
  20. #define JMP_IMM(_op, _dst, _imm, _off) INSN(BPF_JMP | BPF_OP((_op)) | BPF_K, _dst, 0, _off, _imm)
  21. #define ALU(_op, _dst, _src) INSN(BPF_ALU64 | BPF_OP((_op)) | BPF_X, _dst, _src, 0, 0)
  22. #define ALU_IMM(_op, _dst, _imm) INSN(BPF_ALU64 | BPF_OP((_op)) | BPF_K, _dst, 0, 0, _imm)
  23. #define STW_IMM(_dst, _off, _imm) INSN(BPF_ST | BPF_SIZE(BPF_W) | BPF_MEM, _dst, 0, _off, _imm)
  24. #define STXB(_dst, _off, _src) INSN(BPF_STX | BPF_SIZE(BPF_B) | BPF_MEM, _dst, _src, _off, 0)
  25. #define STXH(_dst, _off, _src) INSN(BPF_STX | BPF_SIZE(BPF_H) | BPF_MEM, _dst, _src, _off, 0)
  26. #define STXW(_dst, _off, _src) INSN(BPF_STX | BPF_SIZE(BPF_W) | BPF_MEM, _dst, _src, _off, 0)
  27. #define STXDW(_dst, _off, _src) INSN(BPF_STX | BPF_SIZE(BPF_DW) | BPF_MEM, _dst, _src, _off, 0)
  28. #define LDXB(_dst, _off, _src) INSN(BPF_LDX | BPF_SIZE(BPF_B) | BPF_MEM, _dst, _src, _off, 0)
  29. #define LDXH(_dst, _off, _src) INSN(BPF_LDX | BPF_SIZE(BPF_H) | BPF_MEM, _dst, _src, _off, 0)
  30. #define LDXW(_dst, _off, _src) INSN(BPF_LDX | BPF_SIZE(BPF_W) | BPF_MEM, _dst, _src, _off, 0)
  31. #define LDXDW(_dst, _off, _src) INSN(BPF_LDX | BPF_SIZE(BPF_DW) | BPF_MEM, _dst, _src, _off, 0)
  32. struct sym;
  33. enum vitype {
  34. VI_INSN,
  35. VI_LDMAP,
  36. VI_LABEL,
  37. VI_REG_GET,
  38. VI_REG_PUT,
  39. };
  40. struct vinsn {
  41. enum vitype vitype;
  42. union {
  43. struct {
  44. struct bpf_insn bpf;
  45. uint16_t dst;
  46. uint16_t src;
  47. } insn;
  48. int16_t label;
  49. uint16_t reg;
  50. struct {
  51. uint16_t reg;
  52. struct sym *sym;
  53. } map;
  54. };
  55. };
  56. struct ir {
  57. struct vinsn *vi;
  58. size_t len;
  59. int16_t next_label;
  60. uint16_t next_reg;
  61. };
  62. void insn_dump(struct bpf_insn insn, FILE *fp);
  63. void vinsn_dump(struct vinsn *vi, FILE *fp);
  64. void ir_dump(struct ir *ir, FILE *fp);
  65. int16_t ir_alloc_label (struct ir *ir);
  66. uint16_t ir_alloc_register(struct ir *ir);
  67. void ir_emit_insn (struct ir *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src);
  68. void ir_emit_ldmap (struct ir *ir, uint16_t dst, struct sym *map);
  69. void ir_emit_label (struct ir *ir, int16_t label);
  70. void ir_emit_reg_get(struct ir *ir, uint16_t reg);
  71. void ir_emit_reg_put(struct ir *ir, uint16_t reg);
  72. static inline void ir_emit_call(struct ir *ir, enum bpf_func_id func)
  73. {
  74. ir_emit_reg_get(ir, BPF_REG_0);
  75. ir_emit_reg_get(ir, BPF_REG_1);
  76. ir_emit_reg_get(ir, BPF_REG_2);
  77. ir_emit_reg_get(ir, BPF_REG_3);
  78. ir_emit_reg_get(ir, BPF_REG_4);
  79. ir_emit_reg_get(ir, BPF_REG_5);
  80. ir_emit_insn(ir, CALL(func), 0, 0);
  81. ir_emit_reg_put(ir, BPF_REG_5);
  82. ir_emit_reg_put(ir, BPF_REG_4);
  83. ir_emit_reg_put(ir, BPF_REG_3);
  84. ir_emit_reg_put(ir, BPF_REG_2);
  85. ir_emit_reg_put(ir, BPF_REG_1);
  86. ir_emit_reg_put(ir, BPF_REG_0);
  87. }
  88. struct ir *ir_new(void);
  89. enum irloc {
  90. LOC_IMM = (1 << 0),
  91. LOC_REG = (1 << 1),
  92. LOC_STACK = (1 << 2),
  93. };
  94. struct irstate {
  95. int loc;
  96. uint16_t reg;
  97. int16_t stack;
  98. };
  99. static inline void irs_alloc_reg(struct irstate *irs, struct ir *ir)
  100. {
  101. irs->loc = LOC_REG;
  102. irs->reg = ir_alloc_register(ir);
  103. ir_emit_reg_get(ir, irs->reg);
  104. }
  105. #endif /* _PLY_IR_H */