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