diff options
author | Stefan Gränitz <stefan.graenitz@gmail.com> | 2024-01-20 09:57:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-20 09:57:03 +0100 |
commit | 6a433d77b1f49ddeb03e27394a9b7cbf6e472d1a (patch) | |
tree | 87ef51d0da28aa34a5c2e0a069de31356a4a04ea /llvm/tools/llvm-jitlink | |
parent | 9eb0f86c279f40a792ec27bf0e9b491b8c90a640 (diff) | |
download | llvm-6a433d77b1f49ddeb03e27394a9b7cbf6e472d1a.zip llvm-6a433d77b1f49ddeb03e27394a9b7cbf6e472d1a.tar.gz llvm-6a433d77b1f49ddeb03e27394a9b7cbf6e472d1a.tar.bz2 |
[llvm-jitlink] Allow optional stub-kind filter in stub_addr() expressions (#78369)
We use `jitlink-check` lines in LIT tests as the primary tool for
testing JITLink backends. Parsing and evaluation of the expressions is
implemented in `RuntimeDyldChecker`. The `stub_addr(obj, name)`
expression allows to obtain the linker-generated stub for the external
symbol `name` in object file `obj`.
This patch adds support for a filter parameter to select one out of many
stubs. This is necessary for the AArch32 JITLink backend, which must be
able to emit two different kinds of stubs depending on the instruction
set state (Arm/Thumb) of the relocation site. Since the new parameter is
optional, we don't have to update existing tests.
Filters are regular expressions without brackets that match exactly one
existing stub. Given object file `armv7.o` with two stubs for external
function `ext` of kinds `armv7_abs_le` and `thumbv7_abs_le`, we get the
following filter results e.g.:
```
stub_addr(armv7.o, ext, thumb) thumbv7_abs_le
stub_addr(armv7.o, ext, thumbv7) thumbv7_abs_le
stub_addr(armv7.o, ext, armv7_abs_le) armv7_abs_le
stub_addr(armv7.o, ext, v7_.*_le) Error: "ext" has 2 candidate stubs in file "armv7.o". Please refine stub-kind filter "v7_.*_le" for disambiguation (encountered kinds are "thumbv7_abs_le", "armv7_abs_le").
stub_addr(armv7.o, ext, v8) Error: "ext" has 2 stubs in file "armv7.o", but none of them matches the stub-kind filter "v8" (all encountered kinds are "thumbv7_abs_le", "armv7_abs_le").
```
Diffstat (limited to 'llvm/tools/llvm-jitlink')
-rw-r--r-- | llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp | 2 | ||||
-rw-r--r-- | llvm/tools/llvm-jitlink/llvm-jitlink.cpp | 86 | ||||
-rw-r--r-- | llvm/tools/llvm-jitlink/llvm-jitlink.h | 7 |
3 files changed, 83 insertions, 12 deletions
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp index 9f7d66d..a8c804a 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp @@ -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(); } diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp index 8c18610..d233ebd 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp @@ -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; } @@ -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(); } @@ -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(); @@ -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 &> @@ -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) { diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.h b/llvm/tools/llvm-jitlink/llvm-jitlink.h index 93a0026..e09c15a 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.h +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.h @@ -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; @@ -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 *>; @@ -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); |