summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter')
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt1
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.cpp74
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h25
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp2
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h17
5 files changed, 119 insertions, 0 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
index 9101ac1b8a8..0b0d4b1dddf 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
+++ b/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
@@ -1,4 +1,5 @@
add_lld_library(lldMipsELFTarget
+ MipsCtorsOrderPass.cpp
MipsLinkingContext.cpp
MipsRelocationHandler.cpp
MipsRelocationPass.cpp
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.cpp
new file mode 100644
index 00000000000..0a3973afde4
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.cpp
@@ -0,0 +1,74 @@
+//===- lib/ReaderWriter/ELF/Mips/Mips/CtorsOrderPass.cpp ------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsCtorsOrderPass.h"
+
+#include <algorithm>
+#include <climits>
+
+using namespace lld;
+using namespace lld::elf;
+
+static bool matchCrtObjName(StringRef objName, StringRef objPath) {
+ if (!objPath.endswith(".o"))
+ return false;
+
+ // check *<objName> case
+ objPath = objPath.drop_back(2);
+ if (objPath.endswith(objName))
+ return true;
+
+ // check *<objName>? case
+ return !objPath.empty() && objPath.drop_back(1).endswith(objName);
+}
+
+static int32_t getSectionPriority(StringRef path, StringRef sectionName) {
+ // Arrange .ctors/.dtors sections in the following order:
+ // .ctors from crtbegin.o or crtbegin?.o
+ // .ctors from regular object files
+ // .ctors.* (sorted) from regular object files
+ // .ctors from crtend.o or crtend?.o
+
+ if (matchCrtObjName("crtbegin", path))
+ return std::numeric_limits<int32_t>::min();
+ if (matchCrtObjName("crtend", path))
+ return std::numeric_limits<int32_t>::max();
+
+ StringRef num = sectionName.drop_front().rsplit('.').second;
+
+ int32_t priority = std::numeric_limits<int32_t>::min() + 1;
+ if (!num.empty())
+ num.getAsInteger(10, priority);
+
+ return priority;
+}
+
+void MipsCtorsOrderPass::perform(std::unique_ptr<MutableFile> &f) {
+ auto definedAtoms = f->definedAtoms();
+
+ auto last = std::stable_partition(definedAtoms.begin(), definedAtoms.end(),
+ [](const DefinedAtom *atom) {
+ if (atom->sectionChoice() != DefinedAtom::sectionCustomRequired)
+ return false;
+
+ StringRef name = atom->customSectionName();
+ return name.startswith(".ctors") || name.startswith(".dtors");
+ });
+
+ std::stable_sort(definedAtoms.begin(), last,
+ [](const DefinedAtom *left, const DefinedAtom *right) {
+ StringRef leftSec = left->customSectionName();
+ StringRef rightSec = right->customSectionName();
+
+ int32_t leftPriority = getSectionPriority(left->file().path(), leftSec);
+ int32_t rightPriority = getSectionPriority(right->file().path(), rightSec);
+
+ return leftPriority < rightPriority;
+ });
+}
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h b/lld/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h
new file mode 100644
index 00000000000..eeb1a194f9c
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h
@@ -0,0 +1,25 @@
+//===- lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h ---------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_CTORS_ORDER_PASS_H
+#define LLD_READER_WRITER_ELF_MIPS_MIPS_CTORS_ORDER_PASS_H
+
+#include "lld/Core/Pass.h"
+
+namespace lld {
+namespace elf {
+/// \brief This pass sorts atoms in .{ctors,dtors}.<priority> sections.
+class MipsCtorsOrderPass : public Pass {
+public:
+ void perform(std::unique_ptr<MutableFile> &mergedFile) override;
+};
+}
+}
+
+#endif
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
index b4f73ed6459..9e0e81d3534 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "Atoms.h"
+#include "MipsCtorsOrderPass.h"
#include "MipsLinkingContext.h"
#include "MipsRelocationPass.h"
#include "MipsTargetHandler.h"
@@ -44,6 +45,7 @@ void MipsLinkingContext::addPasses(PassManager &pm) {
if (pass)
pm.add(std::move(pass));
ELFLinkingContext::addPasses(pm);
+ pm.add(std::unique_ptr<Pass>(new elf::MipsCtorsOrderPass()));
}
bool MipsLinkingContext::isDynamicRelocation(const DefinedAtom &,
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
index b2eb496a8c5..fb5fbddff12 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
@@ -43,6 +43,23 @@ public:
order);
}
+ StringRef getSectionName(const DefinedAtom *da) const override {
+ return llvm::StringSwitch<StringRef>(da->customSectionName())
+ .StartsWith(".ctors", ".ctors")
+ .StartsWith(".dtors", ".dtors")
+ .Default(TargetLayout<ELFType>::getSectionName(da));
+ }
+
+ Layout::SegmentType getSegmentType(Section<ELFType> *section) const override {
+ switch (section->order()) {
+ case DefaultLayout<ELFType>::ORDER_CTORS:
+ case DefaultLayout<ELFType>::ORDER_DTORS:
+ return llvm::ELF::PT_LOAD;
+ default:
+ return TargetLayout<ELFType>::getSegmentType(section);
+ }
+ }
+
/// \brief GP offset relative to .got section.
uint64_t getGPOffset() const { return 0x7FF0; }
OpenPOWER on IntegriCloud