Browse Source

save before ast rework

Tobias Waldekranz.com 8 years ago
parent
commit
20fdbc28ac
11 changed files with 302 additions and 14 deletions
  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
 CFLAGS ?= -Wall -Wextra -Werror -Wno-unused -O0 -g
1
 CFLAGS ?= -Wall -Wextra -Werror -Wno-unused -O0 -g
2
 
2
 
3
 objs := $(patsubst %.c,%.o,$(wildcard *.c))
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
 ply: $(objs)
8
 ply: $(objs)

+ 25 - 1
global.c

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

+ 50 - 2
ir.c

6
 #include <linux/bpf.h>
6
 #include <linux/bpf.h>
7
 
7
 
8
 #include "ir.h"
8
 #include "ir.h"
9
+#include "sym.h"
9
 
10
 
10
 const uint16_t vreg_base = 0x8000;
11
 const uint16_t vreg_base = 0x8000;
11
 
12
 
212
 	case VI_INSN:
213
 	case VI_INSN:
213
 		__insn_dump(vi->insn.bpf, vi->insn.dst, vi->insn.src, fp);
214
 		__insn_dump(vi->insn.bpf, vi->insn.dst, vi->insn.src, fp);
214
 		return;
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
 	case VI_LABEL:
220
 	case VI_LABEL:
216
 		offset_dump(vi->label, fp);
221
 		offset_dump(vi->label, fp);
217
 		fputc(':', fp);
222
 		fputc(':', fp);
229
 	size_t i;
234
 	size_t i;
230
 
235
 
231
 	for (i = 0; i < ir->len; i++) {
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
 			fputc('\t', fp);
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
 		fputc('\n', fp);
274
 		fputc('\n', fp);
237
 	}
275
 	}
238
 }
276
 }
256
 	ir_emit(ir, &vi);
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
 void ir_emit_label  (ir_t *ir, int16_t label)
307
 void ir_emit_label  (ir_t *ir, int16_t label)
260
 {
308
 {
261
 	vinsn_t vi;
309
 	vinsn_t vi;

+ 46 - 0
ir.h

37
 #define LDXW(_dst, _off, _src)  INSN(BPF_LDX | BPF_SIZE(BPF_W)  | BPF_MEM, _dst, _src, _off, 0)
37
 #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)
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
 typedef enum vitype {
42
 typedef enum vitype {
41
 	VI_INSN,
43
 	VI_INSN,
44
+	VI_LDMAP,
42
 	VI_LABEL,
45
 	VI_LABEL,
43
 	VI_REG_GET,
46
 	VI_REG_GET,
44
 	VI_REG_PUT,
47
 	VI_REG_PUT,
56
 
59
 
57
 		int16_t label;
60
 		int16_t label;
58
 		uint16_t reg;
61
 		uint16_t reg;
62
+
63
+		struct {
64
+			uint16_t reg;
65
+			sym_t *sym;
66
+		} map;
59
 	};
67
 	};
60
 } vinsn_t;
68
 } vinsn_t;
61
 
69
 
75
 uint16_t ir_alloc_register(ir_t *ir);
83
 uint16_t ir_alloc_register(ir_t *ir);
76
 
84
 
77
 void ir_emit_insn   (ir_t *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src);
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
 void ir_emit_label  (ir_t *ir, int16_t label);
87
 void ir_emit_label  (ir_t *ir, int16_t label);
79
 void ir_emit_reg_get(ir_t *ir, uint16_t reg);
88
 void ir_emit_reg_get(ir_t *ir, uint16_t reg);
80
 void ir_emit_reg_put(ir_t *ir, uint16_t reg);
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
 ir_t *ir_new(void);
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
 #endif	/* _PLY_IR_H */
130
 #endif	/* _PLY_IR_H */

+ 2 - 3
kprobe.c

17
 	if (!ctx)
17
 	if (!ctx)
18
 		return 0;
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
 	/* kernel sets r1 to the address of the context */
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
 	return 0;
24
 	return 0;
26
 }
25
 }
27
 
26
 

+ 75 - 0
node.c

237
 	n->type = type_ptr_of(&t_char);
237
 	n->type = type_ptr_of(&t_char);
238
 	return n;
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
 #include <stdint.h>
4
 #include <stdint.h>
5
 #include <stdio.h>
5
 #include <stdio.h>
6
 
6
 
7
+#include "ir.h"
7
 #include "sym.h"
8
 #include "sym.h"
8
 #include "type.h"
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
 typedef struct node node_t;
40
 typedef struct node node_t;
11
 
41
 
12
 typedef enum kwclass {
42
 typedef enum kwclass {
49
 
79
 
50
 	type_t *type;
80
 	type_t *type;
51
 	sym_t *sym;
81
 	sym_t *sym;
82
+
83
+	irstate_t irs;
52
 };
84
 };
53
 
85
 
54
 /* debug */
86
 /* debug */

+ 62 - 5
ply.c

63
 	prog->globals = ctx->globals;
63
 	prog->globals = ctx->globals;
64
 
64
 
65
 	prog->probe = "k:SyS_read";
65
 	prog->probe = "k:SyS_read";
66
-	/* { t0 = time(); @reads[pid()] = quantize(arg2) } */
66
+	/* { @t[0] = time(); @reads[pid()] = quantize(arg2) } */
67
 	prog->ast =
67
 	prog->ast =
68
 		node_vlist(
68
 		node_vlist(
69
 			node_vlist(node_keyword('=', 0),
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
 				   node_list(node_ident("time")),
74
 				   node_list(node_ident("time")),
72
 				   NULL),
75
 				   NULL),
73
 			node_vlist(node_keyword('=', 0),
76
 			node_vlist(node_keyword('=', 0),
305
 {
308
 {
306
 	prog_t *prog = _prog;
309
 	prog_t *prog = _prog;
307
 
310
 
311
+	node_print(n, stdout); putchar('\n'); 
308
 	if (!n->type) {
312
 	if (!n->type) {
309
 		node_print(n, stderr);
313
 		node_print(n, stderr);
310
-		fputs(": is of unknown type\n", stderr);
314
+		fputs(": type unknown\n", stderr);
311
 		return -EINVAL;
315
 		return -EINVAL;
312
 	}
316
 	}
313
 
317
 
321
 	return validate_func(n->list);
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
 int rewrite_const_math(node_t *n)
354
 int rewrite_const_math(node_t *n)
325
 {
355
 {
326
 	int64_t result;
356
 	int64_t result;
327
 	node_t *a, *b, *new;
357
 	node_t *a, *b, *new;
328
 	int op;
358
 	int op;
329
 
359
 
360
+	/* TODO: handle L/UL/ULL correctly */
361
+	
330
 	op = n->list->keyword.op;
362
 	op = n->list->keyword.op;
331
 	a = node_next(n->list);
363
 	a = node_next(n->list);
332
 	b = node_next(a);
364
 	b = node_next(a);
376
 	return 0;
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
 int pass_generate_ir(node_t *n, void *_prog)
427
 int pass_generate_ir(node_t *n, void *_prog)
380
 {
428
 {
381
 	prog_t *prog = _prog;
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
 	return 0;
440
 	return 0;
384
 }
441
 }
385
 
442
 
398
 		if (err)
455
 		if (err)
399
 			return err;
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
 		if (err)
459
 		if (err)
403
 			return err;
460
 			return err;
404
 
461
 
433
 	{ .run = run_walk, .post = pass_infer_types },
490
 	{ .run = run_walk, .post = pass_infer_types },
434
 	{ .run = run_walk, .post = pass_infer_types },
491
 	{ .run = run_walk, .post = pass_infer_types },
435
 	{ .run = run_walk, .post = pass_infer_types },
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
 	{ .run = run_walk, .post = pass_rewrite_ast },
494
 	{ .run = run_walk, .post = pass_rewrite_ast },
438
 	{ .run = run_generate_ir },
495
 	{ .run = run_generate_ir },
439
 
496
 

+ 2 - 1
sym.h

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

+ 1 - 0
type.c

293
 		break;
293
 		break;
294
 	case T_FUNC:
294
 	case T_FUNC:
295
 		t->size = t->t.func.type->size;
295
 		t->size = t->t.func.type->size;
296
+		assert(t->t.func.generate_ir);
296
 		break;
297
 		break;
297
 	case T_SCALAR:
298
 	case T_SCALAR:
298
 		break;
299
 		break;

+ 5 - 0
type.h

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