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