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