xref: /inferno-os/utils/libmach/8obj.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
174a4d8c2SCharles.Forsyth /*
274a4d8c2SCharles.Forsyth  * 8obj.c - identify and parse a 386 object file
374a4d8c2SCharles.Forsyth  */
474a4d8c2SCharles.Forsyth #include <lib9.h>
574a4d8c2SCharles.Forsyth #include <bio.h>
6*45a20ab7Sforsyth #include "mach.h"
774a4d8c2SCharles.Forsyth #include "8c/8.out.h"
874a4d8c2SCharles.Forsyth #include "obj.h"
974a4d8c2SCharles.Forsyth 
1074a4d8c2SCharles.Forsyth typedef struct Addr	Addr;
1174a4d8c2SCharles.Forsyth struct Addr
1274a4d8c2SCharles.Forsyth {
1374a4d8c2SCharles.Forsyth 	char	sym;
1474a4d8c2SCharles.Forsyth 	char	flags;
1574a4d8c2SCharles.Forsyth };
1674a4d8c2SCharles.Forsyth static	Addr	addr(Biobuf*);
1774a4d8c2SCharles.Forsyth static	char	type2char(int);
1874a4d8c2SCharles.Forsyth static	void	skip(Biobuf*, int);
1974a4d8c2SCharles.Forsyth 
2074a4d8c2SCharles.Forsyth int
_is8(char * t)2174a4d8c2SCharles.Forsyth _is8(char *t)
2274a4d8c2SCharles.Forsyth {
2374a4d8c2SCharles.Forsyth 	uchar *s = (uchar*)t;
2474a4d8c2SCharles.Forsyth 
2574a4d8c2SCharles.Forsyth 	return  s[0] == (ANAME&0xff)			/* aslo = ANAME */
2674a4d8c2SCharles.Forsyth 		&& s[1] == ((ANAME>>8)&0xff)
2774a4d8c2SCharles.Forsyth 		&& s[2] == D_FILE			/* type */
2874a4d8c2SCharles.Forsyth 		&& s[3] == 1				/* sym */
2974a4d8c2SCharles.Forsyth 		&& s[4] == '<';				/* name of file */
3074a4d8c2SCharles.Forsyth }
3174a4d8c2SCharles.Forsyth 
3274a4d8c2SCharles.Forsyth int
_read8(Biobuf * bp,Prog * p)3374a4d8c2SCharles.Forsyth _read8(Biobuf *bp, Prog* p)
3474a4d8c2SCharles.Forsyth {
3574a4d8c2SCharles.Forsyth 	int as, n, c;
3674a4d8c2SCharles.Forsyth 	Addr a;
3774a4d8c2SCharles.Forsyth 
3874a4d8c2SCharles.Forsyth 	as = Bgetc(bp);		/* as(low) */
3974a4d8c2SCharles.Forsyth 	if(as < 0)
4074a4d8c2SCharles.Forsyth 		return 0;
4174a4d8c2SCharles.Forsyth 	c = Bgetc(bp);		/* as(high) */
4274a4d8c2SCharles.Forsyth 	if(c < 0)
4374a4d8c2SCharles.Forsyth 		return 0;
4474a4d8c2SCharles.Forsyth 	as |= ((c & 0xff) << 8);
4574a4d8c2SCharles.Forsyth 	p->kind = aNone;
4673500e27Sforsyth 	p->sig = 0;
4774a4d8c2SCharles.Forsyth 	if(as == ANAME || as == ASIGNAME){
4873500e27Sforsyth 		if(as == ASIGNAME){
4973500e27Sforsyth 			Bread(bp, &p->sig, 4);
5073500e27Sforsyth 			p->sig = leswal(p->sig);
5173500e27Sforsyth 		}
5274a4d8c2SCharles.Forsyth 		p->kind = aName;
5374a4d8c2SCharles.Forsyth 		p->type = type2char(Bgetc(bp));		/* type */
5474a4d8c2SCharles.Forsyth 		p->sym = Bgetc(bp);			/* sym */
5574a4d8c2SCharles.Forsyth 		n = 0;
5674a4d8c2SCharles.Forsyth 		for(;;) {
5774a4d8c2SCharles.Forsyth 			as = Bgetc(bp);
5874a4d8c2SCharles.Forsyth 			if(as < 0)
5974a4d8c2SCharles.Forsyth 				return 0;
6074a4d8c2SCharles.Forsyth 			n++;
6174a4d8c2SCharles.Forsyth 			if(as == 0)
6274a4d8c2SCharles.Forsyth 				break;
6374a4d8c2SCharles.Forsyth 		}
6474a4d8c2SCharles.Forsyth 		p->id = malloc(n);
6574a4d8c2SCharles.Forsyth 		if(p->id == 0)
6674a4d8c2SCharles.Forsyth 			return 0;
6774a4d8c2SCharles.Forsyth 		Bseek(bp, -n, 1);
6874a4d8c2SCharles.Forsyth 		if(Bread(bp, p->id, n) != n)
6974a4d8c2SCharles.Forsyth 			return 0;
7074a4d8c2SCharles.Forsyth 		return 1;
7174a4d8c2SCharles.Forsyth 	}
7274a4d8c2SCharles.Forsyth 	if(as == ATEXT)
7374a4d8c2SCharles.Forsyth 		p->kind = aText;
7474a4d8c2SCharles.Forsyth 	if(as == AGLOBL)
7574a4d8c2SCharles.Forsyth 		p->kind = aData;
7674a4d8c2SCharles.Forsyth 	skip(bp, 4);		/* lineno(4) */
7774a4d8c2SCharles.Forsyth 	a = addr(bp);
7874a4d8c2SCharles.Forsyth 	addr(bp);
7974a4d8c2SCharles.Forsyth 	if(!(a.flags & T_SYM))
8074a4d8c2SCharles.Forsyth 		p->kind = aNone;
8174a4d8c2SCharles.Forsyth 	p->sym = a.sym;
8274a4d8c2SCharles.Forsyth 	return 1;
8374a4d8c2SCharles.Forsyth }
8474a4d8c2SCharles.Forsyth 
8574a4d8c2SCharles.Forsyth static Addr
addr(Biobuf * bp)8674a4d8c2SCharles.Forsyth addr(Biobuf *bp)
8774a4d8c2SCharles.Forsyth {
8874a4d8c2SCharles.Forsyth 	Addr a;
8974a4d8c2SCharles.Forsyth 	int t;
9074a4d8c2SCharles.Forsyth 	long off;
9174a4d8c2SCharles.Forsyth 
9274a4d8c2SCharles.Forsyth 	off = 0;
9374a4d8c2SCharles.Forsyth 	a.sym = -1;
9474a4d8c2SCharles.Forsyth 	a.flags = Bgetc(bp);			/* flags */
9574a4d8c2SCharles.Forsyth 	if(a.flags & T_INDEX)
9674a4d8c2SCharles.Forsyth 		skip(bp, 2);
9774a4d8c2SCharles.Forsyth 	if(a.flags & T_OFFSET){
9874a4d8c2SCharles.Forsyth 		off = Bgetc(bp);
9974a4d8c2SCharles.Forsyth 		off |= Bgetc(bp) << 8;
10074a4d8c2SCharles.Forsyth 		off |= Bgetc(bp) << 16;
10174a4d8c2SCharles.Forsyth 		off |= Bgetc(bp) << 24;
10274a4d8c2SCharles.Forsyth 		if(off < 0)
10374a4d8c2SCharles.Forsyth 			off = -off;
10474a4d8c2SCharles.Forsyth 	}
10574a4d8c2SCharles.Forsyth 	if(a.flags & T_SYM)
10674a4d8c2SCharles.Forsyth 		a.sym = Bgetc(bp);
10774a4d8c2SCharles.Forsyth 	if(a.flags & T_FCONST)
10874a4d8c2SCharles.Forsyth 		skip(bp, 8);
10974a4d8c2SCharles.Forsyth 	else
11074a4d8c2SCharles.Forsyth 	if(a.flags & T_SCONST)
11174a4d8c2SCharles.Forsyth 		skip(bp, NSNAME);
11274a4d8c2SCharles.Forsyth 	if(a.flags & T_TYPE) {
11374a4d8c2SCharles.Forsyth 		t = Bgetc(bp);
11474a4d8c2SCharles.Forsyth 		if(a.sym > 0 && (t==D_PARAM || t==D_AUTO))
11574a4d8c2SCharles.Forsyth 			_offset(a.sym, off);
11674a4d8c2SCharles.Forsyth 	}
11774a4d8c2SCharles.Forsyth 	return a;
11874a4d8c2SCharles.Forsyth }
11974a4d8c2SCharles.Forsyth 
12074a4d8c2SCharles.Forsyth static char
type2char(int t)12174a4d8c2SCharles.Forsyth type2char(int t)
12274a4d8c2SCharles.Forsyth {
12374a4d8c2SCharles.Forsyth 	switch(t){
12474a4d8c2SCharles.Forsyth 	case D_EXTERN:		return 'U';
12574a4d8c2SCharles.Forsyth 	case D_STATIC:		return 'b';
12674a4d8c2SCharles.Forsyth 	case D_AUTO:		return 'a';
12774a4d8c2SCharles.Forsyth 	case D_PARAM:		return 'p';
12874a4d8c2SCharles.Forsyth 	default:		return UNKNOWN;
12974a4d8c2SCharles.Forsyth 	}
13074a4d8c2SCharles.Forsyth }
13174a4d8c2SCharles.Forsyth 
13274a4d8c2SCharles.Forsyth static void
skip(Biobuf * bp,int n)13374a4d8c2SCharles.Forsyth skip(Biobuf *bp, int n)
13474a4d8c2SCharles.Forsyth {
13574a4d8c2SCharles.Forsyth 	while (n-- > 0)
13674a4d8c2SCharles.Forsyth 		Bgetc(bp);
13774a4d8c2SCharles.Forsyth }
138