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