1 /* 2 * obj.c 3 * routines universal to all object files 4 */ 5 #include <lib9.h> 6 #include <ctype.h> 7 #include <bio.h> 8 #include <ar.h> 9 #include "mach.h" 10 #include "obj.h" 11 12 #define islocal(t) ((t)=='a' || (t)=='p') 13 14 enum 15 { 16 NNAMES = 50, 17 MAXIS = 8, /* max length to determine if a file is a .? file */ 18 MAXOFF = 0x7fffffff, /* larger than any possible local offset */ 19 NHASH = 1024, /* must be power of two */ 20 HASHMUL = 79L, 21 }; 22 23 /* in [$OS].c */ 24 int _is5(char*), 25 _is6(char*), 26 _is8(char*), 27 _is9(char*), 28 _isk(char*), 29 _isq(char*), 30 _isv(char*), 31 _read5(Biobuf*, Prog*), 32 _read6(Biobuf*, Prog*), 33 _read8(Biobuf*, Prog*), 34 _read9(Biobuf*, Prog*), 35 _readk(Biobuf*, Prog*), 36 _readq(Biobuf*, Prog*), 37 _readv(Biobuf*, Prog*); 38 39 typedef struct Obj Obj; 40 typedef struct Symtab Symtab; 41 42 struct Obj /* functions to handle each intermediate (.$O) file */ 43 { 44 char *name; /* name of each $O file */ 45 int (*is)(char*); /* test for each type of $O file */ 46 int (*read)(Biobuf*, Prog*); /* read for each type of $O file*/ 47 }; 48 49 static Obj obj[] = 50 { /* functions to identify and parse each type of obj */ 51 /*[Obj68020]*/ {0, 0,}, 52 /*[ObjSparc]*/ "sparc .k", _isk, _readk, 53 /*[ObjMips]*/ "mips .v", _isv, _readv, 54 /*[Obj386]*/ "386 .8", _is8, _read8, 55 /*[Obj960]*/ {0, 0,}, 56 /*[Obj3210]*/ {0, 0,}, 57 /*[ObjMips2]*/ {0, 0,}, 58 /*[Obj29000]*/ {0, 0,}, 59 /*[ObjArm]*/ "arm .5", _is5, _read5, 60 /*[ObjPower]*/ "power .q", _isq, _readq, 61 /*[ObjMips2le]*/ {0, 0,}, 62 /*[ObjAlpha]*/ {0, 0,}, 63 /*[ObjSparc64]*/ {0, 0,}, 64 /*[ObjAmd64]*/ "amd64 .6", _is6, _read6, 65 /*[ObjSpim]*/ {0, 0,}, 66 /*[ObjPower64]*/ "power64 .9", _is9, _read9, 67 /*[Maxobjtype]*/ 0, 0 68 }; 69 70 struct Symtab 71 { 72 struct Sym s; 73 struct Symtab *next; 74 }; 75 76 static Symtab *hash[NHASH]; 77 static Sym *names[NNAMES]; /* working set of active names */ 78 79 static int processprog(Prog*,int); /* decode each symbol reference */ 80 static void objreset(void); 81 static void objlookup(int, char *, int, uint); 82 static void objupdate(int, int); 83 84 int 85 objtype(Biobuf *bp, char **name) 86 { 87 int i; 88 char buf[MAXIS]; 89 90 if(Bread(bp, buf, MAXIS) < MAXIS) 91 return -1; 92 Bseek(bp, -MAXIS, 1); 93 for (i = 0; i < Maxobjtype; i++) { 94 if (obj[i].is && (*obj[i].is)(buf)) { 95 if (name) 96 *name = obj[i].name; 97 return i; 98 } 99 } 100 return -1; 101 } 102 103 int 104 isar(Biobuf *bp) 105 { 106 int n; 107 char magbuf[SARMAG]; 108 109 n = Bread(bp, magbuf, SARMAG); 110 if(n == SARMAG && strncmp(magbuf, ARMAG, SARMAG) == 0) 111 return 1; 112 return 0; 113 } 114 115 /* 116 * determine what kind of object file this is and process it. 117 * return whether or not this was a recognized intermediate file. 118 */ 119 int 120 readobj(Biobuf *bp, int objtype) 121 { 122 Prog p; 123 124 if (objtype < 0 || objtype >= Maxobjtype || obj[objtype].is == 0) 125 return 1; 126 objreset(); 127 while ((*obj[objtype].read)(bp, &p)) 128 if (!processprog(&p, 1)) 129 return 0; 130 return 1; 131 } 132 133 int 134 readar(Biobuf *bp, int objtype, vlong end, int doautos) 135 { 136 Prog p; 137 138 if (objtype < 0 || objtype >= Maxobjtype || obj[objtype].is == 0) 139 return 1; 140 objreset(); 141 while ((*obj[objtype].read)(bp, &p) && Boffset(bp) < end) 142 if (!processprog(&p, doautos)) 143 return 0; 144 return 1; 145 } 146 147 /* 148 * decode a symbol reference or definition 149 */ 150 static int 151 processprog(Prog *p, int doautos) 152 { 153 if(p->kind == aNone) 154 return 1; 155 if(p->sym < 0 || p->sym >= NNAMES) 156 return 0; 157 switch(p->kind) 158 { 159 case aName: 160 if (!doautos) 161 if(p->type != 'U' && p->type != 'b') 162 break; 163 objlookup(p->sym, p->id, p->type, p->sig); 164 break; 165 case aText: 166 objupdate(p->sym, 'T'); 167 break; 168 case aData: 169 objupdate(p->sym, 'D'); 170 break; 171 default: 172 break; 173 } 174 return 1; 175 } 176 177 /* 178 * find the entry for s in the symbol array. 179 * make a new entry if it is not already there. 180 */ 181 static void 182 objlookup(int id, char *name, int type, uint sig) 183 { 184 long h; 185 char *cp; 186 Sym *s; 187 Symtab *sp; 188 189 s = names[id]; 190 if(s && strcmp(s->name, name) == 0) { 191 s->type = type; 192 s->sig = sig; 193 return; 194 } 195 196 h = *name; 197 for(cp = name+1; *cp; h += *cp++) 198 h *= HASHMUL; 199 if(h < 0) 200 h = ~h; 201 h &= (NHASH-1); 202 if (type == 'U' || type == 'b' || islocal(type)) { 203 for(sp = hash[h]; sp; sp = sp->next) 204 if(strcmp(sp->s.name, name) == 0) { 205 switch(sp->s.type) { 206 case 'T': 207 case 'D': 208 case 'U': 209 if (type == 'U') { 210 names[id] = &sp->s; 211 return; 212 } 213 break; 214 case 't': 215 case 'd': 216 case 'b': 217 if (type == 'b') { 218 names[id] = &sp->s; 219 return; 220 } 221 break; 222 case 'a': 223 case 'p': 224 if (islocal(type)) { 225 names[id] = &sp->s; 226 return; 227 } 228 break; 229 default: 230 break; 231 } 232 } 233 } 234 sp = malloc(sizeof(Symtab)); 235 sp->s.name = name; 236 sp->s.type = type; 237 sp->s.sig = sig; 238 sp->s.value = islocal(type) ? MAXOFF : 0; 239 names[id] = &sp->s; 240 sp->next = hash[h]; 241 hash[h] = sp; 242 return; 243 } 244 /* 245 * traverse the symbol lists 246 */ 247 void 248 objtraverse(void (*fn)(Sym*, void*), void *pointer) 249 { 250 int i; 251 Symtab *s; 252 253 for(i = 0; i < NHASH; i++) 254 for(s = hash[i]; s; s = s->next) 255 (*fn)(&s->s, pointer); 256 } 257 258 /* 259 * update the offset information for a 'a' or 'p' symbol in an intermediate file 260 */ 261 void 262 _offset(int id, vlong off) 263 { 264 Sym *s; 265 266 s = names[id]; 267 if (s && s->name[0] && islocal(s->type) && s->value > off) 268 s->value = off; 269 } 270 271 /* 272 * update the type of a global text or data symbol 273 */ 274 static void 275 objupdate(int id, int type) 276 { 277 Sym *s; 278 279 s = names[id]; 280 if (s && s->name[0]) 281 if (s->type == 'U') 282 s->type = type; 283 else if (s->type == 'b') 284 s->type = tolower(type); 285 } 286 287 /* 288 * look for the next file in an archive 289 */ 290 int 291 nextar(Biobuf *bp, int offset, char *buf) 292 { 293 struct ar_hdr a; 294 int i, r; 295 long arsize; 296 297 if (offset&01) 298 offset++; 299 Bseek(bp, offset, 0); 300 r = Bread(bp, &a, SAR_HDR); 301 if(r != SAR_HDR) 302 return 0; 303 if(strncmp(a.fmag, ARFMAG, sizeof(a.fmag))) 304 return -1; 305 for(i=0; i<sizeof(a.name) && i<SARNAME && a.name[i] != ' '; i++) 306 buf[i] = a.name[i]; 307 buf[i] = 0; 308 arsize = strtol(a.size, 0, 0); 309 if (arsize&1) 310 arsize++; 311 return arsize + SAR_HDR; 312 } 313 314 static void 315 objreset(void) 316 { 317 int i; 318 Symtab *s, *n; 319 320 for(i = 0; i < NHASH; i++) { 321 for(s = hash[i]; s; s = n) { 322 n = s->next; 323 free(s->s.name); 324 free(s); 325 } 326 hash[i] = 0; 327 } 328 memset(names, 0, sizeof names); 329 } 330