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