Pārlūkot izejas kodu

argN -> regs rewrite done

Tobias Waldekranz.com 8 gadi atpakaļ
vecāks
revīzija
7c3acf08f0
4 mainītis faili ar 135 papildinājumiem un 41 dzēšanām
  1. 101 13
      global.c
  2. 24 24
      kprobe.c
  3. 5 0
      node.c
  4. 5 4
      ply.c

+ 101 - 13
global.c

@@ -12,6 +12,70 @@
12 12
 #include "sym.h"
13 13
 #include "type.h"
14 14
 
15
+/* . */
16
+
17
+static int global_dot_type_infer(const struct func *func, struct node *n)
18
+{
19
+	struct node *sou, *member;
20
+	struct type *t;
21
+	struct tfield *f;
22
+
23
+	if (n->sym->type)
24
+		return 0;
25
+
26
+	sou = n->expr.args;
27
+	member = sou->next;
28
+	if (!sou->sym->type)
29
+		return 0;
30
+
31
+	t = type_base(sou->sym->type);
32
+
33
+	/* TODO: add union */
34
+	if (t->ttype != T_STRUCT) {
35
+		_e("%#N: %N is neither struct nor union (type '%T').\n",
36
+		   n, sou, sou->sym->type);
37
+		return -EINVAL;
38
+	}
39
+
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
+		}
48
+	}
49
+
50
+	_e("%#N: type '%T' has no member named '%s'.\n",
51
+	   n, t, member->string.data);
52
+	return -EINVAL;
53
+}
54
+
55
+
56
+/* :deref */
57
+
58
+static int global_deref_type_infer(const struct func *func, struct node *n)
59
+{
60
+	struct node *ptr = n->expr.args;
61
+	struct type *t;
62
+
63
+	if (n->sym->type || !ptr->sym->type)
64
+		return 0;
65
+
66
+	t = type_base(ptr->sym->type);
67
+	if (t->ttype != T_POINTER) {
68
+		_e("%#N: can't dereference %N (type '%T').\n",
69
+		   n, ptr, ptr->sym->type);
70
+		return -EINVAL;
71
+	}
72
+
73
+	/* given `*p` where p is a pointer, infer that the
74
+	 * expression's type is equal to p's concrete type. */
75
+	n->sym->type = t->ptr.type;
76
+	return 0;
77
+}
78
+
15 79
 
16 80
 /* :map */
17 81
 
@@ -65,7 +129,7 @@ static int global_map_type_infer(const struct func *func, struct node *n)
65 129
 static int global_map_static_validate(const struct func *func, struct node *n)
66 130
 {
67 131
 	if (n->expr.args->ntype != N_IDENT) {
68
-		_e("%#N: trying to lookup a key in %N, which is not a map.\n",
132
+		_e("%#N: can't lookup a key in %N, which is not a map.\n",
69 133
 		   n, n);
70 134
 		return -EINVAL;
71 135
 	}
@@ -222,6 +286,31 @@ struct type t_block_func = {
222 286
 	.func = { .type = &t_void, .vargs = 1 },
223 287
 };
224 288
 
289
+struct type t_string_array = {
290
+	.ttype = T_ARRAY,
291
+
292
+	.array = { .type = &t_char, .len = 64 }, /* TODO: tunable */
293
+};
294
+
295
+struct type t_string = {
296
+	.ttype = T_TYPEDEF,
297
+
298
+	.tdef = { .name = ":string", .type = &t_string_array },
299
+};
300
+
301
+struct tfield f_dot[] = {
302
+	{ .type = &t_void },
303
+	{ .type = &t_string },
304
+
305
+	{ .type = NULL }
306
+};
307
+
308
+struct type t_dot_func = {
309
+	.ttype = T_FUNC,
310
+
311
+	.func = { .type = &t_void, .args = f_dot },
312
+};
313
+
225 314
 struct tfield f_2args[] = {
226 315
 	{ .type = &t_void },
227 316
 	{ .type = &t_void },
@@ -254,6 +343,17 @@ static const struct func global_funcs[] = {
254 343
 		.static_ret = 1,
255 344
 	},
256 345
 
346
+	{
347
+		.name = ".",
348
+		.type = &t_dot_func,
349
+		.type_infer = global_dot_type_infer,
350
+	},
351
+	{
352
+		.name = ":deref",
353
+		.type = &t_1arg_func,
354
+		.type_infer = global_deref_type_infer,
355
+	},
356
+
257 357
 	{
258 358
 		.name = "+",
259 359
 		.type = &t_2args_func,
@@ -330,18 +430,6 @@ static const struct func global_num_func = {
330 430
 	.name = ":num",
331 431
 };
332 432
 
333
-struct type t_string_array = {
334
-	.ttype = T_ARRAY,
335
-
336
-	.array = { .type = &t_char, .len = 64 }, /* TODO: tunable */
337
-};
338
-
339
-struct type t_string = {
340
-	.ttype = T_TYPEDEF,
341
-
342
-	.tdef = { .name = ":string", .type = &t_string_array },
343
-};
344
-
345 433
 static const struct func global_string_func = {
346 434
 	.name = ":string",
347 435
 	.type = &t_string,

+ 24 - 24
kprobe.c

@@ -14,12 +14,10 @@
14 14
 #include "type.h"
15 15
 
16 16
 struct kprobe {
17
-	int use_ctx:1;
18
-
19
-	struct irstate ctx_irs;
17
+	struct irstate regs_irs;
20 18
 };
21 19
 
22
-/* ctx */
20
+/* regs */
23 21
 
24 22
 static struct type t_pt_regsp = {
25 23
 	.ttype = T_POINTER,
@@ -27,8 +25,8 @@ static struct type t_pt_regsp = {
27 25
 	.ptr.type = &t_pt_regs,
28 26
 };
29 27
 
30
-static const struct func kprobe_ctx_func = {
31
-	.name = "ctx",
28
+static const struct func kprobe_regs_func = {
29
+	.name = "regs",
32 30
 
33 31
 	.type = &t_pt_regsp,
34 32
 	.static_ret = 1,
@@ -61,15 +59,12 @@ static int kprobe_arg_rewrite(const struct func *func, struct node *n,
61 59
 		return -EINVAL;
62 60
 	}
63 61
 
64
-	/* argN => (*ctx).REG */
62
+	/* argN => (*regs).REG */
65 63
 	new = node_expr(".",
66
-			node_expr("*", node_ident("ctx"), NULL),
64
+			node_expr(":deref", node_ident("regs"), NULL),
67 65
 			node_string((char *)reg),
68 66
 			NULL);
69 67
 
70
-	ast_fprint(stdout, n);
71
-	ast_fprint(stdout, new);
72
-
73 68
 	node_replace(n, new);
74 69
 	return 0;
75 70
 }
@@ -91,20 +86,26 @@ static const struct func kprobe_arg_func = {
91 86
 static int kprobe_ir_pre(struct prog *prog)
92 87
 {
93 88
 	struct kprobe *kp = prog->provider_data;
89
+	struct sym **sym;
90
+
91
+	symtab_foreach(prog->locals, sym) {
92
+		if ((*sym)->name && !strcmp((*sym)->name, "regs")) {
93
+			irs_alloc_reg(&kp->regs_irs, prog->ir);
94
+
95
+			/* kernel sets r1 to the address of the
96
+			 * pt_regs struct, which ply denotes as
97
+			 * 'regs'. if we're using it we need to get a
98
+			 * reference to it before it is clobbered. */
99
+			ir_emit_insn(prog->ir, MOV(0, 0),
100
+				     kp->regs_irs.reg, BPF_REG_1);
101
+		}
102
+	}
94 103
 
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 104
 	return 0;
103 105
 }
104 106
 
105 107
 static int kprobe_sym_alloc(struct prog *prog, struct node *n)
106 108
 {
107
-	struct kprobe *kp = prog->provider_data;
108 109
 	const struct func *func = NULL;
109 110
 	int err;
110 111
 
@@ -112,11 +113,10 @@ static int kprobe_sym_alloc(struct prog *prog, struct node *n)
112 113
 	case N_EXPR:
113 114
 		break;
114 115
 	case N_IDENT:
115
-		if (!is_arg(n->ident.name))
116
-			break;
117
-
118
-		func = &kprobe_arg_func;
119
-		kp->use_ctx = 1;
116
+		if (!strcmp(n->ident.name, "regs"))
117
+			func = &kprobe_regs_func;
118
+		else if (is_arg(n->ident.name))
119
+			func = &kprobe_arg_func;
120 120
 		break;
121 121
 	default:
122 122
 		break;

+ 5 - 0
node.c

@@ -86,6 +86,11 @@ int node_replace(struct node *n, struct node *new)
86 86
 		n->next->prev = new;
87 87
 	}
88 88
 
89
+	if (new->up
90
+	    && (new->up->ntype == N_EXPR)
91
+	    && (new->up->expr.args == n))
92
+		new->up->expr.args = new;
93
+
89 94
 	/* TODO: don't leak memory */
90 95
 	return 0;
91 96
 }

+ 5 - 4
ply.c

@@ -254,12 +254,13 @@ int run_walk(struct pass *pass, struct ctx *ctx)
254 254
 
255 255
 struct pass passes[] = {
256 256
 	{ .run = run_walk, .post = pass_sym_alloc },
257
-	/* node->sym ok */
258 257
 	{ .run = run_walk, .post = pass_type_infer },
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. */
258
+
262 259
 	{ .run = run_walk, .post = pass_rewrite },
260
+
261
+	{ .run = run_walk, .post = pass_sym_alloc },
262
+	{ .run = run_walk, .post = pass_type_infer },
263
+
263 264
 	{ .run = run_ir },
264 265
 	/* program flattened to vBPF instructions, now rewrite it to
265 266
 	 * fit into the actual hw/vm. */