1 //===----- MachOLinkGraphBuilder.h - MachO LinkGraph builder ----*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Generic MachO LinkGraph building code.
11 //===----------------------------------------------------------------------===//
13 #ifndef LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H
14 #define LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
19 #include "llvm/Object/MachO.h"
21 #include "EHFrameSupportImpl.h"
22 #include "JITLinkGeneric.h"
29 class MachOLinkGraphBuilder
{
31 virtual ~MachOLinkGraphBuilder();
32 Expected
<std::unique_ptr
<LinkGraph
>> buildGraph();
36 struct NormalizedSymbol
{
37 friend class MachOLinkGraphBuilder
;
40 NormalizedSymbol(std::optional
<StringRef
> Name
, uint64_t Value
,
41 uint8_t Type
, uint8_t Sect
, uint16_t Desc
, Linkage L
,
43 : Name(Name
), Value(Value
), Type(Type
), Sect(Sect
), Desc(Desc
), L(L
),
45 assert((!Name
|| !Name
->empty()) && "Name must be none or non-empty");
49 NormalizedSymbol(const NormalizedSymbol
&) = delete;
50 NormalizedSymbol
&operator=(const NormalizedSymbol
&) = delete;
51 NormalizedSymbol(NormalizedSymbol
&&) = delete;
52 NormalizedSymbol
&operator=(NormalizedSymbol
&&) = delete;
54 std::optional
<StringRef
> Name
;
59 Linkage L
= Linkage::Strong
;
60 Scope S
= Scope::Default
;
61 Symbol
*GraphSymbol
= nullptr;
64 // Normalized section representation. Section and segment names are guaranteed
65 // to be null-terminated, hence the extra bytes on SegName and SectName.
66 class NormalizedSection
{
67 friend class MachOLinkGraphBuilder
;
70 NormalizedSection() = default;
75 orc::ExecutorAddr Address
;
77 uint64_t Alignment
= 0;
79 const char *Data
= nullptr;
80 Section
*GraphSection
= nullptr;
81 std::map
<orc::ExecutorAddr
, Symbol
*> CanonicalSymbols
;
84 using SectionParserFunction
= std::function
<Error(NormalizedSection
&S
)>;
86 MachOLinkGraphBuilder(const object::MachOObjectFile
&Obj
, Triple TT
,
87 SubtargetFeatures Features
,
88 LinkGraph::GetEdgeKindNameFunction GetEdgeKindName
);
90 LinkGraph
&getGraph() const { return *G
; }
92 const object::MachOObjectFile
&getObject() const { return Obj
; }
94 void addCustomSectionParser(StringRef SectionName
,
95 SectionParserFunction Parse
);
97 virtual Error
addRelocations() = 0;
100 template <typename
... ArgTs
>
101 NormalizedSymbol
&createNormalizedSymbol(ArgTs
&&... Args
) {
102 NormalizedSymbol
*Sym
= reinterpret_cast<NormalizedSymbol
*>(
103 Allocator
.Allocate
<NormalizedSymbol
>());
104 new (Sym
) NormalizedSymbol(std::forward
<ArgTs
>(Args
)...);
108 /// Index is zero-based (MachO section indexes are usually one-based) and
109 /// assumed to be in-range. Client is responsible for checking.
110 NormalizedSection
&getSectionByIndex(unsigned Index
) {
111 auto I
= IndexToSection
.find(Index
);
112 assert(I
!= IndexToSection
.end() && "No section recorded at index");
116 /// Try to get the section at the given index. Will return an error if the
117 /// given index is out of range, or if no section has been added for the given
119 Expected
<NormalizedSection
&> findSectionByIndex(unsigned Index
) {
120 auto I
= IndexToSection
.find(Index
);
121 if (I
== IndexToSection
.end())
122 return make_error
<JITLinkError
>("No section recorded for index " +
123 formatv("{0:d}", Index
));
127 /// Try to get the symbol at the given index. Will return an error if the
128 /// given index is out of range, or if no symbol has been added for the given
130 Expected
<NormalizedSymbol
&> findSymbolByIndex(uint64_t Index
) {
131 auto I
= IndexToSymbol
.find(Index
);
132 if (I
== IndexToSymbol
.end())
133 return make_error
<JITLinkError
>("No symbol at index " +
134 formatv("{0:d}", Index
));
135 assert(I
->second
&& "Null symbol at index");
139 /// Returns the symbol with the highest address not greater than the search
140 /// address, or null if no such symbol exists.
141 Symbol
*getSymbolByAddress(NormalizedSection
&NSec
,
142 orc::ExecutorAddr Address
) {
143 auto I
= NSec
.CanonicalSymbols
.upper_bound(Address
);
144 if (I
== NSec
.CanonicalSymbols
.begin())
146 return std::prev(I
)->second
;
149 /// Returns the symbol with the highest address not greater than the search
150 /// address, or an error if no such symbol exists.
151 Expected
<Symbol
&> findSymbolByAddress(NormalizedSection
&NSec
,
152 orc::ExecutorAddr Address
) {
153 auto *Sym
= getSymbolByAddress(NSec
, Address
);
155 if (Address
<= Sym
->getAddress() + Sym
->getSize())
157 return make_error
<JITLinkError
>("No symbol covering address " +
158 formatv("{0:x16}", Address
));
161 static Linkage
getLinkage(uint16_t Desc
);
162 static Scope
getScope(StringRef Name
, uint8_t Type
);
163 static bool isAltEntry(const NormalizedSymbol
&NSym
);
165 static bool isDebugSection(const NormalizedSection
&NSec
);
166 static bool isZeroFillSection(const NormalizedSection
&NSec
);
168 MachO::relocation_info
169 getRelocationInfo(const object::relocation_iterator RelItr
) {
170 MachO::any_relocation_info ARI
=
171 getObject().getRelocation(RelItr
->getRawDataRefImpl());
172 MachO::relocation_info RI
;
173 RI
.r_address
= ARI
.r_word0
;
174 RI
.r_symbolnum
= ARI
.r_word1
& 0xffffff;
175 RI
.r_pcrel
= (ARI
.r_word1
>> 24) & 1;
176 RI
.r_length
= (ARI
.r_word1
>> 25) & 3;
177 RI
.r_extern
= (ARI
.r_word1
>> 27) & 1;
178 RI
.r_type
= (ARI
.r_word1
>> 28);
183 static unsigned getPointerSize(const object::MachOObjectFile
&Obj
);
184 static llvm::endianness
getEndianness(const object::MachOObjectFile
&Obj
);
186 void setCanonicalSymbol(NormalizedSection
&NSec
, Symbol
&Sym
) {
187 auto *&CanonicalSymEntry
= NSec
.CanonicalSymbols
[Sym
.getAddress()];
188 // There should be no symbol at this address, or, if there is,
189 // it should be a zero-sized symbol from an empty section (which
190 // we can safely override).
191 assert((!CanonicalSymEntry
|| CanonicalSymEntry
->getSize() == 0) &&
192 "Duplicate canonical symbol at address");
193 CanonicalSymEntry
= &Sym
;
196 Section
&getCommonSection();
197 void addSectionStartSymAndBlock(unsigned SecIndex
, Section
&GraphSec
,
198 orc::ExecutorAddr Address
, const char *Data
,
199 orc::ExecutorAddrDiff Size
,
200 uint32_t Alignment
, bool IsLive
);
202 Error
createNormalizedSections();
203 Error
createNormalizedSymbols();
205 /// Create graph blocks and symbols for externals, absolutes, commons and
206 /// all defined symbols in sections without custom parsers.
207 Error
graphifyRegularSymbols();
209 /// Create and return a graph symbol for the given normalized symbol.
211 /// NSym's GraphSymbol member will be updated to point at the newly created
213 Symbol
&createStandardGraphSymbol(NormalizedSymbol
&Sym
, Block
&B
,
214 size_t Size
, bool IsText
,
215 bool IsNoDeadStrip
, bool IsCanonical
);
217 /// Create graph blocks and symbols for all sections.
218 Error
graphifySectionsWithCustomParsers();
220 /// Graphify cstring section.
221 Error
graphifyCStringSection(NormalizedSection
&NSec
,
222 std::vector
<NormalizedSymbol
*> NSyms
);
224 // Put the BumpPtrAllocator first so that we don't free any of the underlying
225 // memory until the Symbol/Addressable destructors have been run.
226 BumpPtrAllocator Allocator
;
228 const object::MachOObjectFile
&Obj
;
229 std::unique_ptr
<LinkGraph
> G
;
231 bool SubsectionsViaSymbols
= false;
232 DenseMap
<unsigned, NormalizedSection
> IndexToSection
;
233 Section
*CommonSection
= nullptr;
235 DenseMap
<uint32_t, NormalizedSymbol
*> IndexToSymbol
;
236 StringMap
<SectionParserFunction
> CustomSectionParserFunctions
;
239 /// A pass to split up __LD,__compact_unwind sections.
240 class CompactUnwindSplitter
{
242 CompactUnwindSplitter(StringRef CompactUnwindSectionName
)
243 : CompactUnwindSectionName(CompactUnwindSectionName
) {}
244 Error
operator()(LinkGraph
&G
);
247 StringRef CompactUnwindSectionName
;
250 } // end namespace jitlink
251 } // end namespace llvm
253 #endif // LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H