浏览代码

ir back up, working on rewrite

Tobias Waldekranz.com 8 年之前
父节点
当前提交
a5e5286b12
共有 7 个文件被更改,包括 195 次插入426 次删除
  1. 5 1
      func.h
  2. 18 20
      ir.c
  3. 27 26
      ir.h
  4. 74 70
      kprobe.c
  5. 63 303
      ply.c
  6. 4 3
      ply.h
  7. 4 3
      sym.h

+ 5 - 1
func.h

12
 	int static_ret:1; 	/* return type is statically known */
12
 	int static_ret:1; 	/* return type is statically known */
13
 
13
 
14
 	int (*static_validate)(const struct func *, struct node *);
14
 	int (*static_validate)(const struct func *, struct node *);
15
-	int (*type_infer)(const struct func *, struct node *);
15
+	int (*type_infer)     (const struct func *, struct node *);
16
+	int (*rewrite)        (const struct func *, struct node *, struct prog *);
17
+
18
+	int (*ir_pre) (const struct func *, struct node *, struct prog *);
19
+	int (*ir_post)(const struct func *, struct node *, struct prog *);
16
 };
20
 };
17
 
21
 
18
 int func_static_validate(const struct func *func, struct node *n);
22
 int func_static_validate(const struct func *func, struct node *n);

+ 18 - 20
ir.c

1
-#if 0
2
 #include <assert.h>
1
 #include <assert.h>
3
 #include <inttypes.h>
2
 #include <inttypes.h>
4
 #include <stdio.h>
3
 #include <stdio.h>
208
 	__insn_dump(insn, insn.dst_reg, insn.src_reg, fp);
207
 	__insn_dump(insn, insn.dst_reg, insn.src_reg, fp);
209
 }
208
 }
210
 
209
 
211
-void vinsn_dump(vinsn_t *vi, FILE *fp)
210
+void vinsn_dump(struct vinsn *vi, FILE *fp)
212
 {
211
 {
213
 	switch (vi->vitype) {
212
 	switch (vi->vitype) {
214
 	case VI_INSN:
213
 	case VI_INSN:
230
 	}
229
 	}
231
 }
230
 }
232
 
231
 
233
-void ir_dump(ir_t *ir, FILE *fp)
232
+void ir_dump(struct ir *ir, FILE *fp)
234
 {
233
 {
235
 	size_t i;
234
 	size_t i;
236
 
235
 
237
 	for (i = 0; i < ir->len; i++) {
236
 	for (i = 0; i < ir->len; i++) {
238
-		vinsn_t *vi = &ir->vi[i];
237
+		struct vinsn *vi = &ir->vi[i];
239
 
238
 
240
 		switch (vi->vitype) {
239
 		switch (vi->vitype) {
241
 		case VI_INSN:
240
 		case VI_INSN:
276
 	}
275
 	}
277
 }
276
 }
278
 
277
 
279
-static void ir_emit(ir_t *ir, vinsn_t *vi)
278
+static void ir_emit(struct ir *ir, struct vinsn *vi)
280
 {
279
 {
281
 	ir->vi = realloc(ir->vi, (++ir->len)*sizeof(*vi));
280
 	ir->vi = realloc(ir->vi, (++ir->len)*sizeof(*vi));
282
 	assert(ir->vi);
281
 	assert(ir->vi);
284
 	ir->vi[ir->len - 1] = *vi;
283
 	ir->vi[ir->len - 1] = *vi;
285
 }
284
 }
286
 
285
 
287
-void ir_emit_insn(ir_t *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src)
286
+void ir_emit_insn(struct ir *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src)
288
 {
287
 {
289
-	vinsn_t vi;
288
+	struct vinsn vi;
290
 
289
 
291
 	vi.vitype = VI_INSN;
290
 	vi.vitype = VI_INSN;
292
 	vi.insn.bpf = bpf;
291
 	vi.insn.bpf = bpf;
295
 	ir_emit(ir, &vi);
294
 	ir_emit(ir, &vi);
296
 }
295
 }
297
 
296
 
298
-void ir_emit_ldmap(ir_t *ir, uint16_t dst, sym_t *map)
297
+void ir_emit_ldmap(struct ir *ir, uint16_t dst, struct sym *map)
299
 {
298
 {
300
-	vinsn_t vi;
299
+	struct vinsn vi;
301
 
300
 
302
 	vi.vitype = VI_LDMAP;
301
 	vi.vitype = VI_LDMAP;
303
 	vi.map.reg = dst;
302
 	vi.map.reg = dst;
305
 	ir_emit(ir, &vi);
304
 	ir_emit(ir, &vi);
306
 }
305
 }
307
 
306
 
308
-void ir_emit_label  (ir_t *ir, int16_t label)
307
+void ir_emit_label  (struct ir *ir, int16_t label)
309
 {
308
 {
310
-	vinsn_t vi;
309
+	struct vinsn vi;
311
 
310
 
312
 	vi.vitype = VI_LABEL;
311
 	vi.vitype = VI_LABEL;
313
 	vi.label = label;
312
 	vi.label = label;
314
 	ir_emit(ir, &vi);
313
 	ir_emit(ir, &vi);
315
 }
314
 }
316
 
315
 
317
-void ir_emit_reg_get(ir_t *ir, uint16_t reg)
316
+void ir_emit_reg_get(struct ir *ir, uint16_t reg)
318
 {
317
 {
319
-	vinsn_t vi;
318
+	struct vinsn vi;
320
 
319
 
321
 	vi.vitype = VI_REG_GET;
320
 	vi.vitype = VI_REG_GET;
322
 	vi.reg = reg;
321
 	vi.reg = reg;
323
 	ir_emit(ir, &vi);
322
 	ir_emit(ir, &vi);
324
 }
323
 }
325
 
324
 
326
-void ir_emit_reg_put(ir_t *ir, uint16_t reg)
325
+void ir_emit_reg_put(struct ir *ir, uint16_t reg)
327
 {
326
 {
328
-	vinsn_t vi;
327
+	struct vinsn vi;
329
 
328
 
330
 	vi.vitype = VI_REG_PUT;
329
 	vi.vitype = VI_REG_PUT;
331
 	vi.reg = reg;
330
 	vi.reg = reg;
332
 	ir_emit(ir, &vi);
331
 	ir_emit(ir, &vi);
333
 }
332
 }
334
 
333
 
335
-int16_t ir_alloc_label (ir_t *ir)
334
+int16_t ir_alloc_label (struct ir *ir)
336
 {
335
 {
337
 	return ir->next_label--;
336
 	return ir->next_label--;
338
 }
337
 }
339
 
338
 
340
-uint16_t ir_alloc_register(ir_t *ir)
339
+uint16_t ir_alloc_register(struct ir *ir)
341
 {
340
 {
342
 	return ir->next_reg++;
341
 	return ir->next_reg++;
343
 }
342
 }
344
 
343
 
345
-ir_t *ir_new(void)
344
+struct ir *ir_new(void)
346
 {
345
 {
347
-	ir_t *ir;
346
+	struct ir *ir;
348
 
347
 
349
 	ir = calloc(1, sizeof(*ir));
348
 	ir = calloc(1, sizeof(*ir));
350
 	assert(ir);
349
 	assert(ir);
353
 	ir->next_label = -1;
352
 	ir->next_label = -1;
354
 	return ir;
353
 	return ir;
355
 }
354
 }
356
-#endif

+ 27 - 26
ir.h

2
 #define _PLY_IR_H
2
 #define _PLY_IR_H
3
 
3
 
4
 #include <stdint.h>
4
 #include <stdint.h>
5
+#include <stdio.h>
5
 #include <stdlib.h>
6
 #include <stdlib.h>
6
 
7
 
7
 #include <linux/bpf.h>
8
 #include <linux/bpf.h>
37
 #define LDXW(_dst, _off, _src)  INSN(BPF_LDX | BPF_SIZE(BPF_W)  | 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)
38
 #define LDXDW(_dst, _off, _src) INSN(BPF_LDX | BPF_SIZE(BPF_DW) | 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)
39
 
40
 
40
-typedef struct sym sym_t;
41
+struct sym;
41
 
42
 
42
-typedef enum vitype {
43
+enum vitype {
43
 	VI_INSN,
44
 	VI_INSN,
44
 	VI_LDMAP,
45
 	VI_LDMAP,
45
 	VI_LABEL,
46
 	VI_LABEL,
46
 	VI_REG_GET,
47
 	VI_REG_GET,
47
 	VI_REG_PUT,
48
 	VI_REG_PUT,
48
-} vitype_t;
49
+};
49
 
50
 
50
-typedef struct vinsn {
51
-	vitype_t vitype;
51
+struct vinsn {
52
+	enum vitype vitype;
52
 
53
 
53
 	union {
54
 	union {
54
 		struct {
55
 		struct {
62
 
63
 
63
 		struct {
64
 		struct {
64
 			uint16_t reg;
65
 			uint16_t reg;
65
-			sym_t *sym;
66
+			struct sym *sym;
66
 		} map;
67
 		} map;
67
 	};
68
 	};
68
-} vinsn_t;
69
+};
69
 
70
 
70
-typedef struct ir {
71
-	vinsn_t *vi;
71
+struct ir {
72
+	struct vinsn *vi;
72
 	size_t len;
73
 	size_t len;
73
 
74
 
74
 	int16_t next_label;
75
 	int16_t next_label;
75
 	uint16_t next_reg;
76
 	uint16_t next_reg;
76
-} ir_t;
77
+};
77
 
78
 
78
 void insn_dump(struct bpf_insn insn, FILE *fp);
79
 void insn_dump(struct bpf_insn insn, FILE *fp);
79
-void vinsn_dump(vinsn_t *vi, FILE *fp);
80
-void ir_dump(ir_t *ir, FILE *fp);
80
+void vinsn_dump(struct vinsn *vi, FILE *fp);
81
+void ir_dump(struct ir *ir, FILE *fp);
81
 
82
 
82
-int16_t  ir_alloc_label   (ir_t *ir);
83
-uint16_t ir_alloc_register(ir_t *ir);
83
+int16_t  ir_alloc_label   (struct ir *ir);
84
+uint16_t ir_alloc_register(struct ir *ir);
84
 
85
 
85
-void ir_emit_insn   (ir_t *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src);
86
-void ir_emit_ldmap  (ir_t *ir, uint16_t dst, sym_t *map);
87
-void ir_emit_label  (ir_t *ir, int16_t label);
88
-void ir_emit_reg_get(ir_t *ir, uint16_t reg);
89
-void ir_emit_reg_put(ir_t *ir, uint16_t reg);
86
+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);
88
+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);
90
 
91
 
91
-static inline void ir_emit_call(ir_t *ir, enum bpf_func_id func)
92
+static inline void ir_emit_call(struct ir *ir, enum bpf_func_id func)
92
 {
93
 {
93
 	ir_emit_reg_get(ir, BPF_REG_0);
94
 	ir_emit_reg_get(ir, BPF_REG_0);
94
 	ir_emit_reg_get(ir, BPF_REG_1);
95
 	ir_emit_reg_get(ir, BPF_REG_1);
105
 	ir_emit_reg_put(ir, BPF_REG_0);
106
 	ir_emit_reg_put(ir, BPF_REG_0);
106
 }
107
 }
107
 
108
 
108
-ir_t *ir_new(void);
109
+struct ir *ir_new(void);
109
 
110
 
110
-typedef enum irloc {
111
+enum irloc {
111
 	LOC_IMM   = (1 << 0),
112
 	LOC_IMM   = (1 << 0),
112
 	LOC_REG   = (1 << 1),
113
 	LOC_REG   = (1 << 1),
113
 	LOC_STACK = (1 << 2),
114
 	LOC_STACK = (1 << 2),
114
-} irloc_t;
115
+};
115
 
116
 
116
-typedef struct irstate {
117
+struct irstate {
117
 	int loc;
118
 	int loc;
118
 
119
 
119
 	uint16_t reg;
120
 	uint16_t reg;
120
 	int16_t stack;
121
 	int16_t stack;
121
-} irstate_t;
122
+};
122
 
123
 
123
-static inline void irs_alloc_reg(irstate_t *irs, ir_t *ir)
124
+static inline void irs_alloc_reg(struct irstate *irs, struct ir *ir)
124
 {
125
 {
125
 	irs->loc = LOC_REG;
126
 	irs->loc = LOC_REG;
126
 	irs->reg = ir_alloc_register(ir);
127
 	irs->reg = ir_alloc_register(ir);

+ 74 - 70
kprobe.c

5
 
5
 
6
 #include <linux/ptrace.h>
6
 #include <linux/ptrace.h>
7
 
7
 
8
+#include "arch.h"
8
 #include "func.h"
9
 #include "func.h"
10
+#include "ir.h"
9
 #include "node.h"
11
 #include "node.h"
10
 #include "ply.h"
12
 #include "ply.h"
11
 #include "sym.h"
13
 #include "sym.h"
12
 #include "type.h"
14
 #include "type.h"
13
 
15
 
14
 struct kprobe {
16
 struct kprobe {
17
+	int use_ctx:1;
18
+
19
+	struct irstate ctx_irs;
15
 };
20
 };
16
 
21
 
17
-/* static int kprobe_ir_prologue(prog_t *prog) */
18
-/* { */
19
-/* 	sym_t *ctx = sym_get(prog->locals, "ctx"); */
22
+/* ctx */
23
+
24
+static struct type t_pt_regsp = {
25
+	.ttype = T_POINTER,
26
+
27
+	.ptr.type = &t_pt_regs,
28
+};
20
 
29
 
21
-/* 	if (!ctx) */
22
-/* 		return 0; */
30
+static const struct func kprobe_ctx_func = {
31
+	.name = "ctx",
32
+
33
+	.type = &t_pt_regsp,
34
+	.static_ret = 1,
35
+};
23
 
36
 
24
-/* 	irs_alloc_reg(&ctx->irs, prog->ir); */
25
 
37
 
26
-/* 	/\* kernel sets r1 to the address of the context *\/ */
27
-/* 	ir_emit_insn(prog->ir, MOV(0, 0), ctx->irs.reg, BPF_REG_1); */
28
-/* 	return 0; */
29
-/* } */
38
+/* argN */
30
 
39
 
31
 static inline int is_arg(const char *name)
40
 static inline int is_arg(const char *name)
32
 {
41
 {
35
 		&& (name[3] >= '0' && name[3] <= '9');
44
 		&& (name[3] >= '0' && name[3] <= '9');
36
 }
45
 }
37
 
46
 
38
-/* static int kprobe_rewrite_arg(prog_t *prog, node_t *n) */
39
-/* { */
40
-/* 	const char *reg; */
41
-/* 	int arg = n->ident[3] - '0'; */
42
-/* 	node_t *new, *ctx; */
43
-
44
-/* 	reg = arch_register_argument(arg); */
45
-/* 	if (!reg) { */
46
-/* 		node_print(n, stderr); */
47
-/* 		fputs(": the location of this argument is unknown\n", stderr); */
48
-/* 		/\* TODO: add ABI mappings for specifying arguments */
49
-/* 		 * passed on the stack. *\/ */
50
-/* 		return -EINVAL; */
51
-/* 	} */
52
-
53
-/* 	ctx = node_ident("ctx"); */
54
-
55
-/* 	/\* argN => (*ctx).REG *\/ */
56
-/* 	new = node_vlist(node_keyword('.', 0), */
57
-/* 			 node_vlist(node_keyword('*', 0), */
58
-/* 				    ctx, */
59
-/* 				    NULL), */
60
-/* 			 node_string(reg), */
61
-/* 			 NULL); */
62
-
63
-/* 	ctx->type = type_ptr_of(&t_pt_regs); */
64
-/* 	new->type = n->type; */
65
-/* 	new->list->type = &t_void; */
66
-/* 	new->list->next->type = &t_pt_regs; */
67
-/* 	new->list->next->list->type = &t_void; */
68
-/* 	node_replace(n, new); */
69
-
70
-/* 	return sym_add(prog->locals, ctx->ident, ctx->type, &ctx->sym); */
71
-/* } */
72
-
73
-/* static int kprobe_rewrite_node(prog_t *prog, node_t *n) */
74
-/* { */
75
-/* 	if ((n->ntype == N_IDENT) && is_arg(n->ident)) */
76
-/* 		return kprobe_rewrite_arg(prog, n); */
77
-
78
-/* 	return 0; */
79
-/* } */
80
-
81
-/* static int kprobe_resolve(prog_t *prog, node_t *n) */
82
-/* { */
83
-/* 	type_t *t; */
84
-
85
-/* 	if (is_arg(n->ident)) */
86
-/* 		t = &t_ulong; */
87
-/* 	else if (!strcmp(n->ident, "ctx")) */
88
-/* 		t = type_ptr_of(&t_pt_regs); */
89
-/* 	else */
90
-/* 		return -ENOENT; */
91
-
92
-/* 	n->type = t; */
93
-/* 	return sym_add(prog->locals, n->ident, t, &n->sym); */
94
-/* } */
47
+static int kprobe_arg_rewrite(const struct func *func, struct node *n,
48
+			      struct prog *prog)
49
+{
50
+	struct node *new;
51
+	const char *reg;
52
+	int arg;
53
+
54
+	arg = n->ident.name[3] - '0';
55
+	reg = arch_register_argument(arg);
56
+	if (!reg) {
57
+		_e("%#N: the location of %N is unknown\n", n, n);
58
+
59
+		/* TODO: add ABI mappings for specifying arguments
60
+		 * passed on the stack. */
61
+		return -EINVAL;
62
+	}
63
+
64
+	/* argN => (*ctx).REG */
65
+	new = node_expr(".",
66
+			node_expr("*", node_ident("ctx"), NULL),
67
+			node_string((char *)reg),
68
+			NULL);
69
+
70
+	ast_fprint(stdout, n);
71
+	ast_fprint(stdout, new);
72
+
73
+	node_replace(n, new);
74
+	return 0;
75
+}
95
 
76
 
96
 static const struct func kprobe_arg_func = {
77
 static const struct func kprobe_arg_func = {
97
 	.name = "argN",
78
 	.name = "argN",
100
 	 * figure out the real type. */
81
 	 * figure out the real type. */
101
 	.type = &t_ulong,
82
 	.type = &t_ulong,
102
 	.static_ret = 1,
83
 	.static_ret = 1,
84
+
85
+	.rewrite = kprobe_arg_rewrite,
103
 };
86
 };
104
 
87
 
88
+
89
+/*  */
90
+
91
+static int kprobe_ir_pre(struct prog *prog)
92
+{
93
+	struct kprobe *kp = prog->provider_data;
94
+
95
+	if (!kp->use_ctx)
96
+		return 0;
97
+
98
+	irs_alloc_reg(&kp->ctx_irs, prog->ir);
99
+
100
+	/* kernel sets r1 to the address of the context */
101
+	ir_emit_insn(prog->ir, MOV(0, 0), kp->ctx_irs.reg, BPF_REG_1);
102
+	return 0;
103
+}
104
+
105
 static int kprobe_sym_alloc(struct prog *prog, struct node *n)
105
 static int kprobe_sym_alloc(struct prog *prog, struct node *n)
106
 {
106
 {
107
+	struct kprobe *kp = prog->provider_data;
107
 	const struct func *func = NULL;
108
 	const struct func *func = NULL;
108
 	int err;
109
 	int err;
109
 
110
 
111
 	case N_EXPR:
112
 	case N_EXPR:
112
 		break;
113
 		break;
113
 	case N_IDENT:
114
 	case N_IDENT:
114
-		if (is_arg(n->ident.name))
115
-			func = &kprobe_arg_func;
115
+		if (!is_arg(n->ident.name))
116
+			break;
117
+
118
+		func = &kprobe_arg_func;
119
+		kp->use_ctx = 1;
116
 		break;
120
 		break;
117
 	default:
121
 	default:
118
 		break;
122
 		break;
146
 struct provider kprobe = {
150
 struct provider kprobe = {
147
 	.name = "kprobe",
151
 	.name = "kprobe",
148
 
152
 
149
-	/* .ir_prologue = kprobe_ir_prologue, */
153
+	.ir_pre = kprobe_ir_pre,
150
 	/* .rewrite_node = kprobe_rewrite_node, */
154
 	/* .rewrite_node = kprobe_rewrite_node, */
151
 	/* .resolve = kprobe_resolve, */
155
 	/* .resolve = kprobe_resolve, */
152
 	.sym_alloc = kprobe_sym_alloc,
156
 	.sym_alloc = kprobe_sym_alloc,

+ 63 - 303
ply.c

5
 #include <string.h>
5
 #include <string.h>
6
 
6
 
7
 #include "func.h"
7
 #include "func.h"
8
+#include "ir.h"
8
 #include "node.h"
9
 #include "node.h"
9
 #include "ply.h"
10
 #include "ply.h"
10
 #include "sym.h"
11
 #include "sym.h"
100
 
101
 
101
 	prog->provider = provider_get("k");
102
 	prog->provider = provider_get("k");
102
 	prog->provider->probe(prog);
103
 	prog->provider->probe(prog);
103
-	/* prog->ir = ir_new(); */
104
+	prog->ir = ir_new();
104
 	ctx->progs[0] = prog;
105
 	ctx->progs[0] = prog;
105
 
106
 
106
 	/* PROBE1 */
107
 	/* PROBE1 */
132
 
133
 
133
 	prog->provider = provider_get("k");
134
 	prog->provider = provider_get("k");
134
 	prog->provider->probe(prog);
135
 	prog->provider->probe(prog);
135
-	/* prog->ir = ir_new(); */
136
+	prog->ir = ir_new();
136
 	ctx->progs[1] = prog;
137
 	ctx->progs[1] = prog;
137
 
138
 
138
 	return ctx;
139
 	return ctx;
167
 	return err;
168
 	return err;
168
 }
169
 }
169
 
170
 
170
-/* int infer_type_list(struct prog *prog, struct node *n) */
171
-/* { */
172
-/* 	type_t *t; */
173
 
171
 
174
-/* 	/\* list of lists (code block) => void *\/ */
175
-/* 	if (n->list->ntype == N_LIST) { */
176
-/* 		n->type = &t_void; */
177
-/* 		return 0; */
178
-/* 	} */
179
-
180
-/* 	t = n->list->type; */
181
-/* 	if (!t) */
182
-/* 		return 0; */
183
-
184
-/* 	switch (t->ttype) { */
185
-/* 	case T_FUNC: */
186
-/* 		n->type = t->t.func.type; */
187
-/* 		break; */
188
-/* 	default: */
189
-/* 		n->type = t; */
190
-/* 	} */
191
-/* 	return 0; */
192
-/* } */
193
-
194
-/* int infer_type_keyword(struct prog *prog, struct node *n) */
195
-/* { */
196
-/* 	struct node *dst, *src; */
197
-
198
-/* 	switch (n->keyword.class) { */
199
-/* 	case KW_ASSIGN: */
200
-/* 		dst = node_next(n); */
201
-/* 		src = node_next(dst); */
202
-/* 		assert(dst && src); */
203
-
204
-/* 		if (!src->type) */
205
-/* 			return 0; */
206
-
207
-/* 		/\* TODO: assignment is statement for now. do we need */
208
-/* 		 * c-style assignment expressions? e.g `a = b = 2;` *\/ */
209
-/* 		n->type = &t_void; */
210
-
211
-/* 		if (dst->type) */
212
-/* 			return 0; */
172
+int pass_type_infer(struct node *n, void *_prog)
173
+{
174
+	struct prog *prog = _prog;
213
 
175
 
214
-/* 		dst->type = src->type; */
176
+	if (n->sym->func->type_infer)
177
+		return n->sym->func->type_infer(n->sym->func, n);
215
 
178
 
216
-/* 		if (dst->ntype != N_IDENT) */
217
-/* 			return 0; */
179
+	/* TODO recurse as long as we're infering new types */
180
+	return 0;
181
+}
218
 
182
 
219
-/* 		return sym_add(dst->sym->st, dst->ident, dst->type, NULL); */
183
+int pass_rewrite(struct node *n, void *_prog)
184
+{
185
+	struct prog *prog = _prog;
220
 
186
 
221
-/* 	case KW_BINOP: */
222
-/* 		dst = node_next(n); */
223
-/* 		src = node_next(dst); */
224
-/* 		assert(dst && src); */
187
+	if (n->sym->func->rewrite)
188
+		return n->sym->func->rewrite(n->sym->func, n, prog);
225
 
189
 
226
-/* 		if (!(src->type && dst->type && type_equal(src->type, dst->type))) */
227
-/* 			return 0; */
190
+	return 0;
191
+}
228
 
192
 
229
-/* 		n->type = dst->type; */
230
-/* 		return 0; */
193
+int pass_ir_pre(struct node *n, void *_prog)
194
+{
195
+	struct prog *prog = _prog;
231
 
196
 
232
-/* 	default: */
233
-/* 		n->type = &t_void; */
234
-/* 		return 0; */
235
-/* 	} */
197
+	if (n->sym->func->ir_pre)
198
+		return n->sym->func->ir_pre(n->sym->func, n, prog);
236
 
199
 
237
-/* 	return -ENOSYS; */
238
-/* } */
200
+	return 0;
201
+}
239
 
202
 
240
-/* int infer_type_sym(struct prog *prog, struct node *n) */
241
-/* { */
242
-/* 	struct node *parent, *key; */
203
+int pass_ir_post(struct node *n, void *_prog)
204
+{
205
+	struct prog *prog = _prog;
243
 
206
 
244
-/* 	if (n->sym->type) { */
245
-/* 		/\* the symbol type could have been inferred in another */
246
-/* 		 * probe, in that case copy the type to this node. *\/ */
247
-/* 		if (!n->type) */
248
-/* 			n->type = n->sym->type; */
207
+	if (n->sym->func->ir_post)
208
+		return n->sym->func->ir_post(n->sym->func, n, prog);
249
 
209
 
250
-/* 		return 0; */
251
-/* 	} */
210
+	return 0;
211
+}
252
 
212
 
253
-/* 	parent = node_up(n); */
254
-/* 	key = node_next(n); */
213
+int run_ir(struct pass *pass, struct ctx *ctx)
214
+{
215
+	struct prog **progp;
216
+	int err;
255
 
217
 
256
-/* 	/\* match `somemap[somekey]` where the type of the entire */
257
-/* 	 * expression and the type of the key is known, since that */
258
-/* 	 * means the type of the map itself is also known. *\/ */
259
-/* 	if (parent && parent->type */
260
-/* 	    && (parent->list->ntype == N_KEYWORD) */
261
-/* 	    && (parent->list->keyword.class == KW_SUBSCRIPT) */
262
-/* 	    && key && key->type) { */
263
-/* 		n->type = type_map_of(key->type, parent->type); */
218
+	for (progp = ctx->progs; *progp; progp++) {
219
+		struct prog *prog = *progp;
264
 
220
 
265
-/* 		return sym_add(n->sym->st, n->ident, n->type, NULL); */
266
-/* 	} */
221
+		err = prog->provider->ir_pre ?
222
+			prog->provider->ir_pre(prog) : 0;
223
+		if (err)
224
+			return err;
267
 
225
 
268
-/* 	return 0; */
269
-/* } */
226
+		err = node_walk(prog->ast, pass_ir_pre, pass_ir_post, prog);
227
+		if (err)
228
+			return err;
270
 
229
 
271
-int pass_type_infer(struct node *n, void *_prog)
272
-{
273
-	struct prog *prog = _prog;
230
+		err = prog->provider->ir_post ?
231
+			prog->provider->ir_post(prog) : 0;
232
+		if (err)
233
+			return err;
274
 
234
 
275
-	if (n->sym->func->type_infer)
276
-		return n->sym->func->type_infer(n->sym->func, n);
235
+		ir_emit_insn(prog->ir, EXIT, 0, 0);
236
+	}
277
 
237
 
278
 	return 0;
238
 	return 0;
279
 }
239
 }
280
 
240
 
281
-/* int validate_func(struct node *n) */
282
-/* { */
283
-/* 	struct node *arg; */
284
-/* 	field_t *f; */
285
-/* 	int i; */
286
-
287
-/* 	for (arg = node_next(n), f = n->type->t.func.args, i = 1; */
288
-/* 	     arg && f && f->type; arg = node_next(arg), f++, i++) { */
289
-/* 		if (type_compatible(arg->type, f->type)) */
290
-/* 			continue; */
291
-
292
-/* 		node_print(n, stderr); */
293
-/* 		fprintf(stderr, ": incompatible type of argument %d (", i); */
294
-/* 		type_dump(arg->type, stderr); */
295
-/* 		fputs("), expected ", stderr); */
296
-/* 		type_dump(f->type, stderr); */
297
-/* 		fputs("\n", stderr); */
298
-/* 		return -EINVAL; */
299
-/* 	} */
300
-
301
-/* 	if (!arg && (!f || !f->type)) */
302
-/* 		return 0; */
303
-
304
-/* 	if (arg) { */
305
-/* 		node_print(n, stderr); */
306
-/* 		fprintf(stderr, ": too many arguments, expected %d", i); */
307
-/* 		return -EINVAL; */
308
-/* 	} */
309
-
310
-/* 	if (f->optional) */
311
-/* 		return 0; */
312
-
313
-/* 	node_print(n, stderr); */
314
-/* 	fputs(": too few arguments", stderr); */
315
-/* 	return -EINVAL;	 */
316
-/* } */
317
-
318
-/* int pass_validate_types(struct node *n, void *_prog) */
319
-/* { */
320
-/* 	struct prog *prog = _prog; */
321
-
322
-/* 	node_print(n, stdout); putchar('\n');  */
323
-/* 	if (!n->type) { */
324
-/* 		node_print(n, stderr); */
325
-/* 		fputs(": type unknown\n", stderr); */
326
-/* 		return -EINVAL; */
327
-/* 	} */
328
-
329
-/* 	if (n->ntype != N_LIST) */
330
-/* 		return 0; */
331
-
332
-/* 	if (n->list->ntype != N_IDENT) */
333
-/* 		return 0; */
334
-
335
-/* 	assert(n->list->type->ttype == T_FUNC); */
336
-/* 	return validate_func(n->list); */
337
-/* } */
338
-
339
-/* int validate_syms(struct prog *prog) */
340
-/* { */
341
-/* 	return 0; */
342
-/* } */
343
-
344
-/* int run_validate_types(struct pass *pass, struct ctx *ctx) */
345
-/* { */
346
-/* 	struct prog **prog; */
347
-/* 	int err; */
348
-
349
-/* 	for (prog = ctx->progs; *prog; prog++) { */
350
-/* 		/\* check syms first to give better error messages. */
351
-/* 		 * e.g. "i: type unknown", not "b-: type unknown" *\/ */
352
-/* 		err = validate_syms(*prog); */
353
-/* 		if (err) */
354
-/* 			return err; */
355
-
356
-/* 		err = node_walk((*prog)->ast, pass->pre, pass->post, *prog); */
357
-/* 		if (err) */
358
-/* 			return err; */
359
-/* 	} */
360
-
361
-/* 	return 0; */
362
-
363
-/* } */
364
-
365
-/* int rewrite_const_math(struct node *n) */
366
-/* { */
367
-/* 	int64_t result; */
368
-/* 	struct node *a, *b, *new; */
369
-/* 	int op; */
370
-
371
-/* 	/\* TODO: handle L/UL/ULL correctly *\/ */
372
-	
373
-/* 	op = n->list->keyword.op; */
374
-/* 	a = node_next(n->list); */
375
-/* 	b = node_next(a); */
376
-
377
-/* 	switch (op) { */
378
-/* 	case '*': result = a->num *  b->num; break; */
379
-/* 	case '/': result = a->num /  b->num; break; */
380
-/* 	case '%': result = a->num %  b->num; break; */
381
-/* 	case '+': result = a->num +  b->num; break; */
382
-/* 	case '-': result = a->num -  b->num; break; */
383
-/* 	case '<': result = a->num << b->num; break; */
384
-/* 	case '>': result = a->num >> b->num; break; */
385
-/* 	default: return 0; */
386
-/* 	} */
387
-
388
-/* 	new = node_num(result); */
389
-/* 	new->type = n->type; */
390
-/* 	return node_replace(n, new); */
391
-/* } */
392
-
393
-/* int pass_rewrite_ast(struct node *n, void *_prog) */
394
-/* { */
395
-/* 	struct prog *prog = _prog; */
396
-/* 	provider_t *global = provider_get(":"); */
397
-/* 	int err; */
398
-
399
-/* 	if (prog->provider->rewrite_node) { */
400
-/* 		err = prog->provider->rewrite_node(prog, n); */
401
-/* 		if (err) */
402
-/* 			return err; */
403
-/* 	} */
404
-
405
-/* 	if (global->rewrite_node) { */
406
-/* 		err = global->rewrite_node(prog, n); */
407
-/* 		if (err) */
408
-/* 			return err; */
409
-/* 	} */
410
-
411
-/* 	/\* pre-compute binops where both sides are constants *\/ */
412
-/* 	if ((n->ntype == N_LIST) */
413
-/* 	    && (n->list->ntype == N_KEYWORD) */
414
-/* 	    && (n->list->keyword.class == KW_BINOP) */
415
-/* 	    && (node_next(n->list)->ntype == N_NUM) */
416
-/* 	    && (node_next(node_next(n->list))->ntype == N_NUM)) */
417
-/* 		return rewrite_const_math(n); */
418
-
419
-/* 	return 0; */
420
-/* } */
421
-
422
-/* int generate_ir_ident(struct prog *prog, struct node *n) */
423
-/* { */
424
-
425
-/* 	switch (n->sym->type->ttype) { */
426
-/* 	case T_FUNC: */
427
-/* 		return n->sym->type->t.func.generate_ir(prog, n); */
428
-/* 	case T_MAP: */
429
-/* 		ir_emit_ldmap(prog->ir, BPF_REG_0, n->sym); */
430
-/* 		return 0; */
431
-/* 	default: */
432
-/* 		break; */
433
-/* 	} */
434
-
435
-/* 	return 0; */
436
-/* } */
437
-
438
-/* int pass_generate_ir(struct node *n, void *_prog) */
439
-/* { */
440
-/* 	struct prog *prog = _prog; */
441
-
442
-/* 	switch (n->ntype) { */
443
-/* 	case N_LIST: */
444
-/* 		return 0; */
445
-/* 	case N_IDENT: */
446
-/* 		return generate_ir_ident(prog, n); */
447
-
448
-/* 	default: */
449
-/* 		break; */
450
-/* 	} */
451
-/* 	return 0; */
452
-/* } */
453
-
454
-/* int run_generate_ir(struct pass *pass, struct ctx *ctx) */
455
-/* { */
456
-/* 	struct prog **progp; */
457
-/* 	int err; */
458
-
459
-/* 	for (progp = ctx->progs; *progp; progp++) { */
460
-/* 		struct prog *prog = *progp; */
461
-
462
-/* 		int return_label = ir_alloc_label(prog->ir); */
463
-
464
-/* 		err = prog->provider->ir_prologue ? */
465
-/* 			prog->provider->ir_prologue(prog) : 0; */
466
-/* 		if (err) */
467
-/* 			return err; */
468
-
469
-/* 		err = node_walk(prog->ast, NULL, pass_generate_ir, prog); */
470
-/* 		if (err) */
471
-/* 			return err; */
472
-
473
-/* 		err = prog->provider->ir_epilogue ? */
474
-/* 			prog->provider->ir_epilogue(prog) : 0; */
475
-/* 		if (err) */
476
-/* 			return err; */
477
-
478
-/* 		ir_emit_label(prog->ir, return_label); */
479
-/* 		ir_emit_insn(prog->ir, EXIT, 0, 0); */
480
-/* 	} */
481
-
482
-/* 	return 0; */
483
-/* } */
484
-
485
 int run_walk(struct pass *pass, struct ctx *ctx)
241
 int run_walk(struct pass *pass, struct ctx *ctx)
486
 {
242
 {
487
 	struct prog **prog;
243
 	struct prog **prog;
498
 
254
 
499
 struct pass passes[] = {
255
 struct pass passes[] = {
500
 	{ .run = run_walk, .post = pass_sym_alloc },
256
 	{ .run = run_walk, .post = pass_sym_alloc },
257
+	/* node->sym ok */
501
 	{ .run = run_walk, .post = pass_type_infer },
258
 	{ .run = run_walk, .post = pass_type_infer },
502
-	/* { .run = run_walk, .post = pass_infer_types }, */
503
-	/* { .run = run_walk, .post = pass_infer_types }, */
504
-	/* { .run = run_validate_types, .post = pass_validate_types }, */
505
-	/* { .run = run_walk, .post = pass_rewrite_ast }, */
506
-	/* { .run = run_generate_ir }, */
507
-
259
+	/* node->sym->type ok */
260
+	/* user input is accepted. we'll now start rewriting the ast,
261
+	 * so errors beyond this point are internal errors. */
262
+	{ .run = run_walk, .post = pass_rewrite },
263
+	{ .run = run_ir },
264
+	/* program flattened to vBPF instructions, now rewrite it to
265
+	 * fit into the actual hw/vm. */
266
+
267
+	/* BPF program ready */
508
 	{ NULL }
268
 	{ NULL }
509
 };
269
 };
510
 
270
 
526
 		ast_fprint(stdout, (*prog)->ast);
286
 		ast_fprint(stdout, (*prog)->ast);
527
 		printf("\n-- locals\n");
287
 		printf("\n-- locals\n");
528
 		symtab_dump((*prog)->locals, stdout);
288
 		symtab_dump((*prog)->locals, stdout);
529
-		/* printf("-- ir\n"); */
530
-		/* ir_dump((*prog)->ir, stdout); */
289
+		printf("-- ir\n");
290
+		ir_dump((*prog)->ir, stdout);
531
 	}
291
 	}
532
 
292
 
533
 	printf("\n\n-- globals\n");
293
 	printf("\n\n-- globals\n");

+ 4 - 3
ply.h

5
 
5
 
6
 struct node;
6
 struct node;
7
 struct symtab;
7
 struct symtab;
8
+struct ir;
8
 
9
 
9
 struct prog {
10
 struct prog {
10
 	const char *probe;
11
 	const char *probe;
19
 	struct provider *provider;
20
 	struct provider *provider;
20
 	void *provider_data;
21
 	void *provider_data;
21
 
22
 
22
-	/* ir_t *ir; */
23
+	struct ir *ir;
23
 };
24
 };
24
 
25
 
25
 struct ctx {
26
 struct ctx {
38
 	int (*sym_alloc)(struct prog *, struct node *);
39
 	int (*sym_alloc)(struct prog *, struct node *);
39
 	/* int (*resolve)(struct prog *, struct node *); */
40
 	/* int (*resolve)(struct prog *, struct node *); */
40
 	/* int (*rewrite_node)(struct prog *, struct node *); */
41
 	/* int (*rewrite_node)(struct prog *, struct node *); */
41
-	/* int (*ir_prologue)(struct prog *); */
42
-	/* int (*ir_epilogue)(struct prog *); */
42
+	int (*ir_pre)(struct prog *);
43
+	int (*ir_post)(struct prog *);
43
 };
44
 };
44
 
45
 
45
 void provider_register(struct provider *p);
46
 void provider_register(struct provider *p);

+ 4 - 3
sym.h

3
 
3
 
4
 #include <stdint.h>
4
 #include <stdint.h>
5
 
5
 
6
-struct symtab;
7
-
8
-struct type;
9
 struct func;
6
 struct func;
7
+struct node;
8
+struct type;
9
+
10
+struct symtab;
10
 
11
 
11
 struct sym {
12
 struct sym {
12
 	struct symtab *st;
13
 	struct symtab *st;