xref: /plan9/sys/src/libmach/6obj.c (revision 4d44ba9b9ee4246ddbd96c7fcaf0918ab92ab35a)
1 /*
2  * 6obj.c - identify and parse an amd64 object file
3  */
4 #include <u.h>
5 #include <libc.h>
6 #include <bio.h>
7 #include "6c/6.out.h"
8 #include "obj.h"
9 
10 typedef struct Addr	Addr;
11 struct Addr
12 {
13 	char	sym;
14 	char	flags;
15 };
16 static	Addr	addr(Biobuf*);
17 static	char	type2char(int);
18 static	void	skip(Biobuf*, int);
19 
20 int
21 _is6(char *t)
22 {
23 	uchar *s = (uchar*)t;
24 
25 	return  s[0] == (ANAME&0xff)			/* aslo = ANAME */
26 		&& s[1] == ((ANAME>>8)&0xff)
27 		&& s[2] == D_FILE			/* type */
28 		&& s[3] == 1				/* sym */
29 		&& s[4] == '<';				/* name of file */
30 }
31 
32 int
33 _read6(Biobuf *bp, Prog* p)
34 {
35 	int as, n, c;
36 	Addr a;
37 
38 	as = Bgetc(bp);		/* as(low) */
39 	if(as < 0)
40 		return 0;
41 	c = Bgetc(bp);		/* as(high) */
42 	if(c < 0)
43 		return 0;
44 	as |= ((c & 0xff) << 8);
45 	p->kind = aNone;
46 	if(as == ANAME || as == ASIGNAME){
47 		if(as == ASIGNAME)
48 			skip(bp, 4);	/* signature */
49 		p->kind = aName;
50 		p->type = type2char(Bgetc(bp));		/* type */
51 		p->sym = Bgetc(bp);			/* sym */
52 		n = 0;
53 		for(;;) {
54 			as = Bgetc(bp);
55 			if(as < 0)
56 				return 0;
57 			n++;
58 			if(as == 0)
59 				break;
60 		}
61 		p->id = malloc(n);
62 		if(p->id == 0)
63 			return 0;
64 		Bseek(bp, -n, 1);
65 		if(Bread(bp, p->id, n) != n)
66 			return 0;
67 		return 1;
68 	}
69 	if(as == ATEXT)
70 		p->kind = aText;
71 	if(as == AGLOBL)
72 		p->kind = aData;
73 	skip(bp, 4);		/* lineno(4) */
74 	a = addr(bp);
75 	addr(bp);
76 	if(!(a.flags & T_SYM))
77 		p->kind = aNone;
78 	p->sym = a.sym;
79 	return 1;
80 }
81 
82 static Addr
83 addr(Biobuf *bp)
84 {
85 	Addr a;
86 	int t;
87 	long l;
88 	vlong off;
89 
90 	off = 0;
91 	a.sym = -1;
92 	a.flags = Bgetc(bp);			/* flags */
93 	if(a.flags & T_INDEX)
94 		skip(bp, 2);
95 	if(a.flags & T_OFFSET){
96 		l = Bgetc(bp);
97 		l |= Bgetc(bp) << 8;
98 		l |= Bgetc(bp) << 16;
99 		l |= Bgetc(bp) << 24;
100 		off = l;
101 		if(a.flags & T_64){
102 			l = Bgetc(bp);
103 			l |= Bgetc(bp) << 8;
104 			l |= Bgetc(bp) << 16;
105 			l |= Bgetc(bp) << 24;
106 			off = ((vlong)l << 32) | (off & 0xFFFFFFFF);
107 		}
108 		if(off < 0)
109 			off = -off;
110 	}
111 	if(a.flags & T_SYM)
112 		a.sym = Bgetc(bp);
113 	if(a.flags & T_FCONST)
114 		skip(bp, 8);
115 	else
116 	if(a.flags & T_SCONST)
117 		skip(bp, NSNAME);
118 	if(a.flags & T_TYPE) {
119 		t = Bgetc(bp);
120 		if(a.sym > 0 && (t==D_PARAM || t==D_AUTO))
121 			_offset(a.sym, off);
122 	}
123 	return a;
124 }
125 
126 static char
127 type2char(int t)
128 {
129 	switch(t){
130 	case D_EXTERN:		return 'U';
131 	case D_STATIC:		return 'b';
132 	case D_AUTO:		return 'a';
133 	case D_PARAM:		return 'p';
134 	default:		return UNKNOWN;
135 	}
136 }
137 
138 static void
139 skip(Biobuf *bp, int n)
140 {
141 	while (n-- > 0)
142 		Bgetc(bp);
143 }
144