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