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