1 //===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "EHFrameSupportImpl.h"
11
12 #include "llvm/BinaryFormat/Dwarf.h"
13 #include "llvm/Config/config.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
EHFrameSplitter(StringRef EHFrameSectionName)22 EHFrameSplitter::EHFrameSplitter(StringRef EHFrameSectionName)
23 : EHFrameSectionName(EHFrameSectionName) {}
24
operator ()(LinkGraph & G)25 Error EHFrameSplitter::operator()(LinkGraph &G) {
26 auto *EHFrame = G.findSectionByName(EHFrameSectionName);
27
28 if (!EHFrame) {
29 LLVM_DEBUG({
30 dbgs() << "EHFrameSplitter: No " << EHFrameSectionName
31 << " section. Nothing to do\n";
32 });
33 return Error::success();
34 }
35
36 LLVM_DEBUG({
37 dbgs() << "EHFrameSplitter: Processing " << EHFrameSectionName << "...\n";
38 });
39
40 DenseMap<Block *, LinkGraph::SplitBlockCache> Caches;
41
42 {
43 // Pre-build the split caches.
44 for (auto *B : EHFrame->blocks())
45 Caches[B] = LinkGraph::SplitBlockCache::value_type();
46 for (auto *Sym : EHFrame->symbols())
47 Caches[&Sym->getBlock()]->push_back(Sym);
48 for (auto *B : EHFrame->blocks())
49 llvm::sort(*Caches[B], [](const Symbol *LHS, const Symbol *RHS) {
50 return LHS->getOffset() > RHS->getOffset();
51 });
52 }
53
54 // Iterate over blocks (we do this by iterating over Caches entries rather
55 // than EHFrame->blocks() as we will be inserting new blocks along the way,
56 // which would invalidate iterators in the latter sequence.
57 for (auto &KV : Caches) {
58 auto &B = *KV.first;
59 auto &BCache = KV.second;
60 if (auto Err = processBlock(G, B, BCache))
61 return Err;
62 }
63
64 return Error::success();
65 }
66
processBlock(LinkGraph & G,Block & B,LinkGraph::SplitBlockCache & Cache)67 Error EHFrameSplitter::processBlock(LinkGraph &G, Block &B,
68 LinkGraph::SplitBlockCache &Cache) {
69 LLVM_DEBUG({
70 dbgs() << " Processing block at " << formatv("{0:x16}", B.getAddress())
71 << "\n";
72 });
73
74 // eh-frame should not contain zero-fill blocks.
75 if (B.isZeroFill())
76 return make_error<JITLinkError>("Unexpected zero-fill block in " +
77 EHFrameSectionName + " section");
78
79 if (B.getSize() == 0) {
80 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n");
81 return Error::success();
82 }
83
84 BinaryStreamReader BlockReader(B.getContent(), G.getEndianness());
85
86 while (true) {
87 uint64_t RecordStartOffset = BlockReader.getOffset();
88
89 LLVM_DEBUG({
90 dbgs() << " Processing CFI record at "
91 << formatv("{0:x16}", B.getAddress()) << "\n";
92 });
93
94 uint32_t Length;
95 if (auto Err = BlockReader.readInteger(Length))
96 return Err;
97 if (Length != 0xffffffff) {
98 if (auto Err = BlockReader.skip(Length))
99 return Err;
100 } else {
101 uint64_t ExtendedLength;
102 if (auto Err = BlockReader.readInteger(ExtendedLength))
103 return Err;
104 if (auto Err = BlockReader.skip(ExtendedLength))
105 return Err;
106 }
107
108 // If this was the last block then there's nothing to split
109 if (BlockReader.empty()) {
110 LLVM_DEBUG(dbgs() << " Extracted " << B << "\n");
111 return Error::success();
112 }
113
114 uint64_t BlockSize = BlockReader.getOffset() - RecordStartOffset;
115 auto &NewBlock = G.splitBlock(B, BlockSize);
116 (void)NewBlock;
117 LLVM_DEBUG(dbgs() << " Extracted " << NewBlock << "\n");
118 }
119 }
120
EHFrameEdgeFixer(StringRef EHFrameSectionName,unsigned PointerSize,Edge::Kind Delta64,Edge::Kind Delta32,Edge::Kind NegDelta32)121 EHFrameEdgeFixer::EHFrameEdgeFixer(StringRef EHFrameSectionName,
122 unsigned PointerSize, Edge::Kind Delta64,
123 Edge::Kind Delta32, Edge::Kind NegDelta32)
124 : EHFrameSectionName(EHFrameSectionName), PointerSize(PointerSize),
125 Delta64(Delta64), Delta32(Delta32), NegDelta32(NegDelta32) {}
126
operator ()(LinkGraph & G)127 Error EHFrameEdgeFixer::operator()(LinkGraph &G) {
128 auto *EHFrame = G.findSectionByName(EHFrameSectionName);
129
130 if (!EHFrame) {
131 LLVM_DEBUG({
132 dbgs() << "EHFrameEdgeFixer: No " << EHFrameSectionName
133 << " section. Nothing to do\n";
134 });
135 return Error::success();
136 }
137
138 // Check that we support the graph's pointer size.
139 if (G.getPointerSize() != 4 && G.getPointerSize() != 8)
140 return make_error<JITLinkError>(
141 "EHFrameEdgeFixer only supports 32 and 64 bit targets");
142
143 LLVM_DEBUG({
144 dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << "...\n";
145 });
146
147 ParseContext PC(G);
148
149 // Build a map of all blocks and symbols in the text sections. We will use
150 // these for finding / building edge targets when processing FDEs.
151 for (auto &Sec : G.sections()) {
152 PC.AddrToSyms.addSymbols(Sec.symbols());
153 if (auto Err = PC.AddrToBlock.addBlocks(Sec.blocks(),
154 BlockAddressMap::includeNonNull))
155 return Err;
156 }
157
158 // Sort eh-frame blocks into address order to ensure we visit CIEs before
159 // their child FDEs.
160 std::vector<Block *> EHFrameBlocks;
161 for (auto *B : EHFrame->blocks())
162 EHFrameBlocks.push_back(B);
163 llvm::sort(EHFrameBlocks, [](const Block *LHS, const Block *RHS) {
164 return LHS->getAddress() < RHS->getAddress();
165 });
166
167 // Loop over the blocks in address order.
168 for (auto *B : EHFrameBlocks)
169 if (auto Err = processBlock(PC, *B))
170 return Err;
171
172 return Error::success();
173 }
174
processBlock(ParseContext & PC,Block & B)175 Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
176
177 LLVM_DEBUG({
178 dbgs() << " Processing block at " << formatv("{0:x16}", B.getAddress())
179 << "\n";
180 });
181
182 // eh-frame should not contain zero-fill blocks.
183 if (B.isZeroFill())
184 return make_error<JITLinkError>("Unexpected zero-fill block in " +
185 EHFrameSectionName + " section");
186
187 if (B.getSize() == 0) {
188 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n");
189 return Error::success();
190 }
191
192 // Find the offsets of any existing edges from this block.
193 BlockEdgeMap BlockEdges;
194 for (auto &E : B.edges())
195 if (E.isRelocation()) {
196 if (BlockEdges.count(E.getOffset()))
197 return make_error<JITLinkError>(
198 "Multiple relocations at offset " +
199 formatv("{0:x16}", E.getOffset()) + " in " + EHFrameSectionName +
200 " block at address " + formatv("{0:x16}", B.getAddress()));
201
202 BlockEdges[E.getOffset()] = EdgeTarget(E);
203 }
204
205 CIEInfosMap CIEInfos;
206 BinaryStreamReader BlockReader(B.getContent(), PC.G.getEndianness());
207 while (!BlockReader.empty()) {
208 size_t RecordStartOffset = BlockReader.getOffset();
209
210 LLVM_DEBUG({
211 dbgs() << " Processing CFI record at "
212 << formatv("{0:x16}", B.getAddress() + RecordStartOffset) << "\n";
213 });
214
215 // Get the record length.
216 size_t RecordRemaining;
217 {
218 uint32_t Length;
219 if (auto Err = BlockReader.readInteger(Length))
220 return Err;
221 // If Length < 0xffffffff then use the regular length field, otherwise
222 // read the extended length field.
223 if (Length != 0xffffffff)
224 RecordRemaining = Length;
225 else {
226 uint64_t ExtendedLength;
227 if (auto Err = BlockReader.readInteger(ExtendedLength))
228 return Err;
229 RecordRemaining = ExtendedLength;
230 }
231 }
232
233 if (BlockReader.bytesRemaining() < RecordRemaining)
234 return make_error<JITLinkError>(
235 "Incomplete CFI record at " +
236 formatv("{0:x16}", B.getAddress() + RecordStartOffset));
237
238 // Read the CIE delta for this record.
239 uint64_t CIEDeltaFieldOffset = BlockReader.getOffset() - RecordStartOffset;
240 uint32_t CIEDelta;
241 if (auto Err = BlockReader.readInteger(CIEDelta))
242 return Err;
243
244 if (CIEDelta == 0) {
245 if (auto Err = processCIE(PC, B, RecordStartOffset,
246 CIEDeltaFieldOffset + RecordRemaining,
247 CIEDeltaFieldOffset))
248 return Err;
249 } else {
250 if (auto Err = processFDE(PC, B, RecordStartOffset,
251 CIEDeltaFieldOffset + RecordRemaining,
252 CIEDeltaFieldOffset, CIEDelta, BlockEdges))
253 return Err;
254 }
255
256 // Move to the next record.
257 BlockReader.setOffset(RecordStartOffset + CIEDeltaFieldOffset +
258 RecordRemaining);
259 }
260
261 return Error::success();
262 }
263
processCIE(ParseContext & PC,Block & B,size_t RecordOffset,size_t RecordLength,size_t CIEDeltaFieldOffset)264 Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
265 size_t RecordOffset, size_t RecordLength,
266 size_t CIEDeltaFieldOffset) {
267
268 LLVM_DEBUG(dbgs() << " Record is CIE\n");
269
270 auto RecordContent = B.getContent().substr(RecordOffset, RecordLength);
271 BinaryStreamReader RecordReader(RecordContent, PC.G.getEndianness());
272
273 // Skip past the CIE delta field: we've already processed this far.
274 RecordReader.setOffset(CIEDeltaFieldOffset + 4);
275
276 auto &CIESymbol =
277 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
278 CIEInformation CIEInfo(CIESymbol);
279
280 uint8_t Version = 0;
281 if (auto Err = RecordReader.readInteger(Version))
282 return Err;
283
284 if (Version != 0x01)
285 return make_error<JITLinkError>("Bad CIE version " + Twine(Version) +
286 " (should be 0x01) in eh-frame");
287
288 auto AugInfo = parseAugmentationString(RecordReader);
289 if (!AugInfo)
290 return AugInfo.takeError();
291
292 // Skip the EH Data field if present.
293 if (AugInfo->EHDataFieldPresent)
294 if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
295 return Err;
296
297 // Read and sanity check the code alignment factor.
298 {
299 uint64_t CodeAlignmentFactor = 0;
300 if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor))
301 return Err;
302 if (CodeAlignmentFactor != 1)
303 return make_error<JITLinkError>("Unsupported CIE code alignment factor " +
304 Twine(CodeAlignmentFactor) +
305 " (expected 1)");
306 }
307
308 // Read and sanity check the data alignment factor.
309 {
310 int64_t DataAlignmentFactor = 0;
311 if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor))
312 return Err;
313 if (DataAlignmentFactor != -8)
314 return make_error<JITLinkError>("Unsupported CIE data alignment factor " +
315 Twine(DataAlignmentFactor) +
316 " (expected -8)");
317 }
318
319 // Skip the return address register field.
320 if (auto Err = RecordReader.skip(1))
321 return Err;
322
323 uint64_t AugmentationDataLength = 0;
324 if (auto Err = RecordReader.readULEB128(AugmentationDataLength))
325 return Err;
326
327 uint32_t AugmentationDataStartOffset = RecordReader.getOffset();
328
329 uint8_t *NextField = &AugInfo->Fields[0];
330 while (uint8_t Field = *NextField++) {
331 switch (Field) {
332 case 'L': {
333 CIEInfo.FDEsHaveLSDAField = true;
334 uint8_t LSDAPointerEncoding;
335 if (auto Err = RecordReader.readInteger(LSDAPointerEncoding))
336 return Err;
337 if (!isSupportedPointerEncoding(LSDAPointerEncoding))
338 return make_error<JITLinkError>(
339 "Unsupported LSDA pointer encoding " +
340 formatv("{0:x2}", LSDAPointerEncoding) + " in CIE at " +
341 formatv("{0:x16}", CIESymbol.getAddress()));
342 CIEInfo.LSDAPointerEncoding = LSDAPointerEncoding;
343 break;
344 }
345 case 'P': {
346 uint8_t PersonalityPointerEncoding = 0;
347 if (auto Err = RecordReader.readInteger(PersonalityPointerEncoding))
348 return Err;
349 if (PersonalityPointerEncoding !=
350 (dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
351 dwarf::DW_EH_PE_sdata4))
352 return make_error<JITLinkError>(
353 "Unspported personality pointer "
354 "encoding " +
355 formatv("{0:x2}", PersonalityPointerEncoding) + " in CIE at " +
356 formatv("{0:x16}", CIESymbol.getAddress()));
357 uint32_t PersonalityPointerAddress;
358 if (auto Err = RecordReader.readInteger(PersonalityPointerAddress))
359 return Err;
360 break;
361 }
362 case 'R': {
363 uint8_t FDEPointerEncoding;
364 if (auto Err = RecordReader.readInteger(FDEPointerEncoding))
365 return Err;
366 if (!isSupportedPointerEncoding(FDEPointerEncoding))
367 return make_error<JITLinkError>(
368 "Unsupported FDE pointer encoding " +
369 formatv("{0:x2}", FDEPointerEncoding) + " in CIE at " +
370 formatv("{0:x16}", CIESymbol.getAddress()));
371 CIEInfo.FDEPointerEncoding = FDEPointerEncoding;
372 break;
373 }
374 default:
375 llvm_unreachable("Invalid augmentation string field");
376 }
377 }
378
379 if (RecordReader.getOffset() - AugmentationDataStartOffset >
380 AugmentationDataLength)
381 return make_error<JITLinkError>("Read past the end of the augmentation "
382 "data while parsing fields");
383
384 assert(!PC.CIEInfos.count(CIESymbol.getAddress()) &&
385 "Multiple CIEs recorded at the same address?");
386 PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo);
387
388 return Error::success();
389 }
390
processFDE(ParseContext & PC,Block & B,size_t RecordOffset,size_t RecordLength,size_t CIEDeltaFieldOffset,uint32_t CIEDelta,BlockEdgeMap & BlockEdges)391 Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
392 size_t RecordOffset, size_t RecordLength,
393 size_t CIEDeltaFieldOffset,
394 uint32_t CIEDelta,
395 BlockEdgeMap &BlockEdges) {
396 LLVM_DEBUG(dbgs() << " Record is FDE\n");
397
398 JITTargetAddress RecordAddress = B.getAddress() + RecordOffset;
399
400 auto RecordContent = B.getContent().substr(RecordOffset, RecordLength);
401 BinaryStreamReader RecordReader(RecordContent, PC.G.getEndianness());
402
403 // Skip past the CIE delta field: we've already read this far.
404 RecordReader.setOffset(CIEDeltaFieldOffset + 4);
405
406 auto &FDESymbol =
407 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
408
409 CIEInformation *CIEInfo = nullptr;
410
411 {
412 // Process the CIE pointer field.
413 auto CIEEdgeItr = BlockEdges.find(RecordOffset + CIEDeltaFieldOffset);
414 JITTargetAddress CIEAddress =
415 RecordAddress + CIEDeltaFieldOffset - CIEDelta;
416 if (CIEEdgeItr == BlockEdges.end()) {
417
418 LLVM_DEBUG({
419 dbgs() << " Adding edge at "
420 << formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset)
421 << " to CIE at: " << formatv("{0:x16}", CIEAddress) << "\n";
422 });
423 if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress))
424 CIEInfo = *CIEInfoOrErr;
425 else
426 return CIEInfoOrErr.takeError();
427 assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set");
428 B.addEdge(NegDelta32, RecordOffset + CIEDeltaFieldOffset,
429 *CIEInfo->CIESymbol, 0);
430 } else {
431 LLVM_DEBUG({
432 dbgs() << " Already has edge at "
433 << formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset)
434 << " to CIE at " << formatv("{0:x16}", CIEAddress) << "\n";
435 });
436 auto &EI = CIEEdgeItr->second;
437 if (EI.Addend)
438 return make_error<JITLinkError>(
439 "CIE edge at " +
440 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) +
441 " has non-zero addend");
442 if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress()))
443 CIEInfo = *CIEInfoOrErr;
444 else
445 return CIEInfoOrErr.takeError();
446 }
447 }
448
449 {
450 // Process the PC-Begin field.
451 Block *PCBeginBlock = nullptr;
452 JITTargetAddress PCBeginFieldOffset = RecordReader.getOffset();
453 auto PCEdgeItr = BlockEdges.find(RecordOffset + PCBeginFieldOffset);
454 if (PCEdgeItr == BlockEdges.end()) {
455 auto PCBeginPtrInfo =
456 readEncodedPointer(CIEInfo->FDEPointerEncoding,
457 RecordAddress + PCBeginFieldOffset, RecordReader);
458 if (!PCBeginPtrInfo)
459 return PCBeginPtrInfo.takeError();
460 JITTargetAddress PCBegin = PCBeginPtrInfo->first;
461 Edge::Kind PCBeginEdgeKind = PCBeginPtrInfo->second;
462 LLVM_DEBUG({
463 dbgs() << " Adding edge at "
464 << formatv("{0:x16}", RecordAddress + PCBeginFieldOffset)
465 << " to PC at " << formatv("{0:x16}", PCBegin) << "\n";
466 });
467 auto PCBeginSym = getOrCreateSymbol(PC, PCBegin);
468 if (!PCBeginSym)
469 return PCBeginSym.takeError();
470 B.addEdge(PCBeginEdgeKind, RecordOffset + PCBeginFieldOffset, *PCBeginSym,
471 0);
472 PCBeginBlock = &PCBeginSym->getBlock();
473 } else {
474 auto &EI = PCEdgeItr->second;
475 LLVM_DEBUG({
476 dbgs() << " Already has edge at "
477 << formatv("{0:x16}", RecordAddress + PCBeginFieldOffset)
478 << " to PC at " << formatv("{0:x16}", EI.Target->getAddress());
479 if (EI.Addend)
480 dbgs() << " + " << formatv("{0:x16}", EI.Addend);
481 dbgs() << "\n";
482 });
483
484 // Make sure the existing edge points at a defined block.
485 if (!EI.Target->isDefined()) {
486 auto EdgeAddr = RecordAddress + PCBeginFieldOffset;
487 return make_error<JITLinkError>("FDE edge at " +
488 formatv("{0:x16}", EdgeAddr) +
489 " points at external block");
490 }
491 PCBeginBlock = &EI.Target->getBlock();
492 if (auto Err = RecordReader.skip(
493 getPointerEncodingDataSize(CIEInfo->FDEPointerEncoding)))
494 return Err;
495 }
496
497 // Add a keep-alive edge from the FDE target to the FDE to ensure that the
498 // FDE is kept alive if its target is.
499 assert(PCBeginBlock && "PC-begin block not recorded");
500 LLVM_DEBUG({
501 dbgs() << " Adding keep-alive edge from target at "
502 << formatv("{0:x16}", PCBeginBlock->getAddress()) << " to FDE at "
503 << formatv("{0:x16}", RecordAddress) << "\n";
504 });
505 PCBeginBlock->addEdge(Edge::KeepAlive, 0, FDESymbol, 0);
506 }
507
508 // Skip over the PC range size field.
509 if (auto Err = RecordReader.skip(
510 getPointerEncodingDataSize(CIEInfo->FDEPointerEncoding)))
511 return Err;
512
513 if (CIEInfo->FDEsHaveLSDAField) {
514 uint64_t AugmentationDataSize;
515 if (auto Err = RecordReader.readULEB128(AugmentationDataSize))
516 return Err;
517
518 JITTargetAddress LSDAFieldOffset = RecordReader.getOffset();
519 auto LSDAEdgeItr = BlockEdges.find(RecordOffset + LSDAFieldOffset);
520 if (LSDAEdgeItr == BlockEdges.end()) {
521 auto LSDAPointerInfo =
522 readEncodedPointer(CIEInfo->LSDAPointerEncoding,
523 RecordAddress + LSDAFieldOffset, RecordReader);
524 if (!LSDAPointerInfo)
525 return LSDAPointerInfo.takeError();
526 JITTargetAddress LSDA = LSDAPointerInfo->first;
527 Edge::Kind LSDAEdgeKind = LSDAPointerInfo->second;
528 auto LSDASym = getOrCreateSymbol(PC, LSDA);
529 if (!LSDASym)
530 return LSDASym.takeError();
531 LLVM_DEBUG({
532 dbgs() << " Adding edge at "
533 << formatv("{0:x16}", RecordAddress + LSDAFieldOffset)
534 << " to LSDA at " << formatv("{0:x16}", LSDA) << "\n";
535 });
536 B.addEdge(LSDAEdgeKind, RecordOffset + LSDAFieldOffset, *LSDASym, 0);
537 } else {
538 LLVM_DEBUG({
539 auto &EI = LSDAEdgeItr->second;
540 dbgs() << " Already has edge at "
541 << formatv("{0:x16}", RecordAddress + LSDAFieldOffset)
542 << " to LSDA at " << formatv("{0:x16}", EI.Target->getAddress());
543 if (EI.Addend)
544 dbgs() << " + " << formatv("{0:x16}", EI.Addend);
545 dbgs() << "\n";
546 });
547 if (auto Err = RecordReader.skip(AugmentationDataSize))
548 return Err;
549 }
550 } else {
551 LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n");
552 }
553
554 return Error::success();
555 }
556
557 Expected<EHFrameEdgeFixer::AugmentationInfo>
parseAugmentationString(BinaryStreamReader & RecordReader)558 EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {
559 AugmentationInfo AugInfo;
560 uint8_t NextChar;
561 uint8_t *NextField = &AugInfo.Fields[0];
562
563 if (auto Err = RecordReader.readInteger(NextChar))
564 return std::move(Err);
565
566 while (NextChar != 0) {
567 switch (NextChar) {
568 case 'z':
569 AugInfo.AugmentationDataPresent = true;
570 break;
571 case 'e':
572 if (auto Err = RecordReader.readInteger(NextChar))
573 return std::move(Err);
574 if (NextChar != 'h')
575 return make_error<JITLinkError>("Unrecognized substring e" +
576 Twine(NextChar) +
577 " in augmentation string");
578 AugInfo.EHDataFieldPresent = true;
579 break;
580 case 'L':
581 case 'P':
582 case 'R':
583 *NextField++ = NextChar;
584 break;
585 default:
586 return make_error<JITLinkError>("Unrecognized character " +
587 Twine(NextChar) +
588 " in augmentation string");
589 }
590
591 if (auto Err = RecordReader.readInteger(NextChar))
592 return std::move(Err);
593 }
594
595 return std::move(AugInfo);
596 }
597
isSupportedPointerEncoding(uint8_t PointerEncoding)598 bool EHFrameEdgeFixer::isSupportedPointerEncoding(uint8_t PointerEncoding) {
599 using namespace dwarf;
600
601 // We only support PC-rel for now.
602 if ((PointerEncoding & 0x70) != DW_EH_PE_pcrel)
603 return false;
604
605 // readEncodedPointer does not handle indirect.
606 if (PointerEncoding & DW_EH_PE_indirect)
607 return false;
608
609 // Supported datatypes.
610 switch (PointerEncoding & 0xf) {
611 case DW_EH_PE_absptr:
612 case DW_EH_PE_udata4:
613 case DW_EH_PE_udata8:
614 case DW_EH_PE_sdata4:
615 case DW_EH_PE_sdata8:
616 return true;
617 }
618
619 return false;
620 }
621
getPointerEncodingDataSize(uint8_t PointerEncoding)622 unsigned EHFrameEdgeFixer::getPointerEncodingDataSize(uint8_t PointerEncoding) {
623 using namespace dwarf;
624
625 assert(isSupportedPointerEncoding(PointerEncoding) &&
626 "Unsupported pointer encoding");
627 switch (PointerEncoding & 0xf) {
628 case DW_EH_PE_absptr:
629 return PointerSize;
630 case DW_EH_PE_udata4:
631 case DW_EH_PE_sdata4:
632 return 4;
633 case DW_EH_PE_udata8:
634 case DW_EH_PE_sdata8:
635 return 8;
636 default:
637 llvm_unreachable("Unsupported encoding");
638 }
639 }
640
641 Expected<std::pair<JITTargetAddress, Edge::Kind>>
readEncodedPointer(uint8_t PointerEncoding,JITTargetAddress PointerFieldAddress,BinaryStreamReader & RecordReader)642 EHFrameEdgeFixer::readEncodedPointer(uint8_t PointerEncoding,
643 JITTargetAddress PointerFieldAddress,
644 BinaryStreamReader &RecordReader) {
645 static_assert(sizeof(JITTargetAddress) == sizeof(uint64_t),
646 "Result must be able to hold a uint64_t");
647 assert(isSupportedPointerEncoding(PointerEncoding) &&
648 "Unsupported pointer encoding");
649
650 using namespace dwarf;
651
652 // Isolate data type, remap absptr to udata4 or udata8. This relies on us
653 // having verified that the graph uses 32-bit or 64-bit pointers only at the
654 // start of this pass.
655 uint8_t EffectiveType = PointerEncoding & 0xf;
656 if (EffectiveType == DW_EH_PE_absptr)
657 EffectiveType = (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
658
659 JITTargetAddress Addr;
660 Edge::Kind PointerEdgeKind;
661 switch (EffectiveType) {
662 case DW_EH_PE_udata4: {
663 uint32_t Val;
664 if (auto Err = RecordReader.readInteger(Val))
665 return std::move(Err);
666 Addr = PointerFieldAddress + Val;
667 PointerEdgeKind = Delta32;
668 break;
669 }
670 case DW_EH_PE_udata8: {
671 uint64_t Val;
672 if (auto Err = RecordReader.readInteger(Val))
673 return std::move(Err);
674 Addr = PointerFieldAddress + Val;
675 PointerEdgeKind = Delta64;
676 break;
677 }
678 case DW_EH_PE_sdata4: {
679 int32_t Val;
680 if (auto Err = RecordReader.readInteger(Val))
681 return std::move(Err);
682 Addr = PointerFieldAddress + Val;
683 PointerEdgeKind = Delta32;
684 break;
685 }
686 case DW_EH_PE_sdata8: {
687 int64_t Val;
688 if (auto Err = RecordReader.readInteger(Val))
689 return std::move(Err);
690 Addr = PointerFieldAddress + Val;
691 PointerEdgeKind = Delta64;
692 break;
693 }
694 }
695
696 if (PointerEdgeKind == Edge::Invalid)
697 return make_error<JITLinkError>(
698 "Unspported edge kind for encoded pointer at " +
699 formatv("{0:x}", PointerFieldAddress));
700
701 return std::make_pair(Addr, Delta64);
702 }
703
getOrCreateSymbol(ParseContext & PC,JITTargetAddress Addr)704 Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
705 JITTargetAddress Addr) {
706 Symbol *CanonicalSym = nullptr;
707
708 auto UpdateCanonicalSym = [&](Symbol *Sym) {
709 if (!CanonicalSym || Sym->getLinkage() < CanonicalSym->getLinkage() ||
710 Sym->getScope() < CanonicalSym->getScope() ||
711 (Sym->hasName() && !CanonicalSym->hasName()) ||
712 Sym->getName() < CanonicalSym->getName())
713 CanonicalSym = Sym;
714 };
715
716 if (auto *SymbolsAtAddr = PC.AddrToSyms.getSymbolsAt(Addr))
717 for (auto *Sym : *SymbolsAtAddr)
718 UpdateCanonicalSym(Sym);
719
720 // If we found an existing symbol at the given address then use it.
721 if (CanonicalSym)
722 return *CanonicalSym;
723
724 // Otherwise search for a block covering the address and create a new symbol.
725 auto *B = PC.AddrToBlock.getBlockCovering(Addr);
726 if (!B)
727 return make_error<JITLinkError>("No symbol or block covering address " +
728 formatv("{0:x16}", Addr));
729
730 return PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false);
731 }
732
~EHFrameRegistrar()733 EHFrameRegistrar::~EHFrameRegistrar() {}
734
registerEHFrames(JITTargetAddress EHFrameSectionAddr,size_t EHFrameSectionSize)735 Error InProcessEHFrameRegistrar::registerEHFrames(
736 JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) {
737 return orc::registerEHFrameSection(
738 jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
739 EHFrameSectionSize);
740 }
741
deregisterEHFrames(JITTargetAddress EHFrameSectionAddr,size_t EHFrameSectionSize)742 Error InProcessEHFrameRegistrar::deregisterEHFrames(
743 JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) {
744 return orc::deregisterEHFrameSection(
745 jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
746 EHFrameSectionSize);
747 }
748
749 LinkGraphPassFunction
createEHFrameRecorderPass(const Triple & TT,StoreFrameRangeFunction StoreRangeAddress)750 createEHFrameRecorderPass(const Triple &TT,
751 StoreFrameRangeFunction StoreRangeAddress) {
752 const char *EHFrameSectionName = nullptr;
753 if (TT.getObjectFormat() == Triple::MachO)
754 EHFrameSectionName = "__eh_frame";
755 else
756 EHFrameSectionName = ".eh_frame";
757
758 auto RecordEHFrame =
759 [EHFrameSectionName,
760 StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error {
761 // Search for a non-empty eh-frame and record the address of the first
762 // symbol in it.
763 JITTargetAddress Addr = 0;
764 size_t Size = 0;
765 if (auto *S = G.findSectionByName(EHFrameSectionName)) {
766 auto R = SectionRange(*S);
767 Addr = R.getStart();
768 Size = R.getSize();
769 }
770 if (Addr == 0 && Size != 0)
771 return make_error<JITLinkError>("__eh_frame section can not have zero "
772 "address with non-zero size");
773 StoreFrameRange(Addr, Size);
774 return Error::success();
775 };
776
777 return RecordEHFrame;
778 }
779
780 } // end namespace jitlink
781 } // end namespace llvm
782