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 @@ -391,6 +391,7 @@ }; class BigArchive : public Archive { +public: /// Fixed-Length Header. struct FixLenHdr { char Magic[sizeof(BigArchiveMagic) - 1]; ///< Big archive magic string. diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/SmallVectorMemoryBuffer.h" #include "llvm/Support/raw_ostream.h" @@ -127,16 +128,20 @@ Kind == object::Archive::K_DARWIN64; } +static bool isAIXBigArchive(object::Archive::Kind Kind) { + return Kind == object::Archive::K_AIXBIG; +} + static bool isBSDLike(object::Archive::Kind Kind) { switch (Kind) { case object::Archive::K_GNU: case object::Archive::K_GNU64: + case object::Archive::K_AIXBIG: return false; case object::Archive::K_BSD: case object::Archive::K_DARWIN: case object::Archive::K_DARWIN64: return true; - case object::Archive::K_AIXBIG: case object::Archive::K_COFF: break; } @@ -189,6 +194,31 @@ Out.write(uint8_t(0)); } +static void +printBigArchiveMemberHeader(raw_ostream &Out, StringRef Name, + const sys::TimePoint &ModTime, + unsigned UID, unsigned GID, unsigned Perms, + uint64_t Size, unsigned PrevOffset, + unsigned NextOffset) { + unsigned NameLen = Name.size(); + + printWithSpacePadding(Out, Size, 20); // File member size + printWithSpacePadding(Out, NextOffset, 20); // Next member header offset + printWithSpacePadding(Out, PrevOffset, 20); // Previous member header offset + printWithSpacePadding(Out, sys::toTimeT(ModTime), 12); // File member date + // The big archive format has 12 chars for uid and gid. + printWithSpacePadding(Out, UID % 1000000000000, 12); // UID + printWithSpacePadding(Out, GID % 1000000000000, 12); // GID + printWithSpacePadding(Out, format("%o", Perms), 12); // Permission + printWithSpacePadding(Out, NameLen, 4); // Name length + if (NameLen) { + printWithSpacePadding(Out, Name, NameLen); // Name + if (NameLen % 2) + Out.write(uint8_t(0)); // Null byte padding + } + Out << "`\n"; // Terminator +} + static bool useStringTable(bool Thin, StringRef Name) { return Thin || Name.size() >= 16 || Name.contains('/'); } @@ -199,8 +229,8 @@ case object::Archive::K_BSD: case object::Archive::K_DARWIN: case object::Archive::K_COFF: - case object::Archive::K_AIXBIG: return false; + case object::Archive::K_AIXBIG: case object::Archive::K_DARWIN64: case object::Archive::K_GNU64: return true; @@ -304,7 +334,11 @@ // least 4-byte aligned for 32-bit content. Opt for the larger encoding // uniformly. // We do this for all bsd formats because it simplifies aligning members. - uint32_t Pad = offsetToAlignment(Size, Align(isBSDLike(Kind) ? 8 : 2)); + // For the big archive format, the symbol table is the last member, so there + // is no need to align. + uint32_t Pad = isAIXBigArchive(Kind) + ? 0 + : offsetToAlignment(Size, Align(isBSDLike(Kind) ? 8 : 2)); Size += Pad; if (Padding) *Padding = Pad; @@ -312,11 +346,15 @@ } static void writeSymbolTableHeader(raw_ostream &Out, object::Archive::Kind Kind, - bool Deterministic, uint64_t Size) { + bool Deterministic, uint64_t Size, + uint64_t PrevMemberOffset = 0) { if (isBSDLike(Kind)) { const char *Name = is64BitKind(Kind) ? "__.SYMDEF_64" : "__.SYMDEF"; printBSDMemberHeader(Out, Out.tell(), Name, now(Deterministic), 0, 0, 0, Size); + } else if (isAIXBigArchive(Kind)) { + printBigArchiveMemberHeader(Out, "", now(Deterministic), 0, 0, + 0, Size, PrevMemberOffset, 0); } else { const char *Name = is64BitKind(Kind) ? "/SYM64" : ""; printGNUSmallMemberHeader(Out, Name, now(Deterministic), 0, 0, 0, Size); @@ -325,7 +363,8 @@ static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef Members, - StringRef StringTable) { + StringRef StringTable, + uint64_t PrevMemberOffset = 0) { // We don't write a symbol table on an archive with no members -- except on // Darwin, where the linker will abort unless the archive has a symbol table. if (StringTable.empty() && !isDarwin(Kind)) @@ -338,9 +377,10 @@ uint64_t OffsetSize = is64BitKind(Kind) ? 8 : 4; uint32_t Pad; uint64_t Size = computeSymbolTableSize(Kind, NumSyms, OffsetSize, StringTable, &Pad); - writeSymbolTableHeader(Out, Kind, Deterministic, Size); + writeSymbolTableHeader(Out, Kind, Deterministic, Size, PrevMemberOffset); - uint64_t Pos = Out.tell() + Size; + uint64_t Pos = isAIXBigArchive(Kind) ? sizeof(object::BigArchive::FixLenHdr) + : Out.tell() + Size; if (isBSDLike(Kind)) printNBits(Out, Kind, NumSyms * 2 * OffsetSize); @@ -409,9 +449,8 @@ bool NeedSymbols, ArrayRef NewMembers) { static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'}; - // This ignores the symbol table, but we only need the value mod 8 and the - // symbol table is aligned to be a multiple of 8 bytes - uint64_t Pos = 0; + uint64_t Pos = + isAIXBigArchive(Kind) ? sizeof(object::BigArchive::FixLenHdr) : 0; std::vector Ret; bool HasObject = false; @@ -471,6 +510,9 @@ Entry.second = Entry.second > 1 ? 1 : 0; } + // The big archive format needs to know the offset of the previous member + // header. + unsigned PrevOffset = 0; for (const NewArchiveMember &M : NewMembers) { std::string Header; raw_string_ostream Out(Header); @@ -503,8 +545,16 @@ std::move(StringMsg), object::object_error::parse_failed); } - printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M, - ModTime, Size); + if (isAIXBigArchive(Kind)) { + unsigned NextOffset = Pos + sizeof(object::BigArMemHdrType) + + alignTo(M.MemberName.size(), 2) + alignTo(Size, 2); + printBigArchiveMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID, + M.Perms, Size, PrevOffset, NextOffset); + PrevOffset = Pos; + } else { + printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M, + ModTime, Size); + } Out.flush(); std::vector Symbols; @@ -588,22 +638,25 @@ return E; std::vector &Data = *DataOrErr; - if (!StringTableBuf.empty()) + if (!StringTableBuf.empty() && !isAIXBigArchive(Kind)) Data.insert(Data.begin(), computeStringTable(StringTableBuf)); // We would like to detect if we need to switch to a 64-bit symbol table. - if (WriteSymtab) { - uint64_t MaxOffset = 8; // For the file signature. - uint64_t LastOffset = MaxOffset; - uint64_t NumSyms = 0; - for (const auto &M : Data) { - // Record the start of the member's offset - LastOffset = MaxOffset; - // Account for the size of each part associated with the member. - MaxOffset += M.Header.size() + M.Data.size() + M.Padding.size(); - NumSyms += M.Symbols.size(); - } + uint64_t LastMemberEndOffset = + isAIXBigArchive(Kind) ? sizeof(object::BigArchive::FixLenHdr) : 8; + uint64_t LastMemberHeaderOffset = LastMemberEndOffset; + uint64_t NumSyms = 0; + for (const auto &M : Data) { + // Record the start of the member's offset + LastMemberHeaderOffset = LastMemberEndOffset; + // Account for the size of each part associated with the member. + LastMemberEndOffset += M.Header.size() + M.Data.size() + M.Padding.size(); + NumSyms += M.Symbols.size(); + } + // The symbol table is put at the end of the big archive file. The symbol + // table is at the start of the archive file for other archive formats. + if (WriteSymtab && !isAIXBigArchive(Kind)) { // We assume 32-bit offsets to see if 32-bit symbols are possible or not. uint64_t SymtabSize = computeSymbolTableSize(Kind, NumSyms, 4, SymNamesBuf); auto computeSymbolTableHeaderSize = @@ -613,7 +666,7 @@ writeSymbolTableHeader(Tmp, Kind, Deterministic, SymtabSize); return TmpBuf.size(); }; - LastOffset += computeSymbolTableHeaderSize() + SymtabSize; + LastMemberHeaderOffset += computeSymbolTableHeaderSize() + SymtabSize; // The SYM64 format is used when an archive's member offsets are larger than // 32-bits can hold. The need for this shift in format is detected by @@ -627,10 +680,10 @@ if (Sym64Env) StringRef(Sym64Env).getAsInteger(10, Sym64Threshold); - // If LastOffset isn't going to fit in a 32-bit varible we need to switch - // to 64-bit. Note that the file can be larger than 4GB as long as the last - // member starts before the 4GB offset. - if (LastOffset >= Sym64Threshold) { + // If LastMemberHeaderOffset isn't going to fit in a 32-bit varible we need + // to switch to 64-bit. Note that the file can be larger than 4GB as long as + // the last member starts before the 4GB offset. + if (LastMemberHeaderOffset >= Sym64Threshold) { if (Kind == object::Archive::K_DARWIN) Kind = object::Archive::K_DARWIN64; else @@ -640,15 +693,92 @@ if (Thin) Out << "!\n"; + else if (isAIXBigArchive(Kind)) + Out << "\n"; else Out << "!\n"; - if (WriteSymtab) - writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf); + if (!isAIXBigArchive(Kind)) { + if (WriteSymtab) + writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf); + for (const MemberData &M : Data) + Out << M.Header << M.Data << M.Padding; + } else { + // For the big archive (AIX) format, compute a table of member names and + // offsets, used in the member table. + uint64_t MemberTableNameStrTblSize = 0; + std::vector MemberOffsets; + std::vector MemberNames; + // Loop across object to find offset and names. + uint64_t MemberEndOffset = sizeof(object::BigArchive::FixLenHdr); + for (size_t I = 0, Size = NewMembers.size(); I != Size; ++I) { + const NewArchiveMember &Member = NewMembers[I]; + MemberTableNameStrTblSize += Member.MemberName.size() + 1; + MemberOffsets.push_back(MemberEndOffset); + MemberNames.push_back(Member.MemberName); + // File member name ended with "`\n". The length is included in + // BigArMemHdrType. + MemberEndOffset += sizeof(object::BigArMemHdrType) + + alignTo(Data[I].Data.size(), 2) + + alignTo(Member.MemberName.size(), 2); + } - for (const MemberData &M : Data) - Out << M.Header << M.Data << M.Padding; + // AIX member table size. + unsigned MemberTableSize = 20 + // Number of members field + 20 * MemberOffsets.size() + + MemberTableNameStrTblSize; + + unsigned GlobalSymbolOffset = + (WriteSymtab && NumSyms > 0) + ? LastMemberEndOffset + + alignTo(sizeof(object::BigArMemHdrType) + MemberTableSize, 2) + : 0; + + // Fixed Sized Header. + printWithSpacePadding(Out, NewMembers.size() ? LastMemberEndOffset : 0, + 20); // Offset to member table + // If there are no file members in the archive, there will be no global + // symbol table. + printWithSpacePadding(Out, NewMembers.size() ? GlobalSymbolOffset : 0, 20); + printWithSpacePadding( + Out, 0, + 20); // Offset to 64 bits global symbol table - Not supported yet + printWithSpacePadding( + Out, NewMembers.size() ? sizeof(object::BigArchive::FixLenHdr) : 0, + 20); // Offset to first archive member + printWithSpacePadding(Out, NewMembers.size() ? LastMemberHeaderOffset : 0, + 20); // Offset to last archive member + printWithSpacePadding( + Out, 0, + 20); // Offset to first member of free list - Not supported yet + + for (const MemberData &M : Data) { + Out << M.Header << M.Data; + if (M.Data.size() % 2) + Out << '\0'; + } + if (NewMembers.size()) { + // Member table. + printBigArchiveMemberHeader(Out, "", sys::toTimePoint(0), 0, 0, 0, + MemberTableSize, LastMemberHeaderOffset, + GlobalSymbolOffset); + printWithSpacePadding(Out, MemberOffsets.size(), 20); // Number of members + for (uint64_t MemberOffset : MemberOffsets) + printWithSpacePadding(Out, MemberOffset, + 20); // Offset to member file header. + for (StringRef MemberName : MemberNames) + Out << MemberName << '\0'; // Member file name, null byte padding. + + if (MemberTableNameStrTblSize % 2) + Out << '\0'; // Name table must be tail padded to an even number of + // bytes. + + if (WriteSymtab && NumSyms > 0) + writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf, + LastMemberEndOffset); + } + } Out.flush(); return Error::success(); } diff --git a/llvm/test/Object/ar-create.test b/llvm/test/Object/ar-create.test --- a/llvm/test/Object/ar-create.test +++ b/llvm/test/Object/ar-create.test @@ -1,4 +1,3 @@ -XFAIL: system-aix Test which operations create an archive and which don't. RUN: touch %t diff --git a/llvm/test/Object/archive-extract-dir.test b/llvm/test/Object/archive-extract-dir.test --- a/llvm/test/Object/archive-extract-dir.test +++ b/llvm/test/Object/archive-extract-dir.test @@ -1,5 +1,3 @@ -XFAIL: system-aix - RUN: mkdir -p %t RUN: cd %t RUN: rm -rf foo diff --git a/llvm/test/Object/archive-malformed-object.test b/llvm/test/Object/archive-malformed-object.test --- a/llvm/test/Object/archive-malformed-object.test +++ b/llvm/test/Object/archive-malformed-object.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## Show that the archive library emits error messages when adding malformed ## objects. diff --git a/llvm/test/Object/archive-replace-pos.test b/llvm/test/Object/archive-replace-pos.test --- a/llvm/test/Object/archive-replace-pos.test +++ b/llvm/test/Object/archive-replace-pos.test @@ -1,5 +1,3 @@ -XFAIL: system-aix - Test adding a member to a particular position RUN: touch %t.foo diff --git a/llvm/test/Object/archive-unknown-filetype.test b/llvm/test/Object/archive-unknown-filetype.test --- a/llvm/test/Object/archive-unknown-filetype.test +++ b/llvm/test/Object/archive-unknown-filetype.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## Show that the archive library does not emit an error or add any symbols to ## the archive symbol table, when it encounters an unknown file type, but still ## adds the file to the archive. diff --git a/llvm/test/Object/archive-update.test b/llvm/test/Object/archive-update.test --- a/llvm/test/Object/archive-update.test +++ b/llvm/test/Object/archive-update.test @@ -1,5 +1,3 @@ -XFAIL: system-aix - Test the 'u' option of llvm-ar RUN: rm -rf %t && mkdir -p %t && cd %t diff --git a/llvm/test/Object/directory.ll b/llvm/test/Object/directory.ll --- a/llvm/test/Object/directory.ll +++ b/llvm/test/Object/directory.ll @@ -1,5 +1,3 @@ -; XFAIL: system-aix - ;RUN: rm -rf %t && mkdir -p %t ;RUN: not llvm-ar r %t/test.a . 2>&1 | FileCheck -DMSG=%errc_EISDIR %s ;CHECK: .: [[MSG]] diff --git a/llvm/test/tools/llvm-ar/count.test b/llvm/test/tools/llvm-ar/count.test --- a/llvm/test/tools/llvm-ar/count.test +++ b/llvm/test/tools/llvm-ar/count.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix # Test the 'N' count parameter. # Get a temp clean cwd to extract into. diff --git a/llvm/test/tools/llvm-ar/create.test b/llvm/test/tools/llvm-ar/create.test --- a/llvm/test/tools/llvm-ar/create.test +++ b/llvm/test/tools/llvm-ar/create.test @@ -1,4 +1,3 @@ -XFAIL: system-aix ## Test the creation warning and supression of that warning. RUN: touch %t1.txt diff --git a/llvm/test/tools/llvm-ar/dash-before-letter.test b/llvm/test/tools/llvm-ar/dash-before-letter.test --- a/llvm/test/tools/llvm-ar/dash-before-letter.test +++ b/llvm/test/tools/llvm-ar/dash-before-letter.test @@ -1,4 +1,3 @@ -XFAIL: system-aix # Test the use of dash before key letters. RUN: touch %t1.txt diff --git a/llvm/test/tools/llvm-ar/default-xcoff.test b/llvm/test/tools/llvm-ar/default-xcoff.test --- a/llvm/test/tools/llvm-ar/default-xcoff.test +++ b/llvm/test/tools/llvm-ar/default-xcoff.test @@ -1,10 +1,7 @@ -; REQUIRES: system-aix -;; Test llvm-ar does not support Big AIX archive write operation. - +;; Test llvm-ar uses the big archive format for XCOFF object files by default. ; RUN: yaml2obj %S/Inputs/xcoff.yaml -o %t.obj ; RUN: rm -f %t.ar -; RUN: not llvm-ar cr %t.ar %t.obj 2>&1 | FileCheck %s -; RUN: echo "test big archive" > %t.txt -; RUN: not llvm-ar cr %t.ar %t.txt 2>&1 | FileCheck %s +; RUN: llvm-ar cr %t.ar %t.obj +; RUN: FileCheck %s --input-file=%t.ar -; CHECK: big archive writer operation on AIX not yet supported +; CHECK: bigaf diff --git a/llvm/test/tools/llvm-ar/display-empty.test b/llvm/test/tools/llvm-ar/display-empty.test --- a/llvm/test/tools/llvm-ar/display-empty.test +++ b/llvm/test/tools/llvm-ar/display-empty.test @@ -1,10 +1,9 @@ -# XFAIL: system-aix ## Test Display of empty archives. # RUN: rm -rf %t && mkdir -p %t ## Display empty archive: -# RUN: llvm-ar cr %t/empty.a +# RUN: llvm-ar cr --format=gnu %t/empty.a # RUN: llvm-ar tv %t/empty.a 2>&1 | count 0 ## Display empty thin archive: diff --git a/llvm/test/tools/llvm-ar/double-hyphen.test b/llvm/test/tools/llvm-ar/double-hyphen.test --- a/llvm/test/tools/llvm-ar/double-hyphen.test +++ b/llvm/test/tools/llvm-ar/double-hyphen.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## Test the use of "--" on the commandline # RUN: echo contents > %t.txt diff --git a/llvm/test/tools/llvm-ar/error-opening-permission.test b/llvm/test/tools/llvm-ar/error-opening-permission.test --- a/llvm/test/tools/llvm-ar/error-opening-permission.test +++ b/llvm/test/tools/llvm-ar/error-opening-permission.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## Unsupported on windows as marking files "unreadable" ## is non-trivial on windows. # UNSUPPORTED: system-windows diff --git a/llvm/test/tools/llvm-ar/extract.test b/llvm/test/tools/llvm-ar/extract.test --- a/llvm/test/tools/llvm-ar/extract.test +++ b/llvm/test/tools/llvm-ar/extract.test @@ -1,10 +1,10 @@ ## Test extract operation. -# XFAIL: system-darwin,system-aix +# XFAIL: system-darwin # RUN: rm -rf %t && mkdir -p %t/extracted/ ## Extracting from an empty archive should not warn or error: -# RUN: llvm-ar cr %t/empty.a +# RUN: llvm-ar cr --format=gnu %t/empty.a # RUN: llvm-ar xv %t/empty.a 2>&1 | count 0 # RUN: echo filea > %t/a.txt diff --git a/llvm/test/tools/llvm-ar/flatten-thin-archive.test b/llvm/test/tools/llvm-ar/flatten-thin-archive.test --- a/llvm/test/tools/llvm-ar/flatten-thin-archive.test +++ b/llvm/test/tools/llvm-ar/flatten-thin-archive.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## This test creates a thin archive that contains a thin archive, a regular ## archive, and a file. ## diff --git a/llvm/test/tools/llvm-ar/full-path-option.test b/llvm/test/tools/llvm-ar/full-path-option.test --- a/llvm/test/tools/llvm-ar/full-path-option.test +++ b/llvm/test/tools/llvm-ar/full-path-option.test @@ -1,4 +1,3 @@ -XFAIL: system-aix # Note: many of these tests depend on relative paths, so we have to cd to a # test directory first. RUN: mkdir -p %t && cd %t @@ -28,7 +27,7 @@ # Deleting will fail with P because the members exist as foo.txt, not a/foo.txt. RUN: rm -f del1.a -RUN: llvm-ar rcS del1.a foo.txt +RUN: llvm-ar rcS --format=gnu del1.a foo.txt RUN: llvm-ar dP del1.a a/foo.txt RUN: llvm-ar t del1.a a/foo.txt | FileCheck %s --check-prefix=DISPLAY-FOUND --match-full-lines RUN: llvm-ar d del1.a a/foo.txt diff --git a/llvm/test/tools/llvm-ar/insert-after.test b/llvm/test/tools/llvm-ar/insert-after.test --- a/llvm/test/tools/llvm-ar/insert-after.test +++ b/llvm/test/tools/llvm-ar/insert-after.test @@ -1,4 +1,3 @@ -XFAIL: system-aix ## Test inserting files after a file. RUN: touch %t1.txt diff --git a/llvm/test/tools/llvm-ar/insert-before.test b/llvm/test/tools/llvm-ar/insert-before.test --- a/llvm/test/tools/llvm-ar/insert-before.test +++ b/llvm/test/tools/llvm-ar/insert-before.test @@ -1,4 +1,3 @@ -XFAIL: system-aix ## Test inserting files before a file. RUN: touch %t1.txt diff --git a/llvm/test/tools/llvm-ar/move-after.test b/llvm/test/tools/llvm-ar/move-after.test --- a/llvm/test/tools/llvm-ar/move-after.test +++ b/llvm/test/tools/llvm-ar/move-after.test @@ -1,4 +1,3 @@ -XFAIL: system-aix ## Test moving files after a file. RUN: touch %t1.txt diff --git a/llvm/test/tools/llvm-ar/move-before.test b/llvm/test/tools/llvm-ar/move-before.test --- a/llvm/test/tools/llvm-ar/move-before.test +++ b/llvm/test/tools/llvm-ar/move-before.test @@ -1,4 +1,3 @@ -XFAIL: system-aix ## Test moving files after a file. RUN: touch %t1.txt diff --git a/llvm/test/tools/llvm-ar/mri-delete.test b/llvm/test/tools/llvm-ar/mri-delete.test --- a/llvm/test/tools/llvm-ar/mri-delete.test +++ b/llvm/test/tools/llvm-ar/mri-delete.test @@ -1,4 +1,3 @@ -XFAIL: system-aix RUN: yaml2obj %S/Inputs/elf.yaml -o %t.o RUN: rm -f %t.ar diff --git a/llvm/test/tools/llvm-ar/mri-nonascii.test b/llvm/test/tools/llvm-ar/mri-nonascii.test --- a/llvm/test/tools/llvm-ar/mri-nonascii.test +++ b/llvm/test/tools/llvm-ar/mri-nonascii.test @@ -1,4 +1,3 @@ -XFAIL: system-aix # Test non-ascii archive members RUN: rm -rf %t && mkdir -p %t/extracted diff --git a/llvm/test/tools/llvm-ar/non-windows-name-case.test b/llvm/test/tools/llvm-ar/non-windows-name-case.test --- a/llvm/test/tools/llvm-ar/non-windows-name-case.test +++ b/llvm/test/tools/llvm-ar/non-windows-name-case.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## Test that on windows, members are case insensitive. # UNSUPPORTED: system-windows diff --git a/llvm/test/tools/llvm-ar/plugin.test b/llvm/test/tools/llvm-ar/plugin.test --- a/llvm/test/tools/llvm-ar/plugin.test +++ b/llvm/test/tools/llvm-ar/plugin.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## Test that --plugin is ignored. # RUN: rm -f %t.a diff --git a/llvm/test/tools/llvm-ar/print.test b/llvm/test/tools/llvm-ar/print.test --- a/llvm/test/tools/llvm-ar/print.test +++ b/llvm/test/tools/llvm-ar/print.test @@ -1,5 +1,5 @@ ## Test Print output -# XFAIL: system-darwin,system-aix +# XFAIL: system-darwin # RUN: rm -rf %t && mkdir -p %t # RUN: echo file1 > %t/1.txt @@ -9,7 +9,7 @@ # RUN: llvm-ar -rc %t/archive.a %t/1.txt %t/2.txt %t/3.txt ## Print empty archive: -# RUN: llvm-ar cr %t/empty.a +# RUN: llvm-ar --format=gnu cr %t/empty.a # RUN: llvm-ar p %t/empty.a 2>&1 | count 0 # RUN: llvm-ar pv %t/empty.a 2>&1 | count 0 diff --git a/llvm/test/tools/llvm-ar/read-only-archive.test b/llvm/test/tools/llvm-ar/read-only-archive.test --- a/llvm/test/tools/llvm-ar/read-only-archive.test +++ b/llvm/test/tools/llvm-ar/read-only-archive.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## Test that read-only archives cannot be edited # RUN: rm -rf %t && mkdir -p %t diff --git a/llvm/test/tools/llvm-ar/response-utf8.test b/llvm/test/tools/llvm-ar/response-utf8.test --- a/llvm/test/tools/llvm-ar/response-utf8.test +++ b/llvm/test/tools/llvm-ar/response-utf8.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## Check that response files can cope with non-ascii characters. # RUN: echo 'contents' > %t-£.txt diff --git a/llvm/test/tools/llvm-ar/response.test b/llvm/test/tools/llvm-ar/response.test --- a/llvm/test/tools/llvm-ar/response.test +++ b/llvm/test/tools/llvm-ar/response.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## llvm-ar should be able to consume response files. # RUN: echo 'contents' > %t.txt diff --git a/llvm/test/tools/llvm-libtool-darwin/archive-flattening.test b/llvm/test/tools/llvm-libtool-darwin/archive-flattening.test --- a/llvm/test/tools/llvm-libtool-darwin/archive-flattening.test +++ b/llvm/test/tools/llvm-libtool-darwin/archive-flattening.test @@ -1,4 +1,3 @@ -# XFAIL: system-aix ## This test checks that an archive is flattened correctly. # RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o diff --git a/llvm/test/tools/llvm-link/archive.ll b/llvm/test/tools/llvm-link/archive.ll --- a/llvm/test/tools/llvm-link/archive.ll +++ b/llvm/test/tools/llvm-link/archive.ll @@ -1,7 +1,7 @@ # RUN: llvm-as %S/Inputs/f.ll -o %t.f.bc # RUN: llvm-as %S/Inputs/g.ll -o %t.g.bc -# RUN: llvm-ar cr --format=gnu %t.fg.a %t.f.bc %t.g.bc -# RUN: llvm-ar cr --format=gnu %t.empty.lib +# RUN: llvm-ar cr %t.fg.a %t.f.bc %t.g.bc +# RUN: llvm-ar cr --format=gnu %t.empty.lib # RUN: llvm-link %S/Inputs/h.ll %t.fg.a %t.empty.lib -o %t.linked.bc # RUN: llvm-nm %t.linked.bc | FileCheck %s diff --git a/llvm/test/tools/llvm-link/archivell.ll b/llvm/test/tools/llvm-link/archivell.ll --- a/llvm/test/tools/llvm-link/archivell.ll +++ b/llvm/test/tools/llvm-link/archivell.ll @@ -1,4 +1,5 @@ -# RUN: llvm-ar --format=gnu cr %t.fg.a %S/Inputs/f.ll %S/Inputs/g.ll +# XFAIL: system-aix +# RUN: llvm-ar cr %t.fg.a %S/Inputs/f.ll %S/Inputs/g.ll # RUN: not llvm-link %S/Inputs/h.ll %t.fg.a -o %t.linked.bc 2>&1 | FileCheck %s # RUN: rm -f %t.fg.a diff --git a/llvm/test/tools/llvm-lipo/create-archive-input.test b/llvm/test/tools/llvm-lipo/create-archive-input.test --- a/llvm/test/tools/llvm-lipo/create-archive-input.test +++ b/llvm/test/tools/llvm-lipo/create-archive-input.test @@ -4,16 +4,16 @@ # RUN: llvm-as %p/Inputs/armv7-ios.ll -o %t-ir-armv7.o # RUN: llvm-as %p/Inputs/x64-osx.ll -o %t-ir-x86_64.o -# RUN: llvm-ar --format=gnu cr %t.empty.a +# RUN: llvm-ar cr --format=gnu %t.empty.a # RUN: not llvm-lipo %t.empty.a -create -output /dev/null 2>&1 | FileCheck --check-prefix=EMPTY-ARCHIVE %s -# RUN: llvm-ar --format=gnu cr %t.different_architectures.a %t-i386.o %t-x86_64.o +# RUN: llvm-ar cr %t.different_architectures.a %t-i386.o %t-x86_64.o # RUN: not llvm-lipo %t.different_architectures.a -create -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-DIFFERENT-ARCHS %s -# RUN: llvm-ar --format=gnu cr %t.contains_fat_binary.a %t-universal.o +# RUN: llvm-ar cr %t.contains_fat_binary.a %t-universal.o # RUN: not llvm-lipo %t.contains_fat_binary.a -create -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-FAT-BINARY %s -# RUN: llvm-ar --format=gnu cr %t-i386-lib.a %t-i386.o +# RUN: llvm-ar cr %t-i386-lib.a %t-i386.o # RUN: llvm-lipo %t-i386-lib.a %t-x86_64.o -create -output %t-i386-x86_64-universal.o # RUN: llvm-lipo %t-i386-x86_64-universal.o -info | FileCheck --check-prefix=INFO-i386-x86_64 %s # RUN: llvm-lipo %t-i386-x86_64-universal.o -thin i386 -output %t-extracted-i386-lib.a @@ -21,18 +21,18 @@ # RUN: llvm-lipo %t-i386-x86_64-universal.o -thin x86_64 -output %t-extracted-x86_64.o # RUN: cmp %t-extracted-x86_64.o %t-x86_64.o -# RUN: llvm-ar --format=gnu cr %t-ir-armv7-lib.a %t-ir-armv7.o +# RUN: llvm-ar cr %t-ir-armv7-lib.a %t-ir-armv7.o # RUN: llvm-lipo %t-ir-armv7-lib.a %t-ir-x86_64.o -create -output %t-ir-armv7-x86_64-universal.o # RUN: llvm-lipo %t-ir-armv7-x86_64-universal.o -thin armv7 -output %t-ir-extracted-armv7-lib.a # RUN: cmp %t-ir-extracted-armv7-lib.a %t-ir-armv7-lib.a # RUN: llvm-lipo %t-ir-armv7-x86_64-universal.o -thin x86_64 -output %t-ir-extracted-x86_64.o # RUN: cmp %t-ir-extracted-x86_64.o %t-ir-x86_64.o -# RUN: llvm-ar --format=gnu cr %t.different_types0.a %t-i386.o %t-ir-x86_64.o +# RUN: llvm-ar cr %t.different_types0.a %t-i386.o %t-ir-x86_64.o # RUN: not llvm-lipo -create %t.different_types0.a -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-MACHO-AND-IR %s -# RUN: llvm-ar --format=gnu cr %t.different_types1.a %t-ir-x86_64.o %t-i386.o +# RUN: llvm-ar cr %t.different_types1.a %t-ir-x86_64.o %t-i386.o # RUN: not llvm-lipo -create %t.different_types1.a -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-IR-AND-MACHO %s -# RUN: llvm-ar --format=gnu cr %t.different_architectures_ir.a %t-ir-x86_64.o %t-ir-armv7.o +# RUN: llvm-ar cr %t.different_architectures_ir.a %t-ir-x86_64.o %t-ir-armv7.o # RUN: not llvm-lipo -create %t.different_architectures_ir.a -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-DIFFERENT-ARCHS %s # EMPTY-ARCHIVE: empty archive diff --git a/llvm/test/tools/llvm-nm/option-X.test b/llvm/test/tools/llvm-nm/option-X.test --- a/llvm/test/tools/llvm-nm/option-X.test +++ b/llvm/test/tools/llvm-nm/option-X.test @@ -56,7 +56,7 @@ # RUN: yaml2obj --docnum=2 -DFLAG=0x1DF %s -o %t_xcoff32.o # RUN: yaml2obj --docnum=2 -DFLAG=0x1F7 %s -o %t_xcoff64.o # RUN: rm -f %t.a -# RUN: llvm-ar --format=gnu -q -c %t.a %t_xcoff32.o %t_xcoff64.o +# RUN: llvm-ar -q -c %t.a %t_xcoff32.o %t_xcoff64.o # RUN: llvm-nm --format=just-symbols -X32 %t_xcoff32.o | \ # RUN: FileCheck --check-prefixes=XCOFF32 %s --implicit-check-not={{.}} diff --git a/llvm/test/tools/llvm-objcopy/MachO/universal-object.test b/llvm/test/tools/llvm-objcopy/MachO/universal-object.test --- a/llvm/test/tools/llvm-objcopy/MachO/universal-object.test +++ b/llvm/test/tools/llvm-objcopy/MachO/universal-object.test @@ -14,7 +14,7 @@ ## Case 2: copy a universal object file containing an archive. # RUN: rm -f %t.archive.i386 -# RUN: llvm-ar --format=gnu cr %t.archive.i386 %t.i386 +# RUN: llvm-ar cr %t.archive.i386 %t.i386 # RUN: llvm-lipo %t.archive.i386 %t.x86_64 -create -output %t.universal.containing.archive # RUN: llvm-objcopy %t.universal.containing.archive %t.universal.containing.archive.copy # RUN: llvm-lipo %t.universal.containing.archive.copy -archs | FileCheck --check-prefix=VERIFY_ARCHS %s @@ -24,7 +24,7 @@ # RUN: cmp %t.x86_64 %t.archive.x86_64.copy ## Case 3: copy an archive containing a universal object. -# RUN: llvm-ar --format=gnu cr %t.archive.containing.universal %t.universal +# RUN: llvm-ar cr %t.archive.containing.universal %t.universal # RUN: llvm-objcopy %t.archive.containing.universal %t.archive.containing.universal.copy ## Case 4: try to copy a universal object file contaning a bitcode slice. @@ -34,7 +34,7 @@ # RUN: | FileCheck --check-prefix=UNSUPPORTED_UNIVERSAL_OBJECT %s ## Case 5: try to copy an archive containing an unsupported universal object. -# RUN: llvm-ar --format=gnu cr %t.archive.universal.bitcode %t.universal.containing.bitcode +# RUN: llvm-ar cr %t.archive.universal.bitcode %t.universal.containing.bitcode # RUN: not llvm-objcopy %t.archive.universal.bitcode %t.archive.universal.bitcode.copy 2>&1 \ # RUN: | FileCheck --check-prefix=UNSUPPORTED_UNIVERSAL_OBJECT %s diff --git a/llvm/test/tools/llvm-readobj/basic.test b/llvm/test/tools/llvm-readobj/basic.test --- a/llvm/test/tools/llvm-readobj/basic.test +++ b/llvm/test/tools/llvm-readobj/basic.test @@ -16,7 +16,7 @@ # Test that unrecognised files in archives are ignored. RUN: rm -f %t.a -RUN: llvm-ar --format=gnu rc %t.a %t.empty +RUN: llvm-ar rc %t.a %t.empty RUN: llvm-readobj --all %t.a 2>&1 | FileCheck --check-prefix=NO-OUTPUT --allow-empty %s NO-OUTPUT-NOT: {{.}} diff --git a/llvm/test/tools/llvm-size/archive.test b/llvm/test/tools/llvm-size/archive.test --- a/llvm/test/tools/llvm-size/archive.test +++ b/llvm/test/tools/llvm-size/archive.test @@ -5,21 +5,21 @@ ## Case 1: Empty archive. No output expected. # RUN: rm -f %t1.a -# RUN: llvm-ar --format=gnu rc %t1.a +# RUN: llvm-ar rc --format=gnu %t1.a # RUN: llvm-size -B %t1.a | count 0 # RUN: llvm-size -A %t1.a | count 0 ## Case 2: Single member. # RUN: rm -f %t2.a -# RUN: llvm-ar --format=gnu rc %t2.a %t1 +# RUN: llvm-ar rc %t2.a %t1 # RUN: llvm-size -B %t2.a | FileCheck %s -DARCHIVE=%t2.a --check-prefix=BERKELEY-1 # RUN: llvm-size -A %t2.a | FileCheck %s -DARCHIVE=%t2.a --check-prefix=SYSV-1 ## Case 3: Multiple members. # RUN: rm -f %t3.a -# RUN: llvm-ar --format=gnu rc %t3.a %t1 %t2 +# RUN: llvm-ar rc %t3.a %t1 %t2 # RUN: llvm-size -B %t3.a | FileCheck %s -DARCHIVE=%t3.a --check-prefixes=BERKELEY-1,BERKELEY-2 # RUN: llvm-size -A %t3.a | FileCheck %s -DARCHIVE=%t3.a --check-prefixes=SYSV-1,SYSV-2 diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -82,6 +82,7 @@ =gnu - gnu =darwin - darwin =bsd - bsd + =aix - aix (big archive) --plugin= - ignored for compatibility -h --help - display this help and exit --rsp-quoting - quoting style for response files @@ -187,7 +188,7 @@ static bool MRI; namespace { -enum Format { Default, GNU, BSD, DARWIN, Unknown }; +enum Format { Default, GNU, BSD, DARWIN, BIGARCHIVE, Unknown }; } static Format FormatType = Default; @@ -950,8 +951,6 @@ else Kind = !NewMembers.empty() ? getKindFromMember(NewMembers.front()) : getDefaultForHost(); - if (Kind == object::Archive::K_AIXBIG) - fail("big archive writer operation on AIX not yet supported"); break; case GNU: Kind = object::Archive::K_GNU; @@ -966,6 +965,11 @@ fail("only the gnu format has a thin mode"); Kind = object::Archive::K_DARWIN; break; + case BIGARCHIVE: + if (Thin) + fail("only the gnu format has a thin mode"); + Kind = object::Archive::K_AIXBIG; + break; case Unknown: llvm_unreachable(""); } @@ -1237,6 +1241,7 @@ .Case("gnu", GNU) .Case("darwin", DARWIN) .Case("bsd", BSD) + .Case("bigarchive", BIGARCHIVE) .Default(Unknown); if (FormatType == Unknown) fail(std::string("Invalid format ") + Match);