Skip to content

Commit 52b5e36

Browse files
committed
[ORC] Fix eh-frame record target finding in MachOPlatform.
Unwind-info records only have one keep-alive edge to their target function, but eh-frame records may have multiple edges (to the CIE, function, personality, and lsda). We need to identify the target-function edge differently for each section type.
1 parent b84ac58 commit 52b5e36

File tree

1 file changed

+44
-13
lines changed

1 file changed

+44
-13
lines changed

llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,30 +1256,61 @@ MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
12561256
// ScanSection records a section range and adds any executable blocks that
12571257
// that section points to to the CodeBlocks vector.
12581258
SmallVector<Block *> CodeBlocks;
1259-
auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) {
1259+
auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange,
1260+
auto GetCodeForRecord) {
12601261
if (Sec.blocks().empty())
12611262
return;
12621263
SecRange = (*Sec.blocks().begin())->getRange();
12631264
for (auto *B : Sec.blocks()) {
12641265
auto R = B->getRange();
12651266
SecRange.Start = std::min(SecRange.Start, R.Start);
12661267
SecRange.End = std::max(SecRange.End, R.End);
1267-
for (auto &E : B->edges()) {
1268-
if (E.getKind() != Edge::KeepAlive || !E.getTarget().isDefined())
1269-
continue;
1270-
auto &TargetBlock = E.getTarget().getBlock();
1271-
auto &TargetSection = TargetBlock.getSection();
1272-
if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec)
1273-
CodeBlocks.push_back(&TargetBlock);
1274-
}
1268+
if (auto *CodeBlock = GetCodeForRecord(*B))
1269+
CodeBlocks.push_back(CodeBlock);
12751270
}
12761271
};
12771272

1278-
if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName))
1279-
ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);
1273+
if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName)) {
1274+
ScanUnwindInfoSection(
1275+
*EHFrameSec, US.DwarfSection, [&](Block &B) -> Block * {
1276+
// Filter out CIE, personality, etc. edges.
1277+
SmallVector<Edge *, 4> BEdges;
1278+
for (auto &E : B.edges())
1279+
BEdges.push_back(&E);
1280+
llvm::sort(BEdges, [](const Edge *LHS, const Edge *RHS) {
1281+
return LHS->getOffset() < RHS->getOffset();
1282+
});
1283+
if (BEdges.size() < 2)
1284+
return nullptr;
1285+
auto &TargetBlock = BEdges[1]->getTarget().getBlock();
1286+
#ifndef NDEBUG
1287+
auto &TargetSection = TargetBlock.getSection();
1288+
assert(&TargetSection != EHFrameSec &&
1289+
(TargetSection.getMemProt() & MemProt::Exec) ==
1290+
MemProt::Exec &&
1291+
"Invalid eh-frame function target");
1292+
#endif // NDEBUG
1293+
return &TargetBlock;
1294+
});
1295+
}
12801296

1281-
if (Section *CUInfoSec = G.findSectionByName(MachOUnwindInfoSectionName))
1282-
ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);
1297+
if (Section *CUInfoSec = G.findSectionByName(MachOUnwindInfoSectionName)) {
1298+
ScanUnwindInfoSection(
1299+
*CUInfoSec, US.CompactUnwindSection, [&](Block &B) -> Block * {
1300+
// Compact unwind records should just have a keep-alive pointing to
1301+
// the target function.
1302+
assert(B.edges_size() == 1 &&
1303+
"unwind-info record should only have one edge");
1304+
for (auto &E : B.edges()) {
1305+
assert(E.getTarget().isDefined() &&
1306+
"unwind-info record edge has external target");
1307+
assert(E.getKind() == Edge::KeepAlive &&
1308+
"unwind-info record has unexpected edge kind");
1309+
return &E.getTarget().getBlock();
1310+
}
1311+
return nullptr;
1312+
});
1313+
}
12831314

12841315
// If we didn't find any pointed-to code-blocks then there's no need to
12851316
// register any info.

0 commit comments

Comments
 (0)