xref: /inferno-os/utils/libmach/9obj.c (revision d67b7dad77bb8aa973dad1f7c3ab0c309b114278)
1*d67b7dadSforsyth /*
2*d67b7dadSforsyth  * 9obj.c - identify and parse a PowerPC-64 object file
3*d67b7dadSforsyth  *	forsyth@terzarima.net
4*d67b7dadSforsyth  */
5*d67b7dadSforsyth #include <lib9.h>
6*d67b7dadSforsyth #include <bio.h>
7*d67b7dadSforsyth #include "mach.h"
8*d67b7dadSforsyth #include "9c/9.out.h"
9*d67b7dadSforsyth #include "obj.h"
10*d67b7dadSforsyth 
11*d67b7dadSforsyth typedef struct Addr	Addr;
12*d67b7dadSforsyth struct Addr
13*d67b7dadSforsyth {
14*d67b7dadSforsyth 	char	type;
15*d67b7dadSforsyth 	char	sym;
16*d67b7dadSforsyth 	char	name;
17*d67b7dadSforsyth };
18*d67b7dadSforsyth static Addr addr(Biobuf*);
19*d67b7dadSforsyth static char type2char(int);
20*d67b7dadSforsyth static void skip(Biobuf*, int);
21*d67b7dadSforsyth 
22*d67b7dadSforsyth int
_is9(char * s)23*d67b7dadSforsyth _is9(char *s)
24*d67b7dadSforsyth {
25*d67b7dadSforsyth 	return  (s[0]&0377) == ANAME				/* ANAME */
26*d67b7dadSforsyth 		&& (s[1]&0377) == ANAME>>8
27*d67b7dadSforsyth 		&& s[2] == D_FILE			/* type */
28*d67b7dadSforsyth 		&& s[3] == 1				/* sym */
29*d67b7dadSforsyth 		&& s[4] == '<';				/* name of file */
30*d67b7dadSforsyth }
31*d67b7dadSforsyth 
32*d67b7dadSforsyth int
_read9(Biobuf * bp,Prog * p)33*d67b7dadSforsyth _read9(Biobuf *bp, Prog *p)
34*d67b7dadSforsyth {
35*d67b7dadSforsyth 	int as, n, c;
36*d67b7dadSforsyth 	Addr a;
37*d67b7dadSforsyth 
38*d67b7dadSforsyth 	as = Bgetc(bp);			/* as(low) */
39*d67b7dadSforsyth 	if(as < 0)
40*d67b7dadSforsyth 		return 0;
41*d67b7dadSforsyth 	c = Bgetc(bp);		/* as(high) */
42*d67b7dadSforsyth 	if(c < 0)
43*d67b7dadSforsyth 		return 0;
44*d67b7dadSforsyth 	as |= ((c & 0xff) << 8);
45*d67b7dadSforsyth 	p->kind = aNone;
46*d67b7dadSforsyth 	p->sig = 0;
47*d67b7dadSforsyth 	if(as == ANAME || as == ASIGNAME){
48*d67b7dadSforsyth 		if(as == ASIGNAME){
49*d67b7dadSforsyth 			Bread(bp, &p->sig, 4);
50*d67b7dadSforsyth 			p->sig = beswal(p->sig);
51*d67b7dadSforsyth 		}
52*d67b7dadSforsyth 		p->kind = aName;
53*d67b7dadSforsyth 		p->type = type2char(Bgetc(bp));		/* type */
54*d67b7dadSforsyth 		p->sym = Bgetc(bp);			/* sym */
55*d67b7dadSforsyth 		n = 0;
56*d67b7dadSforsyth 		for(;;) {
57*d67b7dadSforsyth 			as = Bgetc(bp);
58*d67b7dadSforsyth 			if(as < 0)
59*d67b7dadSforsyth 				return 0;
60*d67b7dadSforsyth 			n++;
61*d67b7dadSforsyth 			if(as == 0)
62*d67b7dadSforsyth 				break;
63*d67b7dadSforsyth 		}
64*d67b7dadSforsyth 		p->id = malloc(n);
65*d67b7dadSforsyth 		if(p->id == 0)
66*d67b7dadSforsyth 			return 0;
67*d67b7dadSforsyth 		Bseek(bp, -n, 1);
68*d67b7dadSforsyth 		if(Bread(bp, p->id, n) != n)
69*d67b7dadSforsyth 			return 0;
70*d67b7dadSforsyth 		return 1;
71*d67b7dadSforsyth 	}
72*d67b7dadSforsyth 	if(as == ATEXT)
73*d67b7dadSforsyth 		p->kind = aText;
74*d67b7dadSforsyth 	else if(as == AGLOBL)
75*d67b7dadSforsyth 		p->kind = aData;
76*d67b7dadSforsyth 	n = Bgetc(bp);	/* reg and flag */
77*d67b7dadSforsyth 	skip(bp, 4);		/* lineno(4) */
78*d67b7dadSforsyth 	a = addr(bp);
79*d67b7dadSforsyth 	if(n & 0x40)
80*d67b7dadSforsyth 		addr(bp);
81*d67b7dadSforsyth 	addr(bp);
82*d67b7dadSforsyth 	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
83*d67b7dadSforsyth 		p->kind = aNone;
84*d67b7dadSforsyth 	p->sym = a.sym;
85*d67b7dadSforsyth 	return 1;
86*d67b7dadSforsyth }
87*d67b7dadSforsyth 
88*d67b7dadSforsyth static Addr
addr(Biobuf * bp)89*d67b7dadSforsyth addr(Biobuf *bp)
90*d67b7dadSforsyth {
91*d67b7dadSforsyth 	Addr a;
92*d67b7dadSforsyth 	vlong off;
93*d67b7dadSforsyth 	long l;
94*d67b7dadSforsyth 
95*d67b7dadSforsyth 	a.type = Bgetc(bp);	/* a.type */
96*d67b7dadSforsyth 	skip(bp,1);		/* reg */
97*d67b7dadSforsyth 	a.sym = Bgetc(bp);	/* sym index */
98*d67b7dadSforsyth 	a.name = Bgetc(bp);	/* sym type */
99*d67b7dadSforsyth 	switch(a.type){
100*d67b7dadSforsyth 	default:
101*d67b7dadSforsyth 	case D_NONE: case D_REG: case D_FREG: case D_CREG:
102*d67b7dadSforsyth 	case D_FPSCR: case D_MSR:
103*d67b7dadSforsyth 		break;
104*d67b7dadSforsyth 	case D_SPR:
105*d67b7dadSforsyth 	case D_OREG:
106*d67b7dadSforsyth 	case D_CONST:
107*d67b7dadSforsyth 	case D_BRANCH:
108*d67b7dadSforsyth 	case D_DCONST:
109*d67b7dadSforsyth 	case D_DCR:
110*d67b7dadSforsyth 		l = Bgetc(bp);
111*d67b7dadSforsyth 		l |= Bgetc(bp) << 8;
112*d67b7dadSforsyth 		l |= Bgetc(bp) << 16;
113*d67b7dadSforsyth 		l |= Bgetc(bp) << 24;
114*d67b7dadSforsyth 		off = l;
115*d67b7dadSforsyth 		if(a.type == D_DCONST){
116*d67b7dadSforsyth 			l = Bgetc(bp);
117*d67b7dadSforsyth 			l |= Bgetc(bp) << 8;
118*d67b7dadSforsyth 			l |= Bgetc(bp) << 16;
119*d67b7dadSforsyth 			l |= Bgetc(bp) << 24;
120*d67b7dadSforsyth 			off = ((vlong)l << 32) | (off & 0xFFFFFFFF);
121*d67b7dadSforsyth 			a.type = D_CONST;	/* perhaps */
122*d67b7dadSforsyth 		}
123*d67b7dadSforsyth 		if(off < 0)
124*d67b7dadSforsyth 			off = -off;
125*d67b7dadSforsyth 		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
126*d67b7dadSforsyth 			_offset(a.sym, off);
127*d67b7dadSforsyth 		break;
128*d67b7dadSforsyth 	case D_SCONST:
129*d67b7dadSforsyth 		skip(bp, NSNAME);
130*d67b7dadSforsyth 		break;
131*d67b7dadSforsyth 	case D_FCONST:
132*d67b7dadSforsyth 		skip(bp, 8);
133*d67b7dadSforsyth 		break;
134*d67b7dadSforsyth 	}
135*d67b7dadSforsyth 	return a;
136*d67b7dadSforsyth }
137*d67b7dadSforsyth 
138*d67b7dadSforsyth static char
type2char(int t)139*d67b7dadSforsyth type2char(int t)
140*d67b7dadSforsyth {
141*d67b7dadSforsyth 	switch(t){
142*d67b7dadSforsyth 	case D_EXTERN:		return 'U';
143*d67b7dadSforsyth 	case D_STATIC:		return 'b';
144*d67b7dadSforsyth 	case D_AUTO:		return 'a';
145*d67b7dadSforsyth 	case D_PARAM:		return 'p';
146*d67b7dadSforsyth 	default:		return UNKNOWN;
147*d67b7dadSforsyth 	}
148*d67b7dadSforsyth }
149*d67b7dadSforsyth 
150*d67b7dadSforsyth static void
skip(Biobuf * bp,int n)151*d67b7dadSforsyth skip(Biobuf *bp, int n)
152*d67b7dadSforsyth {
153*d67b7dadSforsyth 	while (n-- > 0)
154*d67b7dadSforsyth 		Bgetc(bp);
155*d67b7dadSforsyth }
156