Skip to content

Commit 773fc10

Browse files
[llvm-jitlink] Allow optional stub-kind filter in stub_addr() expressions
1 parent 01ba627 commit 773fc10

File tree

7 files changed

+114
-24
lines changed

7 files changed

+114
-24
lines changed

llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class RuntimeDyldChecker {
154154
using GetSectionInfoFunction = std::function<Expected<MemoryRegionInfo>(
155155
StringRef FileName, StringRef SectionName)>;
156156
using GetStubInfoFunction = std::function<Expected<MemoryRegionInfo>(
157-
StringRef StubContainer, StringRef TargetName)>;
157+
StringRef StubContainer, StringRef TargetName, StringRef StubKindFilter)>;
158158
using GetGOTInfoFunction = std::function<Expected<MemoryRegionInfo>(
159159
StringRef GOTContainer, StringRef TargetName)>;
160160

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -400,15 +400,25 @@ class RuntimeDyldCheckerExprEval {
400400
StringRef Symbol;
401401
std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);
402402

403+
// Parse optional parameter to filter by stub kind
404+
StringRef KindNameFilter;
405+
if (RemainingExpr.starts_with(",")) {
406+
RemainingExpr = RemainingExpr.substr(1).ltrim();
407+
size_t ClosingBracket = RemainingExpr.find(")");
408+
KindNameFilter = RemainingExpr.substr(0, ClosingBracket);
409+
RemainingExpr = RemainingExpr.substr(ClosingBracket);
410+
}
411+
403412
if (!RemainingExpr.starts_with(")"))
404413
return std::make_pair(
405414
unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
406415
RemainingExpr = RemainingExpr.substr(1).ltrim();
407416

408417
uint64_t StubAddr;
409418
std::string ErrorMsg;
410-
std::tie(StubAddr, ErrorMsg) = Checker.getStubOrGOTAddrFor(
411-
StubContainerName, Symbol, PCtx.IsInsideLoad, IsStubAddr);
419+
std::tie(StubAddr, ErrorMsg) =
420+
Checker.getStubOrGOTAddrFor(StubContainerName, Symbol, KindNameFilter,
421+
PCtx.IsInsideLoad, IsStubAddr);
412422

413423
if (ErrorMsg != "")
414424
return std::make_pair(EvalResult(ErrorMsg), "");
@@ -985,11 +995,14 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
985995
}
986996

987997
std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(
988-
StringRef StubContainerName, StringRef SymbolName, bool IsInsideLoad,
989-
bool IsStubAddr) const {
990-
991-
auto StubInfo = IsStubAddr ? GetStubInfo(StubContainerName, SymbolName)
992-
: GetGOTInfo(StubContainerName, SymbolName);
998+
StringRef StubContainerName, StringRef SymbolName, StringRef StubKindFilter,
999+
bool IsInsideLoad, bool IsStubAddr) const {
1000+
1001+
assert((StubKindFilter.empty() || IsStubAddr) &&
1002+
"Kind name filter only supported for stubs");
1003+
auto StubInfo =
1004+
IsStubAddr ? GetStubInfo(StubContainerName, SymbolName, StubKindFilter)
1005+
: GetGOTInfo(StubContainerName, SymbolName);
9931006

9941007
if (!StubInfo) {
9951008
std::string ErrMsg;

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ class RuntimeDyldCheckerImpl {
6464

6565
std::pair<uint64_t, std::string>
6666
getStubOrGOTAddrFor(StringRef StubContainerName, StringRef Symbol,
67-
bool IsInsideLoad, bool IsStubAddr) const;
67+
StringRef StubKindFilter, bool IsInsideLoad,
68+
bool IsStubAddr) const;
6869

6970
std::optional<uint64_t> getSectionLoadAddress(void *LocalAddr) const;
7071

llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ static Error registerSymbol(LinkGraph &G, Symbol &Sym, Session::FileInfo &FI,
9191
case Stubs:
9292
return FI.registerStubEntry(G, Sym, getELFStubTarget);
9393
case AArch32Stubs:
94-
return FI.registerStubEntry(G, Sym, getELFAArch32StubTarget);
94+
return FI.registerMultiStubEntry(G, Sym, getELFAArch32StubTarget);
9595
case Other:
9696
return Error::success();
9797
}

llvm/tools/llvm-jitlink/llvm-jitlink.cpp

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,12 @@ operator<<(raw_ostream &OS, const Session::FileInfo &FI) {
331331
OS << " Section \"" << SIKV.first() << "\": " << SIKV.second << "\n";
332332
for (auto &GOTKV : FI.GOTEntryInfos)
333333
OS << " GOT \"" << GOTKV.first() << "\": " << GOTKV.second << "\n";
334-
for (auto &StubKV : FI.StubInfos)
335-
OS << " Stub \"" << StubKV.first() << "\": " << StubKV.second << "\n";
334+
for (auto &StubKVs : FI.StubInfos) {
335+
OS << " Stubs \"" << StubKVs.first() << "\":";
336+
for (auto MemRegion : StubKVs.second)
337+
OS << " " << MemRegion;
338+
OS << "\n";
339+
}
336340
return OS;
337341
}
338342

@@ -1207,9 +1211,35 @@ Error Session::FileInfo::registerStubEntry(
12071211
auto TS = GetSymbolTarget(G, Sym.getBlock());
12081212
if (!TS)
12091213
return TS.takeError();
1210-
StubInfos[TS->getName()] = {Sym.getSymbolContent(),
1211-
Sym.getAddress().getValue(),
1212-
Sym.getTargetFlags()};
1214+
1215+
SmallVector<MemoryRegionInfo> &Entry = StubInfos[TS->getName()];
1216+
Entry.insert(Entry.begin(),
1217+
{Sym.getSymbolContent(), Sym.getAddress().getValue(),
1218+
Sym.getTargetFlags()});
1219+
return Error::success();
1220+
}
1221+
1222+
Error Session::FileInfo::registerMultiStubEntry(
1223+
LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {
1224+
if (Sym.isSymbolZeroFill())
1225+
return make_error<StringError>("Unexpected zero-fill symbol in section " +
1226+
Sym.getBlock().getSection().getName(),
1227+
inconvertibleErrorCode());
1228+
1229+
auto Target = GetSymbolTarget(G, Sym.getBlock());
1230+
if (!Target)
1231+
return Target.takeError();
1232+
1233+
SmallVector<MemoryRegionInfo> &Entry = StubInfos[Target->getName()];
1234+
Entry.emplace_back(Sym.getSymbolContent(), Sym.getAddress().getValue(),
1235+
Sym.getTargetFlags());
1236+
1237+
// Let's keep stubs ordered by ascending address.
1238+
std::sort(Entry.begin(), Entry.end(),
1239+
[](const MemoryRegionInfo &L, const MemoryRegionInfo &R) {
1240+
return L.getTargetAddress() < R.getTargetAddress();
1241+
});
1242+
12131243
return Error::success();
12141244
}
12151245

@@ -1235,8 +1265,14 @@ Session::findSectionInfo(StringRef FileName, StringRef SectionName) {
12351265
return SecInfoItr->second;
12361266
}
12371267

1268+
static StringRef detectStubKind(const Session::MemoryRegionInfo &Stub) {
1269+
// Implement acutal stub kind detection
1270+
return "";
1271+
}
1272+
12381273
Expected<Session::MemoryRegionInfo &>
1239-
Session::findStubInfo(StringRef FileName, StringRef TargetName) {
1274+
Session::findStubInfo(StringRef FileName, StringRef TargetName,
1275+
StringRef KindNameFilter) {
12401276
auto FI = findFileInfo(FileName);
12411277
if (!FI)
12421278
return FI.takeError();
@@ -1246,7 +1282,38 @@ Session::findStubInfo(StringRef FileName, StringRef TargetName) {
12461282
"\" registered for file \"" + FileName +
12471283
"\"",
12481284
inconvertibleErrorCode());
1249-
return StubInfoItr->second;
1285+
auto &StubsForTarget = StubInfoItr->second;
1286+
assert(!StubsForTarget.empty() && "At least 1 stub in each entry");
1287+
if (KindNameFilter.empty() && StubsForTarget.size() == 1)
1288+
return StubsForTarget[0]; // Regular single-stub match
1289+
1290+
std::string KindsStr;
1291+
SmallVector<MemoryRegionInfo *, 1> Matches;
1292+
Regex KindNameMatcher(KindNameFilter.empty() ? ".*" : KindNameFilter);
1293+
for (MemoryRegionInfo &Stub : StubsForTarget) {
1294+
StringRef Kind = detectStubKind(Stub);
1295+
if (KindNameMatcher.match(Kind))
1296+
Matches.push_back(&Stub);
1297+
KindsStr += "\"" + (Kind.empty() ? "<unknown>" : Kind.str()) + "\", ";
1298+
}
1299+
if (Matches.empty())
1300+
return make_error<StringError>(
1301+
"\"" + TargetName + "\" has " + Twine(StubsForTarget.size()) +
1302+
" stubs in file \"" + FileName +
1303+
"\", but none of them matches the stub-kind filter \"" +
1304+
KindNameFilter + "\" (all encountered kinds are " +
1305+
StringRef(KindsStr.data(), KindsStr.size() - 2) + ").",
1306+
inconvertibleErrorCode());
1307+
if (Matches.size() > 1)
1308+
return make_error<StringError>(
1309+
"\"" + TargetName + "\" has " + Twine(Matches.size()) +
1310+
" candidate stubs in file \"" + FileName +
1311+
"\". Please refine stub-kind filter \"" + KindNameFilter +
1312+
"\" for disambiguation (encountered kinds are " +
1313+
StringRef(KindsStr.data(), KindsStr.size() - 2) + ").",
1314+
inconvertibleErrorCode());
1315+
1316+
return *Matches[0];
12501317
}
12511318

12521319
Expected<Session::MemoryRegionInfo &>
@@ -2015,8 +2082,9 @@ static Error runChecks(Session &S, Triple TT, SubtargetFeatures Features) {
20152082
return S.findSectionInfo(FileName, SectionName);
20162083
};
20172084

2018-
auto GetStubInfo = [&S](StringRef FileName, StringRef SectionName) {
2019-
return S.findStubInfo(FileName, SectionName);
2085+
auto GetStubInfo = [&S](StringRef FileName, StringRef SectionName,
2086+
StringRef KindNameFilter) {
2087+
return S.findStubInfo(FileName, SectionName, KindNameFilter);
20202088
};
20212089

20222090
auto GetGOTInfo = [&S](StringRef FileName, StringRef SectionName) {

llvm/tools/llvm-jitlink/llvm-jitlink.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ struct Session {
4949

5050
struct FileInfo {
5151
StringMap<MemoryRegionInfo> SectionInfos;
52-
StringMap<MemoryRegionInfo> StubInfos;
52+
StringMap<SmallVector<MemoryRegionInfo, 1>> StubInfos;
5353
StringMap<MemoryRegionInfo> GOTEntryInfos;
5454

5555
using Symbol = jitlink::Symbol;
@@ -61,6 +61,8 @@ struct Session {
6161
GetSymbolTargetFunction GetSymbolTarget);
6262
Error registerStubEntry(LinkGraph &G, Symbol &Sym,
6363
GetSymbolTargetFunction GetSymbolTarget);
64+
Error registerMultiStubEntry(LinkGraph &G, Symbol &Sym,
65+
GetSymbolTargetFunction GetSymbolTarget);
6466
};
6567

6668
using DynLibJDMap = std::map<std::string, orc::JITDylib *>;
@@ -74,7 +76,8 @@ struct Session {
7476
Expected<MemoryRegionInfo &> findSectionInfo(StringRef FileName,
7577
StringRef SectionName);
7678
Expected<MemoryRegionInfo &> findStubInfo(StringRef FileName,
77-
StringRef TargetName);
79+
StringRef TargetName,
80+
StringRef KindNameFilter);
7881
Expected<MemoryRegionInfo &> findGOTEntryInfo(StringRef FileName,
7982
StringRef TargetName);
8083

llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,8 @@ static int linkAndVerify() {
926926
};
927927

928928
auto GetStubInfo = [&Dyld, &StubMap](StringRef StubContainer,
929-
StringRef SymbolName)
929+
StringRef SymbolName,
930+
StringRef KindNameFilter)
930931
-> Expected<RuntimeDyldChecker::MemoryRegionInfo> {
931932
if (!StubMap.count(StubContainer))
932933
return make_error<StringError>("Stub container not found: " +
@@ -947,6 +948,11 @@ static int linkAndVerify() {
947948
return StubMemInfo;
948949
};
949950

951+
auto GetGOTInfo = [&GetStubInfo](StringRef StubContainer,
952+
StringRef SymbolName) {
953+
return GetStubInfo(StubContainer, SymbolName, "");
954+
};
955+
950956
// We will initialize this below once we have the first object file and can
951957
// know the endianness.
952958
std::unique_ptr<RuntimeDyldChecker> Checker;
@@ -977,8 +983,7 @@ static int linkAndVerify() {
977983

978984
if (!Checker)
979985
Checker = std::make_unique<RuntimeDyldChecker>(
980-
IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo,
981-
GetStubInfo,
986+
IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,
982987
Obj.isLittleEndian() ? llvm::endianness::little
983988
: llvm::endianness::big,
984989
TheTriple, MCPU, SubtargetFeatures(), dbgs());

0 commit comments

Comments
 (0)