aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/LinkerScript.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/LinkerScript.cpp')
-rw-r--r--lld/ELF/LinkerScript.cpp33
1 files changed, 32 insertions, 1 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index b7f71944..50f2d50 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -215,11 +215,42 @@ template <class ELFT> void LinkerScript<ELFT>::createAssignments() {
}
template <class ELFT>
+static SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
+ StringRef OutsecName) {
+ // When using linker script the merge rules are different.
+ // Unfortunately, linker scripts are name based. This means that expressions
+ // like *(.foo*) can refer to multiple input sections that would normally be
+ // placed in different output sections. We cannot put them in different
+ // output sections or we would produce wrong results for
+ // start = .; *(.foo.*) end = .; *(.bar)
+ // and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to
+ // another. The problem is that there is no way to layout those output
+ // sections such that the .foo sections are the only thing between the
+ // start and end symbols.
+
+ // An extra annoyance is that we cannot simply disable merging of the contents
+ // of SHF_MERGE sections, but our implementation requires one output section
+ // per "kind" (string or not, which size/aligment).
+ // Fortunately, creating symbols in the middle of a merge section is not
+ // supported by bfd or gold, so we can just create multiple section in that
+ // case.
+ const typename ELFT::Shdr *H = C->getSectionHdr();
+ typedef typename ELFT::uint uintX_t;
+ uintX_t Flags = H->sh_flags & (SHF_MERGE | SHF_STRINGS);
+
+ uintX_t Alignment = 0;
+ if (isa<MergeInputSection<ELFT>>(C))
+ Alignment = std::max(H->sh_addralign, H->sh_entsize);
+
+ return SectionKey<ELFT::Is64Bits>{OutsecName, /*Type*/ 0, Flags, Alignment};
+}
+
+template <class ELFT>
void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
auto AddSec = [&](InputSectionBase<ELFT> *Sec, StringRef Name) {
OutputSectionBase<ELFT> *OutSec;
bool IsNew;
- std::tie(OutSec, IsNew) = Factory.create(Sec, Name);
+ std::tie(OutSec, IsNew) = Factory.create(createKey(Sec, Name), Sec);
if (IsNew)
OutputSections->push_back(OutSec);
return OutSec;