Skip to content

Commit 9d88ffe

Browse files
committed
[JITLink] Handle compact-unwind records that depend on DWARF FDEs.
Compact-unwind encodings are more limited than DWARF frame descriptions. For functions whose frame layout cannot be described by a compact unwind encoding, the encoding for the function will specify "use DWARF", and the corresponding unwind-info record will use the low bits of the encoding to point to the FDE for the function. We test this with a frame-pointer=none function, since these frame layouts always triger a fall-back to DWARF on arm64.
1 parent c9446ff commit 9d88ffe

File tree

4 files changed

+43
-13
lines changed

4 files changed

+43
-13
lines changed

llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ template <typename CRTPImpl, size_t PtrSize> struct CompactUnwindTraits {
6161
return support::endian::read32<CRTPImpl::Endianness>(RecordContent.data() +
6262
EncodingFieldOffset);
6363
}
64+
65+
static std::optional<uint32_t> encodeDWARFOffset(size_t Delta) {
66+
uint32_t Encoded =
67+
static_cast<uint32_t>(Delta) & CRTPImpl::DWARFSectionOffsetMask;
68+
if (Encoded != Delta)
69+
return std::nullopt;
70+
return Encoded;
71+
}
6472
};
6573

6674
/// Architecture specific implementation of CompactUnwindManager.
@@ -133,19 +141,22 @@ template <typename CURecTraits> class CompactUnwindManager {
133141
<< Fn.getName() << "\n";
134142
});
135143
continue;
136-
} else {
137-
LLVM_DEBUG({
138-
dbgs() << " Found record for function ";
139-
if (Fn.hasName())
140-
dbgs() << Fn.getName();
141-
else
142-
dbgs() << "<anon @ " << Fn.getAddress() << '>';
143-
dbgs() << '\n';
144-
});
145144
}
146145

147-
bool NeedsDWARF = CURecTraits::encodingSpecifiesDWARF(
148-
CURecTraits::readEncoding(B->getContent()));
146+
uint32_t Encoding = CURecTraits::readEncoding(B->getContent());
147+
bool NeedsDWARF = CURecTraits::encodingSpecifiesDWARF(Encoding);
148+
149+
LLVM_DEBUG({
150+
dbgs() << " Found record for function ";
151+
if (Fn.hasName())
152+
dbgs() << Fn.getName();
153+
else
154+
dbgs() << "<anon @ " << Fn.getAddress() << '>';
155+
dbgs() << ": encoding = " << formatv("{0:x}", Encoding);
156+
if (NeedsDWARF)
157+
dbgs() << " (needs DWARF)";
158+
dbgs() << "\n";
159+
});
149160

150161
auto &CURecSym =
151162
G.addAnonymousSymbol(*B, 0, CURecTraits::Size, false, false);
@@ -170,7 +181,7 @@ template <typename CURecTraits> class CompactUnwindManager {
170181
KeepAliveAlreadyPresent = true;
171182
if (NeedsDWARF) {
172183
LLVM_DEBUG({
173-
dbgs() << " Needs DWARF: adding keep-alive edge to FDE at "
184+
dbgs() << " Adding keep-alive edge to FDE at "
174185
<< FDE.getAddress() << "\n";
175186
});
176187
B->addEdge(Edge::KeepAlive, 0, FDE, 0);
@@ -595,8 +606,24 @@ template <typename CURecTraits> class CompactUnwindManager {
595606
", delta to function at " + formatv("{0:x}", R.Fn->getAddress()) +
596607
" exceeds 32 bits");
597608

609+
auto Encoding = R.Encoding;
610+
611+
if (LLVM_UNLIKELY(CURecTraits::encodingSpecifiesDWARF(R.Encoding))) {
612+
if (!EHFrameBase)
613+
EHFrameBase = SectionRange(R.FDE->getSection()).getStart();
614+
auto FDEDelta = R.FDE->getAddress() - EHFrameBase;
615+
616+
if (auto EncodedFDEDelta = CURecTraits::encodeDWARFOffset(FDEDelta))
617+
Encoding |= *EncodedFDEDelta;
618+
else
619+
return make_error<JITLinkError>(
620+
"In " + G.getName() + " " + UnwindInfoSectionName +
621+
", cannot encode delta " + formatv("{0:x}", FDEDelta) +
622+
" to FDE at " + formatv("{0:x}", R.FDE->getAddress()));
623+
}
624+
598625
cantFail(W.writeInteger<uint32_t>(FnDelta));
599-
cantFail(W.writeInteger<uint32_t>(R.Encoding));
626+
cantFail(W.writeInteger<uint32_t>(Encoding));
600627

601628
++RecordIdx;
602629
}
@@ -639,6 +666,7 @@ template <typename CURecTraits> class CompactUnwindManager {
639666
StringRef UnwindInfoSectionName;
640667
StringRef EHFrameSectionName;
641668
Symbol *CompactUnwindBase = nullptr;
669+
orc::ExecutorAddr EHFrameBase;
642670

643671
size_t NumLSDAs = 0;
644672
size_t NumSecondLevelPages = 0;

llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,7 @@ struct CompactUnwindTraits_MachO_arm64
637637
constexpr static endianness Endianness = endianness::little;
638638

639639
constexpr static uint32_t EncodingModeMask = 0x0f000000;
640+
constexpr static uint32_t DWARFSectionOffsetMask = 0x00ffffff;
640641

641642
using GOTManager = aarch64::GOTTableManager;
642643

llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ struct CompactUnwindTraits_MachO_x86_64
512512
constexpr static endianness Endianness = endianness::little;
513513

514514
constexpr static uint32_t EncodingModeMask = 0x0f000000;
515+
constexpr static uint32_t DWARFSectionOffsetMask = 0x00ffffff;
515516

516517
using GOTManager = x86_64::GOTTableManager;
517518

0 commit comments

Comments
 (0)