1 #include <lib9.h> 2 #include <bio.h> 3 #include "bootexec.h" 4 #include "mach.h" 5 #include "elf.h" 6 7 /* 8 * All a.out header types. The dummy entry allows canonical 9 * processing of the union as a sequence of longs 10 */ 11 12 typedef struct { 13 union{ 14 Exec exec; /* in a.out.h */ 15 Ehdr ehdr; /* in elf.h */ 16 struct mipsexec mipsexec; 17 struct mips4kexec mips4kexec; 18 struct sparcexec sparcexec; 19 struct nextexec nextexec; 20 } e; 21 long dummy; /* padding to ensure extra long */ 22 } ExecHdr; 23 24 static int nextboot(int, Fhdr*, ExecHdr*); 25 static int sparcboot(int, Fhdr*, ExecHdr*); 26 static int mipsboot(int, Fhdr*, ExecHdr*); 27 static int mips4kboot(int, Fhdr*, ExecHdr*); 28 static int common(int, Fhdr*, ExecHdr*); 29 static int adotout(int, Fhdr*, ExecHdr*); 30 static int elfdotout(int, Fhdr*, ExecHdr*); 31 static int armdotout(int, Fhdr*, ExecHdr*); 32 static void setsym(Fhdr*, long, long, long, long); 33 static void setdata(Fhdr*, long, long, long, long); 34 static void settext(Fhdr*, long, long, long, long); 35 static void hswal(long*, int, long(*)(long)); 36 static long _round(long, long); 37 38 /* 39 * definition of per-executable file type structures 40 */ 41 42 typedef struct Exectable{ 43 long magic; /* big-endian magic number of file */ 44 char *name; /* executable identifier */ 45 int type; /* Internal code */ 46 Mach *mach; /* Per-machine data */ 47 ulong hsize; /* header size */ 48 long (*swal)(long); /* beswal or leswal */ 49 int (*hparse)(int, Fhdr*, ExecHdr*); 50 } ExecTable; 51 52 extern Mach mmips; 53 extern Mach mmips2le; 54 extern Mach mmips2be; 55 extern Mach msparc; 56 extern Mach m68020; 57 extern Mach mi386; 58 extern Mach marm; 59 extern Mach mpower; 60 61 ExecTable exectab[] = 62 { 63 { V_MAGIC, /* Mips v.out */ 64 "mips plan 9 executable", 65 FMIPS, 66 &mmips, 67 sizeof(Exec), 68 beswal, 69 adotout }, 70 { M_MAGIC, /* Mips 4.out */ 71 "mips 4k plan 9 executable BE", 72 FMIPS2BE, 73 &mmips2be, 74 sizeof(Exec), 75 beswal, 76 adotout }, 77 { N_MAGIC, /* Mips 0.out */ 78 "mips 4k plan 9 executable LE", 79 FMIPS2LE, 80 &mmips2le, 81 sizeof(Exec), 82 beswal, 83 adotout }, 84 { 0x160<<16, /* Mips boot image */ 85 "mips plan 9 boot image", 86 FMIPSB, 87 &mmips, 88 sizeof(struct mipsexec), 89 beswal, 90 mipsboot }, 91 { (0x160<<16)|3, /* Mips boot image */ 92 "mips 4k plan 9 boot image", 93 FMIPSB, 94 &mmips, 95 sizeof(struct mips4kexec), 96 beswal, 97 mips4kboot }, 98 { K_MAGIC, /* Sparc k.out */ 99 "sparc plan 9 executable", 100 FSPARC, 101 &msparc, 102 sizeof(Exec), 103 beswal, 104 adotout }, 105 { 0x01030107, /* Sparc boot image */ 106 "sparc plan 9 boot image", 107 FSPARCB, 108 &msparc, 109 sizeof(struct sparcexec), 110 beswal, 111 sparcboot }, 112 { A_MAGIC, /* 68020 2.out & boot image */ 113 "68020 plan 9 executable", 114 F68020, 115 &m68020, 116 sizeof(Exec), 117 beswal, 118 common }, 119 { 0xFEEDFACE, /* Next boot image */ 120 "next plan 9 boot image", 121 FNEXTB, 122 &m68020, 123 sizeof(struct nextexec), 124 beswal, 125 nextboot }, 126 { I_MAGIC, /* I386 8.out & boot image */ 127 "386 plan 9 executable", 128 FI386, 129 &mi386, 130 sizeof(Exec), 131 beswal, 132 common }, 133 { ELF_MAG, 134 "Irix 5.X Elf executable", 135 FMIPS, 136 &mmips, 137 sizeof(Ehdr), 138 beswal, 139 elfdotout }, 140 { E_MAGIC, /* Arm 5.out */ 141 "Arm plan 9 executable", 142 FARM, 143 &marm, 144 sizeof(Exec), 145 beswal, 146 common }, 147 { (143<<16)|0413, /* (Free|Net)BSD Arm */ 148 "Arm *BSD executable", 149 FARM, 150 &marm, 151 sizeof(Exec), 152 leswal, 153 armdotout }, 154 { Q_MAGIC, /* PowerPC q.out */ 155 "power plan 9 executable", 156 FPOWER, 157 &mpower, 158 sizeof(Exec), 159 beswal, 160 common }, 161 { 0 }, 162 }; 163 164 Mach *mach = &mmips; /* Global current machine table */ 165 166 ExecTable* 167 couldbe4k(ExecTable *mp) 168 { 169 Dir *d; 170 ExecTable *f; 171 172 if((d=dirstat("/proc/1/regs")) == nil) 173 return mp; 174 if(d->length < 32*8){ /* R3000 */ 175 free(d); 176 return mp; 177 } 178 free(d); 179 for (f = exectab; f->magic; f++) 180 if(f->magic == M_MAGIC) { 181 f->name = "mips plan 9 executable on mips2 kernel"; 182 return f; 183 } 184 return mp; 185 } 186 187 188 int 189 crackhdr(int fd, Fhdr *fp) 190 { 191 ExecTable *mp; 192 ExecHdr d; 193 int nb, magic, ret; 194 195 fp->type = FNONE; 196 nb = read(fd, (char *)&d.e, sizeof(d.e)); 197 if (nb <= 0) 198 return 0; 199 200 ret = 0; 201 fp->magic = magic = beswal(d.e.exec.magic); /* big-endian */ 202 for (mp = exectab; mp->magic; mp++) { 203 if (mp->magic == magic && nb >= mp->hsize) { 204 if(mp->magic == V_MAGIC) 205 mp = couldbe4k(mp); 206 207 hswal((long *) &d, sizeof(d.e)/sizeof(long), mp->swal); 208 fp->type = mp->type; 209 fp->name = mp->name; 210 fp->hdrsz = mp->hsize; /* zero on bootables */ 211 mach = mp->mach; 212 ret = mp->hparse(fd, fp, &d); 213 seek(fd, mp->hsize, 0); /* seek to end of header */ 214 break; 215 } 216 } 217 if(mp->magic == 0) 218 werrstr("unknown header type"); 219 return ret; 220 } 221 /* 222 * Convert header to canonical form 223 */ 224 static void 225 hswal(long *lp, int n, long (*swap) (long)) 226 { 227 while (n--) { 228 *lp = (*swap) (*lp); 229 lp++; 230 } 231 } 232 /* 233 * Crack a normal a.out-type header 234 */ 235 static int 236 adotout(int fd, Fhdr *fp, ExecHdr *hp) 237 { 238 long pgsize; 239 240 USED(fd); 241 pgsize = mach->pgsize; 242 settext(fp, hp->e.exec.entry, pgsize+sizeof(Exec), 243 hp->e.exec.text, sizeof(Exec)); 244 setdata(fp, _round(pgsize+fp->txtsz+sizeof(Exec), pgsize), 245 hp->e.exec.data, fp->txtsz+sizeof(Exec), hp->e.exec.bss); 246 setsym(fp, hp->e.exec.syms, hp->e.exec.spsz, hp->e.exec.pcsz, fp->datoff+fp->datsz); 247 return 1; 248 } 249 250 /* 251 * 68020 2.out and 68020 bootable images 252 * 386I 8.out and 386I bootable images 253 * 254 */ 255 static int 256 common(int fd, Fhdr *fp, ExecHdr *hp) 257 { 258 long kbase; 259 260 adotout(fd, fp, hp); 261 kbase = mach->kbase; 262 if ((fp->entry & kbase) == kbase) { /* Boot image */ 263 switch(fp->type) { 264 case F68020: 265 fp->type = F68020B; 266 fp->name = "68020 plan 9 boot image"; 267 fp->hdrsz = 0; /* header stripped */ 268 break; 269 case FI386: 270 fp->type = FI386B; 271 fp->txtaddr = sizeof(Exec); 272 fp->name = "386 plan 9 boot image"; 273 fp->hdrsz = 0; /* header stripped */ 274 fp->dataddr = fp->txtaddr+fp->txtsz; 275 break; 276 case FARM: 277 fp->txtaddr = kbase+0x8000+sizeof(Exec); 278 fp->name = "ARM plan 9 boot image"; 279 fp->hdrsz = 0; /* header stripped */ 280 fp->dataddr = fp->txtaddr+fp->txtsz; 281 return 1; 282 default: 283 break; 284 } 285 fp->txtaddr |= kbase; 286 fp->entry |= kbase; 287 fp->dataddr |= kbase; 288 } 289 else if (fp->type == FARM && (fp->entry == 0x8020 || fp->entry == 0x8080)) { 290 fp->txtaddr = fp->entry; 291 fp->name = "ARM Inferno boot image"; 292 fp->hdrsz = 0; /* header stripped */ 293 fp->dataddr = fp->txtaddr+fp->txtsz; 294 } 295 else if (fp->type == FPOWER && fp->entry == 0x3020) { 296 fp->txtaddr = fp->entry; 297 fp->name = "Power Inferno boot image"; 298 fp->hdrsz = 0; /* header stripped */ 299 fp->dataddr = fp->txtaddr+fp->txtsz; 300 } 301 return 1; 302 } 303 304 /* 305 * mips bootable image. 306 */ 307 static int 308 mipsboot(int fd, Fhdr *fp, ExecHdr *hp) 309 { 310 USED(fd); 311 switch(hp->e.mipsexec.amagic) { 312 default: 313 case 0407: /* some kind of mips */ 314 fp->type = FMIPSB; 315 settext(fp, hp->e.mipsexec.mentry, hp->e.mipsexec.text_start, hp->e.mipsexec.tsize, 316 sizeof(struct mipsexec)+4); 317 setdata(fp, hp->e.mipsexec.data_start, hp->e.mipsexec.dsize, 318 fp->txtoff+hp->e.mipsexec.tsize, hp->e.mipsexec.bsize); 319 break; 320 case 0413: /* some kind of mips */ 321 fp->type = FMIPSB; 322 settext(fp, hp->e.mipsexec.mentry, hp->e.mipsexec.text_start, hp->e.mipsexec.tsize, 0); 323 setdata(fp, hp->e.mipsexec.data_start, hp->e.mipsexec.dsize, hp->e.mipsexec.tsize, 324 hp->e.mipsexec.bsize); 325 break; 326 } 327 setsym(fp, hp->e.mipsexec.nsyms, 0, hp->e.mipsexec.u0.mpcsize, hp->e.mipsexec.symptr); 328 fp->hdrsz = 0; /* header stripped */ 329 return 1; 330 } 331 332 /* 333 * mips4k bootable image. 334 */ 335 static int 336 mips4kboot(int fd, Fhdr *fp, ExecHdr *hp) 337 { 338 USED(fd); 339 switch(hp->e.mipsexec.amagic) { 340 default: 341 case 0407: /* some kind of mips */ 342 fp->type = FMIPSB; 343 settext(fp, hp->e.mipsexec.mentry, hp->e.mipsexec.text_start, hp->e.mipsexec.tsize, 344 sizeof(struct mips4kexec)); 345 setdata(fp, hp->e.mipsexec.data_start, hp->e.mipsexec.dsize, 346 fp->txtoff+hp->e.mipsexec.tsize, hp->e.mipsexec.bsize); 347 break; 348 case 0413: /* some kind of mips */ 349 fp->type = FMIPSB; 350 settext(fp, hp->e.mipsexec.mentry, hp->e.mipsexec.text_start, hp->e.mipsexec.tsize, 0); 351 setdata(fp, hp->e.mipsexec.data_start, hp->e.mipsexec.dsize, hp->e.mipsexec.tsize, 352 hp->e.mipsexec.bsize); 353 break; 354 } 355 setsym(fp, hp->e.mipsexec.nsyms, 0, hp->e.mipsexec.u0.mpcsize, hp->e.mipsexec.symptr); 356 fp->hdrsz = 0; /* header stripped */ 357 return 1; 358 } 359 360 /* 361 * sparc bootable image 362 */ 363 static int 364 sparcboot(int fd, Fhdr *fp, ExecHdr *hp) 365 { 366 USED(fd); 367 fp->type = FSPARCB; 368 settext(fp, hp->e.sparcexec.sentry, hp->e.sparcexec.sentry, hp->e.sparcexec.stext, 369 sizeof(struct sparcexec)); 370 setdata(fp, hp->e.sparcexec.sentry+hp->e.sparcexec.stext, hp->e.sparcexec.sdata, 371 fp->txtoff+hp->e.sparcexec.stext, hp->e.sparcexec.sbss); 372 setsym(fp, hp->e.sparcexec.ssyms, 0, hp->e.sparcexec.sdrsize, fp->datoff+hp->e.sparcexec.sdata); 373 fp->hdrsz = 0; /* header stripped */ 374 return 1; 375 } 376 377 /* 378 * next bootable image 379 */ 380 static int 381 nextboot(int fd, Fhdr *fp, ExecHdr *hp) 382 { 383 USED(fd); 384 fp->type = FNEXTB; 385 settext(fp, hp->e.nextexec.textc.vmaddr, hp->e.nextexec.textc.vmaddr, 386 hp->e.nextexec.texts.size, hp->e.nextexec.texts.offset); 387 setdata(fp, hp->e.nextexec.datac.vmaddr, hp->e.nextexec.datas.size, 388 hp->e.nextexec.datas.offset, hp->e.nextexec.bsss.size); 389 setsym(fp, hp->e.nextexec.symc.nsyms, hp->e.nextexec.symc.spoff, hp->e.nextexec.symc.pcoff, 390 hp->e.nextexec.symc.symoff); 391 fp->hdrsz = 0; /* header stripped */ 392 return 1; 393 } 394 395 static Shdr* 396 elfsectbyname(int fd, Ehdr *hp, Shdr *sp, char *name) 397 { 398 int i, offset, n; 399 char s[64]; 400 401 offset = sp[hp->shstrndx].offset; 402 for(i = 1; i < hp->shnum; i++) { 403 seek(fd, offset+sp[i].name, 0); 404 n = read(fd, s, sizeof(s)-1); 405 if(n < 0) 406 continue; 407 s[n] = 0; 408 if(strcmp(s, name) == 0) 409 return &sp[i]; 410 } 411 return 0; 412 } 413 /* 414 * Decode an Irix 5.x ELF header 415 */ 416 static int 417 elfdotout(int fd, Fhdr *fp, ExecHdr *hp) 418 { 419 420 Ehdr *ep; 421 Shdr *es, *txt, *init, *s; 422 long addr, size, offset, bsize; 423 424 ep = &hp->e.ehdr; 425 fp->magic = ELF_MAG; 426 fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; 427 428 if(ep->shnum <= 0) { 429 werrstr("no ELF header sections"); 430 return 0; 431 } 432 es = malloc(sizeof(Shdr)*ep->shnum); 433 if(es == 0) 434 return 0; 435 436 seek(fd, ep->shoff, 0); 437 if(read(fd, es, sizeof(Shdr)*ep->shnum) < 0){ 438 free(es); 439 return 0; 440 } 441 442 txt = elfsectbyname(fd, ep, es, ".text"); 443 init = elfsectbyname(fd, ep, es, ".init"); 444 if(txt == 0 || init == 0 || init != txt+1) 445 goto bad; 446 if(txt->addr+txt->size != init->addr) 447 goto bad; 448 settext(fp, ep->elfentry, txt->addr, txt->size+init->size, txt->offset); 449 450 addr = 0; 451 offset = 0; 452 size = 0; 453 s = elfsectbyname(fd, ep, es, ".data"); 454 if(s) { 455 addr = s->addr; 456 size = s->size; 457 offset = s->offset; 458 } 459 460 s = elfsectbyname(fd, ep, es, ".rodata"); 461 if(s) { 462 if(addr){ 463 if(addr+size != s->addr) 464 goto bad; 465 } else { 466 addr = s->addr; 467 offset = s->offset; 468 } 469 size += s->size; 470 } 471 472 s = elfsectbyname(fd, ep, es, ".got"); 473 if(s) { 474 if(addr){ 475 if(addr+size != s->addr) 476 goto bad; 477 } else { 478 addr = s->addr; 479 offset = s->offset; 480 } 481 size += s->size; 482 } 483 484 bsize = 0; 485 s = elfsectbyname(fd, ep, es, ".bss"); 486 if(s) { 487 if(addr){ 488 if(addr+size != s->addr) 489 goto bad; 490 } else { 491 addr = s->addr; 492 offset = s->offset; 493 } 494 bsize = s->size; 495 } 496 497 if(addr == 0) 498 goto bad; 499 500 setdata(fp, addr, size, offset, bsize); 501 fp->name = "IRIX Elf a.out executable"; 502 free(es); 503 return 1; 504 bad: 505 free(es); 506 werrstr("ELF sections scrambled"); 507 return 0; 508 } 509 510 /* 511 * (Free|Net)BSD ARM header. 512 */ 513 static int 514 armdotout(int fd, Fhdr *fp, ExecHdr *hp) 515 { 516 long kbase; 517 518 USED(fd); 519 settext(fp, hp->e.exec.entry, sizeof(Exec), hp->e.exec.text, sizeof(Exec)); 520 setdata(fp, fp->txtsz, hp->e.exec.data, fp->txtsz, hp->e.exec.bss); 521 setsym(fp, hp->e.exec.syms, hp->e.exec.spsz, hp->e.exec.pcsz, fp->datoff+fp->datsz); 522 523 kbase = 0xF0000000; 524 if ((fp->entry & kbase) == kbase) { /* Boot image */ 525 fp->txtaddr = kbase+sizeof(Exec); 526 fp->name = "ARM *BSD boot image"; 527 fp->hdrsz = 0; /* header stripped */ 528 fp->dataddr = kbase+fp->txtsz; 529 } 530 return 1; 531 } 532 533 static void 534 settext(Fhdr *fp, long e, long a, long s, long off) 535 { 536 fp->txtaddr = a; 537 fp->entry = e; 538 fp->txtsz = s; 539 fp->txtoff = off; 540 } 541 static void 542 setdata(Fhdr *fp, long a, long s, long off, long bss) 543 { 544 fp->dataddr = a; 545 fp->datsz = s; 546 fp->datoff = off; 547 fp->bsssz = bss; 548 } 549 static void 550 setsym(Fhdr *fp, long sy, long sppc, long lnpc, long symoff) 551 { 552 fp->symsz = sy; 553 fp->symoff = symoff; 554 fp->sppcsz = sppc; 555 fp->sppcoff = fp->symoff+fp->symsz; 556 fp->lnpcsz = lnpc; 557 fp->lnpcoff = fp->sppcoff+fp->sppcsz; 558 } 559 560 561 static long 562 _round(long a, long b) 563 { 564 long w; 565 566 w = (a/b)*b; 567 if (a!=w) 568 w += b; 569 return(w); 570 } 571