[llvm] [llvm-symbolizer] Recognize AIX big archive (PR #150401)
James Henderson via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 10 02:05:22 PDT 2025
================
@@ -557,57 +558,149 @@ LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path,
if (!DbgObj)
DbgObj = Obj;
ObjectPair Res = std::make_pair(Obj, DbgObj);
- std::string DbgObjPath = DbgObj->getFileName().str();
auto Pair =
ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res);
- BinaryForPath.find(DbgObjPath)->second.pushEvictor([this, I = Pair.first]() {
- ObjectPairForPathArch.erase(I);
- });
+ std::string DbgObjPath = DbgObj->getFileName().str();
+ auto BinIter = BinaryForPath.find(DbgObjPath);
+ if (BinIter != BinaryForPath.end()) {
+ BinIter->second.pushEvictor(
+ [this, I = Pair.first]() { ObjectPairForPathArch.erase(I); });
+ }
return Res;
}
-Expected<ObjectFile *>
-LLVMSymbolizer::getOrCreateObject(const std::string &Path,
- const std::string &ArchName) {
- Binary *Bin;
+Expected<object::Binary *>
+LLVMSymbolizer::loadOrGetBinary(const std::string &Path) {
auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>());
if (!Pair.second) {
- Bin = Pair.first->second->getBinary();
recordAccess(Pair.first->second);
- } else {
- Expected<OwningBinary<Binary>> BinOrErr = createBinary(Path);
- if (!BinOrErr)
- return BinOrErr.takeError();
+ return Pair.first->second->getBinary();
+ }
- CachedBinary &CachedBin = Pair.first->second;
- CachedBin = std::move(BinOrErr.get());
- CachedBin.pushEvictor([this, I = Pair.first]() { BinaryForPath.erase(I); });
- LRUBinaries.push_back(CachedBin);
- CacheSize += CachedBin.size();
- Bin = CachedBin->getBinary();
+ Expected<OwningBinary<Binary>> BinOrErr = createBinary(Path);
+ if (!BinOrErr) {
+ BinaryForPath.erase(Pair.first);
+ return BinOrErr.takeError();
}
- if (!Bin)
- return static_cast<ObjectFile *>(nullptr);
+ CachedBinary &CachedBin = Pair.first->second;
+ CachedBin = std::move(*BinOrErr);
+ CachedBin.pushEvictor([this, I = Pair.first]() { BinaryForPath.erase(I); });
+ LRUBinaries.push_back(CachedBin);
+ CacheSize += CachedBin.size();
+ return CachedBin->getBinary();
+}
- if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(Bin)) {
- auto I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
- if (I != ObjectForUBPathAndArch.end())
- return I->second.get();
-
- Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
- UB->getMachOObjectForArch(ArchName);
- if (!ObjOrErr) {
- ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
- std::unique_ptr<ObjectFile>());
- return ObjOrErr.takeError();
+Expected<ObjectFile *> LLVMSymbolizer::findOrCacheObject(
+ const ArchiveCacheKey &Key,
+ llvm::function_ref<Expected<std::unique_ptr<ObjectFile>>()> Loader,
+ const std::string &PathForBinaryCache) {
+
+ auto It = ObjectFileCache.find(Key);
+ if (It != ObjectFileCache.end())
+ return It->second.get();
+
+ Expected<std::unique_ptr<ObjectFile>> ObjOrErr = Loader();
+ if (!ObjOrErr) {
+ ObjectFileCache.emplace(Key, std::unique_ptr<ObjectFile>());
+ return ObjOrErr.takeError();
+ }
+
+ ObjectFile *Res = ObjOrErr->get();
+ auto NewEntry = ObjectFileCache.emplace(Key, std::move(*ObjOrErr));
+ auto CacheIter = BinaryForPath.find(PathForBinaryCache);
+ if (CacheIter != BinaryForPath.end())
+ CacheIter->second.pushEvictor(
+ [this, Iter = NewEntry.first]() { ObjectFileCache.erase(Iter); });
+ return Res;
+}
+
+Expected<ObjectFile *> LLVMSymbolizer::getOrCreateObjectFromArchive(
+ StringRef ArchivePath, StringRef MemberName, StringRef ArchName) {
+ Expected<object::Binary *> BinOrErr = loadOrGetBinary(ArchivePath.str());
+ if (!BinOrErr)
+ return BinOrErr.takeError();
+ object::Binary *Bin = *BinOrErr;
+
+ object::Archive *Archive = dyn_cast_if_present<object::Archive>(Bin);
+ if (!Archive)
+ return createStringError(std::errc::invalid_argument,
+ "'%s' is not a valid archive",
+ ArchivePath.str().c_str());
+
+ Error Err = Error::success();
+ // On AIX, archives can contain multiple members with the same name but
+ // different types. We need to check all matches and find one that matches
+ // both name and architecture.
+ for (auto &Child : Archive->children(Err, /*SkipInternal=*/true)) {
+ Expected<StringRef> NameOrErr = Child.getName();
+ if (!NameOrErr)
+ continue;
+ if (*NameOrErr == sys::path::filename(MemberName)) {
----------------
jh7370 wrote:
That doesn't actually answer my question. Do big archives contain full paths?
Putting it another way, what test would fail if you didn't have this call? If you haven't currently got a test for it, you should add one.
https://github.com/llvm/llvm-project/pull/150401
More information about the llvm-commits
mailing list