xref: /plan9-contrib/sys/src/libmach/8obj.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 /*
2  * 8obj.c - identify and parse a 386 object file
3  */
4 #include <u.h>
5 #include <libc.h>
6 #include <bio.h>
7 #include "8c/8.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 _is8(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 _read8(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){
47 		p->kind = aName;
48 		p->type = type2char(Bgetc(bp));		/* type */
49 		p->sym = Bgetc(bp);			/* sym */
50 		n = 0;
51 		for(;;) {
52 			as = Bgetc(bp);
53 			if(as < 0)
54 				return 0;
55 			n++;
56 			if(as == 0)
57 				break;
58 		}
59 		p->id = malloc(n);
60 		if(p->id == 0)
61 			return 0;
62 		Bseek(bp, -n, 1);
63 		if(Bread(bp, p->id, n) != n)
64 			return 0;
65 		return 1;
66 	}
67 	if(as == ATEXT)
68 		p->kind = aText;
69 	if(as == AGLOBL)
70 		p->kind = aData;
71 	skip(bp, 4);		/* lineno(4) */
72 	a = addr(bp);
73 	addr(bp);
74 	if(!(a.flags & T_SYM))
75 		p->kind = aNone;
76 	p->sym = a.sym;
77 	return 1;
78 }
79 
80 static Addr
81 addr(Biobuf *bp)
82 {
83 	Addr a;
84 	int t;
85 	long off;
86 
87 	off = 0;
88 	a.sym = -1;
89 	a.flags = Bgetc(bp);			/* flags */
90 	if(a.flags & T_INDEX)
91 		skip(bp, 2);
92 	if(a.flags & T_OFFSET){
93 		off = Bgetc(bp);
94 		off |= Bgetc(bp) << 8;
95 		off |= Bgetc(bp) << 16;
96 		off |= Bgetc(bp) << 24;
97 		if(off < 0)
98 			off = -off;
99 	}
100 	if(a.flags & T_SYM)
101 		a.sym = Bgetc(bp);
102 	if(a.flags & T_FCONST)
103 		skip(bp, 8);
104 	else
105 	if(a.flags & T_SCONST)
106 		skip(bp, NSNAME);
107 	if(a.flags & T_TYPE) {
108 		t = Bgetc(bp);
109 		if(a.sym > 0 && (t==D_PARAM || t==D_AUTO))
110 			_offset(a.sym, off);
111 	}
112 	return a;
113 }
114 
115 static char
116 type2char(int t)
117 {
118 	switch(t){
119 	case D_EXTERN:		return 'U';
120 	case D_STATIC:		return 'b';
121 	case D_AUTO:		return 'a';
122 	case D_PARAM:		return 'p';
123 	default:		return UNKNOWN;
124 	}
125 }
126 
127 static void
128 skip(Biobuf *bp, int n)
129 {
130 	while (n-- > 0)
131 		Bgetc(bp);
132 }
133