diff --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp --- a/clang/lib/Driver/OffloadBundler.cpp +++ b/clang/lib/Driver/OffloadBundler.cpp @@ -1265,8 +1265,9 @@ OutputArchivesMap.find(Target); if (CurArchiveMembers != OutputArchivesMap.end()) { if (Error WriteErr = writeArchive(FileName, CurArchiveMembers->getValue(), - true, getDefaultArchiveKindForHost(), - true, false, nullptr)) + SymtabWritingMode::NormalSymtab, + getDefaultArchiveKindForHost(), true, + false, nullptr)) return WriteErr; } else if (!BundlerConfig.AllowMissingBundles) { std::string ErrMsg = @@ -1280,9 +1281,9 @@ // the missing input file. std::vector EmptyArchive; EmptyArchive.clear(); - if (Error WriteErr = writeArchive(FileName, EmptyArchive, true, - getDefaultArchiveKindForHost(), true, - false, nullptr)) + if (Error WriteErr = writeArchive( + FileName, EmptyArchive, SymtabWritingMode::NormalSymtab, + getDefaultArchiveKindForHost(), true, false, nullptr)) return WriteErr; } } diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -380,16 +380,15 @@ elif platform.system() == "AIX": config.environment["AIXTHREAD_STK"] = "4194304" -# The llvm-nm tool supports an environment variable "OBJECT_MODE" on AIX OS, which +# Some tools support an environment variable "OBJECT_MODE" on AIX OS, which # controls the kind of objects they will support. If there is no "OBJECT_MODE" # environment variable specified, the default behaviour is to support 32-bit # objects only. In order to not affect most test cases, which expect to support # 32-bit and 64-bit objects by default, set the environment variable -# "OBJECT_MODE" to 'any' for llvm-nm on AIX OS. +# "OBJECT_MODE" to "any" by default on AIX OS. if "system-aix" in config.available_features: - config.substitutions.append(("llvm-nm", "env OBJECT_MODE=any llvm-nm")) - config.substitutions.append(("llvm-ar", "env OBJECT_MODE=any llvm-ar")) + config.environment["OBJECT_MODE"] = "any" # It is not realistically possible to account for all options that could # possibly be present in system and user configuration files, so disable diff --git a/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp b/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp --- a/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp +++ b/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp @@ -192,9 +192,9 @@ Binary->getImage(), Binary->getMemoryBufferRef().getBufferIdentifier())); - if (Error E = writeArchive(Args["file"], Members, true, - Archive::getDefaultKindForHost(), true, false, - nullptr)) + if (Error E = writeArchive( + Args["file"], Members, SymtabWritingMode::NormalSymtab, + Archive::getDefaultKindForHost(), true, false, nullptr)) return E; } else if (Args.count("file")) { if (Extracted.size() > 1) 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 @@ -411,12 +411,17 @@ uint64_t FirstChildOffset = 0; uint64_t LastChildOffset = 0; std::string MergedGlobalSymtabBuf; + bool Has32BitGlobalSymtab = false; + bool Has64BitGlobalSymtab = false; public: BigArchive(MemoryBufferRef Source, Error &Err); uint64_t getFirstChildOffset() const override { return FirstChildOffset; } uint64_t getLastChildOffset() const { return LastChildOffset; } bool isEmpty() const override { return getFirstChildOffset() == 0; } + + bool has32BitGlobalSymtab() { return Has32BitGlobalSymtab; } + bool has64BitGlobalSymtab() { return Has64BitGlobalSymtab; } }; } // end namespace object diff --git a/llvm/include/llvm/Object/ArchiveWriter.h b/llvm/include/llvm/Object/ArchiveWriter.h --- a/llvm/include/llvm/Object/ArchiveWriter.h +++ b/llvm/include/llvm/Object/ArchiveWriter.h @@ -40,8 +40,16 @@ Expected computeArchiveRelativePath(StringRef From, StringRef To); +enum class SymtabWritingMode { + NoSymtab, // Do not write symbol table. + NormalSymtab, // Write symbol table. For the Big Archive format, write both + // 32-bit and 64-bit symbol tables. + BigArchive32, // Only write the 32-bit symbol table. + BigArchive64 // Only write the 64-bit symbol table. +}; + Error writeArchive(StringRef ArcName, ArrayRef NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, + SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr OldArchiveBuf = nullptr, bool IsEC = false); @@ -49,8 +57,9 @@ // writeArchiveToBuffer is similar to writeArchive but returns the Archive in a // buffer instead of writing it out to a file. Expected> -writeArchiveToBuffer(ArrayRef NewMembers, bool WriteSymtab, - object::Archive::Kind Kind, bool Deterministic, bool Thin); +writeArchiveToBuffer(ArrayRef NewMembers, + SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, + bool Deterministic, bool Thin); } #endif diff --git a/llvm/lib/ObjCopy/Archive.cpp b/llvm/lib/ObjCopy/Archive.cpp --- a/llvm/lib/ObjCopy/Archive.cpp +++ b/llvm/lib/ObjCopy/Archive.cpp @@ -60,8 +60,9 @@ // For thin archives it writes the archive file itself as well as its members. static Error deepWriteArchive(StringRef ArcName, ArrayRef NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, - bool Deterministic, bool Thin) { + SymtabWritingMode WriteSymtab, + object::Archive::Kind Kind, bool Deterministic, + bool Thin) { if (Kind == object::Archive::K_BSD && !NewMembers.empty() && NewMembers.front().detectKindFromObject() == object::Archive::K_DARWIN) Kind = object::Archive::K_DARWIN; @@ -102,8 +103,10 @@ return NewArchiveMembersOrErr.takeError(); const CommonConfig &CommonConfig = Config.getCommonConfig(); return deepWriteArchive(CommonConfig.OutputFilename, *NewArchiveMembersOrErr, - Ar.hasSymbolTable(), Ar.kind(), - CommonConfig.DeterministicArchives, Ar.isThin()); + Ar.hasSymbolTable() ? SymtabWritingMode::NormalSymtab + : SymtabWritingMode::NoSymtab, + Ar.kind(), CommonConfig.DeterministicArchives, + Ar.isThin()); } } // end namespace objcopy diff --git a/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp --- a/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp +++ b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp @@ -490,10 +490,12 @@ if (Kind == object::Archive::K_BSD) Kind = object::Archive::K_DARWIN; Expected> OutputBufferOrErr = - writeArchiveToBuffer(*NewArchiveMembersOrErr, - (*ArOrErr)->hasSymbolTable(), Kind, - Config.getCommonConfig().DeterministicArchives, - (*ArOrErr)->isThin()); + writeArchiveToBuffer( + *NewArchiveMembersOrErr, + (*ArOrErr)->hasSymbolTable() ? SymtabWritingMode::NormalSymtab + : SymtabWritingMode::NoSymtab, + Kind, Config.getCommonConfig().DeterministicArchives, + (*ArOrErr)->isThin()); if (!OutputBufferOrErr) return OutputBufferOrErr.takeError(); Expected> BinaryOrErr = 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 @@ -1392,6 +1392,8 @@ GlobSymtab32Loc, GlobSymtab32Size, "32-bit"); if (Err) return; + + Has32BitGlobalSymtab = true; } if (GlobSymtab64Offset) { @@ -1400,6 +1402,8 @@ GlobSymtab64Loc, GlobSymtab64Size, "64-bit"); if (Err) return; + + Has64BitGlobalSymtab = true; } SmallVector SymtabInfos; 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 @@ -680,7 +680,7 @@ static Expected> computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, object::Archive::Kind Kind, bool Thin, bool Deterministic, - bool NeedSymbols, SymMap *SymMap, + SymtabWritingMode NeedSymbols, SymMap *SymMap, ArrayRef NewMembers) { static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'}; @@ -796,7 +796,7 @@ Out.flush(); std::vector Symbols; - if (NeedSymbols) { + if (NeedSymbols != SymtabWritingMode::NoSymtab) { Expected> SymbolsOrErr = getSymbols(Buf, Index, SymNames, SymMap, HasObject); if (!SymbolsOrErr) @@ -860,7 +860,8 @@ static Error writeArchiveToStream(raw_ostream &Out, ArrayRef NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, + SymtabWritingMode WriteSymtab, + object::Archive::Kind Kind, bool Deterministic, bool Thin, bool IsEC) { assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode"); @@ -897,6 +898,7 @@ uint64_t LastMemberHeaderOffset = 0; uint64_t NumSyms = 0; uint64_t NumSyms32 = 0; // Store symbol number of 32-bit member files. + bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab; for (const auto &M : Data) { // Record the start of the member's offset @@ -910,7 +912,7 @@ // symbols; the second global symbol table does the same for 64-bit file // members. As a big archive can have both 32-bit and 64-bit file members, // we need to know the number of symbols in each symbol table individually. - if (isAIXBigArchive(Kind) && WriteSymtab) { + if (isAIXBigArchive(Kind) && ShouldWriteSymtab) { Expected Is64BitOrErr = is64BitSymbolicFile(M.Data); if (Error E = Is64BitOrErr.takeError()) return E; @@ -924,7 +926,7 @@ // 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 && !is64BitKind(Kind)) { + if (ShouldWriteSymtab && !is64BitKind(Kind)) { // We assume 32-bit offsets to see if 32-bit symbols are possible or not. HeadersSize = computeHeadersSize(Kind, Data.size(), StringTableSize, NumSyms, SymNamesBuf.size(), @@ -962,7 +964,7 @@ Out << "!\n"; if (!isAIXBigArchive(Kind)) { - if (WriteSymtab) { + if (ShouldWriteSymtab) { if (!HeadersSize) HeadersSize = computeHeadersSize( Kind, Data.size(), StringTableSize, NumSyms, SymNamesBuf.size(), @@ -978,7 +980,7 @@ Out << StringTableMember.Header << StringTableMember.Data << StringTableMember.Padding; - if (WriteSymtab && SymMap.ECMap.size()) + if (ShouldWriteSymtab && SymMap.ECMap.size()) writeECSymbols(Out, Kind, Deterministic, Data, SymMap); for (const MemberData &M : Data) @@ -1017,7 +1019,7 @@ raw_svector_ostream SymNames32(SymNamesBuf32); raw_svector_ostream SymNames64(SymNamesBuf64); - if (WriteSymtab && NumSyms) + if (ShouldWriteSymtab && NumSyms) // Generate the symbol names for the members. for (const NewArchiveMember &M : NewMembers) { MemoryBufferRef Buf = M.Buf->getMemBufferRef(); @@ -1041,11 +1043,15 @@ // the offset to the 32-bit global symbol table, and the 'GlobSym64Offset' // contains the offset to the 64-bit global symbol table. uint64_t GlobalSymbolOffset = - (WriteSymtab && NumSyms32 > 0) ? MemberTableEndOffset : 0; + (ShouldWriteSymtab && + (WriteSymtab != SymtabWritingMode::BigArchive64) && NumSyms32 > 0) + ? MemberTableEndOffset + : 0; uint64_t GlobalSymbolOffset64 = 0; uint64_t NumSyms64 = NumSyms - NumSyms32; - if (WriteSymtab && NumSyms64 > 0) { + if (ShouldWriteSymtab && (WriteSymtab != SymtabWritingMode::BigArchive32) && + NumSyms64 > 0) { if (GlobalSymbolOffset == 0) GlobalSymbolOffset64 = MemberTableEndOffset; else @@ -1095,7 +1101,7 @@ Out << '\0'; // Name table must be tail padded to an even number of // bytes. - if (WriteSymtab) { + if (ShouldWriteSymtab) { // Write global symbol table for 32-bit file members. if (GlobalSymbolOffset) { writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf32, @@ -1121,7 +1127,7 @@ } Error writeArchive(StringRef ArcName, ArrayRef NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, + SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr OldArchiveBuf, bool IsEC) { Expected Temp = @@ -1153,9 +1159,9 @@ } Expected> -writeArchiveToBuffer(ArrayRef NewMembers, bool WriteSymtab, - object::Archive::Kind Kind, bool Deterministic, - bool Thin) { +writeArchiveToBuffer(ArrayRef NewMembers, + SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, + bool Deterministic, bool Thin) { SmallVector ArchiveBufferVector; raw_svector_ostream ArchiveStream(ArchiveBufferVector); diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -610,7 +610,7 @@ OF.createShortImport(*Name, E.Ordinal, ImportType, NameType)); } - return writeArchive(Path, Members, /*WriteSymtab*/ true, + return writeArchive(Path, Members, SymtabWritingMode::NormalSymtab, MinGW ? object::Archive::K_GNU : object::Archive::K_COFF, /*Deterministic*/ true, /*Thin*/ false); } diff --git a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp --- a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp +++ b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp @@ -482,12 +482,10 @@ std::reverse(Members.begin(), Members.end()); bool Thin = Args.hasArg(OPT_llvmlibthin); - if (Error E = - writeArchive(OutputPath, Members, - /*WriteSymtab=*/true, - Thin ? object::Archive::K_GNU : object::Archive::K_COFF, - /*Deterministic*/ true, Thin, nullptr, - COFF::isArm64EC(LibMachine))) { + if (Error E = writeArchive( + OutputPath, Members, SymtabWritingMode::NormalSymtab, + Thin ? object::Archive::K_GNU : object::Archive::K_COFF, + /*Deterministic=*/true, Thin, nullptr, COFF::isArm64EC(LibMachine))) { handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) { llvm::errs() << OutputPath << ": " << EI.message() << "\n"; }); diff --git a/llvm/test/tools/llvm-ranlib/AIX-X-option-non-AIX.test b/llvm/test/tools/llvm-ranlib/AIX-X-option-non-AIX.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ranlib/AIX-X-option-non-AIX.test @@ -0,0 +1,6 @@ +# UNSUPPORTED: system-aix +## Test the -X option is not supported on non-AIX os. + +# RUN: not llvm-ranlib -X32 2>&1 | FileCheck --implicit-check-not="error:" --check-prefix=INVALID-X-OPTION %s + +# INVALID-X-OPTION: error: -X32 option not supported on non AIX OS diff --git a/llvm/test/tools/llvm-ranlib/aix-X-option.test b/llvm/test/tools/llvm-ranlib/aix-X-option.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ranlib/aix-X-option.test @@ -0,0 +1,130 @@ +# REQUIRES: system-aix +## Test the -X option. +## The option specifies the type of object file on which llvm-ranlib will operate. + +# RUN: rm -rf %t && mkdir %t && cd %t +# RUN: yaml2obj --docnum=1 -DFLAG=0x1DF %s -o t32_1.o +# RUN: yaml2obj --docnum=1 -DFLAG=0x1F7 %s -o t64_1.o +# RUN: yaml2obj --docnum=2 -DFLAG=0x1DF %s -o t32_2.o +# RUN: yaml2obj --docnum=2 -DFLAG=0x1F7 %s -o t64_2.o + +# RUN: llvm-ar qS t_all.a t32_1.o t64_1.o t32_2.o t64_2.o +# RUN: cp t_all.a t_X32.a +# RUN: cp t_all.a t_X64.a +# RUN: cp t_all.a t_X32_64.a + +## Test the OBJECT_MODE environment variable when adding symbol table. +# RUN: unset OBJECT_MODE +# RUN: llvm-ranlib t_X32.a +# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s +# RUN: cp t_all.a t_X32.a +# RUN: env OBJECT_MODE=32 llvm-ranlib t_X32.a +# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s + +# RUN: env OBJECT_MODE=64 llvm-ranlib t_X64.a +# RUN: llvm-nm --print-armap t_X64.a 2>&1 | FileCheck --check-prefixes=GLOB64 --implicit-check-not="in t32" %s + +# RUN: env OBJECT_MODE=32_64 llvm-ranlib t_X32_64.a +# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s +# RUN: cp t_all.a t_X32_64.a +# RUN: env OBJECT_MODE=any llvm-ranlib t_X32_64.a +# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s + +# RUN: cp t_all.a t_X32.a +# RUN: cp t_all.a t_X64.a +# RUN: cp t_all.a t_X32_64.a + +## Test the -X option when adding symbol table. +# RUN: llvm-ranlib -X32 t_X32.a +# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s +# RUN: llvm-ranlib -X64 t_X32.a +# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s + +# RUN: llvm-ranlib -X64 t_X64.a +# RUN: llvm-nm --print-armap t_X64.a 2>&1 | FileCheck --check-prefixes=GLOB64 --implicit-check-not="in t32" %s +# RUN: llvm-ranlib -X32 t_X64.a +# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s + +# RUN: llvm-ranlib -X32_64 t_X32_64.a +# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s +# RUN: cp t_all.a t_X32_64.a +# RUN: llvm-ranlib -Xany t_X32_64.a +# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s + +# RUN: cp t_all.a t_X32.a +# RUN: cp t_all.a t_X64.a + +## Test that the -X option will override the "OBJECT_MODE" environment variable. +# RUN: env OBJECT_MODE=32_64 llvm-ranlib -X32 t_X32.a +# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s + +# RUN: env OBJECT_MODE=32 llvm-ranlib -X64 t_X64.a +# RUN: llvm-nm --print-armap t_X64.a 2>&1 | FileCheck --check-prefixes=GLOB64 --implicit-check-not="in t32" %s + +# GLOB32: sym1_0x1DF in t32_1.o +# GLOB32-NEXT: sym2_0x1DF in t32_1.o +# GLOB32-NEXT: sym3_0x1DF in t32_2.o +# GLOB32-NEXT: sym4_0x1DF in t32_2.o + +# GLOB64: sym1_0x1F7 in t64_1.o +# GLOB64-NEXT: sym2_0x1F7 in t64_1.o +# GLOB64-NEXT: sym3_0x1F7 in t64_2.o +# GLOB64-NEXT: sym4_0x1F7 in t64_2.o + +## Test invalid -X option and OBJECT_MODE enviornment var. +# RUN: not env OBJECT_MODE= llvm-ranlib t_X32.a 2>&1 | FileCheck --implicit-check-not="error:" --check-prefixes=INVALID-OBJECT-MODE %s +# RUN: not env OBJECT_MODE="" llvm-ranlib t_X32.a 2>&1 | FileCheck --implicit-check-not="error:" --check-prefixes=INVALID-OBJECT-MODE %s +# RUN: not env OBJECT_MODE=31 llvm-ranlib t_X64.a 2>&1 | FileCheck --implicit-check-not="error:" --check-prefixes=INVALID-OBJECT-MODE %s +# RUN: not llvm-ranlib -X t_X64.a 2>&1 | FileCheck --implicit-check-not="error:" --check-prefixes=INVALID-X-OPTION %s +# RUN: not llvm-ranlib -X31 t_X64.a 2>&1 | FileCheck --implicit-check-not="error:" --check-prefixes=INVALID-X-OPTION %s + +# INVALID-OBJECT-MODE: error: the OBJECT_MODE environment variable has an invalid value. OBJECT_MODE must be 32, 64, 32_64, or any +# INVALID-X-OPTION: error: the specified object mode is not valid. Specify -X32, -X64, -X32_64, or -Xany + +--- !XCOFF +FileHeader: + MagicNumber: [[FLAG]] +Sections: + - Name: .data + Flags: [ STYP_DATA ] +Symbols: + - Name: sym1_[[FLAG]] + Section: .data + Type: 0x4000 + StorageClass: C_EXT + AuxEntries: + - Type: AUX_CSECT + SymbolAlignmentAndType: 0x09 + StorageMappingClass: XMC_RW + - Name: sym2_[[FLAG]] + Section: .data + Type: 0x4000 + StorageClass: C_EXT + AuxEntries: + - Type: AUX_CSECT + SymbolAlignmentAndType: 0x09 + StorageMappingClass: XMC_RW + +--- !XCOFF +FileHeader: + MagicNumber: [[FLAG]] +Sections: + - Name: .text + Flags: [ STYP_DATA ] +Symbols: + - Name: sym3_[[FLAG]] + Section: .text + Type: 0x4000 + StorageClass: C_EXT + AuxEntries: + - Type: AUX_CSECT + SymbolAlignmentAndType: 0x09 + StorageMappingClass: XMC_PR + - Name: sym4_[[FLAG]] + Section: .text + Type: 0x4000 + StorageClass: C_EXT + AuxEntries: + - Type: AUX_CSECT + SymbolAlignmentAndType: 0x09 + StorageMappingClass: XMC_PR 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 @@ -69,7 +69,9 @@ << " -v --version - Display the version of this program\n" << " -D - Use zero for timestamps and uids/gids " "(default)\n" - << " -U - Use actual timestamps and uids/gids\n"; + << " -U - Use actual timestamps and uids/gids\n" + << " -X{32|64|32_64|any} - Specify which archive symbol tables " + "should be generated if they do not already exist (AIX OS only)\n"; } static void printArHelp(StringRef ToolName) { @@ -225,7 +227,8 @@ static bool CompareFullPath = false; ///< 'P' modifier static bool OnlyUpdate = false; ///< 'u' modifier static bool Verbose = false; ///< 'v' modifier -static bool Symtab = true; ///< 's' modifier +static SymtabWritingMode Symtab = + SymtabWritingMode::NormalSymtab; ///< 's' modifier static bool Deterministic = true; ///< 'D' and 'U' modifiers static bool Thin = false; ///< 'T' modifier static bool AddLibrary = false; ///< 'L' modifier @@ -371,11 +374,11 @@ CompareFullPath = true; break; case 's': - Symtab = true; + Symtab = SymtabWritingMode::NormalSymtab; MaybeJustCreateSymTab = true; break; case 'S': - Symtab = false; + Symtab = SymtabWritingMode::NoSymtab; break; case 'u': OnlyUpdate = true; @@ -1074,9 +1077,31 @@ // In summary, we only need to update the symbol table if we have none. // This is actually very common because of broken build systems that think // they have to run ranlib. - if (OldArchive->hasSymbolTable()) - return; + if (OldArchive->hasSymbolTable()) { + if (OldArchive->kind() != object::Archive::K_AIXBIG) + return; + // For archives in the Big Archive format, the bit mode option specifies + // which symbol table to generate. The presence of a symbol table that does + // not match the specified bit mode does not prevent creation of the symbol + // table that has been requested. + if (OldArchive->kind() == object::Archive::K_AIXBIG) { + BigArchive *BigArc = dyn_cast(OldArchive); + if (BigArc->has32BitGlobalSymtab() && + Symtab == SymtabWritingMode::BigArchive32) + return; + + if (BigArc->has64BitGlobalSymtab() && + Symtab == SymtabWritingMode::BigArchive64) + return; + + if (BigArc->has32BitGlobalSymtab() && BigArc->has64BitGlobalSymtab() && + Symtab == SymtabWritingMode::NormalSymtab) + return; + + Symtab = SymtabWritingMode::NormalSymtab; + } + } if (OldArchive->isThin()) Thin = true; performWriteOperation(CreateSymTab, OldArchive, nullptr, nullptr); @@ -1389,6 +1414,8 @@ static int ranlib_main(int argc, char **argv) { std::vector Archives; + bool HasAIXXOption = false; + for (int i = 1; i < argc; ++i) { StringRef arg(argv[i]); if (handleGenericOption(arg)) { @@ -1406,6 +1433,28 @@ } else if (arg.front() == 'v') { cl::PrintVersionMessage(); return 0; + } else if (arg.front() == 'X') { + if (object::Archive::getDefaultKindForHost() == + object::Archive::K_AIXBIG) { + HasAIXXOption = true; + arg.consume_front("X"); + const char *Xarg = arg.data(); + if (Xarg[0] == '\0') { + if (argv[i + 1][0] != '-') + BitMode = getBitMode(argv[++i]); + else + BitMode = BitModeTy::Unknown; + } else + BitMode = getBitMode(arg.data()); + + if (BitMode == BitModeTy::Unknown) + fail("the specified object mode is not valid. Specify -X32, " + "-X64, -X32_64, or -Xany"); + } else { + fail(Twine("-") + Twine(arg) + + " option not supported on non AIX OS"); + } + break; } else { // TODO: GNU ranlib also supports a -t flag fail("Invalid option: '-" + arg + "'"); @@ -1417,6 +1466,31 @@ } } + if (object::Archive::getDefaultKindForHost() == object::Archive::K_AIXBIG) { + // If not specify -X option, get BitMode from enviorment variable + // "OBJECT_MODE" for AIX OS if specify. + if (!HasAIXXOption) { + if (char *EnvObjectMode = getenv("OBJECT_MODE")) { + BitMode = getBitMode(EnvObjectMode); + if (BitMode == BitModeTy::Unknown) + fail("the OBJECT_MODE environment variable has an invalid value. " + "OBJECT_MODE must be 32, 64, 32_64, or any"); + } + } + + switch (BitMode) { + case BitModeTy::Bit32: + Symtab = SymtabWritingMode::BigArchive32; + break; + case BitModeTy::Bit64: + Symtab = SymtabWritingMode::BigArchive64; + break; + default: + Symtab = SymtabWritingMode::NormalSymtab; + break; + } + } + for (StringRef Archive : Archives) { ArchiveName = Archive.str(); performOperation(CreateSymTab); diff --git a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp --- a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp +++ b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp @@ -594,18 +594,17 @@ if (NewMembers.size() == 1) return writeArchive(OutputFile, NewMembers.begin()->second.getMembers(), - /*WriteSymtab=*/true, + SymtabWritingMode::NormalSymtab, /*Kind=*/object::Archive::K_DARWIN, C.Deterministic, /*Thin=*/false); SmallVector, 2> OutputBinaries; for (const std::pair &M : NewMembers) { Expected> OutputBufferOrErr = - writeArchiveToBuffer(M.second.getMembers(), - /*WriteSymtab=*/true, - /*Kind=*/object::Archive::K_DARWIN, - C.Deterministic, - /*Thin=*/false); + writeArchiveToBuffer( + M.second.getMembers(), SymtabWritingMode::NormalSymtab, + /*Kind=*/object::Archive::K_DARWIN, C.Deterministic, + /*Thin=*/false); if (!OutputBufferOrErr) return OutputBufferOrErr.takeError(); std::unique_ptr &OutputBuffer = OutputBufferOrErr.get();