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