diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h --- a/llvm/include/llvm/Object/Archive.h +++ b/llvm/include/llvm/Object/Archive.h @@ -378,10 +378,10 @@ uint64_t getArchiveMagicLen() const; void setFirstRegular(const Child &C); -private: StringRef SymbolTable; StringRef StringTable; +private: StringRef FirstRegularData; uint16_t FirstRegularStartOfFile = -1; diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp --- a/llvm/lib/Object/Archive.cpp +++ b/llvm/lib/Object/Archive.cpp @@ -952,14 +952,15 @@ Expected Archive::Symbol::getMember() const { const char *Buf = Parent->getSymbolTable().begin(); const char *Offsets = Buf; - if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64) + if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64 || + Parent->kind() == K_AIXBIG) Offsets += sizeof(uint64_t); else Offsets += sizeof(uint32_t); uint64_t Offset = 0; if (Parent->kind() == K_GNU) { Offset = read32be(Offsets + SymbolIndex * 4); - } else if (Parent->kind() == K_GNU64) { + } else if (Parent->kind() == K_GNU64 || Parent->kind() == K_AIXBIG) { Offset = read64be(Offsets + SymbolIndex * 8); } else if (Parent->kind() == K_BSD) { // The SymbolIndex is an index into the ranlib structs that start at @@ -1092,7 +1093,9 @@ // Skip the byte count of the string table. buf += sizeof(uint64_t); buf += ran_strx; - } else { + } else if (kind() == K_AIXBIG) + buf = getStringTable().begin(); + else { uint32_t member_count = 0; uint32_t symbol_count = 0; member_count = read32le(buf); @@ -1114,7 +1117,7 @@ const char *buf = getSymbolTable().begin(); if (kind() == K_GNU) return read32be(buf); - if (kind() == K_GNU64) + if (kind() == K_GNU64 || kind() == K_AIXBIG) return read64be(buf); if (kind() == K_BSD) return read32le(buf) / 8; @@ -1167,6 +1170,31 @@ Err = malformedError("malformed AIX big archive: last member offset \"" + RawOffset + "\" is not a number"); + // Calculate the global symbol table. + uint64_t GlobSymOffset = 0; + RawOffset = getFieldRawString(ArFixLenHdr->GlobSymOffset); + if (RawOffset.getAsInteger(10, GlobSymOffset)) + Err = malformedError( + "malformed AIX big archive: global symbol tables offset \"" + + RawOffset + "\" is not a number"); + if (GlobSymOffset > 0) { + const char *GlobSymTblLoc = Data.getBufferStart() + GlobSymOffset; + const BigArMemHdrType *GlobalSymHdr = + reinterpret_cast(GlobSymTblLoc); + RawOffset = getFieldRawString(GlobalSymHdr->Size); + uint64_t Size; + if (RawOffset.getAsInteger(10, Size)) + Err = malformedError( + "malformed AIX big archive: global symbol tables size \"" + + RawOffset + "\" is not a number"); + SymbolTable = StringRef(GlobSymTblLoc + sizeof(BigArMemHdrType), Size); + unsigned SymNum = getNumberOfSymbols(); + uint64_t SymbolTableStringSize = Size - 8 * (SymNum + 1); + StringTable = + StringRef(GlobSymTblLoc + sizeof(BigArMemHdrType) + 8 * (SymNum + 1), + SymbolTableStringSize); + } + child_iterator I = child_begin(Err, false); if (Err) return; diff --git a/llvm/test/tools/llvm-ar/delete.test b/llvm/test/tools/llvm-ar/delete.test --- a/llvm/test/tools/llvm-ar/delete.test +++ b/llvm/test/tools/llvm-ar/delete.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## Test the deletion of members and that symbols are removed from the symbol table. # RUN: yaml2obj %s -o %t-delete.o --docnum=1