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