Bläddra i källkod

function verifier done, started on rewrites

Tobias Waldekranz.com 8 år sedan
förälder
incheckning
01d681fcf9
9 ändrade filer med 204 tillägg och 16 borttagningar
  1. 24 0
      arch-x86_64.c
  2. 7 0
      arch.h
  3. 37 2
      kprobe.c
  4. 19 2
      node.c
  5. 6 4
      node.h
  6. 59 6
      ply.c
  7. 2 1
      ply.h
  8. 44 0
      type.c
  9. 6 1
      type.h

+ 24 - 0
arch-x86_64.c

@@ -62,6 +62,30 @@ type_t *arch_types[] = {
62 62
 	NULL
63 63
 };
64 64
 
65
+const char *arch_register_argument(int num)
66
+{
67
+	switch (num) {
68
+	case 0: return "di";
69
+	case 1: return "si";
70
+	case 2: return "dx";
71
+	case 3: return "r10";
72
+	case 4: return "r8";
73
+	case 5: return "r9";
74
+	}
75
+
76
+	return NULL;
77
+}
78
+
79
+const char *arch_register_pc(void) 
80
+{
81
+	return "ip";
82
+}
83
+
84
+const char *arch_register_return(void)
85
+{
86
+	return "ax";
87
+}
88
+
65 89
 __attribute__((constructor))
66 90
 static void arch_init(void)
67 91
 {

+ 7 - 0
arch.h

@@ -3,6 +3,7 @@
3 3
 
4 4
 #include "type.h"
5 5
 
6
+/* fixed length integers */
6 7
 extern type_t t_s8;
7 8
 extern type_t t_u8;
8 9
 extern type_t t_s16;
@@ -12,6 +13,12 @@ extern type_t t_u32;
12 13
 extern type_t t_s64;
13 14
 extern type_t t_u64;
14 15
 
16
+/* layout of captured registers */
15 17
 extern type_t t_pt_regs;
16 18
 
19
+/* ABI mapping of registers to arguments/return value */
20
+const char *arch_register_argument(int num);
21
+const char *arch_register_pc      (void);
22
+const char *arch_register_return  (void);
23
+
17 24
 #endif	/* _PLY_ARCH_H */

+ 37 - 2
kprobe.c

@@ -17,7 +17,41 @@ static inline int is_arg(const char *name)
17 17
 		&& (name[3] >= '0' && name[3] <= '9');
18 18
 }
19 19
 
20
-int kprobe_resolve(prog_t *prog, node_t *n)
20
+static int kprobe_rewrite_arg(prog_t *prog, node_t *n)
21
+{
22
+	const char *reg;
23
+	int arg = n->ident[3] - '0';
24
+	node_t *new;
25
+
26
+	reg = arch_register_argument(arg);
27
+	if (!reg) {
28
+		node_print(n, stderr);
29
+		fputs(": the location of this argument is unknown\n", stderr);
30
+		/* TODO: add ABI mappings for specifying arguments
31
+		 * passed on the stack. */
32
+		return -EINVAL;
33
+	}
34
+
35
+	/* argN => (*ctx).REG */
36
+	new = node_vlist(node_keyword('.', 0),
37
+			 node_vlist(node_keyword('*', 0),
38
+				    node_ident("ctx"),
39
+				    NULL),
40
+			 node_string(reg),
41
+			 NULL);
42
+
43
+	return node_replace(n, new);
44
+}
45
+
46
+static int kprobe_rewrite_node(prog_t *prog, node_t *n)
47
+{
48
+	if ((n->ntype == N_IDENT) && is_arg(n->ident))
49
+		return kprobe_rewrite_arg(prog, n);
50
+
51
+	return 0;
52
+}
53
+
54
+static int kprobe_resolve(prog_t *prog, node_t *n)
21 55
 {
22 56
 	type_t *t;
23 57
 
@@ -32,7 +66,7 @@ int kprobe_resolve(prog_t *prog, node_t *n)
32 66
 	return sym_add(prog->locals, n->ident, t, &n->sym);
33 67
 }
34 68
 
35
-int kprobe_probe(prog_t *prog)
69
+static int kprobe_probe(prog_t *prog)
36 70
 {
37 71
 	struct kprobe *kp;
38 72
 
@@ -46,6 +80,7 @@ int kprobe_probe(prog_t *prog)
46 80
 provider_t kprobe = {
47 81
 	.name = "kprobe",
48 82
 
83
+	.rewrite_node = kprobe_rewrite_node,
49 84
 	.resolve = kprobe_resolve,
50 85
 	.probe = kprobe_probe,
51 86
 };

+ 19 - 2
node.c

@@ -147,6 +147,23 @@ int node_walk(node_t *n,
147 147
 	return 0;
148 148
 }
149 149
 
150
+int node_replace(node_t *n, node_t *new)
151
+{
152
+	new->up = n->up;
153
+
154
+	if (n->prev) {
155
+		new->prev = n->prev;
156
+		n->prev->next = new;
157
+	}
158
+
159
+	if (n->next) {
160
+		new->next = n->next;
161
+		n->next->prev = new;
162
+	}
163
+
164
+	/* TODO: don't leak memory */
165
+	return 0;
166
+}
150 167
 
151 168
 /* constructors */
152 169
 
@@ -194,7 +211,7 @@ node_t *node_keyword(kwclass_t class, int op)
194 211
 	return n;
195 212
 }
196 213
 
197
-node_t *node_ident(char *name)
214
+node_t *node_ident(const char *name)
198 215
 {
199 216
 	node_t *n = __node(N_IDENT);
200 217
 	n->ident = name;
@@ -211,7 +228,7 @@ node_t *node_num(int64_t num)
211 228
 	return n;
212 229
 }
213 230
 
214
-node_t *node_string(char *string)
231
+node_t *node_string(const char *string)
215 232
 {
216 233
 	node_t *n = __node(N_STRING);
217 234
 	n->string = string;

+ 6 - 4
node.h

@@ -42,9 +42,9 @@ struct node {
42 42
 	union {
43 43
 		node_t *list;
44 44
 		keyword_t keyword;
45
-		char *ident;
45
+		const char *ident;
46 46
 		int64_t num;
47
-		char *string;
47
+		const char *string;
48 48
 	};
49 49
 
50 50
 	type_t *type;
@@ -58,15 +58,17 @@ void node_dump (node_t *n, FILE *fp);
58 58
 typedef int (*walk_fn)(node_t *, void *);
59 59
 int node_walk(node_t *n, walk_fn pre, walk_fn post, void *ctx);
60 60
 
61
+int node_replace(node_t *n, node_t *new);
62
+
61 63
 
62 64
 /* constructors */
63 65
 node_t *node_list  (node_t *head);
64 66
 node_t *node_vlist (node_t *head, ...);
65 67
 
66 68
 node_t *node_keyword(kwclass_t class, int op);
67
-node_t *node_ident  (char *name);
69
+node_t *node_ident  (const char *name);
68 70
 node_t *node_num    (int64_t num);
69
-node_t *node_string (char *string);
71
+node_t *node_string (const char *string);
70 72
 
71 73
 static inline node_t *node_head(node_t *n)
72 74
 {

+ 59 - 6
ply.c

@@ -127,11 +127,6 @@ int pass_resolve_symbols(node_t *n, void *_prog)
127 127
 	if (n->ntype != N_IDENT)
128 128
 		return 0;
129 129
 
130
-	/* .IDENT/->IDENT is a struct/union member, skip */
131
-	/* op = node_prev(node_prev(n)); */
132
-	/* if (op && (op->ntype == N_IDENT) && !strcmp(".", op->ident)) */
133
-	/* 	return 0; */
134
-
135 130
 	err = prog->provider->resolve(prog, n);
136 131
 	if (!err || (err != -ENOENT))
137 132
 		return err;
@@ -269,7 +264,39 @@ int pass_infer_types(node_t *n, void *_prog)
269 264
 
270 265
 int validate_func(node_t *n)
271 266
 {
272
-	return 0;
267
+	node_t *arg;
268
+	field_t *f;
269
+	int i;
270
+
271
+	for (arg = node_next(n), f = n->type->t.func.args, i = 1;
272
+	     arg && f && f->type; arg = node_next(arg), f++, i++) {
273
+		if (type_compatible(arg->type, f->type))
274
+			continue;
275
+
276
+		node_print(n, stderr);
277
+		fprintf(stderr, ": incompatible type of argument %d (", i);
278
+		type_dump(arg->type, stderr);
279
+		fputs("), expected ", stderr);
280
+		type_dump(f->type, stderr);
281
+		fputs("\n", stderr);
282
+		return -EINVAL;
283
+	}
284
+
285
+	if (!arg && (!f || !f->type))
286
+		return 0;
287
+
288
+	if (arg) {
289
+		node_print(n, stderr);
290
+		fprintf(stderr, ": too many arguments, expected %d", i);
291
+		return -EINVAL;
292
+	}
293
+
294
+	if (f->optional)
295
+		return 0;
296
+
297
+	node_print(n, stderr);
298
+	fputs(": too few arguments", stderr);
299
+	return -EINVAL;	
273 300
 }
274 301
 
275 302
 int pass_validate_types(node_t *n, void *_prog)
@@ -292,6 +319,27 @@ int pass_validate_types(node_t *n, void *_prog)
292 319
 	return validate_func(n->list);
293 320
 }
294 321
 
322
+int pass_rewrite_ast(node_t *n, void *_prog)
323
+{
324
+	prog_t *prog = _prog;
325
+	provider_t *global = provider_get(":");
326
+	int err;
327
+
328
+	if (prog->provider->rewrite_node) {
329
+		err = prog->provider->rewrite_node(prog, n);
330
+		if (err)
331
+			return err;
332
+	}
333
+
334
+	if (global->rewrite_node) {
335
+		err = global->rewrite_node(prog, n);
336
+		if (err)
337
+			return err;
338
+	}
339
+
340
+	return 0;
341
+}
342
+
295 343
 int pass_walk(pass_t *pass, ctx_t *ctx)
296 344
 {
297 345
 	prog_t **prog;
@@ -312,6 +360,7 @@ pass_t passes[] = {
312 360
 	{ .run = pass_walk, .post = pass_infer_types },
313 361
 	{ .run = pass_walk, .post = pass_infer_types },
314 362
 	{ .run = pass_walk, .post = pass_validate_types },
363
+	{ .run = pass_walk, .post = pass_rewrite_ast },
315 364
 
316 365
 	{ NULL }
317 366
 };
@@ -338,5 +387,9 @@ int main(void)
338 387
 
339 388
 	printf("\n\n-- globals\n");
340 389
 	symtab_dump(ctx->globals, stdout);
390
+
391
+	if (err)
392
+		printf("ERR: %d\n", err);
393
+
341 394
 	return err;
342 395
 }

+ 2 - 1
ply.h

@@ -29,8 +29,9 @@ typedef struct ctx {
29 29
 struct provider {
30 30
 	const char *name;
31 31
 
32
-	int (*resolve)(prog_t *, node_t *);
33 32
 	int (*probe)(prog_t *);
33
+	int (*resolve)(prog_t *, node_t *);
34
+	int (*rewrite_node)(prog_t *, node_t *);
34 35
 };
35 36
 
36 37
 void provider_register(provider_t *prov);

+ 44 - 0
type.c

@@ -1,6 +1,7 @@
1 1
 #include <assert.h>
2 2
 #include <stdio.h>
3 3
 #include <stdlib.h>
4
+#include <string.h>
4 5
 
5 6
 #include "type.h"
6 7
 
@@ -198,12 +199,55 @@ type_t *type_ptr_of(type_t *type)
198 199
 	return t;
199 200
 }
200 201
 
202
+type_t *type_normalize(type_t *t)
203
+{
204
+	while (t->ttype == T_TYPEDEF)
205
+		t = t->t.tdef.type;
206
+
207
+	return t;
208
+}
209
+
201 210
 int type_equal(type_t *a, type_t *b)
202 211
 {
203 212
 	/* TODO */
204 213
 	return a == b;
205 214
 }
206 215
 
216
+int type_compatible(type_t *a, type_t *b)
217
+{
218
+
219
+	a = type_normalize(a);
220
+	b = type_normalize(b);
221
+
222
+	if (a->ttype != b->ttype)
223
+		return 0;
224
+
225
+	switch (a->ttype){
226
+	case T_SCALAR:
227
+		return 1;
228
+	case T_POINTER:
229
+		return 1;
230
+	case T_ARRAY:
231
+		if (a->t.array.len != b->t.array.len)
232
+			return 0;
233
+
234
+		return type_compatible(a->t.array.type, b->t.array.type);
235
+	case T_STRUCT:
236
+	case T_UNION:
237
+		return !strcmp(a->t.sou.name, b->t.sou.name);
238
+	case T_FUNC:
239
+		return type_compatible(a->t.func.type, b->t.func.type);
240
+	case T_MAP:
241
+		return type_compatible(a->t.map.vtype, b->t.map.vtype);
242
+
243
+	case T_TYPEDEF:
244
+		assert(0);
245
+	}
246
+
247
+	assert(0);
248
+	return 0;
249
+}
250
+
207 251
 void type_size_set_sou(type_t *t)
208 252
 {
209 253
 	field_t *f;

+ 6 - 1
type.h

@@ -34,6 +34,9 @@ typedef struct field {
34 34
 	char *name;
35 35
 	type_t *type;
36 36
 	size_t offset;
37
+
38
+	/* function arguments */
39
+	int optional:1;
37 40
 } field_t;
38 41
 
39 42
 struct t_sou {
@@ -92,7 +95,9 @@ extern type_t t_ullong;
92 95
 type_t *type_map_of(type_t *ktype, type_t *vtype);
93 96
 type_t *type_ptr_of(type_t *type);
94 97
 
95
-int type_equal(type_t *a, type_t *b);
98
+int type_equal     (type_t *a, type_t *b);
99
+int type_compatible(type_t *a, type_t *b);
100
+
96 101
 int type_add(type_t *t);
97 102
 int type_add_list(type_t **ts);
98 103