xref: /inferno-os/utils/libmach/vobj.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
174a4d8c2SCharles.Forsyth /*
274a4d8c2SCharles.Forsyth  * vobj.c - identify and parse a mips object file
374a4d8c2SCharles.Forsyth  */
474a4d8c2SCharles.Forsyth #include <lib9.h>
574a4d8c2SCharles.Forsyth #include <bio.h>
6*45a20ab7Sforsyth #include "mach.h"
774a4d8c2SCharles.Forsyth #include "vc/v.out.h"
874a4d8c2SCharles.Forsyth #include "obj.h"
974a4d8c2SCharles.Forsyth 
1074a4d8c2SCharles.Forsyth typedef struct Addr	Addr;
1174a4d8c2SCharles.Forsyth struct Addr
1274a4d8c2SCharles.Forsyth {
1374a4d8c2SCharles.Forsyth 	char	type;
1474a4d8c2SCharles.Forsyth 	char	sym;
1574a4d8c2SCharles.Forsyth 	char	name;
1674a4d8c2SCharles.Forsyth };
1774a4d8c2SCharles.Forsyth static Addr addr(Biobuf*);
1874a4d8c2SCharles.Forsyth static char type2char(int);
1974a4d8c2SCharles.Forsyth static void skip(Biobuf*, int);
2074a4d8c2SCharles.Forsyth 
2174a4d8c2SCharles.Forsyth int
_isv(char * s)2274a4d8c2SCharles.Forsyth _isv(char *s)
2374a4d8c2SCharles.Forsyth {
2474a4d8c2SCharles.Forsyth 	return  s[0] == ANAME				/* ANAME */
2574a4d8c2SCharles.Forsyth 		&& s[1] == D_FILE			/* type */
2674a4d8c2SCharles.Forsyth 		&& s[2] == 1				/* sym */
2774a4d8c2SCharles.Forsyth 		&& s[3] == '<';				/* name of file */
2874a4d8c2SCharles.Forsyth }
2974a4d8c2SCharles.Forsyth 
3074a4d8c2SCharles.Forsyth int
_readv(Biobuf * bp,Prog * p)3174a4d8c2SCharles.Forsyth _readv(Biobuf *bp, Prog *p)
3274a4d8c2SCharles.Forsyth {
3374a4d8c2SCharles.Forsyth 	int as, n;
3474a4d8c2SCharles.Forsyth 	Addr a;
3574a4d8c2SCharles.Forsyth 
3674a4d8c2SCharles.Forsyth 	as = Bgetc(bp);			/* as */
3774a4d8c2SCharles.Forsyth 	if(as < 0)
3874a4d8c2SCharles.Forsyth 		return 0;
3974a4d8c2SCharles.Forsyth 	p->kind = aNone;
4073500e27Sforsyth 	p->sig = 0;
4174a4d8c2SCharles.Forsyth 	if(as == ANAME || as == ASIGNAME){
4273500e27Sforsyth 		if(as == ASIGNAME){
4373500e27Sforsyth 			Bread(bp, &p->sig, 4);
44*45a20ab7Sforsyth 			p->sig = leswal(p->sig);
4573500e27Sforsyth 		}
4674a4d8c2SCharles.Forsyth 		p->kind = aName;
4774a4d8c2SCharles.Forsyth 		p->type = type2char(Bgetc(bp));		/* type */
4874a4d8c2SCharles.Forsyth 		p->sym = Bgetc(bp);			/* sym */
4974a4d8c2SCharles.Forsyth 		n = 0;
5074a4d8c2SCharles.Forsyth 		for(;;) {
5174a4d8c2SCharles.Forsyth 			as = Bgetc(bp);
5274a4d8c2SCharles.Forsyth 			if(as < 0)
5374a4d8c2SCharles.Forsyth 				return 0;
5474a4d8c2SCharles.Forsyth 			n++;
5574a4d8c2SCharles.Forsyth 			if(as == 0)
5674a4d8c2SCharles.Forsyth 				break;
5774a4d8c2SCharles.Forsyth 		}
5874a4d8c2SCharles.Forsyth 		p->id = malloc(n);
5974a4d8c2SCharles.Forsyth 		if(p->id == 0)
6074a4d8c2SCharles.Forsyth 			return 0;
6174a4d8c2SCharles.Forsyth 		Bseek(bp, -n, 1);
6274a4d8c2SCharles.Forsyth 		if(Bread(bp, p->id, n) != n)
6374a4d8c2SCharles.Forsyth 			return 0;
6474a4d8c2SCharles.Forsyth 		return 1;
6574a4d8c2SCharles.Forsyth 	}
6674a4d8c2SCharles.Forsyth 	if(as == ATEXT)
6774a4d8c2SCharles.Forsyth 		p->kind = aText;
6874a4d8c2SCharles.Forsyth 	else if(as == AGLOBL)
6974a4d8c2SCharles.Forsyth 		p->kind = aData;
7074a4d8c2SCharles.Forsyth 	skip(bp, 5);		/* reg(1), lineno(4) */
7174a4d8c2SCharles.Forsyth 	a = addr(bp);
7274a4d8c2SCharles.Forsyth 	addr(bp);
7374a4d8c2SCharles.Forsyth 	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
7474a4d8c2SCharles.Forsyth 		p->kind = aNone;
7574a4d8c2SCharles.Forsyth 	p->sym = a.sym;
7674a4d8c2SCharles.Forsyth 	return 1;
7774a4d8c2SCharles.Forsyth }
7874a4d8c2SCharles.Forsyth 
7974a4d8c2SCharles.Forsyth static Addr
addr(Biobuf * bp)8074a4d8c2SCharles.Forsyth addr(Biobuf *bp)
8174a4d8c2SCharles.Forsyth {
8274a4d8c2SCharles.Forsyth 	Addr a;
8374a4d8c2SCharles.Forsyth 	long off;
8474a4d8c2SCharles.Forsyth 
8574a4d8c2SCharles.Forsyth 	a.type = Bgetc(bp);	/* a.type */
8674a4d8c2SCharles.Forsyth 	skip(bp,1);		/* reg */
8774a4d8c2SCharles.Forsyth 	a.sym = Bgetc(bp);	/* sym index */
8874a4d8c2SCharles.Forsyth 	a.name = Bgetc(bp);	/* sym type */
8974a4d8c2SCharles.Forsyth 	switch(a.type){
9074a4d8c2SCharles.Forsyth 	default:
9174a4d8c2SCharles.Forsyth 	case D_NONE: case D_REG: case D_FREG: case D_MREG:
9274a4d8c2SCharles.Forsyth 	case D_FCREG: case D_LO: case D_HI:
9374a4d8c2SCharles.Forsyth 		break;
9474a4d8c2SCharles.Forsyth 	case D_OREG:
9574a4d8c2SCharles.Forsyth 	case D_CONST:
9674a4d8c2SCharles.Forsyth 	case D_BRANCH:
9774a4d8c2SCharles.Forsyth 		off = Bgetc(bp);
9874a4d8c2SCharles.Forsyth 		off |= Bgetc(bp) << 8;
9974a4d8c2SCharles.Forsyth 		off |= Bgetc(bp) << 16;
10074a4d8c2SCharles.Forsyth 		off |= Bgetc(bp) << 24;
10174a4d8c2SCharles.Forsyth 		if(off < 0)
10274a4d8c2SCharles.Forsyth 			off = -off;
10374a4d8c2SCharles.Forsyth 		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
10474a4d8c2SCharles.Forsyth 			_offset(a.sym, off);
10574a4d8c2SCharles.Forsyth 		break;
10674a4d8c2SCharles.Forsyth 	case D_SCONST:
10774a4d8c2SCharles.Forsyth 		skip(bp, NSNAME);
10874a4d8c2SCharles.Forsyth 		break;
10974a4d8c2SCharles.Forsyth 	case D_FCONST:
11074a4d8c2SCharles.Forsyth 		skip(bp, 8);
11174a4d8c2SCharles.Forsyth 		break;
11274a4d8c2SCharles.Forsyth 	}
11374a4d8c2SCharles.Forsyth 	return a;
11474a4d8c2SCharles.Forsyth }
11574a4d8c2SCharles.Forsyth 
11674a4d8c2SCharles.Forsyth static char
type2char(int t)11774a4d8c2SCharles.Forsyth type2char(int t)
11874a4d8c2SCharles.Forsyth {
11974a4d8c2SCharles.Forsyth 	switch(t){
12074a4d8c2SCharles.Forsyth 	case D_EXTERN:		return 'U';
12174a4d8c2SCharles.Forsyth 	case D_STATIC:		return 'b';
12274a4d8c2SCharles.Forsyth 	case D_AUTO:		return 'a';
12374a4d8c2SCharles.Forsyth 	case D_PARAM:		return 'p';
12474a4d8c2SCharles.Forsyth 	default:		return UNKNOWN;
12574a4d8c2SCharles.Forsyth 	}
12674a4d8c2SCharles.Forsyth }
12774a4d8c2SCharles.Forsyth 
12874a4d8c2SCharles.Forsyth static void
skip(Biobuf * bp,int n)12974a4d8c2SCharles.Forsyth skip(Biobuf *bp, int n)
13074a4d8c2SCharles.Forsyth {
13174a4d8c2SCharles.Forsyth 	while (n-- > 0)
13274a4d8c2SCharles.Forsyth 		Bgetc(bp);
13374a4d8c2SCharles.Forsyth }
134