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 struct { 16 Exec; /* a.out.h */ 17 uvlong hdr[1]; 18 }; 19 Ehdr; /* elf.h */ 20 E64hdr; 21 struct mipsexec; /* bootexec.h */ 22 struct mips4kexec; /* bootexec.h */ 23 struct sparcexec; /* bootexec.h */ 24 struct nextexec; /* bootexec.h */ 25 } e; 26 long dummy; /* padding to ensure extra long */ 27 } ExecHdr; 28 29 static int nextboot(int, Fhdr*, ExecHdr*); 30 static int sparcboot(int, Fhdr*, ExecHdr*); 31 static int mipsboot(int, Fhdr*, ExecHdr*); 32 static int mips4kboot(int, Fhdr*, ExecHdr*); 33 static int common(int, Fhdr*, ExecHdr*); 34 static int commonllp64(int, Fhdr*, ExecHdr*); 35 static int adotout(int, Fhdr*, ExecHdr*); 36 static int elfdotout(int, Fhdr*, ExecHdr*); 37 static int armdotout(int, Fhdr*, ExecHdr*); 38 static void setsym(Fhdr*, long, long, long, vlong); 39 static void setdata(Fhdr*, uvlong, long, vlong, long); 40 static void settext(Fhdr*, uvlong, uvlong, long, vlong); 41 static void hswal(void*, int, ulong(*)(ulong)); 42 static uvlong _round(uvlong, ulong); 43 44 /* 45 * definition of per-executable file type structures 46 */ 47 48 typedef struct Exectable{ 49 long magic; /* big-endian magic number of file */ 50 char *name; /* executable identifier */ 51 char *dlmname; /* dynamically loadable module identifier */ 52 uchar type; /* Internal code */ 53 uchar _magic; /* _MAGIC() magic */ 54 Mach *mach; /* Per-machine data */ 55 long hsize; /* header size */ 56 ulong (*swal)(ulong); /* beswal or leswal */ 57 int (*hparse)(int, Fhdr*, ExecHdr*); 58 } ExecTable; 59 60 extern Mach mmips; 61 extern Mach mmips2le; 62 extern Mach mmips2be; 63 extern Mach msparc; 64 extern Mach msparc64; 65 extern Mach m68020; 66 extern Mach mi386; 67 extern Mach mamd64; 68 extern Mach marm; 69 extern Mach mpower; 70 extern Mach mpower64; 71 extern Mach malpha; 72 73 ExecTable exectab[] = 74 { 75 { V_MAGIC, /* Mips v.out */ 76 "mips plan 9 executable BE", 77 "mips plan 9 dlm BE", 78 FMIPS, 79 1, 80 &mmips, 81 sizeof(Exec), 82 beswal, 83 adotout }, 84 { P_MAGIC, /* Mips 0.out (r3k le) */ 85 "mips plan 9 executable LE", 86 "mips plan 9 dlm LE", 87 FMIPSLE, 88 1, 89 &mmips, 90 sizeof(Exec), 91 beswal, 92 adotout }, 93 { M_MAGIC, /* Mips 4.out */ 94 "mips 4k plan 9 executable BE", 95 "mips 4k plan 9 dlm BE", 96 FMIPS2BE, 97 1, 98 &mmips2be, 99 sizeof(Exec), 100 beswal, 101 adotout }, 102 { N_MAGIC, /* Mips 0.out */ 103 "mips 4k plan 9 executable LE", 104 "mips 4k plan 9 dlm LE", 105 FMIPS2LE, 106 1, 107 &mmips2le, 108 sizeof(Exec), 109 beswal, 110 adotout }, 111 { 0x160<<16, /* Mips boot image */ 112 "mips plan 9 boot image", 113 nil, 114 FMIPSB, 115 0, 116 &mmips, 117 sizeof(struct mipsexec), 118 beswal, 119 mipsboot }, 120 { (0x160<<16)|3, /* Mips boot image */ 121 "mips 4k plan 9 boot image", 122 nil, 123 FMIPSB, 124 0, 125 &mmips2be, 126 sizeof(struct mips4kexec), 127 beswal, 128 mips4kboot }, 129 { K_MAGIC, /* Sparc k.out */ 130 "sparc plan 9 executable", 131 "sparc plan 9 dlm", 132 FSPARC, 133 1, 134 &msparc, 135 sizeof(Exec), 136 beswal, 137 adotout }, 138 { 0x01030107, /* Sparc boot image */ 139 "sparc plan 9 boot image", 140 nil, 141 FSPARCB, 142 0, 143 &msparc, 144 sizeof(struct sparcexec), 145 beswal, 146 sparcboot }, 147 { U_MAGIC, /* Sparc64 u.out */ 148 "sparc64 plan 9 executable", 149 "sparc64 plan 9 dlm", 150 FSPARC64, 151 1, 152 &msparc64, 153 sizeof(Exec), 154 beswal, 155 adotout }, 156 { A_MAGIC, /* 68020 2.out & boot image */ 157 "68020 plan 9 executable", 158 "68020 plan 9 dlm", 159 F68020, 160 1, 161 &m68020, 162 sizeof(Exec), 163 beswal, 164 common }, 165 { 0xFEEDFACE, /* Next boot image */ 166 "next plan 9 boot image", 167 nil, 168 FNEXTB, 169 0, 170 &m68020, 171 sizeof(struct nextexec), 172 beswal, 173 nextboot }, 174 { I_MAGIC, /* I386 8.out & boot image */ 175 "386 plan 9 executable", 176 "386 plan 9 dlm", 177 FI386, 178 1, 179 &mi386, 180 sizeof(Exec), 181 beswal, 182 common }, 183 { S_MAGIC, /* amd64 6.out & boot image */ 184 "amd64 plan 9 executable", 185 "amd64 plan 9 dlm", 186 FAMD64, 187 1, 188 &mamd64, 189 sizeof(Exec)+8, 190 nil, 191 commonllp64 }, 192 { Q_MAGIC, /* PowerPC q.out & boot image */ 193 "power plan 9 executable", 194 "power plan 9 dlm", 195 FPOWER, 196 1, 197 &mpower, 198 sizeof(Exec), 199 beswal, 200 common }, 201 { T_MAGIC, /* power64 9.out & boot image */ 202 "power64 plan 9 executable", 203 "power64 plan 9 dlm", 204 FPOWER64, 205 1, 206 &mpower64, 207 sizeof(Exec)+8, 208 nil, 209 commonllp64 }, 210 { ELF_MAG, /* any ELF */ 211 "elf executable", 212 nil, 213 FNONE, 214 0, 215 &mi386, 216 sizeof(Ehdr), 217 nil, 218 elfdotout }, 219 { E_MAGIC, /* Arm 5.out and boot image */ 220 "arm plan 9 executable", 221 "arm plan 9 dlm", 222 FARM, 223 1, 224 &marm, 225 sizeof(Exec), 226 beswal, 227 common }, 228 { (143<<16)|0413, /* (Free|Net)BSD Arm */ 229 "arm *bsd executable", 230 nil, 231 FARM, 232 0, 233 &marm, 234 sizeof(Exec), 235 leswal, 236 armdotout }, 237 { L_MAGIC, /* alpha 7.out */ 238 "alpha plan 9 executable", 239 "alpha plan 9 dlm", 240 FALPHA, 241 1, 242 &malpha, 243 sizeof(Exec), 244 beswal, 245 common }, 246 { 0x0700e0c3, /* alpha boot image */ 247 "alpha plan 9 boot image", 248 nil, 249 FALPHA, 250 0, 251 &malpha, 252 sizeof(Exec), 253 beswal, 254 common }, 255 { 0 }, 256 }; 257 258 Mach *mach = &mi386; /* Global current machine table */ 259 260 static ExecTable* 261 couldbe4k(ExecTable *mp) 262 { 263 Dir *d; 264 ExecTable *f; 265 266 if((d=dirstat("/proc/1/regs")) == nil) 267 return mp; 268 if(d->length < 32*8){ /* R3000 */ 269 free(d); 270 return mp; 271 } 272 free(d); 273 for (f = exectab; f->magic; f++) 274 if(f->magic == M_MAGIC) { 275 f->name = "mips plan 9 executable on mips2 kernel"; 276 return f; 277 } 278 return mp; 279 } 280 281 int 282 crackhdr(int fd, Fhdr *fp) 283 { 284 ExecTable *mp; 285 ExecHdr d; 286 int nb, ret; 287 ulong magic; 288 289 fp->type = FNONE; 290 nb = read(fd, (char *)&d.e, sizeof(d.e)); 291 if (nb <= 0) 292 return 0; 293 294 ret = 0; 295 magic = beswal(d.e.magic); /* big-endian */ 296 for (mp = exectab; mp->magic; mp++) { 297 if (nb < mp->hsize) 298 continue; 299 300 /* 301 * The magic number has morphed into something 302 * with fields (the straw was DYN_MAGIC) so now 303 * a flag is needed in Fhdr to distinguish _MAGIC() 304 * magic numbers from foreign magic numbers. 305 * 306 * This code is creaking a bit and if it has to 307 * be modified/extended much more it's probably 308 * time to step back and redo it all. 309 */ 310 if(mp->_magic){ 311 if(mp->magic != (magic & ~DYN_MAGIC)) 312 continue; 313 314 if(mp->magic == V_MAGIC) 315 mp = couldbe4k(mp); 316 317 if ((magic & DYN_MAGIC) && mp->dlmname != nil) 318 fp->name = mp->dlmname; 319 else 320 fp->name = mp->name; 321 } 322 else{ 323 if(mp->magic != magic) 324 continue; 325 fp->name = mp->name; 326 } 327 fp->type = mp->type; 328 fp->hdrsz = mp->hsize; /* will be zero on bootables */ 329 fp->_magic = mp->_magic; 330 fp->magic = magic; 331 332 mach = mp->mach; 333 if(mp->swal != nil) 334 hswal(&d, sizeof(d.e)/sizeof(ulong), mp->swal); 335 ret = mp->hparse(fd, fp, &d); 336 seek(fd, mp->hsize, 0); /* seek to end of header */ 337 break; 338 } 339 if(mp->magic == 0) 340 werrstr("unknown header type"); 341 return ret; 342 } 343 344 /* 345 * Convert header to canonical form 346 */ 347 static void 348 hswal(void *v, int n, ulong (*swap)(ulong)) 349 { 350 ulong *ulp; 351 352 for(ulp = v; n--; ulp++) 353 *ulp = (*swap)(*ulp); 354 } 355 356 /* 357 * Crack a normal a.out-type header 358 */ 359 static int 360 adotout(int fd, Fhdr *fp, ExecHdr *hp) 361 { 362 long pgsize; 363 364 USED(fd); 365 pgsize = mach->pgsize; 366 settext(fp, hp->e.entry, pgsize+sizeof(Exec), 367 hp->e.text, sizeof(Exec)); 368 setdata(fp, _round(pgsize+fp->txtsz+sizeof(Exec), pgsize), 369 hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); 370 setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 371 return 1; 372 } 373 374 static void 375 commonboot(Fhdr *fp) 376 { 377 if (!(fp->entry & mach->ktmask)) 378 return; 379 380 switch(fp->type) { /* boot image */ 381 case F68020: 382 fp->type = F68020B; 383 fp->name = "68020 plan 9 boot image"; 384 break; 385 case FI386: 386 fp->type = FI386B; 387 fp->txtaddr = (u32int)fp->entry; 388 fp->name = "386 plan 9 boot image"; 389 fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); 390 break; 391 case FARM: 392 fp->type = FARMB; 393 fp->txtaddr = (u32int)fp->entry; 394 fp->name = "ARM plan 9 boot image"; 395 fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); 396 return; 397 case FALPHA: 398 fp->type = FALPHAB; 399 fp->txtaddr = (u32int)fp->entry; 400 fp->name = "alpha plan 9 boot image"; 401 fp->dataddr = fp->txtaddr+fp->txtsz; 402 break; 403 case FPOWER: 404 fp->type = FPOWERB; 405 fp->txtaddr = (u32int)fp->entry; 406 fp->name = "power plan 9 boot image"; 407 fp->dataddr = fp->txtaddr+fp->txtsz; 408 break; 409 case FAMD64: 410 fp->type = FAMD64B; 411 fp->txtaddr = fp->entry; 412 fp->name = "amd64 plan 9 boot image"; 413 fp->dataddr = _round(fp->txtaddr+fp->txtsz, 4096); 414 break; 415 case FPOWER64: 416 fp->type = FPOWER64B; 417 fp->txtaddr = fp->entry; 418 fp->name = "power64 plan 9 boot image"; 419 fp->dataddr = fp->txtaddr+fp->txtsz; 420 break; 421 default: 422 return; 423 } 424 fp->hdrsz = 0; /* header stripped */ 425 } 426 427 /* 428 * _MAGIC() style headers and 429 * alpha plan9-style bootable images for axp "headerless" boot 430 * 431 */ 432 static int 433 common(int fd, Fhdr *fp, ExecHdr *hp) 434 { 435 adotout(fd, fp, hp); 436 if(hp->e.magic & DYN_MAGIC) { 437 fp->txtaddr = 0; 438 fp->dataddr = fp->txtsz; 439 return 1; 440 } 441 commonboot(fp); 442 return 1; 443 } 444 445 static int 446 commonllp64(int, Fhdr *fp, ExecHdr *hp) 447 { 448 long pgsize; 449 uvlong entry; 450 451 hswal(&hp->e, sizeof(Exec)/sizeof(long), beswal); 452 if(!(hp->e.magic & HDR_MAGIC)) 453 return 0; 454 455 /* 456 * There can be more magic here if the 457 * header ever needs more expansion. 458 * For now just catch use of any of the 459 * unused bits. 460 */ 461 if((hp->e.magic & ~DYN_MAGIC)>>16) 462 return 0; 463 entry = beswav(hp->e.hdr[0]); 464 465 pgsize = mach->pgsize; 466 settext(fp, entry, pgsize+fp->hdrsz, hp->e.text, fp->hdrsz); 467 setdata(fp, _round(pgsize+fp->txtsz+fp->hdrsz, pgsize), 468 hp->e.data, fp->txtsz+fp->hdrsz, hp->e.bss); 469 setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 470 471 if(hp->e.magic & DYN_MAGIC) { 472 fp->txtaddr = 0; 473 fp->dataddr = fp->txtsz; 474 return 1; 475 } 476 commonboot(fp); 477 return 1; 478 } 479 480 /* 481 * mips bootable image. 482 */ 483 static int 484 mipsboot(int fd, Fhdr *fp, ExecHdr *hp) 485 { 486 USED(fd); 487 fp->type = FMIPSB; 488 switch(hp->e.amagic) { 489 default: 490 case 0407: /* some kind of mips */ 491 settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start, 492 hp->e.tsize, sizeof(struct mipsexec)+4); 493 setdata(fp, (u32int)hp->e.data_start, hp->e.dsize, 494 fp->txtoff+hp->e.tsize, hp->e.bsize); 495 break; 496 case 0413: /* some kind of mips */ 497 settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start, 498 hp->e.tsize, 0); 499 setdata(fp, (u32int)hp->e.data_start, hp->e.dsize, 500 hp->e.tsize, hp->e.bsize); 501 break; 502 } 503 setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr); 504 fp->hdrsz = 0; /* header stripped */ 505 return 1; 506 } 507 508 /* 509 * mips4k bootable image. 510 */ 511 static int 512 mips4kboot(int fd, Fhdr *fp, ExecHdr *hp) 513 { 514 USED(fd); 515 fp->type = FMIPSB; 516 switch(hp->e.h.amagic) { 517 default: 518 case 0407: /* some kind of mips */ 519 settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start, 520 hp->e.h.tsize, sizeof(struct mips4kexec)); 521 setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize, 522 fp->txtoff+hp->e.h.tsize, hp->e.h.bsize); 523 break; 524 case 0413: /* some kind of mips */ 525 settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start, 526 hp->e.h.tsize, 0); 527 setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize, 528 hp->e.h.tsize, hp->e.h.bsize); 529 break; 530 } 531 setsym(fp, hp->e.h.nsyms, 0, hp->e.h.pcsize, hp->e.h.symptr); 532 fp->hdrsz = 0; /* header stripped */ 533 return 1; 534 } 535 536 /* 537 * sparc bootable image 538 */ 539 static int 540 sparcboot(int fd, Fhdr *fp, ExecHdr *hp) 541 { 542 USED(fd); 543 fp->type = FSPARCB; 544 settext(fp, hp->e.sentry, hp->e.sentry, hp->e.stext, 545 sizeof(struct sparcexec)); 546 setdata(fp, hp->e.sentry+hp->e.stext, hp->e.sdata, 547 fp->txtoff+hp->e.stext, hp->e.sbss); 548 setsym(fp, hp->e.ssyms, 0, hp->e.sdrsize, fp->datoff+hp->e.sdata); 549 fp->hdrsz = 0; /* header stripped */ 550 return 1; 551 } 552 553 /* 554 * next bootable image 555 */ 556 static int 557 nextboot(int fd, Fhdr *fp, ExecHdr *hp) 558 { 559 USED(fd); 560 fp->type = FNEXTB; 561 settext(fp, hp->e.textc.vmaddr, hp->e.textc.vmaddr, 562 hp->e.texts.size, hp->e.texts.offset); 563 setdata(fp, hp->e.datac.vmaddr, hp->e.datas.size, 564 hp->e.datas.offset, hp->e.bsss.size); 565 setsym(fp, hp->e.symc.nsyms, hp->e.symc.spoff, hp->e.symc.pcoff, 566 hp->e.symc.symoff); 567 fp->hdrsz = 0; /* header stripped */ 568 return 1; 569 } 570 571 /* 572 * ELF64 binaries. 573 */ 574 static int 575 elf64dotout(int fd, Fhdr *fp, ExecHdr *hp) 576 { 577 E64hdr *ep; 578 P64hdr *ph; 579 ushort (*swab)(ushort); 580 ulong (*swal)(ulong); 581 uvlong (*swav)(uvlong); 582 int i, it, id, is, phsz; 583 uvlong uvl; 584 585 ep = &hp->e; 586 if(ep->ident[DATA] == ELFDATA2LSB) { 587 swab = leswab; 588 swal = leswal; 589 swav = leswav; 590 } else if(ep->ident[DATA] == ELFDATA2MSB) { 591 swab = beswab; 592 swal = beswal; 593 swav = beswav; 594 } else { 595 werrstr("bad ELF64 encoding - not big or little endian"); 596 return 0; 597 } 598 599 ep->type = swab(ep->type); 600 ep->machine = swab(ep->machine); 601 ep->version = swal(ep->version); 602 if(ep->type != EXEC || ep->version != CURRENT) 603 return 0; 604 ep->elfentry = swav(ep->elfentry); 605 ep->phoff = swav(ep->phoff); 606 ep->shoff = swav(ep->shoff); 607 ep->flags = swal(ep->flags); 608 ep->ehsize = swab(ep->ehsize); 609 ep->phentsize = swab(ep->phentsize); 610 ep->phnum = swab(ep->phnum); 611 ep->shentsize = swab(ep->shentsize); 612 ep->shnum = swab(ep->shnum); 613 ep->shstrndx = swab(ep->shstrndx); 614 615 fp->magic = ELF_MAG; 616 fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; 617 switch(ep->machine) { 618 default: 619 return 0; 620 case AMD64: 621 mach = &mamd64; 622 fp->type = FAMD64; 623 fp->name = "amd64 ELF64 executable"; 624 break; 625 case POWER64: 626 mach = &mpower64; 627 fp->type = FPOWER64; 628 fp->name = "power64 ELF64 executable"; 629 break; 630 } 631 632 if(ep->phentsize != sizeof(P64hdr)) { 633 werrstr("bad ELF64 header size"); 634 return 0; 635 } 636 phsz = sizeof(P64hdr)*ep->phnum; 637 ph = malloc(phsz); 638 if(!ph) 639 return 0; 640 seek(fd, ep->phoff, 0); 641 if(read(fd, ph, phsz) < 0) { 642 free(ph); 643 return 0; 644 } 645 for(i = 0; i < ep->phnum; i++) { 646 ph[i].type = swal(ph[i].type); 647 ph[i].flags = swal(ph[i].flags); 648 ph[i].offset = swav(ph[i].offset); 649 ph[i].vaddr = swav(ph[i].vaddr); 650 ph[i].paddr = swav(ph[i].paddr); 651 ph[i].filesz = swav(ph[i].filesz); 652 ph[i].memsz = swav(ph[i].memsz); 653 ph[i].align = swav(ph[i].align); 654 } 655 656 /* find text, data and symbols and install them */ 657 it = id = is = -1; 658 for(i = 0; i < ep->phnum; i++) { 659 if(ph[i].type == LOAD 660 && (ph[i].flags & (R|X)) == (R|X) && it == -1) 661 it = i; 662 else if(ph[i].type == LOAD 663 && (ph[i].flags & (R|W)) == (R|W) && id == -1) 664 id = i; 665 else if(ph[i].type == NOPTYPE && is == -1) 666 is = i; 667 } 668 if(it == -1 || id == -1) { 669 werrstr("No ELF64 TEXT or DATA sections"); 670 free(ph); 671 return 0; 672 } 673 674 settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset); 675 /* 8c: out of fixed registers */ 676 uvl = ph[id].memsz - ph[id].filesz; 677 setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, uvl); 678 if(is != -1) 679 setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset); 680 free(ph); 681 return 1; 682 } 683 684 /* 685 * ELF32 binaries. 686 */ 687 static int 688 elf32dotout(int fd, Fhdr *fp, ExecHdr *hp) 689 { 690 ulong (*swal)(ulong); 691 ushort (*swab)(ushort); 692 Ehdr *ep; 693 Phdr *ph; 694 int i, it, id, is, phsz; 695 696 /* bitswap the header according to the DATA format */ 697 ep = &hp->e; 698 if(ep->ident[DATA] == ELFDATA2LSB) { 699 swab = leswab; 700 swal = leswal; 701 } else if(ep->ident[DATA] == ELFDATA2MSB) { 702 swab = beswab; 703 swal = beswal; 704 } else { 705 werrstr("bad ELF32 encoding - not big or little endian"); 706 return 0; 707 } 708 709 ep->type = swab(ep->type); 710 ep->machine = swab(ep->machine); 711 ep->version = swal(ep->version); 712 ep->elfentry = swal(ep->elfentry); 713 ep->phoff = swal(ep->phoff); 714 ep->shoff = swal(ep->shoff); 715 ep->flags = swal(ep->flags); 716 ep->ehsize = swab(ep->ehsize); 717 ep->phentsize = swab(ep->phentsize); 718 ep->phnum = swab(ep->phnum); 719 ep->shentsize = swab(ep->shentsize); 720 ep->shnum = swab(ep->shnum); 721 ep->shstrndx = swab(ep->shstrndx); 722 if(ep->type != EXEC || ep->version != CURRENT) 723 return 0; 724 725 /* we could definitely support a lot more machines here */ 726 fp->magic = ELF_MAG; 727 fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; 728 switch(ep->machine) { 729 case I386: 730 mach = &mi386; 731 fp->type = FI386; 732 fp->name = "386 ELF32 executable"; 733 break; 734 case MIPS: 735 mach = &mmips; 736 fp->type = FMIPS; 737 fp->name = "mips ELF32 executable"; 738 break; 739 case SPARC64: 740 mach = &msparc64; 741 fp->type = FSPARC64; 742 fp->name = "sparc64 ELF32 executable"; 743 break; 744 case POWER: 745 mach = &mpower; 746 fp->type = FPOWER; 747 fp->name = "power ELF32 executable"; 748 break; 749 case POWER64: 750 mach = &mpower64; 751 fp->type = FPOWER64; 752 fp->name = "power64 ELF32 executable"; 753 break; 754 case AMD64: 755 mach = &mamd64; 756 fp->type = FAMD64; 757 fp->name = "amd64 ELF32 executable"; 758 break; 759 case ARM: 760 mach = &marm; 761 fp->type = FARM; 762 fp->name = "arm ELF32 executable"; 763 break; 764 default: 765 return 0; 766 } 767 768 if(ep->phentsize != sizeof(Phdr)) { 769 werrstr("bad ELF32 header size"); 770 return 0; 771 } 772 phsz = sizeof(Phdr)*ep->phnum; 773 ph = malloc(phsz); 774 if(!ph) 775 return 0; 776 seek(fd, ep->phoff, 0); 777 if(read(fd, ph, phsz) < 0) { 778 free(ph); 779 return 0; 780 } 781 hswal(ph, phsz/sizeof(ulong), swal); 782 783 /* find text, data and symbols and install them */ 784 it = id = is = -1; 785 for(i = 0; i < ep->phnum; i++) { 786 if(ph[i].type == LOAD 787 && (ph[i].flags & (R|X)) == (R|X) && it == -1) 788 it = i; 789 else if(ph[i].type == LOAD 790 && (ph[i].flags & (R|W)) == (R|W) && id == -1) 791 id = i; 792 else if(ph[i].type == NOPTYPE && is == -1) 793 is = i; 794 } 795 if(it == -1 || id == -1) { 796 /* 797 * The SPARC64 boot image is something of an ELF hack. 798 * Text+Data+BSS are represented by ph[0]. Symbols 799 * are represented by ph[1]: 800 * 801 * filesz, memsz, vaddr, paddr, off 802 * ph[0] : txtsz+datsz, txtsz+datsz+bsssz, txtaddr-KZERO, datasize, txtoff 803 * ph[1] : symsz, lcsz, 0, 0, symoff 804 */ 805 if(ep->machine == SPARC64 && ep->phnum == 2) { 806 ulong txtaddr, txtsz, dataddr, bsssz; 807 808 txtaddr = ph[0].vaddr | 0x80000000; 809 txtsz = ph[0].filesz - ph[0].paddr; 810 dataddr = txtaddr + txtsz; 811 bsssz = ph[0].memsz - ph[0].filesz; 812 settext(fp, ep->elfentry | 0x80000000, txtaddr, txtsz, ph[0].offset); 813 setdata(fp, dataddr, ph[0].paddr, ph[0].offset + txtsz, bsssz); 814 setsym(fp, ph[1].filesz, 0, ph[1].memsz, ph[1].offset); 815 free(ph); 816 return 1; 817 } 818 819 werrstr("No ELF32 TEXT or DATA sections"); 820 free(ph); 821 return 0; 822 } 823 824 settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset); 825 setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, ph[id].memsz - ph[id].filesz); 826 if(is != -1) 827 setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset); 828 free(ph); 829 return 1; 830 } 831 832 /* 833 * Elf binaries. 834 */ 835 static int 836 elfdotout(int fd, Fhdr *fp, ExecHdr *hp) 837 { 838 Ehdr *ep; 839 840 /* bitswap the header according to the DATA format */ 841 ep = &hp->e; 842 if(ep->ident[CLASS] == ELFCLASS32) 843 return elf32dotout(fd, fp, hp); 844 else if(ep->ident[CLASS] == ELFCLASS64) 845 return elf64dotout(fd, fp, hp); 846 847 werrstr("bad ELF class - not 32 bit"); 848 return 0; 849 } 850 851 /* 852 * (Free|Net)BSD ARM header. 853 */ 854 static int 855 armdotout(int fd, Fhdr *fp, ExecHdr *hp) 856 { 857 uvlong kbase; 858 859 USED(fd); 860 settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); 861 setdata(fp, fp->txtsz, hp->e.data, fp->txtsz, hp->e.bss); 862 setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 863 864 kbase = 0xF0000000; 865 if ((fp->entry & kbase) == kbase) { /* Boot image */ 866 fp->txtaddr = kbase+sizeof(Exec); 867 fp->name = "ARM *BSD boot image"; 868 fp->hdrsz = 0; /* header stripped */ 869 fp->dataddr = kbase+fp->txtsz; 870 } 871 return 1; 872 } 873 874 static void 875 settext(Fhdr *fp, uvlong e, uvlong a, long s, vlong off) 876 { 877 fp->txtaddr = a; 878 fp->entry = e; 879 fp->txtsz = s; 880 fp->txtoff = off; 881 } 882 883 static void 884 setdata(Fhdr *fp, uvlong a, long s, vlong off, long bss) 885 { 886 fp->dataddr = a; 887 fp->datsz = s; 888 fp->datoff = off; 889 fp->bsssz = bss; 890 } 891 892 static void 893 setsym(Fhdr *fp, long symsz, long sppcsz, long lnpcsz, vlong symoff) 894 { 895 fp->symsz = symsz; 896 fp->symoff = symoff; 897 fp->sppcsz = sppcsz; 898 fp->sppcoff = fp->symoff+fp->symsz; 899 fp->lnpcsz = lnpcsz; 900 fp->lnpcoff = fp->sppcoff+fp->sppcsz; 901 } 902 903 904 static uvlong 905 _round(uvlong a, ulong b) 906 { 907 uvlong w; 908 909 w = (a/b)*b; 910 if (a!=w) 911 w += b; 912 return(w); 913 } 914