github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/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 use EABI on both linux/arm and freebsd/arm. 59 if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd) 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(LSym *s, int tag, uint64 val) 291 { 292 if(elf64) { 293 adduint64(ctxt, s, tag); 294 adduint64(ctxt, s, val); 295 } else { 296 adduint32(ctxt, s, tag); 297 adduint32(ctxt, s, val); 298 } 299 } 300 301 void 302 elfwritedynentsym(LSym *s, int tag, LSym *t) 303 { 304 if(elf64) 305 adduint64(ctxt, s, tag); 306 else 307 adduint32(ctxt, s, tag); 308 addaddr(ctxt, s, t); 309 } 310 311 void 312 elfwritedynentsymsize(LSym *s, int tag, LSym *t) 313 { 314 if(elf64) 315 adduint64(ctxt, s, tag); 316 else 317 adduint32(ctxt, s, tag); 318 addsize(ctxt, 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 - resoff % 4; 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 = rnd(ELF_NOTE_NETBSD_NAMESZ, 4) + rnd(ELF_NOTE_NETBSD_DESCSZ, 4); 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 LSym *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 = linklookup(ctxt, ".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 ctxt->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=ctxt->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(ctxt, s, nbucket); 617 adduint32(ctxt, s, nsym); 618 for(i = 0; i<nbucket; i++) 619 adduint32(ctxt, s, buckets[i]); 620 for(i = 0; i<nsym; i++) 621 adduint32(ctxt, s, chain[i]); 622 623 free(chain); 624 free(buckets); 625 626 // version symbols 627 dynstr = linklookup(ctxt, ".dynstr", 0); 628 s = linklookup(ctxt, ".gnu.version_r", 0); 629 i = 2; 630 nfile = 0; 631 for(l=needlib; l; l=l->next) { 632 nfile++; 633 // header 634 adduint16(ctxt, s, 1); // table version 635 j = 0; 636 for(x=l->aux; x; x=x->next) 637 j++; 638 adduint16(ctxt, s, j); // aux count 639 adduint32(ctxt, s, addstring(dynstr, l->file)); // file string offset 640 adduint32(ctxt, s, 16); // offset from header to first aux 641 if(l->next) 642 adduint32(ctxt, s, 16+j*16); // offset from this header to next 643 else 644 adduint32(ctxt, s, 0); 645 646 for(x=l->aux; x; x=x->next) { 647 x->num = i++; 648 // aux struct 649 adduint32(ctxt, s, elfhash((uchar*)x->vers)); // hash 650 adduint16(ctxt, s, 0); // flags 651 adduint16(ctxt, s, x->num); // other - index we refer to this by 652 adduint32(ctxt, s, addstring(dynstr, x->vers)); // version string offset 653 if(x->next) 654 adduint32(ctxt, s, 16); // offset from this aux to next 655 else 656 adduint32(ctxt, s, 0); 657 } 658 } 659 660 // version references 661 s = linklookup(ctxt, ".gnu.version", 0); 662 for(i=0; i<nsym; i++) { 663 if(i == 0) 664 adduint16(ctxt, s, 0); // first entry - no symbol 665 else if(need[i] == nil) 666 adduint16(ctxt, s, 1); // global 667 else 668 adduint16(ctxt, s, need[i]->num); 669 } 670 671 free(need); 672 673 s = linklookup(ctxt, ".dynamic", 0); 674 elfverneed = nfile; 675 if(elfverneed) { 676 elfwritedynentsym(s, DT_VERNEED, linklookup(ctxt, ".gnu.version_r", 0)); 677 elfwritedynent(s, DT_VERNEEDNUM, nfile); 678 elfwritedynentsym(s, DT_VERSYM, linklookup(ctxt, ".gnu.version", 0)); 679 } 680 681 if(thechar == '6') { 682 sy = linklookup(ctxt, ".rela.plt", 0); 683 if(sy->size > 0) { 684 elfwritedynent(s, DT_PLTREL, DT_RELA); 685 elfwritedynentsymsize(s, DT_PLTRELSZ, sy); 686 elfwritedynentsym(s, DT_JMPREL, sy); 687 } 688 } else { 689 sy = linklookup(ctxt, ".rel.plt", 0); 690 if(sy->size > 0) { 691 elfwritedynent(s, DT_PLTREL, DT_REL); 692 elfwritedynentsymsize(s, DT_PLTRELSZ, sy); 693 elfwritedynentsym(s, DT_JMPREL, sy); 694 } 695 } 696 697 elfwritedynent(s, DT_NULL, 0); 698 } 699 700 ElfPhdr* 701 elfphload(Segment *seg) 702 { 703 ElfPhdr *ph; 704 705 ph = newElfPhdr(); 706 ph->type = PT_LOAD; 707 if(seg->rwx & 4) 708 ph->flags |= PF_R; 709 if(seg->rwx & 2) 710 ph->flags |= PF_W; 711 if(seg->rwx & 1) 712 ph->flags |= PF_X; 713 ph->vaddr = seg->vaddr; 714 ph->paddr = seg->vaddr; 715 ph->memsz = seg->len; 716 ph->off = seg->fileoff; 717 ph->filesz = seg->filelen; 718 ph->align = INITRND; 719 720 return ph; 721 } 722 723 ElfShdr* 724 elfshname(char *name) 725 { 726 int i, off; 727 ElfShdr *sh; 728 729 for(i=0; i<nelfstr; i++) { 730 if(strcmp(name, elfstr[i].s) == 0) { 731 off = elfstr[i].off; 732 goto found; 733 } 734 } 735 diag("cannot find elf name %s", name); 736 errorexit(); 737 return nil; 738 739 found: 740 for(i=0; i<hdr.shnum; i++) { 741 sh = shdr[i]; 742 if(sh->name == off) 743 return sh; 744 } 745 746 sh = newElfShdr(off); 747 return sh; 748 } 749 750 ElfShdr* 751 elfshalloc(Section *sect) 752 { 753 ElfShdr *sh; 754 755 sh = elfshname(sect->name); 756 sect->elfsect = sh; 757 return sh; 758 } 759 760 ElfShdr* 761 elfshbits(Section *sect) 762 { 763 ElfShdr *sh; 764 765 sh = elfshalloc(sect); 766 if(sh->type > 0) 767 return sh; 768 769 if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen) 770 sh->type = SHT_PROGBITS; 771 else 772 sh->type = SHT_NOBITS; 773 sh->flags = SHF_ALLOC; 774 if(sect->rwx & 1) 775 sh->flags |= SHF_EXECINSTR; 776 if(sect->rwx & 2) 777 sh->flags |= SHF_WRITE; 778 if(strcmp(sect->name, ".tbss") == 0) { 779 if(strcmp(goos, "android") != 0) 780 sh->flags |= SHF_TLS; // no TLS on android 781 sh->type = SHT_NOBITS; 782 } 783 if(linkmode != LinkExternal) 784 sh->addr = sect->vaddr; 785 sh->addralign = sect->align; 786 sh->size = sect->len; 787 sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr; 788 789 return sh; 790 } 791 792 ElfShdr* 793 elfshreloc(Section *sect) 794 { 795 int typ; 796 ElfShdr *sh; 797 char *prefix; 798 char buf[100]; 799 800 // If main section is SHT_NOBITS, nothing to relocate. 801 // Also nothing to relocate in .shstrtab. 802 if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen) 803 return nil; 804 if(strcmp(sect->name, ".shstrtab") == 0 || strcmp(sect->name, ".tbss") == 0) 805 return nil; 806 807 if(thechar == '6') { 808 prefix = ".rela"; 809 typ = SHT_RELA; 810 } else { 811 prefix = ".rel"; 812 typ = SHT_REL; 813 } 814 815 snprint(buf, sizeof buf, "%s%s", prefix, sect->name); 816 sh = elfshname(buf); 817 sh->type = typ; 818 sh->entsize = RegSize*(2+(typ==SHT_RELA)); 819 sh->link = elfshname(".symtab")->shnum; 820 sh->info = sect->elfsect->shnum; 821 sh->off = sect->reloff; 822 sh->size = sect->rellen; 823 sh->addralign = RegSize; 824 return sh; 825 } 826 827 void 828 elfrelocsect(Section *sect, LSym *first) 829 { 830 LSym *sym; 831 int32 eaddr; 832 Reloc *r; 833 834 // If main section is SHT_NOBITS, nothing to relocate. 835 // Also nothing to relocate in .shstrtab. 836 if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen) 837 return; 838 if(strcmp(sect->name, ".shstrtab") == 0) 839 return; 840 841 sect->reloff = cpos(); 842 for(sym = first; sym != nil; sym = sym->next) { 843 if(!sym->reachable) 844 continue; 845 if(sym->value >= sect->vaddr) 846 break; 847 } 848 849 eaddr = sect->vaddr + sect->len; 850 for(; sym != nil; sym = sym->next) { 851 if(!sym->reachable) 852 continue; 853 if(sym->value >= eaddr) 854 break; 855 ctxt->cursym = sym; 856 857 for(r = sym->r; r < sym->r+sym->nr; r++) { 858 if(r->done) 859 continue; 860 if(r->xsym == nil) { 861 diag("missing xsym in relocation"); 862 continue; 863 } 864 if(r->xsym->elfsym == 0) 865 diag("reloc %d to non-elf symbol %s (outer=%s) %d", r->type, r->sym->name, r->xsym->name, r->sym->type); 866 if(elfreloc1(r, sym->value+r->off - sect->vaddr) < 0) 867 diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name); 868 } 869 } 870 871 sect->rellen = cpos() - sect->reloff; 872 } 873 874 void 875 elfemitreloc(void) 876 { 877 Section *sect; 878 879 while(cpos()&7) 880 cput(0); 881 882 elfrelocsect(segtext.sect, ctxt->textp); 883 for(sect=segtext.sect->next; sect!=nil; sect=sect->next) 884 elfrelocsect(sect, datap); 885 for(sect=segrodata.sect; sect!=nil; sect=sect->next) 886 elfrelocsect(sect, datap); 887 for(sect=segdata.sect; sect!=nil; sect=sect->next) 888 elfrelocsect(sect, datap); 889 } 890 891 void 892 doelf(void) 893 { 894 LSym *s, *shstrtab, *dynstr; 895 896 if(!iself) 897 return; 898 899 /* predefine strings we need for section headers */ 900 shstrtab = linklookup(ctxt, ".shstrtab", 0); 901 shstrtab->type = SELFROSECT; 902 shstrtab->reachable = 1; 903 904 addstring(shstrtab, ""); 905 addstring(shstrtab, ".text"); 906 addstring(shstrtab, ".noptrdata"); 907 addstring(shstrtab, ".data"); 908 addstring(shstrtab, ".bss"); 909 addstring(shstrtab, ".noptrbss"); 910 // generate .tbss section (except for OpenBSD where it's not supported) 911 // for dynamic internal linker or external linking, so that various 912 // binutils could correctly calculate PT_TLS size. 913 // see http://golang.org/issue/5200. 914 if(HEADTYPE != Hopenbsd) 915 if(!debug['d'] || linkmode == LinkExternal) 916 addstring(shstrtab, ".tbss"); 917 if(HEADTYPE == Hnetbsd) 918 addstring(shstrtab, ".note.netbsd.ident"); 919 if(HEADTYPE == Hopenbsd) 920 addstring(shstrtab, ".note.openbsd.ident"); 921 if(buildinfolen > 0) 922 addstring(shstrtab, ".note.gnu.build-id"); 923 addstring(shstrtab, ".elfdata"); 924 addstring(shstrtab, ".rodata"); 925 addstring(shstrtab, ".typelink"); 926 addstring(shstrtab, ".gosymtab"); 927 addstring(shstrtab, ".gopclntab"); 928 929 if(linkmode == LinkExternal) { 930 debug_s = debug['s']; 931 debug['s'] = 0; 932 debug['d'] = 1; 933 934 if(thechar == '6') { 935 addstring(shstrtab, ".rela.text"); 936 addstring(shstrtab, ".rela.rodata"); 937 addstring(shstrtab, ".rela.typelink"); 938 addstring(shstrtab, ".rela.gosymtab"); 939 addstring(shstrtab, ".rela.gopclntab"); 940 addstring(shstrtab, ".rela.noptrdata"); 941 addstring(shstrtab, ".rela.data"); 942 } else { 943 addstring(shstrtab, ".rel.text"); 944 addstring(shstrtab, ".rel.rodata"); 945 addstring(shstrtab, ".rel.typelink"); 946 addstring(shstrtab, ".rel.gosymtab"); 947 addstring(shstrtab, ".rel.gopclntab"); 948 addstring(shstrtab, ".rel.noptrdata"); 949 addstring(shstrtab, ".rel.data"); 950 } 951 // add a .note.GNU-stack section to mark the stack as non-executable 952 addstring(shstrtab, ".note.GNU-stack"); 953 } 954 955 if(flag_shared) { 956 addstring(shstrtab, ".init_array"); 957 if(thechar == '6') 958 addstring(shstrtab, ".rela.init_array"); 959 else 960 addstring(shstrtab, ".rel.init_array"); 961 } 962 963 if(!debug['s']) { 964 addstring(shstrtab, ".symtab"); 965 addstring(shstrtab, ".strtab"); 966 dwarfaddshstrings(shstrtab); 967 } 968 addstring(shstrtab, ".shstrtab"); 969 970 if(!debug['d']) { /* -d suppresses dynamic loader format */ 971 addstring(shstrtab, ".interp"); 972 addstring(shstrtab, ".hash"); 973 addstring(shstrtab, ".got"); 974 addstring(shstrtab, ".got.plt"); 975 addstring(shstrtab, ".dynamic"); 976 addstring(shstrtab, ".dynsym"); 977 addstring(shstrtab, ".dynstr"); 978 if(thechar == '6') { 979 addstring(shstrtab, ".rela"); 980 addstring(shstrtab, ".rela.plt"); 981 } else { 982 addstring(shstrtab, ".rel"); 983 addstring(shstrtab, ".rel.plt"); 984 } 985 addstring(shstrtab, ".plt"); 986 addstring(shstrtab, ".gnu.version"); 987 addstring(shstrtab, ".gnu.version_r"); 988 989 /* dynamic symbol table - first entry all zeros */ 990 s = linklookup(ctxt, ".dynsym", 0); 991 s->type = SELFROSECT; 992 s->reachable = 1; 993 if(thechar == '6') 994 s->size += ELF64SYMSIZE; 995 else 996 s->size += ELF32SYMSIZE; 997 998 /* dynamic string table */ 999 s = linklookup(ctxt, ".dynstr", 0); 1000 s->type = SELFROSECT; 1001 s->reachable = 1; 1002 if(s->size == 0) 1003 addstring(s, ""); 1004 dynstr = s; 1005 1006 /* relocation table */ 1007 if(thechar == '6') 1008 s = linklookup(ctxt, ".rela", 0); 1009 else 1010 s = linklookup(ctxt, ".rel", 0); 1011 s->reachable = 1; 1012 s->type = SELFROSECT; 1013 1014 /* global offset table */ 1015 s = linklookup(ctxt, ".got", 0); 1016 s->reachable = 1; 1017 s->type = SELFSECT; // writable 1018 1019 /* hash */ 1020 s = linklookup(ctxt, ".hash", 0); 1021 s->reachable = 1; 1022 s->type = SELFROSECT; 1023 1024 s = linklookup(ctxt, ".got.plt", 0); 1025 s->reachable = 1; 1026 s->type = SELFSECT; // writable 1027 1028 s = linklookup(ctxt, ".plt", 0); 1029 s->reachable = 1; 1030 s->type = SELFRXSECT; 1031 1032 elfsetupplt(); 1033 1034 if(thechar == '6') 1035 s = linklookup(ctxt, ".rela.plt", 0); 1036 else 1037 s = linklookup(ctxt, ".rel.plt", 0); 1038 s->reachable = 1; 1039 s->type = SELFROSECT; 1040 1041 s = linklookup(ctxt, ".gnu.version", 0); 1042 s->reachable = 1; 1043 s->type = SELFROSECT; 1044 1045 s = linklookup(ctxt, ".gnu.version_r", 0); 1046 s->reachable = 1; 1047 s->type = SELFROSECT; 1048 1049 /* define dynamic elf table */ 1050 s = linklookup(ctxt, ".dynamic", 0); 1051 s->reachable = 1; 1052 s->type = SELFSECT; // writable 1053 1054 /* 1055 * .dynamic table 1056 */ 1057 elfwritedynentsym(s, DT_HASH, linklookup(ctxt, ".hash", 0)); 1058 elfwritedynentsym(s, DT_SYMTAB, linklookup(ctxt, ".dynsym", 0)); 1059 if(thechar == '6') 1060 elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE); 1061 else 1062 elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE); 1063 elfwritedynentsym(s, DT_STRTAB, linklookup(ctxt, ".dynstr", 0)); 1064 elfwritedynentsymsize(s, DT_STRSZ, linklookup(ctxt, ".dynstr", 0)); 1065 if(thechar == '6') { 1066 elfwritedynentsym(s, DT_RELA, linklookup(ctxt, ".rela", 0)); 1067 elfwritedynentsymsize(s, DT_RELASZ, linklookup(ctxt, ".rela", 0)); 1068 elfwritedynent(s, DT_RELAENT, ELF64RELASIZE); 1069 } else { 1070 elfwritedynentsym(s, DT_REL, linklookup(ctxt, ".rel", 0)); 1071 elfwritedynentsymsize(s, DT_RELSZ, linklookup(ctxt, ".rel", 0)); 1072 elfwritedynent(s, DT_RELENT, ELF32RELSIZE); 1073 } 1074 if(rpath) 1075 elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath)); 1076 1077 elfwritedynentsym(s, DT_PLTGOT, linklookup(ctxt, ".got.plt", 0)); 1078 1079 // Solaris dynamic linker can't handle an empty .rela.plt if 1080 // DT_JMPREL is emitted so we have to defer generation of DT_PLTREL, 1081 // DT_PLTRELSZ, and DT_JMPREL dynamic entries until after we know the 1082 // size of .rel(a).plt section. 1083 elfwritedynent(s, DT_DEBUG, 0); 1084 1085 // Do not write DT_NULL. elfdynhash will finish it. 1086 } 1087 } 1088 1089 void 1090 shsym(ElfShdr *sh, LSym *s) 1091 { 1092 vlong addr; 1093 addr = symaddr(s); 1094 if(sh->flags&SHF_ALLOC) 1095 sh->addr = addr; 1096 sh->off = datoff(addr); 1097 sh->size = s->size; 1098 } 1099 1100 void 1101 phsh(ElfPhdr *ph, ElfShdr *sh) 1102 { 1103 ph->vaddr = sh->addr; 1104 ph->paddr = ph->vaddr; 1105 ph->off = sh->off; 1106 ph->filesz = sh->size; 1107 ph->memsz = sh->size; 1108 ph->align = sh->addralign; 1109 } 1110 1111 void 1112 asmbelfsetup(void) 1113 { 1114 Section *sect; 1115 1116 /* This null SHdr must appear before all others */ 1117 elfshname(""); 1118 1119 for(sect=segtext.sect; sect!=nil; sect=sect->next) 1120 elfshalloc(sect); 1121 for(sect=segrodata.sect; sect!=nil; sect=sect->next) 1122 elfshalloc(sect); 1123 for(sect=segdata.sect; sect!=nil; sect=sect->next) 1124 elfshalloc(sect); 1125 } 1126 1127 void 1128 asmbelf(vlong symo) 1129 { 1130 vlong a, o; 1131 vlong startva, resoff; 1132 ElfEhdr *eh; 1133 ElfPhdr *ph, *pph, *pnote; 1134 ElfShdr *sh; 1135 Section *sect; 1136 1137 eh = getElfEhdr(); 1138 switch(thechar) { 1139 default: 1140 diag("unknown architecture in asmbelf"); 1141 errorexit(); 1142 case '5': 1143 eh->machine = EM_ARM; 1144 break; 1145 case '6': 1146 eh->machine = EM_X86_64; 1147 break; 1148 case '8': 1149 eh->machine = EM_386; 1150 break; 1151 } 1152 1153 startva = INITTEXT - HEADR; 1154 resoff = ELFRESERVE; 1155 1156 pph = nil; 1157 if(linkmode == LinkExternal) { 1158 /* skip program headers */ 1159 eh->phoff = 0; 1160 eh->phentsize = 0; 1161 goto elfobj; 1162 } 1163 1164 /* program header info */ 1165 pph = newElfPhdr(); 1166 pph->type = PT_PHDR; 1167 pph->flags = PF_R; 1168 pph->off = eh->ehsize; 1169 pph->vaddr = INITTEXT - HEADR + pph->off; 1170 pph->paddr = INITTEXT - HEADR + pph->off; 1171 pph->align = INITRND; 1172 1173 /* 1174 * PHDR must be in a loaded segment. Adjust the text 1175 * segment boundaries downwards to include it. 1176 * Except on NaCl where it must not be loaded. 1177 */ 1178 if(HEADTYPE != Hnacl) { 1179 o = segtext.vaddr - pph->vaddr; 1180 segtext.vaddr -= o; 1181 segtext.len += o; 1182 o = segtext.fileoff - pph->off; 1183 segtext.fileoff -= o; 1184 segtext.filelen += o; 1185 } 1186 1187 if(!debug['d']) { 1188 /* interpreter */ 1189 sh = elfshname(".interp"); 1190 sh->type = SHT_PROGBITS; 1191 sh->flags = SHF_ALLOC; 1192 sh->addralign = 1; 1193 if(interpreter == nil) { 1194 switch(HEADTYPE) { 1195 case Hlinux: 1196 interpreter = linuxdynld; 1197 break; 1198 case Hfreebsd: 1199 interpreter = freebsddynld; 1200 break; 1201 case Hnetbsd: 1202 interpreter = netbsddynld; 1203 break; 1204 case Hopenbsd: 1205 interpreter = openbsddynld; 1206 break; 1207 case Hdragonfly: 1208 interpreter = dragonflydynld; 1209 break; 1210 case Hsolaris: 1211 interpreter = solarisdynld; 1212 break; 1213 } 1214 } 1215 resoff -= elfinterp(sh, startva, resoff, interpreter); 1216 1217 ph = newElfPhdr(); 1218 ph->type = PT_INTERP; 1219 ph->flags = PF_R; 1220 phsh(ph, sh); 1221 } 1222 1223 pnote = nil; 1224 if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) { 1225 sh = nil; 1226 switch(HEADTYPE) { 1227 case Hnetbsd: 1228 sh = elfshname(".note.netbsd.ident"); 1229 resoff -= elfnetbsdsig(sh, startva, resoff); 1230 break; 1231 case Hopenbsd: 1232 sh = elfshname(".note.openbsd.ident"); 1233 resoff -= elfopenbsdsig(sh, startva, resoff); 1234 break; 1235 } 1236 1237 pnote = newElfPhdr(); 1238 pnote->type = PT_NOTE; 1239 pnote->flags = PF_R; 1240 phsh(pnote, sh); 1241 } 1242 1243 if(buildinfolen > 0) { 1244 sh = elfshname(".note.gnu.build-id"); 1245 resoff -= elfbuildinfo(sh, startva, resoff); 1246 1247 if(pnote == nil) { 1248 pnote = newElfPhdr(); 1249 pnote->type = PT_NOTE; 1250 pnote->flags = PF_R; 1251 } 1252 phsh(pnote, sh); 1253 } 1254 1255 // Additions to the reserved area must be above this line. 1256 USED(resoff); 1257 1258 elfphload(&segtext); 1259 if(segrodata.sect != nil) 1260 elfphload(&segrodata); 1261 elfphload(&segdata); 1262 1263 /* Dynamic linking sections */ 1264 if(!debug['d']) { /* -d suppresses dynamic loader format */ 1265 sh = elfshname(".dynsym"); 1266 sh->type = SHT_DYNSYM; 1267 sh->flags = SHF_ALLOC; 1268 if(elf64) 1269 sh->entsize = ELF64SYMSIZE; 1270 else 1271 sh->entsize = ELF32SYMSIZE; 1272 sh->addralign = RegSize; 1273 sh->link = elfshname(".dynstr")->shnum; 1274 // sh->info = index of first non-local symbol (number of local symbols) 1275 shsym(sh, linklookup(ctxt, ".dynsym", 0)); 1276 1277 sh = elfshname(".dynstr"); 1278 sh->type = SHT_STRTAB; 1279 sh->flags = SHF_ALLOC; 1280 sh->addralign = 1; 1281 shsym(sh, linklookup(ctxt, ".dynstr", 0)); 1282 1283 if(elfverneed) { 1284 sh = elfshname(".gnu.version"); 1285 sh->type = SHT_GNU_VERSYM; 1286 sh->flags = SHF_ALLOC; 1287 sh->addralign = 2; 1288 sh->link = elfshname(".dynsym")->shnum; 1289 sh->entsize = 2; 1290 shsym(sh, linklookup(ctxt, ".gnu.version", 0)); 1291 1292 sh = elfshname(".gnu.version_r"); 1293 sh->type = SHT_GNU_VERNEED; 1294 sh->flags = SHF_ALLOC; 1295 sh->addralign = RegSize; 1296 sh->info = elfverneed; 1297 sh->link = elfshname(".dynstr")->shnum; 1298 shsym(sh, linklookup(ctxt, ".gnu.version_r", 0)); 1299 } 1300 1301 switch(eh->machine) { 1302 case EM_X86_64: 1303 sh = elfshname(".rela.plt"); 1304 sh->type = SHT_RELA; 1305 sh->flags = SHF_ALLOC; 1306 sh->entsize = ELF64RELASIZE; 1307 sh->addralign = RegSize; 1308 sh->link = elfshname(".dynsym")->shnum; 1309 sh->info = elfshname(".plt")->shnum; 1310 shsym(sh, linklookup(ctxt, ".rela.plt", 0)); 1311 1312 sh = elfshname(".rela"); 1313 sh->type = SHT_RELA; 1314 sh->flags = SHF_ALLOC; 1315 sh->entsize = ELF64RELASIZE; 1316 sh->addralign = 8; 1317 sh->link = elfshname(".dynsym")->shnum; 1318 shsym(sh, linklookup(ctxt, ".rela", 0)); 1319 break; 1320 1321 default: 1322 sh = elfshname(".rel.plt"); 1323 sh->type = SHT_REL; 1324 sh->flags = SHF_ALLOC; 1325 sh->entsize = ELF32RELSIZE; 1326 sh->link = elfshname(".dynsym")->shnum; 1327 shsym(sh, linklookup(ctxt, ".rel.plt", 0)); 1328 1329 sh = elfshname(".rel"); 1330 sh->type = SHT_REL; 1331 sh->flags = SHF_ALLOC; 1332 sh->entsize = ELF32RELSIZE; 1333 sh->addralign = 4; 1334 sh->link = elfshname(".dynsym")->shnum; 1335 shsym(sh, linklookup(ctxt, ".rel", 0)); 1336 break; 1337 } 1338 1339 sh = elfshname(".plt"); 1340 sh->type = SHT_PROGBITS; 1341 sh->flags = SHF_ALLOC+SHF_EXECINSTR; 1342 if(eh->machine == EM_X86_64) 1343 sh->entsize = 16; 1344 else 1345 sh->entsize = 4; 1346 sh->addralign = 4; 1347 shsym(sh, linklookup(ctxt, ".plt", 0)); 1348 1349 sh = elfshname(".got"); 1350 sh->type = SHT_PROGBITS; 1351 sh->flags = SHF_ALLOC+SHF_WRITE; 1352 sh->entsize = RegSize; 1353 sh->addralign = RegSize; 1354 shsym(sh, linklookup(ctxt, ".got", 0)); 1355 1356 sh = elfshname(".got.plt"); 1357 sh->type = SHT_PROGBITS; 1358 sh->flags = SHF_ALLOC+SHF_WRITE; 1359 sh->entsize = RegSize; 1360 sh->addralign = RegSize; 1361 shsym(sh, linklookup(ctxt, ".got.plt", 0)); 1362 1363 sh = elfshname(".hash"); 1364 sh->type = SHT_HASH; 1365 sh->flags = SHF_ALLOC; 1366 sh->entsize = 4; 1367 sh->addralign = RegSize; 1368 sh->link = elfshname(".dynsym")->shnum; 1369 shsym(sh, linklookup(ctxt, ".hash", 0)); 1370 1371 /* sh and PT_DYNAMIC for .dynamic section */ 1372 sh = elfshname(".dynamic"); 1373 sh->type = SHT_DYNAMIC; 1374 sh->flags = SHF_ALLOC+SHF_WRITE; 1375 sh->entsize = 2*RegSize; 1376 sh->addralign = RegSize; 1377 sh->link = elfshname(".dynstr")->shnum; 1378 shsym(sh, linklookup(ctxt, ".dynamic", 0)); 1379 ph = newElfPhdr(); 1380 ph->type = PT_DYNAMIC; 1381 ph->flags = PF_R + PF_W; 1382 phsh(ph, sh); 1383 1384 /* 1385 * Thread-local storage segment (really just size). 1386 */ 1387 // Do not emit PT_TLS for OpenBSD since ld.so(1) does 1388 // not currently support it. This is handled 1389 // appropriately in runtime/cgo. 1390 if(ctxt->tlsoffset != 0 && HEADTYPE != Hopenbsd) { 1391 ph = newElfPhdr(); 1392 ph->type = PT_TLS; 1393 ph->flags = PF_R; 1394 ph->memsz = -ctxt->tlsoffset; 1395 ph->align = RegSize; 1396 } 1397 } 1398 1399 if(HEADTYPE == Hlinux) { 1400 ph = newElfPhdr(); 1401 ph->type = PT_GNU_STACK; 1402 ph->flags = PF_W+PF_R; 1403 ph->align = RegSize; 1404 1405 ph = newElfPhdr(); 1406 ph->type = PT_PAX_FLAGS; 1407 ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled 1408 ph->align = RegSize; 1409 } 1410 1411 elfobj: 1412 sh = elfshname(".shstrtab"); 1413 sh->type = SHT_STRTAB; 1414 sh->addralign = 1; 1415 shsym(sh, linklookup(ctxt, ".shstrtab", 0)); 1416 eh->shstrndx = sh->shnum; 1417 1418 // put these sections early in the list 1419 if(!debug['s']) { 1420 elfshname(".symtab"); 1421 elfshname(".strtab"); 1422 } 1423 1424 for(sect=segtext.sect; sect!=nil; sect=sect->next) 1425 elfshbits(sect); 1426 for(sect=segrodata.sect; sect!=nil; sect=sect->next) 1427 elfshbits(sect); 1428 for(sect=segdata.sect; sect!=nil; sect=sect->next) 1429 elfshbits(sect); 1430 1431 if(linkmode == LinkExternal) { 1432 for(sect=segtext.sect; sect!=nil; sect=sect->next) 1433 elfshreloc(sect); 1434 for(sect=segrodata.sect; sect!=nil; sect=sect->next) 1435 elfshreloc(sect); 1436 for(sect=segdata.sect; sect!=nil; sect=sect->next) 1437 elfshreloc(sect); 1438 // add a .note.GNU-stack section to mark the stack as non-executable 1439 sh = elfshname(".note.GNU-stack"); 1440 sh->type = SHT_PROGBITS; 1441 sh->addralign = 1; 1442 sh->flags = 0; 1443 } 1444 1445 // generate .tbss section for dynamic internal linking (except for OpenBSD) 1446 // external linking generates .tbss in data.c 1447 if(linkmode == LinkInternal && !debug['d'] && HEADTYPE != Hopenbsd) { 1448 sh = elfshname(".tbss"); 1449 sh->type = SHT_NOBITS; 1450 sh->addralign = RegSize; 1451 sh->size = -ctxt->tlsoffset; 1452 sh->flags = SHF_ALLOC | SHF_TLS | SHF_WRITE; 1453 } 1454 1455 if(!debug['s']) { 1456 sh = elfshname(".symtab"); 1457 sh->type = SHT_SYMTAB; 1458 sh->off = symo; 1459 sh->size = symsize; 1460 sh->addralign = RegSize; 1461 sh->entsize = 8+2*RegSize; 1462 sh->link = elfshname(".strtab")->shnum; 1463 sh->info = elfglobalsymndx; 1464 1465 sh = elfshname(".strtab"); 1466 sh->type = SHT_STRTAB; 1467 sh->off = symo+symsize; 1468 sh->size = elfstrsize; 1469 sh->addralign = 1; 1470 1471 dwarfaddelfheaders(); 1472 } 1473 1474 /* Main header */ 1475 eh->ident[EI_MAG0] = '\177'; 1476 eh->ident[EI_MAG1] = 'E'; 1477 eh->ident[EI_MAG2] = 'L'; 1478 eh->ident[EI_MAG3] = 'F'; 1479 if(HEADTYPE == Hfreebsd) 1480 eh->ident[EI_OSABI] = ELFOSABI_FREEBSD; 1481 else if(HEADTYPE == Hnetbsd) 1482 eh->ident[EI_OSABI] = ELFOSABI_NETBSD; 1483 else if(HEADTYPE == Hopenbsd) 1484 eh->ident[EI_OSABI] = ELFOSABI_OPENBSD; 1485 else if(HEADTYPE == Hdragonfly) 1486 eh->ident[EI_OSABI] = ELFOSABI_NONE; 1487 if(elf64) 1488 eh->ident[EI_CLASS] = ELFCLASS64; 1489 else 1490 eh->ident[EI_CLASS] = ELFCLASS32; 1491 eh->ident[EI_DATA] = ELFDATA2LSB; 1492 eh->ident[EI_VERSION] = EV_CURRENT; 1493 1494 if(linkmode == LinkExternal) 1495 eh->type = ET_REL; 1496 else 1497 eh->type = ET_EXEC; 1498 1499 if(linkmode != LinkExternal) 1500 eh->entry = entryvalue(); 1501 1502 eh->version = EV_CURRENT; 1503 1504 if(pph != nil) { 1505 pph->filesz = eh->phnum * eh->phentsize; 1506 pph->memsz = pph->filesz; 1507 } 1508 1509 cseek(0); 1510 a = 0; 1511 a += elfwritehdr(); 1512 a += elfwritephdrs(); 1513 a += elfwriteshdrs(); 1514 if(!debug['d']) 1515 a += elfwriteinterp(); 1516 if(linkmode != LinkExternal) { 1517 if(HEADTYPE == Hnetbsd) 1518 a += elfwritenetbsdsig(); 1519 if(HEADTYPE == Hopenbsd) 1520 a += elfwriteopenbsdsig(); 1521 if(buildinfolen > 0) 1522 a += elfwritebuildinfo(); 1523 } 1524 if(a > ELFRESERVE) 1525 diag("ELFRESERVE too small: %lld > %d", a, ELFRESERVE); 1526 }