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 */ 19219b2ee8SDavid du Colombier NHASH = 1024, /* must be power of two */ 20219b2ee8SDavid du Colombier HASHMUL = 79L, 21bd389b36SDavid du Colombier }; 22bd389b36SDavid du Colombier 23bd389b36SDavid du Colombier int _is2(char*), /* in [$OS].c */ 247dd7cddfSDavid du Colombier _is5(char*), 25b0dcc5a8SDavid du Colombier _is6(char*), 267dd7cddfSDavid du Colombier _is7(char*), 27bd389b36SDavid du Colombier _is8(char*), 28bd389b36SDavid du Colombier _isk(char*), 297dd7cddfSDavid du Colombier _isq(char*), 30bd389b36SDavid du Colombier _isv(char*), 31b0dcc5a8SDavid du Colombier _isu(char*), 32bd389b36SDavid du Colombier _read2(Biobuf*, Prog*), 337dd7cddfSDavid du Colombier _read5(Biobuf*, Prog*), 34b0dcc5a8SDavid du Colombier _read6(Biobuf*, Prog*), 357dd7cddfSDavid du Colombier _read7(Biobuf*, Prog*), 36bd389b36SDavid du Colombier _read8(Biobuf*, Prog*), 37bd389b36SDavid du Colombier _readk(Biobuf*, Prog*), 387dd7cddfSDavid du Colombier _readq(Biobuf*, Prog*), 39b0dcc5a8SDavid du Colombier _readv(Biobuf*, Prog*), 40b0dcc5a8SDavid du Colombier _readu(Biobuf*, Prog*); 413e12c5d1SDavid du Colombier 423e12c5d1SDavid du Colombier typedef struct Obj Obj; 43219b2ee8SDavid du Colombier typedef struct Symtab Symtab; 443e12c5d1SDavid du Colombier 45bd389b36SDavid du Colombier struct Obj /* functions to handle each intermediate (.$O) file */ 46bd389b36SDavid du Colombier { 47219b2ee8SDavid du Colombier char *name; /* name of each $O file */ 48bd389b36SDavid du Colombier int (*is)(char*); /* test for each type of $O file */ 49bd389b36SDavid du Colombier int (*read)(Biobuf*, Prog*); /* read for each type of $O file*/ 503e12c5d1SDavid du Colombier }; 513e12c5d1SDavid du Colombier 52bd389b36SDavid du Colombier static Obj obj[] = 53bd389b36SDavid du Colombier { /* functions to identify and parse each type of obj */ 54219b2ee8SDavid du Colombier [Obj68020] "68020 .2", _is2, _read2, 55b0dcc5a8SDavid du Colombier [ObjAmd64] "amd64 .6", _is6, _read6, 567dd7cddfSDavid du Colombier [ObjArm] "arm .5", _is5, _read5, 577dd7cddfSDavid du Colombier [ObjAlpha] "alpha .7", _is7, _read7, 58375daca8SDavid du Colombier [Obj386] "386 .8", _is8, _read8, 59375daca8SDavid du Colombier [ObjSparc] "sparc .k", _isk, _readk, 60375daca8SDavid du Colombier [ObjPower] "power .q", _isq, _readq, 61375daca8SDavid du Colombier [ObjMips] "mips .v", _isv, _readv, 62b0dcc5a8SDavid du Colombier [ObjSparc64] "sparc64 .u", _isu, _readu, 63bd389b36SDavid du Colombier [Maxobjtype] 0, 0 643e12c5d1SDavid du Colombier }; 653e12c5d1SDavid du Colombier 66219b2ee8SDavid du Colombier struct Symtab 67219b2ee8SDavid du Colombier { 68219b2ee8SDavid du Colombier struct Sym s; 69219b2ee8SDavid du Colombier struct Symtab *next; 70219b2ee8SDavid du Colombier }; 713e12c5d1SDavid du Colombier 72219b2ee8SDavid du Colombier static Symtab *hash[NHASH]; 73219b2ee8SDavid du Colombier static Sym *names[NNAMES]; /* working set of active names */ 74219b2ee8SDavid du Colombier 75219b2ee8SDavid du Colombier static int processprog(Prog*,int); /* decode each symbol reference */ 76219b2ee8SDavid du Colombier static void objreset(void); 77bd389b36SDavid du Colombier static void objlookup(int, char *, int ); 78219b2ee8SDavid du Colombier static void objupdate(int, int); 793e12c5d1SDavid du Colombier 80bd389b36SDavid du Colombier int 81219b2ee8SDavid du Colombier objtype(Biobuf *bp, char **name) 82bd389b36SDavid du Colombier { 83bd389b36SDavid du Colombier int i; 84bd389b36SDavid du Colombier char buf[MAXIS]; 85bd389b36SDavid du Colombier 86bd389b36SDavid du Colombier if(Bread(bp, buf, MAXIS) < MAXIS) 87bd389b36SDavid du Colombier return -1; 88bd389b36SDavid du Colombier Bseek(bp, -MAXIS, 1); 897dd7cddfSDavid du Colombier for (i = 0; i < Maxobjtype; i++) { 907dd7cddfSDavid du Colombier if (obj[i].is && (*obj[i].is)(buf)) { 91219b2ee8SDavid du Colombier if (name) 92219b2ee8SDavid du Colombier *name = obj[i].name; 93bd389b36SDavid du Colombier return i; 94bd389b36SDavid du Colombier } 95219b2ee8SDavid du Colombier } 96bd389b36SDavid du Colombier return -1; 97bd389b36SDavid du Colombier } 98bd389b36SDavid du Colombier 99bd389b36SDavid du Colombier int 100bd389b36SDavid du Colombier isar(Biobuf *bp) 101bd389b36SDavid du Colombier { 102bd389b36SDavid du Colombier int n; 103bd389b36SDavid du Colombier char magbuf[SARMAG]; 104bd389b36SDavid du Colombier 105bd389b36SDavid du Colombier n = Bread(bp, magbuf, SARMAG); 106bd389b36SDavid du Colombier if(n == SARMAG && strncmp(magbuf, ARMAG, SARMAG) == 0) 107bd389b36SDavid du Colombier return 1; 108bd389b36SDavid du Colombier return 0; 109bd389b36SDavid du Colombier } 1103e12c5d1SDavid du Colombier 1113e12c5d1SDavid du Colombier /* 1123e12c5d1SDavid du Colombier * determine what kind of object file this is and process it. 1133e12c5d1SDavid du Colombier * return whether or not this was a recognized intermediate file. 1143e12c5d1SDavid du Colombier */ 1153e12c5d1SDavid du Colombier int 116bd389b36SDavid du Colombier readobj(Biobuf *bp, int objtype) 1173e12c5d1SDavid du Colombier { 1183e12c5d1SDavid du Colombier Prog p; 1193e12c5d1SDavid du Colombier 1207dd7cddfSDavid du Colombier if (objtype < 0 || objtype >= Maxobjtype || obj[objtype].is == 0) 121bd389b36SDavid du Colombier return 1; 122219b2ee8SDavid du Colombier objreset(); 123bd389b36SDavid du Colombier while ((*obj[objtype].read)(bp, &p)) 124219b2ee8SDavid du Colombier if (!processprog(&p, 1)) 125bd389b36SDavid du Colombier return 0; 126bd389b36SDavid du Colombier return 1; 1273e12c5d1SDavid du Colombier } 128bd389b36SDavid du Colombier 129bd389b36SDavid du Colombier int 130*4de34a7eSDavid du Colombier readar(Biobuf *bp, int objtype, vlong end, int doautos) 131bd389b36SDavid du Colombier { 132bd389b36SDavid du Colombier Prog p; 133bd389b36SDavid du Colombier 1347dd7cddfSDavid du Colombier if (objtype < 0 || objtype >= Maxobjtype || obj[objtype].is == 0) 135bd389b36SDavid du Colombier return 1; 136219b2ee8SDavid du Colombier objreset(); 1377dd7cddfSDavid du Colombier while ((*obj[objtype].read)(bp, &p) && Boffset(bp) < end) 138219b2ee8SDavid du Colombier if (!processprog(&p, doautos)) 139bd389b36SDavid du Colombier return 0; 140bd389b36SDavid du Colombier return 1; 141bd389b36SDavid du Colombier } 142bd389b36SDavid du Colombier 143bd389b36SDavid du Colombier /* 144bd389b36SDavid du Colombier * decode a symbol reference or definition 145bd389b36SDavid du Colombier */ 146bd389b36SDavid du Colombier static int 147219b2ee8SDavid du Colombier processprog(Prog *p, int doautos) 148bd389b36SDavid du Colombier { 149bd389b36SDavid du Colombier if(p->kind == aNone) 150bd389b36SDavid du Colombier return 1; 151bd389b36SDavid du Colombier if(p->sym < 0 || p->sym >= NNAMES) 152bd389b36SDavid du Colombier return 0; 153bd389b36SDavid du Colombier switch(p->kind) 154bd389b36SDavid du Colombier { 1553e12c5d1SDavid du Colombier case aName: 156219b2ee8SDavid du Colombier if (!doautos) 157219b2ee8SDavid du Colombier if(p->type != 'U' && p->type != 'b') 158219b2ee8SDavid du Colombier break; 159bd389b36SDavid du Colombier objlookup(p->sym, p->id, p->type); 1603e12c5d1SDavid du Colombier break; 1613e12c5d1SDavid du Colombier case aText: 162bd389b36SDavid du Colombier objupdate(p->sym, 'T'); 1633e12c5d1SDavid du Colombier break; 1643e12c5d1SDavid du Colombier case aData: 165bd389b36SDavid du Colombier objupdate(p->sym, 'D'); 166bd389b36SDavid du Colombier break; 167bd389b36SDavid du Colombier default: 1683e12c5d1SDavid du Colombier break; 1693e12c5d1SDavid du Colombier } 170bd389b36SDavid du Colombier return 1; 1713e12c5d1SDavid du Colombier } 1723e12c5d1SDavid du Colombier 1733e12c5d1SDavid du Colombier /* 1743e12c5d1SDavid du Colombier * find the entry for s in the symbol array. 1753e12c5d1SDavid du Colombier * make a new entry if it is not already there. 1763e12c5d1SDavid du Colombier */ 177bd389b36SDavid du Colombier static void 178bd389b36SDavid du Colombier objlookup(int id, char *name, int type) 1793e12c5d1SDavid du Colombier { 180219b2ee8SDavid du Colombier long h; 181219b2ee8SDavid du Colombier char *cp; 1823e12c5d1SDavid du Colombier Sym *s; 183219b2ee8SDavid du Colombier Symtab *sp; 1843e12c5d1SDavid du Colombier 185219b2ee8SDavid du Colombier s = names[id]; 186219b2ee8SDavid du Colombier if(s && strcmp(s->name, name) == 0) { 1873e12c5d1SDavid du Colombier s->type = type; 188bd389b36SDavid du Colombier return; 1893e12c5d1SDavid du Colombier } 190219b2ee8SDavid du Colombier 191219b2ee8SDavid du Colombier h = *name; 192219b2ee8SDavid du Colombier for(cp = name+1; *cp; h += *cp++) 193219b2ee8SDavid du Colombier h *= HASHMUL; 194219b2ee8SDavid du Colombier if(h < 0) 195219b2ee8SDavid du Colombier h = ~h; 196219b2ee8SDavid du Colombier h &= (NHASH-1); 197219b2ee8SDavid du Colombier if (type == 'U' || type == 'b' || islocal(type)) { 198219b2ee8SDavid du Colombier for(sp = hash[h]; sp; sp = sp->next) 199219b2ee8SDavid du Colombier if(strcmp(sp->s.name, name) == 0) { 200219b2ee8SDavid du Colombier switch(sp->s.type) { 2013e12c5d1SDavid du Colombier case 'T': 2023e12c5d1SDavid du Colombier case 'D': 2033e12c5d1SDavid du Colombier case 'U': 2043e12c5d1SDavid du Colombier if (type == 'U') { 205219b2ee8SDavid du Colombier names[id] = &sp->s; 206bd389b36SDavid du Colombier return; 2073e12c5d1SDavid du Colombier } 2083e12c5d1SDavid du Colombier break; 2093e12c5d1SDavid du Colombier case 't': 2103e12c5d1SDavid du Colombier case 'd': 2113e12c5d1SDavid du Colombier case 'b': 2123e12c5d1SDavid du Colombier if (type == 'b') { 213219b2ee8SDavid du Colombier names[id] = &sp->s; 214bd389b36SDavid du Colombier return; 2153e12c5d1SDavid du Colombier } 2163e12c5d1SDavid du Colombier break; 2173e12c5d1SDavid du Colombier case 'a': 2183e12c5d1SDavid du Colombier case 'p': 219219b2ee8SDavid du Colombier if (islocal(type)) { 220219b2ee8SDavid du Colombier names[id] = &sp->s; 221bd389b36SDavid du Colombier return; 2223e12c5d1SDavid du Colombier } 2233e12c5d1SDavid du Colombier break; 2243e12c5d1SDavid du Colombier default: 2253e12c5d1SDavid du Colombier break; 2263e12c5d1SDavid du Colombier } 227bd389b36SDavid du Colombier } 228bd389b36SDavid du Colombier } 229219b2ee8SDavid du Colombier sp = malloc(sizeof(Symtab)); 230219b2ee8SDavid du Colombier sp->s.name = name; 231219b2ee8SDavid du Colombier sp->s.type = type; 232219b2ee8SDavid du Colombier sp->s.value = islocal(type) ? MAXOFF : 0; 233219b2ee8SDavid du Colombier names[id] = &sp->s; 234219b2ee8SDavid du Colombier sp->next = hash[h]; 235219b2ee8SDavid du Colombier hash[h] = sp; 236bd389b36SDavid du Colombier return; 237bd389b36SDavid du Colombier } 238bd389b36SDavid du Colombier /* 239219b2ee8SDavid du Colombier * traverse the symbol lists 240bd389b36SDavid du Colombier */ 241219b2ee8SDavid du Colombier void 242219b2ee8SDavid du Colombier objtraverse(void (*fn)(Sym*, void*), void *pointer) 243bd389b36SDavid du Colombier { 244219b2ee8SDavid du Colombier int i; 245219b2ee8SDavid du Colombier Symtab *s; 246219b2ee8SDavid du Colombier 247219b2ee8SDavid du Colombier for(i = 0; i < NHASH; i++) 248219b2ee8SDavid du Colombier for(s = hash[i]; s; s = s->next) 249219b2ee8SDavid du Colombier (*fn)(&s->s, pointer); 2503e12c5d1SDavid du Colombier } 2513e12c5d1SDavid du Colombier 2523e12c5d1SDavid du Colombier /* 2533e12c5d1SDavid du Colombier * update the offset information for a 'a' or 'p' symbol in an intermediate file 2543e12c5d1SDavid du Colombier */ 2553e12c5d1SDavid du Colombier void 256*4de34a7eSDavid du Colombier _offset(int id, vlong off) 2573e12c5d1SDavid du Colombier { 2583e12c5d1SDavid du Colombier Sym *s; 2593e12c5d1SDavid du Colombier 260219b2ee8SDavid du Colombier s = names[id]; 261219b2ee8SDavid du Colombier if (s && s->name[0] && islocal(s->type) && s->value > off) 2623e12c5d1SDavid du Colombier s->value = off; 2633e12c5d1SDavid du Colombier } 2643e12c5d1SDavid du Colombier 2653e12c5d1SDavid du Colombier /* 2663e12c5d1SDavid du Colombier * update the type of a global text or data symbol 2673e12c5d1SDavid du Colombier */ 268219b2ee8SDavid du Colombier static void 269bd389b36SDavid du Colombier objupdate(int id, int type) 2703e12c5d1SDavid du Colombier { 2713e12c5d1SDavid du Colombier Sym *s; 2723e12c5d1SDavid du Colombier 273219b2ee8SDavid du Colombier s = names[id]; 274219b2ee8SDavid du Colombier if (s && s->name[0]) 275219b2ee8SDavid du Colombier if (s->type == 'U') 2763e12c5d1SDavid du Colombier s->type = type; 277219b2ee8SDavid du Colombier else if (s->type == 'b') 2783e12c5d1SDavid du Colombier s->type = tolower(type); 2793e12c5d1SDavid du Colombier } 2803e12c5d1SDavid du Colombier 2813e12c5d1SDavid du Colombier /* 2823e12c5d1SDavid du Colombier * look for the next file in an archive 2833e12c5d1SDavid du Colombier */ 2843e12c5d1SDavid du Colombier int 285bd389b36SDavid du Colombier nextar(Biobuf *bp, int offset, char *buf) 2863e12c5d1SDavid du Colombier { 2873e12c5d1SDavid du Colombier struct ar_hdr a; 2883e12c5d1SDavid du Colombier int i, r; 2893e12c5d1SDavid du Colombier long arsize; 290bd389b36SDavid du Colombier 291bd389b36SDavid du Colombier if (offset&01) 292bd389b36SDavid du Colombier offset++; 293bd389b36SDavid du Colombier Bseek(bp, offset, 0); 294bd389b36SDavid du Colombier r = Bread(bp, &a, SAR_HDR); 2953e12c5d1SDavid du Colombier if(r != SAR_HDR) 2963e12c5d1SDavid du Colombier return 0; 297bd389b36SDavid du Colombier if(strncmp(a.fmag, ARFMAG, sizeof(a.fmag))) 298bd389b36SDavid du Colombier return -1; 299219b2ee8SDavid du Colombier for(i=0; i<sizeof(a.name) && i<SARNAME && a.name[i] != ' '; i++) 300bd389b36SDavid du Colombier buf[i] = a.name[i]; 301bd389b36SDavid du Colombier buf[i] = 0; 302*4de34a7eSDavid du Colombier arsize = strtol(a.size, 0, 0); 303bd389b36SDavid du Colombier if (arsize&1) 304bd389b36SDavid du Colombier arsize++; 305bd389b36SDavid du Colombier return arsize + SAR_HDR; 3063e12c5d1SDavid du Colombier } 3073e12c5d1SDavid du Colombier 308bd389b36SDavid du Colombier static void 309bd389b36SDavid du Colombier objreset(void) 310bd389b36SDavid du Colombier { 311219b2ee8SDavid du Colombier int i; 312219b2ee8SDavid du Colombier Symtab *s, *n; 313219b2ee8SDavid du Colombier 314219b2ee8SDavid du Colombier for(i = 0; i < NHASH; i++) { 315219b2ee8SDavid du Colombier for(s = hash[i]; s; s = n) { 316219b2ee8SDavid du Colombier n = s->next; 317219b2ee8SDavid du Colombier free(s->s.name); 318219b2ee8SDavid du Colombier free(s); 3193e12c5d1SDavid du Colombier } 320219b2ee8SDavid du Colombier hash[i] = 0; 321219b2ee8SDavid du Colombier } 322219b2ee8SDavid du Colombier memset(names, 0, sizeof names); 3233e12c5d1SDavid du Colombier } 324