/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/lib/ReaderWriter/MachO/LayoutPass.h
Line | Count | Source |
1 | | //===------ lib/ReaderWriter/MachO/LayoutPass.h - Handles Layout of atoms -===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #ifndef LLD_READER_WRITER_MACHO_LAYOUT_PASS_H |
10 | | #define LLD_READER_WRITER_MACHO_LAYOUT_PASS_H |
11 | | |
12 | | #include "lld/Core/File.h" |
13 | | #include "lld/Core/Pass.h" |
14 | | #include "lld/Core/Reader.h" |
15 | | #include "lld/Core/Simple.h" |
16 | | #include "llvm/ADT/DenseMap.h" |
17 | | #include <map> |
18 | | #include <string> |
19 | | #include <vector> |
20 | | |
21 | | namespace lld { |
22 | | class DefinedAtom; |
23 | | class SimpleFile; |
24 | | |
25 | | namespace mach_o { |
26 | | |
27 | | /// This linker pass does the layout of the atoms. The pass is done after the |
28 | | /// order their .o files were found on the command line, then by order of the |
29 | | /// atoms (address) in the .o file. But some atoms have a preferred location |
30 | | /// in their section (such as pinned to the start or end of the section), so |
31 | | /// the sort must take that into account too. |
32 | | class LayoutPass : public Pass { |
33 | | public: |
34 | | struct SortKey { |
35 | | SortKey(OwningAtomPtr<DefinedAtom> &&atom, |
36 | | const DefinedAtom *root, uint64_t override) |
37 | 732 | : _atom(std::move(atom)), _root(root), _override(override) {} |
38 | | OwningAtomPtr<DefinedAtom> _atom; |
39 | | const DefinedAtom *_root; |
40 | | uint64_t _override; |
41 | | |
42 | | // Note, these are only here to appease MSVC bots which didn't like |
43 | | // the same methods being implemented/deleted in OwningAtomPtr. |
44 | | SortKey(SortKey &&key) : _atom(std::move(key._atom)), _root(key._root), |
45 | 1.95k | _override(key._override) { |
46 | 1.95k | key._root = nullptr; |
47 | 1.95k | } |
48 | | |
49 | 1.04k | SortKey &operator=(SortKey &&key) { |
50 | 1.04k | _atom = std::move(key._atom); |
51 | 1.04k | _root = key._root; |
52 | 1.04k | key._root = nullptr; |
53 | 1.04k | _override = key._override; |
54 | 1.04k | return *this; |
55 | 1.04k | } |
56 | | |
57 | | private: |
58 | | SortKey(const SortKey &) = delete; |
59 | | void operator=(const SortKey&) = delete; |
60 | | }; |
61 | | |
62 | | typedef std::function<bool (const DefinedAtom *left, const DefinedAtom *right, |
63 | | bool &leftBeforeRight)> SortOverride; |
64 | | |
65 | | LayoutPass(const Registry ®istry, SortOverride sorter); |
66 | | |
67 | | /// Sorts atoms in mergedFile by content type then by command line order. |
68 | | llvm::Error perform(SimpleFile &mergedFile) override; |
69 | | |
70 | 170 | ~LayoutPass() override = default; |
71 | | |
72 | | private: |
73 | | // Build the followOn atoms chain as specified by the kindLayoutAfter |
74 | | // reference type |
75 | | void buildFollowOnTable(const File::AtomRange<DefinedAtom> &range); |
76 | | |
77 | | // Build a map of Atoms to ordinals for sorting the atoms |
78 | | void buildOrdinalOverrideMap(const File::AtomRange<DefinedAtom> &range); |
79 | | |
80 | | const Registry &_registry; |
81 | | SortOverride _customSorter; |
82 | | |
83 | | typedef llvm::DenseMap<const DefinedAtom *, const DefinedAtom *> AtomToAtomT; |
84 | | typedef llvm::DenseMap<const DefinedAtom *, uint64_t> AtomToOrdinalT; |
85 | | |
86 | | // A map to be used to sort atoms. It represents the order of atoms in the |
87 | | // result; if Atom X is mapped to atom Y in this map, X will be located |
88 | | // immediately before Y in the output file. Y might be mapped to another |
89 | | // atom, constructing a follow-on chain. An atom cannot be mapped to more |
90 | | // than one atom unless all but one atom are of size zero. |
91 | | AtomToAtomT _followOnNexts; |
92 | | |
93 | | // A map to be used to sort atoms. It's a map from an atom to its root of |
94 | | // follow-on chain. A root atom is mapped to itself. If an atom is not in |
95 | | // _followOnNexts, the atom is not in this map, and vice versa. |
96 | | AtomToAtomT _followOnRoots; |
97 | | |
98 | | AtomToOrdinalT _ordinalOverrideMap; |
99 | | |
100 | | // Helper methods for buildFollowOnTable(). |
101 | | const DefinedAtom *findAtomFollowedBy(const DefinedAtom *targetAtom); |
102 | | bool checkAllPrevAtomsZeroSize(const DefinedAtom *targetAtom); |
103 | | |
104 | | void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root); |
105 | | |
106 | | std::vector<SortKey> decorate(File::AtomRange<DefinedAtom> &atomRange) const; |
107 | | |
108 | | void undecorate(File::AtomRange<DefinedAtom> &atomRange, |
109 | | std::vector<SortKey> &keys) const; |
110 | | |
111 | | // Check if the follow-on graph is a correct structure. For debugging only. |
112 | | void checkFollowonChain(const File::AtomRange<DefinedAtom> &range); |
113 | | }; |
114 | | |
115 | | } // namespace mach_o |
116 | | } // namespace lld |
117 | | |
118 | | #endif // LLD_READER_WRITER_MACHO_LAYOUT_PASS_H |