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