@@ -119,9 +119,10 @@ Error EHFrameSplitter::processBlock(LinkGraph &G, Block &B,
119
119
}
120
120
121
121
EHFrameEdgeFixer::EHFrameEdgeFixer (StringRef EHFrameSectionName,
122
- Edge::Kind Delta64, Edge::Kind NegDelta32)
123
- : EHFrameSectionName(EHFrameSectionName), Delta64(Delta64),
124
- NegDelta32 (NegDelta32) {}
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) {}
125
126
126
127
Error EHFrameEdgeFixer::operator ()(LinkGraph &G) {
127
128
auto *EHFrame = G.findSectionByName (EHFrameSectionName);
@@ -134,6 +135,11 @@ Error EHFrameEdgeFixer::operator()(LinkGraph &G) {
134
135
return Error::success ();
135
136
}
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
+
137
143
LLVM_DEBUG ({
138
144
dbgs () << " EHFrameEdgeFixer: Processing " << EHFrameSectionName << " ...\n " ;
139
145
});
@@ -258,7 +264,6 @@ Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
258
264
Error EHFrameEdgeFixer::processCIE (ParseContext &PC, Block &B,
259
265
size_t RecordOffset, size_t RecordLength,
260
266
size_t CIEDeltaFieldOffset) {
261
- using namespace dwarf ;
262
267
263
268
LLVM_DEBUG (dbgs () << " Record is CIE\n " );
264
269
@@ -329,19 +334,21 @@ Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
329
334
uint8_t LSDAPointerEncoding;
330
335
if (auto Err = RecordReader.readInteger (LSDAPointerEncoding))
331
336
return Err;
332
- if (LSDAPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr ))
337
+ if (! isSupportedPointerEncoding (LSDAPointerEncoding ))
333
338
return make_error<JITLinkError>(
334
339
" Unsupported LSDA pointer encoding " +
335
340
formatv (" {0:x2}" , LSDAPointerEncoding) + " in CIE at " +
336
341
formatv (" {0:x16}" , CIESymbol.getAddress ()));
342
+ CIEInfo.LSDAPointerEncoding = LSDAPointerEncoding;
337
343
break ;
338
344
}
339
345
case ' P' : {
340
346
uint8_t PersonalityPointerEncoding = 0 ;
341
347
if (auto Err = RecordReader.readInteger (PersonalityPointerEncoding))
342
348
return Err;
343
349
if (PersonalityPointerEncoding !=
344
- (DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4))
350
+ (dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
351
+ dwarf::DW_EH_PE_sdata4))
345
352
return make_error<JITLinkError>(
346
353
" Unspported personality pointer "
347
354
" encoding " +
@@ -356,12 +363,12 @@ Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
356
363
uint8_t FDEPointerEncoding;
357
364
if (auto Err = RecordReader.readInteger (FDEPointerEncoding))
358
365
return Err;
359
- if (FDEPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr ))
366
+ if (! isSupportedPointerEncoding (FDEPointerEncoding ))
360
367
return make_error<JITLinkError>(
361
- " Unsupported FDE address pointer "
362
- " encoding " +
368
+ " Unsupported FDE pointer encoding " +
363
369
formatv (" {0:x2}" , FDEPointerEncoding) + " in CIE at " +
364
370
formatv (" {0:x16}" , CIESymbol.getAddress ()));
371
+ CIEInfo.FDEPointerEncoding = FDEPointerEncoding;
365
372
break ;
366
373
}
367
374
default :
@@ -445,11 +452,13 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
445
452
JITTargetAddress PCBeginFieldOffset = RecordReader.getOffset ();
446
453
auto PCEdgeItr = BlockEdges.find (RecordOffset + PCBeginFieldOffset);
447
454
if (PCEdgeItr == BlockEdges.end ()) {
448
- auto PCBeginDelta = readAbsolutePointer (PC.G , RecordReader);
449
- if (!PCBeginDelta)
450
- return PCBeginDelta.takeError ();
451
- JITTargetAddress PCBegin =
452
- RecordAddress + PCBeginFieldOffset + *PCBeginDelta;
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 ;
453
462
LLVM_DEBUG ({
454
463
dbgs () << " Adding edge at "
455
464
<< formatv (" {0:x16}" , RecordAddress + PCBeginFieldOffset)
@@ -458,7 +467,8 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
458
467
auto PCBeginSym = getOrCreateSymbol (PC, PCBegin);
459
468
if (!PCBeginSym)
460
469
return PCBeginSym.takeError ();
461
- B.addEdge (Delta64, RecordOffset + PCBeginFieldOffset, *PCBeginSym, 0 );
470
+ B.addEdge (PCBeginEdgeKind, RecordOffset + PCBeginFieldOffset, *PCBeginSym,
471
+ 0 );
462
472
PCBeginBlock = &PCBeginSym->getBlock ();
463
473
} else {
464
474
auto &EI = PCEdgeItr->second ;
@@ -479,38 +489,42 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
479
489
" points at external block" );
480
490
}
481
491
PCBeginBlock = &EI.Target ->getBlock ();
482
- if (auto Err = RecordReader.skip (PC.G .getPointerSize ()))
492
+ if (auto Err = RecordReader.skip (
493
+ getPointerEncodingDataSize (CIEInfo->FDEPointerEncoding )))
483
494
return Err;
484
495
}
485
496
486
497
// Add a keep-alive edge from the FDE target to the FDE to ensure that the
487
498
// FDE is kept alive if its target is.
488
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
+ });
489
505
PCBeginBlock->addEdge (Edge::KeepAlive, 0 , FDESymbol, 0 );
490
506
}
491
507
492
508
// Skip over the PC range size field.
493
- if (auto Err = RecordReader.skip (PC.G .getPointerSize ()))
509
+ if (auto Err = RecordReader.skip (
510
+ getPointerEncodingDataSize (CIEInfo->FDEPointerEncoding )))
494
511
return Err;
495
512
496
513
if (CIEInfo->FDEsHaveLSDAField ) {
497
514
uint64_t AugmentationDataSize;
498
515
if (auto Err = RecordReader.readULEB128 (AugmentationDataSize))
499
516
return Err;
500
- if (AugmentationDataSize != PC.G .getPointerSize ())
501
- return make_error<JITLinkError>(
502
- " Unexpected FDE augmentation data size (expected " +
503
- Twine (PC.G .getPointerSize ()) + " , got " +
504
- Twine (AugmentationDataSize) + " ) for FDE at " +
505
- formatv (" {0:x16}" , RecordAddress));
506
517
507
518
JITTargetAddress LSDAFieldOffset = RecordReader.getOffset ();
508
519
auto LSDAEdgeItr = BlockEdges.find (RecordOffset + LSDAFieldOffset);
509
520
if (LSDAEdgeItr == BlockEdges.end ()) {
510
- auto LSDADelta = readAbsolutePointer (PC.G , RecordReader);
511
- if (!LSDADelta)
512
- return LSDADelta.takeError ();
513
- JITTargetAddress LSDA = RecordAddress + LSDAFieldOffset + *LSDADelta;
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 ;
514
528
auto LSDASym = getOrCreateSymbol (PC, LSDA);
515
529
if (!LSDASym)
516
530
return LSDASym.takeError ();
@@ -519,7 +533,7 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
519
533
<< formatv (" {0:x16}" , RecordAddress + LSDAFieldOffset)
520
534
<< " to LSDA at " << formatv (" {0:x16}" , LSDA) << " \n " ;
521
535
});
522
- B.addEdge (Delta64 , RecordOffset + LSDAFieldOffset, *LSDASym, 0 );
536
+ B.addEdge (LSDAEdgeKind , RecordOffset + LSDAFieldOffset, *LSDASym, 0 );
523
537
} else {
524
538
LLVM_DEBUG ({
525
539
auto &EI = LSDAEdgeItr->second ;
@@ -530,7 +544,7 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
530
544
dbgs () << " + " << formatv (" {0:x16}" , EI.Addend );
531
545
dbgs () << " \n " ;
532
546
});
533
- if (auto Err = RecordReader.skip (PC. G . getPointerSize () ))
547
+ if (auto Err = RecordReader.skip (AugmentationDataSize ))
534
548
return Err;
535
549
}
536
550
} else {
@@ -581,23 +595,110 @@ EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {
581
595
return std::move (AugInfo);
582
596
}
583
597
584
- Expected<JITTargetAddress>
585
- EHFrameEdgeFixer::readAbsolutePointer (LinkGraph &G,
586
- BinaryStreamReader &RecordReader) {
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
+
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>>
642
+ EHFrameEdgeFixer::readEncodedPointer (uint8_t PointerEncoding,
643
+ JITTargetAddress PointerFieldAddress,
644
+ BinaryStreamReader &RecordReader) {
587
645
static_assert (sizeof (JITTargetAddress) == sizeof (uint64_t ),
588
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
+
589
659
JITTargetAddress Addr;
590
- if (G.getPointerSize () == 8 ) {
591
- if (auto Err = RecordReader.readInteger (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))
592
665
return std::move (Err);
593
- } else if (G.getPointerSize () == 4 ) {
594
- uint32_t Addr32;
595
- if (auto Err = RecordReader.readInteger (Addr32))
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))
596
673
return std::move (Err);
597
- Addr = Addr32;
598
- } else
599
- llvm_unreachable (" Pointer size is not 32-bit or 64-bit" );
600
- return Addr;
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);
601
702
}
602
703
603
704
Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol (ParseContext &PC,
0 commit comments