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