diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:33:45 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:33:45 +0000 |
commit | 4ea16835ba66f2240d050ffcaee44cee6c97cab9 (patch) | |
tree | d2f3d66f3352a3ec22362de0b7a5c1366fc25df8 /ELF/Writer.cpp | |
parent | 15f7a1a3796209b21af2817fdf11ca9932165c70 (diff) |
Notes
Diffstat (limited to 'ELF/Writer.cpp')
-rw-r--r-- | ELF/Writer.cpp | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index 4ff06388ec780..4c12b18836bf6 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -87,6 +87,8 @@ private: uint64_t FileSize; uint64_t SectionHeaderOff; + + bool HasGotBaseSym = false; }; } // anonymous namespace @@ -815,19 +817,13 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() { Symtab<ELFT>::X->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL); } - // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol - // is magical and is used to produce a R_386_GOTPC relocation. - // The R_386_GOTPC relocation value doesn't actually depend on the - // symbol value, so it could use an index of STN_UNDEF which, according - // to the spec, means the symbol value is 0. - // Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in - // the object file. - // The situation is even stranger on x86_64 where the assembly doesn't - // need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as - // an undefined symbol in the .o files. - // Given that the symbol is effectively unused, we just create a dummy - // hidden one to avoid the undefined symbol error. - Symtab<ELFT>::X->addIgnored("_GLOBAL_OFFSET_TABLE_"); + // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to + // be at some offset from the base of the .got section, usually 0 or the end + // of the .got + InputSection *GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot) + : cast<InputSection>(InX::Got); + ElfSym::GlobalOffsetTable = addOptionalRegular<ELFT>( + "_GLOBAL_OFFSET_TABLE_", GotSection, Target->GotBaseSymOff); // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For // static linking the linker is required to optimize away any references to @@ -1147,6 +1143,8 @@ static void removeUnusedSyntheticSections(std::vector<OutputSection *> &V) { OutputSection *OS = SS->getParent(); if (!SS->empty() || !OS) continue; + if ((SS == InX::Got || SS == InX::MipsGot) && ElfSym::GlobalOffsetTable) + continue; OS->Sections.erase(std::find(OS->Sections.begin(), OS->Sections.end(), SS)); SS->Live = false; // If there are no other sections in the output section, remove it from the @@ -1231,6 +1229,13 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) OutputSectionCommands.push_back(Cmd); + // Prefer command line supplied address over other constraints. + for (OutputSectionCommand *Cmd : OutputSectionCommands) { + auto I = Config->SectionStartMap.find(Cmd->Name); + if (I != Config->SectionStartMap.end()) + Cmd->AddrExpr = [=] { return I->second; }; + } + // This is a bit of a hack. A value of 0 means undef, so we set it // to 1 t make __ehdr_start defined. The section number is not // particularly relevant. |