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