13e12c5d1SDavid du Colombier /* 23e12c5d1SDavid du Colombier * obj.c 33e12c5d1SDavid du Colombier * routines universal to all object files 43e12c5d1SDavid du Colombier */ 53e12c5d1SDavid du Colombier #include <u.h> 63e12c5d1SDavid du Colombier #include <libc.h> 73e12c5d1SDavid du Colombier #include <bio.h> 8bd389b36SDavid du Colombier #include <ar.h> 9bd389b36SDavid du Colombier #include <mach.h> 103e12c5d1SDavid du Colombier #include "obj.h" 11bd389b36SDavid du Colombier 12bd389b36SDavid du Colombier #define islocal(t) ((t)=='a' || (t)=='p') 13bd389b36SDavid du Colombier 14bd389b36SDavid du Colombier enum 15bd389b36SDavid du Colombier { 16bd389b36SDavid du Colombier NNAMES = 50, 17bd389b36SDavid du Colombier MAXIS = 8, /* max length to determine if a file is a .? file */ 18bd389b36SDavid du Colombier MAXOFF = 0x7fffffff, /* larger than any possible local offset */ 19*219b2ee8SDavid du Colombier NHASH = 1024, /* must be power of two */ 20*219b2ee8SDavid du Colombier HASHMUL = 79L, 21bd389b36SDavid du Colombier }; 22bd389b36SDavid du Colombier 23bd389b36SDavid du Colombier int _is2(char*), /* in [$OS].c */ 24bd389b36SDavid du Colombier _is6(char*), 25bd389b36SDavid du Colombier _is8(char*), 26bd389b36SDavid du Colombier _isk(char*), 27bd389b36SDavid du Colombier _isv(char*), 28*219b2ee8SDavid du Colombier _isx(char*), 29bd389b36SDavid du Colombier _read2(Biobuf*, Prog*), 30bd389b36SDavid du Colombier _read6(Biobuf*, Prog*), 31bd389b36SDavid du Colombier _read8(Biobuf*, Prog*), 32bd389b36SDavid du Colombier _readk(Biobuf*, Prog*), 33bd389b36SDavid du Colombier _readv(Biobuf*, Prog*), 34*219b2ee8SDavid du Colombier _readx(Biobuf*, Prog*); 353e12c5d1SDavid du Colombier 363e12c5d1SDavid du Colombier typedef struct Obj Obj; 37*219b2ee8SDavid du Colombier typedef struct Symtab Symtab; 383e12c5d1SDavid du Colombier 39bd389b36SDavid du Colombier struct Obj /* functions to handle each intermediate (.$O) file */ 40bd389b36SDavid du Colombier { 41*219b2ee8SDavid du Colombier char *name; /* name of each $O file */ 42bd389b36SDavid du Colombier int (*is)(char*); /* test for each type of $O file */ 43bd389b36SDavid du Colombier int (*read)(Biobuf*, Prog*); /* read for each type of $O file*/ 443e12c5d1SDavid du Colombier }; 453e12c5d1SDavid du Colombier 46bd389b36SDavid du Colombier static Obj obj[] = 47bd389b36SDavid du Colombier { /* functions to identify and parse each type of obj */ 48*219b2ee8SDavid du Colombier [Obj68020] "68020 .2", _is2, _read2, 49*219b2ee8SDavid du Colombier [ObjSparc] "sparc .k", _isk, _readk, 50*219b2ee8SDavid du Colombier [ObjMips] "mips .v", _isv, _readv, 51*219b2ee8SDavid du Colombier [Obj386] "386 .8", _is8, _read8, 52*219b2ee8SDavid du Colombier [Obj960] "960 .6", _is6, _read6, 53*219b2ee8SDavid du Colombier [Obj3210] "3210 .x", _isx, _readx, 54bd389b36SDavid du Colombier [Maxobjtype] 0, 0 553e12c5d1SDavid du Colombier }; 563e12c5d1SDavid du Colombier 57*219b2ee8SDavid du Colombier struct Symtab 58*219b2ee8SDavid du Colombier { 59*219b2ee8SDavid du Colombier struct Sym s; 60*219b2ee8SDavid du Colombier struct Symtab *next; 61*219b2ee8SDavid du Colombier }; 623e12c5d1SDavid du Colombier 63*219b2ee8SDavid du Colombier static Symtab *hash[NHASH]; 64*219b2ee8SDavid du Colombier static Sym *names[NNAMES]; /* working set of active names */ 65*219b2ee8SDavid du Colombier 66*219b2ee8SDavid du Colombier static int processprog(Prog*,int); /* decode each symbol reference */ 67*219b2ee8SDavid du Colombier static void objreset(void); 68bd389b36SDavid du Colombier static void objlookup(int, char *, int ); 69*219b2ee8SDavid du Colombier static void objupdate(int, int); 703e12c5d1SDavid du Colombier 71bd389b36SDavid du Colombier int 72*219b2ee8SDavid du Colombier objtype(Biobuf *bp, char **name) 73bd389b36SDavid du Colombier { 74bd389b36SDavid du Colombier int i; 75bd389b36SDavid du Colombier char buf[MAXIS]; 76bd389b36SDavid du Colombier 77bd389b36SDavid du Colombier if(Bread(bp, buf, MAXIS) < MAXIS) 78bd389b36SDavid du Colombier return -1; 79bd389b36SDavid du Colombier Bseek(bp, -MAXIS, 1); 80bd389b36SDavid du Colombier for (i = 0; obj[i].is; i++) { 81*219b2ee8SDavid du Colombier if ((*obj[i].is)(buf)) { 82*219b2ee8SDavid du Colombier if (name) 83*219b2ee8SDavid du Colombier *name = obj[i].name; 84bd389b36SDavid du Colombier return i; 85bd389b36SDavid du Colombier } 86*219b2ee8SDavid du Colombier } 87bd389b36SDavid du Colombier return -1; 88bd389b36SDavid du Colombier } 89bd389b36SDavid du Colombier 90bd389b36SDavid du Colombier int 91bd389b36SDavid du Colombier isar(Biobuf *bp) 92bd389b36SDavid du Colombier { 93bd389b36SDavid du Colombier int n; 94bd389b36SDavid du Colombier char magbuf[SARMAG]; 95bd389b36SDavid du Colombier 96bd389b36SDavid du Colombier n = Bread(bp, magbuf, SARMAG); 97bd389b36SDavid du Colombier if(n == SARMAG && strncmp(magbuf, ARMAG, SARMAG) == 0) 98bd389b36SDavid du Colombier return 1; 99bd389b36SDavid du Colombier return 0; 100bd389b36SDavid du Colombier } 1013e12c5d1SDavid du Colombier 1023e12c5d1SDavid du Colombier /* 1033e12c5d1SDavid du Colombier * determine what kind of object file this is and process it. 1043e12c5d1SDavid du Colombier * return whether or not this was a recognized intermediate file. 1053e12c5d1SDavid du Colombier */ 1063e12c5d1SDavid du Colombier int 107bd389b36SDavid du Colombier readobj(Biobuf *bp, int objtype) 1083e12c5d1SDavid du Colombier { 1093e12c5d1SDavid du Colombier Prog p; 1103e12c5d1SDavid du Colombier 111bd389b36SDavid du Colombier if (objtype < 0 || objtype >= Maxobjtype) 112bd389b36SDavid du Colombier return 1; 113*219b2ee8SDavid du Colombier objreset(); 114bd389b36SDavid du Colombier while ((*obj[objtype].read)(bp, &p)) 115*219b2ee8SDavid du Colombier if (!processprog(&p, 1)) 116bd389b36SDavid du Colombier return 0; 117bd389b36SDavid du Colombier return 1; 1183e12c5d1SDavid du Colombier } 119bd389b36SDavid du Colombier 120bd389b36SDavid du Colombier int 121*219b2ee8SDavid du Colombier readar(Biobuf *bp, int objtype, int end, int doautos) 122bd389b36SDavid du Colombier { 123bd389b36SDavid du Colombier Prog p; 124bd389b36SDavid du Colombier 125bd389b36SDavid du Colombier if (objtype < 0 || objtype >= Maxobjtype) 126bd389b36SDavid du Colombier return 1; 127*219b2ee8SDavid du Colombier objreset(); 128bd389b36SDavid du Colombier while ((*obj[objtype].read)(bp, &p) && BOFFSET(bp) < end) 129*219b2ee8SDavid du Colombier if (!processprog(&p, doautos)) 130bd389b36SDavid du Colombier return 0; 131bd389b36SDavid du Colombier return 1; 132bd389b36SDavid du Colombier } 133bd389b36SDavid du Colombier 134bd389b36SDavid du Colombier /* 135bd389b36SDavid du Colombier * decode a symbol reference or definition 136bd389b36SDavid du Colombier */ 137bd389b36SDavid du Colombier static int 138*219b2ee8SDavid du Colombier processprog(Prog *p, int doautos) 139bd389b36SDavid du Colombier { 140bd389b36SDavid du Colombier if(p->kind == aNone) 141bd389b36SDavid du Colombier return 1; 142bd389b36SDavid du Colombier if(p->sym < 0 || p->sym >= NNAMES) 143bd389b36SDavid du Colombier return 0; 144bd389b36SDavid du Colombier switch(p->kind) 145bd389b36SDavid du Colombier { 1463e12c5d1SDavid du Colombier case aName: 147*219b2ee8SDavid du Colombier if (!doautos) 148*219b2ee8SDavid du Colombier if(p->type != 'U' && p->type != 'b') 149*219b2ee8SDavid du Colombier break; 150bd389b36SDavid du Colombier objlookup(p->sym, p->id, p->type); 1513e12c5d1SDavid du Colombier break; 1523e12c5d1SDavid du Colombier case aText: 153bd389b36SDavid du Colombier objupdate(p->sym, 'T'); 1543e12c5d1SDavid du Colombier break; 1553e12c5d1SDavid du Colombier case aData: 156bd389b36SDavid du Colombier objupdate(p->sym, 'D'); 157bd389b36SDavid du Colombier break; 158bd389b36SDavid du Colombier default: 1593e12c5d1SDavid du Colombier break; 1603e12c5d1SDavid du Colombier } 161bd389b36SDavid du Colombier return 1; 1623e12c5d1SDavid du Colombier } 1633e12c5d1SDavid du Colombier 1643e12c5d1SDavid du Colombier /* 1653e12c5d1SDavid du Colombier * find the entry for s in the symbol array. 1663e12c5d1SDavid du Colombier * make a new entry if it is not already there. 1673e12c5d1SDavid du Colombier */ 168bd389b36SDavid du Colombier static void 169bd389b36SDavid du Colombier objlookup(int id, char *name, int type) 1703e12c5d1SDavid du Colombier { 171*219b2ee8SDavid du Colombier long h; 172*219b2ee8SDavid du Colombier char *cp; 1733e12c5d1SDavid du Colombier Sym *s; 174*219b2ee8SDavid du Colombier Symtab *sp; 1753e12c5d1SDavid du Colombier 176*219b2ee8SDavid du Colombier s = names[id]; 177*219b2ee8SDavid du Colombier if(s && strcmp(s->name, name) == 0) { 1783e12c5d1SDavid du Colombier s->type = type; 179bd389b36SDavid du Colombier return; 1803e12c5d1SDavid du Colombier } 181*219b2ee8SDavid du Colombier 182*219b2ee8SDavid du Colombier h = *name; 183*219b2ee8SDavid du Colombier for(cp = name+1; *cp; h += *cp++) 184*219b2ee8SDavid du Colombier h *= HASHMUL; 185*219b2ee8SDavid du Colombier if(h < 0) 186*219b2ee8SDavid du Colombier h = ~h; 187*219b2ee8SDavid du Colombier h &= (NHASH-1); 188*219b2ee8SDavid du Colombier if (type == 'U' || type == 'b' || islocal(type)) { 189*219b2ee8SDavid du Colombier for(sp = hash[h]; sp; sp = sp->next) 190*219b2ee8SDavid du Colombier if(strcmp(sp->s.name, name) == 0) { 191*219b2ee8SDavid du Colombier switch(sp->s.type) { 1923e12c5d1SDavid du Colombier case 'T': 1933e12c5d1SDavid du Colombier case 'D': 1943e12c5d1SDavid du Colombier case 'U': 1953e12c5d1SDavid du Colombier if (type == 'U') { 196*219b2ee8SDavid du Colombier names[id] = &sp->s; 197bd389b36SDavid du Colombier return; 1983e12c5d1SDavid du Colombier } 1993e12c5d1SDavid du Colombier break; 2003e12c5d1SDavid du Colombier case 't': 2013e12c5d1SDavid du Colombier case 'd': 2023e12c5d1SDavid du Colombier case 'b': 2033e12c5d1SDavid du Colombier if (type == 'b') { 204*219b2ee8SDavid du Colombier names[id] = &sp->s; 205bd389b36SDavid du Colombier return; 2063e12c5d1SDavid du Colombier } 2073e12c5d1SDavid du Colombier break; 2083e12c5d1SDavid du Colombier case 'a': 2093e12c5d1SDavid du Colombier case 'p': 210*219b2ee8SDavid du Colombier if (islocal(type)) { 211*219b2ee8SDavid du Colombier names[id] = &sp->s; 212bd389b36SDavid du Colombier return; 2133e12c5d1SDavid du Colombier } 2143e12c5d1SDavid du Colombier break; 2153e12c5d1SDavid du Colombier default: 2163e12c5d1SDavid du Colombier break; 2173e12c5d1SDavid du Colombier } 218bd389b36SDavid du Colombier } 219bd389b36SDavid du Colombier } 220*219b2ee8SDavid du Colombier sp = malloc(sizeof(Symtab)); 221*219b2ee8SDavid du Colombier sp->s.name = name; 222*219b2ee8SDavid du Colombier sp->s.type = type; 223*219b2ee8SDavid du Colombier sp->s.value = islocal(type) ? MAXOFF : 0; 224*219b2ee8SDavid du Colombier names[id] = &sp->s; 225*219b2ee8SDavid du Colombier sp->next = hash[h]; 226*219b2ee8SDavid du Colombier hash[h] = sp; 227bd389b36SDavid du Colombier return; 228bd389b36SDavid du Colombier } 229bd389b36SDavid du Colombier /* 230*219b2ee8SDavid du Colombier * traverse the symbol lists 231bd389b36SDavid du Colombier */ 232*219b2ee8SDavid du Colombier void 233*219b2ee8SDavid du Colombier objtraverse(void (*fn)(Sym*, void*), void *pointer) 234bd389b36SDavid du Colombier { 235*219b2ee8SDavid du Colombier int i; 236*219b2ee8SDavid du Colombier Symtab *s; 237*219b2ee8SDavid du Colombier 238*219b2ee8SDavid du Colombier for(i = 0; i < NHASH; i++) 239*219b2ee8SDavid du Colombier for(s = hash[i]; s; s = s->next) 240*219b2ee8SDavid du Colombier (*fn)(&s->s, pointer); 2413e12c5d1SDavid du Colombier } 2423e12c5d1SDavid du Colombier 2433e12c5d1SDavid du Colombier /* 2443e12c5d1SDavid du Colombier * update the offset information for a 'a' or 'p' symbol in an intermediate file 2453e12c5d1SDavid du Colombier */ 2463e12c5d1SDavid du Colombier void 247bd389b36SDavid du Colombier _offset(int id, long off) 2483e12c5d1SDavid du Colombier { 2493e12c5d1SDavid du Colombier Sym *s; 2503e12c5d1SDavid du Colombier 251*219b2ee8SDavid du Colombier s = names[id]; 252*219b2ee8SDavid du Colombier if (s && s->name[0] && islocal(s->type) && s->value > off) 2533e12c5d1SDavid du Colombier s->value = off; 2543e12c5d1SDavid du Colombier } 2553e12c5d1SDavid du Colombier 2563e12c5d1SDavid du Colombier /* 2573e12c5d1SDavid du Colombier * update the type of a global text or data symbol 2583e12c5d1SDavid du Colombier */ 259*219b2ee8SDavid du Colombier static void 260bd389b36SDavid du Colombier objupdate(int id, int type) 2613e12c5d1SDavid du Colombier { 2623e12c5d1SDavid du Colombier Sym *s; 2633e12c5d1SDavid du Colombier 264*219b2ee8SDavid du Colombier s = names[id]; 265*219b2ee8SDavid du Colombier if (s && s->name[0]) 266*219b2ee8SDavid du Colombier if (s->type == 'U') 2673e12c5d1SDavid du Colombier s->type = type; 268*219b2ee8SDavid du Colombier else if (s->type == 'b') 2693e12c5d1SDavid du Colombier s->type = tolower(type); 2703e12c5d1SDavid du Colombier } 2713e12c5d1SDavid du Colombier 2723e12c5d1SDavid du Colombier /* 2733e12c5d1SDavid du Colombier * look for the next file in an archive 2743e12c5d1SDavid du Colombier */ 2753e12c5d1SDavid du Colombier int 276bd389b36SDavid du Colombier nextar(Biobuf *bp, int offset, char *buf) 2773e12c5d1SDavid du Colombier { 2783e12c5d1SDavid du Colombier struct ar_hdr a; 2793e12c5d1SDavid du Colombier int i, r; 2803e12c5d1SDavid du Colombier long arsize; 281bd389b36SDavid du Colombier 282bd389b36SDavid du Colombier if (offset&01) 283bd389b36SDavid du Colombier offset++; 284bd389b36SDavid du Colombier Bseek(bp, offset, 0); 285bd389b36SDavid du Colombier r = Bread(bp, &a, SAR_HDR); 2863e12c5d1SDavid du Colombier if(r != SAR_HDR) 2873e12c5d1SDavid du Colombier return 0; 288bd389b36SDavid du Colombier if(strncmp(a.fmag, ARFMAG, sizeof(a.fmag))) 289bd389b36SDavid du Colombier return -1; 290*219b2ee8SDavid du Colombier for(i=0; i<sizeof(a.name) && i<SARNAME && a.name[i] != ' '; i++) 291bd389b36SDavid du Colombier buf[i] = a.name[i]; 292bd389b36SDavid du Colombier buf[i] = 0; 2933e12c5d1SDavid du Colombier arsize = atol(a.size); 294bd389b36SDavid du Colombier if (arsize&1) 295bd389b36SDavid du Colombier arsize++; 296bd389b36SDavid du Colombier return arsize + SAR_HDR; 2973e12c5d1SDavid du Colombier } 2983e12c5d1SDavid du Colombier 299bd389b36SDavid du Colombier static void 300bd389b36SDavid du Colombier objreset(void) 301bd389b36SDavid du Colombier { 302*219b2ee8SDavid du Colombier int i; 303*219b2ee8SDavid du Colombier Symtab *s, *n; 304*219b2ee8SDavid du Colombier 305*219b2ee8SDavid du Colombier for(i = 0; i < NHASH; i++) { 306*219b2ee8SDavid du Colombier for(s = hash[i]; s; s = n) { 307*219b2ee8SDavid du Colombier n = s->next; 308*219b2ee8SDavid du Colombier free(s->s.name); 309*219b2ee8SDavid du Colombier free(s); 3103e12c5d1SDavid du Colombier } 311*219b2ee8SDavid du Colombier hash[i] = 0; 312*219b2ee8SDavid du Colombier } 313*219b2ee8SDavid du Colombier memset(names, 0, sizeof names); 3143e12c5d1SDavid du Colombier } 315