浏览代码

working on deref compilation

Tobias Waldekranz.com 8 年之前
父节点
当前提交
4b28f9ab92
共有 6 个文件被更改,包括 137 次插入55 次删除
  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
 		}
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
 	return -EINVAL;
51
 	return -EINVAL;
53
 }
52
 }
54
 
53
 
55
 
54
 
56
 /* :deref */
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
 static int global_deref_type_infer(const struct func *func, struct node *n)
90
 static int global_deref_type_infer(const struct func *func, struct node *n)
59
 {
91
 {
60
 	struct node *ptr = n->expr.args;
92
 	struct node *ptr = n->expr.args;
175
 
207
 
176
 		/* TODO do we need assignment expressions? */
208
 		/* TODO do we need assignment expressions? */
177
 		n->sym->type = &t_void;
209
 		n->sym->type = &t_void;
178
-
210
+		
179
 		if (node_is_map(lval))
211
 		if (node_is_map(lval))
180
 			return global_assign_type_infer_map(lval);
212
 			return global_assign_type_infer_map(lval);
181
 
213
 
352
 		.name = ":deref",
384
 		.name = ":deref",
353
 		.type = &t_1arg_func,
385
 		.type = &t_1arg_func,
354
 		.type_infer = global_deref_type_infer,
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
 	ir_emit(ir, &vi);
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
 int16_t ir_alloc_label (struct ir *ir)
352
 int16_t ir_alloc_label (struct ir *ir)
341
 	return ir->next_reg++;
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
 struct ir *ir_new(void)
370
 struct ir *ir_new(void)
345
 {
371
 {
346
 	struct ir *ir;
372
 	struct ir *ir;

+ 54 - 35
ir.h

5
 #include <stdio.h>
5
 #include <stdio.h>
6
 #include <stdlib.h>
6
 #include <stdlib.h>
7
 
7
 
8
+#include <bits/wordsize.h>
8
 #include <linux/bpf.h>
9
 #include <linux/bpf.h>
9
 
10
 
10
 #define INSN(_code, _dst, _src, _off, _imm)	\
11
 #define INSN(_code, _dst, _src, _off, _imm)	\
24
 #define JMP(_op, _dst, _src, _off)     INSN(BPF_JMP | BPF_OP((_op)) | BPF_X, _dst, _src, _off, 0)
25
 #define JMP(_op, _dst, _src, _off)     INSN(BPF_JMP | BPF_OP((_op)) | BPF_X, _dst, _src, _off, 0)
25
 #define JMP_IMM(_op, _dst, _imm, _off) INSN(BPF_JMP | BPF_OP((_op)) | BPF_K, _dst, 0, _off, _imm)
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
 #define STW_IMM(_dst, _off, _imm) INSN(BPF_ST  | BPF_SIZE(BPF_W)  | BPF_MEM, _dst, 0, _off, _imm)
34
 #define STW_IMM(_dst, _off, _imm) INSN(BPF_ST  | BPF_SIZE(BPF_W)  | BPF_MEM, _dst, 0, _off, _imm)
31
 #define STXB(_dst, _off, _src)   INSN(BPF_STX | BPF_SIZE(BPF_B) | BPF_MEM, _dst, _src, _off, 0)
35
 #define STXB(_dst, _off, _src)   INSN(BPF_STX | BPF_SIZE(BPF_B) | BPF_MEM, _dst, _src, _off, 0)
38
 #define LDXW(_dst, _off, _src)  INSN(BPF_LDX | BPF_SIZE(BPF_W)  | BPF_MEM, _dst, _src, _off, 0)
42
 #define LDXW(_dst, _off, _src)  INSN(BPF_LDX | BPF_SIZE(BPF_W)  | BPF_MEM, _dst, _src, _off, 0)
39
 #define LDXDW(_dst, _off, _src) INSN(BPF_LDX | BPF_SIZE(BPF_DW) | BPF_MEM, _dst, _src, _off, 0)
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
 struct sym;
59
 struct sym;
42
 
60
 
43
 enum vitype {
61
 enum vitype {
74
 
92
 
75
 	int16_t next_label;
93
 	int16_t next_label;
76
 	uint16_t next_reg;
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
 void insn_dump(struct bpf_insn insn, FILE *fp);
119
 void insn_dump(struct bpf_insn insn, FILE *fp);
82
 
122
 
83
 int16_t  ir_alloc_label   (struct ir *ir);
123
 int16_t  ir_alloc_label   (struct ir *ir);
84
 uint16_t ir_alloc_register(struct ir *ir);
124
 uint16_t ir_alloc_register(struct ir *ir);
125
+ssize_t  ir_alloc_stack   (struct ir *ir, size_t size);
85
 
126
 
86
 void ir_emit_insn   (struct ir *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src);
127
 void ir_emit_insn   (struct ir *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src);
87
 void ir_emit_ldmap  (struct ir *ir, uint16_t dst, struct sym *map);
128
 void ir_emit_ldmap  (struct ir *ir, uint16_t dst, struct sym *map);
88
 void ir_emit_label  (struct ir *ir, int16_t label);
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
 struct ir *ir_new(void);
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
 	irs->loc = LOC_REG;
139
 	irs->loc = LOC_REG;
127
 	irs->reg = ir_alloc_register(ir);
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
 #endif	/* _PLY_IR_H */
150
 #endif	/* _PLY_IR_H */

+ 2 - 4
kprobe.c

14
 #include "type.h"
14
 #include "type.h"
15
 
15
 
16
 struct kprobe {
16
 struct kprobe {
17
-	struct irstate regs_irs;
18
 };
17
 };
19
 
18
 
20
 /* regs */
19
 /* regs */
85
 
84
 
86
 static int kprobe_ir_pre(struct prog *prog)
85
 static int kprobe_ir_pre(struct prog *prog)
87
 {
86
 {
88
-	struct kprobe *kp = prog->provider_data;
89
 	struct sym **sym;
87
 	struct sym **sym;
90
 
88
 
91
 	symtab_foreach(prog->locals, sym) {
89
 	symtab_foreach(prog->locals, sym) {
92
 		if ((*sym)->name && !strcmp((*sym)->name, "regs")) {
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
 			/* kernel sets r1 to the address of the
93
 			/* kernel sets r1 to the address of the
96
 			 * pt_regs struct, which ply denotes as
94
 			 * pt_regs struct, which ply denotes as
97
 			 * 'regs'. if we're using it we need to get a
95
 			 * 'regs'. if we're using it we need to get a
98
 			 * reference to it before it is clobbered. */
96
 			 * reference to it before it is clobbered. */
99
 			ir_emit_insn(prog->ir, MOV(0, 0),
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
 	struct provider *global = provider_get(":");
146
 	struct provider *global = provider_get(":");
147
 	int err = 0;
147
 	int err = 0;
148
 
148
 
149
+	if (n->sym)
150
+		return 0;
151
+
149
 	switch (n->ntype) {
152
 	switch (n->ntype) {
150
 	case N_EXPR:
153
 	case N_EXPR:
151
 	case N_IDENT:
154
 	case N_IDENT:

+ 3 - 1
sym.h

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