Bug Summary

File:llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h
Warning:line 449, column 38
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name MachO_x86_64.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/ExecutionEngine/JITLink -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/ExecutionEngine/JITLink -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/ExecutionEngine/JITLink -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/include -D NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/ExecutionEngine/JITLink -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e=. -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-09-04-040900-46481-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp

/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp

1//===---- MachO_x86_64.cpp -JIT linker implementation for MachO/x86-64 ----===//
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// MachO/x86-64 jit-link implementation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/ExecutionEngine/JITLink/MachO_x86_64.h"
14#include "llvm/ExecutionEngine/JITLink/x86_64.h"
15
16#include "MachOLinkGraphBuilder.h"
17#include "PerGraphGOTAndPLTStubsBuilder.h"
18
19#define DEBUG_TYPE"jitlink" "jitlink"
20
21using namespace llvm;
22using namespace llvm::jitlink;
23
24namespace {
25
26class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder {
27public:
28 MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj)
29 : MachOLinkGraphBuilder(Obj, Triple("x86_64-apple-darwin"),
30 x86_64::getEdgeKindName) {}
31
32private:
33 enum MachONormalizedRelocationType : unsigned {
34 MachOBranch32,
35 MachOPointer32,
36 MachOPointer64,
37 MachOPointer64Anon,
38 MachOPCRel32,
39 MachOPCRel32Minus1,
40 MachOPCRel32Minus2,
41 MachOPCRel32Minus4,
42 MachOPCRel32Anon,
43 MachOPCRel32Minus1Anon,
44 MachOPCRel32Minus2Anon,
45 MachOPCRel32Minus4Anon,
46 MachOPCRel32GOTLoad,
47 MachOPCRel32GOT,
48 MachOPCRel32TLV,
49 MachOSubtractor32,
50 MachOSubtractor64,
51 };
52
53 static Expected<MachONormalizedRelocationType>
54 getRelocKind(const MachO::relocation_info &RI) {
55 switch (RI.r_type) {
56 case MachO::X86_64_RELOC_UNSIGNED:
57 if (!RI.r_pcrel) {
58 if (RI.r_length == 3)
59 return RI.r_extern ? MachOPointer64 : MachOPointer64Anon;
60 else if (RI.r_extern && RI.r_length == 2)
61 return MachOPointer32;
62 }
63 break;
64 case MachO::X86_64_RELOC_SIGNED:
65 if (RI.r_pcrel && RI.r_length == 2)
66 return RI.r_extern ? MachOPCRel32 : MachOPCRel32Anon;
67 break;
68 case MachO::X86_64_RELOC_BRANCH:
69 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
70 return MachOBranch32;
71 break;
72 case MachO::X86_64_RELOC_GOT_LOAD:
73 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
74 return MachOPCRel32GOTLoad;
75 break;
76 case MachO::X86_64_RELOC_GOT:
77 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
78 return MachOPCRel32GOT;
79 break;
80 case MachO::X86_64_RELOC_SUBTRACTOR:
81 if (!RI.r_pcrel && RI.r_extern) {
82 if (RI.r_length == 2)
83 return MachOSubtractor32;
84 else if (RI.r_length == 3)
85 return MachOSubtractor64;
86 }
87 break;
88 case MachO::X86_64_RELOC_SIGNED_1:
89 if (RI.r_pcrel && RI.r_length == 2)
90 return RI.r_extern ? MachOPCRel32Minus1 : MachOPCRel32Minus1Anon;
91 break;
92 case MachO::X86_64_RELOC_SIGNED_2:
93 if (RI.r_pcrel && RI.r_length == 2)
94 return RI.r_extern ? MachOPCRel32Minus2 : MachOPCRel32Minus2Anon;
95 break;
96 case MachO::X86_64_RELOC_SIGNED_4:
97 if (RI.r_pcrel && RI.r_length == 2)
98 return RI.r_extern ? MachOPCRel32Minus4 : MachOPCRel32Minus4Anon;
99 break;
100 case MachO::X86_64_RELOC_TLV:
101 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
102 return MachOPCRel32TLV;
103 break;
104 }
105
106 return make_error<JITLinkError>(
107 "Unsupported x86-64 relocation: address=" +
108 formatv("{0:x8}", RI.r_address) +
109 ", symbolnum=" + formatv("{0:x6}", RI.r_symbolnum) +
110 ", kind=" + formatv("{0:x1}", RI.r_type) +
111 ", pc_rel=" + (RI.r_pcrel ? "true" : "false") +
112 ", extern=" + (RI.r_extern ? "true" : "false") +
113 ", length=" + formatv("{0:d}", RI.r_length));
114 }
115
116 using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;
117
118 // Parses paired SUBTRACTOR/UNSIGNED relocations and, on success,
119 // returns the edge kind and addend to be used.
120 Expected<PairRelocInfo> parsePairRelocation(
121 Block &BlockToFix, MachONormalizedRelocationType SubtractorKind,
122 const MachO::relocation_info &SubRI, JITTargetAddress FixupAddress,
123 const char *FixupContent, object::relocation_iterator &UnsignedRelItr,
124 object::relocation_iterator &RelEnd) {
125 using namespace support;
126
127 assert(((SubtractorKind == MachOSubtractor32 && SubRI.r_length == 2) ||(static_cast<void> (0))
128 (SubtractorKind == MachOSubtractor64 && SubRI.r_length == 3)) &&(static_cast<void> (0))
129 "Subtractor kind should match length")(static_cast<void> (0));
130 assert(SubRI.r_extern && "SUBTRACTOR reloc symbol should be extern")(static_cast<void> (0));
131 assert(!SubRI.r_pcrel && "SUBTRACTOR reloc should not be PCRel")(static_cast<void> (0));
132
133 if (UnsignedRelItr == RelEnd)
134 return make_error<JITLinkError>("x86_64 SUBTRACTOR without paired "
135 "UNSIGNED relocation");
136
137 auto UnsignedRI = getRelocationInfo(UnsignedRelItr);
138
139 if (SubRI.r_address != UnsignedRI.r_address)
140 return make_error<JITLinkError>("x86_64 SUBTRACTOR and paired UNSIGNED "
141 "point to different addresses");
142
143 if (SubRI.r_length != UnsignedRI.r_length)
144 return make_error<JITLinkError>("length of x86_64 SUBTRACTOR and paired "
145 "UNSIGNED reloc must match");
146
147 Symbol *FromSymbol;
148 if (auto FromSymbolOrErr = findSymbolByIndex(SubRI.r_symbolnum))
149 FromSymbol = FromSymbolOrErr->GraphSymbol;
150 else
151 return FromSymbolOrErr.takeError();
152
153 // Read the current fixup value.
154 uint64_t FixupValue = 0;
155 if (SubRI.r_length == 3)
156 FixupValue = *(const little64_t *)FixupContent;
157 else
158 FixupValue = *(const little32_t *)FixupContent;
159
160 // Find 'ToSymbol' using symbol number or address, depending on whether the
161 // paired UNSIGNED relocation is extern.
162 Symbol *ToSymbol = nullptr;
163 if (UnsignedRI.r_extern) {
164 // Find target symbol by symbol index.
165 if (auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum))
166 ToSymbol = ToSymbolOrErr->GraphSymbol;
167 else
168 return ToSymbolOrErr.takeError();
169 } else {
170 auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);
171 if (!ToSymbolSec)
172 return ToSymbolSec.takeError();
173 ToSymbol = getSymbolByAddress(ToSymbolSec->Address);
174 assert(ToSymbol && "No symbol for section")(static_cast<void> (0));
175 FixupValue -= ToSymbol->getAddress();
176 }
177
178 Edge::Kind DeltaKind;
179 Symbol *TargetSymbol;
180 uint64_t Addend;
181 if (&BlockToFix == &FromSymbol->getAddressable()) {
182 TargetSymbol = ToSymbol;
183 DeltaKind = (SubRI.r_length == 3) ? x86_64::Delta64 : x86_64::Delta32;
184 Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());
185 // FIXME: handle extern 'from'.
186 } else if (&BlockToFix == &ToSymbol->getAddressable()) {
187 TargetSymbol = FromSymbol;
188 DeltaKind =
189 (SubRI.r_length == 3) ? x86_64::NegDelta64 : x86_64::NegDelta32;
190 Addend = FixupValue - (FixupAddress - ToSymbol->getAddress());
191 } else {
192 // BlockToFix was neither FromSymbol nor ToSymbol.
193 return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "
194 "either 'A' or 'B' (or a symbol in one "
195 "of their alt-entry chains)");
196 }
197
198 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
199 }
200
201 Error addRelocations() override {
202 using namespace support;
203 auto &Obj = getObject();
204
205 LLVM_DEBUG(dbgs() << "Processing relocations:\n")do { } while (false);
206
207 for (auto &S : Obj.sections()) {
208
209 JITTargetAddress SectionAddress = S.getAddress();
210
211 // Skip relocations virtual sections.
212 if (S.isVirtual()) {
213 if (S.relocation_begin() != S.relocation_end())
214 return make_error<JITLinkError>("Virtual section contains "
215 "relocations");
216 continue;
217 }
218
219 // Skip relocations for debug symbols.
220 {
221 auto &NSec =
222 getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
223 if (!NSec.GraphSection) {
224 LLVM_DEBUG({do { } while (false)
225 dbgs() << " Skipping relocations for MachO section "do { } while (false)
226 << NSec.SegName << "/" << NSec.SectNamedo { } while (false)
227 << " which has no associated graph section\n";do { } while (false)
228 })do { } while (false);
229 continue;
230 }
231 }
232
233 // Add relocations for section.
234 for (auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
235 RelItr != RelEnd; ++RelItr) {
236
237 MachO::relocation_info RI = getRelocationInfo(RelItr);
238
239 // Find the address of the value to fix up.
240 JITTargetAddress FixupAddress = SectionAddress + (uint32_t)RI.r_address;
241
242 LLVM_DEBUG({do { } while (false)
243 auto &NSec =do { } while (false)
244 getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));do { } while (false)
245 dbgs() << " " << NSec.SectName << " + "do { } while (false)
246 << formatv("{0:x8}", RI.r_address) << ":\n";do { } while (false)
247 })do { } while (false);
248
249 // Find the block that the fixup points to.
250 Block *BlockToFix = nullptr;
251 {
252 auto SymbolToFixOrErr = findSymbolByAddress(FixupAddress);
253 if (!SymbolToFixOrErr)
254 return SymbolToFixOrErr.takeError();
255 BlockToFix = &SymbolToFixOrErr->getBlock();
256 }
257
258 if (FixupAddress + static_cast<JITTargetAddress>(1ULL << RI.r_length) >
259 BlockToFix->getAddress() + BlockToFix->getContent().size())
260 return make_error<JITLinkError>(
261 "Relocation extends past end of fixup block");
262
263 // Get a pointer to the fixup content.
264 const char *FixupContent = BlockToFix->getContent().data() +
265 (FixupAddress - BlockToFix->getAddress());
266
267 size_t FixupOffset = FixupAddress - BlockToFix->getAddress();
268
269 // The target symbol and addend will be populated by the switch below.
270 Symbol *TargetSymbol = nullptr;
271 uint64_t Addend = 0;
272
273 // Sanity check the relocation kind.
274 auto MachORelocKind = getRelocKind(RI);
275 if (!MachORelocKind)
276 return MachORelocKind.takeError();
277
278 Edge::Kind Kind = Edge::Invalid;
279
280 switch (*MachORelocKind) {
281 case MachOBranch32:
282 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
283 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
284 else
285 return TargetSymbolOrErr.takeError();
286 Addend = *(const little32_t *)FixupContent;
287 Kind = x86_64::BranchPCRel32;
288 break;
289 case MachOPCRel32:
290 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
291 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
292 else
293 return TargetSymbolOrErr.takeError();
294 Addend = *(const little32_t *)FixupContent - 4;
295 Kind = x86_64::Delta32;
296 break;
297 case MachOPCRel32GOTLoad:
298 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
299 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
300 else
301 return TargetSymbolOrErr.takeError();
302 Addend = *(const little32_t *)FixupContent;
303 Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable;
304 if (FixupOffset < 3)
305 return make_error<JITLinkError>("GOTLD at invalid offset " +
306 formatv("{0}", FixupOffset));
307 break;
308 case MachOPCRel32GOT:
309 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
310 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
311 else
312 return TargetSymbolOrErr.takeError();
313 Addend = *(const little32_t *)FixupContent - 4;
314 Kind = x86_64::RequestGOTAndTransformToDelta32;
315 break;
316 case MachOPCRel32TLV:
317 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
318 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
319 else
320 return TargetSymbolOrErr.takeError();
321 Addend = *(const little32_t *)FixupContent;
322 Kind = x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable;
323 if (FixupOffset < 3)
324 return make_error<JITLinkError>("TLV at invalid offset " +
325 formatv("{0}", FixupOffset));
326 break;
327 case MachOPointer32:
328 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
329 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
330 else
331 return TargetSymbolOrErr.takeError();
332 Addend = *(const ulittle32_t *)FixupContent;
333 Kind = x86_64::Pointer32;
334 break;
335 case MachOPointer64:
336 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
337 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
338 else
339 return TargetSymbolOrErr.takeError();
340 Addend = *(const ulittle64_t *)FixupContent;
341 Kind = x86_64::Pointer64;
342 break;
343 case MachOPointer64Anon: {
344 JITTargetAddress TargetAddress = *(const ulittle64_t *)FixupContent;
345 if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
346 TargetSymbol = &*TargetSymbolOrErr;
347 else
348 return TargetSymbolOrErr.takeError();
349 Addend = TargetAddress - TargetSymbol->getAddress();
350 Kind = x86_64::Pointer64;
351 break;
352 }
353 case MachOPCRel32Minus1:
354 case MachOPCRel32Minus2:
355 case MachOPCRel32Minus4:
356 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
357 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
358 else
359 return TargetSymbolOrErr.takeError();
360 Addend = *(const little32_t *)FixupContent - 4;
361 Kind = x86_64::Delta32;
362 break;
363 case MachOPCRel32Anon: {
364 JITTargetAddress TargetAddress =
365 FixupAddress + 4 + *(const little32_t *)FixupContent;
366 if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
367 TargetSymbol = &*TargetSymbolOrErr;
368 else
369 return TargetSymbolOrErr.takeError();
370 Addend = TargetAddress - TargetSymbol->getAddress() - 4;
371 Kind = x86_64::Delta32;
372 break;
373 }
374 case MachOPCRel32Minus1Anon:
375 case MachOPCRel32Minus2Anon:
376 case MachOPCRel32Minus4Anon: {
377 JITTargetAddress Delta =
378 4 + static_cast<JITTargetAddress>(
379 1ULL << (*MachORelocKind - MachOPCRel32Minus1Anon));
380 JITTargetAddress TargetAddress =
381 FixupAddress + Delta + *(const little32_t *)FixupContent;
382 if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
383 TargetSymbol = &*TargetSymbolOrErr;
384 else
385 return TargetSymbolOrErr.takeError();
386 Addend = TargetAddress - TargetSymbol->getAddress() - Delta;
387 Kind = x86_64::Delta32;
388 break;
389 }
390 case MachOSubtractor32:
391 case MachOSubtractor64: {
392 // We use Delta32/Delta64 to represent SUBTRACTOR relocations.
393 // parsePairRelocation handles the paired reloc, and returns the
394 // edge kind to be used (either Delta32/Delta64, or
395 // NegDelta32/NegDelta64, depending on the direction of the
396 // subtraction) along with the addend.
397 auto PairInfo =
398 parsePairRelocation(*BlockToFix, *MachORelocKind, RI,
399 FixupAddress, FixupContent, ++RelItr, RelEnd);
400 if (!PairInfo)
401 return PairInfo.takeError();
402 std::tie(Kind, TargetSymbol, Addend) = *PairInfo;
403 assert(TargetSymbol && "No target symbol from parsePairRelocation?")(static_cast<void> (0));
404 break;
405 }
406 }
407
408 LLVM_DEBUG({do { } while (false)
409 dbgs() << " ";do { } while (false)
410 Edge GE(Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,do { } while (false)
411 Addend);do { } while (false)
412 printEdge(dbgs(), *BlockToFix, GE, x86_64::getEdgeKindName(Kind));do { } while (false)
413 dbgs() << "\n";do { } while (false)
414 })do { } while (false);
415 BlockToFix->addEdge(Kind, FixupAddress - BlockToFix->getAddress(),
416 *TargetSymbol, Addend);
417 }
418 }
419 return Error::success();
420 }
421};
422
423class PerGraphGOTAndPLTStubsBuilder_MachO_x86_64
424 : public PerGraphGOTAndPLTStubsBuilder<
425 PerGraphGOTAndPLTStubsBuilder_MachO_x86_64> {
426public:
427
428 using PerGraphGOTAndPLTStubsBuilder<
429 PerGraphGOTAndPLTStubsBuilder_MachO_x86_64>::
430 PerGraphGOTAndPLTStubsBuilder;
431
432 bool isGOTEdgeToFix(Edge &E) const {
433 return E.getKind() == x86_64::RequestGOTAndTransformToDelta32 ||
434 E.getKind() ==
435 x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable;
436 }
437
438 Symbol &createGOTEntry(Symbol &Target) {
439 return x86_64::createAnonymousPointer(G, getGOTSection(), &Target);
440 }
441
442 void fixGOTEdge(Edge &E, Symbol &GOTEntry) {
443 // Fix the edge kind.
444 switch (E.getKind()) {
445 case x86_64::RequestGOTAndTransformToDelta32:
446 E.setKind(x86_64::Delta32);
447 break;
448 case x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable:
449 E.setKind(x86_64::PCRel32GOTLoadREXRelaxable);
450 break;
451 default:
452 llvm_unreachable("Not a GOT transform edge")__builtin_unreachable();
453 }
454 // Fix the target, leave the addend as-is.
455 E.setTarget(GOTEntry);
456 }
457
458 bool isExternalBranchEdge(Edge &E) {
459 return E.getKind() == x86_64::BranchPCRel32 && E.getTarget().isExternal();
460 }
461
462 Symbol &createPLTStub(Symbol &Target) {
463 return x86_64::createAnonymousPointerJumpStub(G, getStubsSection(),
464 getGOTEntry(Target));
465 }
466
467 void fixPLTEdge(Edge &E, Symbol &Stub) {
468 assert(E.getKind() == x86_64::BranchPCRel32 && "Not a Branch32 edge?")(static_cast<void> (0));
469 assert(E.getAddend() == 0 &&(static_cast<void> (0))
470 "BranchPCRel32 edge has unexpected addend value")(static_cast<void> (0));
471
472 // Set the edge kind to BranchPCRel32ToPtrJumpStubBypassable. We will use
473 // this to check for stub optimization opportunities in the
474 // optimizeMachO_x86_64_GOTAndStubs pass below.
475 E.setKind(x86_64::BranchPCRel32ToPtrJumpStubBypassable);
476 E.setTarget(Stub);
477 }
478
479private:
480 Section &getGOTSection() {
481 if (!GOTSection)
482 GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ);
483 return *GOTSection;
484 }
485
486 Section &getStubsSection() {
487 if (!StubsSection) {
488 auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
489 sys::Memory::MF_READ | sys::Memory::MF_EXEC);
490 StubsSection = &G.createSection("$__STUBS", StubsProt);
491 }
492 return *StubsSection;
493 }
494
495 Section *GOTSection = nullptr;
496 Section *StubsSection = nullptr;
497};
498
499} // namespace
500
501namespace llvm {
502namespace jitlink {
503
504class MachOJITLinker_x86_64 : public JITLinker<MachOJITLinker_x86_64> {
505 friend class JITLinker<MachOJITLinker_x86_64>;
506
507public:
508 MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
509 std::unique_ptr<LinkGraph> G,
510 PassConfiguration PassConfig)
511 : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
512
513private:
514 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
515 return x86_64::applyFixup(G, B, E, nullptr);
1
Passing null pointer value via 4th parameter 'GOTSymbol'
2
Calling 'applyFixup'
516 }
517};
518
519Expected<std::unique_ptr<LinkGraph>>
520createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer) {
521 auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
522 if (!MachOObj)
523 return MachOObj.takeError();
524 return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
525}
526
527void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
528 std::unique_ptr<JITLinkContext> Ctx) {
529
530 PassConfiguration Config;
531
532 if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
533 // Add eh-frame passses.
534 Config.PrePrunePasses.push_back(createEHFrameSplitterPass_MachO_x86_64());
535 Config.PrePrunePasses.push_back(createEHFrameEdgeFixerPass_MachO_x86_64());
536
537 // Add a mark-live pass.
538 if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
539 Config.PrePrunePasses.push_back(std::move(MarkLive));
540 else
541 Config.PrePrunePasses.push_back(markAllSymbolsLive);
542
543 // Add an in-place GOT/Stubs pass.
544 Config.PostPrunePasses.push_back(
545 PerGraphGOTAndPLTStubsBuilder_MachO_x86_64::asPass);
546
547 // Add GOT/Stubs optimizer pass.
548 Config.PreFixupPasses.push_back(x86_64::optimize_x86_64_GOTAndStubs);
549 }
550
551 if (auto Err = Ctx->modifyPassConfig(*G, Config))
552 return Ctx->notifyFailed(std::move(Err));
553
554 // Construct a JITLinker and run the link function.
555 MachOJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
556}
557
558LinkGraphPassFunction createEHFrameSplitterPass_MachO_x86_64() {
559 return EHFrameSplitter("__TEXT,__eh_frame");
560}
561
562LinkGraphPassFunction createEHFrameEdgeFixerPass_MachO_x86_64() {
563 return EHFrameEdgeFixer("__TEXT,__eh_frame", x86_64::PointerSize,
564 x86_64::Delta64, x86_64::Delta32, x86_64::NegDelta32);
565}
566
567} // end namespace jitlink
568} // end namespace llvm

/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h

1//===-- x86_64.h - Generic JITLink x86-64 edge kinds, utilities -*- 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 utilities for graphs representing x86-64 objects.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_JITLINK_X86_64_H
14#define LLVM_EXECUTIONENGINE_JITLINK_X86_64_H
15
16#include "llvm/ExecutionEngine/JITLink/JITLink.h"
17
18#include <limits>
19
20namespace llvm {
21namespace jitlink {
22namespace x86_64 {
23
24/// Represents x86-64 fixups and other x86-64-specific edge kinds.
25enum EdgeKind_x86_64 : Edge::Kind {
26
27 /// A plain 64-bit pointer value relocation.
28 ///
29 /// Fixup expression:
30 /// Fixup <- Target + Addend : uint64
31 ///
32 Pointer64 = Edge::FirstRelocation,
33
34 /// A plain 32-bit pointer value relocation.
35 ///
36 /// Fixup expression:
37 /// Fixup <- Target + Addend : uint32
38 ///
39 /// Errors:
40 /// - The target must reside in the low 32-bits of the address space,
41 /// otherwise an out-of-range error will be returned.
42 ///
43 Pointer32,
44
45 /// A signed 32-bit pointer value relocation
46 ///
47 /// Fixup expression:
48 /// Fixup <- Target + Addend : int32
49 ///
50 /// Errors:
51 /// - The target must reside in the signed 32-bits([-2**31, 2**32 - 1]) of
52 /// the address space, otherwise an out-of-range error will be returned.
53 Pointer32Signed,
54
55 /// A 64-bit delta.
56 ///
57 /// Delta from the fixup to the target.
58 ///
59 /// Fixup expression:
60 /// Fixup <- Target - Fixup + Addend : int64
61 ///
62 Delta64,
63
64 /// A 32-bit delta.
65 ///
66 /// Delta from the fixup to the target.
67 ///
68 /// Fixup expression:
69 /// Fixup <- Target - Fixup + Addend : int64
70 ///
71 /// Errors:
72 /// - The result of the fixup expression must fit into an int32, otherwise
73 /// an out-of-range error will be returned.
74 ///
75 Delta32,
76
77 /// A 64-bit negative delta.
78 ///
79 /// Delta from target back to the fixup.
80 ///
81 /// Fixup expression:
82 /// Fixup <- Fixup - Target + Addend : int64
83 ///
84 NegDelta64,
85
86 /// A 32-bit negative delta.
87 ///
88 /// Delta from the target back to the fixup.
89 ///
90 /// Fixup expression:
91 /// Fixup <- Fixup - Target + Addend : int32
92 ///
93 /// Errors:
94 /// - The result of the fixup expression must fit into an int32, otherwise
95 /// an out-of-range error will be returned.
96 NegDelta32,
97
98 /// A 64-bit GOT delta.
99 ///
100 /// Delta from the global offset table to the target
101 ///
102 /// Fixup expression:
103 /// Fixup <- Target - GOTSymbol + Addend : int64
104 ///
105 /// Errors:
106 /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
107 /// symbol was not been defined.
108 Delta64FromGOT,
109
110 /// A 32-bit PC-relative branch.
111 ///
112 /// Represents a PC-relative call or branch to a target. This can be used to
113 /// identify, record, and/or patch call sites.
114 ///
115 /// The fixup expression for this kind includes an implicit offset to account
116 /// for the PC (unlike the Delta edges) so that a Branch32PCRel with a target
117 /// T and addend zero is a call/branch to the start (offset zero) of T.
118 ///
119 /// Fixup expression:
120 /// Fixup <- Target - (Fixup + 4) + Addend : int32
121 ///
122 /// Errors:
123 /// - The result of the fixup expression must fit into an int32, otherwise
124 /// an out-of-range error will be returned.
125 ///
126 BranchPCRel32,
127
128 /// A 32-bit PC-relative branch to a pointer jump stub.
129 ///
130 /// The target of this relocation should be a pointer jump stub of the form:
131 ///
132 /// \code{.s}
133 /// .text
134 /// jmpq *tgtptr(%rip)
135 /// ; ...
136 ///
137 /// .data
138 /// tgtptr:
139 /// .quad 0
140 /// \endcode
141 ///
142 /// This edge kind has the same fixup expression as BranchPCRel32, but further
143 /// identifies the call/branch as being to a pointer jump stub. For edges of
144 /// this kind the jump stub should not be bypassed (use
145 /// BranchPCRel32ToPtrJumpStubBypassable for that), but the pointer location
146 /// target may be recorded to allow manipulation at runtime.
147 ///
148 /// Fixup expression:
149 /// Fixup <- Target - Fixup + Addend - 4 : int32
150 ///
151 /// Errors:
152 /// - The result of the fixup expression must fit into an int32, otherwise
153 /// an out-of-range error will be returned.
154 ///
155 BranchPCRel32ToPtrJumpStub,
156
157 /// A relaxable version of BranchPCRel32ToPtrJumpStub.
158 ///
159 /// The edge kind has the same fixup expression as BranchPCRel32ToPtrJumpStub,
160 /// but identifies the call/branch as being to a pointer jump stub that may be
161 /// bypassed with a direct jump to the ultimate target if the ultimate target
162 /// is within range of the fixup location.
163 ///
164 /// Fixup expression:
165 /// Fixup <- Target - Fixup + Addend - 4: int32
166 ///
167 /// Errors:
168 /// - The result of the fixup expression must fit into an int32, otherwise
169 /// an out-of-range error will be returned.
170 ///
171 BranchPCRel32ToPtrJumpStubBypassable,
172
173 /// A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT
174 /// entry for the original target.
175 ///
176 /// Indicates that this edge should be transformed into a Delta32 targeting
177 /// the GOT entry for the edge's current target, maintaining the same addend.
178 /// A GOT entry for the target should be created if one does not already
179 /// exist.
180 ///
181 /// Edges of this kind are usually handled by a GOT builder pass inserted by
182 /// default.
183 ///
184 /// Fixup expression:
185 /// NONE
186 ///
187 /// Errors:
188 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
189 /// phase will result in an assert/unreachable during the fixup phase.
190 ///
191 RequestGOTAndTransformToDelta32,
192
193 /// A GOT entry getter/constructor, transformed to Delta64 pointing at the GOT
194 /// entry for the original target.
195 ///
196 /// Indicates that this edge should be transformed into a Delta64 targeting
197 /// the GOT entry for the edge's current target, maintaining the same addend.
198 /// A GOT entry for the target should be created if one does not already
199 /// exist.
200 ///
201 /// Edges of this kind are usually handled by a GOT builder pass inserted by
202 /// default.
203 ///
204 /// Fixup expression:
205 /// NONE
206 ///
207 /// Errors:
208 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
209 /// phase will result in an assert/unreachable during the fixup phase.
210 ///
211 RequestGOTAndTransformToDelta64,
212
213 /// A GOT entry offset within GOT getter/constructor, transformed to
214 /// Delta64FromGOT
215 /// pointing at the GOT entry for the original target
216 ///
217 /// Indicates that this edge should be transformed into a Delta64FromGOT
218 /// targeting
219 /// the GOT entry for the edge's current target, maintaining the same addend.
220 /// A GOT entry for the target should be created if one does not already
221 /// exist.
222 ///
223 /// Edges of this kind are usually handled by a GOT builder pass inserted by
224 /// default
225 ///
226 /// Fixup expression:
227 /// NONE
228 ///
229 /// Errors:
230 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
231 /// phase will result in an assert/unreachable during the fixup phase
232 RequestGOTAndTransformToDelta64FromGOT,
233
234 /// A PC-relative load of a GOT entry, relaxable if GOT entry target is
235 /// in-range of the fixup
236 ///
237 /// TODO: Explain the optimization
238 ///
239 /// Fixup expression
240 /// Fixup <- Target - (Fixup + 4) + Addend : int32
241 ///
242 /// Errors:
243 /// - The result of the fixup expression must fit into an int32, otherwise
244 /// an out-of-range error will be returned.
245 //
246 PCRel32GOTLoadRelaxable,
247
248 /// A PC-relative REX load of a GOT entry, relaxable if GOT entry target
249 /// is in-range of the fixup.
250 ///
251 /// If the GOT entry target is in-range of the fixup then the load from the
252 /// GOT may be replaced with a direct memory address calculation.
253 ///
254 /// Fixup expression:
255 /// Fixup <- Target - (Fixup + 4) + Addend : int32
256 ///
257 /// Errors:
258 /// - The result of the fixup expression must fit into an int32, otherwise
259 /// an out-of-range error will be returned.
260 ///
261 PCRel32GOTLoadREXRelaxable,
262
263 /// A GOT entry getter/constructor, transformed to
264 /// PCRel32ToGOTLoadREXRelaxable pointing at the GOT entry for the original
265 /// target.
266 ///
267 /// Indicates that this edge should be lowered to a PC32ToGOTLoadREXRelaxable
268 /// targeting the GOT entry for the edge's current target, maintaining the
269 /// same addend. A GOT entry for the target should be created if one does not
270 /// already exist.
271 ///
272 /// Edges of this kind are usually lowered by a GOT builder pass inserted by
273 /// default.
274 ///
275 /// Fixup expression:
276 /// NONE
277 ///
278 /// Errors:
279 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
280 /// phase will result in an assert/unreachable during the fixup phase.
281 ///
282 RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable,
283
284 /// A GOT entry getter/constructor, transformed to
285 /// PCRel32ToGOTLoadRelaxable pointing at the GOT entry for the original
286 /// target.
287 ///
288 /// Indicates that this edge should be lowered to a PC32ToGOTLoadRelaxable
289 /// targeting the GOT entry for the edge's current target, maintaining the
290 /// same addend. A GOT entry for the target should be created if one does not
291 /// already exist.
292 ///
293 /// Edges of this kind are usually lowered by a GOT builder pass inserted by
294 /// default.
295 ///
296 /// Fixup expression:
297 /// NONE
298 ///
299 /// Errors:
300 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
301 /// phase will result in an assert/unreachable during the fixup phase.
302 ///
303 RequestGOTAndTransformToPCRel32GOTLoadRelaxable,
304
305 /// A PC-relative REX load of a Thread Local Variable Pointer (TLVP) entry,
306 /// relaxable if the TLVP entry target is in-range of the fixup.
307 ///
308 /// If the TLVP entry target is in-range of the fixup then the load from the
309 /// TLVP may be replaced with a direct memory address calculation.
310 ///
311 /// The target of this edge must be a thread local variable entry of the form
312 /// .quad <tlv getter thunk>
313 /// .quad <tlv key>
314 /// .quad <tlv initializer>
315 ///
316 /// Fixup expression:
317 /// Fixup <- Target - (Fixup + 4) + Addend : int32
318 ///
319 /// Errors:
320 /// - The result of the fixup expression must fit into an int32, otherwise
321 /// an out-of-range error will be returned.
322 /// - The target must be either external, or a TLV entry of the required
323 /// form, otherwise a malformed TLV entry error will be returned.
324 ///
325 PCRel32TLVPLoadREXRelaxable,
326
327 /// A TLVP entry getter/constructor, transformed to
328 /// Delta32ToTLVPLoadREXRelaxable.
329 ///
330 /// Indicates that this edge should be transformed into a
331 /// Delta32ToTLVPLoadREXRelaxable targeting the TLVP entry for the edge's
332 /// current target. A TLVP entry for the target should be created if one does
333 /// not already exist.
334 ///
335 /// Fixup expression:
336 /// NONE
337 ///
338 /// Errors:
339 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
340 /// phase will result in an assert/unreachable during the fixup phase.
341 ///
342 RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable
343};
344
345/// Returns a string name for the given x86-64 edge. For debugging purposes
346/// only.
347const char *getEdgeKindName(Edge::Kind K);
348
349/// Optimize the GOT and Stub relocations if the edge target address is in range
350/// 1. PCRel32GOTLoadRelaxable. For this edge kind, if the target is in range,
351/// then replace GOT load with lea
352/// 2. BranchPCRel32ToPtrJumpStubRelaxable. For this edge kind, if the target is
353/// in range, replace a indirect jump by plt stub with a direct jump to the
354/// target
355Error optimize_x86_64_GOTAndStubs(LinkGraph &G);
356
357/// Returns true if the given uint64_t value is in range for a uint32_t.
358inline bool isInRangeForImmU32(uint64_t Value) {
359 return Value <= std::numeric_limits<uint32_t>::max();
360}
361
362/// Returns true if the given int64_t value is in range for an int32_t.
363inline bool isInRangeForImmS32(int64_t Value) {
364 return (Value >= std::numeric_limits<int32_t>::min() &&
365 Value <= std::numeric_limits<int32_t>::max());
366}
367
368/// Apply fixup expression for edge to block content.
369inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
370 const Symbol *GOTSymbol) {
371 using namespace support;
372
373 char *BlockWorkingMem = B.getAlreadyMutableContent().data();
374 char *FixupPtr = BlockWorkingMem + E.getOffset();
375 JITTargetAddress FixupAddress = B.getAddress() + E.getOffset();
376
377 switch (E.getKind()) {
3
Control jumps to 'case Delta64FromGOT:' at line 446
378
379 case Pointer64: {
380 uint64_t Value = E.getTarget().getAddress() + E.getAddend();
381 *(ulittle64_t *)FixupPtr = Value;
382 break;
383 }
384
385 case Pointer32: {
386 uint64_t Value = E.getTarget().getAddress() + E.getAddend();
387 if (LLVM_LIKELY(isInRangeForImmU32(Value))__builtin_expect((bool)(isInRangeForImmU32(Value)), true))
388 *(ulittle32_t *)FixupPtr = Value;
389 else
390 return makeTargetOutOfRangeError(G, B, E);
391 break;
392 }
393 case Pointer32Signed: {
394 int64_t Value = E.getTarget().getAddress() + E.getAddend();
395 if (LLVM_LIKELY(isInRangeForImmS32(Value))__builtin_expect((bool)(isInRangeForImmS32(Value)), true))
396 *(little32_t *)FixupPtr = Value;
397 else
398 return makeTargetOutOfRangeError(G, B, E);
399 break;
400 }
401
402 case BranchPCRel32:
403 case BranchPCRel32ToPtrJumpStub:
404 case BranchPCRel32ToPtrJumpStubBypassable:
405 case PCRel32GOTLoadRelaxable:
406 case PCRel32GOTLoadREXRelaxable:
407 case PCRel32TLVPLoadREXRelaxable: {
408 int64_t Value =
409 E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend();
410 if (LLVM_LIKELY(isInRangeForImmS32(Value))__builtin_expect((bool)(isInRangeForImmS32(Value)), true))
411 *(little32_t *)FixupPtr = Value;
412 else
413 return makeTargetOutOfRangeError(G, B, E);
414 break;
415 }
416
417 case Delta64: {
418 int64_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend();
419 *(little64_t *)FixupPtr = Value;
420 break;
421 }
422
423 case Delta32: {
424 int64_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend();
425 if (LLVM_LIKELY(isInRangeForImmS32(Value))__builtin_expect((bool)(isInRangeForImmS32(Value)), true))
426 *(little32_t *)FixupPtr = Value;
427 else
428 return makeTargetOutOfRangeError(G, B, E);
429 break;
430 }
431
432 case NegDelta64: {
433 int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
434 *(little64_t *)FixupPtr = Value;
435 break;
436 }
437
438 case NegDelta32: {
439 int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
440 if (LLVM_LIKELY(isInRangeForImmS32(Value))__builtin_expect((bool)(isInRangeForImmS32(Value)), true))
441 *(little32_t *)FixupPtr = Value;
442 else
443 return makeTargetOutOfRangeError(G, B, E);
444 break;
445 }
446 case Delta64FromGOT: {
447 assert(GOTSymbol && "No GOT section symbol")(static_cast<void> (0));
448 int64_t Value =
449 E.getTarget().getAddress() - GOTSymbol->getAddress() + E.getAddend();
4
Called C++ object pointer is null
450 *(little64_t *)FixupPtr = Value;
451 break;
452 }
453
454 default: {
455 // If you hit this you should check that *constructor and other non-fixup
456 // edges have been removed prior to applying fixups.
457 llvm_unreachable("Graph contains edge kind with no fixup expression")__builtin_unreachable();
458 }
459 }
460
461 return Error::success();
462}
463
464/// x86_64 pointer size.
465constexpr uint64_t PointerSize = 8;
466
467/// x86-64 null pointer content.
468extern const char NullPointerContent[PointerSize];
469
470/// x86-64 pointer jump stub content.
471///
472/// Contains the instruction sequence for an indirect jump via an in-memory
473/// pointer:
474/// jmpq *ptr(%rip)
475extern const char PointerJumpStubContent[6];
476
477/// Creates a new pointer block in the given section and returns an anonymous
478/// symbol pointing to it.
479///
480/// If InitialTarget is given then an Pointer64 relocation will be added to the
481/// block pointing at InitialTarget.
482///
483/// The pointer block will have the following default values:
484/// alignment: 64-bit
485/// alignment-offset: 0
486/// address: highest allowable (~7U)
487inline Symbol &createAnonymousPointer(LinkGraph &G, Section &PointerSection,
488 Symbol *InitialTarget = nullptr,
489 uint64_t InitialAddend = 0) {
490 auto &B =
491 G.createContentBlock(PointerSection, NullPointerContent, ~7ULL, 8, 0);
492 if (InitialTarget)
493 B.addEdge(Pointer64, 0, *InitialTarget, InitialAddend);
494 return G.addAnonymousSymbol(B, 0, 8, false, false);
495}
496
497/// Create a jump stub block that jumps via the pointer at the given symbol.
498///
499/// The stub block will have the following default values:
500/// alignment: 8-bit
501/// alignment-offset: 0
502/// address: highest allowable: (~5U)
503inline Block &createPointerJumpStubBlock(LinkGraph &G, Section &StubSection,
504 Symbol &PointerSymbol) {
505 auto &B =
506 G.createContentBlock(StubSection, PointerJumpStubContent, ~5ULL, 1, 0);
507 B.addEdge(Delta32, 2, PointerSymbol, -4);
508 return B;
509}
510
511/// Create a jump stub that jumps via the pointer at the given symbol and
512/// an anonymous symbol pointing to it. Return the anonymous symbol.
513///
514/// The stub block will be created by createPointerJumpStubBlock.
515inline Symbol &createAnonymousPointerJumpStub(LinkGraph &G,
516 Section &StubSection,
517 Symbol &PointerSymbol) {
518 return G.addAnonymousSymbol(
519 createPointerJumpStubBlock(G, StubSection, PointerSymbol), 0, 6, true,
520 false);
521}
522
523} // namespace x86_64
524} // end namespace jitlink
525} // end namespace llvm
526
527#endif // LLVM_EXECUTIONENGINE_JITLINK_X86_64_H