diff options
Diffstat (limited to 'lib/ReaderWriter/PECOFF/OrderPass.h')
-rw-r--r-- | lib/ReaderWriter/PECOFF/OrderPass.h | 67 |
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 |