diff options
Diffstat (limited to 'src/cmd/ld/elf.c')
-rw-r--r-- | src/cmd/ld/elf.c | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c index daef5793f..6b3638ec5 100644 --- a/src/cmd/ld/elf.c +++ b/src/cmd/ld/elf.c @@ -864,6 +864,8 @@ elfemitreloc(void) elfrelocsect(segtext.sect, textp); for(sect=segtext.sect->next; sect!=nil; sect=sect->next) elfrelocsect(sect, datap); + for(sect=segrodata.sect; sect!=nil; sect=sect->next) + elfrelocsect(sect, datap); for(sect=segdata.sect; sect!=nil; sect=sect->next) elfrelocsect(sect, datap); } @@ -887,7 +889,12 @@ doelf(void) addstring(shstrtab, ".data"); addstring(shstrtab, ".bss"); addstring(shstrtab, ".noptrbss"); - if(linkmode == LinkExternal && HEADTYPE != Hopenbsd) + // generate .tbss section (except for OpenBSD where it's not supported) + // for dynamic internal linker or external linking, so that various + // binutils could correctly calculate PT_TLS size. + // see http://golang.org/issue/5200. + if(HEADTYPE != Hopenbsd) + if(!debug['d'] || linkmode == LinkExternal) addstring(shstrtab, ".tbss"); if(HEADTYPE == Hnetbsd) addstring(shstrtab, ".note.netbsd.ident"); @@ -898,14 +905,11 @@ doelf(void) addstring(shstrtab, ".elfdata"); addstring(shstrtab, ".rodata"); addstring(shstrtab, ".typelink"); - if(flag_shared) - addstring(shstrtab, ".data.rel.ro"); - addstring(shstrtab, ".gcdata"); - addstring(shstrtab, ".gcbss"); addstring(shstrtab, ".gosymtab"); addstring(shstrtab, ".gopclntab"); if(linkmode == LinkExternal) { + debug_s = debug['s']; debug['s'] = 0; debug['d'] = 1; @@ -913,8 +917,6 @@ doelf(void) addstring(shstrtab, ".rela.text"); addstring(shstrtab, ".rela.rodata"); addstring(shstrtab, ".rela.typelink"); - addstring(shstrtab, ".rela.gcdata"); - addstring(shstrtab, ".rela.gcbss"); addstring(shstrtab, ".rela.gosymtab"); addstring(shstrtab, ".rela.gopclntab"); addstring(shstrtab, ".rela.noptrdata"); @@ -923,8 +925,6 @@ doelf(void) addstring(shstrtab, ".rel.text"); addstring(shstrtab, ".rel.rodata"); addstring(shstrtab, ".rel.typelink"); - addstring(shstrtab, ".rel.gcdata"); - addstring(shstrtab, ".rel.gcbss"); addstring(shstrtab, ".rel.gosymtab"); addstring(shstrtab, ".rel.gopclntab"); addstring(shstrtab, ".rel.noptrdata"); @@ -934,6 +934,14 @@ doelf(void) addstring(shstrtab, ".note.GNU-stack"); } + if(flag_shared) { + addstring(shstrtab, ".init_array"); + if(thechar == '6') + addstring(shstrtab, ".rela.init_array"); + else + addstring(shstrtab, ".rel.init_array"); + } + if(!debug['s']) { addstring(shstrtab, ".symtab"); addstring(shstrtab, ".strtab"); @@ -1001,7 +1009,7 @@ doelf(void) s = lookup(".plt", 0); s->reachable = 1; - s->type = SELFROSECT; + s->type = SELFRXSECT; elfsetupplt(); @@ -1062,13 +1070,6 @@ doelf(void) elfwritedynent(s, DT_DEBUG, 0); - if(flag_shared) { - Sym *init_sym = lookup(LIBINITENTRY, 0); - if(init_sym->type != STEXT) - diag("entry not text: %s", init_sym->name); - elfwritedynentsym(s, DT_INIT, init_sym); - } - // Do not write DT_NULL. elfdynhash will finish it. } } @@ -1105,6 +1106,8 @@ asmbelfsetup(void) for(sect=segtext.sect; sect!=nil; sect=sect->next) elfshalloc(sect); + for(sect=segrodata.sect; sect!=nil; sect=sect->next) + elfshalloc(sect); for(sect=segdata.sect; sect!=nil; sect=sect->next) elfshalloc(sect); } @@ -1186,6 +1189,9 @@ asmbelf(vlong symo) case Hopenbsd: interpreter = openbsddynld; break; + case Hdragonfly: + interpreter = dragonflydynld; + break; } } resoff -= elfinterp(sh, startva, resoff, interpreter); @@ -1232,6 +1238,8 @@ asmbelf(vlong symo) USED(resoff); elfphload(&segtext); + if(segrodata.sect != nil) + elfphload(&segrodata); elfphload(&segdata); /* Dynamic linking sections */ @@ -1397,12 +1405,16 @@ elfobj: for(sect=segtext.sect; sect!=nil; sect=sect->next) elfshbits(sect); + for(sect=segrodata.sect; sect!=nil; sect=sect->next) + elfshbits(sect); for(sect=segdata.sect; sect!=nil; sect=sect->next) elfshbits(sect); if(linkmode == LinkExternal) { for(sect=segtext.sect; sect!=nil; sect=sect->next) elfshreloc(sect); + for(sect=segrodata.sect; sect!=nil; sect=sect->next) + elfshreloc(sect); for(sect=segdata.sect; sect!=nil; sect=sect->next) elfshreloc(sect); // add a .note.GNU-stack section to mark the stack as non-executable @@ -1412,6 +1424,16 @@ elfobj: sh->flags = 0; } + // generate .tbss section for dynamic internal linking (except for OpenBSD) + // external linking generates .tbss in data.c + if(linkmode == LinkInternal && !debug['d'] && HEADTYPE != Hopenbsd) { + sh = elfshname(".tbss"); + sh->type = SHT_NOBITS; + sh->addralign = PtrSize; + sh->size = -tlsoffset; + sh->flags = SHF_ALLOC | SHF_TLS | SHF_WRITE; + } + if(!debug['s']) { sh = elfshname(".symtab"); sh->type = SHT_SYMTAB; @@ -1442,6 +1464,8 @@ elfobj: eh->ident[EI_OSABI] = ELFOSABI_NETBSD; else if(HEADTYPE == Hopenbsd) eh->ident[EI_OSABI] = ELFOSABI_OPENBSD; + else if(HEADTYPE == Hdragonfly) + eh->ident[EI_OSABI] = ELFOSABI_NONE; if(PtrSize == 8) eh->ident[EI_CLASS] = ELFCLASS64; else @@ -1449,9 +1473,7 @@ elfobj: eh->ident[EI_DATA] = ELFDATA2LSB; eh->ident[EI_VERSION] = EV_CURRENT; - if(flag_shared) - eh->type = ET_DYN; - else if(linkmode == LinkExternal) + if(linkmode == LinkExternal) eh->type = ET_REL; else eh->type = ET_EXEC; |