1 /* 2 * obj.c 3 * routines universal to all object files 4 */ 5 #include <u.h> 6 #include <libc.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 int _is2(char*), /* in [$OS].c */ 24 _is5(char*), 25 _is6(char*), 26 _is7(char*), 27 _is8(char*), 28 _is9(char*), 29 _isk(char*), 30 _isq(char*), 31 _isv(char*), 32 _isu(char*), 33 _read2(Biobuf*, Prog*), 34 _read5(Biobuf*, Prog*), 35 _read6(Biobuf*, Prog*), 36 _read7(Biobuf*, Prog*), 37 _read8(Biobuf*, Prog*), 38 _read9(Biobuf*, Prog*), 39 _readk(Biobuf*, Prog*), 40 _readq(Biobuf*, Prog*), 41 _readv(Biobuf*, Prog*), 42 _readu(Biobuf*, Prog*); 43 44 typedef struct Obj Obj; 45 typedef struct Symtab Symtab; 46 47 struct Obj /* functions to handle each intermediate (.$O) file */ 48 { 49 char *name; /* name of each $O file */ 50 int (*is)(char*); /* test for each type of $O file */ 51 int (*read)(Biobuf*, Prog*); /* read for each type of $O file*/ 52 }; 53 54 static Obj obj[] = 55 { /* functions to identify and parse each type of obj */ 56 [Obj68020] "68020 .2", _is2, _read2, 57 [ObjAmd64] "amd64 .6", _is6, _read6, 58 [ObjArm] "arm .5", _is5, _read5, 59 [ObjAlpha] "alpha .7", _is7, _read7, 60 [Obj386] "386 .8", _is8, _read8, 61 [ObjSparc] "sparc .k", _isk, _readk, 62 [ObjPower] "power .q", _isq, _readq, 63 [ObjMips] "mips .v", _isv, _readv, 64 [ObjSparc64] "sparc64 .u", _isu, _readu, 65 [ObjPower64] "power64 .9", _is9, _read9, 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, uint); 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, vlong 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, p->sig); 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, uint sig) 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 s->sig = sig; 192 return; 193 } 194 195 h = *name; 196 for(cp = name+1; *cp; h += *cp++) 197 h *= HASHMUL; 198 if(h < 0) 199 h = ~h; 200 h &= (NHASH-1); 201 if (type == 'U' || type == 'b' || islocal(type)) { 202 for(sp = hash[h]; sp; sp = sp->next) 203 if(strcmp(sp->s.name, name) == 0) { 204 switch(sp->s.type) { 205 case 'T': 206 case 'D': 207 case 'U': 208 if (type == 'U') { 209 names[id] = &sp->s; 210 return; 211 } 212 break; 213 case 't': 214 case 'd': 215 case 'b': 216 if (type == 'b') { 217 names[id] = &sp->s; 218 return; 219 } 220 break; 221 case 'a': 222 case 'p': 223 if (islocal(type)) { 224 names[id] = &sp->s; 225 return; 226 } 227 break; 228 default: 229 break; 230 } 231 } 232 } 233 sp = malloc(sizeof(Symtab)); 234 sp->s.name = name; 235 sp->s.type = type; 236 sp->s.sig = sig; 237 sp->s.value = islocal(type) ? MAXOFF : 0; 238 names[id] = &sp->s; 239 sp->next = hash[h]; 240 hash[h] = sp; 241 return; 242 } 243 /* 244 * traverse the symbol lists 245 */ 246 void 247 objtraverse(void (*fn)(Sym*, void*), void *pointer) 248 { 249 int i; 250 Symtab *s; 251 252 for(i = 0; i < NHASH; i++) 253 for(s = hash[i]; s; s = s->next) 254 (*fn)(&s->s, pointer); 255 } 256 257 /* 258 * update the offset information for a 'a' or 'p' symbol in an intermediate file 259 */ 260 void 261 _offset(int id, vlong off) 262 { 263 Sym *s; 264 265 s = names[id]; 266 if (s && s->name[0] && islocal(s->type) && s->value > off) 267 s->value = off; 268 } 269 270 /* 271 * update the type of a global text or data symbol 272 */ 273 static void 274 objupdate(int id, int type) 275 { 276 Sym *s; 277 278 s = names[id]; 279 if (s && s->name[0]) 280 if (s->type == 'U') 281 s->type = type; 282 else if (s->type == 'b') 283 s->type = tolower(type); 284 } 285 286 /* 287 * look for the next file in an archive 288 */ 289 int 290 nextar(Biobuf *bp, int offset, char *buf) 291 { 292 struct ar_hdr a; 293 int i, r; 294 long arsize; 295 296 if (offset&01) 297 offset++; 298 Bseek(bp, offset, 0); 299 r = Bread(bp, &a, SAR_HDR); 300 if(r != SAR_HDR) 301 return 0; 302 if(strncmp(a.fmag, ARFMAG, sizeof(a.fmag))) 303 return -1; 304 for(i=0; i<sizeof(a.name) && i<SARNAME && a.name[i] != ' '; i++) 305 buf[i] = a.name[i]; 306 buf[i] = 0; 307 arsize = strtol(a.size, 0, 0); 308 if (arsize&1) 309 arsize++; 310 return arsize + SAR_HDR; 311 } 312 313 static void 314 objreset(void) 315 { 316 int i; 317 Symtab *s, *n; 318 319 for(i = 0; i < NHASH; i++) { 320 for(s = hash[i]; s; s = n) { 321 n = s->next; 322 free(s->s.name); 323 free(s); 324 } 325 hash[i] = 0; 326 } 327 memset(names, 0, sizeof names); 328 } 329