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