[llvm] big archive recognition by the llvm-symbolizer (PR #150401)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 1 04:01:54 PDT 2025


https://github.com/midhuncodes7 updated https://github.com/llvm/llvm-project/pull/150401

>From d98ed0219d45b6e66fdab6773e2c4f77f6b0e3eb Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Mon, 21 Jul 2025 14:24:50 +0530
Subject: [PATCH 1/9] big archive recognition implementation

---
 llvm/docs/CommandGuide/llvm-symbolizer.rst    |  18 ++-
 .../llvm/DebugInfo/Symbolize/Symbolize.h      |  26 ++++
 llvm/lib/DebugInfo/Symbolize/Symbolize.cpp    | 102 +++++++++++++--
 .../test/DebugInfo/Inputs/big-archive-32.yaml | 119 ++++++++++++++++++
 .../test/DebugInfo/Inputs/big-archive-64.yaml |  26 ++++
 .../DebugInfo/Inputs/big-archive-elf-1.yaml   |  68 ++++++++++
 .../DebugInfo/Inputs/big-archive-elf-2.yaml   |  68 ++++++++++
 .../DebugInfo/symbolize-big-archive-elf.test  |  24 ++++
 .../symbolize-big-archive-xcoff.test          |  26 ++++
 llvm/tools/llvm-symbolizer/Opts.td            |   6 +-
 10 files changed, 469 insertions(+), 14 deletions(-)
 create mode 100644 llvm/test/DebugInfo/Inputs/big-archive-32.yaml
 create mode 100644 llvm/test/DebugInfo/Inputs/big-archive-64.yaml
 create mode 100644 llvm/test/DebugInfo/Inputs/big-archive-elf-1.yaml
 create mode 100644 llvm/test/DebugInfo/Inputs/big-archive-elf-2.yaml
 create mode 100644 llvm/test/DebugInfo/symbolize-big-archive-elf.test
 create mode 100644 llvm/test/DebugInfo/symbolize-big-archive-xcoff.test

diff --git a/llvm/docs/CommandGuide/llvm-symbolizer.rst b/llvm/docs/CommandGuide/llvm-symbolizer.rst
index 2da1b2470a83e..8f3a132139fe9 100644
--- a/llvm/docs/CommandGuide/llvm-symbolizer.rst
+++ b/llvm/docs/CommandGuide/llvm-symbolizer.rst
@@ -535,16 +535,20 @@ MACH-O SPECIFIC OPTIONS
 .. option:: --default-arch <arch>
 
   If a binary contains object files for multiple architectures (e.g. it is a
-  Mach-O universal binary), symbolize the object file for a given architecture.
-  You can also specify the architecture by writing ``binary_name:arch_name`` in
-  the input (see example below). If the architecture is not specified in either
-  way, the address will not be symbolized. Defaults to empty string.
+  Mach-O universal binary or an AIX archive with architecture variants),
+  symbolize the object file for a given architecture. You can also specify
+  the architecture by writing ``binary_name:arch_name`` in the input (see
+  example below). For AIX archives, the format ``archive.a(member.o):arch``
+  is also supported. If the architecture is not specified in either way,
+  the address will not be symbolized. Defaults to empty string.
 
   .. code-block:: console
 
     $ cat addr.txt
     /tmp/mach_universal_binary:i386 0x1f84
     /tmp/mach_universal_binary:x86_64 0x100000f24
+    /tmp/archive.a(member.o):ppc 0x1000
+    /tmp/archive.a(member.o):ppc64 0x2000
 
     $ llvm-symbolizer < addr.txt
     _main
@@ -553,6 +557,12 @@ MACH-O SPECIFIC OPTIONS
     _main
     /tmp/source_x86_64.cc:8
 
+    _foo
+    /tmp/source_ppc.cc:12
+    
+    _foo
+    /tmp/source_ppc64.cc:12
+
 .. option:: --dsym-hint <path/to/file.dSYM>
 
   If the debug info for a binary isn't present in the default location, look for
diff --git a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
index fb8f3d8af6b1b..5144085f3e23c 100644
--- a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
+++ b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
@@ -29,6 +29,12 @@
 #include <utility>
 #include <vector>
 
+#if defined(_AIX)
+#  define SYMBOLIZE_AIX 1
+#else
+#  define SYMBOLIZE_AIX 0
+#endif
+
 namespace llvm {
 namespace object {
 class ELFObjectFileBase;
@@ -202,6 +208,12 @@ class LLVMSymbolizer {
   Expected<ObjectFile *> getOrCreateObject(const std::string &Path,
                                            const std::string &ArchName);
 
+  /// Return a pointer to object file at specified path, for a specified
+  /// architecture that is present inside an archive file
+  Expected<ObjectFile *> getOrCreateObjectFromArchive(StringRef ArchivePath,
+                                                      StringRef MemberName,
+                                                      const std::string &ArchName);   
+
   /// Update the LRU cache order when a binary is accessed.
   void recordAccess(CachedBinary &Bin);
 
@@ -226,6 +238,20 @@ class LLVMSymbolizer {
   std::map<std::pair<std::string, std::string>, std::unique_ptr<ObjectFile>>
       ObjectForUBPathAndArch;
 
+  struct ArchiveCacheKey {
+    std::string ArchivePath;  // Storage for StringRef
+    std::string MemberName;   // Storage for StringRef
+    std::string ArchName;     // Storage for StringRef
+
+    // Required for map comparison
+    bool operator<(const ArchiveCacheKey &Other) const {
+      return std::tie(ArchivePath, MemberName, ArchName) < 
+             std::tie(Other.ArchivePath, Other.MemberName, Other.ArchName);
+    }
+  };
+
+  std::map<ArchiveCacheKey, std::unique_ptr<ObjectFile>> ObjectForArchivePathAndArch;
+  
   Options Opts;
 
   std::unique_ptr<BuildIDFetcher> BIDFetcher;
diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
index 56527719da51f..6dddc3a709239 100644
--- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -33,6 +33,7 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Object/Archive.h"
 #include <cassert>
 #include <cstring>
 
@@ -286,6 +287,7 @@ LLVMSymbolizer::findSymbol(ArrayRef<uint8_t> BuildID, StringRef Symbol,
 
 void LLVMSymbolizer::flush() {
   ObjectForUBPathAndArch.clear();
+  ObjectForArchivePathAndArch.clear();
   LRUBinaries.clear();
   CacheSize = 0;
   BinaryForPath.clear();
@@ -321,7 +323,7 @@ bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
 
 bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName,
                              uint32_t &CRCHash) {
-  if (!Obj)
+  if (!Obj || !isa<ObjectFile>(Obj))
     return false;
   for (const SectionRef &Section : Obj->sections()) {
     StringRef Name;
@@ -557,19 +559,101 @@ 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]() {
+  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::getOrCreateObjectFromArchive(StringRef ArchivePath, 
+                                                                    StringRef MemberName, 
+                                                                    const std::string &ArchName) {
+  Binary *Bin = nullptr;
+  auto Pair = BinaryForPath.emplace(ArchivePath.str(), OwningBinary<Binary>());
+  if (!Pair.second) {
+    Bin = Pair.first->second->getBinary();
+    recordAccess(Pair.first->second);
+  } else {
+    Expected<OwningBinary<Binary>> ArchiveOrErr = createBinary(ArchivePath);
+    if (!ArchiveOrErr) {
+      return ArchiveOrErr.takeError();
+    }
+
+    CachedBinary &CachedBin = Pair.first->second;
+    CachedBin = std::move(ArchiveOrErr.get());
+    CachedBin.pushEvictor([this, I = Pair.first]() { BinaryForPath.erase(I); });
+    LRUBinaries.push_back(CachedBin);
+    CacheSize += CachedBin.size();
+    Bin = CachedBin->getBinary();
+  }
+
+  if (!Bin || !isa<object::Archive>(Bin))
+    return errorCodeToError(object_error::invalid_file_type);
+
+  object::Archive *Archive = cast<object::Archive>(Bin);
+  Error Err = Error::success();
+  
+  // On AIX, archives can contain multiple members with 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 == llvm::sys::path::filename(MemberName)) {
+      Expected<std::unique_ptr<object::Binary>> MemberOrErr = Child.getAsBinary();
+      if (!MemberOrErr)
+        continue; 
+      
+      std::unique_ptr<object::Binary> Binary = std::move(*MemberOrErr);
+      if (auto *Obj = dyn_cast<object::ObjectFile>(Binary.get())) {
+#if defined(_AIX)
+        Triple::ArchType ObjArch = Obj->makeTriple().getArch();
+        Triple RequestedTriple;
+        RequestedTriple.setArch(Triple::getArchTypeForLLVMName(ArchName));
+        if (ObjArch != RequestedTriple.getArch())
+          continue;
+#endif
+        ArchiveCacheKey CacheKey{ArchivePath.str(), MemberName.str(), ArchName};
+        auto I = ObjectForArchivePathAndArch.find(CacheKey);
+        if (I != ObjectForArchivePathAndArch.end())
+          return I->second.get();
+
+        auto CachedObj = std::unique_ptr<ObjectFile>(Obj);
+        auto NewEntry = ObjectForArchivePathAndArch.emplace(
+            CacheKey, std::move(CachedObj));
+        Binary.release();
+        BinaryForPath.find(ArchivePath.str())->second.pushEvictor(
+            [this, Iter = NewEntry.first]() { ObjectForArchivePathAndArch.erase(Iter); });
+        return NewEntry.first->second.get();
+      }
+    }
+  }
+  if (Err)
+    return std::move(Err);
+  return errorCodeToError(object_error::arch_not_found);
+}
+
 Expected<ObjectFile *>
 LLVMSymbolizer::getOrCreateObject(const std::string &Path,
                                   const std::string &ArchName) {
-  Binary *Bin;
+  // First check for archive(member) format - more efficient to check closing paren first
+  size_t CloseParen = Path.rfind(')');
+  if (CloseParen != std::string::npos && CloseParen == Path.length() - 1) {
+    size_t OpenParen = Path.rfind('(', CloseParen);
+    if (OpenParen != std::string::npos) {
+      StringRef ArchivePath = StringRef(Path).substr(0, OpenParen);
+      StringRef MemberName = StringRef(Path).substr(OpenParen + 1, CloseParen - OpenParen - 1);
+      return getOrCreateObjectFromArchive(ArchivePath, MemberName, ArchName);
+    }
+  }
+
+  Binary *Bin = nullptr;
   auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>());
   if (!Pair.second) {
     Bin = Pair.first->second->getBinary();
@@ -648,7 +732,9 @@ LLVMSymbolizer::getOrCreateModuleInfo(StringRef ModuleName) {
 
   auto I = Modules.find(ModuleName);
   if (I != Modules.end()) {
-    recordAccess(BinaryForPath.find(BinaryName)->second);
+    auto BinIter = BinaryForPath.find(BinaryName);
+    if (BinIter != BinaryForPath.end())
+      recordAccess(BinIter->second);
     return I->second.get();
   }
 
@@ -716,7 +802,9 @@ LLVMSymbolizer::getOrCreateModuleInfo(StringRef ModuleName) {
       createModuleInfo(Objects.first, std::move(Context), ModuleName);
   if (ModuleOrErr) {
     auto I = Modules.find(ModuleName);
-    BinaryForPath.find(BinaryName)->second.pushEvictor([this, I]() {
+    auto BinIter = BinaryForPath.find(BinaryName);
+    if (BinIter != BinaryForPath.end()) 
+      BinIter->second.pushEvictor([this, I]() {
       Modules.erase(I);
     });
   }
diff --git a/llvm/test/DebugInfo/Inputs/big-archive-32.yaml b/llvm/test/DebugInfo/Inputs/big-archive-32.yaml
new file mode 100644
index 0000000000000..2080607a1a88c
--- /dev/null
+++ b/llvm/test/DebugInfo/Inputs/big-archive-32.yaml
@@ -0,0 +1,119 @@
+--- !XCOFF
+FileHeader:
+  MagicNumber:     0x1DF
+  NumberOfSections: 2
+  CreationTime:    0
+  OffsetToSymbolTable: 0xA0
+  EntriesInSymbolTable: 11
+  AuxiliaryHeaderSize: 0
+  Flags:           0x0
+Sections:
+  - Name:            .text
+    Address:         0x0
+    Size:            0x1C
+    FileOffsetToData: 0x64
+    FileOffsetToRelocations: 0x0
+    FileOffsetToLineNumbers: 0x0
+    NumberOfRelocations: 0x0
+    NumberOfLineNumbers: 0x0
+    Flags:           [ STYP_TEXT ]
+    SectionData:     4E800020000000000009204000000001000000040003666F6F000000
+  - Name:            .data
+    Address:         0x1C
+    Size:            0xC
+    FileOffsetToData: 0x80
+    FileOffsetToRelocations: 0x8C
+    FileOffsetToLineNumbers: 0x0
+    NumberOfRelocations: 0x2
+    NumberOfLineNumbers: 0x0
+    Flags:           [ STYP_DATA ]
+    SectionData:     '000000000000002800000000'
+    Relocations:
+      - Address:         0x1C
+        Symbol:          0x5
+        Info:            0x1F
+        Type:            0x0
+      - Address:         0x20
+        Symbol:          0x9
+        Info:            0x1F
+        Type:            0x0
+Symbols:
+  - Name:            .file
+    Value:           0x0
+    Section:         N_DEBUG
+    Type:            0x18
+    StorageClass:    C_FILE
+    NumberOfAuxEntries: 2
+    AuxEntries:
+      - Type:            AUX_FILE
+        FileNameOrString: foo.c
+        FileStringType:  XFT_FN
+      - Type:            AUX_FILE
+        FileNameOrString: 'IBM Open XL C/C++ for AIX 17.1.3 (5725-C72, 5765-J18), version 17.1.3.0, LLVM version 21.0.0git (145c02cece3630765e6412e6820bc446ddb4e138)'
+        FileStringType:  XFT_CV
+  - Name:            ''
+    Value:           0x0
+    Section:         .text
+    Type:            0x0
+    StorageClass:    C_HIDEXT
+    NumberOfAuxEntries: 1
+    AuxEntries:
+      - Type:            AUX_CSECT
+        ParameterHashIndex: 0
+        TypeChkSectNum:  0
+        SymbolType:      XTY_SD
+        SymbolAlignment: 5
+        StorageMappingClass: XMC_PR
+        SectionOrLength: 25
+        StabInfoIndex:   0
+        StabSectNum:     0
+  - Name:            .foo
+    Value:           0x0
+    Section:         .text
+    Type:            0x0
+    StorageClass:    C_EXT
+    NumberOfAuxEntries: 1
+    AuxEntries:
+      - Type:            AUX_CSECT
+        ParameterHashIndex: 0
+        TypeChkSectNum:  0
+        SymbolType:      XTY_LD
+        SymbolAlignment: 0
+        StorageMappingClass: XMC_PR
+        SectionOrLength: 3
+        StabInfoIndex:   0
+        StabSectNum:     0
+  - Name:            foo
+    Value:           0x1C
+    Section:         .data
+    Type:            0x0
+    StorageClass:    C_EXT
+    NumberOfAuxEntries: 1
+    AuxEntries:
+      - Type:            AUX_CSECT
+        ParameterHashIndex: 0
+        TypeChkSectNum:  0
+        SymbolType:      XTY_SD
+        SymbolAlignment: 2
+        StorageMappingClass: XMC_DS
+        SectionOrLength: 12
+        StabInfoIndex:   0
+        StabSectNum:     0
+  - Name:            TOC
+    Value:           0x28
+    Section:         .data
+    Type:            0x0
+    StorageClass:    C_HIDEXT
+    NumberOfAuxEntries: 1
+    AuxEntries:
+      - Type:            AUX_CSECT
+        ParameterHashIndex: 0
+        TypeChkSectNum:  0
+        SymbolType:      XTY_SD
+        SymbolAlignment: 2
+        StorageMappingClass: XMC_TC0
+        SectionOrLength: 0
+        StabInfoIndex:   0
+        StabSectNum:     0
+StringTable:     {}
+...
diff --git a/llvm/test/DebugInfo/Inputs/big-archive-64.yaml b/llvm/test/DebugInfo/Inputs/big-archive-64.yaml
new file mode 100644
index 0000000000000..c1078efe2407e
--- /dev/null
+++ b/llvm/test/DebugInfo/Inputs/big-archive-64.yaml
@@ -0,0 +1,26 @@
+--- !XCOFF
+FileHeader:
+  Magic: 0x01F7        # XCOFF64 magic number
+  NumberOfSections: 1
+  TimeStamp: 0
+  SymbolTableOffset: 0
+  NumberOfSymTableEntries: 1
+OptionalHeader:
+  Flags: 0x0
+Sections:
+  - Name: .text
+    Address: 0x0`
+    Size: 1
+    FileOffsetToRawData: 0x100
+    FileOffsetToRelocations: 0
+    FileOffsetToLineNumbers: 0
+    NumberOfRelocations: 0
+    NumberOfLineNumbers: 0
+    Flags: STYP_TEXT
+    SectionData: '00'
+Symbols:
+  - Name: foo
+    Value: 0
+    SectionNumber: 1
+    StorageClass: C_EXT
+    NumberOfAuxEntries: 0
diff --git a/llvm/test/DebugInfo/Inputs/big-archive-elf-1.yaml b/llvm/test/DebugInfo/Inputs/big-archive-elf-1.yaml
new file mode 100644
index 0000000000000..8e5c929e82878
--- /dev/null
+++ b/llvm/test/DebugInfo/Inputs/big-archive-elf-1.yaml
@@ -0,0 +1,68 @@
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_PPC64
+  Flags:           [  ]
+  SectionHeaderStringTable: .strtab
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x10
+    Content:         '2000804E000000000000000000000000'
+  - Name:            .comment
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x1
+    EntSize:         0x1
+    Content:         0049424D204F70656E20584C20432F432B2B20666F72204C696E7578206F6E20506F7765722031372E312E322028353732352D4337322C20353736352D4A3230292C2076657273696F6E2031372E312E322E302C20636C616E672076657273696F6E2032312E302E306769742028676974406769746875622E69626D2E636F6D3A636F6D70696C65722F6C6C766D2D70726F6A6563742E67697420653165653233663838333532623937333563363735386661396335653035313366626234393361322900
+  - Name:            .note.GNU-stack
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x1
+  - Name:            .eh_frame
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    AddressAlign:    0x8
+    Content:         1000000000000000017A5200047841011B0C01001000000018000000000000001000000000000000
+  - Name:            .rela.eh_frame
+    Type:            SHT_RELA
+    Flags:           [ SHF_INFO_LINK ]
+    Link:            .symtab
+    AddressAlign:    0x8
+    Info:            .eh_frame
+    Relocations:
+      - Offset:          0x1C
+        Symbol:          .text
+        Type:            R_PPC64_REL32
+  - Name:            .llvm_addrsig
+    Type:            SHT_LLVM_ADDRSIG
+    Flags:           [ SHF_EXCLUDE ]
+    Link:            .symtab
+    AddressAlign:    0x1
+    Offset:          0x1B8
+    Symbols:         [  ]
+  - Type:            SectionHeaderTable
+    Sections:
+      - Name:            .strtab
+      - Name:            .text
+      - Name:            .comment
+      - Name:            .note.GNU-stack
+      - Name:            .eh_frame
+      - Name:            .rela.eh_frame
+      - Name:            .llvm_addrsig
+      - Name:            .symtab
+Symbols:
+  - Name:            foo1.c
+    Type:            STT_FILE
+    Index:           SHN_ABS
+  - Name:            .text
+    Type:            STT_SECTION
+    Section:         .text
+  - Name:            foo1
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Size:            0x10
+...
diff --git a/llvm/test/DebugInfo/Inputs/big-archive-elf-2.yaml b/llvm/test/DebugInfo/Inputs/big-archive-elf-2.yaml
new file mode 100644
index 0000000000000..0052db732500f
--- /dev/null
+++ b/llvm/test/DebugInfo/Inputs/big-archive-elf-2.yaml
@@ -0,0 +1,68 @@
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_PPC64
+  Flags:           [  ]
+  SectionHeaderStringTable: .strtab
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x10
+    Content:         '2000804E000000000000000000000000'
+  - Name:            .comment
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x1
+    EntSize:         0x1
+    Content:         0049424D204F70656E20584C20432F432B2B20666F72204C696E7578206F6E20506F7765722031372E312E322028353732352D4337322C20353736352D4A3230292C2076657273696F6E2031372E312E322E302C20636C616E672076657273696F6E2032312E302E306769742028676974406769746875622E69626D2E636F6D3A636F6D70696C65722F6C6C766D2D70726F6A6563742E67697420653165653233663838333532623937333563363735386661396335653035313366626234393361322900
+  - Name:            .note.GNU-stack
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x1
+  - Name:            .eh_frame
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    AddressAlign:    0x8
+    Content:         1000000000000000017A5200047841011B0C01001000000018000000000000001000000000000000
+  - Name:            .rela.eh_frame
+    Type:            SHT_RELA
+    Flags:           [ SHF_INFO_LINK ]
+    Link:            .symtab
+    AddressAlign:    0x8
+    Info:            .eh_frame
+    Relocations:
+      - Offset:          0x1C
+        Symbol:          .text
+        Type:            R_PPC64_REL32
+  - Name:            .llvm_addrsig
+    Type:            SHT_LLVM_ADDRSIG
+    Flags:           [ SHF_EXCLUDE ]
+    Link:            .symtab
+    AddressAlign:    0x1
+    Offset:          0x1B8
+    Symbols:         [  ]
+  - Type:            SectionHeaderTable
+    Sections:
+      - Name:            .strtab
+      - Name:            .text
+      - Name:            .comment
+      - Name:            .note.GNU-stack
+      - Name:            .eh_frame
+      - Name:            .rela.eh_frame
+      - Name:            .llvm_addrsig
+      - Name:            .symtab
+Symbols:
+  - Name:            foo2.c
+    Type:            STT_FILE
+    Index:           SHN_ABS
+  - Name:            .text
+    Type:            STT_SECTION
+    Section:         .text
+  - Name:            foo2
+    Type:            STT_FUNC
+    Section:         .text
+    Binding:         STB_GLOBAL
+    Size:            0x10
+...
diff --git a/llvm/test/DebugInfo/symbolize-big-archive-elf.test b/llvm/test/DebugInfo/symbolize-big-archive-elf.test
new file mode 100644
index 0000000000000..2cd223333d546
--- /dev/null
+++ b/llvm/test/DebugInfo/symbolize-big-archive-elf.test
@@ -0,0 +1,24 @@
+// Test archive member recognition by name (ELF format)
+
+// Generate object files from YAML
+// RUN: yaml2obj -o %t-1.o %S/Inputs/big-archive-elf-1.yaml
+// RUN: yaml2obj -o %t-2.o %S/Inputs/big-archive-elf-2.yaml
+
+// Create archive with differently named members
+// RUN: rm -f %t.a
+// RUN: llvm-ar crv %t.a %t-1.o %t-2.o
+
+// Verify archive contents
+// RUN: llvm-ar tv %t.a | FileCheck %s --check-prefix=CHECK-ARCHIVE
+// CHECK-ARCHIVE: {{.*}}-1.o
+// CHECK-ARCHIVE: {{.*}}-2.o
+
+// Test symbolization by member name (using just base names)
+// RUN: llvm-symbolizer --default-arch=ppc64 --obj="%t.a(%t-1.o)" 0x0 | FileCheck %s --check-prefix=CHECK-1
+// RUN: llvm-symbolizer --default-arch=ppc64 --obj="%t.a(%t-2.o)" 0x0 | FileCheck %s --check-prefix=CHECK-2
+// CHECK-1: foo1
+// CHECK-2: foo2
+
+// Test error cases
+// RUN: not llvm-symbolizer --obj="%t.a(nonexistent.o)" 0x1000 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+// CHECK-ERROR: error: {{.*}}No object file for requested architecture
diff --git a/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test b/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
new file mode 100644
index 0000000000000..ae39fc929bea6
--- /dev/null
+++ b/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
@@ -0,0 +1,26 @@
+// Test big archive recognition and error handling in llvm-symbolizer
+
+// Generate object files
+// RUN: yaml2obj -o %t-32.o %S/Inputs/big-archive-32.yaml
+// RUN: yaml2obj -o %t-64.o %S/Inputs/big-archive-64.yaml
+
+// Create archive with same-named members using different modes
+// RUN: rm -f %t.a
+// RUN: cp %t-32.o %t.o && llvm-ar -X32 crv %t.a %t.o
+// RUN: cp %t-64.o %t.o && llvm-ar -X64 qv %t.a %t.o
+ 
+// Verify archive contains two members with same name
+// RUN: llvm-ar tv -X32_64 %t.a | FileCheck %s --check-prefix=CHECK-ARCHIVE
+// CHECK-ARCHIVE: {{.*}}symbolize-big-archive-xcoff.test.tmp.o{{$}}
+// CHECK-ARCHIVE: {{.*}}symbolize-big-archive-xcoff.test.tmp.o{{$}}
+
+// Test successful symbolization
+// RUN: llvm-symbolizer --default-arch=ppc --obj="%t.a(%t.o)" 0x0 | FileCheck %s --check-prefix=CHECK-32
+// RUN: llvm-symbolizer --default-arch=ppc64 --obj="%t.a(%t.o)" 0x0 | FileCheck %s --check-prefix=CHECK-64
+// CHECK-32: foo
+// CHECK-64: foo
+
+// Test error cases
+// RUN: not llvm-symbolizer --obj="%t.a(nonexistent.o)" 0x1000 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+
+// CHECK-ERROR: error: {{.*}}No object file for requested architecture
diff --git a/llvm/tools/llvm-symbolizer/Opts.td b/llvm/tools/llvm-symbolizer/Opts.td
index 10f1e6dbbddf7..f616109346c55 100644
--- a/llvm/tools/llvm-symbolizer/Opts.td
+++ b/llvm/tools/llvm-symbolizer/Opts.td
@@ -15,7 +15,7 @@ class F<string name, string help>: Flag<["--"], name>, HelpText<help>;
 
 def grp_mach_o : OptionGroup<"kind">,
                  HelpText<"llvm-symbolizer Mach-O Specific Options">;
-
+def grp_symbolizer : OptionGroup<"Symbolizer Options">;
 def grp_gsym : OptionGroup<"kind">,
                HelpText<"llvm-symbolizer GSYM Related Options">;
 
@@ -31,8 +31,8 @@ def color_EQ : Joined<["--"], "color=">, HelpText<"Whether to use color when sym
 defm debug_file_directory : Eq<"debug-file-directory", "Path to directory where to look for debug files">, MetaVarName<"<dir>">;
 defm debuginfod : B<"debuginfod", "Use debuginfod to find debug binaries", "Don't use debuginfod to find debug binaries">;
 defm default_arch
-    : Eq<"default-arch", "Default architecture (for multi-arch objects)">,
-      Group<grp_mach_o>;
+    : Eq<"default-arch", "Default architecture for multi-arch containers (Mach-O objects or AIX archives)">,
+      Group<grp_symbolizer>;
 defm demangle : B<"demangle", "Demangle function names", "Don't demangle function names">;
 def disable_gsym : F<"disable-gsym", "Don't consider using GSYM files for symbolication">, Group<grp_gsym>;
 def filter_markup : Flag<["--"], "filter-markup">, HelpText<"Filter symbolizer markup from stdin.">;

>From 64639e1512af8f31a9dfd909082f3c2a496bd914 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Tue, 22 Jul 2025 15:25:01 +0530
Subject: [PATCH 2/9] ELF test not supported on AIX

---
 llvm/test/DebugInfo/symbolize-big-archive-elf.test | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/test/DebugInfo/symbolize-big-archive-elf.test b/llvm/test/DebugInfo/symbolize-big-archive-elf.test
index 2cd223333d546..87442f633548d 100644
--- a/llvm/test/DebugInfo/symbolize-big-archive-elf.test
+++ b/llvm/test/DebugInfo/symbolize-big-archive-elf.test
@@ -1,4 +1,5 @@
 // Test archive member recognition by name (ELF format)
+// UNSUPPORTED: target={{.*}}-aix{{.*}}
 
 // Generate object files from YAML
 // RUN: yaml2obj -o %t-1.o %S/Inputs/big-archive-elf-1.yaml

>From f5a357ef3d638cc7d603783755f646d035853bc5 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhuensh.p at ibm.com>
Date: Thu, 24 Jul 2025 05:07:26 -0400
Subject: [PATCH 3/9] update yaml script

---
 .../test/DebugInfo/Inputs/big-archive-64.yaml | 133 +++++++++++++++---
 1 file changed, 111 insertions(+), 22 deletions(-)

diff --git a/llvm/test/DebugInfo/Inputs/big-archive-64.yaml b/llvm/test/DebugInfo/Inputs/big-archive-64.yaml
index c1078efe2407e..9bbb1107555e0 100644
--- a/llvm/test/DebugInfo/Inputs/big-archive-64.yaml
+++ b/llvm/test/DebugInfo/Inputs/big-archive-64.yaml
@@ -1,26 +1,115 @@
 --- !XCOFF
 FileHeader:
-  Magic: 0x01F7        # XCOFF64 magic number
-  NumberOfSections: 1
-  TimeStamp: 0
-  SymbolTableOffset: 0
-  NumberOfSymTableEntries: 1
-OptionalHeader:
-  Flags: 0x0
+  MagicNumber:     0x1F7
+  NumberOfSections: 2
+  CreationTime:    0
+  OffsetToSymbolTable: 0xF8
+  EntriesInSymbolTable: 11
+  AuxiliaryHeaderSize: 0
+  Flags:           0x0
 Sections:
-  - Name: .text
-    Address: 0x0`
-    Size: 1
-    FileOffsetToRawData: 0x100
-    FileOffsetToRelocations: 0
-    FileOffsetToLineNumbers: 0
-    NumberOfRelocations: 0
-    NumberOfLineNumbers: 0
-    Flags: STYP_TEXT
-    SectionData: '00'
+  - Name:            .text
+    Address:         0x0
+    Size:            0x1C
+    FileOffsetToData: 0xA8
+    FileOffsetToRelocations: 0x0
+    FileOffsetToLineNumbers: 0x0
+    NumberOfRelocations: 0x0
+    NumberOfLineNumbers: 0x0
+    Flags:           [ STYP_TEXT ]
+    SectionData:     4E800020000000000009204000000001000000040003666F6F000000
+  - Name:            .data
+    Address:         0x20
+    Size:            0x18
+    FileOffsetToData: 0xC4
+    FileOffsetToRelocations: 0xDC
+    FileOffsetToLineNumbers: 0x0
+    NumberOfRelocations: 0x2
+    NumberOfLineNumbers: 0x0
+    Flags:           [ STYP_DATA ]
+    SectionData:     '000000000000000000000000000000380000000000000000'
+    Relocations:
+      - Address:         0x20
+        Symbol:          0x5
+        Info:            0x3F
+        Type:            0x0
+      - Address:         0x28
+        Symbol:          0x9
+        Info:            0x3F
+        Type:            0x0
 Symbols:
-  - Name: foo
-    Value: 0
-    SectionNumber: 1
-    StorageClass: C_EXT
-    NumberOfAuxEntries: 0
+  - Name:            .file
+    Value:           0x0
+    Section:         N_DEBUG
+    Type:            0x18
+    StorageClass:    C_FILE
+    NumberOfAuxEntries: 2
+    AuxEntries:
+      - Type:            AUX_FILE
+        FileNameOrString: foo.c
+        FileStringType:  XFT_FN
+      - Type:            AUX_FILE
+        FileNameOrString: 'IBM Open XL C/C++ for AIX 17.1.3 (5725-C72, 5765-J18), version 17.1.3.0, LLVM version 21.0.0git (5ca72bc8d2e87445649eab1825dffd2a047440ba)'
+        FileStringType:  XFT_CV
+  - Name:            ''
+    Value:           0x0
+    Section:         .text
+    Type:            0x0
+    StorageClass:    C_HIDEXT
+    NumberOfAuxEntries: 1
+    AuxEntries:
+      - Type:            AUX_CSECT
+        ParameterHashIndex: 0
+        TypeChkSectNum:  0
+        SymbolType:      XTY_SD
+        SymbolAlignment: 5
+        StorageMappingClass: XMC_PR
+        SectionOrLengthLo: 25
+        SectionOrLengthHi: 0
+  - Name:            .foo
+    Value:           0x0
+    Section:         .text
+    Type:            0x0
+    StorageClass:    C_EXT
+    NumberOfAuxEntries: 1
+    AuxEntries:
+      - Type:            AUX_CSECT
+        ParameterHashIndex: 0
+        TypeChkSectNum:  0
+        SymbolType:      XTY_LD
+        SymbolAlignment: 0
+        StorageMappingClass: XMC_PR
+        SectionOrLengthLo: 3
+        SectionOrLengthHi: 0
+  - Name:            foo
+    Value:           0x20
+    Section:         .data
+    Type:            0x0
+    StorageClass:    C_EXT
+    NumberOfAuxEntries: 1
+    AuxEntries:
+      - Type:            AUX_CSECT
+        ParameterHashIndex: 0
+        TypeChkSectNum:  0
+        SymbolType:      XTY_SD
+        SymbolAlignment: 3
+        StorageMappingClass: XMC_DS
+        SectionOrLengthLo: 24
+        SectionOrLengthHi: 0
+  - Name:            TOC
+    Value:           0x38
+    Section:         .data
+    Type:            0x0
+    StorageClass:    C_HIDEXT
+    NumberOfAuxEntries: 1
+    AuxEntries:
+      - Type:            AUX_CSECT
+        ParameterHashIndex: 0
+        TypeChkSectNum:  0
+        SymbolType:      XTY_SD
+        SymbolAlignment: 2
+        StorageMappingClass: XMC_TC0
+        SectionOrLengthLo: 0
+        SectionOrLengthHi: 0
+StringTable:     {}
+...

>From 305ef99231413fde40eac648a40217e6e69cf49a Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Thu, 24 Jul 2025 16:00:48 +0530
Subject: [PATCH 4/9] target specific changes

---
 llvm/test/DebugInfo/symbolize-big-archive-xcoff.test | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test b/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
index ae39fc929bea6..f034520638267 100644
--- a/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
+++ b/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
@@ -1,4 +1,5 @@
 // Test big archive recognition and error handling in llvm-symbolizer
+// REQUIRES: system-aix, target={{.*}}-aix{{.*}}
 
 // Generate object files
 // RUN: yaml2obj -o %t-32.o %S/Inputs/big-archive-32.yaml

>From 27b4f10441e8ad73ebf79d30245d1f7c8359437e Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Wed, 30 Jul 2025 19:53:32 +0530
Subject: [PATCH 5/9] Review comments addressed

---
 llvm/docs/CommandGuide/llvm-symbolizer.rst    |  6 +-
 .../llvm/DebugInfo/Symbolize/Symbolize.h      | 27 +++++----
 llvm/lib/DebugInfo/Symbolize/Symbolize.cpp    | 59 ++++++++++---------
 .../DebugInfo/symbolize-big-archive-elf.test  | 12 ++--
 .../symbolize-big-archive-xcoff.test          | 32 +++++++---
 5 files changed, 75 insertions(+), 61 deletions(-)

diff --git a/llvm/docs/CommandGuide/llvm-symbolizer.rst b/llvm/docs/CommandGuide/llvm-symbolizer.rst
index 8f3a132139fe9..7a33d538269fd 100644
--- a/llvm/docs/CommandGuide/llvm-symbolizer.rst
+++ b/llvm/docs/CommandGuide/llvm-symbolizer.rst
@@ -547,8 +547,8 @@ MACH-O SPECIFIC OPTIONS
     $ cat addr.txt
     /tmp/mach_universal_binary:i386 0x1f84
     /tmp/mach_universal_binary:x86_64 0x100000f24
-    /tmp/archive.a(member.o):ppc 0x1000
-    /tmp/archive.a(member.o):ppc64 0x2000
+    /tmp/big-archive.a(member.o):ppc 0x1000
+    /tmp/big-archive.a(member.o):ppc64 0x2000
 
     $ llvm-symbolizer < addr.txt
     _main
@@ -559,7 +559,7 @@ MACH-O SPECIFIC OPTIONS
 
     _foo
     /tmp/source_ppc.cc:12
-    
+
     _foo
     /tmp/source_ppc64.cc:12
 
diff --git a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
index 5144085f3e23c..99297cebd5c89 100644
--- a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
+++ b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
@@ -29,10 +29,10 @@
 #include <utility>
 #include <vector>
 
-#if defined(_AIX)
-#  define SYMBOLIZE_AIX 1
+#ifdef _AIX
+#define SYMBOLIZE_AIX 1
 #else
-#  define SYMBOLIZE_AIX 0
+#define SYMBOLIZE_AIX 0
 #endif
 
 namespace llvm {
@@ -205,14 +205,14 @@ class LLVMSymbolizer {
   /// Return a pointer to object file at specified path, for a specified
   /// architecture (e.g. if path refers to a Mach-O universal binary, only one
   /// object file from it will be returned).
-  Expected<ObjectFile *> getOrCreateObject(const std::string &Path,
-                                           const std::string &ArchName);
+  Expected<ObjectFile *> getOrCreateObject(const std::string &InputPath,
+                                           const std::string &DefaultArchName);
 
   /// Return a pointer to object file at specified path, for a specified
   /// architecture that is present inside an archive file
-  Expected<ObjectFile *> getOrCreateObjectFromArchive(StringRef ArchivePath,
-                                                      StringRef MemberName,
-                                                      const std::string &ArchName);   
+  Expected<ObjectFile *>
+  getOrCreateObjectFromArchive(StringRef ArchivePath, StringRef MemberName,
+                               StringRef ArchName);
 
   /// Update the LRU cache order when a binary is accessed.
   void recordAccess(CachedBinary &Bin);
@@ -239,18 +239,19 @@ class LLVMSymbolizer {
       ObjectForUBPathAndArch;
 
   struct ArchiveCacheKey {
-    std::string ArchivePath;  // Storage for StringRef
-    std::string MemberName;   // Storage for StringRef
-    std::string ArchName;     // Storage for StringRef
+    std::string ArchivePath; // Storage for StringRef
+    std::string MemberName;  // Storage for StringRef
+    std::string ArchName;    // Storage for StringRef
 
     // Required for map comparison
     bool operator<(const ArchiveCacheKey &Other) const {
-      return std::tie(ArchivePath, MemberName, ArchName) < 
+      return std::tie(ArchivePath, MemberName, ArchName) <
              std::tie(Other.ArchivePath, Other.MemberName, Other.ArchName);
     }
   };
 
-  std::map<ArchiveCacheKey, std::unique_ptr<ObjectFile>> ObjectForArchivePathAndArch;
+  std::map<ArchiveCacheKey, std::unique_ptr<ObjectFile>>
+      ObjectForArchivePathAndArch;
   
   Options Opts;
 
diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
index 6dddc3a709239..74990347d4b5d 100644
--- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -21,6 +21,7 @@
 #include "llvm/DebugInfo/PDB/PDBContext.h"
 #include "llvm/DebugInfo/Symbolize/SymbolizableObjectFile.h"
 #include "llvm/Demangle/Demangle.h"
+#include "llvm/Object/Archive.h"
 #include "llvm/Object/BuildID.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Object/ELFObjectFile.h"
@@ -33,7 +34,6 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
-#include "llvm/Object/Archive.h"
 #include <cassert>
 #include <cstring>
 
@@ -323,7 +323,7 @@ bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
 
 bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName,
                              uint32_t &CRCHash) {
-  if (!Obj || !isa<ObjectFile>(Obj))
+  if (!Obj)
     return false;
   for (const SectionRef &Section : Obj->sections()) {
     StringRef Name;
@@ -564,16 +564,14 @@ LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path,
   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);
-    });
+    BinIter->second.pushEvictor(
+        [this, I = Pair.first]() { ObjectPairForPathArch.erase(I); });
   }
   return Res;
 }
 
-Expected<ObjectFile *> LLVMSymbolizer::getOrCreateObjectFromArchive(StringRef ArchivePath, 
-                                                                    StringRef MemberName, 
-                                                                    const std::string &ArchName) {
+Expected<ObjectFile *> LLVMSymbolizer::getOrCreateObjectFromArchive(
+    StringRef ArchivePath, StringRef MemberName, StringRef ArchName) {
   Binary *Bin = nullptr;
   auto Pair = BinaryForPath.emplace(ArchivePath.str(), OwningBinary<Binary>());
   if (!Pair.second) {
@@ -581,9 +579,8 @@ Expected<ObjectFile *> LLVMSymbolizer::getOrCreateObjectFromArchive(StringRef Ar
     recordAccess(Pair.first->second);
   } else {
     Expected<OwningBinary<Binary>> ArchiveOrErr = createBinary(ArchivePath);
-    if (!ArchiveOrErr) {
+    if (!ArchiveOrErr)
       return ArchiveOrErr.takeError();
-    }
 
     CachedBinary &CachedBin = Pair.first->second;
     CachedBin = std::move(ArchiveOrErr.get());
@@ -593,26 +590,28 @@ Expected<ObjectFile *> LLVMSymbolizer::getOrCreateObjectFromArchive(StringRef Ar
     Bin = CachedBin->getBinary();
   }
 
-  if (!Bin || !isa<object::Archive>(Bin))
+  object::Archive *Archive = dyn_cast_if_present<object::Archive>(Bin);
+  if (!Archive)
     return errorCodeToError(object_error::invalid_file_type);
 
-  object::Archive *Archive = cast<object::Archive>(Bin);
   Error Err = Error::success();
   
-  // On AIX, archives can contain multiple members with same name but different types
-  // We need to check all matches and find one that matches both name and architecture
+  // On AIX, archives can contain multiple members with 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 == llvm::sys::path::filename(MemberName)) {
-      Expected<std::unique_ptr<object::Binary>> MemberOrErr = Child.getAsBinary();
+      continue;
+    if (*NameOrErr == sys::path::filename(MemberName)) {
+      Expected<std::unique_ptr<object::Binary>> MemberOrErr =
+          Child.getAsBinary();
       if (!MemberOrErr)
-        continue; 
+        continue;
       
       std::unique_ptr<object::Binary> Binary = std::move(*MemberOrErr);
       if (auto *Obj = dyn_cast<object::ObjectFile>(Binary.get())) {
-#if defined(_AIX)
+#ifdef _AIX
         Triple::ArchType ObjArch = Obj->makeTriple().getArch();
         Triple RequestedTriple;
         RequestedTriple.setArch(Triple::getArchTypeForLLVMName(ArchName));
@@ -625,11 +624,13 @@ Expected<ObjectFile *> LLVMSymbolizer::getOrCreateObjectFromArchive(StringRef Ar
           return I->second.get();
 
         auto CachedObj = std::unique_ptr<ObjectFile>(Obj);
-        auto NewEntry = ObjectForArchivePathAndArch.emplace(
-            CacheKey, std::move(CachedObj));
+        auto NewEntry =
+            ObjectForArchivePathAndArch.emplace(CacheKey, std::move(CachedObj));
         Binary.release();
-        BinaryForPath.find(ArchivePath.str())->second.pushEvictor(
-            [this, Iter = NewEntry.first]() { ObjectForArchivePathAndArch.erase(Iter); });
+        BinaryForPath.find(ArchivePath.str())
+            ->second.pushEvictor([this, Iter = NewEntry.first]() {
+              ObjectForArchivePathAndArch.erase(Iter);
+            });
         return NewEntry.first->second.get();
       }
     }
@@ -642,13 +643,15 @@ Expected<ObjectFile *> LLVMSymbolizer::getOrCreateObjectFromArchive(StringRef Ar
 Expected<ObjectFile *>
 LLVMSymbolizer::getOrCreateObject(const std::string &Path,
                                   const std::string &ArchName) {
-  // First check for archive(member) format - more efficient to check closing paren first
+  // First check for archive(member) format - more efficient to check closing
+  // paren first.
   size_t CloseParen = Path.rfind(')');
   if (CloseParen != std::string::npos && CloseParen == Path.length() - 1) {
     size_t OpenParen = Path.rfind('(', CloseParen);
     if (OpenParen != std::string::npos) {
       StringRef ArchivePath = StringRef(Path).substr(0, OpenParen);
-      StringRef MemberName = StringRef(Path).substr(OpenParen + 1, CloseParen - OpenParen - 1);
+      StringRef MemberName =
+          StringRef(Path).substr(OpenParen + 1, CloseParen - OpenParen - 1);
       return getOrCreateObjectFromArchive(ArchivePath, MemberName, ArchName);
     }
   }
@@ -803,10 +806,8 @@ LLVMSymbolizer::getOrCreateModuleInfo(StringRef ModuleName) {
   if (ModuleOrErr) {
     auto I = Modules.find(ModuleName);
     auto BinIter = BinaryForPath.find(BinaryName);
-    if (BinIter != BinaryForPath.end()) 
-      BinIter->second.pushEvictor([this, I]() {
-      Modules.erase(I);
-    });
+    if (BinIter != BinaryForPath.end())
+      BinIter->second.pushEvictor([this, I]() { Modules.erase(I); });
   }
   return ModuleOrErr;
 }
diff --git a/llvm/test/DebugInfo/symbolize-big-archive-elf.test b/llvm/test/DebugInfo/symbolize-big-archive-elf.test
index 87442f633548d..f92e3140c5e70 100644
--- a/llvm/test/DebugInfo/symbolize-big-archive-elf.test
+++ b/llvm/test/DebugInfo/symbolize-big-archive-elf.test
@@ -1,5 +1,4 @@
 // Test archive member recognition by name (ELF format)
-// UNSUPPORTED: target={{.*}}-aix{{.*}}
 
 // Generate object files from YAML
 // RUN: yaml2obj -o %t-1.o %S/Inputs/big-archive-elf-1.yaml
@@ -9,14 +8,11 @@
 // RUN: rm -f %t.a
 // RUN: llvm-ar crv %t.a %t-1.o %t-2.o
 
-// Verify archive contents
-// RUN: llvm-ar tv %t.a | FileCheck %s --check-prefix=CHECK-ARCHIVE
-// CHECK-ARCHIVE: {{.*}}-1.o
-// CHECK-ARCHIVE: {{.*}}-2.o
-
 // Test symbolization by member name (using just base names)
-// RUN: llvm-symbolizer --default-arch=ppc64 --obj="%t.a(%t-1.o)" 0x0 | FileCheck %s --check-prefix=CHECK-1
-// RUN: llvm-symbolizer --default-arch=ppc64 --obj="%t.a(%t-2.o)" 0x0 | FileCheck %s --check-prefix=CHECK-2
+// RUN: MEMBER1=$(basename %t-1.o)
+// RUN: llvm-symbolizer --default-arch=ppc64 --obj="%t.a($MEMBER1)" 0x0 | FileCheck %s --check-prefix=CHECK-1
+// RUN: MEMBER2=$(basename %t-2.o)
+// RUN: llvm-symbolizer --default-arch=ppc64 --obj="%t.a($MEMBER2)" 0x0 | FileCheck %s --check-prefix=CHECK-2
 // CHECK-1: foo1
 // CHECK-2: foo2
 
diff --git a/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test b/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
index f034520638267..fdace7510d4e1 100644
--- a/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
+++ b/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
@@ -1,5 +1,4 @@
 // Test big archive recognition and error handling in llvm-symbolizer
-// REQUIRES: system-aix, target={{.*}}-aix{{.*}}
 
 // Generate object files
 // RUN: yaml2obj -o %t-32.o %S/Inputs/big-archive-32.yaml
@@ -7,21 +6,38 @@
 
 // Create archive with same-named members using different modes
 // RUN: rm -f %t.a
-// RUN: cp %t-32.o %t.o && llvm-ar -X32 crv %t.a %t.o
-// RUN: cp %t-64.o %t.o && llvm-ar -X64 qv %t.a %t.o
- 
+// RUN: cp %t-32.o %t.o
+// RUN: if [ "$(uname)" = "AIX" ]; then \
+          llvm-ar -X32 crv %t.a %t.o; \
+        else \
+          llvm-ar crv %t.a %t.o; \
+        fi
+// RUN: cp %t-64.o %t.o
+// RUN: if [ "$(uname)" = "AIX" ]; then \
+          llvm-ar -X64 rv %t.a %t.o; \
+        else \
+          llvm-ar qv %t.a %t.o; \
+        fi
+
+
 // Verify archive contains two members with same name
-// RUN: llvm-ar tv -X32_64 %t.a | FileCheck %s --check-prefix=CHECK-ARCHIVE
+// RUN: if [ "$(uname)" = "AIX" ]; then \
+          llvm-ar tv -X32_64 %t.a | FileCheck %s --check-prefix=CHECK-ARCHIVE; \
+        else \
+          llvm-ar tv %t.a | FileCheck %s --check-prefix=CHECK-ARCHIVE; \
+        fi
 // CHECK-ARCHIVE: {{.*}}symbolize-big-archive-xcoff.test.tmp.o{{$}}
 // CHECK-ARCHIVE: {{.*}}symbolize-big-archive-xcoff.test.tmp.o{{$}}
 
 // Test successful symbolization
-// RUN: llvm-symbolizer --default-arch=ppc --obj="%t.a(%t.o)" 0x0 | FileCheck %s --check-prefix=CHECK-32
-// RUN: llvm-symbolizer --default-arch=ppc64 --obj="%t.a(%t.o)" 0x0 | FileCheck %s --check-prefix=CHECK-64
+// RUN: MEMBER=$(basename %t.o)
+// RUN: llvm-symbolizer --default-arch=ppc --obj="%t.a($MEMBER)" 0x0 | FileCheck %s --check-prefix=CHECK-32
+// RUN: llvm-symbolizer --default-arch=ppc64 --obj="%t.a($MEMBER)" 0x0 | FileCheck %s --check-prefix=CHECK-64
+// RUN: llvm-symbolizer --obj="%t.a($MEMBER):ppc" 0x0 | FileCheck %s --check-prefix=CHECK-32
+// RUN: llvm-symbolizer --obj="%t.a($MEMBER):ppc64" 0x0 | FileCheck %s --check-prefix=CHECK-64
 // CHECK-32: foo
 // CHECK-64: foo
 
 // Test error cases
 // RUN: not llvm-symbolizer --obj="%t.a(nonexistent.o)" 0x1000 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
-
 // CHECK-ERROR: error: {{.*}}No object file for requested architecture

>From 647f98ebe074e45ca0c93b486d08c212bc7b549a Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Fri, 1 Aug 2025 12:28:52 +0530
Subject: [PATCH 6/9] review comments addressed

---
 .../llvm/DebugInfo/Symbolize/Symbolize.h      | 14 ++++----------
 .../DebugInfo/symbolize-big-archive-elf.test  |  6 ++++--
 .../symbolize-big-archive-xcoff.test          | 19 +++----------------
 3 files changed, 11 insertions(+), 28 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
index 99297cebd5c89..6cebd91ecbbd5 100644
--- a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
+++ b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
@@ -29,12 +29,6 @@
 #include <utility>
 #include <vector>
 
-#ifdef _AIX
-#define SYMBOLIZE_AIX 1
-#else
-#define SYMBOLIZE_AIX 0
-#endif
-
 namespace llvm {
 namespace object {
 class ELFObjectFileBase;
@@ -210,9 +204,9 @@ class LLVMSymbolizer {
 
   /// Return a pointer to object file at specified path, for a specified
   /// architecture that is present inside an archive file
-  Expected<ObjectFile *>
-  getOrCreateObjectFromArchive(StringRef ArchivePath, StringRef MemberName,
-                               StringRef ArchName);
+  Expected<ObjectFile *> getOrCreateObjectFromArchive(StringRef ArchivePath,
+                                                      StringRef MemberName,
+                                                      StringRef ArchName);
 
   /// Update the LRU cache order when a binary is accessed.
   void recordAccess(CachedBinary &Bin);
@@ -252,7 +246,7 @@ class LLVMSymbolizer {
 
   std::map<ArchiveCacheKey, std::unique_ptr<ObjectFile>>
       ObjectForArchivePathAndArch;
-  
+
   Options Opts;
 
   std::unique_ptr<BuildIDFetcher> BIDFetcher;
diff --git a/llvm/test/DebugInfo/symbolize-big-archive-elf.test b/llvm/test/DebugInfo/symbolize-big-archive-elf.test
index f92e3140c5e70..3290a0684c568 100644
--- a/llvm/test/DebugInfo/symbolize-big-archive-elf.test
+++ b/llvm/test/DebugInfo/symbolize-big-archive-elf.test
@@ -10,9 +10,11 @@
 
 // Test symbolization by member name (using just base names)
 // RUN: MEMBER1=$(basename %t-1.o)
-// RUN: llvm-symbolizer --default-arch=ppc64 --obj="%t.a($MEMBER1)" 0x0 | FileCheck %s --check-prefix=CHECK-1
+// RUN: llvm-symbolizer --default-arch=ppc64le --obj="%t.a($MEMBER1)" 0x0 | FileCheck %s --check-prefix=CHECK-1
+// RUN: llvm-symbolizer --obj="%t.a($MEMBER1):ppc64le" 0x0 | FileCheck %s --check-prefix=CHECK-1
 // RUN: MEMBER2=$(basename %t-2.o)
-// RUN: llvm-symbolizer --default-arch=ppc64 --obj="%t.a($MEMBER2)" 0x0 | FileCheck %s --check-prefix=CHECK-2
+// RUN: llvm-symbolizer --default-arch=ppc64le --obj="%t.a($MEMBER2)" 0x0 | FileCheck %s --check-prefix=CHECK-2
+// RUN: llvm-symbolizer --obj="%t.a($MEMBER2):ppc64le" 0x0 | FileCheck %s --check-prefix=CHECK-2
 // CHECK-1: foo1
 // CHECK-2: foo2
 
diff --git a/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test b/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
index fdace7510d4e1..522a20f531774 100644
--- a/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
+++ b/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
@@ -7,25 +7,12 @@
 // Create archive with same-named members using different modes
 // RUN: rm -f %t.a
 // RUN: cp %t-32.o %t.o
-// RUN: if [ "$(uname)" = "AIX" ]; then \
-          llvm-ar -X32 crv %t.a %t.o; \
-        else \
-          llvm-ar crv %t.a %t.o; \
-        fi
+// RUN: llvm-ar %if system-aix %{-X32%} crv %t.a %t.o
 // RUN: cp %t-64.o %t.o
-// RUN: if [ "$(uname)" = "AIX" ]; then \
-          llvm-ar -X64 rv %t.a %t.o; \
-        else \
-          llvm-ar qv %t.a %t.o; \
-        fi
-
+// RUN: llvm-ar %if system-aix %{-X64 rv%} %else %{qv%} %t.a %t.o
 
 // Verify archive contains two members with same name
-// RUN: if [ "$(uname)" = "AIX" ]; then \
-          llvm-ar tv -X32_64 %t.a | FileCheck %s --check-prefix=CHECK-ARCHIVE; \
-        else \
-          llvm-ar tv %t.a | FileCheck %s --check-prefix=CHECK-ARCHIVE; \
-        fi
+// RUN: llvm-ar tv %if system-aix %{-X32_64%} %t.a | FileCheck %s --check-prefix=CHECK-ARCHIVE
 // CHECK-ARCHIVE: {{.*}}symbolize-big-archive-xcoff.test.tmp.o{{$}}
 // CHECK-ARCHIVE: {{.*}}symbolize-big-archive-xcoff.test.tmp.o{{$}}
 

>From 629e7a503fca06551e64357dda7b2f12de15e219 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Fri, 1 Aug 2025 12:29:39 +0530
Subject: [PATCH 7/9] review comments addressed

---
 llvm/lib/DebugInfo/Symbolize/Symbolize.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
index 74990347d4b5d..94d76ace9434f 100644
--- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -595,9 +595,9 @@ Expected<ObjectFile *> LLVMSymbolizer::getOrCreateObjectFromArchive(
     return errorCodeToError(object_error::invalid_file_type);
 
   Error Err = Error::success();
-  
+
   // On AIX, archives can contain multiple members with same name but different
-  // types. We need to check all matches and find one that matches both name and 
+  // 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();
@@ -608,17 +608,15 @@ Expected<ObjectFile *> LLVMSymbolizer::getOrCreateObjectFromArchive(
           Child.getAsBinary();
       if (!MemberOrErr)
         continue;
-      
+
       std::unique_ptr<object::Binary> Binary = std::move(*MemberOrErr);
       if (auto *Obj = dyn_cast<object::ObjectFile>(Binary.get())) {
-#ifdef _AIX
         Triple::ArchType ObjArch = Obj->makeTriple().getArch();
         Triple RequestedTriple;
         RequestedTriple.setArch(Triple::getArchTypeForLLVMName(ArchName));
         if (ObjArch != RequestedTriple.getArch())
           continue;
-#endif
-        ArchiveCacheKey CacheKey{ArchivePath.str(), MemberName.str(), ArchName};
+        ArchiveCacheKey CacheKey{ArchivePath.str(), MemberName.str(), ArchName.str()};
         auto I = ObjectForArchivePathAndArch.find(CacheKey);
         if (I != ObjectForArchivePathAndArch.end())
           return I->second.get();

>From 9c14b3875132941c8d73c54f0fee1e1619144406 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Fri, 1 Aug 2025 12:47:45 +0530
Subject: [PATCH 8/9] format correction

---
 llvm/lib/DebugInfo/Symbolize/Symbolize.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
index 94d76ace9434f..a356edaa722ae 100644
--- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -616,7 +616,8 @@ Expected<ObjectFile *> LLVMSymbolizer::getOrCreateObjectFromArchive(
         RequestedTriple.setArch(Triple::getArchTypeForLLVMName(ArchName));
         if (ObjArch != RequestedTriple.getArch())
           continue;
-        ArchiveCacheKey CacheKey{ArchivePath.str(), MemberName.str(), ArchName.str()};
+        ArchiveCacheKey CacheKey{ArchivePath.str(), MemberName.str(),
+                                 ArchName.str()};
         auto I = ObjectForArchivePathAndArch.find(CacheKey);
         if (I != ObjectForArchivePathAndArch.end())
           return I->second.get();

>From f8aeb3e78a52c2b4c8f4c5face7df5173321c9c3 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Fri, 1 Aug 2025 16:31:36 +0530
Subject: [PATCH 9/9] added test support

---
 llvm/test/DebugInfo/symbolize-big-archive-elf.test   | 1 +
 llvm/test/DebugInfo/symbolize-big-archive-xcoff.test | 1 +
 2 files changed, 2 insertions(+)

diff --git a/llvm/test/DebugInfo/symbolize-big-archive-elf.test b/llvm/test/DebugInfo/symbolize-big-archive-elf.test
index 3290a0684c568..66c59b45c8a76 100644
--- a/llvm/test/DebugInfo/symbolize-big-archive-elf.test
+++ b/llvm/test/DebugInfo/symbolize-big-archive-elf.test
@@ -1,4 +1,5 @@
 // Test archive member recognition by name (ELF format)
+// REQUIRES: system-linux || system-aix
 
 // Generate object files from YAML
 // RUN: yaml2obj -o %t-1.o %S/Inputs/big-archive-elf-1.yaml
diff --git a/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test b/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
index 522a20f531774..e8f6a5f790ffc 100644
--- a/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
+++ b/llvm/test/DebugInfo/symbolize-big-archive-xcoff.test
@@ -1,4 +1,5 @@
 // Test big archive recognition and error handling in llvm-symbolizer
+// REQUIRES: system-linux || system-aix
 
 // Generate object files
 // RUN: yaml2obj -o %t-32.o %S/Inputs/big-archive-32.yaml



More information about the llvm-commits mailing list