Skip to content

Commit 508a697

Browse files
authored
[JITLink] Allow multiple relocations at same offset in EHFrameEdgeFixer (#68252)
The pass only requires that it can determine a uniquely identified target at some offsets. Multiple relocations at the same offset are fine otherwise and will be required when adding exception handling support for RISC-V.
1 parent 9f3b06d commit 508a697

File tree

2 files changed

+41
-21
lines changed

2 files changed

+41
-21
lines changed

llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp

+31-15
Original file line numberDiff line numberDiff line change
@@ -126,16 +126,23 @@ Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
126126
}
127127

128128
// Find the offsets of any existing edges from this block.
129-
BlockEdgeMap BlockEdges;
129+
BlockEdgesInfo BlockEdges;
130130
for (auto &E : B.edges())
131131
if (E.isRelocation()) {
132-
if (BlockEdges.count(E.getOffset()))
133-
return make_error<JITLinkError>(
134-
"Multiple relocations at offset " +
135-
formatv("{0:x16}", E.getOffset()) + " in " + EHFrameSectionName +
136-
" block at address " + formatv("{0:x16}", B.getAddress()));
137-
138-
BlockEdges[E.getOffset()] = EdgeTarget(E);
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+
}
139146
}
140147

141148
BinaryStreamReader BlockReader(
@@ -172,7 +179,7 @@ Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
172179

173180
Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
174181
size_t CIEDeltaFieldOffset,
175-
const BlockEdgeMap &BlockEdges) {
182+
const BlockEdgesInfo &BlockEdges) {
176183

177184
LLVM_DEBUG(dbgs() << " Record is CIE\n");
178185

@@ -285,7 +292,7 @@ Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
285292
Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
286293
size_t CIEDeltaFieldOffset,
287294
uint32_t CIEDelta,
288-
const BlockEdgeMap &BlockEdges) {
295+
const BlockEdgesInfo &BlockEdges) {
289296
LLVM_DEBUG(dbgs() << " Record is FDE\n");
290297

291298
orc::ExecutorAddr RecordAddress = B.getAddress();
@@ -303,12 +310,17 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
303310

304311
{
305312
// Process the CIE pointer field.
306-
auto CIEEdgeItr = BlockEdges.find(CIEDeltaFieldOffset);
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);
307319

308320
orc::ExecutorAddr CIEAddress =
309321
RecordAddress + orc::ExecutorAddrDiff(CIEDeltaFieldOffset) -
310322
orc::ExecutorAddrDiff(CIEDelta);
311-
if (CIEEdgeItr == BlockEdges.end()) {
323+
if (CIEEdgeItr == BlockEdges.TargetMap.end()) {
312324
LLVM_DEBUG({
313325
dbgs() << " Adding edge at "
314326
<< (RecordAddress + CIEDeltaFieldOffset)
@@ -497,7 +509,7 @@ Error EHFrameEdgeFixer::skipEncodedPointer(uint8_t PointerEncoding,
497509
}
498510

499511
Expected<Symbol *> EHFrameEdgeFixer::getOrCreateEncodedPointerEdge(
500-
ParseContext &PC, const BlockEdgeMap &BlockEdges, uint8_t PointerEncoding,
512+
ParseContext &PC, const BlockEdgesInfo &BlockEdges, uint8_t PointerEncoding,
501513
BinaryStreamReader &RecordReader, Block &BlockToFix,
502514
size_t PointerFieldOffset, const char *FieldName) {
503515
using namespace dwarf;
@@ -508,8 +520,8 @@ Expected<Symbol *> EHFrameEdgeFixer::getOrCreateEncodedPointerEdge(
508520
// If there's already an edge here then just skip the encoded pointer and
509521
// return the edge's target.
510522
{
511-
auto EdgeI = BlockEdges.find(PointerFieldOffset);
512-
if (EdgeI != BlockEdges.end()) {
523+
auto EdgeI = BlockEdges.TargetMap.find(PointerFieldOffset);
524+
if (EdgeI != BlockEdges.TargetMap.end()) {
513525
LLVM_DEBUG({
514526
dbgs() << " Existing edge at "
515527
<< (BlockToFix.getAddress() + PointerFieldOffset) << " to "
@@ -522,6 +534,10 @@ Expected<Symbol *> EHFrameEdgeFixer::getOrCreateEncodedPointerEdge(
522534
return std::move(Err);
523535
return EdgeI->second.Target;
524536
}
537+
538+
if (BlockEdges.Multiple.contains(PointerFieldOffset))
539+
return make_error<JITLinkError>("Multiple relocations at offset " +
540+
formatv("{0:x16}", PointerFieldOffset));
525541
}
526542

527543
// Switch absptr to corresponding udata encoding.

llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h

+10-6
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ class EHFrameEdgeFixer {
6060
Edge::AddendT Addend = 0;
6161
};
6262

63-
using BlockEdgeMap = DenseMap<Edge::OffsetT, EdgeTarget>;
63+
struct BlockEdgesInfo {
64+
DenseMap<Edge::OffsetT, EdgeTarget> TargetMap;
65+
DenseSet<Edge::OffsetT> Multiple;
66+
};
67+
6468
using CIEInfosMap = DenseMap<orc::ExecutorAddr, CIEInformation>;
6569

6670
struct ParseContext {
@@ -82,9 +86,9 @@ class EHFrameEdgeFixer {
8286

8387
Error processBlock(ParseContext &PC, Block &B);
8488
Error processCIE(ParseContext &PC, Block &B, size_t CIEDeltaFieldOffset,
85-
const BlockEdgeMap &BlockEdges);
89+
const BlockEdgesInfo &BlockEdges);
8690
Error processFDE(ParseContext &PC, Block &B, size_t CIEDeltaFieldOffset,
87-
uint32_t CIEDelta, const BlockEdgeMap &BlockEdges);
91+
uint32_t CIEDelta, const BlockEdgesInfo &BlockEdges);
8892

8993
Expected<AugmentationInfo>
9094
parseAugmentationString(BinaryStreamReader &RecordReader);
@@ -94,9 +98,9 @@ class EHFrameEdgeFixer {
9498
Error skipEncodedPointer(uint8_t PointerEncoding,
9599
BinaryStreamReader &RecordReader);
96100
Expected<Symbol *> getOrCreateEncodedPointerEdge(
97-
ParseContext &PC, const BlockEdgeMap &BlockEdges, uint8_t PointerEncoding,
98-
BinaryStreamReader &RecordReader, Block &BlockToFix,
99-
size_t PointerFieldOffset, const char *FieldName);
101+
ParseContext &PC, const BlockEdgesInfo &BlockEdges,
102+
uint8_t PointerEncoding, BinaryStreamReader &RecordReader,
103+
Block &BlockToFix, size_t PointerFieldOffset, const char *FieldName);
100104

101105
Expected<Symbol &> getOrCreateSymbol(ParseContext &PC,
102106
orc::ExecutorAddr Addr);

0 commit comments

Comments
 (0)