Tobias Waldekranz.com преди 8 години
родител
ревизия
7d0344b16d
променени са 10 файла, в които са добавени 251 реда и са изтрити 62 реда
  1. 130 21
      global.c
  2. 90 5
      ir.c
  3. 7 16
      ir.h
  4. 1 1
      kprobe.c
  5. 2 9
      node.c
  6. 1 2
      node.h
  7. 5 5
      ply.c
  8. 10 0
      type.c
  9. 2 0
      type.h
  10. 3 3
      utils.c

+ 130 - 21
global.c

@@ -14,6 +14,86 @@
14 14
 
15 15
 /* . */
16 16
 
17
+static int global_dot_ir_pre(const struct func *func, struct node *n,
18
+				struct prog *prog)
19
+{
20
+	struct node *sou = n->expr.args;
21
+
22
+	if (node_is(sou, ":deref")) {
23
+		/* (*ptr).member, if *ptr is not already loaded let it
24
+		 * know that we're only interested in one member */
25
+		sou->sym->irs.hint.dot = 1;
26
+
27
+		/* this also means we need to put ourselves on the
28
+		 * stack since data will be loaded via probe_read */
29
+		n->sym->irs.hint.stack = 1;
30
+	}
31
+	return 0;
32
+}
33
+
34
+static int global_dot_ir_post(const struct func *func, struct node *n,
35
+				struct prog *prog)
36
+{
37
+	struct node *sou, *member;
38
+	struct irstate *dst;
39
+	ssize_t offset;
40
+
41
+	sou = n->expr.args;
42
+	member = sou->next;
43
+	dst = &n->sym->irs;
44
+	
45
+	ir_init_sym(prog->ir, n->sym);
46
+
47
+	offset = type_offsetof(type_base(sou->sym->type), member->string.data);
48
+	assert(offset >= 0);
49
+
50
+	if (!sou->sym->irs.loc) {
51
+		/* sou is a :deref which wasn't loaded by child, just
52
+		 * read the member we're interested in. */
53
+		struct node *ptr = sou->expr.args;
54
+
55
+		ir_emit_sym_to_reg(prog->ir, BPF_REG_3, ptr->sym);
56
+		ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, 0, offset), BPF_REG_3, 0);
57
+		goto probe_read;
58
+	}
59
+
60
+	offset += sou->sym->irs.stack;
61
+
62
+	if (dst->loc == LOC_REG) {
63
+		switch (dst->size) {
64
+		case 1:
65
+			ir_emit_insn(prog->ir, LDXB(0, offset, 0),
66
+				     dst->reg, BPF_REG_BP);
67
+			break;
68
+		case 2:
69
+			ir_emit_insn(prog->ir, LDXH(0, offset, 0),
70
+				     dst->reg, BPF_REG_BP);
71
+			break;
72
+		case 4:
73
+			ir_emit_insn(prog->ir, LDXW(0, offset, 0),
74
+				     dst->reg, BPF_REG_BP);
75
+			break;
76
+		case 8:
77
+			ir_emit_insn(prog->ir, LDXDW(0, offset, 0),
78
+				     dst->reg, BPF_REG_BP);
79
+			break;
80
+		default:
81
+			assert(0);
82
+		}
83
+
84
+		return 0;
85
+	}
86
+
87
+	ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, 0, offset), BPF_REG_3, 0);
88
+probe_read:
89
+	ir_emit_insn(prog->ir, MOV_IMM(0, (int32_t)dst->size), BPF_REG_2, 0);
90
+	ir_emit_insn(prog->ir, MOV(0, 0), BPF_REG_1, BPF_REG_BP);
91
+	ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, 0, dst->stack), BPF_REG_1, 0);
92
+	ir_emit_insn(prog->ir, CALL(BPF_FUNC_probe_read), 0, 0);
93
+	/* TODO if (r0) exit(r0); */
94
+	return 0;
95
+}
96
+
17 97
 static int global_dot_type_infer(const struct func *func, struct node *n)
18 98
 {
19 99
 	struct node *sou, *member;
@@ -37,18 +117,16 @@ static int global_dot_type_infer(const struct func *func, struct node *n)
37 117
 		return -EINVAL;
38 118
 	}
39 119
 
40
-	tfields_foreach(f, t->sou.fields) {
41
-		if (!strcmp(f->name, member->string.data)) {
42
-			/* given `sou.member` where sou is a
43
-			 * struct/union, infer that the expression's
44
-			 * type is equal to member's type. */
45
-			n->sym->type = f->type;
46
-			return 0;
47
-		}
120
+	f = tfields_get(t->sou.fields, member->string.data);
121
+	if (!f) {
122
+		_e("%#N: type '%T' has no member named %N.\n", n, t, member);
123
+		return -EINVAL;
48 124
 	}
49 125
 
50
-	_e("%#N: type '%T' has no member named %N.\n", n, t, member);
51
-	return -EINVAL;
126
+	/* given `sou.member` where sou is a struct/union, infer that
127
+	 * the expression's type is equal to member's type. */
128
+	n->sym->type = f->type;
129
+	return 0;
52 130
 }
53 131
 
54 132
 
@@ -69,20 +147,19 @@ static int global_deref_ir_post(const struct func *func, struct node *n,
69 147
 		 * from our argument */
70 148
 		return 0;
71 149
 
72
-	if (dst->loc)
73
-		return 0;
150
+	ir_init_sym(prog->ir, n->sym);
74 151
 
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);
152
+	if (dst->hint.lval)
153
+		/* *ptr = val, whatever is in our storage now it will
154
+                    be overwritten, so skip the load. */
155
+		return 0;
80 156
 
81 157
 	ir_emit_insn(prog->ir, MOV(0, 0), BPF_REG_1, BPF_REG_BP);
82 158
 	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);
159
+	ir_emit_insn(prog->ir, MOV_IMM(0, (int32_t)dst->size), BPF_REG_2, 0);
160
+	ir_emit_sym_to_reg(prog->ir, BPF_REG_3, ptr->sym);
85 161
 	ir_emit_insn(prog->ir, CALL(BPF_FUNC_probe_read), 0, 0);
162
+	/* TODO if (r0) exit(r0); */
86 163
 	return 0;
87 164
 }
88 165
 
@@ -208,7 +285,7 @@ static int global_assign_type_infer(const struct func *func, struct node *n)
208 285
 		/* TODO do we need assignment expressions? */
209 286
 		n->sym->type = &t_void;
210 287
 		
211
-		if (node_is_map(lval))
288
+		if (node_is(lval, "{}"))
212 289
 			return global_assign_type_infer_map(lval);
213 290
 
214 291
 		return 0;
@@ -229,7 +306,7 @@ static int global_assign_static_validate(const struct func *func, struct node *n
229 306
 
230 307
 	lval = n->expr.args;
231 308
 
232
-	if (node_is_map(lval) || (lval->ntype == N_IDENT))
309
+	if (node_is(lval, "{}") || (lval->ntype == N_IDENT))
233 310
 		return 0;
234 311
 
235 312
 	_e("%#N: can't assign a value to %N.\n", n, lval);
@@ -285,6 +362,19 @@ static int global_quantize_type_infer(const struct func *func, struct node *n)
285 362
 
286 363
 /* pid */
287 364
 
365
+static int global_pid_ir_post(const struct func *func, struct node *n,
366
+				struct prog *prog)
367
+{
368
+	struct node *ptr = n->expr.args;
369
+
370
+	ir_init_sym(prog->ir, n->sym);
371
+
372
+	ir_emit_insn(prog->ir, CALL(BPF_FUNC_get_current_pid_tgid), 0, 0);
373
+	ir_emit_insn(prog->ir, ALU64_IMM(BPF_RSH, 0, 32), BPF_REG_0, 0);
374
+	ir_emit_reg_to_sym(prog->ir, n->sym, BPF_REG_0);
375
+	return 0;
376
+}
377
+
288 378
 struct type t_pid = {
289 379
 	.ttype = T_TYPEDEF,
290 380
 
@@ -299,6 +389,18 @@ struct type t_pid_func = {
299 389
 
300 390
 /* time */
301 391
 
392
+static int global_time_ir_post(const struct func *func, struct node *n,
393
+			       struct prog *prog)
394
+{
395
+	struct node *ptr = n->expr.args;
396
+
397
+	ir_init_sym(prog->ir, n->sym);
398
+
399
+	ir_emit_insn(prog->ir, CALL(BPF_FUNC_ktime_get_ns), 0, 0);
400
+	ir_emit_reg_to_sym(prog->ir, n->sym, BPF_REG_0);
401
+	return 0;
402
+}
403
+
302 404
 struct type t_time = {
303 405
 	.ttype = T_TYPEDEF,	/* TODO: should be a T_FUNC with a static
304 406
 				 * signature */
@@ -379,6 +481,9 @@ static const struct func global_funcs[] = {
379 481
 		.name = ".",
380 482
 		.type = &t_dot_func,
381 483
 		.type_infer = global_dot_type_infer,
484
+
485
+		.ir_pre  = global_dot_ir_pre,
486
+		.ir_post = global_dot_ir_post,
382 487
 	},
383 488
 	{
384 489
 		.name = ":deref",
@@ -416,11 +521,15 @@ static const struct func global_funcs[] = {
416 521
 		.name = "pid",
417 522
 		.type = &t_pid_func,
418 523
 		.static_ret = 1,
524
+
525
+		.ir_post = global_pid_ir_post,
419 526
 	},
420 527
 	{
421 528
 		.name = "time",
422 529
 		.type = &t_time_func,
423 530
 		.static_ret = 1,
531
+
532
+		.ir_post = global_time_ir_post,
424 533
 	},
425 534
 
426 535
 	{

+ 90 - 5
ir.c

@@ -7,6 +7,7 @@
7 7
 
8 8
 #include "ir.h"
9 9
 #include "sym.h"
10
+#include "type.h"
10 11
 
11 12
 const uint16_t vreg_base = 0x8000;
12 13
 
@@ -331,24 +332,81 @@ void ir_emit_label  (struct ir *ir, int16_t label)
331 332
 /* 	ir_emit(ir, &vi); */
332 333
 /* } */
333 334
 
334
-void ir_emit_mov_irs(struct ir *ir, uint16_t dst, struct irstate *src)
335
+void ir_emit_sym_to_reg(struct ir *ir, uint16_t dst, struct sym *src)
335 336
 {
336
-	switch (src->loc) {
337
+	struct irstate *irs = &src->irs;
338
+
339
+	switch (irs->loc) {
337 340
 	case LOC_IMM:
338
-		ir_emit_insn(ir, MOV_IMM(0, src->imm), dst, 0);
341
+		ir_emit_insn(ir, MOV_IMM(0, irs->imm), dst, 0);
339 342
 		break;
340 343
 	case LOC_REG:
341
-		ir_emit_insn(ir, MOV(0, 0), dst, src->reg);
344
+		ir_emit_insn(ir, MOV(0, 0), dst, irs->reg);
342 345
 		break;
343 346
 	case LOC_STACK:
344
-		ir_emit_insn(ir, LDX(0, src->stack, 0), dst, BPF_REG_BP);
347
+		switch (irs->size) {
348
+		case 1:
349
+			ir_emit_insn(ir, LDXB(0, irs->stack, 0),
350
+				     dst, BPF_REG_BP);
351
+			break;
352
+		case 2:
353
+			ir_emit_insn(ir, LDXH(0, irs->stack, 0),
354
+				     dst, BPF_REG_BP);
355
+			break;
356
+		case 4:
357
+			ir_emit_insn(ir, LDXW(0, irs->stack, 0),
358
+				     dst, BPF_REG_BP);
359
+			break;
360
+		case 8:
361
+			ir_emit_insn(ir, LDXDW(0, irs->stack, 0),
362
+				     dst, BPF_REG_BP);
363
+			break;
364
+		default:
365
+			assert(0);
366
+		}
345 367
 		break;
368
+	default:
369
+		assert(0);
370
+	}
371
+}
346 372
 
373
+void ir_emit_reg_to_sym(struct ir *ir, struct sym *dst, uint16_t src)
374
+{
375
+	struct irstate *irs = &dst->irs;
376
+
377
+	switch (irs->loc) {
378
+	case LOC_REG:
379
+		ir_emit_insn(ir, MOV(0, 0), irs->reg, src);
380
+		break;
381
+	case LOC_STACK:
382
+		switch (irs->size) {
383
+		case 1:
384
+			ir_emit_insn(ir, STXB(0, irs->stack, 0),
385
+				     BPF_REG_BP, src);
386
+			break;
387
+		case 2:
388
+			ir_emit_insn(ir, STXH(0, irs->stack, 0),
389
+				     BPF_REG_BP, src);
390
+			break;
391
+		case 4:
392
+			ir_emit_insn(ir, STXW(0, irs->stack, 0),
393
+				     BPF_REG_BP, src);
394
+			break;
395
+		case 8:
396
+			ir_emit_insn(ir, STXDW(0, irs->stack, 0),
397
+				     BPF_REG_BP, src);
398
+			break;
399
+		default:
400
+			assert(0);
401
+		}
402
+		break;
347 403
 	default:
348 404
 		assert(0);
349 405
 	}
350 406
 }
351 407
 
408
+/* void ir_emit_xfer(struct ir *ir,  */
409
+
352 410
 int16_t ir_alloc_label (struct ir *ir)
353 411
 {
354 412
 	return ir->next_label--;
@@ -367,6 +425,33 @@ ssize_t ir_alloc_stack(struct ir *ir, size_t size)
367 425
 	return ir->sp;
368 426
 }
369 427
 
428
+void ir_init_sym(struct ir *ir, struct sym *sym)
429
+{
430
+	struct irstate *irs = &sym->irs;
431
+	struct type *t = type_base(sym->type);
432
+
433
+	if (irs->loc)
434
+		return;
435
+
436
+	irs->size = type_sizeof(t);
437
+
438
+	if (irs->hint.stack)
439
+		goto alloc_stack;
440
+
441
+	switch (t->ttype) {
442
+	case T_SCALAR:
443
+	case T_POINTER:
444
+		irs->loc = LOC_REG;
445
+		irs->reg = ir_alloc_register(ir);
446
+		return;
447
+
448
+	default:
449
+	alloc_stack:
450
+		irs->loc = LOC_STACK;
451
+		irs->stack = ir_alloc_stack(ir, irs->size);
452
+	}
453
+}
454
+
370 455
 struct ir *ir_new(void)
371 456
 {
372 457
 	struct ir *ir;

+ 7 - 16
ir.h

@@ -106,12 +106,14 @@ enum irloc {
106 106
 struct irstate {
107 107
 	int loc;
108 108
 
109
-	uint16_t reg;
109
+	size_t   size;
110 110
 	int32_t  stack;
111 111
 	int32_t  imm;
112
+	uint16_t reg;
112 113
 
113 114
 	struct {
114 115
 		int dot:1;
116
+		int lval:1;
115 117
 		int stack:1;
116 118
 	} hint;
117 119
 };
@@ -124,27 +126,16 @@ int16_t  ir_alloc_label   (struct ir *ir);
124 126
 uint16_t ir_alloc_register(struct ir *ir);
125 127
 ssize_t  ir_alloc_stack   (struct ir *ir, size_t size);
126 128
 
129
+void ir_init_sym(struct ir *ir, struct sym *sym);
130
+
127 131
 void ir_emit_insn   (struct ir *ir, struct bpf_insn bpf, uint16_t dst, uint16_t src);
128 132
 void ir_emit_ldmap  (struct ir *ir, uint16_t dst, struct sym *map);
129 133
 void ir_emit_label  (struct ir *ir, int16_t label);
130 134
 /* void ir_emit_reg_get(struct ir *ir, uint16_t reg); */
131 135
 /* 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);
136
+void ir_emit_sym_to_reg(struct ir *ir, uint16_t dst, struct sym *src);
137
+void ir_emit_reg_to_sym(struct ir *ir, struct sym *dst, uint16_t src);
133 138
 
134 139
 struct ir *ir_new(void);
135 140
 
136
-
137
-static inline void irs_alloc_register(struct irstate *irs, struct ir *ir)
138
-{
139
-	irs->loc = LOC_REG;
140
-	irs->reg = ir_alloc_register(ir);
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);
148
-}
149
-
150 141
 #endif	/* _PLY_IR_H */

+ 1 - 1
kprobe.c

@@ -88,7 +88,7 @@ static int kprobe_ir_pre(struct prog *prog)
88 88
 
89 89
 	symtab_foreach(prog->locals, sym) {
90 90
 		if ((*sym)->name && !strcmp((*sym)->name, "regs")) {
91
-			irs_alloc_register(&(*sym)->irs, prog->ir);
91
+			ir_init_sym(prog->ir, *sym);
92 92
 
93 93
 			/* kernel sets r1 to the address of the
94 94
 			 * pt_regs struct, which ply denotes as

+ 2 - 9
node.c

@@ -97,20 +97,13 @@ int node_replace(struct node *n, struct node *new)
97 97
 
98 98
 /* helpers */
99 99
 
100
-int node_is_block(struct node *n)
100
+int node_is(struct node *n, const char *func)
101 101
 {
102 102
 	if (!n || (n->ntype != N_EXPR))
103 103
 		return 0;
104 104
 
105
-	return !strcmp(n->expr.func, ":block");
106
-}
107
-
108
-int node_is_map(struct node *n)
109
-{
110
-	if (!n || (n->ntype != N_EXPR))
111
-		return 0;
105
+	return !strcmp(n->expr.func, func);
112 106
 
113
-	return !strcmp(n->expr.func, "{}");
114 107
 }
115 108
 
116 109
 

+ 1 - 2
node.h

@@ -71,8 +71,7 @@ static inline int node_nargs(struct node *n)
71 71
 	return nargs;
72 72
 }
73 73
 
74
-int node_is_block(struct node *n);
75
-int node_is_map  (struct node *n);
74
+int node_is(struct node *n, const char *func);
76 75
 
77 76
 #define node_expr_foreach(_expr, _arg) \
78 77
 	for ((_arg) = (_expr)->expr.args; (_arg); (_arg) = (_arg)->next)

+ 5 - 5
ply.c

@@ -71,17 +71,17 @@ struct ctx *ctx_get(void)
71 71
 	prog->probe = "k:SyS_read";
72 72
 
73 73
 	/* { 
74
-	 * 	us = pid();
74
+	 * 	# us = pid();
75 75
 	 * 	t[0, pid()] = time();
76 76
 	 * 	reads[pid()] = quantize(arg2);
77 77
 	 * }
78 78
 	 */
79 79
 	prog->ast =
80 80
 		node_expr(":block",
81
-			  node_expr("=",
82
-				    node_ident("us"),
83
-				    node_expr("pid", NULL),
84
-				    NULL),
81
+			  /* node_expr("=", */
82
+			  /* 	    node_ident("us"), */
83
+			  /* 	    node_expr("pid", NULL), */
84
+			  /* 	    NULL), */
85 85
 			  node_expr("=",
86 86
 				    node_expr("{}",
87 87
 					      node_ident("t"),

+ 10 - 0
type.c

@@ -327,7 +327,17 @@ ssize_t type_sizeof(struct type *t)
327 327
 	return -EINVAL;
328 328
 }
329 329
 
330
+struct tfield *tfields_get(struct tfield *fields, const char *name)
331
+{
332
+	struct tfield *f;
330 333
 
334
+	tfields_foreach(f, fields) {
335
+		if (!strcmp(f->name, name))
336
+			return f;
337
+	}
338
+
339
+	return NULL;
340
+}
331 341
 
332 342
 int all_types_cmp(const void *_a, const void *_b)
333 343
 {

+ 2 - 0
type.h

@@ -38,6 +38,8 @@ struct tfield {
38 38
 #define tfields_foreach(_f, _fields) \
39 39
 	for ((_f) = (_fields); (_f)->type; (_f)++)
40 40
 
41
+struct tfield *tfields_get(struct tfield *fields, const char *name);
42
+
41 43
 struct tstruct {
42 44
 	char *name;
43 45
 	struct tfield *fields;

+ 3 - 3
utils.c

@@ -19,7 +19,7 @@ static int __ast_fprint_pre(struct node *n, void *_info)
19 19
 	if (n->prev)
20 20
 		fputc(' ', info->fp);
21 21
 
22
-	if (node_is_block(n->up)) {
22
+	if (node_is(n->up, ":block")) {
23 23
 		info->indent += 4;
24 24
 		fprintf(info->fp, "\n%*s", info->indent, "");
25 25
 	}
@@ -41,13 +41,13 @@ static int __ast_fprint_post(struct node *n, void *_info)
41 41
 	struct ast_fprint_info *info = _info;
42 42
 	struct node *c;
43 43
 
44
-	if (node_is_block(n))
44
+	if (node_is(n, ":block"))
45 45
 		fprintf(info->fp, "\n%*s", info->indent, "");
46 46
 
47 47
 	if (n->ntype == N_EXPR)
48 48
 		fputc(')', info->fp);
49 49
 
50
-	if (node_is_block(n->up))
50
+	if (node_is(n->up, ":block"))
51 51
 		info->indent -= 4;
52 52
 	
53 53
 	return 0;