diff options
Diffstat (limited to 'lld/ELF/InputFiles.cpp')
-rw-r--r-- | lld/ELF/InputFiles.cpp | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 9aa207b6f65..b2142b75523 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -121,6 +121,33 @@ ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) { } template <class ELFT> +static bool shouldMerge(const typename ELFFile<ELFT>::Elf_Shdr &Sec) { + typedef typename ELFFile<ELFT>::uintX_t uintX_t; + uintX_t Flags = Sec.sh_flags; + if (!(Flags & SHF_MERGE)) + return false; + if (Flags & SHF_WRITE) + error("Writable SHF_MERGE sections are not supported"); + uintX_t EntSize = Sec.sh_entsize; + if (Sec.sh_size % EntSize) + error("SHF_MERGE section size must be a multiple of sh_entsize"); + + // Don't try to merge if the aligment is larger than the sh_entsize. + // + // If this is not a SHF_STRINGS, we would need to pad after every entity. It + // would be equivalent for the producer of the .o to just set a larger + // sh_entsize. + // + // If this is a SHF_STRINGS, the larger alignment makes sense. Unfortunately + // it would complicate tail merging. This doesn't seem that common to + // justify the effort. + if (Sec.sh_addralign > EntSize) + return false; + + return true; +} + +template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &Comdats) { uint64_t Size = this->ELFObj.getNumSections(); Sections.resize(Size); @@ -170,18 +197,13 @@ void elf2::ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &Comdats) { error("Relocations pointing to SHF_MERGE are not supported"); break; } - default: { - uintX_t Flags = Sec.sh_flags; - if (Flags & SHF_MERGE && !(Flags & SHF_STRINGS)) { - if (Flags & SHF_WRITE) - error("Writable SHF_MERGE sections are not supported"); + default: + if (shouldMerge<ELFT>(Sec)) Sections[I] = new (this->Alloc) MergeInputSection<ELFT>(this, &Sec); - } else { + else Sections[I] = new (this->Alloc) InputSection<ELFT>(this, &Sec); - } break; } - } } } |