Tobias Waldekranz.com 8 anni fa
parent
commit
f2acf454e5
12 ha cambiato i file con 603 aggiunte e 224 eliminazioni
  1. 6 1
      Makefile
  2. 87 0
      arch-x86_64.c
  3. 28 0
      arch.h
  4. 24 0
      global.c
  5. 61 0
      kprobe.c
  6. 3 2
      node.h
  7. 72 36
      ply.c
  8. 34 0
      ply.h
  9. 7 12
      sym.c
  10. 2 2
      sym.h
  11. 198 88
      type.c
  12. 81 83
      type.h

+ 6 - 1
Makefile

@@ -1,3 +1,8 @@
1 1
 CFLAGS ?= -Wall -Wextra -Werror -Wno-unused -O0 -g
2 2
 
3
-ply: node.o type.o sym.o
3
+objs := $(patsubst %.c,%.o,$(wildcard *.c))
4
+headers := $(wildcard *.c)
5
+
6
+$(objs): $(headers)
7
+
8
+ply: $(objs)

+ 87 - 0
arch-x86_64.c

@@ -0,0 +1,87 @@
1
+#include <assert.h>
2
+#include <linux/ptrace.h>
3
+
4
+#include "type.h"
5
+
6
+#define arch_typedef(_a, _t) {					\
7
+		.ttype = T_TYPEDEF,				\
8
+		.t = { .tdef = { .name = #_a, .type = _t } },	\
9
+	}
10
+
11
+#define arch_pointer(_t) {					\
12
+		.ttype = T_POINTER,				\
13
+		.t = { .pointer = { .type = _t } },		\
14
+	}
15
+
16
+type_t t_s8 = arch_typedef(s8, &t_c);
17
+type_t t_s8p = arch_pointer(&t_s8);
18
+type_t t_u8 = arch_typedef(u8, &t_uc);
19
+type_t t_u8p = arch_pointer(&t_u8);
20
+
21
+type_t t_s16 = arch_typedef(s16, &t_s);
22
+type_t t_s16p = arch_pointer(&t_s16);
23
+type_t t_u16 = arch_typedef(u16, &t_us);
24
+type_t t_u16p = arch_pointer(&t_u16);
25
+
26
+type_t t_s32 = arch_typedef(s32, &t_i);
27
+type_t t_s32p = arch_pointer(&t_s32);
28
+type_t t_u32 = arch_typedef(u32, &t_ui);
29
+type_t t_u32p = arch_pointer(&t_u32);
30
+
31
+type_t t_s64 = arch_typedef(s64, &t_l);
32
+type_t t_s64p = arch_pointer(&t_s64);
33
+type_t t_u64 = arch_typedef(u64, &t_ul);
34
+type_t t_u64p = arch_pointer(&t_u64);
35
+
36
+field_t f_pt_regs_fields[] = {
37
+	{ .name = "r15",      .type = &t_ul },
38
+	{ .name = "r14",      .type = &t_ul },
39
+	{ .name = "r13",      .type = &t_ul },
40
+	{ .name = "r12",      .type = &t_ul },
41
+	{ .name = "rbp",      .type = &t_ul },
42
+	{ .name = "rbx",      .type = &t_ul },
43
+	{ .name = "r11",      .type = &t_ul },
44
+	{ .name = "r10",      .type = &t_ul },
45
+	{ .name = "r9",       .type = &t_ul },
46
+	{ .name = "r8",       .type = &t_ul },
47
+	{ .name = "rax",      .type = &t_ul },
48
+	{ .name = "rcx",      .type = &t_ul },
49
+	{ .name = "rdx",      .type = &t_ul },
50
+	{ .name = "rsi",      .type = &t_ul },
51
+	{ .name = "rdi",      .type = &t_ul },
52
+	{ .name = "orig_rax", .type = &t_ul },
53
+	{ .name = "rip",      .type = &t_ul },
54
+	{ .name = "cs",       .type = &t_ul },
55
+	{ .name = "eflags",   .type = &t_ul },
56
+	{ .name = "rsp",      .type = &t_ul },
57
+	{ .name = "ss",       .type = &t_ul },
58
+
59
+	{ .type = NULL }
60
+};
61
+
62
+type_t t_pt_regs = {
63
+	.ttype = T_STRUCT,
64
+
65
+	.t.sou = {
66
+		.name = "pt_regs",
67
+		.fields = f_pt_regs_fields,
68
+	},
69
+};
70
+
71
+type_t *arch_types[] = {
72
+	&t_s8, &t_s8p, &t_u8, &t_u8p,
73
+	&t_s16, &t_s16p, &t_u16, &t_u16p,
74
+	&t_s32, &t_s32p, &t_u32, &t_u32p,
75
+	&t_s64, &t_s64p, &t_u64, &t_u64p,
76
+	&t_pt_regs,
77
+
78
+	NULL
79
+};
80
+
81
+__attribute__((constructor))
82
+static void arch_init(void)
83
+{
84
+	type_add_list(arch_types);
85
+
86
+	assert(t_pt_regs.size == sizeof(struct pt_regs));
87
+}

+ 28 - 0
arch.h

@@ -0,0 +1,28 @@
1
+#ifndef _PLY_ARCH_H
2
+#define _PLY_ARCH_H
3
+
4
+#include "type.h"
5
+
6
+extern type_t t_s8;
7
+extern type_t t_s8p;
8
+extern type_t t_u8;
9
+extern type_t t_u8p;
10
+
11
+extern type_t t_s16;
12
+extern type_t t_s16p;
13
+extern type_t t_u16;
14
+extern type_t t_u16p;
15
+
16
+extern type_t t_s32;
17
+extern type_t t_s32p;
18
+extern type_t t_u32;
19
+extern type_t t_u32p;
20
+
21
+extern type_t t_s64;
22
+extern type_t t_s64p;
23
+extern type_t t_u64;
24
+extern type_t t_u64p;
25
+
26
+extern type_t t_pt_regs;
27
+
28
+#endif	/* _PLY_ARCH_H */

+ 24 - 0
global.c

@@ -0,0 +1,24 @@
1
+#include "ply.h"
2
+
3
+int global_resolve(prog_t *prog, node_t *n)
4
+{
5
+	return 0;
6
+}
7
+
8
+int global_probe(prog_t *prog)
9
+{
10
+	return 0;
11
+}
12
+
13
+provider_t global = {
14
+	.name = ":",
15
+
16
+	.resolve = global_resolve,
17
+	.probe = global_probe,
18
+};
19
+
20
+__attribute__((constructor))
21
+static void global_init(void)
22
+{
23
+	provider_register(&global);
24
+}

+ 61 - 0
kprobe.c

@@ -0,0 +1,61 @@
1
+#include <assert.h>
2
+#include <errno.h>
3
+#include <stdlib.h>
4
+#include <string.h>
5
+
6
+#include <linux/ptrace.h>
7
+
8
+#include "ply.h"
9
+
10
+struct kprobe {
11
+};
12
+
13
+static inline int is_arg(const char *name)
14
+{
15
+	return (strstr(name, "arg") == name)
16
+		&& (strlen(name) == 4)
17
+		&& (name[3] >= '0' && name[3] <= '9');
18
+}
19
+
20
+int kprobe_resolve(prog_t *prog, node_t *n)
21
+{
22
+	struct kprobe *kp = prog->provider_data;
23
+	type_t *t;
24
+	char *name;
25
+
26
+	name = n->atom.ident;
27
+
28
+	if (is_arg(name))
29
+		t = &t_ul;
30
+	else if (!strcmp(name, "ctx"))
31
+		t = &t_pt_regs;
32
+	else
33
+		return -ENOENT;
34
+
35
+	n->type = t;
36
+	return sym_add(prog->locals, name, t);
37
+}
38
+
39
+int kprobe_probe(prog_t *prog)
40
+{
41
+	struct kprobe *kp;
42
+
43
+	kp = calloc(1, sizeof(*kp));
44
+	assert(kp);
45
+
46
+	prog->provider_data = kp;
47
+	return 0;
48
+}
49
+
50
+provider_t kprobe = {
51
+	.name = "kprobe",
52
+
53
+	.resolve = kprobe_resolve,
54
+	.probe = kprobe_probe,
55
+};
56
+
57
+__attribute__((constructor))
58
+static void kprobe_init(void)
59
+{
60
+	provider_register(&kprobe);
61
+}

+ 3 - 2
node.h

@@ -2,8 +2,9 @@
2 2
 #define _PLY_NODE_H
3 3
 
4 4
 #include <stdint.h>
5
+#include <stdio.h>
5 6
 
6
-typedef struct sym sym_t;
7
+#include "type.h"
7 8
 
8 9
 typedef struct atom atom_t;
9 10
 typedef struct expr expr_t;
@@ -54,7 +55,7 @@ struct node {
54 55
 	node_t *up;
55 56
 	node_t *next;
56 57
 
57
-	sym_t *sym;
58
+	type_t *type;
58 59
 
59 60
 	union {
60 61
 		atom_t atom;

+ 72 - 36
ply.c

@@ -1,38 +1,63 @@
1
+#include <assert.h>
2
+#include <errno.h>
1 3
 #include <stdio.h>
2 4
 #include <stdlib.h>
5
+#include <string.h>
3 6
 
4
-#include "node.h"
5
-#include "sym.h"
7
+#include "ply.h"
6 8
 
7
-typedef struct pass {
8
-	int (*run)(void *);
9
+struct providers {
10
+	provider_t **prov;
11
+	size_t len;
12
+} providers;
13
+
14
+provider_t *provider_get(const char *name)
15
+{
16
+	size_t i;
17
+
18
+	for (i = 0; i < providers.len; i++) {
19
+		if (strstr(providers.prov[i]->name, name)
20
+		    == providers.prov[i]->name)
21
+			return providers.prov[i];
22
+	}
23
+
24
+	return NULL;
25
+}
26
+
27
+void provider_register(provider_t *prov)
28
+{
29
+	assert(prov);
30
+	assert(prov->probe);
31
+	assert(prov->resolve);
32
+
33
+	providers.prov = realloc(providers.prov,
34
+				 ++providers.len * sizeof(*providers.prov));
35
+
36
+	providers.prov[providers.len - 1] = prov;
37
+}
38
+
39
+typedef struct pass pass_t;
40
+struct pass {
41
+	int (*run)(pass_t *, prog_t *);
9 42
 	walk_fn pre;
10 43
 	walk_fn post;
11
-} pass_t;
12
-
13
-typedef struct provider {
14
-	
15
-} provider_t;
44
+};
16 45
 
17
-typedef struct prog {
18
-	const char *probe;
19
-	provider_t *prov;
20
-	node_t *ast;
21
-	symtab_t *st;
22
-} prog_t;
23 46
 
24
-symtab_t symbols = { .sym = NULL, .len = 0 };
47
+symtab_t globals = { .sym = NULL, .len = 0 };
48
+symtab_t locals = { .sym = NULL, .len = 0 };
25 49
 
26 50
 prog_t *prog_get(void)
27 51
 {
28
-	prog_t *p;
52
+	prog_t *prog;
29 53
 
30
-	p = calloc(1, sizeof(*p));
54
+	prog = calloc(1, sizeof(*prog));
31 55
 
32
-	p->st = &symbols,
56
+	prog->locals = &locals;
57
+	prog->globals = &globals;
33 58
 
34
-	/* reads{pid()} @ quantize(arg2) */
35
-	p->ast =
59
+	prog->probe = "k:SyS_read"; /* { reads{pid()} @ quantize(arg2) } */
60
+	prog->ast =
36 61
 		node_expr('@',
37 62
 			  node_cons(
38 63
 				  node_expr('m',
@@ -50,12 +75,16 @@ prog_t *prog_get(void)
50 75
 				  )
51 76
 			);
52 77
 
53
-	return p;
78
+	prog->provider = provider_get("k");
79
+	prog->provider->probe(prog);
80
+	return prog;
54 81
 }
55 82
 
56 83
 int symtab_populate(node_t *n, void *_prog)
57 84
 {
58 85
 	prog_t *prog = _prog;
86
+	provider_t *global = provider_get(":");
87
+	int err;
59 88
 
60 89
 	if ((n->ntype != N_ATOM) || (n->atom.atype != A_IDENT))
61 90
 		return 0;
@@ -67,19 +96,22 @@ int symtab_populate(node_t *n, void *_prog)
67 96
 	    && (n != n->up->expr.arg))
68 97
 		return 0;
69 98
 
70
-	return sym_add(prog->st, n->atom.ident, tid_none, &n->sym);
99
+	err = prog->provider->resolve(prog, n);
100
+	if (!err || err != -ENOENT)
101
+		return err;
102
+
103
+	return global->resolve(prog, n);
71 104
 }
72 105
 
73
-int symtab_resolve(void *_prog)
106
+int pass_walk(pass_t *pass, prog_t *prog)
74 107
 {
75
-	prog_t *prog = _prog;
76
-	return 0;
108
+	return node_walk(prog->ast, pass->pre, pass->post, prog);
77 109
 }
78 110
 
79 111
 pass_t passes[] = {
80
-	{ .pre = symtab_populate },
81
-	{ .run = symtab_resolve },
82
-	{ NULL, NULL, NULL }
112
+	{ .run = pass_walk, .pre = symtab_populate },
113
+
114
+	{ NULL }
83 115
 };
84 116
 
85 117
 int main(void)
@@ -89,19 +121,23 @@ int main(void)
89 121
 		.fp = stdout,
90 122
 	};
91 123
 
92
-	prog_t *p = prog_get();
124
+	prog_t *prog = prog_get();
93 125
 	pass_t *pass;
94 126
 	int err;
95 127
 
96
-	for (pass = passes; pass->run, pass->pre || pass->post; pass++) {
97
-		err = pass->run ?
98
-			pass->run(p) :
99
-			node_walk(p->ast, pass->pre, pass->post, p);
128
+	for (pass = passes; pass->run; pass++) {
129
+		err = pass->run(pass, prog);
100 130
 		if (err)
101 131
 			break;
102 132
 	}
103 133
 
104
-	node_dump(p->ast, &info);
105
-	symtab_dump(p->st, stdout);
134
+	printf("AST\n===\n");
135
+	node_dump(prog->ast, &info);
136
+	printf("\nLOCALS\n======\n");
137
+	symtab_dump(prog->locals, stdout);
138
+	printf("\nGLOBALS\n=======\n");
139
+	symtab_dump(prog->globals, stdout);
140
+	printf("\nTYPES\n=====\n");
141
+	types_dump_cdecl(stdout);
106 142
 	return err;
107 143
 }

+ 34 - 0
ply.h

@@ -0,0 +1,34 @@
1
+#ifndef _PLY_H
2
+#define _PLY_H
3
+
4
+#include "node.h"
5
+#include "sym.h"
6
+#include "type.h"
7
+#include "arch.h"
8
+
9
+typedef struct prog prog_t;
10
+typedef struct provider provider_t;
11
+
12
+struct prog {
13
+	const char *probe;
14
+	node_t *ast;
15
+
16
+	symtab_t *locals;
17
+	symtab_t *globals;
18
+
19
+	provider_t *provider;
20
+	void *provider_data;
21
+};
22
+
23
+
24
+
25
+struct provider {
26
+	const char *name;
27
+
28
+	int (*resolve)(prog_t *, node_t *);
29
+	int (*probe)(prog_t *);
30
+};
31
+
32
+void provider_register(provider_t *prov);
33
+
34
+#endif	/* _PLY_H */

+ 7 - 12
sym.c

@@ -18,20 +18,20 @@ sym_t *sym_get(symtab_t *st, const char *name)
18 18
 	return NULL;
19 19
 }
20 20
 
21
-int sym_add(symtab_t *st, const char *name, tid_t tid, sym_t **new)
21
+int sym_add(symtab_t *st, const char *name, type_t *type)
22 22
 {
23 23
 	sym_t *sym;
24 24
 
25 25
 	sym = sym_get(st, name);
26 26
 	if (sym) {
27 27
 		/* if there is no type info, accept anything */
28
-		if (!sym->tid)
29
-			sym->tid = tid;
28
+		if (!sym->type)
29
+			sym->type = type;
30 30
 		/* otherwise, if specified, it must match */
31
-		else if (tid && (sym->tid != tid))
31
+		else if (type && !type_equal(sym->type, type))
32 32
 			return -EINVAL;
33 33
 
34
-		goto found;
34
+		return 0;
35 35
 	}
36 36
 
37 37
 	st->sym = realloc(st->sym, ++st->len * sizeof(*st->sym));
@@ -39,18 +39,13 @@ int sym_add(symtab_t *st, const char *name, tid_t tid, sym_t **new)
39 39
 
40 40
 	sym = &st->sym[st->len-1];
41 41
 	sym->name = name;
42
-	sym->tid = tid;
43
-
44
-found:
45
-	if (new)
46
-		*new = sym;
47
-
42
+	sym->type = type;
48 43
 	return 0;
49 44
 }
50 45
 
51 46
 void sym_dump(sym_t *sym, FILE *fp)
52 47
 {
53
-	type_dump_cdecl(type_info(sym->tid), fp);
48
+	type_dump(sym->type, fp);
54 49
 	fputc(' ', fp);
55 50
 	fputs(sym->name, fp);
56 51
 }

+ 2 - 2
sym.h

@@ -5,7 +5,7 @@
5 5
 
6 6
 typedef struct sym {
7 7
 	const char *name;
8
-	tid_t tid;
8
+	type_t *type;
9 9
 } sym_t;
10 10
 
11 11
 typedef struct symtab {
@@ -14,7 +14,7 @@ typedef struct symtab {
14 14
 } symtab_t;
15 15
 
16 16
 sym_t *sym_get(symtab_t *st, const char *name);
17
-int    sym_add(symtab_t *st, const char *name, tid_t tid, sym_t **new);
17
+int    sym_add(symtab_t *st, const char *name, type_t *type);
18 18
 
19 19
 void sym_dump(sym_t *sym, FILE *fp);
20 20
 void symtab_dump(symtab_t *st, FILE *fp);

+ 198 - 88
type.c

@@ -4,145 +4,255 @@
4 4
 
5 5
 #include "type.h"
6 6
 
7
-const type_t builtin_types[] = {
8
-	{ .type = T_NONE },
9
-#define SCALAR(_tid, _, _type) [_tid] = {			\
10
-		.tid = _tid,					\
11
-		.size = sizeof(_type),				\
12
-		.type = T_SCALAR,				\
13
-		.t = {						\
14
-			.scalar = {				\
15
-				.name = #_type,			\
16
-			},					\
17
-		},						\
18
-	},
19
-#define POINTER(_tid, _, _base) [_tid] = {			\
20
-		.tid = _tid,					\
21
-		.size = sizeof(void *),				\
22
-		.type = T_POINTER,				\
23
-		.t = {						\
24
-			.pointer = {				\
25
-				.type = _base,			\
26
-			},					\
27
-		},						\
28
-	},
29
-BUILTIN_TYPES
30
-#undef SCALAR
31
-#undef POINTER
32
-
33
-	{ .type = T_INVALID }
34
-};
7
+#define builtin_scalar(_t) {				\
8
+		.ttype = T_SCALAR,			\
9
+		.size = sizeof(_t),			\
10
+		.t = { .scalar = { .name = #_t } },	\
11
+	}
35 12
 
36
-const type_t arch_builtin_types[] = {
37
-	{ .type = T_ALIAS, .t = { .alias = { .type = tid_c, .name = "s8" } } },
38
-	{ .type = T_ALIAS, .t = { .alias = { .type = tid_uc, .name = "u8" } } },
13
+#define builtin_pointer(_t) {				\
14
+		.ttype = T_POINTER,			\
15
+		.t = { .pointer = { .type = _t } },	\
16
+	}
39 17
 
40
-	{ .type = T_INVALID }
41
-};
18
+type_t t_v    = builtin_scalar(void);
19
+type_t t_vp   = builtin_pointer(&t_v);
20
+
21
+type_t t_c    = builtin_scalar(char);
22
+type_t t_cp   = builtin_pointer(&t_c);
23
+type_t t_uc   = builtin_scalar(unsigned char);
24
+type_t t_ucp  = builtin_pointer(&t_uc);
25
+
26
+type_t t_s    = builtin_scalar(short);
27
+type_t t_sp   = builtin_pointer(&t_s);
28
+type_t t_us   = builtin_scalar(unsigned short);
29
+type_t t_usp  = builtin_pointer(&t_us);
30
+
31
+type_t t_i    = builtin_scalar(int);
32
+type_t t_ip   = builtin_pointer(&t_i);
33
+type_t t_ui   = builtin_scalar(unsigned int);
34
+type_t t_uip  = builtin_pointer(&t_ui);
35
+
36
+type_t t_l    = builtin_scalar(long);
37
+type_t t_lp   = builtin_pointer(&t_l);
38
+type_t t_ul   = builtin_scalar(unsigned long);
39
+type_t t_ulp  = builtin_pointer(&t_ul);
40
+
41
+type_t t_ll   = builtin_scalar(long long);
42
+type_t t_llp  = builtin_pointer(&t_ll);
43
+type_t t_ull  = builtin_scalar(unsigned long long);
44
+type_t t_ullp = builtin_pointer(&t_ull);
42 45
 
43
-static types_t types = {
44
-	.types = NULL,
45
-	.next = 0,
46
+type_t *builtin_types[] = {
47
+	&t_v,  &t_vp,
48
+	&t_c,  &t_cp,  &t_uc,  &t_ucp,
49
+	&t_s,  &t_sp,  &t_us,  &t_usp,
50
+	&t_i,  &t_ip,  &t_ui,  &t_uip,
51
+	&t_l,  &t_lp,  &t_ul,  &t_ulp,
52
+	&t_ll, &t_llp, &t_ull, &t_ullp,
53
+
54
+	NULL
46 55
 };
47 56
 
48
-type_t *type_info(tid_t tid)
57
+struct type_list {
58
+	type_t **type;
59
+	size_t len;
60
+} types;
61
+
62
+
63
+void type_dump_func(type_t *t, FILE *fp)
49 64
 {
50
-	assert(tid < types.next);
51
-	return &types.types[tid];
65
+	field_t *arg;
66
+
67
+	type_dump(t->t.func.type, fp);
68
+	fprintf(fp, " (*%s)(", t->t.func.name);
69
+
70
+	for (arg = t->t.func.args; arg->type; arg++) {
71
+		if (arg != t->t.func.args)
72
+			fputs(", ", fp);
73
+
74
+		type_dump(arg->type, fp);
75
+	}
76
+
77
+	fputc(')', fp);
52 78
 }
53 79
 
54 80
 void type_dump(type_t *t, FILE *fp)
55 81
 {
56
-	switch (t->type){
57
-	case T_NONE:
58
-		fputs("<NONE>", fp);
59
-		break;
60
-	case T_ALIAS:
61
-		fputs(t->t.alias.name, fp);
82
+	switch (t->ttype){
83
+	case T_TYPEDEF:
84
+		fputs(t->t.tdef.name, fp);
62 85
 		break;
63 86
 	case T_SCALAR:
64 87
 		fputs(t->t.scalar.name, fp);
65 88
 		break;
66 89
 	case T_POINTER:
67
-		type_dump(type_info(t->t.pointer.type), fp);
90
+		type_dump(t->t.pointer.type, fp);
68 91
 		fputs(" *", fp);
69 92
 		break;
70 93
 	case T_ARRAY:
71
-		type_dump(type_info(t->t.array.type), fp);
94
+		type_dump(t->t.array.type, fp);
72 95
 		fprintf(fp, "[%zu]", t->t.array.len);
73 96
 		break;
74
-
75
-	default:
97
+	case T_STRUCT:
98
+		fputs("struct ", fp);
99
+		fputs(t->t.sou.name, fp);
100
+		break;
101
+	case T_UNION:
102
+		fputs("union ", fp);
103
+		fputs(t->t.sou.name, fp);
104
+		break;
105
+	case T_FUNC:
106
+		type_dump_func(t, fp);
107
+		break;
108
+	case T_MAP:
109
+		/* TODO */
76 110
 		assert(0);
111
+		break;
112
+	}
113
+}
114
+
115
+void type_dump_cdecl_sou(type_t *t, FILE *fp)
116
+{
117
+	field_t *f;
118
+
119
+	type_dump(t, fp);
120
+	fputs(" {\n", fp);
121
+	for (f = t->t.sou.fields; f->type; f++) {
122
+		fputc('\t', fp);
123
+		type_dump(f->type, fp);
124
+		fprintf(fp, " %s;\n", f->name);
77 125
 	}
126
+	fputs("}", fp);
78 127
 }
79 128
 
80 129
 void type_dump_cdecl(type_t *t, FILE *fp)
81 130
 {
82
-	switch (t->type) {
83
-	case T_ALIAS:
131
+	switch (t->ttype) {
132
+	case T_TYPEDEF:
84 133
 		fputs("typedef ", fp);
85
-		type_dump(type_info(t->t.alias.type), fp);
86
-		fprintf(fp, " %s", t->t.alias.name);
134
+		type_dump(t->t.tdef.type, fp);
135
+		fprintf(fp, " %s", t->t.tdef.name);
136
+		break;
137
+
138
+	case T_STRUCT:
139
+	case T_UNION:
140
+		type_dump_cdecl_sou(t, fp);
87 141
 		break;
88
-	case T_NONE:
142
+
89 143
 	case T_SCALAR:
90 144
 	case T_POINTER:
91 145
 	case T_ARRAY:
146
+	case T_MAP:
147
+	case T_FUNC:
92 148
 		type_dump(t, fp);
93 149
 		break;
94
-
95
-	default:
96
-		assert(0);
97 150
 	}
98 151
 }
99 152
 
100
-tid_t type_add(const type_t *type)
153
+void types_dump_cdecl(FILE *fp)
101 154
 {
102
-	tid_t tid = types.next++;
155
+	size_t i;
103 156
 
104
-	types.types = realloc(types.types, types.next * sizeof(type_t));
105
-	assert(types.types);
157
+	for (i = 0; i < types.len; i++) {
158
+		type_t *t = types.type[i];
106 159
 
107
-	types.types[tid] = *type;
108
-	types.types[tid].tid = tid;
109
-	return tid;
160
+		type_dump_cdecl(t, stdout);
161
+		printf(" <sz:0x%zx>\n", t->size);
162
+	}
110 163
 }
111 164
 
112
-tid_t type_add_list(const type_t *type)
165
+int type_equal(type_t *a, type_t *b)
113 166
 {
114
-	tid_t first = 0;
167
+	/* TODO */
168
+	return a == b;
169
+}
115 170
 
116
-	for (; type->type; type++) {
117
-		if (!first)
118
-			first = type_add(type);
119
-		else
120
-			type_add(type);
171
+void type_size_set_sou(type_t *t)
172
+{
173
+	field_t *f;
174
+	size_t size = 0;
175
+
176
+	if (!t->t.sou.fields)
177
+		return;
178
+
179
+	for (f = t->t.sou.fields; f->name; f++) {
180
+		/* size of all members is now known yet, abort */
181
+		if (!f->type->size)
182
+			return;
183
+
184
+		if (!t->t.sou.packed)
185
+			size += size % f->type->size;
186
+
187
+		size += f->type->size;
188
+		f->offset = size;
121 189
 	}
122 190
 
123
-	return first;
191
+	if (!t->t.sou.packed && size) {
192
+		/* align complete struct to requirements of first
193
+		 * member */
194
+		f = t->t.sou.fields;
195
+
196
+		size += size % f->type->size;
197
+	}
198
+
199
+	t->size = size;
124 200
 }
125 201
 
126
-__attribute__((constructor))
127
-static void type_init(void)
202
+void type_size_set(type_t *t)
128 203
 {
129
-	type_add_list(builtin_types);
130
-	type_add_list(arch_builtin_types);
204
+	switch (t->ttype) {
205
+	case T_TYPEDEF:
206
+		t->size = t->t.tdef.type->size;
207
+		break;
208
+	case T_STRUCT:
209
+	case T_UNION:
210
+		type_size_set_sou(t);
211
+		break;
212
+	case T_FUNC:
213
+		t->size = t->t.func.type->size;
214
+		break;
215
+	case T_SCALAR:
216
+		break;
217
+	case T_POINTER:
218
+		t->size = sizeof(void *);
219
+		break;
220
+	case T_ARRAY:
221
+		t->size = t->t.array.len * t->t.array.type->size;
222
+		break;
223
+
224
+	case T_MAP:
225
+		/* TODO */
226
+		assert(0);
227
+		break;
228
+	}
131 229
 }
132 230
 
133
-/* int main(void) */
134
-/* { */
135
-/* 	tid_t tid; */
136 231
 
137
-/* 	type_init(); */
232
+int type_add(type_t *t)
233
+{
234
+	types.type = realloc(types.type, ++types.len * sizeof(*types.type));
235
+	types.type[types.len - 1] = t;
138 236
 
139
-/* 	for (tid = 0; tid < types.next; tid++) { */
140
-/* 		type_t *t = type_info(tid); */
237
+	type_size_set(t);
238
+	return 0;
239
+}
141 240
 
142
-/* 		printf("tid:%3d sz:%2zx  ", t->tid, t->size);  */
143
-/* 		type_dump_cdecl(t, stdout); */
144
-/* 		putchar('\n'); */
145
-/* 	} */
241
+int type_add_list(type_t **ts)
242
+{
243
+	int err;
146 244
 
147
-/* 	return 0; */
148
-/* } */
245
+	for (; *ts; ts++) {
246
+		err = type_add(*ts);
247
+		if (err)
248
+			return err;
249
+	}
250
+
251
+	return 0;
252
+}
253
+
254
+__attribute__((constructor))
255
+static void type_init(void)
256
+{
257
+	type_add_list(builtin_types);
258
+}

+ 81 - 83
type.h

@@ -1,118 +1,116 @@
1 1
 #ifndef _PLY_TYPE_H
2 2
 #define _PLY_TYPE_H
3 3
 
4
-typedef unsigned int tid_t;
4
+#include <stddef.h>
5
+#include <stdio.h>
5 6
 
6
-typedef struct alias {
7
-	tid_t type;
7
+typedef struct type type_t;
8
+
9
+struct t_tdef {
8 10
 	char *name;
9
-} alias_t;
11
+	type_t *type;
12
+};
10 13
 
11
-typedef struct scalar {
14
+struct t_scalar {
12 15
 	char *name;
13
-} scalar_t;
16
+};
14 17
 
15
-typedef struct pointer {
16
-	tid_t type;
17
-} pointer_t;
18
+struct t_pointer {
19
+	type_t *type;
20
+};
18 21
 
19
-typedef struct array {
20
-	tid_t type;
22
+struct t_array {
23
+	type_t *type;
21 24
 	size_t len;
22
-} array_t;
25
+};
23 26
 
24
-typedef struct map {
25
-	tid_t type;
26
-	tid_t ktype;
27
+struct t_map {
28
+	type_t *vtype;
29
+	type_t *ktype;
27 30
 	size_t len;
28
-} map_t;
31
+};
29 32
 
30 33
 typedef struct field {
31
-	struct field *next;
32
-
33
-	tid_t type;
34
-	size_t offset;
35 34
 	char *name;
35
+	type_t *type;
36
+	size_t offset;
36 37
 } field_t;
37 38
 
38
-typedef struct sou {
39
+struct t_sou {
40
+	char *name;
41
+
42
+	int packed:1;
39 43
 	field_t *fields;
40
-} sou_t;
44
+};
45
+
46
+struct t_func {
47
+	char *name;
48
+	type_t *type;
49
+
50
+	field_t *args;
51
+};
41 52
 
42 53
 typedef enum ttype {
43
-	T_INVALID,
44
-	T_NONE,
45
-	T_ALIAS,
54
+	T_TYPEDEF,
46 55
 	T_SCALAR,
47 56
 	T_POINTER,
48 57
 	T_ARRAY,
49 58
 	T_MAP,
50
-	T_SOU,
59
+	T_STRUCT,
60
+	T_UNION,
61
+	T_FUNC,
51 62
 } ttype_t;
52 63
 
53
-typedef struct type {
54
-	tid_t tid;
55
-
64
+struct type {
56 65
 	size_t size;
57 66
 
58
-	ttype_t type;
67
+	ttype_t ttype;
59 68
 	union {
60
-		alias_t alias;
61
-		scalar_t scalar;
62
-		pointer_t pointer;
63
-		array_t array;
64
-		map_t map;
65
-		sou_t sou;
69
+		struct t_tdef tdef;
70
+		struct t_scalar scalar;
71
+		struct t_pointer pointer;
72
+		struct t_array array;
73
+		struct t_map map;
74
+		struct t_sou sou;
75
+		struct t_func func;
66 76
 	} t;
67
-} type_t;
68
-
69
-typedef struct types {
70
-	type_t *types;
71
-	tid_t next;
72
-} types_t;
73
-
74
-#define BUILTIN_TYPES				\
75
-	SCALAR(1, tid_v, void)			\
76
-	POINTER(2, tid_vp, 1)			\
77
-						\
78
-	SCALAR(3, tid_c, char)			\
79
-	POINTER(4, tid_cp, 3)			\
80
-	SCALAR(5, tid_uc, unsigned char)	\
81
-	POINTER(6, tid_ucp, 5)			\
82
-						\
83
-	SCALAR(7, tid_s, short)			\
84
-	POINTER(8, tid_sp, 7)			\
85
-	SCALAR(9, tid_us, unsigned short)	\
86
-	POINTER(10, tid_usp, 9)			\
87
-						\
88
-	SCALAR(11, tid_i, int)			\
89
-	POINTER(12, tid_ip, 11)			\
90
-	SCALAR(13, tid_ui, unsigned int)	\
91
-	POINTER(14, tid_uip, 13)		\
92
-						\
93
-	SCALAR(15, tid_l, long)			\
94
-	POINTER(16, tid_lp, 15)			\
95
-	SCALAR(17, tid_ul, unsigned long)	\
96
-	POINTER(18, tid_ulp, 17)		\
97
-						\
98
-	SCALAR(19, tid_ll, long long)		\
99
-	POINTER(20, tid_llp, 19)		\
100
-	SCALAR(21, tid_ull, unsigned long long)	\
101
-	POINTER(22, tid_ullp, 21)
102
-
103
-typedef enum builtin_type {
104
-	tid_none = 0,
105
-#define SCALAR(_tid, _name, _) _name = _tid,
106
-#define POINTER(_tid, _name, _) _name = _tid,
107
-BUILTIN_TYPES
108
-#undef SCALAR
109
-#undef POINTER
110
-} builtin_type_t;
111
-
112
-
113
-type_t *type_info(tid_t tid);
77
+};
78
+
79
+extern type_t t_v;
80
+extern type_t t_vp;
81
+
82
+extern type_t t_c;
83
+extern type_t t_cp;
84
+extern type_t t_uc;
85
+extern type_t t_ucp;
86
+
87
+extern type_t t_s;
88
+extern type_t t_sp;
89
+extern type_t t_us;
90
+extern type_t t_usp;
91
+
92
+extern type_t t_i;
93
+extern type_t t_ip;
94
+extern type_t t_ui;
95
+extern type_t t_uip;
96
+
97
+extern type_t t_l;
98
+extern type_t t_lp;
99
+extern type_t t_ul;
100
+extern type_t t_ulp;
101
+
102
+extern type_t t_ll;
103
+extern type_t t_llp;
104
+extern type_t t_ull;
105
+extern type_t t_ullp;
106
+
107
+
108
+int type_equal(type_t *a, type_t *b);
109
+int type_add(type_t *t);
110
+int type_add_list(type_t **ts);
114 111
 
115 112
 void type_dump      (type_t *t, FILE *fp);
116 113
 void type_dump_cdecl(type_t *t, FILE *fp);
114
+void types_dump_cdecl(FILE *fp);
117 115
 
118 116
 #endif	/* _PLY_TYPE_H */