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