492
569
/* size of object */
570
adduint64(d, s->size);
495
if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) {
572
if(!(s->cgoexport & CgoExportDynamic) && s->dynimplib && needlib(s->dynimplib)) {
496
573
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED,
497
574
addstring(lookup(".dynstr", 0), s->dynimplib));
499
576
} else if(HEADTYPE == Hdarwin) {
500
// Mach-o symbol nlist64
501
d = lookup(".dynsym", 0);
502
name = s->dynimpname;
505
s->dynid = d->size/16;
506
// darwin still puts _ prefixes on all C symbols
507
str = lookup(".dynstr", 0);
508
adduint32(d, str->size);
510
addstring(str, name);
511
if(s->type == SDYNIMPORT) {
512
adduint8(d, 0x01); // type - N_EXT - external symbol
513
adduint8(d, 0); // section
529
adduint16(d, 0); // desc
530
if(s->type == SDYNIMPORT)
531
adduint64(d, 0); // value
534
} else if(HEADTYPE != Hwindows) {
577
diag("adddynsym: missed symbol %s (%s)", s->name, s->extname);
578
} else if(HEADTYPE == Hwindows) {
579
// already taken care of
535
581
diag("adddynsym: unsupported binary format");
562
Sym *s, *shstrtab, *dynstr;
564
if(HEADTYPE != Hlinux && HEADTYPE != Hfreebsd && HEADTYPE != Hopenbsd && HEADTYPE != Hnetbsd)
567
/* predefine strings we need for section headers */
568
shstrtab = lookup(".shstrtab", 0);
569
shstrtab->type = SELFROSECT;
570
shstrtab->reachable = 1;
572
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
573
elfstr[ElfStrText] = addstring(shstrtab, ".text");
574
elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata");
575
elfstr[ElfStrData] = addstring(shstrtab, ".data");
576
elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
577
elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
578
if(HEADTYPE == Hnetbsd)
579
elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
580
addstring(shstrtab, ".elfdata");
581
addstring(shstrtab, ".rodata");
582
addstring(shstrtab, ".gosymtab");
583
addstring(shstrtab, ".gopclntab");
585
elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
586
elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
587
dwarfaddshstrings(shstrtab);
589
elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
591
if(!debug['d']) { /* -d suppresses dynamic loader format */
592
elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
593
elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
594
elfstr[ElfStrGot] = addstring(shstrtab, ".got");
595
elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
596
elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
597
elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
598
elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
599
elfstr[ElfStrRela] = addstring(shstrtab, ".rela");
600
elfstr[ElfStrRelaPlt] = addstring(shstrtab, ".rela.plt");
601
elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
602
elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
603
elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
605
/* dynamic symbol table - first entry all zeros */
606
s = lookup(".dynsym", 0);
607
s->type = SELFROSECT;
609
s->size += ELF64SYMSIZE;
611
/* dynamic string table */
612
s = lookup(".dynstr", 0);
613
s->type = SELFROSECT;
619
/* relocation table */
620
s = lookup(".rela", 0);
622
s->type = SELFROSECT;
624
/* global offset table */
625
s = lookup(".got", 0);
627
s->type = SELFSECT; // writable
630
s = lookup(".hash", 0);
632
s->type = SELFROSECT;
634
s = lookup(".got.plt", 0);
636
s->type = SELFSECT; // writable
638
s = lookup(".plt", 0);
640
s->type = SELFROSECT;
644
s = lookup(".rela.plt", 0);
646
s->type = SELFROSECT;
648
s = lookup(".gnu.version", 0);
650
s->type = SELFROSECT;
652
s = lookup(".gnu.version_r", 0);
654
s->type = SELFROSECT;
656
/* define dynamic elf table */
657
s = lookup(".dynamic", 0);
659
s->type = SELFSECT; // writable
664
elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
665
elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
666
elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
667
elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
668
elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
669
elfwritedynentsym(s, DT_RELA, lookup(".rela", 0));
670
elfwritedynentsymsize(s, DT_RELASZ, lookup(".rela", 0));
671
elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
673
elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
675
elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
676
elfwritedynent(s, DT_PLTREL, DT_RELA);
677
elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0));
678
elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0));
680
elfwritedynent(s, DT_DEBUG, 0);
682
// Do not write DT_NULL. elfdynhash will finish it.
687
shsym(ElfShdr *sh, Sym *s)
691
if(sh->flags&SHF_ALLOC)
693
sh->off = datoff(addr);
698
phsh(ElfPhdr *ph, ElfShdr *sh)
700
ph->vaddr = sh->addr;
701
ph->paddr = ph->vaddr;
703
ph->filesz = sh->size;
704
ph->memsz = sh->size;
705
ph->align = sh->addralign;
713
vlong vl, startva, symo, dwarfoff, machlink, resoff;
610
vlong vl, symo, dwarfoff, machlink;
721
615
Bprint(&bso, "%5.2f asmb\n", cputime());
727
619
Bprint(&bso, "%5.2f codeblk\n", cputime());
730
625
sect = segtext.sect;
731
626
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
732
627
codeblk(sect->vaddr, sect->len);
734
/* output read-only data in text segment (rodata, gosymtab and pclntab) */
629
/* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
735
630
for(sect = sect->next; sect != nil; sect = sect->next) {
736
631
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
737
632
datblk(sect->vaddr, sect->len);
886
startva = INITTEXT - HEADR;
889
/* This null SHdr must appear before all others */
890
newElfShdr(elfstr[ElfStrEmpty]);
892
/* program header info */
895
pph->flags = PF_R + PF_X;
896
pph->off = eh->ehsize;
897
pph->vaddr = INITTEXT - HEADR + pph->off;
898
pph->paddr = INITTEXT - HEADR + pph->off;
899
pph->align = INITRND;
902
* PHDR must be in a loaded segment. Adjust the text
903
* segment boundaries downwards to include it.
905
o = segtext.vaddr - pph->vaddr;
908
o = segtext.fileoff - pph->off;
909
segtext.fileoff -= o;
910
segtext.filelen += o;
914
sh = newElfShdr(elfstr[ElfStrInterp]);
915
sh->type = SHT_PROGBITS;
916
sh->flags = SHF_ALLOC;
918
if(interpreter == nil) {
921
interpreter = linuxdynld;
924
interpreter = freebsddynld;
927
interpreter = netbsddynld;
930
interpreter = openbsddynld;
934
resoff -= elfinterp(sh, startva, resoff, interpreter);
937
ph->type = PT_INTERP;
942
if(HEADTYPE == Hnetbsd) {
943
sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
945
sh->flags = SHF_ALLOC;
947
resoff -= elfnetbsdsig(sh, startva, resoff);
958
/* Dynamic linking sections */
959
if(!debug['d']) { /* -d suppresses dynamic loader format */
960
/* S headers for dynamic linking */
961
sh = newElfShdr(elfstr[ElfStrGot]);
962
sh->type = SHT_PROGBITS;
963
sh->flags = SHF_ALLOC+SHF_WRITE;
966
shsym(sh, lookup(".got", 0));
968
sh = newElfShdr(elfstr[ElfStrGotPlt]);
969
sh->type = SHT_PROGBITS;
970
sh->flags = SHF_ALLOC+SHF_WRITE;
973
shsym(sh, lookup(".got.plt", 0));
976
sh = newElfShdr(elfstr[ElfStrDynsym]);
977
sh->type = SHT_DYNSYM;
978
sh->flags = SHF_ALLOC;
979
sh->entsize = ELF64SYMSIZE;
981
sh->link = dynsym+1; // dynstr
982
// sh->info = index of first non-local symbol (number of local symbols)
983
shsym(sh, lookup(".dynsym", 0));
985
sh = newElfShdr(elfstr[ElfStrDynstr]);
986
sh->type = SHT_STRTAB;
987
sh->flags = SHF_ALLOC;
989
shsym(sh, lookup(".dynstr", 0));
992
sh = newElfShdr(elfstr[ElfStrGnuVersion]);
993
sh->type = SHT_GNU_VERSYM;
994
sh->flags = SHF_ALLOC;
998
shsym(sh, lookup(".gnu.version", 0));
1000
sh = newElfShdr(elfstr[ElfStrGnuVersionR]);
1001
sh->type = SHT_GNU_VERNEED;
1002
sh->flags = SHF_ALLOC;
1004
sh->info = elfverneed;
1005
sh->link = dynsym+1; // dynstr
1006
shsym(sh, lookup(".gnu.version_r", 0));
1009
sh = newElfShdr(elfstr[ElfStrRelaPlt]);
1010
sh->type = SHT_RELA;
1011
sh->flags = SHF_ALLOC;
1012
sh->entsize = ELF64RELASIZE;
1015
sh->info = eh->shnum; // .plt
1016
shsym(sh, lookup(".rela.plt", 0));
1018
sh = newElfShdr(elfstr[ElfStrPlt]);
1019
sh->type = SHT_PROGBITS;
1020
sh->flags = SHF_ALLOC+SHF_EXECINSTR;
1023
shsym(sh, lookup(".plt", 0));
1025
sh = newElfShdr(elfstr[ElfStrHash]);
1026
sh->type = SHT_HASH;
1027
sh->flags = SHF_ALLOC;
1031
shsym(sh, lookup(".hash", 0));
1033
sh = newElfShdr(elfstr[ElfStrRela]);
1034
sh->type = SHT_RELA;
1035
sh->flags = SHF_ALLOC;
1036
sh->entsize = ELF64RELASIZE;
1039
shsym(sh, lookup(".rela", 0));
1041
/* sh and PT_DYNAMIC for .dynamic section */
1042
sh = newElfShdr(elfstr[ElfStrDynamic]);
1043
sh->type = SHT_DYNAMIC;
1044
sh->flags = SHF_ALLOC+SHF_WRITE;
1047
sh->link = dynsym+1; // dynstr
1048
shsym(sh, lookup(".dynamic", 0));
1050
ph->type = PT_DYNAMIC;
1051
ph->flags = PF_R + PF_W;
1055
* Thread-local storage segment (really just size).
1057
if(tlsoffset != 0) {
1061
ph->memsz = -tlsoffset;
1067
ph->type = PT_GNU_STACK;
1068
ph->flags = PF_W+PF_R;
1071
sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
1072
sh->type = SHT_STRTAB;
1074
shsym(sh, lookup(".shstrtab", 0));
1076
if(elftextsh != eh->shnum)
1077
diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
1078
for(sect=segtext.sect; sect!=nil; sect=sect->next)
1080
for(sect=segdata.sect; sect!=nil; sect=sect->next)
1084
sh = newElfShdr(elfstr[ElfStrSymtab]);
1085
sh->type = SHT_SYMTAB;
1090
sh->link = eh->shnum; // link to strtab
1092
sh = newElfShdr(elfstr[ElfStrStrtab]);
1093
sh->type = SHT_STRTAB;
1094
sh->off = symo+symsize;
1095
sh->size = elfstrsize;
1098
dwarfaddelfheaders();
1102
eh->ident[EI_MAG0] = '\177';
1103
eh->ident[EI_MAG1] = 'E';
1104
eh->ident[EI_MAG2] = 'L';
1105
eh->ident[EI_MAG3] = 'F';
1106
if(HEADTYPE == Hfreebsd)
1107
eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
1108
else if(HEADTYPE == Hnetbsd)
1109
eh->ident[EI_OSABI] = ELFOSABI_NETBSD;
1110
else if(HEADTYPE == Hopenbsd)
1111
eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
1112
eh->ident[EI_CLASS] = ELFCLASS64;
1113
eh->ident[EI_DATA] = ELFDATA2LSB;
1114
eh->ident[EI_VERSION] = EV_CURRENT;
1117
eh->machine = EM_X86_64;
1118
eh->version = EV_CURRENT;
1119
eh->entry = entryvalue();
1121
pph->filesz = eh->phnum * eh->phentsize;
1122
pph->memsz = pph->filesz;
1127
a += elfwritephdrs();
1128
a += elfwriteshdrs();
1129
a += elfwriteinterp(elfstr[ElfStrInterp]);
1130
if(HEADTYPE == Hnetbsd)
1131
a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
1133
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
1158
genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
1163
s = lookup("etext", 0);
1164
if(s->type == STEXT)
1165
put(s, s->name, 'T', s->value, s->size, s->version, 0);
1167
for(s=allsym; s!=S; s=s->allsym) {
1170
switch(s->type&~SSUB) {
1185
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
1193
diag("%s should not be bss (size=%d type=%d special=%d)", s->name, (int)s->np, s->type, s->special);
1194
put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
1198
put(nil, s->name, 'f', s->value, 0, s->version, 0);
1203
for(s = textp; s != nil; s = s->next) {
1207
/* filenames first */
1208
for(a=s->autom; a; a=a->link)
1209
if(a->type == D_FILE)
1210
put(nil, a->asym->name, 'z', a->aoffset, 0, 0, 0);
1212
if(a->type == D_FILE1)
1213
put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
1215
put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
1217
/* frame, auto and param after */
1218
put(nil, ".frame", 'm', s->text->to.offset+8, 0, 0, 0);
1220
for(a=s->autom; a; a=a->link)
1221
if(a->type == D_AUTO)
1222
put(nil, a->asym->name, 'a', -a->aoffset, 0, 0, a->gotype);
1224
if(a->type == D_PARAM)
1225
put(nil, a->asym->name, 'p', a->aoffset, 0, 0, a->gotype);
1227
if(debug['v'] || debug['n'])
1228
Bprint(&bso, "symsize = %ud\n", symsize);