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