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