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