github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/8l/asm.c (about) 1 // Inferno utils/8l/asm.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8l/asm.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 // Writing object files. 32 33 #include "l.h" 34 #include "../ld/lib.h" 35 #include "../ld/elf.h" 36 #include "../ld/dwarf.h" 37 #include "../ld/macho.h" 38 #include "../ld/pe.h" 39 40 char linuxdynld[] = "/lib/ld-linux.so.2"; 41 char freebsddynld[] = "/usr/libexec/ld-elf.so.1"; 42 char openbsddynld[] = "/usr/libexec/ld.so"; 43 char netbsddynld[] = "/usr/libexec/ld.elf_so"; 44 45 int32 46 entryvalue(void) 47 { 48 char *a; 49 Sym *s; 50 51 a = INITENTRY; 52 if(*a >= '0' && *a <= '9') 53 return atolwhex(a); 54 s = lookup(a, 0); 55 if(s->type == 0) 56 return INITTEXT; 57 if(s->type != STEXT) 58 diag("entry not text: %s", s->name); 59 return s->value; 60 } 61 62 vlong 63 datoff(vlong addr) 64 { 65 if(addr >= segdata.vaddr) 66 return addr - segdata.vaddr + segdata.fileoff; 67 if(addr >= segtext.vaddr) 68 return addr - segtext.vaddr + segtext.fileoff; 69 diag("datoff %#llx", addr); 70 return 0; 71 } 72 73 static int 74 needlib(char *name) 75 { 76 char *p; 77 Sym *s; 78 79 if(*name == '\0') 80 return 0; 81 82 /* reuse hash code in symbol table */ 83 p = smprint(".dynlib.%s", name); 84 s = lookup(p, 0); 85 free(p); 86 if(s->type == 0) { 87 s->type = 100; // avoid SDATA, etc. 88 return 1; 89 } 90 return 0; 91 } 92 93 int nelfsym = 1; 94 95 static void addpltsym(Sym*); 96 static void addgotsym(Sym*); 97 98 Sym * 99 lookuprel(void) 100 { 101 return lookup(".rel", 0); 102 } 103 104 void 105 adddynrela(Sym *rela, Sym *s, Reloc *r) 106 { 107 USED(rela); 108 USED(s); 109 USED(r); 110 sysfatal("adddynrela not implemented"); 111 } 112 113 void 114 adddynrel(Sym *s, Reloc *r) 115 { 116 Sym *targ, *rel, *got; 117 118 targ = r->sym; 119 cursym = s; 120 121 switch(r->type) { 122 default: 123 if(r->type >= 256) { 124 diag("unexpected relocation type %d", r->type); 125 return; 126 } 127 break; 128 129 // Handle relocations found in ELF object files. 130 case 256 + R_386_PC32: 131 if(targ->type == SDYNIMPORT) 132 diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ->name); 133 if(targ->type == 0 || targ->type == SXREF) 134 diag("unknown symbol %s in pcrel", targ->name); 135 r->type = D_PCREL; 136 r->add += 4; 137 return; 138 139 case 256 + R_386_PLT32: 140 r->type = D_PCREL; 141 r->add += 4; 142 if(targ->type == SDYNIMPORT) { 143 addpltsym(targ); 144 r->sym = lookup(".plt", 0); 145 r->add += targ->plt; 146 } 147 return; 148 149 case 256 + R_386_GOT32: 150 if(targ->type != SDYNIMPORT) { 151 // have symbol 152 // turn MOVL of GOT entry into LEAL of symbol itself 153 if(r->off < 2 || s->p[r->off-2] != 0x8b) { 154 diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name); 155 return; 156 } 157 s->p[r->off-2] = 0x8d; 158 r->type = D_GOTOFF; 159 return; 160 } 161 addgotsym(targ); 162 r->type = D_CONST; // write r->add during relocsym 163 r->sym = S; 164 r->add += targ->got; 165 return; 166 167 case 256 + R_386_GOTOFF: 168 r->type = D_GOTOFF; 169 return; 170 171 case 256 + R_386_GOTPC: 172 r->type = D_PCREL; 173 r->sym = lookup(".got", 0); 174 r->add += 4; 175 return; 176 177 case 256 + R_386_32: 178 if(targ->type == SDYNIMPORT) 179 diag("unexpected R_386_32 relocation for dynamic symbol %s", targ->name); 180 r->type = D_ADDR; 181 return; 182 183 case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 0: 184 r->type = D_ADDR; 185 if(targ->type == SDYNIMPORT) 186 diag("unexpected reloc for dynamic symbol %s", targ->name); 187 return; 188 189 case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 1: 190 if(targ->type == SDYNIMPORT) { 191 addpltsym(targ); 192 r->sym = lookup(".plt", 0); 193 r->add = targ->plt; 194 r->type = D_PCREL; 195 return; 196 } 197 r->type = D_PCREL; 198 return; 199 200 case 512 + MACHO_FAKE_GOTPCREL: 201 if(targ->type != SDYNIMPORT) { 202 // have symbol 203 // turn MOVL of GOT entry into LEAL of symbol itself 204 if(r->off < 2 || s->p[r->off-2] != 0x8b) { 205 diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name); 206 return; 207 } 208 s->p[r->off-2] = 0x8d; 209 r->type = D_PCREL; 210 return; 211 } 212 addgotsym(targ); 213 r->sym = lookup(".got", 0); 214 r->add += targ->got; 215 r->type = D_PCREL; 216 return; 217 } 218 219 // Handle references to ELF symbols from our own object files. 220 if(targ->type != SDYNIMPORT) 221 return; 222 223 switch(r->type) { 224 case D_PCREL: 225 addpltsym(targ); 226 r->sym = lookup(".plt", 0); 227 r->add = targ->plt; 228 return; 229 230 case D_ADDR: 231 if(s->type != SDATA) 232 break; 233 if(iself) { 234 adddynsym(targ); 235 rel = lookup(".rel", 0); 236 addaddrplus(rel, s, r->off); 237 adduint32(rel, ELF32_R_INFO(targ->dynid, R_386_32)); 238 r->type = D_CONST; // write r->add during relocsym 239 r->sym = S; 240 return; 241 } 242 if(HEADTYPE == Hdarwin && s->size == PtrSize && r->off == 0) { 243 // Mach-O relocations are a royal pain to lay out. 244 // They use a compact stateful bytecode representation 245 // that is too much bother to deal with. 246 // Instead, interpret the C declaration 247 // void *_Cvar_stderr = &stderr; 248 // as making _Cvar_stderr the name of a GOT entry 249 // for stderr. This is separate from the usual GOT entry, 250 // just in case the C code assigns to the variable, 251 // and of course it only works for single pointers, 252 // but we only need to support cgo and that's all it needs. 253 adddynsym(targ); 254 got = lookup(".got", 0); 255 s->type = got->type | SSUB; 256 s->outer = got; 257 s->sub = got->sub; 258 got->sub = s; 259 s->value = got->size; 260 adduint32(got, 0); 261 adduint32(lookup(".linkedit.got", 0), targ->dynid); 262 r->type = 256; // ignore during relocsym 263 return; 264 } 265 break; 266 } 267 268 cursym = s; 269 diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type); 270 } 271 272 int 273 elfreloc1(Reloc *r, vlong sectoff) 274 { 275 int32 elfsym; 276 277 LPUT(sectoff); 278 279 elfsym = r->xsym->elfsym; 280 switch(r->type) { 281 default: 282 return -1; 283 284 case D_ADDR: 285 if(r->siz == 4) 286 LPUT(R_386_32 | elfsym<<8); 287 else 288 return -1; 289 break; 290 291 case D_PCREL: 292 if(r->siz == 4) 293 LPUT(R_386_PC32 | elfsym<<8); 294 else 295 return -1; 296 break; 297 298 case D_TLS: 299 if(r->siz == 4) 300 LPUT(R_386_TLS_LE | elfsym<<8); 301 else 302 return -1; 303 } 304 305 return 0; 306 } 307 308 int 309 machoreloc1(Reloc *r, vlong sectoff) 310 { 311 uint32 v; 312 Sym *rs; 313 314 rs = r->xsym; 315 316 if(rs->type == SHOSTOBJ) { 317 if(rs->dynid < 0) { 318 diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type); 319 return -1; 320 } 321 v = rs->dynid; 322 v |= 1<<27; // external relocation 323 } else { 324 v = rs->sect->extnum; 325 if(v == 0) { 326 diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type); 327 return -1; 328 } 329 } 330 331 switch(r->type) { 332 default: 333 return -1; 334 case D_ADDR: 335 v |= MACHO_GENERIC_RELOC_VANILLA<<28; 336 break; 337 case D_PCREL: 338 v |= 1<<24; // pc-relative bit 339 v |= MACHO_GENERIC_RELOC_VANILLA<<28; 340 break; 341 } 342 343 switch(r->siz) { 344 default: 345 return -1; 346 case 1: 347 v |= 0<<25; 348 break; 349 case 2: 350 v |= 1<<25; 351 break; 352 case 4: 353 v |= 2<<25; 354 break; 355 case 8: 356 v |= 3<<25; 357 break; 358 } 359 360 LPUT(sectoff); 361 LPUT(v); 362 return 0; 363 } 364 365 int 366 archreloc(Reloc *r, Sym *s, vlong *val) 367 { 368 USED(s); 369 switch(r->type) { 370 case D_CONST: 371 *val = r->add; 372 return 0; 373 case D_GOTOFF: 374 *val = symaddr(r->sym) + r->add - symaddr(lookup(".got", 0)); 375 return 0; 376 } 377 return -1; 378 } 379 380 void 381 elfsetupplt(void) 382 { 383 Sym *plt, *got; 384 385 plt = lookup(".plt", 0); 386 got = lookup(".got.plt", 0); 387 if(plt->size == 0) { 388 // pushl got+4 389 adduint8(plt, 0xff); 390 adduint8(plt, 0x35); 391 addaddrplus(plt, got, 4); 392 393 // jmp *got+8 394 adduint8(plt, 0xff); 395 adduint8(plt, 0x25); 396 addaddrplus(plt, got, 8); 397 398 // zero pad 399 adduint32(plt, 0); 400 401 // assume got->size == 0 too 402 addaddrplus(got, lookup(".dynamic", 0), 0); 403 adduint32(got, 0); 404 adduint32(got, 0); 405 } 406 } 407 408 static void 409 addpltsym(Sym *s) 410 { 411 Sym *plt, *got, *rel; 412 413 if(s->plt >= 0) 414 return; 415 416 adddynsym(s); 417 418 if(iself) { 419 plt = lookup(".plt", 0); 420 got = lookup(".got.plt", 0); 421 rel = lookup(".rel.plt", 0); 422 if(plt->size == 0) 423 elfsetupplt(); 424 425 // jmpq *got+size 426 adduint8(plt, 0xff); 427 adduint8(plt, 0x25); 428 addaddrplus(plt, got, got->size); 429 430 // add to got: pointer to current pos in plt 431 addaddrplus(got, plt, plt->size); 432 433 // pushl $x 434 adduint8(plt, 0x68); 435 adduint32(plt, rel->size); 436 437 // jmp .plt 438 adduint8(plt, 0xe9); 439 adduint32(plt, -(plt->size+4)); 440 441 // rel 442 addaddrplus(rel, got, got->size-4); 443 adduint32(rel, ELF32_R_INFO(s->dynid, R_386_JMP_SLOT)); 444 445 s->plt = plt->size - 16; 446 } else if(HEADTYPE == Hdarwin) { 447 // Same laziness as in 6l. 448 449 Sym *plt; 450 451 plt = lookup(".plt", 0); 452 453 addgotsym(s); 454 455 adduint32(lookup(".linkedit.plt", 0), s->dynid); 456 457 // jmpq *got+size(IP) 458 s->plt = plt->size; 459 460 adduint8(plt, 0xff); 461 adduint8(plt, 0x25); 462 addaddrplus(plt, lookup(".got", 0), s->got); 463 } else { 464 diag("addpltsym: unsupported binary format"); 465 } 466 } 467 468 static void 469 addgotsym(Sym *s) 470 { 471 Sym *got, *rel; 472 473 if(s->got >= 0) 474 return; 475 476 adddynsym(s); 477 got = lookup(".got", 0); 478 s->got = got->size; 479 adduint32(got, 0); 480 481 if(iself) { 482 rel = lookup(".rel", 0); 483 addaddrplus(rel, got, s->got); 484 adduint32(rel, ELF32_R_INFO(s->dynid, R_386_GLOB_DAT)); 485 } else if(HEADTYPE == Hdarwin) { 486 adduint32(lookup(".linkedit.got", 0), s->dynid); 487 } else { 488 diag("addgotsym: unsupported binary format"); 489 } 490 } 491 492 void 493 adddynsym(Sym *s) 494 { 495 Sym *d; 496 int t; 497 char *name; 498 499 if(s->dynid >= 0) 500 return; 501 502 if(iself) { 503 s->dynid = nelfsym++; 504 505 d = lookup(".dynsym", 0); 506 507 /* name */ 508 name = s->extname; 509 adduint32(d, addstring(lookup(".dynstr", 0), name)); 510 511 /* value */ 512 if(s->type == SDYNIMPORT) 513 adduint32(d, 0); 514 else 515 addaddr(d, s); 516 517 /* size */ 518 adduint32(d, 0); 519 520 /* type */ 521 t = STB_GLOBAL << 4; 522 if(s->cgoexport && (s->type&SMASK) == STEXT) 523 t |= STT_FUNC; 524 else 525 t |= STT_OBJECT; 526 adduint8(d, t); 527 adduint8(d, 0); 528 529 /* shndx */ 530 if(s->type == SDYNIMPORT) 531 adduint16(d, SHN_UNDEF); 532 else { 533 switch(s->type) { 534 default: 535 case STEXT: 536 t = 11; 537 break; 538 case SRODATA: 539 t = 12; 540 break; 541 case SDATA: 542 t = 13; 543 break; 544 case SBSS: 545 t = 14; 546 break; 547 } 548 adduint16(d, t); 549 } 550 } else if(HEADTYPE == Hdarwin) { 551 diag("adddynsym: missed symbol %s (%s)", s->name, s->extname); 552 } else if(HEADTYPE == Hwindows) { 553 // already taken care of 554 } else { 555 diag("adddynsym: unsupported binary format"); 556 } 557 } 558 559 void 560 adddynlib(char *lib) 561 { 562 Sym *s; 563 564 if(!needlib(lib)) 565 return; 566 567 if(iself) { 568 s = lookup(".dynstr", 0); 569 if(s->size == 0) 570 addstring(s, ""); 571 elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(s, lib)); 572 } else if(HEADTYPE == Hdarwin) { 573 machoadddynlib(lib); 574 } else if(HEADTYPE != Hwindows) { 575 diag("adddynlib: unsupported binary format"); 576 } 577 } 578 579 void 580 asmb(void) 581 { 582 int32 v, magic; 583 uint32 symo, dwarfoff, machlink; 584 Section *sect; 585 Sym *sym; 586 int i; 587 588 if(debug['v']) 589 Bprint(&bso, "%5.2f asmb\n", cputime()); 590 Bflush(&bso); 591 592 if(iself) 593 asmbelfsetup(); 594 595 sect = segtext.sect; 596 cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); 597 codeblk(sect->vaddr, sect->len); 598 599 /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */ 600 for(sect = sect->next; sect != nil; sect = sect->next) { 601 cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); 602 datblk(sect->vaddr, sect->len); 603 } 604 605 if(debug['v']) 606 Bprint(&bso, "%5.2f datblk\n", cputime()); 607 Bflush(&bso); 608 609 cseek(segdata.fileoff); 610 datblk(segdata.vaddr, segdata.filelen); 611 612 machlink = 0; 613 if(HEADTYPE == Hdarwin) { 614 if(debug['v']) 615 Bprint(&bso, "%5.2f dwarf\n", cputime()); 616 617 dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND); 618 cseek(dwarfoff); 619 620 segdwarf.fileoff = cpos(); 621 dwarfemitdebugsections(); 622 segdwarf.filelen = cpos() - segdwarf.fileoff; 623 624 machlink = domacholink(); 625 } 626 627 symsize = 0; 628 spsize = 0; 629 lcsize = 0; 630 symo = 0; 631 if(!debug['s']) { 632 // TODO: rationalize 633 if(debug['v']) 634 Bprint(&bso, "%5.2f sym\n", cputime()); 635 Bflush(&bso); 636 switch(HEADTYPE) { 637 default: 638 if(iself) 639 goto Elfsym; 640 case Hgarbunix: 641 symo = rnd(HEADR+segtext.filelen, 8192)+segdata.filelen; 642 break; 643 case Hunixcoff: 644 symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; 645 break; 646 case Hplan9x32: 647 symo = HEADR+segtext.filelen+segdata.filelen; 648 break; 649 case Hmsdoscom: 650 case Hmsdosexe: 651 debug['s'] = 1; 652 symo = HEADR+segtext.filelen+segdata.filelen; 653 break; 654 case Hdarwin: 655 symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink; 656 break; 657 Elfsym: 658 symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; 659 symo = rnd(symo, INITRND); 660 break; 661 case Hwindows: 662 symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen; 663 symo = rnd(symo, PEFILEALIGN); 664 break; 665 } 666 cseek(symo); 667 switch(HEADTYPE) { 668 default: 669 if(iself) { 670 if(debug['v']) 671 Bprint(&bso, "%5.2f elfsym\n", cputime()); 672 asmelfsym(); 673 cflush(); 674 cwrite(elfstrdat, elfstrsize); 675 676 if(debug['v']) 677 Bprint(&bso, "%5.2f dwarf\n", cputime()); 678 dwarfemitdebugsections(); 679 680 if(linkmode == LinkExternal) 681 elfemitreloc(); 682 } 683 break; 684 case Hplan9x32: 685 asmplan9sym(); 686 cflush(); 687 688 sym = lookup("pclntab", 0); 689 if(sym != nil) { 690 lcsize = sym->np; 691 for(i=0; i < lcsize; i++) 692 cput(sym->p[i]); 693 694 cflush(); 695 } 696 break; 697 case Hwindows: 698 if(debug['v']) 699 Bprint(&bso, "%5.2f dwarf\n", cputime()); 700 dwarfemitdebugsections(); 701 break; 702 case Hdarwin: 703 if(linkmode == LinkExternal) 704 machoemitreloc(); 705 break; 706 } 707 } 708 if(debug['v']) 709 Bprint(&bso, "%5.2f headr\n", cputime()); 710 Bflush(&bso); 711 cseek(0L); 712 switch(HEADTYPE) { 713 default: 714 case Hgarbunix: /* garbage */ 715 lputb(0x160L<<16); /* magic and sections */ 716 lputb(0L); /* time and date */ 717 lputb(rnd(HEADR+segtext.filelen, 4096)+segdata.filelen); 718 lputb(symsize); /* nsyms */ 719 lputb((0x38L<<16)|7L); /* size of optional hdr and flags */ 720 lputb((0413<<16)|0437L); /* magic and version */ 721 lputb(rnd(HEADR+segtext.filelen, 4096)); /* sizes */ 722 lputb(segdata.filelen); 723 lputb(segdata.len - segdata.filelen); 724 lputb(entryvalue()); /* va of entry */ 725 lputb(INITTEXT-HEADR); /* va of base of text */ 726 lputb(segdata.vaddr); /* va of base of data */ 727 lputb(segdata.vaddr+segdata.filelen); /* va of base of bss */ 728 lputb(~0L); /* gp reg mask */ 729 lputb(0L); 730 lputb(0L); 731 lputb(0L); 732 lputb(0L); 733 lputb(~0L); /* gp value ?? */ 734 break; 735 case Hunixcoff: /* unix coff */ 736 /* 737 * file header 738 */ 739 lputl(0x0004014c); /* 4 sections, magic */ 740 lputl(0); /* unix time stamp */ 741 lputl(0); /* symbol table */ 742 lputl(0); /* nsyms */ 743 lputl(0x0003001c); /* flags, sizeof a.out header */ 744 /* 745 * a.out header 746 */ 747 lputl(0x10b); /* magic, version stamp */ 748 lputl(rnd(segtext.filelen, INITRND)); /* text sizes */ 749 lputl(segdata.filelen); /* data sizes */ 750 lputl(segdata.len - segdata.filelen); /* bss sizes */ 751 lputb(entryvalue()); /* va of entry */ 752 lputl(INITTEXT); /* text start */ 753 lputl(segdata.vaddr); /* data start */ 754 /* 755 * text section header 756 */ 757 s8put(".text"); 758 lputl(HEADR); /* pa */ 759 lputl(HEADR); /* va */ 760 lputl(segtext.filelen); /* text size */ 761 lputl(HEADR); /* file offset */ 762 lputl(0); /* relocation */ 763 lputl(0); /* line numbers */ 764 lputl(0); /* relocation, line numbers */ 765 lputl(0x20); /* flags text only */ 766 /* 767 * data section header 768 */ 769 s8put(".data"); 770 lputl(segdata.vaddr); /* pa */ 771 lputl(segdata.vaddr); /* va */ 772 lputl(segdata.filelen); /* data size */ 773 lputl(HEADR+segtext.filelen); /* file offset */ 774 lputl(0); /* relocation */ 775 lputl(0); /* line numbers */ 776 lputl(0); /* relocation, line numbers */ 777 lputl(0x40); /* flags data only */ 778 /* 779 * bss section header 780 */ 781 s8put(".bss"); 782 lputl(segdata.vaddr+segdata.filelen); /* pa */ 783 lputl(segdata.vaddr+segdata.filelen); /* va */ 784 lputl(segdata.len - segdata.filelen); /* bss size */ 785 lputl(0); /* file offset */ 786 lputl(0); /* relocation */ 787 lputl(0); /* line numbers */ 788 lputl(0); /* relocation, line numbers */ 789 lputl(0x80); /* flags bss only */ 790 /* 791 * comment section header 792 */ 793 s8put(".comment"); 794 lputl(0); /* pa */ 795 lputl(0); /* va */ 796 lputl(symsize+lcsize); /* comment size */ 797 lputl(HEADR+segtext.filelen+segdata.filelen); /* file offset */ 798 lputl(HEADR+segtext.filelen+segdata.filelen); /* offset of syms */ 799 lputl(HEADR+segtext.filelen+segdata.filelen+symsize);/* offset of line numbers */ 800 lputl(0); /* relocation, line numbers */ 801 lputl(0x200); /* flags comment only */ 802 break; 803 case Hplan9x32: /* plan9 */ 804 magic = 4*11*11+7; 805 lputb(magic); /* magic */ 806 lputb(segtext.filelen); /* sizes */ 807 lputb(segdata.filelen); 808 lputb(segdata.len - segdata.filelen); 809 lputb(symsize); /* nsyms */ 810 lputb(entryvalue()); /* va of entry */ 811 lputb(spsize); /* sp offsets */ 812 lputb(lcsize); /* line offsets */ 813 break; 814 case Hmsdoscom: 815 /* MS-DOS .COM */ 816 break; 817 case Hmsdosexe: 818 /* fake MS-DOS .EXE */ 819 v = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; 820 wputl(0x5A4D); /* 'MZ' */ 821 wputl(v % 512); /* bytes in last page */ 822 wputl(rnd(v, 512)/512); /* total number of pages */ 823 wputl(0x0000); /* number of reloc items */ 824 v = rnd(HEADR-(INITTEXT & 0xFFFF), 16); 825 wputl(v/16); /* size of header */ 826 wputl(0x0000); /* minimum allocation */ 827 wputl(0xFFFF); /* maximum allocation */ 828 wputl(0x0000); /* initial ss value */ 829 wputl(0x0100); /* initial sp value */ 830 wputl(0x0000); /* complemented checksum */ 831 v = entryvalue(); 832 wputl(v); /* initial ip value (!) */ 833 wputl(0x0000); /* initial cs value */ 834 wputl(0x0000); 835 wputl(0x0000); 836 wputl(0x003E); /* reloc table offset */ 837 wputl(0x0000); /* overlay number */ 838 break; 839 case Hdarwin: 840 asmbmacho(); 841 break; 842 case Hlinux: 843 case Hfreebsd: 844 case Hnetbsd: 845 case Hopenbsd: 846 asmbelf(symo); 847 break; 848 case Hwindows: 849 asmbpe(); 850 break; 851 } 852 cflush(); 853 } 854 855 void 856 s8put(char *n) 857 { 858 char name[8]; 859 int i; 860 861 strncpy(name, n, sizeof(name)); 862 for(i=0; i<sizeof(name); i++) 863 cput(name[i]); 864 } 865 866 int32 867 rnd(int32 v, int32 r) 868 { 869 int32 c; 870 871 if(r <= 0) 872 return v; 873 v += r - 1; 874 c = v % r; 875 if(c < 0) 876 c += r; 877 v -= c; 878 return v; 879 }