Browse Source

function verifier done, started on rewrites

Tobias Waldekranz.com 8 years ago
parent
commit
01d681fcf9
9 changed files with 204 additions and 16 deletions
  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
 	NULL
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
 __attribute__((constructor))
89
 __attribute__((constructor))
66
 static void arch_init(void)
90
 static void arch_init(void)
67
 {
91
 {

+ 7 - 0
arch.h

3
 
3
 
4
 #include "type.h"
4
 #include "type.h"
5
 
5
 
6
+/* fixed length integers */
6
 extern type_t t_s8;
7
 extern type_t t_s8;
7
 extern type_t t_u8;
8
 extern type_t t_u8;
8
 extern type_t t_s16;
9
 extern type_t t_s16;
12
 extern type_t t_s64;
13
 extern type_t t_s64;
13
 extern type_t t_u64;
14
 extern type_t t_u64;
14
 
15
 
16
+/* layout of captured registers */
15
 extern type_t t_pt_regs;
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
 #endif	/* _PLY_ARCH_H */
24
 #endif	/* _PLY_ARCH_H */

+ 37 - 2
kprobe.c

17
 		&& (name[3] >= '0' && name[3] <= '9');
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
 	type_t *t;
56
 	type_t *t;
23
 
57
 
32
 	return sym_add(prog->locals, n->ident, t, &n->sym);
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
 	struct kprobe *kp;
71
 	struct kprobe *kp;
38
 
72
 
46
 provider_t kprobe = {
80
 provider_t kprobe = {
47
 	.name = "kprobe",
81
 	.name = "kprobe",
48
 
82
 
83
+	.rewrite_node = kprobe_rewrite_node,
49
 	.resolve = kprobe_resolve,
84
 	.resolve = kprobe_resolve,
50
 	.probe = kprobe_probe,
85
 	.probe = kprobe_probe,
51
 };
86
 };

+ 19 - 2
node.c

147
 	return 0;
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
 /* constructors */
168
 /* constructors */
152
 
169
 
194
 	return n;
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
 	node_t *n = __node(N_IDENT);
216
 	node_t *n = __node(N_IDENT);
200
 	n->ident = name;
217
 	n->ident = name;
211
 	return n;
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
 	node_t *n = __node(N_STRING);
233
 	node_t *n = __node(N_STRING);
217
 	n->string = string;
234
 	n->string = string;

+ 6 - 4
node.h

42
 	union {
42
 	union {
43
 		node_t *list;
43
 		node_t *list;
44
 		keyword_t keyword;
44
 		keyword_t keyword;
45
-		char *ident;
45
+		const char *ident;
46
 		int64_t num;
46
 		int64_t num;
47
-		char *string;
47
+		const char *string;
48
 	};
48
 	};
49
 
49
 
50
 	type_t *type;
50
 	type_t *type;
58
 typedef int (*walk_fn)(node_t *, void *);
58
 typedef int (*walk_fn)(node_t *, void *);
59
 int node_walk(node_t *n, walk_fn pre, walk_fn post, void *ctx);
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
 /* constructors */
64
 /* constructors */
63
 node_t *node_list  (node_t *head);
65
 node_t *node_list  (node_t *head);
64
 node_t *node_vlist (node_t *head, ...);
66
 node_t *node_vlist (node_t *head, ...);
65
 
67
 
66
 node_t *node_keyword(kwclass_t class, int op);
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
 node_t *node_num    (int64_t num);
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
 static inline node_t *node_head(node_t *n)
73
 static inline node_t *node_head(node_t *n)
72
 {
74
 {

+ 59 - 6
ply.c

127
 	if (n->ntype != N_IDENT)
127
 	if (n->ntype != N_IDENT)
128
 		return 0;
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
 	err = prog->provider->resolve(prog, n);
130
 	err = prog->provider->resolve(prog, n);
136
 	if (!err || (err != -ENOENT))
131
 	if (!err || (err != -ENOENT))
137
 		return err;
132
 		return err;
269
 
264
 
270
 int validate_func(node_t *n)
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
 int pass_validate_types(node_t *n, void *_prog)
302
 int pass_validate_types(node_t *n, void *_prog)
292
 	return validate_func(n->list);
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
 int pass_walk(pass_t *pass, ctx_t *ctx)
343
 int pass_walk(pass_t *pass, ctx_t *ctx)
296
 {
344
 {
297
 	prog_t **prog;
345
 	prog_t **prog;
312
 	{ .run = pass_walk, .post = pass_infer_types },
360
 	{ .run = pass_walk, .post = pass_infer_types },
313
 	{ .run = pass_walk, .post = pass_infer_types },
361
 	{ .run = pass_walk, .post = pass_infer_types },
314
 	{ .run = pass_walk, .post = pass_validate_types },
362
 	{ .run = pass_walk, .post = pass_validate_types },
363
+	{ .run = pass_walk, .post = pass_rewrite_ast },
315
 
364
 
316
 	{ NULL }
365
 	{ NULL }
317
 };
366
 };
338
 
387
 
339
 	printf("\n\n-- globals\n");
388
 	printf("\n\n-- globals\n");
340
 	symtab_dump(ctx->globals, stdout);
389
 	symtab_dump(ctx->globals, stdout);
390
+
391
+	if (err)
392
+		printf("ERR: %d\n", err);
393
+
341
 	return err;
394
 	return err;
342
 }
395
 }

+ 2 - 1
ply.h

29
 struct provider {
29
 struct provider {
30
 	const char *name;
30
 	const char *name;
31
 
31
 
32
-	int (*resolve)(prog_t *, node_t *);
33
 	int (*probe)(prog_t *);
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
 void provider_register(provider_t *prov);
37
 void provider_register(provider_t *prov);

+ 44 - 0
type.c

1
 #include <assert.h>
1
 #include <assert.h>
2
 #include <stdio.h>
2
 #include <stdio.h>
3
 #include <stdlib.h>
3
 #include <stdlib.h>
4
+#include <string.h>
4
 
5
 
5
 #include "type.h"
6
 #include "type.h"
6
 
7
 
198
 	return t;
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
 int type_equal(type_t *a, type_t *b)
210
 int type_equal(type_t *a, type_t *b)
202
 {
211
 {
203
 	/* TODO */
212
 	/* TODO */
204
 	return a == b;
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
 void type_size_set_sou(type_t *t)
251
 void type_size_set_sou(type_t *t)
208
 {
252
 {
209
 	field_t *f;
253
 	field_t *f;

+ 6 - 1
type.h

34
 	char *name;
34
 	char *name;
35
 	type_t *type;
35
 	type_t *type;
36
 	size_t offset;
36
 	size_t offset;
37
+
38
+	/* function arguments */
39
+	int optional:1;
37
 } field_t;
40
 } field_t;
38
 
41
 
39
 struct t_sou {
42
 struct t_sou {
92
 type_t *type_map_of(type_t *ktype, type_t *vtype);
95
 type_t *type_map_of(type_t *ktype, type_t *vtype);
93
 type_t *type_ptr_of(type_t *type);
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
 int type_add(type_t *t);
101
 int type_add(type_t *t);
97
 int type_add_list(type_t **ts);
102
 int type_add_list(type_t **ts);
98
 
103