xref: /inferno-os/utils/libmach/qobj.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
174a4d8c2SCharles.Forsyth /*
274a4d8c2SCharles.Forsyth  * qobj.c - identify and parse a PowerPC object file
374a4d8c2SCharles.Forsyth  *	forsyth@terzarima.net
474a4d8c2SCharles.Forsyth  */
574a4d8c2SCharles.Forsyth #include <lib9.h>
674a4d8c2SCharles.Forsyth #include <bio.h>
7*45a20ab7Sforsyth #include "mach.h"
874a4d8c2SCharles.Forsyth #include "qc/q.out.h"
974a4d8c2SCharles.Forsyth #include "obj.h"
1074a4d8c2SCharles.Forsyth 
1174a4d8c2SCharles.Forsyth typedef struct Addr	Addr;
1274a4d8c2SCharles.Forsyth struct Addr
1374a4d8c2SCharles.Forsyth {
1474a4d8c2SCharles.Forsyth 	char	type;
1574a4d8c2SCharles.Forsyth 	char	sym;
1674a4d8c2SCharles.Forsyth 	char	name;
1774a4d8c2SCharles.Forsyth };
1874a4d8c2SCharles.Forsyth static Addr addr(Biobuf*);
1974a4d8c2SCharles.Forsyth static char type2char(int);
2074a4d8c2SCharles.Forsyth static void skip(Biobuf*, int);
2174a4d8c2SCharles.Forsyth 
2274a4d8c2SCharles.Forsyth int
_isq(char * s)2374a4d8c2SCharles.Forsyth _isq(char *s)
2474a4d8c2SCharles.Forsyth {
2574a4d8c2SCharles.Forsyth 	return  (s[0]&0377) == ANAME			/* ANAME */
26d67b7dadSforsyth 		&& (s[1]&0377) == ANAME>>8
27d67b7dadSforsyth 		&& s[2] == D_FILE			/* type */
28d67b7dadSforsyth 		&& s[3] == 1				/* sym */
29d67b7dadSforsyth 		&& s[4] == '<';				/* name of file */
3074a4d8c2SCharles.Forsyth }
3174a4d8c2SCharles.Forsyth 
3274a4d8c2SCharles.Forsyth int
_readq(Biobuf * bp,Prog * p)3374a4d8c2SCharles.Forsyth _readq(Biobuf *bp, Prog *p)
3474a4d8c2SCharles.Forsyth {
35d67b7dadSforsyth 	int as, n, c;
3674a4d8c2SCharles.Forsyth 	Addr a;
3774a4d8c2SCharles.Forsyth 
38d67b7dadSforsyth 	as = Bgetc(bp);			/* as(low) */
3974a4d8c2SCharles.Forsyth 	if(as < 0)
4074a4d8c2SCharles.Forsyth 		return 0;
41d67b7dadSforsyth 	c = Bgetc(bp);		/* as(high) */
42d67b7dadSforsyth 	if(c < 0)
43d67b7dadSforsyth 		return 0;
44d67b7dadSforsyth 	as |= ((c & 0xff) << 8);
4574a4d8c2SCharles.Forsyth 	p->kind = aNone;
46d67b7dadSforsyth 	p->sig = 0;
4774a4d8c2SCharles.Forsyth 	if(as == ANAME || as == ASIGNAME){
48d67b7dadSforsyth 		if(as == ASIGNAME){
49d67b7dadSforsyth 			Bread(bp, &p->sig, 4);
50d67b7dadSforsyth 			p->sig = beswal(p->sig);
51d67b7dadSforsyth 		}
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 	else if(as == AGLOBL)
7574a4d8c2SCharles.Forsyth 		p->kind = aData;
7674a4d8c2SCharles.Forsyth 	n = Bgetc(bp);	/* reg and flag */
7774a4d8c2SCharles.Forsyth 	skip(bp, 4);		/* lineno(4) */
7874a4d8c2SCharles.Forsyth 	a = addr(bp);
7974a4d8c2SCharles.Forsyth 	if(n & 0x40)
8074a4d8c2SCharles.Forsyth 		addr(bp);
8174a4d8c2SCharles.Forsyth 	addr(bp);
8274a4d8c2SCharles.Forsyth 	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
8374a4d8c2SCharles.Forsyth 		p->kind = aNone;
8474a4d8c2SCharles.Forsyth 	p->sym = a.sym;
8574a4d8c2SCharles.Forsyth 	return 1;
8674a4d8c2SCharles.Forsyth }
8774a4d8c2SCharles.Forsyth 
8874a4d8c2SCharles.Forsyth static Addr
addr(Biobuf * bp)8974a4d8c2SCharles.Forsyth addr(Biobuf *bp)
9074a4d8c2SCharles.Forsyth {
9174a4d8c2SCharles.Forsyth 	Addr a;
9274a4d8c2SCharles.Forsyth 	long off;
9374a4d8c2SCharles.Forsyth 
9474a4d8c2SCharles.Forsyth 	a.type = Bgetc(bp);	/* a.type */
9574a4d8c2SCharles.Forsyth 	skip(bp,1);		/* reg */
9674a4d8c2SCharles.Forsyth 	a.sym = Bgetc(bp);	/* sym index */
9774a4d8c2SCharles.Forsyth 	a.name = Bgetc(bp);	/* sym type */
9874a4d8c2SCharles.Forsyth 	switch(a.type){
9974a4d8c2SCharles.Forsyth 	default:
10074a4d8c2SCharles.Forsyth 	case D_NONE: case D_REG: case D_FREG: case D_CREG:
10174a4d8c2SCharles.Forsyth 	case D_FPSCR: case D_MSR: case D_SREG:
10274a4d8c2SCharles.Forsyth 		break;
10374a4d8c2SCharles.Forsyth 	case D_SPR:
10474a4d8c2SCharles.Forsyth 	case D_OREG:
105d67b7dadSforsyth 	case D_DCR:
10674a4d8c2SCharles.Forsyth 	case D_CONST:
10774a4d8c2SCharles.Forsyth 	case D_BRANCH:
10874a4d8c2SCharles.Forsyth 		off = Bgetc(bp);
10974a4d8c2SCharles.Forsyth 		off |= Bgetc(bp) << 8;
11074a4d8c2SCharles.Forsyth 		off |= Bgetc(bp) << 16;
11174a4d8c2SCharles.Forsyth 		off |= Bgetc(bp) << 24;
11274a4d8c2SCharles.Forsyth 		if(off < 0)
11374a4d8c2SCharles.Forsyth 			off = -off;
11474a4d8c2SCharles.Forsyth 		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
11574a4d8c2SCharles.Forsyth 			_offset(a.sym, off);
11674a4d8c2SCharles.Forsyth 		break;
11774a4d8c2SCharles.Forsyth 	case D_SCONST:
11874a4d8c2SCharles.Forsyth 		skip(bp, NSNAME);
11974a4d8c2SCharles.Forsyth 		break;
12074a4d8c2SCharles.Forsyth 	case D_FCONST:
12174a4d8c2SCharles.Forsyth 		skip(bp, 8);
12274a4d8c2SCharles.Forsyth 		break;
12374a4d8c2SCharles.Forsyth 	}
12474a4d8c2SCharles.Forsyth 	return a;
12574a4d8c2SCharles.Forsyth }
12674a4d8c2SCharles.Forsyth 
12774a4d8c2SCharles.Forsyth static char
type2char(int t)12874a4d8c2SCharles.Forsyth type2char(int t)
12974a4d8c2SCharles.Forsyth {
13074a4d8c2SCharles.Forsyth 	switch(t){
13174a4d8c2SCharles.Forsyth 	case D_EXTERN:		return 'U';
13274a4d8c2SCharles.Forsyth 	case D_STATIC:		return 'b';
13374a4d8c2SCharles.Forsyth 	case D_AUTO:		return 'a';
13474a4d8c2SCharles.Forsyth 	case D_PARAM:		return 'p';
13574a4d8c2SCharles.Forsyth 	default:		return UNKNOWN;
13674a4d8c2SCharles.Forsyth 	}
13774a4d8c2SCharles.Forsyth }
13874a4d8c2SCharles.Forsyth 
13974a4d8c2SCharles.Forsyth static void
skip(Biobuf * bp,int n)14074a4d8c2SCharles.Forsyth skip(Biobuf *bp, int n)
14174a4d8c2SCharles.Forsyth {
14274a4d8c2SCharles.Forsyth 	while (n-- > 0)
14374a4d8c2SCharles.Forsyth 		Bgetc(bp);
14474a4d8c2SCharles.Forsyth }
145