17dd7cddfSDavid du Colombier /* 27dd7cddfSDavid du Colombier * qobj.c - identify and parse a PowerPC object file 3*061a3f44SDavid du Colombier * forsyth@terzarima.net 47dd7cddfSDavid du Colombier */ 57dd7cddfSDavid du Colombier #include <u.h> 67dd7cddfSDavid du Colombier #include <libc.h> 77dd7cddfSDavid du Colombier #include <bio.h> 87dd7cddfSDavid du Colombier #include "qc/q.out.h" 97dd7cddfSDavid du Colombier #include "obj.h" 107dd7cddfSDavid du Colombier 117dd7cddfSDavid du Colombier typedef struct Addr Addr; 127dd7cddfSDavid du Colombier struct Addr 137dd7cddfSDavid du Colombier { 147dd7cddfSDavid du Colombier char type; 157dd7cddfSDavid du Colombier char sym; 167dd7cddfSDavid du Colombier char name; 177dd7cddfSDavid du Colombier }; 187dd7cddfSDavid du Colombier static Addr addr(Biobuf*); 197dd7cddfSDavid du Colombier static char type2char(int); 207dd7cddfSDavid du Colombier static void skip(Biobuf*, int); 217dd7cddfSDavid du Colombier 227dd7cddfSDavid du Colombier int 237dd7cddfSDavid du Colombier _isq(char *s) 247dd7cddfSDavid du Colombier { 257dd7cddfSDavid du Colombier return (s[0]&0377) == ANAME /* ANAME */ 267dd7cddfSDavid du Colombier && s[1] == D_FILE /* type */ 277dd7cddfSDavid du Colombier && s[2] == 1 /* sym */ 287dd7cddfSDavid du Colombier && s[3] == '<'; /* name of file */ 297dd7cddfSDavid du Colombier } 307dd7cddfSDavid du Colombier 317dd7cddfSDavid du Colombier int 327dd7cddfSDavid du Colombier _readq(Biobuf *bp, Prog *p) 337dd7cddfSDavid du Colombier { 347dd7cddfSDavid du Colombier int as, n; 357dd7cddfSDavid du Colombier Addr a; 367dd7cddfSDavid du Colombier 377dd7cddfSDavid du Colombier as = Bgetc(bp); /* as */ 387dd7cddfSDavid du Colombier if(as < 0) 397dd7cddfSDavid du Colombier return 0; 407dd7cddfSDavid du Colombier p->kind = aNone; 41*061a3f44SDavid du Colombier if(as == ANAME || as == ASIGNAME){ 42*061a3f44SDavid du Colombier if(as == ASIGNAME) 43*061a3f44SDavid du Colombier skip(bp, 4); /* signature */ 447dd7cddfSDavid du Colombier p->kind = aName; 457dd7cddfSDavid du Colombier p->type = type2char(Bgetc(bp)); /* type */ 467dd7cddfSDavid du Colombier p->sym = Bgetc(bp); /* sym */ 477dd7cddfSDavid du Colombier n = 0; 487dd7cddfSDavid du Colombier for(;;) { 497dd7cddfSDavid du Colombier as = Bgetc(bp); 507dd7cddfSDavid du Colombier if(as < 0) 517dd7cddfSDavid du Colombier return 0; 527dd7cddfSDavid du Colombier n++; 537dd7cddfSDavid du Colombier if(as == 0) 547dd7cddfSDavid du Colombier break; 557dd7cddfSDavid du Colombier } 567dd7cddfSDavid du Colombier p->id = malloc(n); 577dd7cddfSDavid du Colombier if(p->id == 0) 587dd7cddfSDavid du Colombier return 0; 597dd7cddfSDavid du Colombier Bseek(bp, -n, 1); 607dd7cddfSDavid du Colombier if(Bread(bp, p->id, n) != n) 617dd7cddfSDavid du Colombier return 0; 627dd7cddfSDavid du Colombier return 1; 637dd7cddfSDavid du Colombier } 647dd7cddfSDavid du Colombier if(as == ATEXT) 657dd7cddfSDavid du Colombier p->kind = aText; 667dd7cddfSDavid du Colombier else if(as == AGLOBL) 677dd7cddfSDavid du Colombier p->kind = aData; 687dd7cddfSDavid du Colombier n = Bgetc(bp); /* reg and flag */ 697dd7cddfSDavid du Colombier skip(bp, 4); /* lineno(4) */ 707dd7cddfSDavid du Colombier a = addr(bp); 717dd7cddfSDavid du Colombier if(n & 0x40) 727dd7cddfSDavid du Colombier addr(bp); 737dd7cddfSDavid du Colombier addr(bp); 747dd7cddfSDavid du Colombier if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN) 757dd7cddfSDavid du Colombier p->kind = aNone; 767dd7cddfSDavid du Colombier p->sym = a.sym; 777dd7cddfSDavid du Colombier return 1; 787dd7cddfSDavid du Colombier } 797dd7cddfSDavid du Colombier 807dd7cddfSDavid du Colombier static Addr 817dd7cddfSDavid du Colombier addr(Biobuf *bp) 827dd7cddfSDavid du Colombier { 837dd7cddfSDavid du Colombier Addr a; 847dd7cddfSDavid du Colombier long off; 857dd7cddfSDavid du Colombier 867dd7cddfSDavid du Colombier a.type = Bgetc(bp); /* a.type */ 877dd7cddfSDavid du Colombier skip(bp,1); /* reg */ 887dd7cddfSDavid du Colombier a.sym = Bgetc(bp); /* sym index */ 897dd7cddfSDavid du Colombier a.name = Bgetc(bp); /* sym type */ 907dd7cddfSDavid du Colombier switch(a.type){ 917dd7cddfSDavid du Colombier default: 927dd7cddfSDavid du Colombier case D_NONE: case D_REG: case D_FREG: case D_CREG: 937dd7cddfSDavid du Colombier case D_FPSCR: case D_MSR: case D_SREG: 947dd7cddfSDavid du Colombier break; 957dd7cddfSDavid du Colombier case D_SPR: 967dd7cddfSDavid du Colombier case D_OREG: 977dd7cddfSDavid du Colombier case D_CONST: 987dd7cddfSDavid du Colombier case D_BRANCH: 997dd7cddfSDavid du Colombier off = Bgetc(bp); 1007dd7cddfSDavid du Colombier off |= Bgetc(bp) << 8; 1017dd7cddfSDavid du Colombier off |= Bgetc(bp) << 16; 1027dd7cddfSDavid du Colombier off |= Bgetc(bp) << 24; 1037dd7cddfSDavid du Colombier if(off < 0) 1047dd7cddfSDavid du Colombier off = -off; 1057dd7cddfSDavid du Colombier if(a.sym && (a.name==D_PARAM || a.name==D_AUTO)) 1067dd7cddfSDavid du Colombier _offset(a.sym, off); 1077dd7cddfSDavid du Colombier break; 1087dd7cddfSDavid du Colombier case D_SCONST: 1097dd7cddfSDavid du Colombier skip(bp, NSNAME); 1107dd7cddfSDavid du Colombier break; 1117dd7cddfSDavid du Colombier case D_FCONST: 1127dd7cddfSDavid du Colombier skip(bp, 8); 1137dd7cddfSDavid du Colombier break; 1147dd7cddfSDavid du Colombier } 1157dd7cddfSDavid du Colombier return a; 1167dd7cddfSDavid du Colombier } 1177dd7cddfSDavid du Colombier 1187dd7cddfSDavid du Colombier static char 1197dd7cddfSDavid du Colombier type2char(int t) 1207dd7cddfSDavid du Colombier { 1217dd7cddfSDavid du Colombier switch(t){ 1227dd7cddfSDavid du Colombier case D_EXTERN: return 'U'; 1237dd7cddfSDavid du Colombier case D_STATIC: return 'b'; 1247dd7cddfSDavid du Colombier case D_AUTO: return 'a'; 1257dd7cddfSDavid du Colombier case D_PARAM: return 'p'; 1267dd7cddfSDavid du Colombier default: return UNKNOWN; 1277dd7cddfSDavid du Colombier } 1287dd7cddfSDavid du Colombier } 1297dd7cddfSDavid du Colombier 1307dd7cddfSDavid du Colombier static void 1317dd7cddfSDavid du Colombier skip(Biobuf *bp, int n) 1327dd7cddfSDavid du Colombier { 1337dd7cddfSDavid du Colombier while (n-- > 0) 1347dd7cddfSDavid du Colombier Bgetc(bp); 1357dd7cddfSDavid du Colombier } 136