Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
35271 views
1
//===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===//
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
#include "EHFrameSupportImpl.h"
10
11
#include "llvm/BinaryFormat/Dwarf.h"
12
#include "llvm/Config/config.h"
13
#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
14
#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
15
#include "llvm/Support/DynamicLibrary.h"
16
17
#define DEBUG_TYPE "jitlink"
18
19
namespace llvm {
20
namespace jitlink {
21
22
EHFrameEdgeFixer::EHFrameEdgeFixer(StringRef EHFrameSectionName,
23
unsigned PointerSize, Edge::Kind Pointer32,
24
Edge::Kind Pointer64, Edge::Kind Delta32,
25
Edge::Kind Delta64, Edge::Kind NegDelta32)
26
: EHFrameSectionName(EHFrameSectionName), PointerSize(PointerSize),
27
Pointer32(Pointer32), Pointer64(Pointer64), Delta32(Delta32),
28
Delta64(Delta64), NegDelta32(NegDelta32) {}
29
30
Error EHFrameEdgeFixer::operator()(LinkGraph &G) {
31
auto *EHFrame = G.findSectionByName(EHFrameSectionName);
32
33
if (!EHFrame) {
34
LLVM_DEBUG({
35
dbgs() << "EHFrameEdgeFixer: No " << EHFrameSectionName
36
<< " section in \"" << G.getName() << "\". Nothing to do.\n";
37
});
38
return Error::success();
39
}
40
41
// Check that we support the graph's pointer size.
42
if (G.getPointerSize() != 4 && G.getPointerSize() != 8)
43
return make_error<JITLinkError>(
44
"EHFrameEdgeFixer only supports 32 and 64 bit targets");
45
46
LLVM_DEBUG({
47
dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << " in \""
48
<< G.getName() << "\"...\n";
49
});
50
51
ParseContext PC(G);
52
53
// Build a map of all blocks and symbols in the text sections. We will use
54
// these for finding / building edge targets when processing FDEs.
55
for (auto &Sec : G.sections()) {
56
// Just record the most-canonical symbol (for eh-frame purposes) at each
57
// address.
58
for (auto *Sym : Sec.symbols()) {
59
auto &CurSym = PC.AddrToSym[Sym->getAddress()];
60
if (!CurSym || (std::make_tuple(Sym->getLinkage(), Sym->getScope(),
61
!Sym->hasName(), Sym->getName()) <
62
std::make_tuple(CurSym->getLinkage(), CurSym->getScope(),
63
!CurSym->hasName(), CurSym->getName())))
64
CurSym = Sym;
65
}
66
if (auto Err = PC.AddrToBlock.addBlocks(Sec.blocks(),
67
BlockAddressMap::includeNonNull))
68
return Err;
69
}
70
71
// Sort eh-frame blocks into address order to ensure we visit CIEs before
72
// their child FDEs.
73
std::vector<Block *> EHFrameBlocks;
74
for (auto *B : EHFrame->blocks())
75
EHFrameBlocks.push_back(B);
76
llvm::sort(EHFrameBlocks, [](const Block *LHS, const Block *RHS) {
77
return LHS->getAddress() < RHS->getAddress();
78
});
79
80
// Loop over the blocks in address order.
81
for (auto *B : EHFrameBlocks)
82
if (auto Err = processBlock(PC, *B))
83
return Err;
84
85
return Error::success();
86
}
87
88
static Expected<size_t> readCFIRecordLength(const Block &B,
89
BinaryStreamReader &R) {
90
uint32_t Length;
91
if (auto Err = R.readInteger(Length))
92
return std::move(Err);
93
94
// If Length < 0xffffffff then use the regular length field, otherwise
95
// read the extended length field.
96
if (Length != 0xffffffff)
97
return Length;
98
99
uint64_t ExtendedLength;
100
if (auto Err = R.readInteger(ExtendedLength))
101
return std::move(Err);
102
103
if (ExtendedLength > std::numeric_limits<size_t>::max())
104
return make_error<JITLinkError>(
105
"In CFI record at " +
106
formatv("{0:x}", B.getAddress() + R.getOffset() - 12) +
107
", extended length of " + formatv("{0:x}", ExtendedLength) +
108
" exceeds address-range max (" +
109
formatv("{0:x}", std::numeric_limits<size_t>::max()));
110
111
return ExtendedLength;
112
}
113
114
Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
115
116
LLVM_DEBUG(dbgs() << " Processing block at " << B.getAddress() << "\n");
117
118
// eh-frame should not contain zero-fill blocks.
119
if (B.isZeroFill())
120
return make_error<JITLinkError>("Unexpected zero-fill block in " +
121
EHFrameSectionName + " section");
122
123
if (B.getSize() == 0) {
124
LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n");
125
return Error::success();
126
}
127
128
// Find the offsets of any existing edges from this block.
129
BlockEdgesInfo BlockEdges;
130
for (auto &E : B.edges())
131
if (E.isRelocation()) {
132
// Check if we already saw more than one relocation at this offset.
133
if (BlockEdges.Multiple.contains(E.getOffset()))
134
continue;
135
136
// Otherwise check if we previously had exactly one relocation at this
137
// offset. If so, we now have a second one and move it from the TargetMap
138
// into the Multiple set.
139
auto It = BlockEdges.TargetMap.find(E.getOffset());
140
if (It != BlockEdges.TargetMap.end()) {
141
BlockEdges.TargetMap.erase(It);
142
BlockEdges.Multiple.insert(E.getOffset());
143
} else {
144
BlockEdges.TargetMap[E.getOffset()] = EdgeTarget(E);
145
}
146
}
147
148
BinaryStreamReader BlockReader(
149
StringRef(B.getContent().data(), B.getContent().size()),
150
PC.G.getEndianness());
151
152
// Get the record length.
153
Expected<size_t> RecordRemaining = readCFIRecordLength(B, BlockReader);
154
if (!RecordRemaining)
155
return RecordRemaining.takeError();
156
157
// We expect DWARFRecordSectionSplitter to split each CFI record into its own
158
// block.
159
if (BlockReader.bytesRemaining() != *RecordRemaining)
160
return make_error<JITLinkError>("Incomplete CFI record at " +
161
formatv("{0:x16}", B.getAddress()));
162
163
// Read the CIE delta for this record.
164
uint64_t CIEDeltaFieldOffset = BlockReader.getOffset();
165
uint32_t CIEDelta;
166
if (auto Err = BlockReader.readInteger(CIEDelta))
167
return Err;
168
169
if (CIEDelta == 0) {
170
if (auto Err = processCIE(PC, B, CIEDeltaFieldOffset, BlockEdges))
171
return Err;
172
} else {
173
if (auto Err = processFDE(PC, B, CIEDeltaFieldOffset, CIEDelta, BlockEdges))
174
return Err;
175
}
176
177
return Error::success();
178
}
179
180
Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
181
size_t CIEDeltaFieldOffset,
182
const BlockEdgesInfo &BlockEdges) {
183
184
LLVM_DEBUG(dbgs() << " Record is CIE\n");
185
186
BinaryStreamReader RecordReader(
187
StringRef(B.getContent().data(), B.getContent().size()),
188
PC.G.getEndianness());
189
190
// Skip past the CIE delta field: we've already processed this far.
191
RecordReader.setOffset(CIEDeltaFieldOffset + 4);
192
193
auto &CIESymbol = PC.G.addAnonymousSymbol(B, 0, B.getSize(), false, false);
194
CIEInformation CIEInfo(CIESymbol);
195
196
uint8_t Version = 0;
197
if (auto Err = RecordReader.readInteger(Version))
198
return Err;
199
200
if (Version != 0x01)
201
return make_error<JITLinkError>("Bad CIE version " + Twine(Version) +
202
" (should be 0x01) in eh-frame");
203
204
auto AugInfo = parseAugmentationString(RecordReader);
205
if (!AugInfo)
206
return AugInfo.takeError();
207
208
// Skip the EH Data field if present.
209
if (AugInfo->EHDataFieldPresent)
210
if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
211
return Err;
212
213
// Read and validate the code alignment factor.
214
{
215
uint64_t CodeAlignmentFactor = 0;
216
if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor))
217
return Err;
218
}
219
220
// Read and validate the data alignment factor.
221
{
222
int64_t DataAlignmentFactor = 0;
223
if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor))
224
return Err;
225
}
226
227
// Skip the return address register field.
228
if (auto Err = RecordReader.skip(1))
229
return Err;
230
231
if (AugInfo->AugmentationDataPresent) {
232
233
CIEInfo.AugmentationDataPresent = true;
234
235
uint64_t AugmentationDataLength = 0;
236
if (auto Err = RecordReader.readULEB128(AugmentationDataLength))
237
return Err;
238
239
uint32_t AugmentationDataStartOffset = RecordReader.getOffset();
240
241
uint8_t *NextField = &AugInfo->Fields[0];
242
while (uint8_t Field = *NextField++) {
243
switch (Field) {
244
case 'L':
245
CIEInfo.LSDAPresent = true;
246
if (auto PE = readPointerEncoding(RecordReader, B, "LSDA"))
247
CIEInfo.LSDAEncoding = *PE;
248
else
249
return PE.takeError();
250
break;
251
case 'P': {
252
auto PersonalityPointerEncoding =
253
readPointerEncoding(RecordReader, B, "personality");
254
if (!PersonalityPointerEncoding)
255
return PersonalityPointerEncoding.takeError();
256
if (auto Err =
257
getOrCreateEncodedPointerEdge(
258
PC, BlockEdges, *PersonalityPointerEncoding, RecordReader,
259
B, RecordReader.getOffset(), "personality")
260
.takeError())
261
return Err;
262
break;
263
}
264
case 'R':
265
if (auto PE = readPointerEncoding(RecordReader, B, "address")) {
266
CIEInfo.AddressEncoding = *PE;
267
if (CIEInfo.AddressEncoding == dwarf::DW_EH_PE_omit)
268
return make_error<JITLinkError>(
269
"Invalid address encoding DW_EH_PE_omit in CIE at " +
270
formatv("{0:x}", B.getAddress().getValue()));
271
} else
272
return PE.takeError();
273
break;
274
default:
275
llvm_unreachable("Invalid augmentation string field");
276
}
277
}
278
279
if (RecordReader.getOffset() - AugmentationDataStartOffset >
280
AugmentationDataLength)
281
return make_error<JITLinkError>("Read past the end of the augmentation "
282
"data while parsing fields");
283
}
284
285
assert(!PC.CIEInfos.count(CIESymbol.getAddress()) &&
286
"Multiple CIEs recorded at the same address?");
287
PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo);
288
289
return Error::success();
290
}
291
292
Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
293
size_t CIEDeltaFieldOffset,
294
uint32_t CIEDelta,
295
const BlockEdgesInfo &BlockEdges) {
296
LLVM_DEBUG(dbgs() << " Record is FDE\n");
297
298
orc::ExecutorAddr RecordAddress = B.getAddress();
299
300
BinaryStreamReader RecordReader(
301
StringRef(B.getContent().data(), B.getContent().size()),
302
PC.G.getEndianness());
303
304
// Skip past the CIE delta field: we've already read this far.
305
RecordReader.setOffset(CIEDeltaFieldOffset + 4);
306
307
auto &FDESymbol = PC.G.addAnonymousSymbol(B, 0, B.getSize(), false, false);
308
309
CIEInformation *CIEInfo = nullptr;
310
311
{
312
// Process the CIE pointer field.
313
if (BlockEdges.Multiple.contains(CIEDeltaFieldOffset))
314
return make_error<JITLinkError>(
315
"CIE pointer field already has multiple edges at " +
316
formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset));
317
318
auto CIEEdgeItr = BlockEdges.TargetMap.find(CIEDeltaFieldOffset);
319
320
orc::ExecutorAddr CIEAddress =
321
RecordAddress + orc::ExecutorAddrDiff(CIEDeltaFieldOffset) -
322
orc::ExecutorAddrDiff(CIEDelta);
323
if (CIEEdgeItr == BlockEdges.TargetMap.end()) {
324
LLVM_DEBUG({
325
dbgs() << " Adding edge at "
326
<< (RecordAddress + CIEDeltaFieldOffset)
327
<< " to CIE at: " << CIEAddress << "\n";
328
});
329
if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress))
330
CIEInfo = *CIEInfoOrErr;
331
else
332
return CIEInfoOrErr.takeError();
333
assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set");
334
B.addEdge(NegDelta32, CIEDeltaFieldOffset, *CIEInfo->CIESymbol, 0);
335
} else {
336
LLVM_DEBUG({
337
dbgs() << " Already has edge at "
338
<< (RecordAddress + CIEDeltaFieldOffset) << " to CIE at "
339
<< CIEAddress << "\n";
340
});
341
auto &EI = CIEEdgeItr->second;
342
if (EI.Addend)
343
return make_error<JITLinkError>(
344
"CIE edge at " +
345
formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) +
346
" has non-zero addend");
347
if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress()))
348
CIEInfo = *CIEInfoOrErr;
349
else
350
return CIEInfoOrErr.takeError();
351
}
352
}
353
354
// Process the PC-Begin field.
355
LLVM_DEBUG({
356
dbgs() << " Processing PC-begin at "
357
<< (RecordAddress + RecordReader.getOffset()) << "\n";
358
});
359
if (auto PCBegin = getOrCreateEncodedPointerEdge(
360
PC, BlockEdges, CIEInfo->AddressEncoding, RecordReader, B,
361
RecordReader.getOffset(), "PC begin")) {
362
assert(*PCBegin && "PC-begin symbol not set");
363
if ((*PCBegin)->isDefined()) {
364
// Add a keep-alive edge from the FDE target to the FDE to ensure that the
365
// FDE is kept alive if its target is.
366
LLVM_DEBUG({
367
dbgs() << " Adding keep-alive edge from target at "
368
<< (*PCBegin)->getBlock().getAddress() << " to FDE at "
369
<< RecordAddress << "\n";
370
});
371
(*PCBegin)->getBlock().addEdge(Edge::KeepAlive, 0, FDESymbol, 0);
372
} else {
373
LLVM_DEBUG({
374
dbgs() << " WARNING: Not adding keep-alive edge to FDE at "
375
<< RecordAddress << ", which points to "
376
<< ((*PCBegin)->isExternal() ? "external" : "absolute")
377
<< " symbol \"" << (*PCBegin)->getName()
378
<< "\" -- FDE must be kept alive manually or it will be "
379
<< "dead stripped.\n";
380
});
381
}
382
} else
383
return PCBegin.takeError();
384
385
// Skip over the PC range size field.
386
if (auto Err = skipEncodedPointer(CIEInfo->AddressEncoding, RecordReader))
387
return Err;
388
389
if (CIEInfo->AugmentationDataPresent) {
390
uint64_t AugmentationDataSize;
391
if (auto Err = RecordReader.readULEB128(AugmentationDataSize))
392
return Err;
393
394
if (CIEInfo->LSDAPresent)
395
if (auto Err = getOrCreateEncodedPointerEdge(
396
PC, BlockEdges, CIEInfo->LSDAEncoding, RecordReader, B,
397
RecordReader.getOffset(), "LSDA")
398
.takeError())
399
return Err;
400
} else {
401
LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n");
402
}
403
404
return Error::success();
405
}
406
407
Expected<EHFrameEdgeFixer::AugmentationInfo>
408
EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {
409
AugmentationInfo AugInfo;
410
uint8_t NextChar;
411
uint8_t *NextField = &AugInfo.Fields[0];
412
413
if (auto Err = RecordReader.readInteger(NextChar))
414
return std::move(Err);
415
416
while (NextChar != 0) {
417
switch (NextChar) {
418
case 'z':
419
AugInfo.AugmentationDataPresent = true;
420
break;
421
case 'e':
422
if (auto Err = RecordReader.readInteger(NextChar))
423
return std::move(Err);
424
if (NextChar != 'h')
425
return make_error<JITLinkError>("Unrecognized substring e" +
426
Twine(NextChar) +
427
" in augmentation string");
428
AugInfo.EHDataFieldPresent = true;
429
break;
430
case 'L':
431
case 'P':
432
case 'R':
433
*NextField++ = NextChar;
434
break;
435
default:
436
return make_error<JITLinkError>("Unrecognized character " +
437
Twine(NextChar) +
438
" in augmentation string");
439
}
440
441
if (auto Err = RecordReader.readInteger(NextChar))
442
return std::move(Err);
443
}
444
445
return std::move(AugInfo);
446
}
447
448
Expected<uint8_t> EHFrameEdgeFixer::readPointerEncoding(BinaryStreamReader &R,
449
Block &InBlock,
450
const char *FieldName) {
451
using namespace dwarf;
452
453
uint8_t PointerEncoding;
454
if (auto Err = R.readInteger(PointerEncoding))
455
return std::move(Err);
456
457
bool Supported = true;
458
switch (PointerEncoding & 0xf) {
459
case DW_EH_PE_uleb128:
460
case DW_EH_PE_udata2:
461
case DW_EH_PE_sleb128:
462
case DW_EH_PE_sdata2:
463
Supported = false;
464
break;
465
}
466
if (Supported) {
467
switch (PointerEncoding & 0x70) {
468
case DW_EH_PE_textrel:
469
case DW_EH_PE_datarel:
470
case DW_EH_PE_funcrel:
471
case DW_EH_PE_aligned:
472
Supported = false;
473
break;
474
}
475
}
476
477
if (Supported)
478
return PointerEncoding;
479
480
return make_error<JITLinkError>("Unsupported pointer encoding " +
481
formatv("{0:x2}", PointerEncoding) + " for " +
482
FieldName + "in CFI record at " +
483
formatv("{0:x16}", InBlock.getAddress()));
484
}
485
486
Error EHFrameEdgeFixer::skipEncodedPointer(uint8_t PointerEncoding,
487
BinaryStreamReader &RecordReader) {
488
using namespace dwarf;
489
490
// Switch absptr to corresponding udata encoding.
491
if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)
492
PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
493
494
switch (PointerEncoding & 0xf) {
495
case DW_EH_PE_udata4:
496
case DW_EH_PE_sdata4:
497
if (auto Err = RecordReader.skip(4))
498
return Err;
499
break;
500
case DW_EH_PE_udata8:
501
case DW_EH_PE_sdata8:
502
if (auto Err = RecordReader.skip(8))
503
return Err;
504
break;
505
default:
506
llvm_unreachable("Unrecognized encoding");
507
}
508
return Error::success();
509
}
510
511
Expected<Symbol *> EHFrameEdgeFixer::getOrCreateEncodedPointerEdge(
512
ParseContext &PC, const BlockEdgesInfo &BlockEdges, uint8_t PointerEncoding,
513
BinaryStreamReader &RecordReader, Block &BlockToFix,
514
size_t PointerFieldOffset, const char *FieldName) {
515
using namespace dwarf;
516
517
if (PointerEncoding == DW_EH_PE_omit)
518
return nullptr;
519
520
// If there's already an edge here then just skip the encoded pointer and
521
// return the edge's target.
522
{
523
auto EdgeI = BlockEdges.TargetMap.find(PointerFieldOffset);
524
if (EdgeI != BlockEdges.TargetMap.end()) {
525
LLVM_DEBUG({
526
dbgs() << " Existing edge at "
527
<< (BlockToFix.getAddress() + PointerFieldOffset) << " to "
528
<< FieldName << " at " << EdgeI->second.Target->getAddress();
529
if (EdgeI->second.Target->hasName())
530
dbgs() << " (" << EdgeI->second.Target->getName() << ")";
531
dbgs() << "\n";
532
});
533
if (auto Err = skipEncodedPointer(PointerEncoding, RecordReader))
534
return std::move(Err);
535
return EdgeI->second.Target;
536
}
537
538
if (BlockEdges.Multiple.contains(PointerFieldOffset))
539
return make_error<JITLinkError>("Multiple relocations at offset " +
540
formatv("{0:x16}", PointerFieldOffset));
541
}
542
543
// Switch absptr to corresponding udata encoding.
544
if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)
545
PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
546
547
// We need to create an edge. Start by reading the field value.
548
uint64_t FieldValue;
549
bool Is64Bit = false;
550
switch (PointerEncoding & 0xf) {
551
case DW_EH_PE_udata4: {
552
uint32_t Val;
553
if (auto Err = RecordReader.readInteger(Val))
554
return std::move(Err);
555
FieldValue = Val;
556
break;
557
}
558
case DW_EH_PE_sdata4: {
559
uint32_t Val;
560
if (auto Err = RecordReader.readInteger(Val))
561
return std::move(Err);
562
FieldValue = Val;
563
break;
564
}
565
case DW_EH_PE_udata8:
566
case DW_EH_PE_sdata8:
567
Is64Bit = true;
568
if (auto Err = RecordReader.readInteger(FieldValue))
569
return std::move(Err);
570
break;
571
default:
572
llvm_unreachable("Unsupported encoding");
573
}
574
575
// Find the edge target and edge kind to use.
576
orc::ExecutorAddr Target;
577
Edge::Kind PtrEdgeKind = Edge::Invalid;
578
if ((PointerEncoding & 0x70) == DW_EH_PE_pcrel) {
579
Target = BlockToFix.getAddress() + PointerFieldOffset;
580
PtrEdgeKind = Is64Bit ? Delta64 : Delta32;
581
} else
582
PtrEdgeKind = Is64Bit ? Pointer64 : Pointer32;
583
Target += FieldValue;
584
585
// Find or create a symbol to point the edge at.
586
auto TargetSym = getOrCreateSymbol(PC, Target);
587
if (!TargetSym)
588
return TargetSym.takeError();
589
BlockToFix.addEdge(PtrEdgeKind, PointerFieldOffset, *TargetSym, 0);
590
591
LLVM_DEBUG({
592
dbgs() << " Adding edge at "
593
<< (BlockToFix.getAddress() + PointerFieldOffset) << " to "
594
<< FieldName << " at " << TargetSym->getAddress();
595
if (TargetSym->hasName())
596
dbgs() << " (" << TargetSym->getName() << ")";
597
dbgs() << "\n";
598
});
599
600
return &*TargetSym;
601
}
602
603
Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
604
orc::ExecutorAddr Addr) {
605
// See whether we have a canonical symbol for the given address already.
606
auto CanonicalSymI = PC.AddrToSym.find(Addr);
607
if (CanonicalSymI != PC.AddrToSym.end())
608
return *CanonicalSymI->second;
609
610
// Otherwise search for a block covering the address and create a new symbol.
611
auto *B = PC.AddrToBlock.getBlockCovering(Addr);
612
if (!B)
613
return make_error<JITLinkError>("No symbol or block covering address " +
614
formatv("{0:x16}", Addr));
615
616
auto &S =
617
PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false);
618
PC.AddrToSym[S.getAddress()] = &S;
619
return S;
620
}
621
622
char EHFrameNullTerminator::NullTerminatorBlockContent[4] = {0, 0, 0, 0};
623
624
EHFrameNullTerminator::EHFrameNullTerminator(StringRef EHFrameSectionName)
625
: EHFrameSectionName(EHFrameSectionName) {}
626
627
Error EHFrameNullTerminator::operator()(LinkGraph &G) {
628
auto *EHFrame = G.findSectionByName(EHFrameSectionName);
629
630
if (!EHFrame)
631
return Error::success();
632
633
LLVM_DEBUG({
634
dbgs() << "EHFrameNullTerminator adding null terminator to "
635
<< EHFrameSectionName << "\n";
636
});
637
638
auto &NullTerminatorBlock =
639
G.createContentBlock(*EHFrame, NullTerminatorBlockContent,
640
orc::ExecutorAddr(~uint64_t(4)), 1, 0);
641
G.addAnonymousSymbol(NullTerminatorBlock, 0, 4, false, true);
642
return Error::success();
643
}
644
645
EHFrameRegistrar::~EHFrameRegistrar() = default;
646
647
Error InProcessEHFrameRegistrar::registerEHFrames(
648
orc::ExecutorAddrRange EHFrameSection) {
649
return orc::registerEHFrameSection(EHFrameSection.Start.toPtr<void *>(),
650
EHFrameSection.size());
651
}
652
653
Error InProcessEHFrameRegistrar::deregisterEHFrames(
654
orc::ExecutorAddrRange EHFrameSection) {
655
return orc::deregisterEHFrameSection(EHFrameSection.Start.toPtr<void *>(),
656
EHFrameSection.size());
657
}
658
659
EHFrameCFIBlockInspector EHFrameCFIBlockInspector::FromEdgeScan(Block &B) {
660
if (B.edges_empty())
661
return EHFrameCFIBlockInspector(nullptr);
662
if (B.edges_size() == 1)
663
return EHFrameCFIBlockInspector(&*B.edges().begin());
664
SmallVector<Edge *, 3> Es;
665
for (auto &E : B.edges())
666
Es.push_back(&E);
667
assert(Es.size() >= 2 && Es.size() <= 3 && "Unexpected number of edges");
668
llvm::sort(Es, [](const Edge *LHS, const Edge *RHS) {
669
return LHS->getOffset() < RHS->getOffset();
670
});
671
return EHFrameCFIBlockInspector(*Es[0], *Es[1],
672
Es.size() == 3 ? Es[2] : nullptr);
673
return EHFrameCFIBlockInspector(nullptr);
674
}
675
676
EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge *PersonalityEdge)
677
: PersonalityEdge(PersonalityEdge) {}
678
679
EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge &CIEEdge,
680
Edge &PCBeginEdge,
681
Edge *LSDAEdge)
682
: CIEEdge(&CIEEdge), PCBeginEdge(&PCBeginEdge), LSDAEdge(LSDAEdge) {}
683
684
LinkGraphPassFunction
685
createEHFrameRecorderPass(const Triple &TT,
686
StoreFrameRangeFunction StoreRangeAddress) {
687
const char *EHFrameSectionName = nullptr;
688
if (TT.getObjectFormat() == Triple::MachO)
689
EHFrameSectionName = "__TEXT,__eh_frame";
690
else
691
EHFrameSectionName = ".eh_frame";
692
693
auto RecordEHFrame =
694
[EHFrameSectionName,
695
StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error {
696
// Search for a non-empty eh-frame and record the address of the first
697
// symbol in it.
698
orc::ExecutorAddr Addr;
699
size_t Size = 0;
700
if (auto *S = G.findSectionByName(EHFrameSectionName)) {
701
auto R = SectionRange(*S);
702
Addr = R.getStart();
703
Size = R.getSize();
704
}
705
if (!Addr && Size != 0)
706
return make_error<JITLinkError>(
707
StringRef(EHFrameSectionName) +
708
" section can not have zero address with non-zero size");
709
StoreFrameRange(Addr, Size);
710
return Error::success();
711
};
712
713
return RecordEHFrame;
714
}
715
716
} // end namespace jitlink
717
} // end namespace llvm
718
719