summaryrefslogtreecommitdiffstats
path: root/lld/ELF/InputFiles.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/InputFiles.cpp')
-rw-r--r--lld/ELF/InputFiles.cpp38
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;
}
- }
}
}
OpenPOWER on IntegriCloud