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