github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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=segdata.sect; sect!=nil; sect=sect->next) 868 elfrelocsect(sect, datap); 869 } 870 871 void 872 doelf(void) 873 { 874 Sym *s, *shstrtab, *dynstr; 875 876 if(!iself) 877 return; 878 879 /* predefine strings we need for section headers */ 880 shstrtab = lookup(".shstrtab", 0); 881 shstrtab->type = SELFROSECT; 882 shstrtab->reachable = 1; 883 884 addstring(shstrtab, ""); 885 addstring(shstrtab, ".text"); 886 addstring(shstrtab, ".noptrdata"); 887 addstring(shstrtab, ".data"); 888 addstring(shstrtab, ".bss"); 889 addstring(shstrtab, ".noptrbss"); 890 if(linkmode == LinkExternal && HEADTYPE != Hopenbsd) 891 addstring(shstrtab, ".tbss"); 892 if(HEADTYPE == Hnetbsd) 893 addstring(shstrtab, ".note.netbsd.ident"); 894 if(HEADTYPE == Hopenbsd) 895 addstring(shstrtab, ".note.openbsd.ident"); 896 if(buildinfolen > 0) 897 addstring(shstrtab, ".note.gnu.build-id"); 898 addstring(shstrtab, ".elfdata"); 899 addstring(shstrtab, ".rodata"); 900 addstring(shstrtab, ".typelink"); 901 if(flag_shared) 902 addstring(shstrtab, ".data.rel.ro"); 903 addstring(shstrtab, ".gcdata"); 904 addstring(shstrtab, ".gcbss"); 905 addstring(shstrtab, ".gosymtab"); 906 addstring(shstrtab, ".gopclntab"); 907 908 if(linkmode == LinkExternal) { 909 debug['s'] = 0; 910 debug['d'] = 1; 911 912 if(thechar == '6') { 913 addstring(shstrtab, ".rela.text"); 914 addstring(shstrtab, ".rela.rodata"); 915 addstring(shstrtab, ".rela.typelink"); 916 addstring(shstrtab, ".rela.gcdata"); 917 addstring(shstrtab, ".rela.gcbss"); 918 addstring(shstrtab, ".rela.gosymtab"); 919 addstring(shstrtab, ".rela.gopclntab"); 920 addstring(shstrtab, ".rela.noptrdata"); 921 addstring(shstrtab, ".rela.data"); 922 } else { 923 addstring(shstrtab, ".rel.text"); 924 addstring(shstrtab, ".rel.rodata"); 925 addstring(shstrtab, ".rel.typelink"); 926 addstring(shstrtab, ".rel.gcdata"); 927 addstring(shstrtab, ".rel.gcbss"); 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(!debug['s']) { 938 addstring(shstrtab, ".symtab"); 939 addstring(shstrtab, ".strtab"); 940 dwarfaddshstrings(shstrtab); 941 } 942 addstring(shstrtab, ".shstrtab"); 943 944 if(!debug['d']) { /* -d suppresses dynamic loader format */ 945 addstring(shstrtab, ".interp"); 946 addstring(shstrtab, ".hash"); 947 addstring(shstrtab, ".got"); 948 addstring(shstrtab, ".got.plt"); 949 addstring(shstrtab, ".dynamic"); 950 addstring(shstrtab, ".dynsym"); 951 addstring(shstrtab, ".dynstr"); 952 if(thechar == '6') { 953 addstring(shstrtab, ".rela"); 954 addstring(shstrtab, ".rela.plt"); 955 } else { 956 addstring(shstrtab, ".rel"); 957 addstring(shstrtab, ".rel.plt"); 958 } 959 addstring(shstrtab, ".plt"); 960 addstring(shstrtab, ".gnu.version"); 961 addstring(shstrtab, ".gnu.version_r"); 962 963 /* dynamic symbol table - first entry all zeros */ 964 s = lookup(".dynsym", 0); 965 s->type = SELFROSECT; 966 s->reachable = 1; 967 if(thechar == '6') 968 s->size += ELF64SYMSIZE; 969 else 970 s->size += ELF32SYMSIZE; 971 972 /* dynamic string table */ 973 s = lookup(".dynstr", 0); 974 s->type = SELFROSECT; 975 s->reachable = 1; 976 if(s->size == 0) 977 addstring(s, ""); 978 dynstr = s; 979 980 /* relocation table */ 981 if(thechar == '6') 982 s = lookup(".rela", 0); 983 else 984 s = lookup(".rel", 0); 985 s->reachable = 1; 986 s->type = SELFROSECT; 987 988 /* global offset table */ 989 s = lookup(".got", 0); 990 s->reachable = 1; 991 s->type = SELFSECT; // writable 992 993 /* hash */ 994 s = lookup(".hash", 0); 995 s->reachable = 1; 996 s->type = SELFROSECT; 997 998 s = lookup(".got.plt", 0); 999 s->reachable = 1; 1000 s->type = SELFSECT; // writable 1001 1002 s = lookup(".plt", 0); 1003 s->reachable = 1; 1004 s->type = SELFROSECT; 1005 1006 elfsetupplt(); 1007 1008 if(thechar == '6') 1009 s = lookup(".rela.plt", 0); 1010 else 1011 s = lookup(".rel.plt", 0); 1012 s->reachable = 1; 1013 s->type = SELFROSECT; 1014 1015 s = lookup(".gnu.version", 0); 1016 s->reachable = 1; 1017 s->type = SELFROSECT; 1018 1019 s = lookup(".gnu.version_r", 0); 1020 s->reachable = 1; 1021 s->type = SELFROSECT; 1022 1023 /* define dynamic elf table */ 1024 s = lookup(".dynamic", 0); 1025 s->reachable = 1; 1026 s->type = SELFSECT; // writable 1027 1028 /* 1029 * .dynamic table 1030 */ 1031 elfwritedynentsym(s, DT_HASH, lookup(".hash", 0)); 1032 elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0)); 1033 if(thechar == '6') 1034 elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE); 1035 else 1036 elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE); 1037 elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0)); 1038 elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0)); 1039 if(thechar == '6') { 1040 elfwritedynentsym(s, DT_RELA, lookup(".rela", 0)); 1041 elfwritedynentsymsize(s, DT_RELASZ, lookup(".rela", 0)); 1042 elfwritedynent(s, DT_RELAENT, ELF64RELASIZE); 1043 } else { 1044 elfwritedynentsym(s, DT_REL, lookup(".rel", 0)); 1045 elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0)); 1046 elfwritedynent(s, DT_RELENT, ELF32RELSIZE); 1047 } 1048 if(rpath) 1049 elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath)); 1050 1051 elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0)); 1052 1053 if(thechar == '6') { 1054 elfwritedynent(s, DT_PLTREL, DT_RELA); 1055 elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0)); 1056 elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0)); 1057 } else { 1058 elfwritedynent(s, DT_PLTREL, DT_REL); 1059 elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0)); 1060 elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0)); 1061 } 1062 1063 elfwritedynent(s, DT_DEBUG, 0); 1064 1065 if(flag_shared) { 1066 Sym *init_sym = lookup(LIBINITENTRY, 0); 1067 if(init_sym->type != STEXT) 1068 diag("entry not text: %s", init_sym->name); 1069 elfwritedynentsym(s, DT_INIT, init_sym); 1070 } 1071 1072 // Do not write DT_NULL. elfdynhash will finish it. 1073 } 1074 } 1075 1076 void 1077 shsym(ElfShdr *sh, Sym *s) 1078 { 1079 vlong addr; 1080 addr = symaddr(s); 1081 if(sh->flags&SHF_ALLOC) 1082 sh->addr = addr; 1083 sh->off = datoff(addr); 1084 sh->size = s->size; 1085 } 1086 1087 void 1088 phsh(ElfPhdr *ph, ElfShdr *sh) 1089 { 1090 ph->vaddr = sh->addr; 1091 ph->paddr = ph->vaddr; 1092 ph->off = sh->off; 1093 ph->filesz = sh->size; 1094 ph->memsz = sh->size; 1095 ph->align = sh->addralign; 1096 } 1097 1098 void 1099 asmbelfsetup(void) 1100 { 1101 Section *sect; 1102 1103 /* This null SHdr must appear before all others */ 1104 elfshname(""); 1105 1106 for(sect=segtext.sect; sect!=nil; sect=sect->next) 1107 elfshalloc(sect); 1108 for(sect=segdata.sect; sect!=nil; sect=sect->next) 1109 elfshalloc(sect); 1110 } 1111 1112 void 1113 asmbelf(vlong symo) 1114 { 1115 vlong a, o; 1116 vlong startva, resoff; 1117 ElfEhdr *eh; 1118 ElfPhdr *ph, *pph, *pnote; 1119 ElfShdr *sh; 1120 Section *sect; 1121 1122 eh = getElfEhdr(); 1123 switch(thechar) { 1124 default: 1125 diag("unknown architecture in asmbelf"); 1126 errorexit(); 1127 case '5': 1128 eh->machine = EM_ARM; 1129 break; 1130 case '6': 1131 eh->machine = EM_X86_64; 1132 break; 1133 case '8': 1134 eh->machine = EM_386; 1135 break; 1136 } 1137 1138 startva = INITTEXT - HEADR; 1139 resoff = ELFRESERVE; 1140 1141 pph = nil; 1142 if(linkmode == LinkExternal) { 1143 /* skip program headers */ 1144 eh->phoff = 0; 1145 eh->phentsize = 0; 1146 goto elfobj; 1147 } 1148 1149 /* program header info */ 1150 pph = newElfPhdr(); 1151 pph->type = PT_PHDR; 1152 pph->flags = PF_R + PF_X; 1153 pph->off = eh->ehsize; 1154 pph->vaddr = INITTEXT - HEADR + pph->off; 1155 pph->paddr = INITTEXT - HEADR + pph->off; 1156 pph->align = INITRND; 1157 1158 /* 1159 * PHDR must be in a loaded segment. Adjust the text 1160 * segment boundaries downwards to include it. 1161 */ 1162 o = segtext.vaddr - pph->vaddr; 1163 segtext.vaddr -= o; 1164 segtext.len += o; 1165 o = segtext.fileoff - pph->off; 1166 segtext.fileoff -= o; 1167 segtext.filelen += o; 1168 1169 if(!debug['d']) { 1170 /* interpreter */ 1171 sh = elfshname(".interp"); 1172 sh->type = SHT_PROGBITS; 1173 sh->flags = SHF_ALLOC; 1174 sh->addralign = 1; 1175 if(interpreter == nil) { 1176 switch(HEADTYPE) { 1177 case Hlinux: 1178 interpreter = linuxdynld; 1179 break; 1180 case Hfreebsd: 1181 interpreter = freebsddynld; 1182 break; 1183 case Hnetbsd: 1184 interpreter = netbsddynld; 1185 break; 1186 case Hopenbsd: 1187 interpreter = openbsddynld; 1188 break; 1189 } 1190 } 1191 resoff -= elfinterp(sh, startva, resoff, interpreter); 1192 1193 ph = newElfPhdr(); 1194 ph->type = PT_INTERP; 1195 ph->flags = PF_R; 1196 phsh(ph, sh); 1197 } 1198 1199 pnote = nil; 1200 if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) { 1201 sh = nil; 1202 switch(HEADTYPE) { 1203 case Hnetbsd: 1204 sh = elfshname(".note.netbsd.ident"); 1205 resoff -= elfnetbsdsig(sh, startva, resoff); 1206 break; 1207 case Hopenbsd: 1208 sh = elfshname(".note.openbsd.ident"); 1209 resoff -= elfopenbsdsig(sh, startva, resoff); 1210 break; 1211 } 1212 1213 pnote = newElfPhdr(); 1214 pnote->type = PT_NOTE; 1215 pnote->flags = PF_R; 1216 phsh(pnote, sh); 1217 } 1218 1219 if(buildinfolen > 0) { 1220 sh = elfshname(".note.gnu.build-id"); 1221 resoff -= elfbuildinfo(sh, startva, resoff); 1222 1223 if(pnote == nil) { 1224 pnote = newElfPhdr(); 1225 pnote->type = PT_NOTE; 1226 pnote->flags = PF_R; 1227 } 1228 phsh(pnote, sh); 1229 } 1230 1231 // Additions to the reserved area must be above this line. 1232 USED(resoff); 1233 1234 elfphload(&segtext); 1235 elfphload(&segdata); 1236 1237 /* Dynamic linking sections */ 1238 if(!debug['d']) { /* -d suppresses dynamic loader format */ 1239 sh = elfshname(".dynsym"); 1240 sh->type = SHT_DYNSYM; 1241 sh->flags = SHF_ALLOC; 1242 if(PtrSize == 8) 1243 sh->entsize = ELF64SYMSIZE; 1244 else 1245 sh->entsize = ELF32SYMSIZE; 1246 sh->addralign = PtrSize; 1247 sh->link = elfshname(".dynstr")->shnum; 1248 // sh->info = index of first non-local symbol (number of local symbols) 1249 shsym(sh, lookup(".dynsym", 0)); 1250 1251 sh = elfshname(".dynstr"); 1252 sh->type = SHT_STRTAB; 1253 sh->flags = SHF_ALLOC; 1254 sh->addralign = 1; 1255 shsym(sh, lookup(".dynstr", 0)); 1256 1257 if(elfverneed) { 1258 sh = elfshname(".gnu.version"); 1259 sh->type = SHT_GNU_VERSYM; 1260 sh->flags = SHF_ALLOC; 1261 sh->addralign = 2; 1262 sh->link = elfshname(".dynsym")->shnum; 1263 sh->entsize = 2; 1264 shsym(sh, lookup(".gnu.version", 0)); 1265 1266 sh = elfshname(".gnu.version_r"); 1267 sh->type = SHT_GNU_VERNEED; 1268 sh->flags = SHF_ALLOC; 1269 sh->addralign = PtrSize; 1270 sh->info = elfverneed; 1271 sh->link = elfshname(".dynstr")->shnum; 1272 shsym(sh, lookup(".gnu.version_r", 0)); 1273 } 1274 1275 switch(eh->machine) { 1276 case EM_X86_64: 1277 sh = elfshname(".rela.plt"); 1278 sh->type = SHT_RELA; 1279 sh->flags = SHF_ALLOC; 1280 sh->entsize = ELF64RELASIZE; 1281 sh->addralign = PtrSize; 1282 sh->link = elfshname(".dynsym")->shnum; 1283 sh->info = elfshname(".plt")->shnum; 1284 shsym(sh, lookup(".rela.plt", 0)); 1285 1286 sh = elfshname(".rela"); 1287 sh->type = SHT_RELA; 1288 sh->flags = SHF_ALLOC; 1289 sh->entsize = ELF64RELASIZE; 1290 sh->addralign = 8; 1291 sh->link = elfshname(".dynsym")->shnum; 1292 shsym(sh, lookup(".rela", 0)); 1293 break; 1294 1295 default: 1296 sh = elfshname(".rel.plt"); 1297 sh->type = SHT_REL; 1298 sh->flags = SHF_ALLOC; 1299 sh->entsize = ELF32RELSIZE; 1300 sh->link = elfshname(".dynsym")->shnum; 1301 shsym(sh, lookup(".rel.plt", 0)); 1302 1303 sh = elfshname(".rel"); 1304 sh->type = SHT_REL; 1305 sh->flags = SHF_ALLOC; 1306 sh->entsize = ELF32RELSIZE; 1307 sh->addralign = 4; 1308 sh->link = elfshname(".dynsym")->shnum; 1309 shsym(sh, lookup(".rel", 0)); 1310 break; 1311 } 1312 1313 sh = elfshname(".plt"); 1314 sh->type = SHT_PROGBITS; 1315 sh->flags = SHF_ALLOC+SHF_EXECINSTR; 1316 if(eh->machine == EM_X86_64) 1317 sh->entsize = 16; 1318 else 1319 sh->entsize = 4; 1320 sh->addralign = 4; 1321 shsym(sh, lookup(".plt", 0)); 1322 1323 sh = elfshname(".got"); 1324 sh->type = SHT_PROGBITS; 1325 sh->flags = SHF_ALLOC+SHF_WRITE; 1326 sh->entsize = PtrSize; 1327 sh->addralign = PtrSize; 1328 shsym(sh, lookup(".got", 0)); 1329 1330 sh = elfshname(".got.plt"); 1331 sh->type = SHT_PROGBITS; 1332 sh->flags = SHF_ALLOC+SHF_WRITE; 1333 sh->entsize = PtrSize; 1334 sh->addralign = PtrSize; 1335 shsym(sh, lookup(".got.plt", 0)); 1336 1337 sh = elfshname(".hash"); 1338 sh->type = SHT_HASH; 1339 sh->flags = SHF_ALLOC; 1340 sh->entsize = 4; 1341 sh->addralign = PtrSize; 1342 sh->link = elfshname(".dynsym")->shnum; 1343 shsym(sh, lookup(".hash", 0)); 1344 1345 /* sh and PT_DYNAMIC for .dynamic section */ 1346 sh = elfshname(".dynamic"); 1347 sh->type = SHT_DYNAMIC; 1348 sh->flags = SHF_ALLOC+SHF_WRITE; 1349 sh->entsize = 2*PtrSize; 1350 sh->addralign = PtrSize; 1351 sh->link = elfshname(".dynstr")->shnum; 1352 shsym(sh, lookup(".dynamic", 0)); 1353 ph = newElfPhdr(); 1354 ph->type = PT_DYNAMIC; 1355 ph->flags = PF_R + PF_W; 1356 phsh(ph, sh); 1357 1358 /* 1359 * Thread-local storage segment (really just size). 1360 */ 1361 // Do not emit PT_TLS for OpenBSD since ld.so(1) does 1362 // not currently support it. This is handled 1363 // appropriately in runtime/cgo. 1364 if(tlsoffset != 0 && HEADTYPE != Hopenbsd) { 1365 ph = newElfPhdr(); 1366 ph->type = PT_TLS; 1367 ph->flags = PF_R; 1368 ph->memsz = -tlsoffset; 1369 ph->align = PtrSize; 1370 } 1371 } 1372 1373 if(HEADTYPE == Hlinux) { 1374 ph = newElfPhdr(); 1375 ph->type = PT_GNU_STACK; 1376 ph->flags = PF_W+PF_R; 1377 ph->align = PtrSize; 1378 1379 ph = newElfPhdr(); 1380 ph->type = PT_PAX_FLAGS; 1381 ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled 1382 ph->align = PtrSize; 1383 } 1384 1385 elfobj: 1386 sh = elfshname(".shstrtab"); 1387 sh->type = SHT_STRTAB; 1388 sh->addralign = 1; 1389 shsym(sh, lookup(".shstrtab", 0)); 1390 eh->shstrndx = sh->shnum; 1391 1392 // put these sections early in the list 1393 if(!debug['s']) { 1394 elfshname(".symtab"); 1395 elfshname(".strtab"); 1396 } 1397 1398 for(sect=segtext.sect; sect!=nil; sect=sect->next) 1399 elfshbits(sect); 1400 for(sect=segdata.sect; sect!=nil; sect=sect->next) 1401 elfshbits(sect); 1402 1403 if(linkmode == LinkExternal) { 1404 for(sect=segtext.sect; sect!=nil; sect=sect->next) 1405 elfshreloc(sect); 1406 for(sect=segdata.sect; sect!=nil; sect=sect->next) 1407 elfshreloc(sect); 1408 // add a .note.GNU-stack section to mark the stack as non-executable 1409 sh = elfshname(".note.GNU-stack"); 1410 sh->type = SHT_PROGBITS; 1411 sh->addralign = 1; 1412 sh->flags = 0; 1413 } 1414 1415 if(!debug['s']) { 1416 sh = elfshname(".symtab"); 1417 sh->type = SHT_SYMTAB; 1418 sh->off = symo; 1419 sh->size = symsize; 1420 sh->addralign = PtrSize; 1421 sh->entsize = 8+2*PtrSize; 1422 sh->link = elfshname(".strtab")->shnum; 1423 sh->info = elfglobalsymndx; 1424 1425 sh = elfshname(".strtab"); 1426 sh->type = SHT_STRTAB; 1427 sh->off = symo+symsize; 1428 sh->size = elfstrsize; 1429 sh->addralign = 1; 1430 1431 dwarfaddelfheaders(); 1432 } 1433 1434 /* Main header */ 1435 eh->ident[EI_MAG0] = '\177'; 1436 eh->ident[EI_MAG1] = 'E'; 1437 eh->ident[EI_MAG2] = 'L'; 1438 eh->ident[EI_MAG3] = 'F'; 1439 if(HEADTYPE == Hfreebsd) 1440 eh->ident[EI_OSABI] = ELFOSABI_FREEBSD; 1441 else if(HEADTYPE == Hnetbsd) 1442 eh->ident[EI_OSABI] = ELFOSABI_NETBSD; 1443 else if(HEADTYPE == Hopenbsd) 1444 eh->ident[EI_OSABI] = ELFOSABI_OPENBSD; 1445 if(PtrSize == 8) 1446 eh->ident[EI_CLASS] = ELFCLASS64; 1447 else 1448 eh->ident[EI_CLASS] = ELFCLASS32; 1449 eh->ident[EI_DATA] = ELFDATA2LSB; 1450 eh->ident[EI_VERSION] = EV_CURRENT; 1451 1452 if(flag_shared) 1453 eh->type = ET_DYN; 1454 else if(linkmode == LinkExternal) 1455 eh->type = ET_REL; 1456 else 1457 eh->type = ET_EXEC; 1458 1459 if(linkmode != LinkExternal) 1460 eh->entry = entryvalue(); 1461 1462 eh->version = EV_CURRENT; 1463 1464 if(pph != nil) { 1465 pph->filesz = eh->phnum * eh->phentsize; 1466 pph->memsz = pph->filesz; 1467 } 1468 1469 cseek(0); 1470 a = 0; 1471 a += elfwritehdr(); 1472 a += elfwritephdrs(); 1473 a += elfwriteshdrs(); 1474 if(!debug['d']) 1475 a += elfwriteinterp(); 1476 if(linkmode != LinkExternal) { 1477 if(HEADTYPE == Hnetbsd) 1478 a += elfwritenetbsdsig(); 1479 if(HEADTYPE == Hopenbsd) 1480 a += elfwriteopenbsdsig(); 1481 if(buildinfolen > 0) 1482 a += elfwritebuildinfo(); 1483 } 1484 if(a > ELFRESERVE) 1485 diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); 1486 }