github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/cmd/6l/asm.c (about) 1 // Inferno utils/6l/asm.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/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 #define PADDR(a) ((uint32)(a) & ~0x80000000) 41 42 char linuxdynld[] = "/lib64/ld-linux-x86-64.so.2"; 43 char freebsddynld[] = "/libexec/ld-elf.so.1"; 44 char openbsddynld[] = "/usr/libexec/ld.so"; 45 char netbsddynld[] = "/libexec/ld.elf_so"; 46 char dragonflydynld[] = "/usr/libexec/ld-elf.so.2"; 47 char solarisdynld[] = "/lib/amd64/ld.so.1"; 48 49 char zeroes[32]; 50 51 static int 52 needlib(char *name) 53 { 54 char *p; 55 LSym *s; 56 57 if(*name == '\0') 58 return 0; 59 60 /* reuse hash code in symbol table */ 61 p = smprint(".elfload.%s", name); 62 s = linklookup(ctxt, p, 0); 63 free(p); 64 if(s->type == 0) { 65 s->type = 100; // avoid SDATA, etc. 66 return 1; 67 } 68 return 0; 69 } 70 71 int nelfsym = 1; 72 73 static void addpltsym(LSym*); 74 static void addgotsym(LSym*); 75 76 void 77 gentext(void) 78 { 79 } 80 81 void 82 adddynrela(LSym *rela, LSym *s, Reloc *r) 83 { 84 addaddrplus(ctxt, rela, s, r->off); 85 adduint64(ctxt, rela, R_X86_64_RELATIVE); 86 addaddrplus(ctxt, rela, r->sym, r->add); // Addend 87 } 88 89 void 90 adddynrel(LSym *s, Reloc *r) 91 { 92 LSym *targ, *rela, *got; 93 94 targ = r->sym; 95 ctxt->cursym = s; 96 97 switch(r->type) { 98 default: 99 if(r->type >= 256) { 100 diag("unexpected relocation type %d", r->type); 101 return; 102 } 103 break; 104 105 // Handle relocations found in ELF object files. 106 case 256 + R_X86_64_PC32: 107 if(targ->type == SDYNIMPORT) 108 diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ->name); 109 if(targ->type == 0 || targ->type == SXREF) 110 diag("unknown symbol %s in pcrel", targ->name); 111 r->type = R_PCREL; 112 r->add += 4; 113 return; 114 115 case 256 + R_X86_64_PLT32: 116 r->type = R_PCREL; 117 r->add += 4; 118 if(targ->type == SDYNIMPORT) { 119 addpltsym(targ); 120 r->sym = linklookup(ctxt, ".plt", 0); 121 r->add += targ->plt; 122 } 123 return; 124 125 case 256 + R_X86_64_GOTPCREL: 126 if(targ->type != SDYNIMPORT) { 127 // have symbol 128 if(r->off >= 2 && s->p[r->off-2] == 0x8b) { 129 // turn MOVQ of GOT entry into LEAQ of symbol itself 130 s->p[r->off-2] = 0x8d; 131 r->type = R_PCREL; 132 r->add += 4; 133 return; 134 } 135 // fall back to using GOT and hope for the best (CMOV*) 136 // TODO: just needs relocation, no need to put in .dynsym 137 } 138 addgotsym(targ); 139 r->type = R_PCREL; 140 r->sym = linklookup(ctxt, ".got", 0); 141 r->add += 4; 142 r->add += targ->got; 143 return; 144 145 case 256 + R_X86_64_64: 146 if(targ->type == SDYNIMPORT) 147 diag("unexpected R_X86_64_64 relocation for dynamic symbol %s", targ->name); 148 r->type = R_ADDR; 149 return; 150 151 // Handle relocations found in Mach-O object files. 152 case 512 + MACHO_X86_64_RELOC_UNSIGNED*2 + 0: 153 case 512 + MACHO_X86_64_RELOC_SIGNED*2 + 0: 154 case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 0: 155 // TODO: What is the difference between all these? 156 r->type = R_ADDR; 157 if(targ->type == SDYNIMPORT) 158 diag("unexpected reloc for dynamic symbol %s", targ->name); 159 return; 160 161 case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 1: 162 if(targ->type == SDYNIMPORT) { 163 addpltsym(targ); 164 r->sym = linklookup(ctxt, ".plt", 0); 165 r->add = targ->plt; 166 r->type = R_PCREL; 167 return; 168 } 169 // fall through 170 case 512 + MACHO_X86_64_RELOC_UNSIGNED*2 + 1: 171 case 512 + MACHO_X86_64_RELOC_SIGNED*2 + 1: 172 case 512 + MACHO_X86_64_RELOC_SIGNED_1*2 + 1: 173 case 512 + MACHO_X86_64_RELOC_SIGNED_2*2 + 1: 174 case 512 + MACHO_X86_64_RELOC_SIGNED_4*2 + 1: 175 r->type = R_PCREL; 176 if(targ->type == SDYNIMPORT) 177 diag("unexpected pc-relative reloc for dynamic symbol %s", targ->name); 178 return; 179 180 case 512 + MACHO_X86_64_RELOC_GOT_LOAD*2 + 1: 181 if(targ->type != SDYNIMPORT) { 182 // have symbol 183 // turn MOVQ of GOT entry into LEAQ of symbol itself 184 if(r->off < 2 || s->p[r->off-2] != 0x8b) { 185 diag("unexpected GOT_LOAD reloc for non-dynamic symbol %s", targ->name); 186 return; 187 } 188 s->p[r->off-2] = 0x8d; 189 r->type = R_PCREL; 190 return; 191 } 192 // fall through 193 case 512 + MACHO_X86_64_RELOC_GOT*2 + 1: 194 if(targ->type != SDYNIMPORT) 195 diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name); 196 addgotsym(targ); 197 r->type = R_PCREL; 198 r->sym = linklookup(ctxt, ".got", 0); 199 r->add += targ->got; 200 return; 201 } 202 203 // Handle references to ELF symbols from our own object files. 204 if(targ->type != SDYNIMPORT) 205 return; 206 207 switch(r->type) { 208 case R_CALL: 209 case R_PCREL: 210 addpltsym(targ); 211 r->sym = linklookup(ctxt, ".plt", 0); 212 r->add = targ->plt; 213 return; 214 215 case R_ADDR: 216 if(s->type == STEXT && iself) { 217 // The code is asking for the address of an external 218 // function. We provide it with the address of the 219 // correspondent GOT symbol. 220 addgotsym(targ); 221 r->sym = linklookup(ctxt, ".got", 0); 222 r->add += targ->got; 223 return; 224 } 225 if(s->type != SDATA) 226 break; 227 if(iself) { 228 adddynsym(ctxt, targ); 229 rela = linklookup(ctxt, ".rela", 0); 230 addaddrplus(ctxt, rela, s, r->off); 231 if(r->siz == 8) 232 adduint64(ctxt, rela, ELF64_R_INFO(targ->dynid, R_X86_64_64)); 233 else 234 adduint64(ctxt, rela, ELF64_R_INFO(targ->dynid, R_X86_64_32)); 235 adduint64(ctxt, rela, r->add); 236 r->type = 256; // ignore during relocsym 237 return; 238 } 239 if(HEADTYPE == Hdarwin && s->size == PtrSize && r->off == 0) { 240 // Mach-O relocations are a royal pain to lay out. 241 // They use a compact stateful bytecode representation 242 // that is too much bother to deal with. 243 // Instead, interpret the C declaration 244 // void *_Cvar_stderr = &stderr; 245 // as making _Cvar_stderr the name of a GOT entry 246 // for stderr. This is separate from the usual GOT entry, 247 // just in case the C code assigns to the variable, 248 // and of course it only works for single pointers, 249 // but we only need to support cgo and that's all it needs. 250 adddynsym(ctxt, targ); 251 got = linklookup(ctxt, ".got", 0); 252 s->type = got->type | SSUB; 253 s->outer = got; 254 s->sub = got->sub; 255 got->sub = s; 256 s->value = got->size; 257 adduint64(ctxt, got, 0); 258 adduint32(ctxt, linklookup(ctxt, ".linkedit.got", 0), targ->dynid); 259 r->type = 256; // ignore during relocsym 260 return; 261 } 262 break; 263 } 264 265 ctxt->cursym = s; 266 diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type); 267 } 268 269 int 270 elfreloc1(Reloc *r, vlong sectoff) 271 { 272 int32 elfsym; 273 274 VPUT(sectoff); 275 276 elfsym = r->xsym->elfsym; 277 switch(r->type) { 278 default: 279 return -1; 280 281 case R_ADDR: 282 if(r->siz == 4) 283 VPUT(R_X86_64_32 | (uint64)elfsym<<32); 284 else if(r->siz == 8) 285 VPUT(R_X86_64_64 | (uint64)elfsym<<32); 286 else 287 return -1; 288 break; 289 290 case R_TLS_LE: 291 if(r->siz == 4) 292 VPUT(R_X86_64_TPOFF32 | (uint64)elfsym<<32); 293 else 294 return -1; 295 break; 296 297 case R_CALL: 298 if(r->siz == 4) { 299 if(r->xsym->type == SDYNIMPORT) 300 VPUT(R_X86_64_GOTPCREL | (uint64)elfsym<<32); 301 else 302 VPUT(R_X86_64_PC32 | (uint64)elfsym<<32); 303 } else 304 return -1; 305 break; 306 307 case R_PCREL: 308 if(r->siz == 4) { 309 VPUT(R_X86_64_PC32 | (uint64)elfsym<<32); 310 } else 311 return -1; 312 break; 313 314 case R_TLS: 315 if(r->siz == 4) { 316 if(flag_shared) 317 VPUT(R_X86_64_GOTTPOFF | (uint64)elfsym<<32); 318 else 319 VPUT(R_X86_64_TPOFF32 | (uint64)elfsym<<32); 320 } else 321 return -1; 322 break; 323 } 324 325 VPUT(r->xadd); 326 return 0; 327 } 328 329 int 330 machoreloc1(Reloc *r, vlong sectoff) 331 { 332 uint32 v; 333 LSym *rs; 334 335 rs = r->xsym; 336 337 if(rs->type == SHOSTOBJ || r->type == R_PCREL) { 338 if(rs->dynid < 0) { 339 diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type); 340 return -1; 341 } 342 v = rs->dynid; 343 v |= 1<<27; // external relocation 344 } else { 345 v = rs->sect->extnum; 346 if(v == 0) { 347 diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type); 348 return -1; 349 } 350 } 351 352 switch(r->type) { 353 default: 354 return -1; 355 case R_ADDR: 356 v |= MACHO_X86_64_RELOC_UNSIGNED<<28; 357 break; 358 case R_CALL: 359 v |= 1<<24; // pc-relative bit 360 v |= MACHO_X86_64_RELOC_BRANCH<<28; 361 break; 362 case R_PCREL: 363 // NOTE: Only works with 'external' relocation. Forced above. 364 v |= 1<<24; // pc-relative bit 365 v |= MACHO_X86_64_RELOC_SIGNED<<28; 366 } 367 368 switch(r->siz) { 369 default: 370 return -1; 371 case 1: 372 v |= 0<<25; 373 break; 374 case 2: 375 v |= 1<<25; 376 break; 377 case 4: 378 v |= 2<<25; 379 break; 380 case 8: 381 v |= 3<<25; 382 break; 383 } 384 385 LPUT(sectoff); 386 LPUT(v); 387 return 0; 388 } 389 390 int 391 archreloc(Reloc *r, LSym *s, vlong *val) 392 { 393 USED(r); 394 USED(s); 395 USED(val); 396 return -1; 397 } 398 399 vlong 400 archrelocvariant(Reloc *r, LSym *s, vlong t) 401 { 402 USED(r); 403 USED(s); 404 sysfatal("unexpected relocation variant"); 405 return t; 406 } 407 408 void 409 elfsetupplt(void) 410 { 411 LSym *plt, *got; 412 413 plt = linklookup(ctxt, ".plt", 0); 414 got = linklookup(ctxt, ".got.plt", 0); 415 if(plt->size == 0) { 416 // pushq got+8(IP) 417 adduint8(ctxt, plt, 0xff); 418 adduint8(ctxt, plt, 0x35); 419 addpcrelplus(ctxt, plt, got, 8); 420 421 // jmpq got+16(IP) 422 adduint8(ctxt, plt, 0xff); 423 adduint8(ctxt, plt, 0x25); 424 addpcrelplus(ctxt, plt, got, 16); 425 426 // nopl 0(AX) 427 adduint32(ctxt, plt, 0x00401f0f); 428 429 // assume got->size == 0 too 430 addaddrplus(ctxt, got, linklookup(ctxt, ".dynamic", 0), 0); 431 adduint64(ctxt, got, 0); 432 adduint64(ctxt, got, 0); 433 } 434 } 435 436 static void 437 addpltsym(LSym *s) 438 { 439 if(s->plt >= 0) 440 return; 441 442 adddynsym(ctxt, s); 443 444 if(iself) { 445 LSym *plt, *got, *rela; 446 447 plt = linklookup(ctxt, ".plt", 0); 448 got = linklookup(ctxt, ".got.plt", 0); 449 rela = linklookup(ctxt, ".rela.plt", 0); 450 if(plt->size == 0) 451 elfsetupplt(); 452 453 // jmpq *got+size(IP) 454 adduint8(ctxt, plt, 0xff); 455 adduint8(ctxt, plt, 0x25); 456 addpcrelplus(ctxt, plt, got, got->size); 457 458 // add to got: pointer to current pos in plt 459 addaddrplus(ctxt, got, plt, plt->size); 460 461 // pushq $x 462 adduint8(ctxt, plt, 0x68); 463 adduint32(ctxt, plt, (got->size-24-8)/8); 464 465 // jmpq .plt 466 adduint8(ctxt, plt, 0xe9); 467 adduint32(ctxt, plt, -(plt->size+4)); 468 469 // rela 470 addaddrplus(ctxt, rela, got, got->size-8); 471 adduint64(ctxt, rela, ELF64_R_INFO(s->dynid, R_X86_64_JMP_SLOT)); 472 adduint64(ctxt, rela, 0); 473 474 s->plt = plt->size - 16; 475 } else if(HEADTYPE == Hdarwin) { 476 // To do lazy symbol lookup right, we're supposed 477 // to tell the dynamic loader which library each 478 // symbol comes from and format the link info 479 // section just so. I'm too lazy (ha!) to do that 480 // so for now we'll just use non-lazy pointers, 481 // which don't need to be told which library to use. 482 // 483 // http://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html 484 // has details about what we're avoiding. 485 486 LSym *plt; 487 488 addgotsym(s); 489 plt = linklookup(ctxt, ".plt", 0); 490 491 adduint32(ctxt, linklookup(ctxt, ".linkedit.plt", 0), s->dynid); 492 493 // jmpq *got+size(IP) 494 s->plt = plt->size; 495 496 adduint8(ctxt, plt, 0xff); 497 adduint8(ctxt, plt, 0x25); 498 addpcrelplus(ctxt, plt, linklookup(ctxt, ".got", 0), s->got); 499 } else { 500 diag("addpltsym: unsupported binary format"); 501 } 502 } 503 504 static void 505 addgotsym(LSym *s) 506 { 507 LSym *got, *rela; 508 509 if(s->got >= 0) 510 return; 511 512 adddynsym(ctxt, s); 513 got = linklookup(ctxt, ".got", 0); 514 s->got = got->size; 515 adduint64(ctxt, got, 0); 516 517 if(iself) { 518 rela = linklookup(ctxt, ".rela", 0); 519 addaddrplus(ctxt, rela, got, s->got); 520 adduint64(ctxt, rela, ELF64_R_INFO(s->dynid, R_X86_64_GLOB_DAT)); 521 adduint64(ctxt, rela, 0); 522 } else if(HEADTYPE == Hdarwin) { 523 adduint32(ctxt, linklookup(ctxt, ".linkedit.got", 0), s->dynid); 524 } else { 525 diag("addgotsym: unsupported binary format"); 526 } 527 } 528 529 void 530 adddynsym(Link *ctxt, LSym *s) 531 { 532 LSym *d; 533 int t; 534 char *name; 535 536 if(s->dynid >= 0) 537 return; 538 539 if(iself) { 540 s->dynid = nelfsym++; 541 542 d = linklookup(ctxt, ".dynsym", 0); 543 544 name = s->extname; 545 adduint32(ctxt, d, addstring(linklookup(ctxt, ".dynstr", 0), name)); 546 /* type */ 547 t = STB_GLOBAL << 4; 548 if(s->cgoexport && (s->type&SMASK) == STEXT) 549 t |= STT_FUNC; 550 else 551 t |= STT_OBJECT; 552 adduint8(ctxt, d, t); 553 554 /* reserved */ 555 adduint8(ctxt, d, 0); 556 557 /* section where symbol is defined */ 558 if(s->type == SDYNIMPORT) 559 adduint16(ctxt, d, SHN_UNDEF); 560 else 561 adduint16(ctxt, d, 1); 562 563 /* value */ 564 if(s->type == SDYNIMPORT) 565 adduint64(ctxt, d, 0); 566 else 567 addaddr(ctxt, d, s); 568 569 /* size of object */ 570 adduint64(ctxt, d, s->size); 571 572 if(!(s->cgoexport & CgoExportDynamic) && s->dynimplib && needlib(s->dynimplib)) { 573 elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, 574 addstring(linklookup(ctxt, ".dynstr", 0), s->dynimplib)); 575 } 576 } else if(HEADTYPE == Hdarwin) { 577 diag("adddynsym: missed symbol %s (%s)", s->name, s->extname); 578 } else if(HEADTYPE == Hwindows) { 579 // already taken care of 580 } else { 581 diag("adddynsym: unsupported binary format"); 582 } 583 } 584 585 void 586 adddynlib(char *lib) 587 { 588 LSym *s; 589 590 if(!needlib(lib)) 591 return; 592 593 if(iself) { 594 s = linklookup(ctxt, ".dynstr", 0); 595 if(s->size == 0) 596 addstring(s, ""); 597 elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(s, lib)); 598 } else if(HEADTYPE == Hdarwin) { 599 machoadddynlib(lib); 600 } else { 601 diag("adddynlib: unsupported binary format"); 602 } 603 } 604 605 void 606 asmb(void) 607 { 608 int32 magic; 609 int i; 610 vlong vl, symo, dwarfoff, machlink; 611 Section *sect; 612 LSym *sym; 613 614 if(debug['v']) 615 Bprint(&bso, "%5.2f asmb\n", cputime()); 616 Bflush(&bso); 617 618 if(debug['v']) 619 Bprint(&bso, "%5.2f codeblk\n", cputime()); 620 Bflush(&bso); 621 622 if(iself) 623 asmbelfsetup(); 624 625 sect = segtext.sect; 626 cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); 627 codeblk(sect->vaddr, sect->len); 628 for(sect = sect->next; sect != nil; sect = sect->next) { 629 cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); 630 datblk(sect->vaddr, sect->len); 631 } 632 633 if(segrodata.filelen > 0) { 634 if(debug['v']) 635 Bprint(&bso, "%5.2f rodatblk\n", cputime()); 636 Bflush(&bso); 637 638 cseek(segrodata.fileoff); 639 datblk(segrodata.vaddr, segrodata.filelen); 640 } 641 642 if(debug['v']) 643 Bprint(&bso, "%5.2f datblk\n", cputime()); 644 Bflush(&bso); 645 646 cseek(segdata.fileoff); 647 datblk(segdata.vaddr, segdata.filelen); 648 649 machlink = 0; 650 if(HEADTYPE == Hdarwin) { 651 if(debug['v']) 652 Bprint(&bso, "%5.2f dwarf\n", cputime()); 653 654 dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND); 655 cseek(dwarfoff); 656 657 segdwarf.fileoff = cpos(); 658 dwarfemitdebugsections(); 659 segdwarf.filelen = cpos() - segdwarf.fileoff; 660 661 machlink = domacholink(); 662 } 663 664 switch(HEADTYPE) { 665 default: 666 diag("unknown header type %d", HEADTYPE); 667 case Hplan9: 668 case Helf: 669 break; 670 case Hdarwin: 671 debug['8'] = 1; /* 64-bit addresses */ 672 break; 673 case Hlinux: 674 case Hfreebsd: 675 case Hnetbsd: 676 case Hopenbsd: 677 case Hdragonfly: 678 case Hsolaris: 679 debug['8'] = 1; /* 64-bit addresses */ 680 break; 681 case Hnacl: 682 case Hwindows: 683 break; 684 } 685 686 symsize = 0; 687 spsize = 0; 688 lcsize = 0; 689 symo = 0; 690 if(!debug['s']) { 691 if(debug['v']) 692 Bprint(&bso, "%5.2f sym\n", cputime()); 693 Bflush(&bso); 694 switch(HEADTYPE) { 695 default: 696 case Hplan9: 697 case Helf: 698 debug['s'] = 1; 699 symo = segdata.fileoff+segdata.filelen; 700 break; 701 case Hdarwin: 702 symo = segdata.fileoff+rnd(segdata.filelen, INITRND)+machlink; 703 break; 704 case Hlinux: 705 case Hfreebsd: 706 case Hnetbsd: 707 case Hopenbsd: 708 case Hdragonfly: 709 case Hsolaris: 710 case Hnacl: 711 symo = segdata.fileoff+segdata.filelen; 712 symo = rnd(symo, INITRND); 713 break; 714 case Hwindows: 715 symo = segdata.fileoff+segdata.filelen; 716 symo = rnd(symo, PEFILEALIGN); 717 break; 718 } 719 cseek(symo); 720 switch(HEADTYPE) { 721 default: 722 if(iself) { 723 cseek(symo); 724 asmelfsym(); 725 cflush(); 726 cwrite(elfstrdat, elfstrsize); 727 728 if(debug['v']) 729 Bprint(&bso, "%5.2f dwarf\n", cputime()); 730 731 dwarfemitdebugsections(); 732 733 if(linkmode == LinkExternal) 734 elfemitreloc(); 735 } 736 break; 737 case Hplan9: 738 asmplan9sym(); 739 cflush(); 740 741 sym = linklookup(ctxt, "pclntab", 0); 742 if(sym != nil) { 743 lcsize = sym->np; 744 for(i=0; i < lcsize; i++) 745 cput(sym->p[i]); 746 747 cflush(); 748 } 749 break; 750 case Hwindows: 751 if(debug['v']) 752 Bprint(&bso, "%5.2f dwarf\n", cputime()); 753 754 dwarfemitdebugsections(); 755 break; 756 case Hdarwin: 757 if(linkmode == LinkExternal) 758 machoemitreloc(); 759 break; 760 } 761 } 762 763 if(debug['v']) 764 Bprint(&bso, "%5.2f headr\n", cputime()); 765 Bflush(&bso); 766 cseek(0L); 767 switch(HEADTYPE) { 768 default: 769 case Hplan9: /* plan9 */ 770 magic = 4*26*26+7; 771 magic |= 0x00008000; /* fat header */ 772 lputb(magic); /* magic */ 773 lputb(segtext.filelen); /* sizes */ 774 lputb(segdata.filelen); 775 lputb(segdata.len - segdata.filelen); 776 lputb(symsize); /* nsyms */ 777 vl = entryvalue(); 778 lputb(PADDR(vl)); /* va of entry */ 779 lputb(spsize); /* sp offsets */ 780 lputb(lcsize); /* line offsets */ 781 vputb(vl); /* va of entry */ 782 break; 783 case Hdarwin: 784 asmbmacho(); 785 break; 786 case Hlinux: 787 case Hfreebsd: 788 case Hnetbsd: 789 case Hopenbsd: 790 case Hdragonfly: 791 case Hsolaris: 792 case Hnacl: 793 asmbelf(symo); 794 break; 795 case Hwindows: 796 asmbpe(); 797 break; 798 } 799 cflush(); 800 } 801 802 vlong 803 rnd(vlong v, vlong r) 804 { 805 vlong c; 806 807 if(r <= 0) 808 return v; 809 v += r - 1; 810 c = v % r; 811 if(c < 0) 812 c += r; 813 v -= c; 814 return v; 815 }