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