github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/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 case R_PCREL: 294 if(r->siz == 4) { 295 if(r->xsym->type == SDYNIMPORT) 296 VPUT(R_X86_64_GOTPCREL | (uint64)elfsym<<32); 297 else 298 VPUT(R_X86_64_PC32 | (uint64)elfsym<<32); 299 } else 300 return -1; 301 break; 302 303 case R_TLS: 304 if(r->siz == 4) { 305 if(flag_shared) 306 VPUT(R_X86_64_GOTTPOFF | (uint64)elfsym<<32); 307 else 308 VPUT(R_X86_64_TPOFF32 | (uint64)elfsym<<32); 309 } else 310 return -1; 311 break; 312 } 313 314 VPUT(r->xadd); 315 return 0; 316 } 317 318 int 319 machoreloc1(Reloc *r, vlong sectoff) 320 { 321 uint32 v; 322 LSym *rs; 323 324 rs = r->xsym; 325 326 if(rs->type == SHOSTOBJ) { 327 if(rs->dynid < 0) { 328 diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type); 329 return -1; 330 } 331 v = rs->dynid; 332 v |= 1<<27; // external relocation 333 } else { 334 v = rs->sect->extnum; 335 if(v == 0) { 336 diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type); 337 return -1; 338 } 339 } 340 341 switch(r->type) { 342 default: 343 return -1; 344 case R_ADDR: 345 v |= MACHO_X86_64_RELOC_UNSIGNED<<28; 346 break; 347 case R_CALL: 348 case R_PCREL: 349 v |= 1<<24; // pc-relative bit 350 v |= MACHO_X86_64_RELOC_BRANCH<<28; 351 break; 352 } 353 354 switch(r->siz) { 355 default: 356 return -1; 357 case 1: 358 v |= 0<<25; 359 break; 360 case 2: 361 v |= 1<<25; 362 break; 363 case 4: 364 v |= 2<<25; 365 break; 366 case 8: 367 v |= 3<<25; 368 break; 369 } 370 371 LPUT(sectoff); 372 LPUT(v); 373 return 0; 374 } 375 376 int 377 archreloc(Reloc *r, LSym *s, vlong *val) 378 { 379 USED(r); 380 USED(s); 381 USED(val); 382 return -1; 383 } 384 385 void 386 elfsetupplt(void) 387 { 388 LSym *plt, *got; 389 390 plt = linklookup(ctxt, ".plt", 0); 391 got = linklookup(ctxt, ".got.plt", 0); 392 if(plt->size == 0) { 393 // pushq got+8(IP) 394 adduint8(ctxt, plt, 0xff); 395 adduint8(ctxt, plt, 0x35); 396 addpcrelplus(ctxt, plt, got, 8); 397 398 // jmpq got+16(IP) 399 adduint8(ctxt, plt, 0xff); 400 adduint8(ctxt, plt, 0x25); 401 addpcrelplus(ctxt, plt, got, 16); 402 403 // nopl 0(AX) 404 adduint32(ctxt, plt, 0x00401f0f); 405 406 // assume got->size == 0 too 407 addaddrplus(ctxt, got, linklookup(ctxt, ".dynamic", 0), 0); 408 adduint64(ctxt, got, 0); 409 adduint64(ctxt, got, 0); 410 } 411 } 412 413 static void 414 addpltsym(LSym *s) 415 { 416 if(s->plt >= 0) 417 return; 418 419 adddynsym(ctxt, s); 420 421 if(iself) { 422 LSym *plt, *got, *rela; 423 424 plt = linklookup(ctxt, ".plt", 0); 425 got = linklookup(ctxt, ".got.plt", 0); 426 rela = linklookup(ctxt, ".rela.plt", 0); 427 if(plt->size == 0) 428 elfsetupplt(); 429 430 // jmpq *got+size(IP) 431 adduint8(ctxt, plt, 0xff); 432 adduint8(ctxt, plt, 0x25); 433 addpcrelplus(ctxt, plt, got, got->size); 434 435 // add to got: pointer to current pos in plt 436 addaddrplus(ctxt, got, plt, plt->size); 437 438 // pushq $x 439 adduint8(ctxt, plt, 0x68); 440 adduint32(ctxt, plt, (got->size-24-8)/8); 441 442 // jmpq .plt 443 adduint8(ctxt, plt, 0xe9); 444 adduint32(ctxt, plt, -(plt->size+4)); 445 446 // rela 447 addaddrplus(ctxt, rela, got, got->size-8); 448 adduint64(ctxt, rela, ELF64_R_INFO(s->dynid, R_X86_64_JMP_SLOT)); 449 adduint64(ctxt, rela, 0); 450 451 s->plt = plt->size - 16; 452 } else if(HEADTYPE == Hdarwin) { 453 // To do lazy symbol lookup right, we're supposed 454 // to tell the dynamic loader which library each 455 // symbol comes from and format the link info 456 // section just so. I'm too lazy (ha!) to do that 457 // so for now we'll just use non-lazy pointers, 458 // which don't need to be told which library to use. 459 // 460 // http://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html 461 // has details about what we're avoiding. 462 463 LSym *plt; 464 465 addgotsym(s); 466 plt = linklookup(ctxt, ".plt", 0); 467 468 adduint32(ctxt, linklookup(ctxt, ".linkedit.plt", 0), s->dynid); 469 470 // jmpq *got+size(IP) 471 s->plt = plt->size; 472 473 adduint8(ctxt, plt, 0xff); 474 adduint8(ctxt, plt, 0x25); 475 addpcrelplus(ctxt, plt, linklookup(ctxt, ".got", 0), s->got); 476 } else { 477 diag("addpltsym: unsupported binary format"); 478 } 479 } 480 481 static void 482 addgotsym(LSym *s) 483 { 484 LSym *got, *rela; 485 486 if(s->got >= 0) 487 return; 488 489 adddynsym(ctxt, s); 490 got = linklookup(ctxt, ".got", 0); 491 s->got = got->size; 492 adduint64(ctxt, got, 0); 493 494 if(iself) { 495 rela = linklookup(ctxt, ".rela", 0); 496 addaddrplus(ctxt, rela, got, s->got); 497 adduint64(ctxt, rela, ELF64_R_INFO(s->dynid, R_X86_64_GLOB_DAT)); 498 adduint64(ctxt, rela, 0); 499 } else if(HEADTYPE == Hdarwin) { 500 adduint32(ctxt, linklookup(ctxt, ".linkedit.got", 0), s->dynid); 501 } else { 502 diag("addgotsym: unsupported binary format"); 503 } 504 } 505 506 void 507 adddynsym(Link *ctxt, LSym *s) 508 { 509 LSym *d; 510 int t; 511 char *name; 512 513 if(s->dynid >= 0) 514 return; 515 516 if(iself) { 517 s->dynid = nelfsym++; 518 519 d = linklookup(ctxt, ".dynsym", 0); 520 521 name = s->extname; 522 adduint32(ctxt, d, addstring(linklookup(ctxt, ".dynstr", 0), name)); 523 /* type */ 524 t = STB_GLOBAL << 4; 525 if(s->cgoexport && (s->type&SMASK) == STEXT) 526 t |= STT_FUNC; 527 else 528 t |= STT_OBJECT; 529 adduint8(ctxt, d, t); 530 531 /* reserved */ 532 adduint8(ctxt, d, 0); 533 534 /* section where symbol is defined */ 535 if(s->type == SDYNIMPORT) 536 adduint16(ctxt, d, SHN_UNDEF); 537 else { 538 switch(s->type) { 539 default: 540 case STEXT: 541 t = 11; 542 break; 543 case SRODATA: 544 t = 12; 545 break; 546 case SDATA: 547 t = 13; 548 break; 549 case SBSS: 550 t = 14; 551 break; 552 } 553 adduint16(ctxt, d, t); 554 } 555 556 /* value */ 557 if(s->type == SDYNIMPORT) 558 adduint64(ctxt, d, 0); 559 else 560 addaddr(ctxt, d, s); 561 562 /* size of object */ 563 adduint64(ctxt, d, s->size); 564 565 if(!(s->cgoexport & CgoExportDynamic) && s->dynimplib && needlib(s->dynimplib)) { 566 elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, 567 addstring(linklookup(ctxt, ".dynstr", 0), s->dynimplib)); 568 } 569 } else if(HEADTYPE == Hdarwin) { 570 diag("adddynsym: missed symbol %s (%s)", s->name, s->extname); 571 } else if(HEADTYPE == Hwindows) { 572 // already taken care of 573 } else { 574 diag("adddynsym: unsupported binary format"); 575 } 576 } 577 578 void 579 adddynlib(char *lib) 580 { 581 LSym *s; 582 583 if(!needlib(lib)) 584 return; 585 586 if(iself) { 587 s = linklookup(ctxt, ".dynstr", 0); 588 if(s->size == 0) 589 addstring(s, ""); 590 elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(s, lib)); 591 } else if(HEADTYPE == Hdarwin) { 592 machoadddynlib(lib); 593 } else { 594 diag("adddynlib: unsupported binary format"); 595 } 596 } 597 598 void 599 asmb(void) 600 { 601 int32 magic; 602 int i; 603 vlong vl, symo, dwarfoff, machlink; 604 Section *sect; 605 LSym *sym; 606 607 if(debug['v']) 608 Bprint(&bso, "%5.2f asmb\n", cputime()); 609 Bflush(&bso); 610 611 if(debug['v']) 612 Bprint(&bso, "%5.2f codeblk\n", cputime()); 613 Bflush(&bso); 614 615 if(iself) 616 asmbelfsetup(); 617 618 sect = segtext.sect; 619 cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); 620 codeblk(sect->vaddr, sect->len); 621 for(sect = sect->next; sect != nil; sect = sect->next) { 622 cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); 623 datblk(sect->vaddr, sect->len); 624 } 625 626 if(segrodata.filelen > 0) { 627 if(debug['v']) 628 Bprint(&bso, "%5.2f rodatblk\n", cputime()); 629 Bflush(&bso); 630 631 cseek(segrodata.fileoff); 632 datblk(segrodata.vaddr, segrodata.filelen); 633 } 634 635 if(debug['v']) 636 Bprint(&bso, "%5.2f datblk\n", cputime()); 637 Bflush(&bso); 638 639 cseek(segdata.fileoff); 640 datblk(segdata.vaddr, segdata.filelen); 641 642 machlink = 0; 643 if(HEADTYPE == Hdarwin) { 644 if(debug['v']) 645 Bprint(&bso, "%5.2f dwarf\n", cputime()); 646 647 dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND); 648 cseek(dwarfoff); 649 650 segdwarf.fileoff = cpos(); 651 dwarfemitdebugsections(); 652 segdwarf.filelen = cpos() - segdwarf.fileoff; 653 654 machlink = domacholink(); 655 } 656 657 switch(HEADTYPE) { 658 default: 659 diag("unknown header type %d", HEADTYPE); 660 case Hplan9: 661 case Helf: 662 break; 663 case Hdarwin: 664 debug['8'] = 1; /* 64-bit addresses */ 665 break; 666 case Hlinux: 667 case Hfreebsd: 668 case Hnetbsd: 669 case Hopenbsd: 670 case Hdragonfly: 671 case Hsolaris: 672 debug['8'] = 1; /* 64-bit addresses */ 673 break; 674 case Hnacl: 675 case Hwindows: 676 break; 677 } 678 679 symsize = 0; 680 spsize = 0; 681 lcsize = 0; 682 symo = 0; 683 if(!debug['s']) { 684 if(debug['v']) 685 Bprint(&bso, "%5.2f sym\n", cputime()); 686 Bflush(&bso); 687 switch(HEADTYPE) { 688 default: 689 case Hplan9: 690 case Helf: 691 debug['s'] = 1; 692 symo = HEADR+segtext.len+segdata.filelen; 693 break; 694 case Hdarwin: 695 symo = rnd(HEADR+segtext.len, INITRND)+rnd(segdata.filelen, INITRND)+machlink; 696 break; 697 case Hlinux: 698 case Hfreebsd: 699 case Hnetbsd: 700 case Hopenbsd: 701 case Hdragonfly: 702 case Hsolaris: 703 case Hnacl: 704 symo = rnd(HEADR+segtext.len, INITRND)+rnd(segrodata.len, INITRND)+segdata.filelen; 705 symo = rnd(symo, INITRND); 706 break; 707 case Hwindows: 708 symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen; 709 symo = rnd(symo, PEFILEALIGN); 710 break; 711 } 712 cseek(symo); 713 switch(HEADTYPE) { 714 default: 715 if(iself) { 716 cseek(symo); 717 asmelfsym(); 718 cflush(); 719 cwrite(elfstrdat, elfstrsize); 720 721 if(debug['v']) 722 Bprint(&bso, "%5.2f dwarf\n", cputime()); 723 724 dwarfemitdebugsections(); 725 726 if(linkmode == LinkExternal) 727 elfemitreloc(); 728 } 729 break; 730 case Hplan9: 731 asmplan9sym(); 732 cflush(); 733 734 sym = linklookup(ctxt, "pclntab", 0); 735 if(sym != nil) { 736 lcsize = sym->np; 737 for(i=0; i < lcsize; i++) 738 cput(sym->p[i]); 739 740 cflush(); 741 } 742 break; 743 case Hwindows: 744 if(debug['v']) 745 Bprint(&bso, "%5.2f dwarf\n", cputime()); 746 747 dwarfemitdebugsections(); 748 break; 749 case Hdarwin: 750 if(linkmode == LinkExternal) 751 machoemitreloc(); 752 break; 753 } 754 } 755 756 if(debug['v']) 757 Bprint(&bso, "%5.2f headr\n", cputime()); 758 Bflush(&bso); 759 cseek(0L); 760 switch(HEADTYPE) { 761 default: 762 case Hplan9: /* plan9 */ 763 magic = 4*26*26+7; 764 magic |= 0x00008000; /* fat header */ 765 lputb(magic); /* magic */ 766 lputb(segtext.filelen); /* sizes */ 767 lputb(segdata.filelen); 768 lputb(segdata.len - segdata.filelen); 769 lputb(symsize); /* nsyms */ 770 vl = entryvalue(); 771 lputb(PADDR(vl)); /* va of entry */ 772 lputb(spsize); /* sp offsets */ 773 lputb(lcsize); /* line offsets */ 774 vputb(vl); /* va of entry */ 775 break; 776 case Hdarwin: 777 asmbmacho(); 778 break; 779 case Hlinux: 780 case Hfreebsd: 781 case Hnetbsd: 782 case Hopenbsd: 783 case Hdragonfly: 784 case Hsolaris: 785 case Hnacl: 786 asmbelf(symo); 787 break; 788 case Hwindows: 789 asmbpe(); 790 break; 791 } 792 cflush(); 793 } 794 795 vlong 796 rnd(vlong v, vlong r) 797 { 798 vlong c; 799 800 if(r <= 0) 801 return v; 802 v += r - 1; 803 c = v % r; 804 if(c < 0) 805 c += r; 806 v -= c; 807 return v; 808 }