Kaynağa Gözat

save before ast rework

Tobias Waldekranz.com 8 yıl önce
ebeveyn
işleme
20fdbc28ac
11 değiştirilmiş dosya ile 302 ekleme ve 14 silme
  1. 2 2
      Makefile
  2. 25 1
      global.c
  3. 50 2
      ir.c
  4. 46 0
      ir.h
  5. 2 3
      kprobe.c
  6. 75 0
      node.c
  7. 32 0
      node.h
  8. 62 5
      ply.c
  9. 2 1
      sym.h
  10. 1 0
      type.c
  11. 5 0
      type.h

+ 2 - 2
Makefile

@@ -1,8 +1,8 @@
1 1
 CFLAGS ?= -Wall -Wextra -Werror -Wno-unused -O0 -g
2 2
 
3 3
 objs := $(patsubst %.c,%.o,$(wildcard *.c))
4
-headers := $(wildcard *.c)
4
+deps := $(wildcard *.c) $(wildcard *.h)
5 5
 
6
-$(objs): $(headers)
6
+$(objs): $(deps)
7 7
 
8 8
 ply: $(objs)

+ 25 - 1
global.c

@@ -5,6 +5,12 @@
5 5
 
6 6
 /* pid */
7 7
 
8
+int pid_generate_ir(prog_t *prog, node_t *node)
9
+{
10
+	/* TODO */
11
+	return 0;
12
+}
13
+
8 14
 type_t t_pid_t = {
9 15
 	.ttype = T_TYPEDEF,
10 16
 
@@ -21,6 +27,7 @@ type_t t_pid_func = {
21 27
 		.name = "pid",
22 28
 		.type = &t_pid_t,
23 29
 		.args = NULL,
30
+		.generate_ir = pid_generate_ir,
24 31
 	},
25 32
 };
26 33
 
@@ -29,6 +36,12 @@ type_t *ts_pid[] = { &t_pid_t, &t_pid_func, NULL };
29 36
 
30 37
 /* quantize */
31 38
 
39
+int quantize_generate_ir(prog_t *prog, node_t *node)
40
+{
41
+	/* TODO */
42
+	return 0;
43
+}
44
+
32 45
 type_t t_u64_64 = {
33 46
 	.ttype = T_ARRAY,
34 47
 	.t.array = {
@@ -58,6 +71,7 @@ type_t t_quantize_func = {
58 71
 		.name = "quantize",
59 72
 		.type = &t_quantize_t,
60 73
 		.args = f_quantize_args,
74
+		.generate_ir = quantize_generate_ir,
61 75
 	},
62 76
 };
63 77
 
@@ -66,12 +80,21 @@ type_t *ts_quantize[] = { &t_u64_64, &t_quantize_t, &t_quantize_func, NULL };
66 80
 
67 81
 /* time */
68 82
 
83
+int time_generate_ir(prog_t *prog, node_t *node)
84
+{
85
+	ir_emit_call(prog->ir, BPF_FUNC_ktime_get_ns);
86
+
87
+	irs_alloc_reg(&node->irs, prog->ir);
88
+	ir_emit_insn(prog->ir, MOV(0, 0), node->irs.reg, BPF_REG_0);
89
+	return 0;
90
+}
91
+
69 92
 type_t t_time_t = {
70 93
 	.ttype = T_TYPEDEF,
71 94
 
72 95
 	.t.tdef = {
73 96
 		.name = "__ply_time_t",
74
-		.type = &t_u32,
97
+		.type = &t_s64,
75 98
 	},
76 99
 };
77 100
 
@@ -82,6 +105,7 @@ type_t t_time_func = {
82 105
 		.name = "time",
83 106
 		.type = &t_time_t,
84 107
 		.args = NULL,
108
+		.generate_ir = time_generate_ir,
85 109
 	},
86 110
 };
87 111
 

+ 50 - 2
ir.c

@@ -6,6 +6,7 @@
6 6
 #include <linux/bpf.h>
7 7
 
8 8
 #include "ir.h"
9
+#include "sym.h"
9 10
 
10 11
 const uint16_t vreg_base = 0x8000;
11 12
 
@@ -212,6 +213,10 @@ void vinsn_dump(vinsn_t *vi, FILE *fp)
212 213
 	case VI_INSN:
213 214
 		__insn_dump(vi->insn.bpf, vi->insn.dst, vi->insn.src, fp);
214 215
 		return;
216
+	case VI_LDMAP:
217
+		fputs("ldmap\t", fp); reg_dump(vi->map.reg, 0, fp);
218
+		fprintf(fp, ", %s", vi->map.sym->name);
219
+		return;
215 220
 	case VI_LABEL:
216 221
 		offset_dump(vi->label, fp);
217 222
 		fputc(':', fp);
@@ -229,10 +234,43 @@ void ir_dump(ir_t *ir, FILE *fp)
229 234
 	size_t i;
230 235
 
231 236
 	for (i = 0; i < ir->len; i++) {
232
-		if (ir->vi[i].vitype == VI_INSN)
237
+		vinsn_t *vi = &ir->vi[i];
238
+
239
+		switch (vi->vitype) {
240
+		case VI_INSN:
241
+		case VI_LDMAP:
233 242
 			fputc('\t', fp);
243
+			break;
244
+		case VI_REG_GET:
245
+		case VI_REG_PUT:
246
+			fputs("\e[2m", fp);
247
+		case VI_LABEL:
248
+		default:
249
+			break;
250
+		}
251
+
252
+		vinsn_dump(vi, fp);
253
+
254
+		/* print multiple gets/puts on one line */
255
+		switch (vi->vitype) {
256
+		case VI_REG_GET:
257
+			for (; (vi + 1)->vitype == VI_REG_GET; vi++, i++) {
258
+				fputs(", ", fp);
259
+				reg_dump((vi + 1)->reg, 0, fp);
260
+			}
261
+			fputs("\e[0m", fp);
262
+			break;
263
+		case VI_REG_PUT:
264
+			for (; (vi + 1)->vitype == VI_REG_PUT; vi++, i++) {
265
+				fputs(", ", fp);
266
+				reg_dump((vi + 1)->reg, 0, fp);
267
+			}
268
+			fputs("\e[0m", fp);
269
+			break;
270
+		default:
271
+			break;
272
+		}
234 273
 
235
-		vinsn_dump(&ir->vi[i], fp);
236 274
 		fputc('\n', fp);
237 275
 	}
238 276
 }
@@ -256,6 +294,16 @@ void ir_emit_insn(ir_t *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src)
256 294
 	ir_emit(ir, &vi);
257 295
 }
258 296
 
297
+void ir_emit_ldmap(ir_t *ir, uint16_t dst, sym_t *map)
298
+{
299
+	vinsn_t vi;
300
+
301
+	vi.vitype = VI_LDMAP;
302
+	vi.map.reg = dst;
303
+	vi.map.sym = map;
304
+	ir_emit(ir, &vi);
305
+}
306
+
259 307
 void ir_emit_label  (ir_t *ir, int16_t label)
260 308
 {
261 309
 	vinsn_t vi;

+ 46 - 0
ir.h

@@ -37,8 +37,11 @@
37 37
 #define LDXW(_dst, _off, _src)  INSN(BPF_LDX | BPF_SIZE(BPF_W)  | BPF_MEM, _dst, _src, _off, 0)
38 38
 #define LDXDW(_dst, _off, _src) INSN(BPF_LDX | BPF_SIZE(BPF_DW) | BPF_MEM, _dst, _src, _off, 0)
39 39
 
40
+typedef struct sym sym_t;
41
+
40 42
 typedef enum vitype {
41 43
 	VI_INSN,
44
+	VI_LDMAP,
42 45
 	VI_LABEL,
43 46
 	VI_REG_GET,
44 47
 	VI_REG_PUT,
@@ -56,6 +59,11 @@ typedef struct vinsn {
56 59
 
57 60
 		int16_t label;
58 61
 		uint16_t reg;
62
+
63
+		struct {
64
+			uint16_t reg;
65
+			sym_t *sym;
66
+		} map;
59 67
 	};
60 68
 } vinsn_t;
61 69
 
@@ -75,10 +83,48 @@ int16_t  ir_alloc_label   (ir_t *ir);
75 83
 uint16_t ir_alloc_register(ir_t *ir);
76 84
 
77 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);
78 87
 void ir_emit_label  (ir_t *ir, int16_t label);
79 88
 void ir_emit_reg_get(ir_t *ir, uint16_t reg);
80 89
 void ir_emit_reg_put(ir_t *ir, uint16_t reg);
81 90
 
91
+static inline void ir_emit_call(ir_t *ir, enum bpf_func_id func)
92
+{
93
+	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_2);
96
+	ir_emit_reg_get(ir, BPF_REG_3);
97
+	ir_emit_reg_get(ir, BPF_REG_4);
98
+	ir_emit_reg_get(ir, BPF_REG_5);
99
+	ir_emit_insn(ir, CALL(func), 0, 0);
100
+	ir_emit_reg_put(ir, BPF_REG_5);
101
+	ir_emit_reg_put(ir, BPF_REG_4);
102
+	ir_emit_reg_put(ir, BPF_REG_3);
103
+	ir_emit_reg_put(ir, BPF_REG_2);
104
+	ir_emit_reg_put(ir, BPF_REG_1);
105
+	ir_emit_reg_put(ir, BPF_REG_0);
106
+}
107
+
82 108
 ir_t *ir_new(void);
83 109
 
110
+typedef enum irloc {
111
+	LOC_IMM   = (1 << 0),
112
+	LOC_REG   = (1 << 1),
113
+	LOC_STACK = (1 << 2),
114
+} irloc_t;
115
+
116
+typedef struct irstate {
117
+	int loc;
118
+
119
+	uint16_t reg;
120
+	int16_t stack;
121
+} irstate_t;
122
+
123
+static inline void irs_alloc_reg(irstate_t *irs, ir_t *ir)
124
+{
125
+	irs->loc = LOC_REG;
126
+	irs->reg = ir_alloc_register(ir);
127
+	ir_emit_reg_get(ir, irs->reg);
128
+}
129
+
84 130
 #endif	/* _PLY_IR_H */

+ 2 - 3
kprobe.c

@@ -17,11 +17,10 @@ static int kprobe_ir_prologue(prog_t *prog)
17 17
 	if (!ctx)
18 18
 		return 0;
19 19
 
20
-	ctx->reg = ir_alloc_register(prog->ir);
21
-	ir_emit_reg_get(prog->ir, ctx->reg);
20
+	irs_alloc_reg(&ctx->irs, prog->ir);
22 21
 
23 22
 	/* kernel sets r1 to the address of the context */
24
-	ir_emit_insn(prog->ir, MOV(0, 0), ctx->reg, BPF_REG_1);
23
+	ir_emit_insn(prog->ir, MOV(0, 0), ctx->irs.reg, BPF_REG_1);
25 24
 	return 0;
26 25
 }
27 26
 

+ 75 - 0
node.c

@@ -237,3 +237,78 @@ node_t *node_string(const char *string)
237 237
 	n->type = type_ptr_of(&t_char);
238 238
 	return n;
239 239
 }
240
+
241
+/* static struct node *node_new(enum ntype ntype) */
242
+/* { */
243
+/* 	struct node *n; */
244
+
245
+/* 	n = calloc(1, sizeof(*n)); */
246
+/* 	assert(n); */
247
+
248
+/* 	n->ntype = N_IDENT; */
249
+/* 	n->ident.name = name; */
250
+/* 	return n; */
251
+/* } */
252
+
253
+/* struct node *node_string(char *data) */
254
+/* { */
255
+/* 	struct node *n = node_new(N_STRING); */
256
+
257
+/* 	n->string.data = data; */
258
+/* 	return n; */
259
+/* } */
260
+
261
+/* struct node *node_num(int64_t num) */
262
+/* { */
263
+/* 	struct node *n = node_new(N_NUM); */
264
+
265
+/* 	n->num.num = num; */
266
+/* 	return n; */
267
+/* } */
268
+
269
+/* struct node *node_ident(char *name) */
270
+/* { */
271
+/* 	struct node *n = node_new(N_IDENT); */
272
+
273
+/* 	n->ident.name = name; */
274
+/* 	return n; */
275
+/* } */
276
+
277
+/* struct node *node_append(struct node *n, struct node *arg) */
278
+/* { */
279
+/* 	struct node *last; */
280
+/* 	assert(n->ntype == N_EXPR); */
281
+
282
+/* 	arg->up = n; */
283
+
284
+/* 	if (!n->expr.args) { */
285
+/* 		n->expr.args = arg; */
286
+/* 		return n; */
287
+/* 	} */
288
+
289
+/* 	for (last = n->expr.args; last->next; last = last->next); */
290
+
291
+/* 	last->next = arg; */
292
+/* 	arg->prev = last; */
293
+/* 	return n; */
294
+/* } */
295
+
296
+/* struct node *node_expr(char *func, ...) */
297
+/* { */
298
+/*         va_list ap; */
299
+/* 	struct node *n, *arg; */
300
+
301
+/* 	n = node_new(N_EXPR); */
302
+
303
+/* 	n->expr.func = func; */
304
+
305
+/*         va_start(ap, func); */
306
+
307
+/*         while ((arg = va_arg(ap, struct node *))) */
308
+/* 		append(n, arg); */
309
+
310
+/*         va_end(ap); */
311
+
312
+/* 	return n; */
313
+	
314
+/* } */

+ 32 - 0
node.h

@@ -4,9 +4,39 @@
4 4
 #include <stdint.h>
5 5
 #include <stdio.h>
6 6
 
7
+#include "ir.h"
7 8
 #include "sym.h"
8 9
 #include "type.h"
9 10
 
11
+/* enum ntype { */
12
+/* 	N_EXPR, */
13
+/* 	N_IDENT, */
14
+/* 	N_NUM, */
15
+/* 	N_STRING, */
16
+/* }; */
17
+
18
+/* struct node { */
19
+/* 	struct node *next, *prev, *up; */
20
+
21
+/* 	enum ntype ntype; */
22
+
23
+/* 	union { */
24
+/* 		struct { */
25
+/* 			char *func; */
26
+/* 			struct node *args; */
27
+/* 		} expr; */
28
+/* 		struct { */
29
+/* 			char *name; */
30
+/* 		} ident; */
31
+/* 		struct { */
32
+/* 			int64_t num; */
33
+/* 		} num; */
34
+/* 		struct { */
35
+/* 			char *data; */
36
+/* 		} string; */
37
+/* 	}; */
38
+/* }; */
39
+	
10 40
 typedef struct node node_t;
11 41
 
12 42
 typedef enum kwclass {
@@ -49,6 +79,8 @@ struct node {
49 79
 
50 80
 	type_t *type;
51 81
 	sym_t *sym;
82
+
83
+	irstate_t irs;
52 84
 };
53 85
 
54 86
 /* debug */

+ 62 - 5
ply.c

@@ -63,11 +63,14 @@ ctx_t *ctx_get(void)
63 63
 	prog->globals = ctx->globals;
64 64
 
65 65
 	prog->probe = "k:SyS_read";
66
-	/* { t0 = time(); @reads[pid()] = quantize(arg2) } */
66
+	/* { @t[0] = time(); @reads[pid()] = quantize(arg2) } */
67 67
 	prog->ast =
68 68
 		node_vlist(
69 69
 			node_vlist(node_keyword('=', 0),
70
-				   node_ident("t0"),
70
+				   node_vlist(node_keyword('[', 0),
71
+					      node_ident("@t"),
72
+					      node_num(0),
73
+					      NULL),
71 74
 				   node_list(node_ident("time")),
72 75
 				   NULL),
73 76
 			node_vlist(node_keyword('=', 0),
@@ -305,9 +308,10 @@ int pass_validate_types(node_t *n, void *_prog)
305 308
 {
306 309
 	prog_t *prog = _prog;
307 310
 
311
+	node_print(n, stdout); putchar('\n'); 
308 312
 	if (!n->type) {
309 313
 		node_print(n, stderr);
310
-		fputs(": is of unknown type\n", stderr);
314
+		fputs(": type unknown\n", stderr);
311 315
 		return -EINVAL;
312 316
 	}
313 317
 
@@ -321,12 +325,40 @@ int pass_validate_types(node_t *n, void *_prog)
321 325
 	return validate_func(n->list);
322 326
 }
323 327
 
328
+int validate_syms(prog_t *prog)
329
+{
330
+	return 0;
331
+}
332
+
333
+int run_validate_types(pass_t *pass, ctx_t *ctx)
334
+{
335
+	prog_t **prog;
336
+	int err;
337
+
338
+	for (prog = ctx->progs; *prog; prog++) {
339
+		/* check syms first to give better error messages.
340
+		 * e.g. "i: type unknown", not "b-: type unknown" */
341
+		err = validate_syms(*prog);
342
+		if (err)
343
+			return err;
344
+
345
+		err = node_walk((*prog)->ast, pass->pre, pass->post, *prog);
346
+		if (err)
347
+			return err;
348
+	}
349
+
350
+	return 0;
351
+
352
+}
353
+
324 354
 int rewrite_const_math(node_t *n)
325 355
 {
326 356
 	int64_t result;
327 357
 	node_t *a, *b, *new;
328 358
 	int op;
329 359
 
360
+	/* TODO: handle L/UL/ULL correctly */
361
+	
330 362
 	op = n->list->keyword.op;
331 363
 	a = node_next(n->list);
332 364
 	b = node_next(a);
@@ -376,10 +408,35 @@ int pass_rewrite_ast(node_t *n, void *_prog)
376 408
 	return 0;
377 409
 }
378 410
 
411
+int generate_ir_ident(prog_t *prog, node_t *n)
412
+{
413
+
414
+	switch (n->sym->type->ttype) {
415
+	case T_FUNC:
416
+		return n->sym->type->t.func.generate_ir(prog, n);
417
+	case T_MAP:
418
+		ir_emit_ldmap(prog->ir, BPF_REG_0, n->sym);
419
+		return 0;
420
+	default:
421
+		break;
422
+	}
423
+
424
+	return 0;
425
+}
426
+
379 427
 int pass_generate_ir(node_t *n, void *_prog)
380 428
 {
381 429
 	prog_t *prog = _prog;
382 430
 
431
+	switch (n->ntype) {
432
+	case N_LIST:
433
+		return 0;
434
+	case N_IDENT:
435
+		return generate_ir_ident(prog, n);
436
+
437
+	default:
438
+		break;
439
+	}
383 440
 	return 0;
384 441
 }
385 442
 
@@ -398,7 +455,7 @@ int run_generate_ir(pass_t *pass, ctx_t *ctx)
398 455
 		if (err)
399 456
 			return err;
400 457
 
401
-		err = node_walk(prog->ast, pass->pre, pass->post, prog);
458
+		err = node_walk(prog->ast, NULL, pass_generate_ir, prog);
402 459
 		if (err)
403 460
 			return err;
404 461
 
@@ -433,7 +490,7 @@ pass_t passes[] = {
433 490
 	{ .run = run_walk, .post = pass_infer_types },
434 491
 	{ .run = run_walk, .post = pass_infer_types },
435 492
 	{ .run = run_walk, .post = pass_infer_types },
436
-	{ .run = run_walk, .post = pass_validate_types },
493
+	{ .run = run_validate_types, .post = pass_validate_types },
437 494
 	{ .run = run_walk, .post = pass_rewrite_ast },
438 495
 	{ .run = run_generate_ir },
439 496
 

+ 2 - 1
sym.h

@@ -3,6 +3,7 @@
3 3
 
4 4
 #include <stdint.h>
5 5
 
6
+#include "ir.h"
6 7
 #include "type.h"
7 8
 
8 9
 typedef struct symtab symtab_t;
@@ -12,7 +13,7 @@ typedef struct sym {
12 13
 	const char *name;
13 14
 	type_t *type;
14 15
 
15
-	uint16_t reg;
16
+	irstate_t irs;
16 17
 } sym_t;
17 18
 
18 19
 struct symtab {

+ 1 - 0
type.c

@@ -293,6 +293,7 @@ void type_size_set(type_t *t)
293 293
 		break;
294 294
 	case T_FUNC:
295 295
 		t->size = t->t.func.type->size;
296
+		assert(t->t.func.generate_ir);
296 297
 		break;
297 298
 	case T_SCALAR:
298 299
 		break;

+ 5 - 0
type.h

@@ -4,6 +4,9 @@
4 4
 #include <stddef.h>
5 5
 #include <stdio.h>
6 6
 
7
+typedef struct prog prog_t;
8
+typedef struct node node_t;
9
+
7 10
 typedef struct type type_t;
8 11
 
9 12
 struct t_tdef {
@@ -51,6 +54,8 @@ struct t_func {
51 54
 	type_t *type;
52 55
 
53 56
 	field_t *args;
57
+
58
+	int (*generate_ir)(prog_t *prog, node_t *n);
54 59
 };
55 60
 
56 61
 typedef enum ttype {