Skip to content

[llvm-jitlink] Allow optional stub-kind filter in stub_addr() expressions #78369

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class RuntimeDyldChecker {
using GetSectionInfoFunction = std::function<Expected<MemoryRegionInfo>(
StringRef FileName, StringRef SectionName)>;
using GetStubInfoFunction = std::function<Expected<MemoryRegionInfo>(
StringRef StubContainer, StringRef TargetName)>;
StringRef StubContainer, StringRef TargetName, StringRef StubKindFilter)>;
using GetGOTInfoFunction = std::function<Expected<MemoryRegionInfo>(
StringRef GOTContainer, StringRef TargetName)>;

Expand Down
27 changes: 20 additions & 7 deletions llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,15 +400,25 @@ class RuntimeDyldCheckerExprEval {
StringRef Symbol;
std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr);

// Parse optional parameter to filter by stub kind
StringRef KindNameFilter;
if (RemainingExpr.starts_with(",")) {
RemainingExpr = RemainingExpr.substr(1).ltrim();
size_t ClosingBracket = RemainingExpr.find(")");
KindNameFilter = RemainingExpr.substr(0, ClosingBracket);
RemainingExpr = RemainingExpr.substr(ClosingBracket);
}

if (!RemainingExpr.starts_with(")"))
return std::make_pair(
unexpectedToken(RemainingExpr, Expr, "expected ')'"), "");
RemainingExpr = RemainingExpr.substr(1).ltrim();

uint64_t StubAddr;
std::string ErrorMsg;
std::tie(StubAddr, ErrorMsg) = Checker.getStubOrGOTAddrFor(
StubContainerName, Symbol, PCtx.IsInsideLoad, IsStubAddr);
std::tie(StubAddr, ErrorMsg) =
Checker.getStubOrGOTAddrFor(StubContainerName, Symbol, KindNameFilter,
PCtx.IsInsideLoad, IsStubAddr);

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

std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(
StringRef StubContainerName, StringRef SymbolName, bool IsInsideLoad,
bool IsStubAddr) const {

auto StubInfo = IsStubAddr ? GetStubInfo(StubContainerName, SymbolName)
: GetGOTInfo(StubContainerName, SymbolName);
StringRef StubContainerName, StringRef SymbolName, StringRef StubKindFilter,
bool IsInsideLoad, bool IsStubAddr) const {

assert((StubKindFilter.empty() || IsStubAddr) &&
"Kind name filter only supported for stubs");
auto StubInfo =
IsStubAddr ? GetStubInfo(StubContainerName, SymbolName, StubKindFilter)
: GetGOTInfo(StubContainerName, SymbolName);

if (!StubInfo) {
std::string ErrMsg;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class RuntimeDyldCheckerImpl {

std::pair<uint64_t, std::string>
getStubOrGOTAddrFor(StringRef StubContainerName, StringRef Symbol,
bool IsInsideLoad, bool IsStubAddr) const;
StringRef StubKindFilter, bool IsInsideLoad,
bool IsStubAddr) const;

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

Expand Down
2 changes: 1 addition & 1 deletion llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ static Error registerSymbol(LinkGraph &G, Symbol &Sym, Session::FileInfo &FI,
case Stubs:
return FI.registerStubEntry(G, Sym, getELFStubTarget);
case AArch32Stubs:
return FI.registerStubEntry(G, Sym, getELFAArch32StubTarget);
return FI.registerMultiStubEntry(G, Sym, getELFAArch32StubTarget);
case Other:
return Error::success();
}
Expand Down
86 changes: 77 additions & 9 deletions llvm/tools/llvm-jitlink/llvm-jitlink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,12 @@ operator<<(raw_ostream &OS, const Session::FileInfo &FI) {
OS << " Section \"" << SIKV.first() << "\": " << SIKV.second << "\n";
for (auto &GOTKV : FI.GOTEntryInfos)
OS << " GOT \"" << GOTKV.first() << "\": " << GOTKV.second << "\n";
for (auto &StubKV : FI.StubInfos)
OS << " Stub \"" << StubKV.first() << "\": " << StubKV.second << "\n";
for (auto &StubKVs : FI.StubInfos) {
OS << " Stubs \"" << StubKVs.first() << "\":";
for (auto MemRegion : StubKVs.second)
OS << " " << MemRegion;
OS << "\n";
}
return OS;
}

Expand Down Expand Up @@ -1207,9 +1211,35 @@ Error Session::FileInfo::registerStubEntry(
auto TS = GetSymbolTarget(G, Sym.getBlock());
if (!TS)
return TS.takeError();
StubInfos[TS->getName()] = {Sym.getSymbolContent(),
Sym.getAddress().getValue(),
Sym.getTargetFlags()};

SmallVector<MemoryRegionInfo> &Entry = StubInfos[TS->getName()];
Entry.insert(Entry.begin(),
{Sym.getSymbolContent(), Sym.getAddress().getValue(),
Sym.getTargetFlags()});
return Error::success();
}

Error Session::FileInfo::registerMultiStubEntry(
LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {
if (Sym.isSymbolZeroFill())
return make_error<StringError>("Unexpected zero-fill symbol in section " +
Sym.getBlock().getSection().getName(),
inconvertibleErrorCode());

auto Target = GetSymbolTarget(G, Sym.getBlock());
if (!Target)
return Target.takeError();

SmallVector<MemoryRegionInfo> &Entry = StubInfos[Target->getName()];
Entry.emplace_back(Sym.getSymbolContent(), Sym.getAddress().getValue(),
Sym.getTargetFlags());

// Let's keep stubs ordered by ascending address.
std::sort(Entry.begin(), Entry.end(),
[](const MemoryRegionInfo &L, const MemoryRegionInfo &R) {
return L.getTargetAddress() < R.getTargetAddress();
});

return Error::success();
}

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

static StringRef detectStubKind(const Session::MemoryRegionInfo &Stub) {
// Implement acutal stub kind detection
return "";
}

Expected<Session::MemoryRegionInfo &>
Session::findStubInfo(StringRef FileName, StringRef TargetName) {
Session::findStubInfo(StringRef FileName, StringRef TargetName,
StringRef KindNameFilter) {
auto FI = findFileInfo(FileName);
if (!FI)
return FI.takeError();
Expand All @@ -1246,7 +1282,38 @@ Session::findStubInfo(StringRef FileName, StringRef TargetName) {
"\" registered for file \"" + FileName +
"\"",
inconvertibleErrorCode());
return StubInfoItr->second;
auto &StubsForTarget = StubInfoItr->second;
assert(!StubsForTarget.empty() && "At least 1 stub in each entry");
if (KindNameFilter.empty() && StubsForTarget.size() == 1)
return StubsForTarget[0]; // Regular single-stub match

std::string KindsStr;
SmallVector<MemoryRegionInfo *, 1> Matches;
Regex KindNameMatcher(KindNameFilter.empty() ? ".*" : KindNameFilter);
for (MemoryRegionInfo &Stub : StubsForTarget) {
StringRef Kind = detectStubKind(Stub);
if (KindNameMatcher.match(Kind))
Matches.push_back(&Stub);
KindsStr += "\"" + (Kind.empty() ? "<unknown>" : Kind.str()) + "\", ";
}
if (Matches.empty())
return make_error<StringError>(
"\"" + TargetName + "\" has " + Twine(StubsForTarget.size()) +
" stubs in file \"" + FileName +
"\", but none of them matches the stub-kind filter \"" +
KindNameFilter + "\" (all encountered kinds are " +
StringRef(KindsStr.data(), KindsStr.size() - 2) + ").",
inconvertibleErrorCode());
if (Matches.size() > 1)
return make_error<StringError>(
"\"" + TargetName + "\" has " + Twine(Matches.size()) +
" candidate stubs in file \"" + FileName +
"\". Please refine stub-kind filter \"" + KindNameFilter +
"\" for disambiguation (encountered kinds are " +
StringRef(KindsStr.data(), KindsStr.size() - 2) + ").",
inconvertibleErrorCode());

return *Matches[0];
}

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

auto GetStubInfo = [&S](StringRef FileName, StringRef SectionName) {
return S.findStubInfo(FileName, SectionName);
auto GetStubInfo = [&S](StringRef FileName, StringRef SectionName,
StringRef KindNameFilter) {
return S.findStubInfo(FileName, SectionName, KindNameFilter);
};

auto GetGOTInfo = [&S](StringRef FileName, StringRef SectionName) {
Expand Down
7 changes: 5 additions & 2 deletions llvm/tools/llvm-jitlink/llvm-jitlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct Session {

struct FileInfo {
StringMap<MemoryRegionInfo> SectionInfos;
StringMap<MemoryRegionInfo> StubInfos;
StringMap<SmallVector<MemoryRegionInfo, 1>> StubInfos;
StringMap<MemoryRegionInfo> GOTEntryInfos;

using Symbol = jitlink::Symbol;
Expand All @@ -61,6 +61,8 @@ struct Session {
GetSymbolTargetFunction GetSymbolTarget);
Error registerStubEntry(LinkGraph &G, Symbol &Sym,
GetSymbolTargetFunction GetSymbolTarget);
Error registerMultiStubEntry(LinkGraph &G, Symbol &Sym,
GetSymbolTargetFunction GetSymbolTarget);
};

using DynLibJDMap = std::map<std::string, orc::JITDylib *>;
Expand All @@ -74,7 +76,8 @@ struct Session {
Expected<MemoryRegionInfo &> findSectionInfo(StringRef FileName,
StringRef SectionName);
Expected<MemoryRegionInfo &> findStubInfo(StringRef FileName,
StringRef TargetName);
StringRef TargetName,
StringRef KindNameFilter);
Expected<MemoryRegionInfo &> findGOTEntryInfo(StringRef FileName,
StringRef TargetName);

Expand Down
11 changes: 8 additions & 3 deletions llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,8 @@ static int linkAndVerify() {
};

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

auto GetGOTInfo = [&GetStubInfo](StringRef StubContainer,
StringRef SymbolName) {
return GetStubInfo(StubContainer, SymbolName, "");
};

// We will initialize this below once we have the first object file and can
// know the endianness.
std::unique_ptr<RuntimeDyldChecker> Checker;
Expand Down Expand Up @@ -977,8 +983,7 @@ static int linkAndVerify() {

if (!Checker)
Checker = std::make_unique<RuntimeDyldChecker>(
IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo,
GetStubInfo,
IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,
Obj.isLittleEndian() ? llvm::endianness::little
: llvm::endianness::big,
TheTriple, MCPU, SubtargetFeatures(), dbgs());
Expand Down