Parcourir la Source

drink the LISP koolaid

Tobias Waldekranz.com il y a 8 ans
Parent
commit
a721c3bd2b
8 fichiers modifiés avec 292 ajouts et 180 suppressions
  1. 7 0
      arch-x86_64.c
  2. 1 0
      arch.h
  3. 85 1
      global.c
  4. 4 8
      kprobe.c
  5. 76 86
      node.c
  6. 73 56
      node.h
  7. 22 27
      ply.c
  8. 24 2
      type.c

+ 7 - 0
arch-x86_64.c

@@ -68,6 +68,13 @@ type_t t_pt_regs = {
68 68
 	},
69 69
 };
70 70
 
71
+type_t t_pt_regsp = {
72
+	.ttype = T_POINTER,
73
+	.t.pointer = {
74
+		.type = &t_pt_regs,
75
+	}
76
+};
77
+
71 78
 type_t *arch_types[] = {
72 79
 	&t_s8, &t_s8p, &t_u8, &t_u8p,
73 80
 	&t_s16, &t_s16p, &t_u16, &t_u16p,

+ 1 - 0
arch.h

@@ -24,5 +24,6 @@ extern type_t t_u64;
24 24
 extern type_t t_u64p;
25 25
 
26 26
 extern type_t t_pt_regs;
27
+extern type_t t_pt_regsp;
27 28
 
28 29
 #endif	/* _PLY_ARCH_H */

+ 85 - 1
global.c

@@ -1,8 +1,92 @@
1
+#include <errno.h>
2
+#include <string.h>
3
+
1 4
 #include "ply.h"
2 5
 
6
+/* pid */
7
+
8
+type_t t_pid_t = {
9
+	.ttype = T_TYPEDEF,
10
+
11
+	.t.tdef = {
12
+		.name = "__ply_pid_t",
13
+		.type = &t_u32,
14
+	},
15
+};
16
+
17
+type_t t_pid_func = {
18
+	.ttype = T_FUNC,
19
+
20
+	.t.func = {
21
+		.name = "pid",
22
+		.type = &t_pid_t,
23
+		.args = NULL,
24
+	},
25
+};
26
+
27
+type_t *ts_pid[] = { &t_pid_t, &t_pid_func, NULL };
28
+
29
+
30
+/* quantize */
31
+
32
+type_t t_u64_64 = {
33
+	.ttype = T_ARRAY,
34
+	.t.array = {
35
+		.type = &t_u64,
36
+		.len = 64,
37
+	},
38
+};
39
+
40
+type_t t_quantize_t = {
41
+	.ttype = T_TYPEDEF,
42
+
43
+	.t.tdef = {
44
+		.name = "__ply_quantize_t",
45
+		.type = &t_u64_64,
46
+	},
47
+};
48
+
49
+field_t f_quantize_args[] = {
50
+	{ .type = &t_s64 },
51
+	{ .type = NULL }
52
+};
53
+
54
+type_t t_quantize_func = {
55
+	.ttype = T_FUNC,
56
+
57
+	.t.func = {
58
+		.name = "quantize",
59
+		.type = &t_quantize_t,
60
+		.args = f_quantize_args,
61
+	},
62
+};
63
+
64
+type_t *ts_quantize[] = { &t_u64_64, &t_quantize_t, &t_quantize_func, NULL };
65
+
3 66
 int global_resolve(prog_t *prog, node_t *n)
4 67
 {
5
-	return 0;
68
+	type_t **ts = NULL;
69
+	type_t *t;
70
+	int err;
71
+
72
+	if (!strcmp(n->ident, "pid")) {
73
+		ts = ts_pid;
74
+		t = &t_pid_func;
75
+	} else if (!strcmp(n->ident, "quantize")) {
76
+		ts = ts_quantize;
77
+		t = &t_quantize_func;
78
+	} else {
79
+		return -ENOENT;
80
+	}
81
+
82
+	if (ts) {
83
+		err = type_add_list(ts);
84
+		if (err)
85
+			return err;
86
+	}
87
+
88
+	n->type = t;
89
+	return sym_add(prog->locals, n->ident, t);
6 90
 }
7 91
 
8 92
 int global_probe(prog_t *prog)

+ 4 - 8
kprobe.c

@@ -19,21 +19,17 @@ static inline int is_arg(const char *name)
19 19
 
20 20
 int kprobe_resolve(prog_t *prog, node_t *n)
21 21
 {
22
-	struct kprobe *kp = prog->provider_data;
23 22
 	type_t *t;
24
-	char *name;
25 23
 
26
-	name = n->atom.ident;
27
-
28
-	if (is_arg(name))
24
+	if (is_arg(n->ident))
29 25
 		t = &t_ul;
30
-	else if (!strcmp(name, "ctx"))
31
-		t = &t_pt_regs;
26
+	else if (!strcmp(n->ident, "ctx"))
27
+		t = &t_pt_regsp;
32 28
 	else
33 29
 		return -ENOENT;
34 30
 
35 31
 	n->type = t;
36
-	return sym_add(prog->locals, name, t);
32
+	return sym_add(prog->locals, n->ident, t);
37 33
 }
38 34
 
39 35
 int kprobe_probe(prog_t *prog)

+ 76 - 86
node.c

@@ -6,98 +6,84 @@
6 6
 
7 7
 #include "node.h"
8 8
 
9
-void node_print_atom(node_t *n, FILE *fp)
9
+void nprint(node_t *n, FILE *fp)
10 10
 {
11
-	switch (n->atom.atype) {
12
-	case A_IDENT:
13
-		fputs(n->atom.ident, fp);
11
+	switch (n->ntype) {
12
+	case N_CONS:
13
+		fputs("<CONS>", fp);
14
+		break;
15
+	case N_OP:
16
+		fputc(n->op, fp);
17
+		break;
18
+	case N_IDENT:
19
+		fputs(n->ident, fp);
14 20
 		break;
15
-	case A_NUM:
16
-		fprintf(fp, "%#"PRIx64, n->atom.num);
21
+	case N_NUM:
22
+		fprintf(fp, "%#"PRIx64, n->num);
17 23
 		break;
18
-	case A_STRING:
19
-		fprintf(fp, "\"%s\"", n->atom.string);
24
+	case N_STRING:
25
+		fprintf(fp, "\"%s\"", n->string);
20 26
 		break;
21 27
 
22 28
 	default:
23
-		fputs("INVALID_ATOM", fp);
29
+		fputs("<INVALID>", fp);
24 30
 	}
25 31
 }
26 32
 
27
-void node_print_expr(node_t *n, FILE *fp)
33
+int __node_dump_pre(node_t *n, void *_info)
28 34
 {
29
-	if (!isprint(n->expr.etype)) {
30
-		fputs("INVALID_EXPR", fp);
31
-		return;
32
-	}
35
+	ndump_info_t *info = _info;
33 36
 
34
-	fputc(n->expr.etype, fp);
35
-}
36
-
37
-void node_print(node_t *n, FILE *fp)
38
-{
39 37
 	switch (n->ntype) {
40
-	case N_ATOM:
41
-		node_print_atom(n, fp);
42
-		break;
43
-	case N_EXPR:
44
-		node_print_expr(n, fp);
38
+	case N_CONS:
39
+		info->indent += 2;
45 40
 		break;
46 41
 
47 42
 	default:
48
-		fputs("INVALID_NODE", fp);
43
+		fprintf(info->fp, "%*s", info->indent, "");
44
+		nprint(n, info->fp);
45
+		fputc('\n', info->fp);
49 46
 	}
50
-}
51
-
52
-int __node_dump_pre(node_t *n, void *_info)
53
-{
54
-	node_dump_info_t *info = _info;
55
-
56
-	fprintf(info->fp, "%*s", info->indent, "");
57
-	node_print(n, info->fp);
58
-	fputc('\n', info->fp);
59 47
 
60
-	if (n->ntype == N_EXPR) {
61
-		info->indent += 2;
62
-	}
63 48
 	return 0;
64 49
 }
65 50
 
66 51
 int __node_dump_post(node_t *n, void *_info)
67 52
 {
68
-	node_dump_info_t *info = _info;
53
+	ndump_info_t *info = _info;
69 54
 	node_t *next;
70 55
 
71
-	if (n->ntype == N_EXPR)
56
+	if (n->ntype == N_CONS)
72 57
 		info->indent -= 2;
73 58
 
74 59
 	return 0;
75 60
 }
76 61
 
77
-void node_dump(node_t *n, node_dump_info_t *info)
62
+void ndump(node_t *n, ndump_info_t *info)
78 63
 {
79 64
 
80
-	node_walk(n, __node_dump_pre, __node_dump_post, info);
65
+	nwalk(n, __node_dump_pre, __node_dump_post, info);
81 66
 }
82 67
 
83
-int node_walk(node_t *n,
84
-	      int (*pre)(node_t *, void *),
85
-	      int (*post)(node_t *, void *),
86
-	      void *ctx)
68
+
69
+int nwalk(node_t *n,
70
+	  int (*pre)(node_t *, void *),
71
+	  int (*post)(node_t *, void *),
72
+	  void *ctx)
87 73
 {
88 74
 	int err = 0;
89 75
 	
90 76
 	if (pre && (err = pre(n, ctx)))
91 77
 		return err;
92 78
 
93
-	if (n->ntype == N_EXPR) {
94
-		node_t *a = n->expr.arg;
79
+	if (n->ntype == N_CONS) {
80
+		err = ncar(n) ? nwalk(ncar(n), pre, post, ctx) : 0;
81
+		if (err)
82
+			return err;
95 83
 
96
-		for (a = n->expr.arg; a; a = a->next) {
97
-			err = node_walk(a, pre, post, ctx);
98
-			if (err)
99
-				return err;
100
-		}
84
+		err = ncdr(n) ? nwalk(ncdr(n), pre, post, ctx) : 0;
85
+		if (err)
86
+			return err;
101 87
 	}
102 88
 
103 89
 	if (post && (err = post(n, ctx)))
@@ -106,6 +92,21 @@ int node_walk(node_t *n,
106 92
 	return 0;
107 93
 }
108 94
 
95
+
96
+/* high-level constructors */
97
+
98
+node_t *ncall(char *name, node_t *args)
99
+{
100
+	return ncons(nop('('), ncons(nident(name), args));
101
+}
102
+
103
+node_t *nmap(char *name, node_t *key)
104
+{
105
+	return ncons(nop('{'), ncons(nident(name), key));
106
+}
107
+
108
+/* basic constructors */
109
+
109 110
 static node_t *__node(ntype_t ntype)
110 111
 {
111 112
 	node_t *n = calloc(1, sizeof(*n));
@@ -115,56 +116,45 @@ static node_t *__node(ntype_t ntype)
115 116
 	return n;
116 117
 }
117 118
 
118
-node_t *node_ident(char *name)
119
+node_t *ncons(node_t *car, node_t *cdr)
119 120
 {
120
-	node_t *n = __node(N_ATOM);
121
+	node_t *n = __node(N_CONS);
122
+
123
+	assert(car);
124
+	car->up = n;
121 125
 
122
-	n->atom.atype = A_IDENT;
123
-	n->atom.ident = name;
126
+	if (cdr)
127
+		cdr->up = n;
128
+
129
+	n->cons.car = car;
130
+	n->cons.cdr = cdr;
124 131
 	return n;
125 132
 }
126 133
 
127
-node_t *node_num(int64_t num)
134
+node_t *nop(op_t op)
128 135
 {
129
-	node_t *n = __node(N_ATOM);
130
-
131
-	n->atom.atype = A_NUM;
132
-	n->atom.num = num;
136
+	node_t *n = __node(N_OP);
137
+	n->op = op;
133 138
 	return n;
134 139
 }
135 140
 
136
-node_t *node_string(char *string)
141
+node_t *nident(char *name)
137 142
 {
138
-	node_t *n = __node(N_ATOM);
139
-
140
-	n->atom.atype = A_STRING;
141
-	n->atom.string = string;
143
+	node_t *n = __node(N_IDENT);
144
+	n->ident = name;
142 145
 	return n;
143 146
 }
144 147
 
145
-node_t *node_expr(etype_t etype, node_t *arg)
148
+node_t *nnum(int64_t num)
146 149
 {
147
-	node_t *n = __node(N_EXPR);
148
-	node_t *next;
149
-
150
-	n->expr.etype = etype;
151
-	n->expr.arg = arg;
152
-
153
-	for (next = arg; next; next = next->next)
154
-		next->up = n;
155
-
150
+	node_t *n = __node(N_NUM);
151
+	n->num = num;
156 152
 	return n;
157 153
 }
158 154
 
159
-node_t *node_cons(node_t *head, node_t *tail)
155
+node_t *nstring(char *string)
160 156
 {
161
-	node_t *next;
162
-
163
-	assert(!head->next);
164
-	head->next = tail;
165
-
166
-	for (next = tail; next; next = next->next)
167
-		next->up = head->up;
168
-
169
-	return head;
157
+	node_t *n = __node(N_STRING);
158
+	n->string = string;
159
+	return n;
170 160
 }

+ 73 - 56
node.h

@@ -6,85 +6,102 @@
6 6
 
7 7
 #include "type.h"
8 8
 
9
-typedef struct atom atom_t;
10
-typedef struct expr expr_t;
11 9
 typedef struct node node_t;
12 10
 
13
-typedef enum atype {
14
-	A_INVALID,
15
-	A_IDENT,
16
-	A_NUM,
17
-	A_STRING,
18
-} atype_t;
19
-
20
-struct atom {
21
-	atype_t atype;
22
-
23
-	union {
24
-		char *ident;
25
-		int64_t num;
26
-		char *string;
27
-	};
11
+struct cons {
12
+	node_t *car;
13
+	node_t *cdr;
28 14
 };
29 15
 
30
-typedef enum etype {
31
-	E_INVALID = '\0',
32
-
33
-	E_AGG = '@',
34
-	E_CALL = '(',
35
-	E_DEREF = '*',
36
-	E_DOT = '.',
37
-	E_MAP = 'm',
38
-	E_SCOPE = '{',
39
-	
40
-} etype_t;
41
-
42
-struct expr {
43
-	etype_t etype;
44
-	node_t *arg;
45
-};
16
+typedef enum op {
17
+	OP_AGG = '@',
18
+	OP_CALL = '(',
19
+	OP_DEREF = '*',
20
+	OP_DOT = '.',
21
+	OP_MAP = '{',
22
+} op_t;
46 23
 
47 24
 typedef enum ntype {
48
-	N_INVALID,
49
-	N_ATOM,
50
-	N_EXPR,
25
+	N_CONS,
26
+
27
+	N_OP,
28
+	N_IDENT,
29
+	N_NUM,
30
+	N_STRING,
51 31
 } ntype_t;
52 32
 
53 33
 struct node {
54 34
 	ntype_t ntype;
55
-	node_t *up;
56
-	node_t *next;
57
-
58
-	type_t *type;
59 35
 
60 36
 	union {
61
-		atom_t atom;
62
-		expr_t expr;
37
+		/* atom_t atom; */
38
+		struct cons cons;
39
+
40
+		op_t op;
41
+		char *ident;
42
+		int64_t num;
43
+		char *string;
63 44
 	};
45
+
46
+	node_t *up;
47
+	type_t *type;
64 48
 };
65 49
 
66
-/* walk a node tree */
50
+/* debug */
51
+typedef struct ndump_info {
52
+	FILE *fp;
53
+	int indent;
54
+} ndump_info_t;
55
+
56
+void ndump(node_t *n, ndump_info_t *info);
57
+
67 58
 
68 59
 typedef int (*walk_fn)(node_t *, void *);
69
-int node_walk(node_t *n, walk_fn pre, walk_fn post, void *ctx);
60
+int nwalk(node_t *n, walk_fn pre, walk_fn post, void *ctx);
70 61
 
62
+/* high-level constructors */
63
+node_t *ncall(char *name, node_t *args);
64
+node_t *nmap (char *name, node_t *key);
71 65
 
72
-/* node constructors */
73 66
 
74
-node_t *node_ident (char *name);
75
-node_t *node_num   (int64_t num);
76
-node_t *node_string(char *string);
77
-node_t *node_expr  (etype_t etype, node_t *arg);
78
-node_t *node_cons  (node_t *head, node_t *tail);
67
+/* basic constructors */
68
+node_t *ncons  (node_t *car, node_t *cdr);
69
+node_t *nop    (op_t op);
70
+node_t *nident (char *name);
71
+node_t *nnum   (int64_t num);
72
+node_t *nstring(char *string);
79 73
 
80 74
 
81
-/* debug */
75
+/* utilities */
82 76
 
83
-typedef struct node_dump_info {
84
-	FILE *fp;
85
-	int indent;
86
-} node_dump_info_t;
77
+static inline int nop_is(node_t *n, op_t op)
78
+{
79
+	if (!n || (n->ntype != N_OP))
80
+		return 0;
81
+
82
+	return n->op == op;
83
+}
84
+
85
+static inline node_t *ncar(node_t *n)
86
+{
87
+	if (!n || (n->ntype != N_CONS))
88
+		return NULL;
89
+
90
+	return n->cons.car;
91
+}
92
+
93
+static inline node_t *ncdr(node_t *n)
94
+{
95
+	if (!n || (n->ntype != N_CONS))
96
+		return NULL;
97
+
98
+	return n->cons.cdr;
99
+}
100
+
101
+static inline node_t *nup(node_t *n)
102
+{
87 103
 
88
-void node_dump(node_t *n, node_dump_info_t *info);
104
+	return n? n->up : NULL;
105
+}
89 106
 
90 107
 #endif	/* _PLY_NODE_H */

+ 22 - 27
ply.c

@@ -58,21 +58,11 @@ prog_t *prog_get(void)
58 58
 
59 59
 	prog->probe = "k:SyS_read"; /* { reads{pid()} @ quantize(arg2) } */
60 60
 	prog->ast =
61
-		node_expr('@',
62
-			  node_cons(
63
-				  node_expr('m',
64
-					    node_cons(
65
-						    node_ident("reads"),
66
-						    node_expr('(', node_ident("pid"))
67
-						    )
68
-					  ),
69
-				  node_expr('(',
70
-					    node_cons(
71
-						    node_ident("quantize"),
72
-						    node_ident("arg2")
73
-						    )
74
-					  )
75
-				  )
61
+		ncons(nop('@'),
62
+		      ncons(
63
+			      nmap("reads", ncons(ncall("pid", NULL), NULL)),
64
+			      ncall("quantize", ncons(nident("arg2"), NULL))
65
+			      )
76 66
 			);
77 67
 
78 68
 	prog->provider = provider_get("k");
@@ -84,28 +74,33 @@ int symtab_populate(node_t *n, void *_prog)
84 74
 {
85 75
 	prog_t *prog = _prog;
86 76
 	provider_t *global = provider_get(":");
77
+	node_t *op;
87 78
 	int err;
88 79
 
89
-	if ((n->ntype != N_ATOM) || (n->atom.atype != A_IDENT))
80
+	if (n->ntype != N_IDENT)
90 81
 		return 0;
91 82
 
92 83
 	/* .IDENT/->IDENT is a struct/union member, skip */
93
-	if (n->up
94
-	    && (n->up->ntype == N_EXPR)
95
-	    && ((n->up->expr.etype == E_DOT) || (n->up->expr.etype == E_DEREF))
96
-	    && (n != n->up->expr.arg))
84
+	op = ncar(nup(nup(n)));
85
+	if (op && nop_is(op, '.'))
97 86
 		return 0;
98 87
 
99 88
 	err = prog->provider->resolve(prog, n);
100
-	if (!err || err != -ENOENT)
89
+	if (!err || (err != -ENOENT))
101 90
 		return err;
102 91
 
103
-	return global->resolve(prog, n);
92
+	err = global->resolve(prog, n);
93
+	if (!err || (err != -ENOENT))
94
+		return err;
95
+
96
+	/* neither provider identifier nor global ditto => user
97
+	 * variable, add it as a global symbol of unknown type. */
98
+	return sym_add(prog->globals, n->ident, NULL);
104 99
 }
105 100
 
106 101
 int pass_walk(pass_t *pass, prog_t *prog)
107 102
 {
108
-	return node_walk(prog->ast, pass->pre, pass->post, prog);
103
+	return nwalk(prog->ast, pass->pre, pass->post, prog);
109 104
 }
110 105
 
111 106
 pass_t passes[] = {
@@ -116,7 +111,7 @@ pass_t passes[] = {
116 111
 
117 112
 int main(void)
118 113
 {
119
-	node_dump_info_t info = {
114
+	ndump_info_t info = {
120 115
 		.indent = 2,
121 116
 		.fp = stdout,
122 117
 	};
@@ -132,12 +127,12 @@ int main(void)
132 127
 	}
133 128
 
134 129
 	printf("AST\n===\n");
135
-	node_dump(prog->ast, &info);
130
+	ndump(prog->ast, &info);
136 131
 	printf("\nLOCALS\n======\n");
137 132
 	symtab_dump(prog->locals, stdout);
138 133
 	printf("\nGLOBALS\n=======\n");
139 134
 	symtab_dump(prog->globals, stdout);
140
-	printf("\nTYPES\n=====\n");
141
-	types_dump_cdecl(stdout);
135
+	/* printf("\nTYPES\n=====\n"); */
136
+	/* types_dump_cdecl(stdout); */
142 137
 	return err;
143 138
 }

+ 24 - 2
type.c

@@ -65,7 +65,12 @@ void type_dump_func(type_t *t, FILE *fp)
65 65
 	field_t *arg;
66 66
 
67 67
 	type_dump(t->t.func.type, fp);
68
-	fprintf(fp, " (*%s)(", t->t.func.name);
68
+	fprintf(fp, " (*%s)(", t->t.func.name ? : "");
69
+
70
+	if (!t->t.func.args) {
71
+		fputs("void)", fp);
72
+		return;
73
+	}
69 74
 
70 75
 	for (arg = t->t.func.args; arg->type; arg++) {
71 76
 		if (arg != t->t.func.args)
@@ -79,6 +84,11 @@ void type_dump_func(type_t *t, FILE *fp)
79 84
 
80 85
 void type_dump(type_t *t, FILE *fp)
81 86
 {
87
+	if (!t) {
88
+		fputs("<NONE>", fp);
89
+		return;
90
+	}
91
+
82 92
 	switch (t->ttype){
83 93
 	case T_TYPEDEF:
84 94
 		fputs(t->t.tdef.name, fp);
@@ -228,13 +238,25 @@ void type_size_set(type_t *t)
228 238
 	}
229 239
 }
230 240
 
241
+int type_cmp(const void *_a, const void *_b)
242
+{
243
+	const type_t *a = *((type_t **)_a);
244
+	const type_t *b = *((type_t **)_b);
245
+
246
+	return a - b;
247
+}
231 248
 
232 249
 int type_add(type_t *t)
233 250
 {
251
+	if (bsearch(t, types.type, types.len, sizeof(*types.type), type_cmp))
252
+		return 0;
253
+
254
+	type_size_set(t);
255
+
234 256
 	types.type = realloc(types.type, ++types.len * sizeof(*types.type));
235 257
 	types.type[types.len - 1] = t;
258
+	qsort(types.type, types.len, sizeof(*types.type), type_cmp);
236 259
 
237
-	type_size_set(t);
238 260
 	return 0;
239 261
 }
240 262