//===------ lib/ReaderWriter/MachO/LayoutPass.h - Handles Layout of atoms -===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_READER_WRITER_MACHO_LAYOUT_PASS_H #define LLD_READER_WRITER_MACHO_LAYOUT_PASS_H #include "lld/Core/File.h" #include "lld/Core/Pass.h" #include "lld/Core/Reader.h" #include "lld/Core/Simple.h" #include "llvm/ADT/DenseMap.h" #include #include #include namespace lld { class DefinedAtom; class SimpleFile; namespace mach_o { /// This linker pass does the layout of the atoms. The pass is done after the /// order their .o files were found on the command line, then by order of the /// atoms (address) in the .o file. But some atoms have a preferred location /// in their section (such as pinned to the start or end of the section), so /// the sort must take that into account too. class LayoutPass : public Pass { public: struct SortKey { SortKey(OwningAtomPtr &&atom, const DefinedAtom *root, uint64_t override) : _atom(std::move(atom)), _root(root), _override(override) {} OwningAtomPtr _atom; const DefinedAtom *_root; uint64_t _override; // Note, these are only here to appease MSVC bots which didn't like // the same methods being implemented/deleted in OwningAtomPtr. SortKey(SortKey &&key) : _atom(std::move(key._atom)), _root(key._root), _override(key._override) { key._root = nullptr; } SortKey &operator=(SortKey &&key) { _atom = std::move(key._atom); _root = key._root; key._root = nullptr; _override = key._override; return *this; } private: SortKey(const SortKey &) = delete; void operator=(const SortKey&) = delete; }; typedef std::function SortOverride; LayoutPass(const Registry ®istry, SortOverride sorter); /// Sorts atoms in mergedFile by content type then by command line order. llvm::Error perform(SimpleFile &mergedFile) override; ~LayoutPass() override = default; private: // Build the followOn atoms chain as specified by the kindLayoutAfter // reference type void buildFollowOnTable(const File::AtomRange &range); // Build a map of Atoms to ordinals for sorting the atoms void buildOrdinalOverrideMap(const File::AtomRange &range); const Registry &_registry; SortOverride _customSorter; typedef llvm::DenseMap AtomToAtomT; typedef llvm::DenseMap AtomToOrdinalT; // A map to be used to sort atoms. It represents the order of atoms in the // result; if Atom X is mapped to atom Y in this map, X will be located // immediately before Y in the output file. Y might be mapped to another // atom, constructing a follow-on chain. An atom cannot be mapped to more // than one atom unless all but one atom are of size zero. AtomToAtomT _followOnNexts; // A map to be used to sort atoms. It's a map from an atom to its root of // follow-on chain. A root atom is mapped to itself. If an atom is not in // _followOnNexts, the atom is not in this map, and vice versa. AtomToAtomT _followOnRoots; AtomToOrdinalT _ordinalOverrideMap; // Helper methods for buildFollowOnTable(). const DefinedAtom *findAtomFollowedBy(const DefinedAtom *targetAtom); bool checkAllPrevAtomsZeroSize(const DefinedAtom *targetAtom); void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root); std::vector decorate(File::AtomRange &atomRange) const; void undecorate(File::AtomRange &atomRange, std::vector &keys) const; // Check if the follow-on graph is a correct structure. For debugging only. void checkFollowonChain(const File::AtomRange &range); }; } // namespace mach_o } // namespace lld #endif // LLD_READER_WRITER_MACHO_LAYOUT_PASS_H