blob: 91b1d5a2238770f93df218535e1e8dd7fd11af2e [file] [log] [blame]
Lang Hames4e920e52019-10-04 03:55:26 +00001//===----- MachOLinkGraphBuilder.h - MachO LinkGraph builder ----*- C++ -*-===//
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// Generic MachO LinkGraph building code.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H
14#define LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H
15
16#include "llvm/ExecutionEngine/JITLink/JITLink.h"
17
18#include "EHFrameSupportImpl.h"
19#include "JITLinkGeneric.h"
20#include "llvm/Object/MachO.h"
21
22#include <list>
23
24namespace llvm {
25namespace jitlink {
26
27class MachOLinkGraphBuilder {
28public:
29 virtual ~MachOLinkGraphBuilder();
30 Expected<std::unique_ptr<LinkGraph>> buildGraph();
31
32protected:
Lang Hames4e920e52019-10-04 03:55:26 +000033
34 struct NormalizedSymbol {
35 friend class MachOLinkGraphBuilder;
36
37 private:
38 NormalizedSymbol(Optional<StringRef> Name, uint64_t Value, uint8_t Type,
39 uint8_t Sect, uint16_t Desc, Linkage L, Scope S)
40 : Name(Name), Value(Value), Type(Type), Sect(Sect), Desc(Desc), L(L),
41 S(S) {
Martin Storsjo5b2e0ba2019-10-04 19:47:42 +000042 assert((!Name || !Name->empty()) && "Name must be none or non-empty");
Lang Hames4e920e52019-10-04 03:55:26 +000043 }
44
45 public:
46 NormalizedSymbol(const NormalizedSymbol &) = delete;
47 NormalizedSymbol &operator=(const NormalizedSymbol &) = delete;
48 NormalizedSymbol(NormalizedSymbol &&) = delete;
49 NormalizedSymbol &operator=(NormalizedSymbol &&) = delete;
50
51 Optional<StringRef> Name;
52 uint64_t Value = 0;
53 uint8_t Type = 0;
54 uint8_t Sect = 0;
55 uint16_t Desc = 0;
56 Linkage L = Linkage::Strong;
57 Scope S = Scope::Default;
58 Symbol *GraphSymbol = nullptr;
59 };
60
61 class NormalizedSection {
62 friend class MachOLinkGraphBuilder;
63
64 private:
65 NormalizedSection() = default;
66
67 public:
68 Section *GraphSection = nullptr;
69 uint64_t Address = 0;
70 uint64_t Size = 0;
71 uint64_t Alignment = 0;
72 uint32_t Flags = 0;
73 const char *Data = nullptr;
74 };
75
76 using SectionParserFunction = std::function<Error(NormalizedSection &S)>;
77
78 MachOLinkGraphBuilder(const object::MachOObjectFile &Obj);
79
80 LinkGraph &getGraph() const { return *G; }
81
82 const object::MachOObjectFile &getObject() const { return Obj; }
83
84 void addCustomSectionParser(StringRef SectionName,
85 SectionParserFunction Parse);
86
87 virtual Error addRelocations() = 0;
88
89 /// Create a symbol.
90 template <typename... ArgTs>
91 NormalizedSymbol &createNormalizedSymbol(ArgTs &&... Args) {
92 NormalizedSymbol *Sym = reinterpret_cast<NormalizedSymbol *>(
93 Allocator.Allocate<NormalizedSymbol>());
94 new (Sym) NormalizedSymbol(std::forward<ArgTs>(Args)...);
95 return *Sym;
96 }
97
98 /// Index is zero-based (MachO section indexes are usually one-based) and
99 /// assumed to be in-range. Client is responsible for checking.
100 NormalizedSection &getSectionByIndex(unsigned Index) {
101 auto I = IndexToSection.find(Index);
102 assert(I != IndexToSection.end() && "No section recorded at index");
103 return I->second;
104 }
105
106 /// Try to get the section at the given index. Will return an error if the
107 /// given index is out of range, or if no section has been added for the given
108 /// index.
109 Expected<NormalizedSection &> findSectionByIndex(unsigned Index) {
110 auto I = IndexToSection.find(Index);
111 if (I == IndexToSection.end())
112 return make_error<JITLinkError>("No section recorded for index " +
113 formatv("{0:u}", Index));
114 return I->second;
115 }
116
117 /// Try to get the symbol at the given index. Will return an error if the
118 /// given index is out of range, or if no symbol has been added for the given
119 /// index.
120 Expected<NormalizedSymbol &> findSymbolByIndex(uint64_t Index) {
121 if (Index >= IndexToSymbol.size())
122 return make_error<JITLinkError>("Symbol index out of range");
123 auto *Sym = IndexToSymbol[Index];
124 if (!Sym)
125 return make_error<JITLinkError>("No symbol at index " +
126 formatv("{0:u}", Index));
127 return *Sym;
128 }
129
130 /// Returns the symbol with the highest address not greater than the search
131 /// address, or null if no such symbol exists.
132 Symbol *getSymbolByAddress(JITTargetAddress Address) {
133 auto I = AddrToCanonicalSymbol.upper_bound(Address);
134 if (I == AddrToCanonicalSymbol.begin())
135 return nullptr;
136 return std::prev(I)->second;
137 }
138
139 /// Returns the symbol with the highest address not greater than the search
140 /// address, or an error if no such symbol exists.
141 Expected<Symbol &> findSymbolByAddress(JITTargetAddress Address) {
142 auto *Sym = getSymbolByAddress(Address);
143 if (Sym)
144 if (Address < Sym->getAddress() + Sym->getSize())
145 return *Sym;
146 return make_error<JITLinkError>("No symbol covering address " +
147 formatv("{0:x16}", Address));
148 }
149
150 static Linkage getLinkage(uint16_t Desc);
151 static Scope getScope(StringRef Name, uint8_t Type);
152 static bool isAltEntry(const NormalizedSymbol &NSym);
153
154private:
155 static unsigned getPointerSize(const object::MachOObjectFile &Obj);
156 static support::endianness getEndianness(const object::MachOObjectFile &Obj);
157
158 void setCanonicalSymbol(Symbol &Sym) {
159 auto *&CanonicalSymEntry = AddrToCanonicalSymbol[Sym.getAddress()];
160 // There should be no symbol at this address, or, if there is,
161 // it should be a zero-sized symbol from an empty section (which
162 // we can safely override).
163 assert((!CanonicalSymEntry || CanonicalSymEntry->getSize() == 0) &&
164 "Duplicate canonical symbol at address");
165 CanonicalSymEntry = &Sym;
166 }
167
168 Section &getCommonSection();
169 void addSectionStartSymAndBlock(Section &GraphSec, uint64_t Address,
170 const char *Data, uint64_t Size,
171 uint32_t Alignment, bool IsLive);
172
173 Error createNormalizedSections();
174 Error createNormalizedSymbols();
175
176 /// Create graph blocks and symbols for externals, absolutes, commons and
177 /// all defined symbols in sections without custom parsers.
178 Error graphifyRegularSymbols();
179
180 /// Create graph blocks and symbols for all sections.
181 Error graphifySectionsWithCustomParsers();
182
183 // Put the BumpPtrAllocator first so that we don't free any of the underlying
184 // memory until the Symbol/Addressable destructors have been run.
185 BumpPtrAllocator Allocator;
186
187 const object::MachOObjectFile &Obj;
188 std::unique_ptr<LinkGraph> G;
189
190 DenseMap<unsigned, NormalizedSection> IndexToSection;
191 Section *CommonSection = nullptr;
192
193 DenseMap<uint32_t, NormalizedSymbol *> IndexToSymbol;
194 std::map<JITTargetAddress, Symbol *> AddrToCanonicalSymbol;
195 StringMap<SectionParserFunction> CustomSectionParserFunctions;
196};
197
198} // end namespace jitlink
199} // end namespace llvm
200
201#endif // LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H