Browse Source

working on deref compilation

Tobias Waldekranz.com 8 years ago
parent
commit
4b28f9ab92
6 changed files with 137 additions and 55 deletions
  1. 37 3
      global.c
  2. 38 12
      ir.c
  3. 54 35
      ir.h
  4. 2 4
      kprobe.c
  5. 3 0
      ply.c
  6. 3 1
      sym.h

+ 37 - 3
global.c

@@ -47,14 +47,46 @@ static int global_dot_type_infer(const struct func *func, struct node *n)
47 47
 		}
48 48
 	}
49 49
 
50
-	_e("%#N: type '%T' has no member named '%s'.\n",
51
-	   n, t, member->string.data);
50
+	_e("%#N: type '%T' has no member named %N.\n", n, t, member);
52 51
 	return -EINVAL;
53 52
 }
54 53
 
55 54
 
56 55
 /* :deref */
57 56
 
57
+static int global_deref_ir_post(const struct func *func, struct node *n,
58
+				struct prog *prog)
59
+{
60
+	struct node *ptr = n->expr.args;
61
+	struct irstate *dst;
62
+	size_t size;
63
+
64
+	dst = &n->sym->irs;
65
+	if (dst->hint.dot)
66
+		/* (*ptr).member, ptr points to a struct and our
67
+		 * parent is only interested in one member. don't load
68
+		 * the struct, let the dot operaton steal the address
69
+		 * from our argument */
70
+		return 0;
71
+
72
+	if (dst->loc)
73
+		return 0;
74
+
75
+	size = type_sizeof(type_base(ptr->sym->type)->ptr.type);
76
+	/* parent might have already allocated stack for us. typically
77
+	 * when the value is one part of a map key or value. */
78
+	if (!dst->hint.stack)
79
+		irs_alloc_stack(dst, prog->ir, size);
80
+
81
+	ir_emit_insn(prog->ir, MOV(0, 0), BPF_REG_1, BPF_REG_BP);
82
+	ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, 0, dst->stack), BPF_REG_1, 0);
83
+	ir_emit_insn(prog->ir, MOV_IMM(0, (int32_t)size), BPF_REG_2, 0);
84
+	ir_emit_mov_irs(prog->ir, BPF_REG_3, &ptr->sym->irs);
85
+	ir_emit_insn(prog->ir, CALL(BPF_FUNC_probe_read), 0, 0);
86
+	return 0;
87
+}
88
+
89
+
58 90
 static int global_deref_type_infer(const struct func *func, struct node *n)
59 91
 {
60 92
 	struct node *ptr = n->expr.args;
@@ -175,7 +207,7 @@ static int global_assign_type_infer(const struct func *func, struct node *n)
175 207
 
176 208
 		/* TODO do we need assignment expressions? */
177 209
 		n->sym->type = &t_void;
178
-
210
+		
179 211
 		if (node_is_map(lval))
180 212
 			return global_assign_type_infer_map(lval);
181 213
 
@@ -352,6 +384,8 @@ static const struct func global_funcs[] = {
352 384
 		.name = ":deref",
353 385
 		.type = &t_1arg_func,
354 386
 		.type_infer = global_deref_type_infer,
387
+
388
+		.ir_post = global_deref_ir_post,
355 389
 	},
356 390
 
357 391
 	{

+ 38 - 12
ir.c

@@ -313,22 +313,40 @@ void ir_emit_label  (struct ir *ir, int16_t label)
313 313
 	ir_emit(ir, &vi);
314 314
 }
315 315
 
316
-void ir_emit_reg_get(struct ir *ir, uint16_t reg)
317
-{
318
-	struct vinsn vi;
316
+/* void ir_emit_reg_get(struct ir *ir, uint16_t reg) */
317
+/* { */
318
+/* 	struct vinsn vi; */
319 319
 
320
-	vi.vitype = VI_REG_GET;
321
-	vi.reg = reg;
322
-	ir_emit(ir, &vi);
323
-}
320
+/* 	vi.vitype = VI_REG_GET; */
321
+/* 	vi.reg = reg; */
322
+/* 	ir_emit(ir, &vi); */
323
+/* } */
324
+
325
+/* void ir_emit_reg_put(struct ir *ir, uint16_t reg) */
326
+/* { */
327
+/* 	struct vinsn vi; */
324 328
 
325
-void ir_emit_reg_put(struct ir *ir, uint16_t reg)
329
+/* 	vi.vitype = VI_REG_PUT; */
330
+/* 	vi.reg = reg; */
331
+/* 	ir_emit(ir, &vi); */
332
+/* } */
333
+
334
+void ir_emit_mov_irs(struct ir *ir, uint16_t dst, struct irstate *src)
326 335
 {
327
-	struct vinsn vi;
336
+	switch (src->loc) {
337
+	case LOC_IMM:
338
+		ir_emit_insn(ir, MOV_IMM(0, src->imm), dst, 0);
339
+		break;
340
+	case LOC_REG:
341
+		ir_emit_insn(ir, MOV(0, 0), dst, src->reg);
342
+		break;
343
+	case LOC_STACK:
344
+		ir_emit_insn(ir, LDX(0, src->stack, 0), dst, BPF_REG_BP);
345
+		break;
328 346
 
329
-	vi.vitype = VI_REG_PUT;
330
-	vi.reg = reg;
331
-	ir_emit(ir, &vi);
347
+	default:
348
+		assert(0);
349
+	}
332 350
 }
333 351
 
334 352
 int16_t ir_alloc_label (struct ir *ir)
@@ -341,6 +359,14 @@ uint16_t ir_alloc_register(struct ir *ir)
341 359
 	return ir->next_reg++;
342 360
 }
343 361
 
362
+ssize_t ir_alloc_stack(struct ir *ir, size_t size)
363
+{
364
+	ir->sp -= size;
365
+	assert(ir->sp > INT32_MIN);
366
+
367
+	return ir->sp;
368
+}
369
+
344 370
 struct ir *ir_new(void)
345 371
 {
346 372
 	struct ir *ir;

+ 54 - 35
ir.h

@@ -5,6 +5,7 @@
5 5
 #include <stdio.h>
6 6
 #include <stdlib.h>
7 7
 
8
+#include <bits/wordsize.h>
8 9
 #include <linux/bpf.h>
9 10
 
10 11
 #define INSN(_code, _dst, _src, _off, _imm)	\
@@ -24,8 +25,11 @@
24 25
 #define JMP(_op, _dst, _src, _off)     INSN(BPF_JMP | BPF_OP((_op)) | BPF_X, _dst, _src, _off, 0)
25 26
 #define JMP_IMM(_op, _dst, _imm, _off) INSN(BPF_JMP | BPF_OP((_op)) | BPF_K, _dst, 0, _off, _imm)
26 27
 
27
-#define ALU(_op, _dst, _src)     INSN(BPF_ALU64 | BPF_OP((_op)) | BPF_X, _dst, _src, 0, 0)
28
-#define ALU_IMM(_op, _dst, _imm) INSN(BPF_ALU64 | BPF_OP((_op)) | BPF_K, _dst, 0, 0, _imm)
28
+#define ALU32(_op, _dst, _src)     INSN(BPF_ALU | BPF_OP((_op)) | BPF_X, _dst, _src, 0, 0)
29
+#define ALU32_IMM(_op, _dst, _imm) INSN(BPF_ALU | BPF_OP((_op)) | BPF_K, _dst, 0, 0, _imm)
30
+
31
+#define ALU64(_op, _dst, _src)     INSN(BPF_ALU64 | BPF_OP((_op)) | BPF_X, _dst, _src, 0, 0)
32
+#define ALU64_IMM(_op, _dst, _imm) INSN(BPF_ALU64 | BPF_OP((_op)) | BPF_K, _dst, 0, 0, _imm)
29 33
 
30 34
 #define STW_IMM(_dst, _off, _imm) INSN(BPF_ST  | BPF_SIZE(BPF_W)  | BPF_MEM, _dst, 0, _off, _imm)
31 35
 #define STXB(_dst, _off, _src)   INSN(BPF_STX | BPF_SIZE(BPF_B) | BPF_MEM, _dst, _src, _off, 0)
@@ -38,6 +42,20 @@
38 42
 #define LDXW(_dst, _off, _src)  INSN(BPF_LDX | BPF_SIZE(BPF_W)  | BPF_MEM, _dst, _src, _off, 0)
39 43
 #define LDXDW(_dst, _off, _src) INSN(BPF_LDX | BPF_SIZE(BPF_DW) | BPF_MEM, _dst, _src, _off, 0)
40 44
 
45
+#if __WORDSIZE == 64
46
+#  define ALU ALU64
47
+#  define ALU_IMM ALU64_IMM
48
+#  define STX STXDW
49
+#  define LDX LDXDW
50
+#else
51
+#  define ALU ALU32
52
+#  define ALU_IMM ALU32_IMM
53
+#  define STX STXW
54
+#  define LDX LDXW
55
+#endif
56
+
57
+#define BPF_REG_BP BPF_REG_10
58
+
41 59
 struct sym;
42 60
 
43 61
 enum vitype {
@@ -74,6 +92,28 @@ struct ir {
74 92
 
75 93
 	int16_t next_label;
76 94
 	uint16_t next_reg;
95
+
96
+	ssize_t sp;
97
+};
98
+
99
+enum irloc {
100
+	LOC_IMM   = (1 << 0),
101
+	LOC_REG   = (1 << 1),
102
+	LOC_STACK = (1 << 2),
103
+};
104
+
105
+
106
+struct irstate {
107
+	int loc;
108
+
109
+	uint16_t reg;
110
+	int32_t  stack;
111
+	int32_t  imm;
112
+
113
+	struct {
114
+		int dot:1;
115
+		int stack:1;
116
+	} hint;
77 117
 };
78 118
 
79 119
 void insn_dump(struct bpf_insn insn, FILE *fp);
@@ -82,50 +122,29 @@ void ir_dump(struct ir *ir, FILE *fp);
82 122
 
83 123
 int16_t  ir_alloc_label   (struct ir *ir);
84 124
 uint16_t ir_alloc_register(struct ir *ir);
125
+ssize_t  ir_alloc_stack   (struct ir *ir, size_t size);
85 126
 
86 127
 void ir_emit_insn   (struct ir *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src);
87 128
 void ir_emit_ldmap  (struct ir *ir, uint16_t dst, struct sym *map);
88 129
 void ir_emit_label  (struct ir *ir, int16_t label);
89
-void ir_emit_reg_get(struct ir *ir, uint16_t reg);
90
-void ir_emit_reg_put(struct ir *ir, uint16_t reg);
91
-
92
-static inline void ir_emit_call(struct ir *ir, enum bpf_func_id func)
93
-{
94
-	ir_emit_reg_get(ir, BPF_REG_0);
95
-	ir_emit_reg_get(ir, BPF_REG_1);
96
-	ir_emit_reg_get(ir, BPF_REG_2);
97
-	ir_emit_reg_get(ir, BPF_REG_3);
98
-	ir_emit_reg_get(ir, BPF_REG_4);
99
-	ir_emit_reg_get(ir, BPF_REG_5);
100
-	ir_emit_insn(ir, CALL(func), 0, 0);
101
-	ir_emit_reg_put(ir, BPF_REG_5);
102
-	ir_emit_reg_put(ir, BPF_REG_4);
103
-	ir_emit_reg_put(ir, BPF_REG_3);
104
-	ir_emit_reg_put(ir, BPF_REG_2);
105
-	ir_emit_reg_put(ir, BPF_REG_1);
106
-	ir_emit_reg_put(ir, BPF_REG_0);
107
-}
130
+/* void ir_emit_reg_get(struct ir *ir, uint16_t reg); */
131
+/* void ir_emit_reg_put(struct ir *ir, uint16_t reg); */
132
+void ir_emit_mov_irs(struct ir *ir, uint16_t dst, struct irstate *src);
108 133
 
109 134
 struct ir *ir_new(void);
110 135
 
111
-enum irloc {
112
-	LOC_IMM   = (1 << 0),
113
-	LOC_REG   = (1 << 1),
114
-	LOC_STACK = (1 << 2),
115
-};
116 136
 
117
-struct irstate {
118
-	int loc;
119
-
120
-	uint16_t reg;
121
-	int16_t stack;
122
-};
123
-
124
-static inline void irs_alloc_reg(struct irstate *irs, struct ir *ir)
137
+static inline void irs_alloc_register(struct irstate *irs, struct ir *ir)
125 138
 {
126 139
 	irs->loc = LOC_REG;
127 140
 	irs->reg = ir_alloc_register(ir);
128
-	ir_emit_reg_get(ir, irs->reg);
141
+}
142
+
143
+static inline void irs_alloc_stack(struct irstate *irs, struct ir *ir,
144
+				   size_t size)
145
+{
146
+	irs->loc = LOC_STACK;
147
+	irs->stack = ir_alloc_stack(ir, size);
129 148
 }
130 149
 
131 150
 #endif	/* _PLY_IR_H */

+ 2 - 4
kprobe.c

@@ -14,7 +14,6 @@
14 14
 #include "type.h"
15 15
 
16 16
 struct kprobe {
17
-	struct irstate regs_irs;
18 17
 };
19 18
 
20 19
 /* regs */
@@ -85,19 +84,18 @@ static const struct func kprobe_arg_func = {
85 84
 
86 85
 static int kprobe_ir_pre(struct prog *prog)
87 86
 {
88
-	struct kprobe *kp = prog->provider_data;
89 87
 	struct sym **sym;
90 88
 
91 89
 	symtab_foreach(prog->locals, sym) {
92 90
 		if ((*sym)->name && !strcmp((*sym)->name, "regs")) {
93
-			irs_alloc_reg(&kp->regs_irs, prog->ir);
91
+			irs_alloc_register(&(*sym)->irs, prog->ir);
94 92
 
95 93
 			/* kernel sets r1 to the address of the
96 94
 			 * pt_regs struct, which ply denotes as
97 95
 			 * 'regs'. if we're using it we need to get a
98 96
 			 * reference to it before it is clobbered. */
99 97
 			ir_emit_insn(prog->ir, MOV(0, 0),
100
-				     kp->regs_irs.reg, BPF_REG_1);
98
+				     (*sym)->irs.reg, BPF_REG_1);
101 99
 		}
102 100
 	}
103 101
 

+ 3 - 0
ply.c

@@ -146,6 +146,9 @@ int pass_sym_alloc(struct node *n, void *_prog)
146 146
 	struct provider *global = provider_get(":");
147 147
 	int err = 0;
148 148
 
149
+	if (n->sym)
150
+		return 0;
151
+
149 152
 	switch (n->ntype) {
150 153
 	case N_EXPR:
151 154
 	case N_IDENT:

+ 3 - 1
sym.h

@@ -3,6 +3,8 @@
3 3
 
4 4
 #include <stdint.h>
5 5
 
6
+#include "ir.h"
7
+
6 8
 struct func;
7 9
 struct node;
8 10
 struct type;
@@ -16,7 +18,7 @@ struct sym {
16 18
 	const struct func *func;
17 19
 
18 20
 	struct type *type;
19
-	/* irstate_t irs; */
21
+	struct irstate irs;
20 22
 };
21 23
 
22 24
 struct symtab {