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 &mmips, 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 { J_MAGIC, /* I960 6.out (big-endian) */ 142 "960 plan 9 executable", 143 FI960, 144 &mi960, 145 sizeof(Exec), 146 beswal, 147 adotout }, 148 { 0x61010200, /* I960 boot image (little endian) */ 149 "960 plan 9 boot image", 150 FI960B, 151 &mi960, 152 sizeof(struct i960exec), 153 leswal, 154 i960boot }, 155 { X_MAGIC, /* 3210 x.out */ 156 "3210 plan 9 executable", 157 F3210, 158 &m3210, 159 sizeof(Exec), 160 beswal, 161 adotout }, 162 { D_MAGIC, /* 29000 9.out */ 163 "29000 plan 9 executable", 164 F29000, 165 &m29000, 166 sizeof(Exec), 167 beswal, 168 adotout }, 169 { Q_MAGIC, /* PowerPC q.out */ 170 "power plan 9 executable", 171 FPOWER, 172 &mpower, 173 sizeof(Exec), 174 beswal, 175 common }, 176 { ELF_MAG, 177 "Irix 5.X Elf executable", 178 FMIPS, 179 &mmips, 180 sizeof(Ehdr), 181 beswal, 182 elfdotout }, 183 { E_MAGIC, /* Arm 5.out */ 184 "Arm plan 9 executable", 185 FARM, 186 &marm, 187 sizeof(Exec), 188 beswal, 189 common }, 190 { (143<<16)|0413, /* (Free|Net)BSD Arm */ 191 "Arm *BSD executable", 192 FARM, 193 &marm, 194 sizeof(Exec), 195 leswal, 196 armdotout }, 197 { L_MAGIC, /* alpha 7.out */ 198 "alpha plan 9 executable", 199 FALPHA, 200 &malpha, 201 sizeof(Exec), 202 beswal, 203 common }, 204 { 0x0700e0c3, /* alpha boot image */ 205 "alpha plan 9 boot image", 206 FALPHAB, 207 &malpha, 208 sizeof(Exec), 209 beswal, 210 alphadotout }, 211 { 0 }, 212 }; 213 214 Mach *mach = &mi386; /* Global current machine table */ 215 216 static ExecTable* 217 couldbe4k(ExecTable *mp) 218 { 219 Dir d; 220 ExecTable *f; 221 222 if(dirstat("/proc/1/regs", &d) < 0) 223 return mp; 224 if(d.length < 32*8) /* R3000 */ 225 return mp; 226 for (f = exectab; f->magic; f++) 227 if(f->magic == M_MAGIC) { 228 f->name = "mips plan 9 executable on mips2 kernel"; 229 return f; 230 } 231 return mp; 232 } 233 234 235 int 236 crackhdr(int fd, Fhdr *fp) 237 { 238 ExecTable *mp; 239 ExecHdr d; 240 int nb, magic, ret; 241 242 fp->type = FNONE; 243 nb = read(fd, (char *)&d.e, sizeof(d.e)); 244 if (nb <= 0) 245 return 0; 246 247 ret = 0; 248 fp->magic = magic = beswal(d.e.magic); /* big-endian */ 249 for (mp = exectab; mp->magic; mp++) { 250 if (mp->magic == magic && nb >= mp->hsize) { 251 if(mp->magic == V_MAGIC) 252 mp = couldbe4k(mp); 253 254 hswal((long *) &d, sizeof(d.e)/sizeof(long), mp->swal); 255 fp->type = mp->type; 256 fp->name = mp->name; 257 fp->hdrsz = mp->hsize; /* zero on bootables */ 258 mach = mp->mach; 259 ret = mp->hparse(fd, fp, &d); 260 seek(fd, mp->hsize, 0); /* seek to end of header */ 261 break; 262 } 263 } 264 if(mp->magic == 0) 265 werrstr("unknown header type"); 266 return ret; 267 } 268 /* 269 * Convert header to canonical form 270 */ 271 static void 272 hswal(long *lp, int n, long (*swap) (long)) 273 { 274 while (n--) { 275 *lp = (*swap) (*lp); 276 lp++; 277 } 278 } 279 /* 280 * Crack a normal a.out-type header 281 */ 282 static int 283 adotout(int fd, Fhdr *fp, ExecHdr *hp) 284 { 285 long pgsize; 286 287 USED(fd); 288 pgsize = mach->pgsize; 289 settext(fp, hp->e.entry, pgsize+sizeof(Exec), 290 hp->e.text, sizeof(Exec)); 291 setdata(fp, _round(pgsize+fp->txtsz+sizeof(Exec), pgsize), 292 hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); 293 setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 294 return 1; 295 } 296 297 /* 298 * 68020 2.out and 68020 bootable images 299 * 386I 8.out and 386I bootable images 300 * alpha plan9-style bootable images for axp "headerless" boot 301 * 302 */ 303 static int 304 common(int fd, Fhdr *fp, ExecHdr *hp) 305 { 306 long kbase; 307 308 adotout(fd, fp, hp); 309 kbase = mach->kbase; 310 if ((fp->entry & kbase) == kbase) { /* Boot image */ 311 switch(fp->type) { 312 case F68020: 313 fp->type = F68020B; 314 fp->name = "68020 plan 9 boot image"; 315 fp->hdrsz = 0; /* header stripped */ 316 break; 317 case FI386: 318 fp->type = FI386B; 319 fp->txtaddr = sizeof(Exec); 320 fp->name = "386 plan 9 boot image"; 321 fp->hdrsz = 0; /* header stripped */ 322 fp->dataddr = fp->txtaddr+fp->txtsz; 323 break; 324 case FARM: 325 fp->txtaddr = kbase+0xC000+sizeof(Exec); 326 fp->name = "ARM plan 9 boot image"; 327 fp->hdrsz = 0; /* header stripped */ 328 fp->dataddr = fp->txtaddr+fp->txtsz; 329 return 1; 330 case FALPHA: 331 fp->type = FALPHAB; 332 fp->txtaddr = fp->entry; 333 fp->name = "Alpha plan 9 boot image?"; 334 fp->hdrsz = 0; /* header stripped */ 335 fp->dataddr = fp->txtaddr+fp->txtsz; 336 break; 337 case FALPHAB: 338 fp->txtaddr = 0x20000000+sizeof(Exec); 339 fp->dataddr = fp->txtaddr+fp->txtsz; 340 fp->hdrsz = 0; /* header stripped */ 341 return 1; 342 default: 343 break; 344 } 345 fp->txtaddr |= kbase; 346 fp->entry |= kbase; 347 fp->dataddr |= kbase; 348 } 349 return 1; 350 } 351 352 /* 353 * mips bootable image. 354 */ 355 static int 356 mipsboot(int fd, Fhdr *fp, ExecHdr *hp) 357 { 358 USED(fd); 359 switch(hp->e.amagic) { 360 default: 361 case 0407: /* some kind of mips */ 362 fp->type = FMIPSB; 363 settext(fp, hp->e.mentry, hp->e.text_start, hp->e.tsize, 364 sizeof(struct mipsexec)+4); 365 setdata(fp, hp->e.data_start, hp->e.dsize, 366 fp->txtoff+hp->e.tsize, hp->e.bsize); 367 break; 368 case 0413: /* some kind of mips */ 369 fp->type = FMIPSB; 370 settext(fp, hp->e.mentry, hp->e.text_start, hp->e.tsize, 0); 371 setdata(fp, hp->e.data_start, hp->e.dsize, hp->e.tsize, 372 hp->e.bsize); 373 break; 374 } 375 setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr); 376 fp->hdrsz = 0; /* header stripped */ 377 return 1; 378 } 379 380 /* 381 * mips4k bootable image. 382 */ 383 static int 384 mips4kboot(int fd, Fhdr *fp, ExecHdr *hp) 385 { 386 USED(fd); 387 switch(hp->e.h.amagic) { 388 default: 389 case 0407: /* some kind of mips */ 390 fp->type = FMIPSB; 391 settext(fp, hp->e.h.mentry, hp->e.h.text_start, hp->e.h.tsize, 392 sizeof(struct mips4kexec)); 393 setdata(fp, hp->e.h.data_start, hp->e.h.dsize, 394 fp->txtoff+hp->e.h.tsize, hp->e.h.bsize); 395 break; 396 case 0413: /* some kind of mips */ 397 fp->type = FMIPSB; 398 settext(fp, hp->e.h.mentry, hp->e.h.text_start, hp->e.h.tsize, 0); 399 setdata(fp, hp->e.h.data_start, hp->e.h.dsize, hp->e.h.tsize, 400 hp->e.h.bsize); 401 break; 402 } 403 setsym(fp, hp->e.h.nsyms, 0, hp->e.h.pcsize, hp->e.h.symptr); 404 fp->hdrsz = 0; /* header stripped */ 405 return 1; 406 } 407 408 /* 409 * sparc bootable image 410 */ 411 static int 412 sparcboot(int fd, Fhdr *fp, ExecHdr *hp) 413 { 414 USED(fd); 415 fp->type = FSPARCB; 416 settext(fp, hp->e.sentry, hp->e.sentry, hp->e.stext, 417 sizeof(struct sparcexec)); 418 setdata(fp, hp->e.sentry+hp->e.stext, hp->e.sdata, 419 fp->txtoff+hp->e.stext, hp->e.sbss); 420 setsym(fp, hp->e.ssyms, 0, hp->e.sdrsize, fp->datoff+hp->e.sdata); 421 fp->hdrsz = 0; /* header stripped */ 422 return 1; 423 } 424 425 /* 426 * next bootable image 427 */ 428 static int 429 nextboot(int fd, Fhdr *fp, ExecHdr *hp) 430 { 431 USED(fd); 432 fp->type = FNEXTB; 433 settext(fp, hp->e.textc.vmaddr, hp->e.textc.vmaddr, 434 hp->e.texts.size, hp->e.texts.offset); 435 setdata(fp, hp->e.datac.vmaddr, hp->e.datas.size, 436 hp->e.datas.offset, hp->e.bsss.size); 437 setsym(fp, hp->e.symc.nsyms, hp->e.symc.spoff, hp->e.symc.pcoff, 438 hp->e.symc.symoff); 439 fp->hdrsz = 0; /* header stripped */ 440 return 1; 441 } 442 443 /* 444 * I960 bootable image 445 */ 446 static int 447 i960boot(int fd, Fhdr *fp, ExecHdr *hp) 448 { 449 /* long n = hp->e.i6comments.fptrlineno-hp->e.i6comments.fptrreloc; */ 450 451 USED(fd); 452 settext(fp, hp->e.i6entry, hp->e.i6texts.virt, hp->e.i6texts.size, 453 hp->e.i6texts.fptr); 454 setdata(fp, hp->e.i6datas.virt, hp->e.i6datas.size, 455 hp->e.i6datas.fptr, hp->e.i6bsssize); 456 setsym(fp, 0, 0, 0, 0); 457 /*setsym(fp, n, 0, hp->e.i6comments.size-n, hp->e.i6comments.fptr); */ 458 fp->hdrsz = 0; /* header stripped */ 459 return 1; 460 } 461 462 static Shdr* 463 elfsectbyname(int fd, Ehdr *hp, Shdr *sp, char *name) 464 { 465 int i, offset, n; 466 char s[64]; 467 468 offset = sp[hp->shstrndx].offset; 469 for(i = 1; i < hp->shnum; i++) { 470 seek(fd, offset+sp[i].name, 0); 471 n = read(fd, s, sizeof(s)-1); 472 if(n < 0) 473 continue; 474 s[n] = 0; 475 if(strcmp(s, name) == 0) 476 return &sp[i]; 477 } 478 return 0; 479 } 480 /* 481 * Decode an Irix 5.x ELF header 482 */ 483 static int 484 elfdotout(int fd, Fhdr *fp, ExecHdr *hp) 485 { 486 487 Ehdr *ep; 488 Shdr *es, *txt, *init, *s; 489 long addr, size, offset, bsize; 490 491 ep = &hp->e; 492 if(ep->type != 8 || ep->machine != 2 || ep->version != 1) 493 return 0; 494 495 fp->magic = ELF_MAG; 496 fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; 497 498 if(ep->shnum <= 0) { 499 werrstr("no ELF header sections"); 500 return 0; 501 } 502 es = malloc(sizeof(Shdr)*ep->shnum); 503 if(es == 0) 504 return 0; 505 506 seek(fd, ep->shoff, 0); 507 if(read(fd, es, sizeof(Shdr)*ep->shnum) < 0){ 508 free(es); 509 return 0; 510 } 511 512 txt = elfsectbyname(fd, ep, es, ".text"); 513 init = elfsectbyname(fd, ep, es, ".init"); 514 if(txt == 0 || init == 0 || init != txt+1) 515 goto bad; 516 if(txt->addr+txt->size != init->addr) 517 goto bad; 518 settext(fp, ep->elfentry, txt->addr, txt->size+init->size, txt->offset); 519 520 addr = 0; 521 offset = 0; 522 size = 0; 523 s = elfsectbyname(fd, ep, es, ".data"); 524 if(s) { 525 addr = s->addr; 526 size = s->size; 527 offset = s->offset; 528 } 529 530 s = elfsectbyname(fd, ep, es, ".rodata"); 531 if(s) { 532 if(addr){ 533 if(addr+size != s->addr) 534 goto bad; 535 } else { 536 addr = s->addr; 537 offset = s->offset; 538 } 539 size += s->size; 540 } 541 542 s = elfsectbyname(fd, ep, es, ".got"); 543 if(s) { 544 if(addr){ 545 if(addr+size != s->addr) 546 goto bad; 547 } else { 548 addr = s->addr; 549 offset = s->offset; 550 } 551 size += s->size; 552 } 553 554 bsize = 0; 555 s = elfsectbyname(fd, ep, es, ".bss"); 556 if(s) { 557 if(addr){ 558 if(addr+size != s->addr) 559 goto bad; 560 } else { 561 addr = s->addr; 562 offset = s->offset; 563 } 564 bsize = s->size; 565 } 566 567 if(addr == 0) 568 goto bad; 569 570 setdata(fp, addr, size, offset, bsize); 571 fp->name = "IRIX Elf a.out executable"; 572 free(es); 573 return 1; 574 bad: 575 free(es); 576 werrstr("ELF sections scrambled"); 577 return 0; 578 } 579 580 /* 581 * alpha bootable 582 */ 583 static int 584 alphadotout(int fd, Fhdr *fp, ExecHdr *hp) 585 { 586 long kbase; 587 588 USED(fd); 589 settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); 590 setdata(fp, fp->txtsz+sizeof(Exec), hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); 591 setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 592 593 /* 594 * Boot images have some of bits <31:28> set: 595 * 0x80400000 kernel 596 * 0x20000000 secondary bootstrap 597 */ 598 kbase = 0xF0000000; 599 if (fp->entry & kbase) { 600 fp->txtaddr = fp->entry; 601 fp->name = "alpha plan 9 boot image"; 602 fp->hdrsz = 0; /* header stripped */ 603 fp->dataddr = fp->entry+fp->txtsz; 604 } 605 return 1; 606 } 607 608 /* 609 * (Free|Net)BSD ARM header. 610 */ 611 static int 612 armdotout(int fd, Fhdr *fp, ExecHdr *hp) 613 { 614 long kbase; 615 616 USED(fd); 617 settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); 618 setdata(fp, fp->txtsz, hp->e.data, fp->txtsz, hp->e.bss); 619 setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 620 621 kbase = 0xF0000000; 622 if ((fp->entry & kbase) == kbase) { /* Boot image */ 623 fp->txtaddr = kbase+sizeof(Exec); 624 fp->name = "ARM *BSD boot image"; 625 fp->hdrsz = 0; /* header stripped */ 626 fp->dataddr = kbase+fp->txtsz; 627 } 628 return 1; 629 } 630 631 static void 632 settext(Fhdr *fp, long e, long a, long s, long off) 633 { 634 fp->txtaddr = a; 635 fp->entry = e; 636 fp->txtsz = s; 637 fp->txtoff = off; 638 } 639 static void 640 setdata(Fhdr *fp, long a, long s, long off, long bss) 641 { 642 fp->dataddr = a; 643 fp->datsz = s; 644 fp->datoff = off; 645 fp->bsssz = bss; 646 } 647 static void 648 setsym(Fhdr *fp, long sy, long sppc, long lnpc, long symoff) 649 { 650 fp->symsz = sy; 651 fp->symoff = symoff; 652 fp->sppcsz = sppc; 653 fp->sppcoff = fp->symoff+fp->symsz; 654 fp->lnpcsz = lnpc; 655 fp->lnpcoff = fp->sppcoff+fp->sppcsz; 656 } 657 658 659 static long 660 _round(long a, long b) 661 { 662 long w; 663 664 w = (a/b)*b; 665 if (a!=w) 666 w += b; 667 return(w); 668 } 669