summaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/PECOFF/OrderPass.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/PECOFF/OrderPass.h')
-rw-r--r--lib/ReaderWriter/PECOFF/OrderPass.h67
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/ReaderWriter/PECOFF/OrderPass.h b/lib/ReaderWriter/PECOFF/OrderPass.h
new file mode 100644
index 000000000000..73133ff73638
--- /dev/null
+++ b/lib/ReaderWriter/PECOFF/OrderPass.h
@@ -0,0 +1,67 @@
+//===- lib/ReaderWriter/PECOFF/OrderPass.h -------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file \brief This pass sorts atoms by section name, so that they will appear
+/// in the correct order in the output.
+///
+/// In COFF, sections will be merged into one section by the linker if their
+/// names are the same after discarding the "$" character and all characters
+/// follow it from their names. The characters following the "$" character
+/// determines the merge order. Assume there's an object file containing four
+/// data sections in the following order.
+///
+/// - .data$2
+/// - .data$3
+/// - .data$1
+/// - .data
+///
+/// In this case, the resulting binary should have ".data" section with the
+/// contents of ".data", ".data$1", ".data$2" and ".data$3" in that order.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_PE_COFF_ORDER_PASS_H
+#define LLD_READER_WRITER_PE_COFF_ORDER_PASS_H
+
+#include "Atoms.h"
+#include "lld/Core/Parallel.h"
+#include "lld/Core/Pass.h"
+#include <algorithm>
+
+namespace lld {
+namespace pecoff {
+
+static bool compare(const DefinedAtom *lhs, const DefinedAtom *rhs) {
+ bool lhsCustom = (lhs->sectionChoice() == DefinedAtom::sectionCustomRequired);
+ bool rhsCustom = (rhs->sectionChoice() == DefinedAtom::sectionCustomRequired);
+ if (lhsCustom && rhsCustom) {
+ int cmp = lhs->customSectionName().compare(rhs->customSectionName());
+ if (cmp != 0)
+ return cmp < 0;
+ return DefinedAtom::compareByPosition(lhs, rhs);
+ }
+ if (lhsCustom && !rhsCustom)
+ return true;
+ if (!lhsCustom && rhsCustom)
+ return false;
+ return DefinedAtom::compareByPosition(lhs, rhs);
+}
+
+class OrderPass : public lld::Pass {
+public:
+ void perform(std::unique_ptr<MutableFile> &file) override {
+ MutableFile::DefinedAtomRange defined = file->definedAtoms();
+ parallel_sort(defined.begin(), defined.end(), compare);
+ }
+};
+
+} // namespace pecoff
+} // namespace lld
+
+#endif