github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/ld/elf.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include "l.h" 6 #include "lib.h" 7 #include "../ld/elf.h" 8 9 /* 10 * We use the 64-bit data structures on both 32- and 64-bit machines 11 * in order to write the code just once. The 64-bit data structure is 12 * written in the 32-bit format on the 32-bit machines. 13 */ 14 #define NSECT 48 15 16 int iself; 17 18 static int elf64; 19 static ElfEhdr hdr; 20 static ElfPhdr *phdr[NSECT]; 21 static ElfShdr *shdr[NSECT]; 22 static char *interp; 23 24 typedef struct Elfstring Elfstring; 25 struct Elfstring 26 { 27 char *s; 28 int off; 29 }; 30 31 static Elfstring elfstr[100]; 32 static int nelfstr; 33 34 static char buildinfo[32]; 35 36 /* 37 Initialize the global variable that describes the ELF header. It will be updated as 38 we write section and prog headers. 39 */ 40 void 41 elfinit(void) 42 { 43 iself = 1; 44 45 switch(thechar) { 46 // 64-bit architectures 47 case '6': 48 elf64 = 1; 49 hdr.phoff = ELF64HDRSIZE; /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */ 50 hdr.shoff = ELF64HDRSIZE; /* Will move as we add PHeaders */ 51 hdr.ehsize = ELF64HDRSIZE; /* Must be ELF64HDRSIZE */ 52 hdr.phentsize = ELF64PHDRSIZE; /* Must be ELF64PHDRSIZE */ 53 hdr.shentsize = ELF64SHDRSIZE; /* Must be ELF64SHDRSIZE */ 54 break; 55 56 // 32-bit architectures 57 case '5': 58 // we only use EABI on linux/arm 59 if(HEADTYPE == Hlinux) 60 hdr.flags = 0x5000002; // has entry point, Version5 EABI 61 // fallthrough 62 default: 63 hdr.phoff = ELF32HDRSIZE; /* Must be be ELF32HDRSIZE: first PHdr must follow ELF header */ 64 hdr.shoff = ELF32HDRSIZE; /* Will move as we add PHeaders */ 65 hdr.ehsize = ELF32HDRSIZE; /* Must be ELF32HDRSIZE */ 66 hdr.phentsize = ELF32PHDRSIZE; /* Must be ELF32PHDRSIZE */ 67 hdr.shentsize = ELF32SHDRSIZE; /* Must be ELF32SHDRSIZE */ 68 } 69 } 70 71 void 72 elf64phdr(ElfPhdr *e) 73 { 74 LPUT(e->type); 75 LPUT(e->flags); 76 VPUT(e->off); 77 VPUT(e->vaddr); 78 VPUT(e->paddr); 79 VPUT(e->filesz); 80 VPUT(e->memsz); 81 VPUT(e->align); 82 } 83 84 void 85 elf32phdr(ElfPhdr *e) 86 { 87 int frag; 88 89 if(e->type == PT_LOAD) { 90 // Correct ELF loaders will do this implicitly, 91 // but buggy ELF loaders like the one in some 92 // versions of QEMU won't. 93 frag = e->vaddr&(e->align-1); 94 e->off -= frag; 95 e->vaddr -= frag; 96 e->paddr -= frag; 97 e->filesz += frag; 98 e->memsz += frag; 99 } 100 LPUT(e->type); 101 LPUT(e->off); 102 LPUT(e->vaddr); 103 LPUT(e->paddr); 104 LPUT(e->filesz); 105 LPUT(e->memsz); 106 LPUT(e->flags); 107 LPUT(e->align); 108 } 109 110 void 111 elf64shdr(ElfShdr *e) 112 { 113 LPUT(e->name); 114 LPUT(e->type); 115 VPUT(e->flags); 116 VPUT(e->addr); 117 VPUT(e->off); 118 VPUT(e->size); 119 LPUT(e->link); 120 LPUT(e->info); 121 VPUT(e->addralign); 122 VPUT(e->entsize); 123 } 124 125 void 126 elf32shdr(ElfShdr *e) 127 { 128 LPUT(e->name); 129 LPUT(e->type); 130 LPUT(e->flags); 131 LPUT(e->addr); 132 LPUT(e->off); 133 LPUT(e->size); 134 LPUT(e->link); 135 LPUT(e->info); 136 LPUT(e->addralign); 137 LPUT(e->entsize); 138 } 139 140 uint32 141 elfwriteshdrs(void) 142 { 143 int i; 144 145 if (elf64) { 146 for (i = 0; i < hdr.shnum; i++) 147 elf64shdr(shdr[i]); 148 return hdr.shnum * ELF64SHDRSIZE; 149 } 150 for (i = 0; i < hdr.shnum; i++) 151 elf32shdr(shdr[i]); 152 return hdr.shnum * ELF32SHDRSIZE; 153 } 154 155 void 156 elfsetstring(char *s, int off) 157 { 158 if(nelfstr >= nelem(elfstr)) { 159 diag("too many elf strings"); 160 errorexit(); 161 } 162 elfstr[nelfstr].s = s; 163 elfstr[nelfstr].off = off; 164 nelfstr++; 165 } 166 167 uint32 168 elfwritephdrs(void) 169 { 170 int i; 171 172 if (elf64) { 173 for (i = 0; i < hdr.phnum; i++) 174 elf64phdr(phdr[i]); 175 return hdr.phnum * ELF64PHDRSIZE; 176 } 177 for (i = 0; i < hdr.phnum; i++) 178 elf32phdr(phdr[i]); 179 return hdr.phnum * ELF32PHDRSIZE; 180 } 181 182 ElfPhdr* 183 newElfPhdr(void) 184 { 185 ElfPhdr *e; 186 187 e = mal(sizeof *e); 188 if (hdr.phnum >= NSECT) 189 diag("too many phdrs"); 190 else 191 phdr[hdr.phnum++] = e; 192 if (elf64) 193 hdr.shoff += ELF64PHDRSIZE; 194 else 195 hdr.shoff += ELF32PHDRSIZE; 196 return e; 197 } 198 199 ElfShdr* 200 newElfShdr(vlong name) 201 { 202 ElfShdr *e; 203 204 e = mal(sizeof *e); 205 e->name = name; 206 e->shnum = hdr.shnum; 207 if (hdr.shnum >= NSECT) { 208 diag("too many shdrs"); 209 } else { 210 shdr[hdr.shnum++] = e; 211 } 212 return e; 213 } 214 215 ElfEhdr* 216 getElfEhdr(void) 217 { 218 return &hdr; 219 } 220 221 uint32 222 elf64writehdr(void) 223 { 224 int i; 225 226 for (i = 0; i < EI_NIDENT; i++) 227 cput(hdr.ident[i]); 228 WPUT(hdr.type); 229 WPUT(hdr.machine); 230 LPUT(hdr.version); 231 VPUT(hdr.entry); 232 VPUT(hdr.phoff); 233 VPUT(hdr.shoff); 234 LPUT(hdr.flags); 235 WPUT(hdr.ehsize); 236 WPUT(hdr.phentsize); 237 WPUT(hdr.phnum); 238 WPUT(hdr.shentsize); 239 WPUT(hdr.shnum); 240 WPUT(hdr.shstrndx); 241 return ELF64HDRSIZE; 242 } 243 244 uint32 245 elf32writehdr(void) 246 { 247 int i; 248 249 for (i = 0; i < EI_NIDENT; i++) 250 cput(hdr.ident[i]); 251 WPUT(hdr.type); 252 WPUT(hdr.machine); 253 LPUT(hdr.version); 254 LPUT(hdr.entry); 255 LPUT(hdr.phoff); 256 LPUT(hdr.shoff); 257 LPUT(hdr.flags); 258 WPUT(hdr.ehsize); 259 WPUT(hdr.phentsize); 260 WPUT(hdr.phnum); 261 WPUT(hdr.shentsize); 262 WPUT(hdr.shnum); 263 WPUT(hdr.shstrndx); 264 return ELF32HDRSIZE; 265 } 266 267 uint32 268 elfwritehdr(void) 269 { 270 if(elf64) 271 return elf64writehdr(); 272 return elf32writehdr(); 273 } 274 275 /* Taken directly from the definition document for ELF64 */ 276 uint32 277 elfhash(uchar *name) 278 { 279 uint32 h = 0, g; 280 while (*name) { 281 h = (h << 4) + *name++; 282 if (g = h & 0xf0000000) 283 h ^= g >> 24; 284 h &= 0x0fffffff; 285 } 286 return h; 287 } 288 289 void 290 elfwritedynent(Sym *s, int tag, uint64 val) 291 { 292 if(elf64) { 293 adduint64(s, tag); 294 adduint64(s, val); 295 } else { 296 adduint32(s, tag); 297 adduint32(s, val); 298 } 299 } 300 301 void 302 elfwritedynentsym(Sym *s, int tag, Sym *t) 303 { 304 if(elf64) 305 adduint64(s, tag); 306 else 307 adduint32(s, tag); 308 addaddr(s, t); 309 } 310 311 void 312 elfwritedynentsymsize(Sym *s, int tag, Sym *t) 313 { 314 if(elf64) 315 adduint64(s, tag); 316 else 317 adduint32(s, tag); 318 addsize(s, t); 319 } 320 321 int 322 elfinterp(ElfShdr *sh, uint64 startva, uint64 resoff, char *p) 323 { 324 int n; 325 326 interp = p; 327 n = strlen(interp)+1; 328 sh->addr = startva + resoff - n; 329 sh->off = resoff - n; 330 sh->size = n; 331 332 return n; 333 } 334 335 int 336 elfwriteinterp(void) 337 { 338 ElfShdr *sh; 339 340 sh = elfshname(".interp"); 341 cseek(sh->off); 342 cwrite(interp, sh->size); 343 return sh->size; 344 } 345 346 int 347 elfnote(ElfShdr *sh, uint64 startva, uint64 resoff, int sz) 348 { 349 uint64 n; 350 351 n = sizeof(Elf_Note) + sz + resoff % 4; 352 353 sh->type = SHT_NOTE; 354 sh->flags = SHF_ALLOC; 355 sh->addralign = 4; 356 sh->addr = startva + resoff - n; 357 sh->off = resoff - n; 358 sh->size = n; 359 360 return n; 361 } 362 363 ElfShdr * 364 elfwritenotehdr(char *str, uint32 namesz, uint32 descsz, uint32 tag) 365 { 366 ElfShdr *sh; 367 368 sh = elfshname(str); 369 370 // Write Elf_Note header. 371 cseek(sh->off); 372 LPUT(namesz); 373 LPUT(descsz); 374 LPUT(tag); 375 376 return sh; 377 } 378 379 // NetBSD Signature (as per sys/exec_elf.h) 380 #define ELF_NOTE_NETBSD_NAMESZ 7 381 #define ELF_NOTE_NETBSD_DESCSZ 4 382 #define ELF_NOTE_NETBSD_TAG 1 383 #define ELF_NOTE_NETBSD_NAME "NetBSD\0\0" 384 #define ELF_NOTE_NETBSD_VERSION 599000000 /* NetBSD 5.99 */ 385 386 int 387 elfnetbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff) 388 { 389 int n; 390 391 n = ELF_NOTE_NETBSD_NAMESZ + ELF_NOTE_NETBSD_DESCSZ + 1; 392 return elfnote(sh, startva, resoff, n); 393 } 394 395 int 396 elfwritenetbsdsig(void) 397 { 398 ElfShdr *sh; 399 400 // Write Elf_Note header. 401 sh = elfwritenotehdr(".note.netbsd.ident", ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG); 402 if(sh == nil) 403 return 0; 404 405 // Followed by NetBSD string and version. 406 cwrite(ELF_NOTE_NETBSD_NAME, ELF_NOTE_NETBSD_NAMESZ + 1); 407 LPUT(ELF_NOTE_NETBSD_VERSION); 408 409 return sh->size; 410 } 411 412 // OpenBSD Signature 413 #define ELF_NOTE_OPENBSD_NAMESZ 8 414 #define ELF_NOTE_OPENBSD_DESCSZ 4 415 #define ELF_NOTE_OPENBSD_TAG 1 416 #define ELF_NOTE_OPENBSD_NAME "OpenBSD\0" 417 #define ELF_NOTE_OPENBSD_VERSION 0 418 419 int 420 elfopenbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff) 421 { 422 int n; 423 424 n = ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ; 425 return elfnote(sh, startva, resoff, n); 426 } 427 428 int 429 elfwriteopenbsdsig(void) 430 { 431 ElfShdr *sh; 432 433 // Write Elf_Note header. 434 sh = elfwritenotehdr(".note.openbsd.ident", ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG); 435 if(sh == nil) 436 return 0; 437 438 // Followed by OpenBSD string and version. 439 cwrite(ELF_NOTE_OPENBSD_NAME, ELF_NOTE_OPENBSD_NAMESZ); 440 LPUT(ELF_NOTE_OPENBSD_VERSION); 441 442 return sh->size; 443 } 444 445 void 446 addbuildinfo(char *val) 447 { 448 char *ov; 449 int i, b, j; 450 451 if(val[0] != '0' || val[1] != 'x') { 452 fprint(2, "%s: -B argument must start with 0x: %s\n", argv0, val); 453 exits("usage"); 454 } 455 ov = val; 456 val += 2; 457 i = 0; 458 while(*val != '\0') { 459 if(val[1] == '\0') { 460 fprint(2, "%s: -B argument must have even number of digits: %s\n", argv0, ov); 461 exits("usage"); 462 } 463 b = 0; 464 for(j = 0; j < 2; j++, val++) { 465 b *= 16; 466 if(*val >= '0' && *val <= '9') 467 b += *val - '0'; 468 else if(*val >= 'a' && *val <= 'f') 469 b += *val - 'a' + 10; 470 else if(*val >= 'A' && *val <= 'F') 471 b += *val - 'A' + 10; 472 else { 473 fprint(2, "%s: -B argument contains invalid hex digit %c: %s\n", argv0, *val, ov); 474 exits("usage"); 475 } 476 } 477 if(i >= nelem(buildinfo)) { 478 fprint(2, "%s: -B option too long (max %d digits): %s\n", argv0, (int)nelem(buildinfo), ov); 479 exits("usage"); 480 } 481 buildinfo[i++] = b; 482 } 483 buildinfolen = i; 484 } 485 486 // Build info note 487 #define ELF_NOTE_BUILDINFO_NAMESZ 4 488 #define ELF_NOTE_BUILDINFO_TAG 3 489 #define ELF_NOTE_BUILDINFO_NAME "GNU\0" 490 491 int 492 elfbuildinfo(ElfShdr *sh, uint64 startva, uint64 resoff) 493 { 494 int n; 495 496 n = ELF_NOTE_BUILDINFO_NAMESZ + rnd(buildinfolen, 4); 497 return elfnote(sh, startva, resoff, n); 498 } 499 500 int 501 elfwritebuildinfo(void) 502 { 503 ElfShdr *sh; 504 505 sh = elfwritenotehdr(".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, buildinfolen, ELF_NOTE_BUILDINFO_TAG); 506 if(sh == nil) 507 return 0; 508 509 cwrite(ELF_NOTE_BUILDINFO_NAME, ELF_NOTE_BUILDINFO_NAMESZ); 510 cwrite(buildinfo, buildinfolen); 511 cwrite("\0\0\0", rnd(buildinfolen, 4) - buildinfolen); 512 513 return sh->size; 514 } 515 516 extern int nelfsym; 517 int elfverneed; 518 519 typedef struct Elfaux Elfaux; 520 typedef struct Elflib Elflib; 521 522 struct Elflib 523 { 524 Elflib *next; 525 Elfaux *aux; 526 char *file; 527 }; 528 529 struct Elfaux 530 { 531 Elfaux *next; 532 int num; 533 char *vers; 534 }; 535 536 Elfaux* 537 addelflib(Elflib **list, char *file, char *vers) 538 { 539 Elflib *lib; 540 Elfaux *aux; 541 542 for(lib=*list; lib; lib=lib->next) 543 if(strcmp(lib->file, file) == 0) 544 goto havelib; 545 lib = mal(sizeof *lib); 546 lib->next = *list; 547 lib->file = file; 548 *list = lib; 549 havelib: 550 for(aux=lib->aux; aux; aux=aux->next) 551 if(strcmp(aux->vers, vers) == 0) 552 goto haveaux; 553 aux = mal(sizeof *aux); 554 aux->next = lib->aux; 555 aux->vers = vers; 556 lib->aux = aux; 557 haveaux: 558 return aux; 559 } 560 561 void 562 elfdynhash(void) 563 { 564 Sym *s, *sy, *dynstr; 565 int i, j, nbucket, b, nfile; 566 uint32 hc, *chain, *buckets; 567 int nsym; 568 char *name; 569 Elfaux **need; 570 Elflib *needlib; 571 Elflib *l; 572 Elfaux *x; 573 574 if(!iself) 575 return; 576 577 nsym = nelfsym; 578 s = lookup(".hash", 0); 579 s->type = SELFROSECT; 580 s->reachable = 1; 581 582 i = nsym; 583 nbucket = 1; 584 while(i > 0) { 585 ++nbucket; 586 i >>= 1; 587 } 588 589 needlib = nil; 590 need = malloc(nsym * sizeof need[0]); 591 chain = malloc(nsym * sizeof chain[0]); 592 buckets = malloc(nbucket * sizeof buckets[0]); 593 if(need == nil || chain == nil || buckets == nil) { 594 cursym = nil; 595 diag("out of memory"); 596 errorexit(); 597 } 598 memset(need, 0, nsym * sizeof need[0]); 599 memset(chain, 0, nsym * sizeof chain[0]); 600 memset(buckets, 0, nbucket * sizeof buckets[0]); 601 for(sy=allsym; sy!=S; sy=sy->allsym) { 602 if (sy->dynid <= 0) 603 continue; 604 605 if(sy->dynimpvers) 606 need[sy->dynid] = addelflib(&needlib, sy->dynimplib, sy->dynimpvers); 607 608 name = sy->extname; 609 hc = elfhash((uchar*)name); 610 611 b = hc % nbucket; 612 chain[sy->dynid] = buckets[b]; 613 buckets[b] = sy->dynid; 614 } 615 616 adduint32(s, nbucket); 617 adduint32(s, nsym); 618 for(i = 0; i<nbucket; i++) 619 adduint32(s, buckets[i]); 620 for(i = 0; i<nsym; i++) 621 adduint32(s, chain[i]); 622 623 free(chain); 624 free(buckets); 625 626 // version symbols 627 dynstr = lookup(".dynstr", 0); 628 s = lookup(".gnu.version_r", 0); 629 i = 2; 630 nfile = 0; 631 for(l=needlib; l; l=l->next) { 632 nfile++; 633 // header 634 adduint16(s, 1); // table version 635 j = 0; 636 for(x=l->aux; x; x=x->next) 637 j++; 638 adduint16(s, j); // aux count 639 adduint32(s, addstring(dynstr, l->file)); // file string offset 640 adduint32(s, 16); // offset from header to first aux 641 if(l->next) 642 adduint32(s, 16+j*16); // offset from this header to next 643 else 644 adduint32(s, 0); 645 646 for(x=l->aux; x; x=x->next) { 647 x->num = i++; 648 // aux struct 649 adduint32(s, elfhash((uchar*)x->vers)); // hash 650 adduint16(s, 0); // flags 651 adduint16(s, x->num); // other - index we refer to this by 652 adduint32(s, addstring(dynstr, x->vers)); // version string offset 653 if(x->next) 654 adduint32(s, 16); // offset from this aux to next 655 else 656 adduint32(s, 0); 657 } 658 } 659 660 // version references 661 s = lookup(".gnu.version", 0); 662 for(i=0; i<nsym; i++) { 663 if(i == 0) 664 adduint16(s, 0); // first entry - no symbol 665 else if(need[i] == nil) 666 adduint16(s, 1); // global 667 else 668 adduint16(s, need[i]->num); 669 } 670 671 free(need); 672 673 s = lookup(".dynamic", 0); 674 elfverneed = nfile; 675 if(elfverneed) { 676 elfwritedynentsym(s, DT_VERNEED, lookup(".gnu.version_r", 0)); 677 elfwritedynent(s, DT_VERNEEDNUM, nfile); 678 elfwritedynentsym(s, DT_VERSYM, lookup(".gnu.version", 0)); 679 } 680 elfwritedynent(s, DT_NULL, 0); 681 } 682 683 ElfPhdr* 684 elfphload(Segment *seg) 685 { 686 ElfPhdr *ph; 687 688 ph = newElfPhdr(); 689 ph->type = PT_LOAD; 690 if(seg->rwx & 4) 691 ph->flags |= PF_R; 692 if(seg->rwx & 2) 693 ph->flags |= PF_W; 694 if(seg->rwx & 1) 695 ph->flags |= PF_X; 696 ph->vaddr = seg->vaddr; 697 ph->paddr = seg->vaddr; 698 ph->memsz = seg->len; 699 ph->off = seg->fileoff; 700 ph->filesz = seg->filelen; 701 ph->align = INITRND; 702 703 return ph; 704 } 705 706 ElfShdr* 707 elfshname(char *name) 708 { 709 int i, off; 710 ElfShdr *sh; 711 712 for(i=0; i<nelfstr; i++) { 713 if(strcmp(name, elfstr[i].s) == 0) { 714 off = elfstr[i].off; 715 goto found; 716 } 717 } 718 diag("cannot find elf name %s", name); 719 errorexit(); 720 return nil; 721 722 found: 723 for(i=0; i<hdr.shnum; i++) { 724 sh = shdr[i]; 725 if(sh->name == off) 726 return sh; 727 } 728 729 sh = newElfShdr(off); 730 return sh; 731 } 732 733 ElfShdr* 734 elfshalloc(Section *sect) 735 { 736 ElfShdr *sh; 737 738 sh = elfshname(sect->name); 739 sect->elfsect = sh; 740 return sh; 741 } 742 743 ElfShdr* 744 elfshbits(Section *sect) 745 { 746 ElfShdr *sh; 747 748 sh = elfshalloc(sect); 749 if(sh->type > 0) 750 return sh; 751 752 if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen) 753 sh->type = SHT_PROGBITS; 754 else 755 sh->type = SHT_NOBITS; 756 sh->flags = SHF_ALLOC; 757 if(sect->rwx & 1) 758 sh->flags |= SHF_EXECINSTR; 759 if(sect->rwx & 2) 760 sh->flags |= SHF_WRITE; 761 if(strcmp(sect->name, ".tbss") == 0) { 762 sh->flags |= SHF_TLS; 763 sh->type = SHT_NOBITS; 764 } 765 if(linkmode != LinkExternal) 766 sh->addr = sect->vaddr; 767 sh->addralign = sect->align; 768 sh->size = sect->len; 769 sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr; 770 771 return sh; 772 } 773 774 ElfShdr* 775 elfshreloc(Section *sect) 776 { 777 int typ; 778 ElfShdr *sh; 779 char *prefix; 780 char buf[100]; 781 782 // If main section is SHT_NOBITS, nothing to relocate. 783 // Also nothing to relocate in .shstrtab. 784 if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen) 785 return nil; 786 if(strcmp(sect->name, ".shstrtab") == 0 || strcmp(sect->name, ".tbss") == 0) 787 return nil; 788 789 if(thechar == '6') { 790 prefix = ".rela"; 791 typ = SHT_RELA; 792 } else { 793 prefix = ".rel"; 794 typ = SHT_REL; 795 } 796 797 snprint(buf, sizeof buf, "%s%s", prefix, sect->name); 798 sh = elfshname(buf); 799 sh->type = typ; 800 sh->entsize = PtrSize*(2+(typ==SHT_RELA)); 801 sh->link = elfshname(".symtab")->shnum; 802 sh->info = sect->elfsect->shnum; 803 sh->off = sect->reloff; 804 sh->size = sect->rellen; 805 sh->addralign = PtrSize; 806 return sh; 807 } 808 809 void 810 elfrelocsect(Section *sect, Sym *first) 811 { 812 Sym *sym; 813 int32 eaddr; 814 Reloc *r; 815 816 // If main section is SHT_NOBITS, nothing to relocate. 817 // Also nothing to relocate in .shstrtab. 818 if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen) 819 return; 820 if(strcmp(sect->name, ".shstrtab") == 0) 821 return; 822 823 sect->reloff = cpos(); 824 for(sym = first; sym != nil; sym = sym->next) { 825 if(!sym->reachable) 826 continue; 827 if(sym->value >= sect->vaddr) 828 break; 829 } 830 831 eaddr = sect->vaddr + sect->len; 832 for(; sym != nil; sym = sym->next) { 833 if(!sym->reachable) 834 continue; 835 if(sym->value >= eaddr) 836 break; 837 cursym = sym; 838 839 for(r = sym->r; r < sym->r+sym->nr; r++) { 840 if(r->done) 841 continue; 842 if(r->xsym == nil) { 843 diag("missing xsym in relocation"); 844 continue; 845 } 846 if(r->xsym->elfsym == 0) 847 diag("reloc %d to non-elf symbol %s (outer=%s) %d", r->type, r->sym->name, r->xsym->name, r->sym->type); 848 if(elfreloc1(r, sym->value+r->off - sect->vaddr) < 0) 849 diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name); 850 } 851 } 852 853 sect->rellen = cpos() - sect->reloff; 854 } 855 856 void 857 elfemitreloc(void) 858 { 859 Section *sect; 860 861 while(cpos()&7) 862 cput(0); 863 864 elfrelocsect(segtext.sect, textp); 865 for(sect=segtext.sect->next; sect!=nil; sect=sect->next) 866 elfrelocsect(sect, datap); 867 for(sect=segrodata.sect; sect!=nil; sect=sect->next) 868 elfrelocsect(sect, datap); 869 for(sect=segdata.sect; sect!=nil; sect=sect->next) 870 elfrelocsect(sect, datap); 871 } 872 873 void 874 doelf(void) 875 { 876 Sym *s, *shstrtab, *dynstr; 877 878 if(!iself) 879 return; 880 881 /* predefine strings we need for section headers */ 882 shstrtab = lookup(".shstrtab", 0); 883 shstrtab->type = SELFROSECT; 884 shstrtab->reachable = 1; 885 886 addstring(shstrtab, ""); 887 addstring(shstrtab, ".text"); 888 addstring(shstrtab, ".noptrdata"); 889 addstring(shstrtab, ".data"); 890 addstring(shstrtab, ".bss"); 891 addstring(shstrtab, ".noptrbss"); 892 // generate .tbss section (except for OpenBSD where it's not supported) 893 // for dynamic internal linker or external linking, so that various 894 // binutils could correctly calculate PT_TLS size. 895 // see http://golang.org/issue/5200. 896 if(HEADTYPE != Hopenbsd) 897 if(!debug['d'] || linkmode == LinkExternal) 898 addstring(shstrtab, ".tbss"); 899 if(HEADTYPE == Hnetbsd) 900 addstring(shstrtab, ".note.netbsd.ident"); 901 if(HEADTYPE == Hopenbsd) 902 addstring(shstrtab, ".note.openbsd.ident"); 903 if(buildinfolen > 0) 904 addstring(shstrtab, ".note.gnu.build-id"); 905 addstring(shstrtab, ".elfdata"); 906 addstring(shstrtab, ".rodata"); 907 addstring(shstrtab, ".typelink"); 908 addstring(shstrtab, ".gosymtab"); 909 addstring(shstrtab, ".gopclntab"); 910 911 if(linkmode == LinkExternal) { 912 debug_s = debug['s']; 913 debug['s'] = 0; 914 debug['d'] = 1; 915 916 if(thechar == '6') { 917 addstring(shstrtab, ".rela.text"); 918 addstring(shstrtab, ".rela.rodata"); 919 addstring(shstrtab, ".rela.typelink"); 920 addstring(shstrtab, ".rela.gosymtab"); 921 addstring(shstrtab, ".rela.gopclntab"); 922 addstring(shstrtab, ".rela.noptrdata"); 923 addstring(shstrtab, ".rela.data"); 924 } else { 925 addstring(shstrtab, ".rel.text"); 926 addstring(shstrtab, ".rel.rodata"); 927 addstring(shstrtab, ".rel.typelink"); 928 addstring(shstrtab, ".rel.gosymtab"); 929 addstring(shstrtab, ".rel.gopclntab"); 930 addstring(shstrtab, ".rel.noptrdata"); 931 addstring(shstrtab, ".rel.data"); 932 } 933 // add a .note.GNU-stack section to mark the stack as non-executable 934 addstring(shstrtab, ".note.GNU-stack"); 935 } 936 937 if(flag_shared) { 938 addstring(shstrtab, ".init_array"); 939 if(thechar == '6') 940 addstring(shstrtab, ".rela.init_array"); 941 else 942 addstring(shstrtab, ".rel.init_array"); 943 } 944 945 if(!debug['s']) { 946 addstring(shstrtab, ".symtab"); 947 addstring(shstrtab, ".strtab"); 948 dwarfaddshstrings(shstrtab); 949 } 950 addstring(shstrtab, ".shstrtab"); 951 952 if(!debug['d']) { /* -d suppresses dynamic loader format */ 953 addstring(shstrtab, ".interp"); 954 addstring(shstrtab, ".hash"); 955 addstring(shstrtab, ".got"); 956 addstring(shstrtab, ".got.plt"); 957 addstring(shstrtab, ".dynamic"); 958 addstring(shstrtab, ".dynsym"); 959 addstring(shstrtab, ".dynstr"); 960 if(thechar == '6') { 961 addstring(shstrtab, ".rela"); 962 addstring(shstrtab, ".rela.plt"); 963 } else { 964 addstring(shstrtab, ".rel"); 965 addstring(shstrtab, ".rel.plt"); 966 } 967 addstring(shstrtab, ".plt"); 968 addstring(shstrtab, ".gnu.version"); 969 addstring(shstrtab, ".gnu.version_r"); 970 971 /* dynamic symbol table - first entry all zeros */ 972 s = lookup(".dynsym", 0); 973 s->type = SELFROSECT; 974 s->reachable = 1; 975 if(thechar == '6') 976 s->size += ELF64SYMSIZE; 977 else 978 s->size += ELF32SYMSIZE; 979 980 /* dynamic string table */ 981 s = lookup(".dynstr", 0); 982 s->type = SELFROSECT; 983 s->reachable = 1; 984 if(s->size == 0) 985 addstring(s, ""); 986 dynstr = s; 987 988 /* relocation table */ 989 if(thechar == '6') 990 s = lookup(".rela", 0); 991 else 992 s = lookup(".rel", 0); 993 s->reachable = 1; 994 s->type = SELFROSECT; 995 996 /* global offset table */ 997 s = lookup(".got", 0); 998 s->reachable = 1; 999 s->type = SELFSECT; // writable 1000 1001 /* hash */ 1002 s = lookup(".hash", 0); 1003 s->reachable = 1; 1004 s->type = SELFROSECT; 1005 1006 s = lookup(".got.plt", 0); 1007 s->reachable = 1; 1008 s->type = SELFSECT; // writable 1009 1010 s = lookup(".plt", 0); 1011 s->reachable = 1; 1012 s->type = SELFRXSECT; 1013 1014 elfsetupplt(); 1015 1016 if(thechar == '6') 1017 s = lookup(".rela.plt", 0); 1018 else 1019 s = lookup(".rel.plt", 0); 1020 s->reachable = 1; 1021 s->type = SELFROSECT; 1022 1023 s = lookup(".gnu.version", 0); 1024 s->reachable = 1; 1025 s->type = SELFROSECT; 1026 1027 s = lookup(".gnu.version_r", 0); 1028 s->reachable = 1; 1029 s->type = SELFROSECT; 1030 1031 /* define dynamic elf table */ 1032 s = lookup(".dynamic", 0); 1033 s->reachable = 1; 1034 s->type = SELFSECT; // writable 1035 1036 /* 1037 * .dynamic table 1038 */ 1039 elfwritedynentsym(s, DT_HASH, lookup(".hash", 0)); 1040 elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0)); 1041 if(thechar == '6') 1042 elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE); 1043 else 1044 elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE); 1045 elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0)); 1046 elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0)); 1047 if(thechar == '6') { 1048 elfwritedynentsym(s, DT_RELA, lookup(".rela", 0)); 1049 elfwritedynentsymsize(s, DT_RELASZ, lookup(".rela", 0)); 1050 elfwritedynent(s, DT_RELAENT, ELF64RELASIZE); 1051 } else { 1052 elfwritedynentsym(s, DT_REL, lookup(".rel", 0)); 1053 elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0)); 1054 elfwritedynent(s, DT_RELENT, ELF32RELSIZE); 1055 } 1056 if(rpath) 1057 elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath)); 1058 1059 elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0)); 1060 1061 if(thechar == '6') { 1062 elfwritedynent(s, DT_PLTREL, DT_RELA); 1063 elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0)); 1064 elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0)); 1065 } else { 1066 elfwritedynent(s, DT_PLTREL, DT_REL); 1067 elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0)); 1068 elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0)); 1069 } 1070 1071 elfwritedynent(s, DT_DEBUG, 0); 1072 1073 // Do not write DT_NULL. elfdynhash will finish it. 1074 } 1075 } 1076 1077 void 1078 shsym(ElfShdr *sh, Sym *s) 1079 { 1080 vlong addr; 1081 addr = symaddr(s); 1082 if(sh->flags&SHF_ALLOC) 1083 sh->addr = addr; 1084 sh->off = datoff(addr); 1085 sh->size = s->size; 1086 } 1087 1088 void 1089 phsh(ElfPhdr *ph, ElfShdr *sh) 1090 { 1091 ph->vaddr = sh->addr; 1092 ph->paddr = ph->vaddr; 1093 ph->off = sh->off; 1094 ph->filesz = sh->size; 1095 ph->memsz = sh->size; 1096 ph->align = sh->addralign; 1097 } 1098 1099 void 1100 asmbelfsetup(void) 1101 { 1102 Section *sect; 1103 1104 /* This null SHdr must appear before all others */ 1105 elfshname(""); 1106 1107 for(sect=segtext.sect; sect!=nil; sect=sect->next) 1108 elfshalloc(sect); 1109 for(sect=segrodata.sect; sect!=nil; sect=sect->next) 1110 elfshalloc(sect); 1111 for(sect=segdata.sect; sect!=nil; sect=sect->next) 1112 elfshalloc(sect); 1113 } 1114 1115 void 1116 asmbelf(vlong symo) 1117 { 1118 vlong a, o; 1119 vlong startva, resoff; 1120 ElfEhdr *eh; 1121 ElfPhdr *ph, *pph, *pnote; 1122 ElfShdr *sh; 1123 Section *sect; 1124 1125 eh = getElfEhdr(); 1126 switch(thechar) { 1127 default: 1128 diag("unknown architecture in asmbelf"); 1129 errorexit(); 1130 case '5': 1131 eh->machine = EM_ARM; 1132 break; 1133 case '6': 1134 eh->machine = EM_X86_64; 1135 break; 1136 case '8': 1137 eh->machine = EM_386; 1138 break; 1139 } 1140 1141 startva = INITTEXT - HEADR; 1142 resoff = ELFRESERVE; 1143 1144 pph = nil; 1145 if(linkmode == LinkExternal) { 1146 /* skip program headers */ 1147 eh->phoff = 0; 1148 eh->phentsize = 0; 1149 goto elfobj; 1150 } 1151 1152 /* program header info */ 1153 pph = newElfPhdr(); 1154 pph->type = PT_PHDR; 1155 pph->flags = PF_R + PF_X; 1156 pph->off = eh->ehsize; 1157 pph->vaddr = INITTEXT - HEADR + pph->off; 1158 pph->paddr = INITTEXT - HEADR + pph->off; 1159 pph->align = INITRND; 1160 1161 /* 1162 * PHDR must be in a loaded segment. Adjust the text 1163 * segment boundaries downwards to include it. 1164 */ 1165 o = segtext.vaddr - pph->vaddr; 1166 segtext.vaddr -= o; 1167 segtext.len += o; 1168 o = segtext.fileoff - pph->off; 1169 segtext.fileoff -= o; 1170 segtext.filelen += o; 1171 1172 if(!debug['d']) { 1173 /* interpreter */ 1174 sh = elfshname(".interp"); 1175 sh->type = SHT_PROGBITS; 1176 sh->flags = SHF_ALLOC; 1177 sh->addralign = 1; 1178 if(interpreter == nil) { 1179 switch(HEADTYPE) { 1180 case Hlinux: 1181 interpreter = linuxdynld; 1182 break; 1183 case Hfreebsd: 1184 interpreter = freebsddynld; 1185 break; 1186 case Hnetbsd: 1187 interpreter = netbsddynld; 1188 break; 1189 case Hopenbsd: 1190 interpreter = openbsddynld; 1191 break; 1192 case Hdragonfly: 1193 interpreter = dragonflydynld; 1194 break; 1195 } 1196 } 1197 resoff -= elfinterp(sh, startva, resoff, interpreter); 1198 1199 ph = newElfPhdr(); 1200 ph->type = PT_INTERP; 1201 ph->flags = PF_R; 1202 phsh(ph, sh); 1203 } 1204 1205 pnote = nil; 1206 if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) { 1207 sh = nil; 1208 switch(HEADTYPE) { 1209 case Hnetbsd: 1210 sh = elfshname(".note.netbsd.ident"); 1211 resoff -= elfnetbsdsig(sh, startva, resoff); 1212 break; 1213 case Hopenbsd: 1214 sh = elfshname(".note.openbsd.ident"); 1215 resoff -= elfopenbsdsig(sh, startva, resoff); 1216 break; 1217 } 1218 1219 pnote = newElfPhdr(); 1220 pnote->type = PT_NOTE; 1221 pnote->flags = PF_R; 1222 phsh(pnote, sh); 1223 } 1224 1225 if(buildinfolen > 0) { 1226 sh = elfshname(".note.gnu.build-id"); 1227 resoff -= elfbuildinfo(sh, startva, resoff); 1228 1229 if(pnote == nil) { 1230 pnote = newElfPhdr(); 1231 pnote->type = PT_NOTE; 1232 pnote->flags = PF_R; 1233 } 1234 phsh(pnote, sh); 1235 } 1236 1237 // Additions to the reserved area must be above this line. 1238 USED(resoff); 1239 1240 elfphload(&segtext); 1241 if(segrodata.sect != nil) 1242 elfphload(&segrodata); 1243 elfphload(&segdata); 1244 1245 /* Dynamic linking sections */ 1246 if(!debug['d']) { /* -d suppresses dynamic loader format */ 1247 sh = elfshname(".dynsym"); 1248 sh->type = SHT_DYNSYM; 1249 sh->flags = SHF_ALLOC; 1250 if(PtrSize == 8) 1251 sh->entsize = ELF64SYMSIZE; 1252 else 1253 sh->entsize = ELF32SYMSIZE; 1254 sh->addralign = PtrSize; 1255 sh->link = elfshname(".dynstr")->shnum; 1256 // sh->info = index of first non-local symbol (number of local symbols) 1257 shsym(sh, lookup(".dynsym", 0)); 1258 1259 sh = elfshname(".dynstr"); 1260 sh->type = SHT_STRTAB; 1261 sh->flags = SHF_ALLOC; 1262 sh->addralign = 1; 1263 shsym(sh, lookup(".dynstr", 0)); 1264 1265 if(elfverneed) { 1266 sh = elfshname(".gnu.version"); 1267 sh->type = SHT_GNU_VERSYM; 1268 sh->flags = SHF_ALLOC; 1269 sh->addralign = 2; 1270 sh->link = elfshname(".dynsym")->shnum; 1271 sh->entsize = 2; 1272 shsym(sh, lookup(".gnu.version", 0)); 1273 1274 sh = elfshname(".gnu.version_r"); 1275 sh->type = SHT_GNU_VERNEED; 1276 sh->flags = SHF_ALLOC; 1277 sh->addralign = PtrSize; 1278 sh->info = elfverneed; 1279 sh->link = elfshname(".dynstr")->shnum; 1280 shsym(sh, lookup(".gnu.version_r", 0)); 1281 } 1282 1283 switch(eh->machine) { 1284 case EM_X86_64: 1285 sh = elfshname(".rela.plt"); 1286 sh->type = SHT_RELA; 1287 sh->flags = SHF_ALLOC; 1288 sh->entsize = ELF64RELASIZE; 1289 sh->addralign = PtrSize; 1290 sh->link = elfshname(".dynsym")->shnum; 1291 sh->info = elfshname(".plt")->shnum; 1292 shsym(sh, lookup(".rela.plt", 0)); 1293 1294 sh = elfshname(".rela"); 1295 sh->type = SHT_RELA; 1296 sh->flags = SHF_ALLOC; 1297 sh->entsize = ELF64RELASIZE; 1298 sh->addralign = 8; 1299 sh->link = elfshname(".dynsym")->shnum; 1300 shsym(sh, lookup(".rela", 0)); 1301 break; 1302 1303 default: 1304 sh = elfshname(".rel.plt"); 1305 sh->type = SHT_REL; 1306 sh->flags = SHF_ALLOC; 1307 sh->entsize = ELF32RELSIZE; 1308 sh->link = elfshname(".dynsym")->shnum; 1309 shsym(sh, lookup(".rel.plt", 0)); 1310 1311 sh = elfshname(".rel"); 1312 sh->type = SHT_REL; 1313 sh->flags = SHF_ALLOC; 1314 sh->entsize = ELF32RELSIZE; 1315 sh->addralign = 4; 1316 sh->link = elfshname(".dynsym")->shnum; 1317 shsym(sh, lookup(".rel", 0)); 1318 break; 1319 } 1320 1321 sh = elfshname(".plt"); 1322 sh->type = SHT_PROGBITS; 1323 sh->flags = SHF_ALLOC+SHF_EXECINSTR; 1324 if(eh->machine == EM_X86_64) 1325 sh->entsize = 16; 1326 else 1327 sh->entsize = 4; 1328 sh->addralign = 4; 1329 shsym(sh, lookup(".plt", 0)); 1330 1331 sh = elfshname(".got"); 1332 sh->type = SHT_PROGBITS; 1333 sh->flags = SHF_ALLOC+SHF_WRITE; 1334 sh->entsize = PtrSize; 1335 sh->addralign = PtrSize; 1336 shsym(sh, lookup(".got", 0)); 1337 1338 sh = elfshname(".got.plt"); 1339 sh->type = SHT_PROGBITS; 1340 sh->flags = SHF_ALLOC+SHF_WRITE; 1341 sh->entsize = PtrSize; 1342 sh->addralign = PtrSize; 1343 shsym(sh, lookup(".got.plt", 0)); 1344 1345 sh = elfshname(".hash"); 1346 sh->type = SHT_HASH; 1347 sh->flags = SHF_ALLOC; 1348 sh->entsize = 4; 1349 sh->addralign = PtrSize; 1350 sh->link = elfshname(".dynsym")->shnum; 1351 shsym(sh, lookup(".hash", 0)); 1352 1353 /* sh and PT_DYNAMIC for .dynamic section */ 1354 sh = elfshname(".dynamic"); 1355 sh->type = SHT_DYNAMIC; 1356 sh->flags = SHF_ALLOC+SHF_WRITE; 1357 sh->entsize = 2*PtrSize; 1358 sh->addralign = PtrSize; 1359 sh->link = elfshname(".dynstr")->shnum; 1360 shsym(sh, lookup(".dynamic", 0)); 1361 ph = newElfPhdr(); 1362 ph->type = PT_DYNAMIC; 1363 ph->flags = PF_R + PF_W; 1364 phsh(ph, sh); 1365 1366 /* 1367 * Thread-local storage segment (really just size). 1368 */ 1369 // Do not emit PT_TLS for OpenBSD since ld.so(1) does 1370 // not currently support it. This is handled 1371 // appropriately in runtime/cgo. 1372 if(tlsoffset != 0 && HEADTYPE != Hopenbsd) { 1373 ph = newElfPhdr(); 1374 ph->type = PT_TLS; 1375 ph->flags = PF_R; 1376 ph->memsz = -tlsoffset; 1377 ph->align = PtrSize; 1378 } 1379 } 1380 1381 if(HEADTYPE == Hlinux) { 1382 ph = newElfPhdr(); 1383 ph->type = PT_GNU_STACK; 1384 ph->flags = PF_W+PF_R; 1385 ph->align = PtrSize; 1386 1387 ph = newElfPhdr(); 1388 ph->type = PT_PAX_FLAGS; 1389 ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled 1390 ph->align = PtrSize; 1391 } 1392 1393 elfobj: 1394 sh = elfshname(".shstrtab"); 1395 sh->type = SHT_STRTAB; 1396 sh->addralign = 1; 1397 shsym(sh, lookup(".shstrtab", 0)); 1398 eh->shstrndx = sh->shnum; 1399 1400 // put these sections early in the list 1401 if(!debug['s']) { 1402 elfshname(".symtab"); 1403 elfshname(".strtab"); 1404 } 1405 1406 for(sect=segtext.sect; sect!=nil; sect=sect->next) 1407 elfshbits(sect); 1408 for(sect=segrodata.sect; sect!=nil; sect=sect->next) 1409 elfshbits(sect); 1410 for(sect=segdata.sect; sect!=nil; sect=sect->next) 1411 elfshbits(sect); 1412 1413 if(linkmode == LinkExternal) { 1414 for(sect=segtext.sect; sect!=nil; sect=sect->next) 1415 elfshreloc(sect); 1416 for(sect=segrodata.sect; sect!=nil; sect=sect->next) 1417 elfshreloc(sect); 1418 for(sect=segdata.sect; sect!=nil; sect=sect->next) 1419 elfshreloc(sect); 1420 // add a .note.GNU-stack section to mark the stack as non-executable 1421 sh = elfshname(".note.GNU-stack"); 1422 sh->type = SHT_PROGBITS; 1423 sh->addralign = 1; 1424 sh->flags = 0; 1425 } 1426 1427 // generate .tbss section for dynamic internal linking (except for OpenBSD) 1428 // external linking generates .tbss in data.c 1429 if(linkmode == LinkInternal && !debug['d'] && HEADTYPE != Hopenbsd) { 1430 sh = elfshname(".tbss"); 1431 sh->type = SHT_NOBITS; 1432 sh->addralign = PtrSize; 1433 sh->size = -tlsoffset; 1434 sh->flags = SHF_ALLOC | SHF_TLS | SHF_WRITE; 1435 } 1436 1437 if(!debug['s']) { 1438 sh = elfshname(".symtab"); 1439 sh->type = SHT_SYMTAB; 1440 sh->off = symo; 1441 sh->size = symsize; 1442 sh->addralign = PtrSize; 1443 sh->entsize = 8+2*PtrSize; 1444 sh->link = elfshname(".strtab")->shnum; 1445 sh->info = elfglobalsymndx; 1446 1447 sh = elfshname(".strtab"); 1448 sh->type = SHT_STRTAB; 1449 sh->off = symo+symsize; 1450 sh->size = elfstrsize; 1451 sh->addralign = 1; 1452 1453 dwarfaddelfheaders(); 1454 } 1455 1456 /* Main header */ 1457 eh->ident[EI_MAG0] = '\177'; 1458 eh->ident[EI_MAG1] = 'E'; 1459 eh->ident[EI_MAG2] = 'L'; 1460 eh->ident[EI_MAG3] = 'F'; 1461 if(HEADTYPE == Hfreebsd) 1462 eh->ident[EI_OSABI] = ELFOSABI_FREEBSD; 1463 else if(HEADTYPE == Hnetbsd) 1464 eh->ident[EI_OSABI] = ELFOSABI_NETBSD; 1465 else if(HEADTYPE == Hopenbsd) 1466 eh->ident[EI_OSABI] = ELFOSABI_OPENBSD; 1467 else if(HEADTYPE == Hdragonfly) 1468 eh->ident[EI_OSABI] = ELFOSABI_NONE; 1469 if(PtrSize == 8) 1470 eh->ident[EI_CLASS] = ELFCLASS64; 1471 else 1472 eh->ident[EI_CLASS] = ELFCLASS32; 1473 eh->ident[EI_DATA] = ELFDATA2LSB; 1474 eh->ident[EI_VERSION] = EV_CURRENT; 1475 1476 if(linkmode == LinkExternal) 1477 eh->type = ET_REL; 1478 else 1479 eh->type = ET_EXEC; 1480 1481 if(linkmode != LinkExternal) 1482 eh->entry = entryvalue(); 1483 1484 eh->version = EV_CURRENT; 1485 1486 if(pph != nil) { 1487 pph->filesz = eh->phnum * eh->phentsize; 1488 pph->memsz = pph->filesz; 1489 } 1490 1491 cseek(0); 1492 a = 0; 1493 a += elfwritehdr(); 1494 a += elfwritephdrs(); 1495 a += elfwriteshdrs(); 1496 if(!debug['d']) 1497 a += elfwriteinterp(); 1498 if(linkmode != LinkExternal) { 1499 if(HEADTYPE == Hnetbsd) 1500 a += elfwritenetbsdsig(); 1501 if(HEADTYPE == Hopenbsd) 1502 a += elfwriteopenbsdsig(); 1503 if(buildinfolen > 0) 1504 a += elfwritebuildinfo(); 1505 } 1506 if(a > ELFRESERVE) 1507 diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); 1508 }