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,16 +40,35 @@ Expected computeArchiveRelativePath(StringRef From, StringRef To); +class WriteSymTabType { + enum { + None, // Not write Symbol table. + Both, // Write both 32-bit and 64-bit symbol table. + Bit32, // Only write the 32-bit symbol table. + Bit64 // Only write the 64-bit symbol table. + } Value; + +public: + WriteSymTabType(bool PrintSym) { Value = PrintSym ? Both : None; } + void operator=(bool PrintSym) { Value = PrintSym ? Both : None; } + operator bool() { return Value != None; } + void SetBit32Only() { Value = Bit32; } + bool IsBit32Only() { return Value == Bit32; } + void SetBit64Only() { Value = Bit64; } + bool IsBit64Only() { return Value == Bit64; } +}; + Error writeArchive(StringRef ArcName, ArrayRef NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, + WriteSymTabType WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr OldArchiveBuf = nullptr); // 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, + WriteSymTabType WriteSymtab, object::Archive::Kind Kind, + bool Deterministic, bool Thin); } #endif 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 @@ -553,7 +553,8 @@ static Expected> computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, object::Archive::Kind Kind, bool Thin, bool Deterministic, - bool NeedSymbols, ArrayRef NewMembers) { + WriteSymTabType NeedSymbols, + ArrayRef NewMembers) { static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'}; uint64_t Pos = @@ -729,7 +730,8 @@ static Error writeArchiveToStream(raw_ostream &Out, ArrayRef NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, + WriteSymTabType WriteSymtab, + object::Archive::Kind Kind, bool Deterministic, bool Thin) { assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode"); @@ -876,14 +878,14 @@ // 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) + ((WriteSymtab && !WriteSymtab.IsBit64Only()) && NumSyms32 > 0) ? LastMemberEndOffset + alignTo(sizeof(object::BigArMemHdrType) + MemberTableSize, 2) : 0; uint64_t GlobalSymbolOffset64 = 0; uint64_t NumSyms64 = NumSyms - NumSyms32; - if (WriteSymtab && NumSyms64 > 0) { + if ((WriteSymtab && !WriteSymtab.IsBit32Only()) && NumSyms64 > 0) { if (GlobalSymbolOffset == 0) GlobalSymbolOffset64 = LastMemberEndOffset + @@ -962,7 +964,7 @@ } Error writeArchive(StringRef ArcName, ArrayRef NewMembers, - bool WriteSymtab, object::Archive::Kind Kind, + WriteSymTabType WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr OldArchiveBuf) { Expected Temp = @@ -994,9 +996,9 @@ } Expected> -writeArchiveToBuffer(ArrayRef NewMembers, bool WriteSymtab, - object::Archive::Kind Kind, bool Deterministic, - bool Thin) { +writeArchiveToBuffer(ArrayRef NewMembers, + WriteSymTabType WriteSymtab, object::Archive::Kind Kind, + bool Deterministic, bool Thin) { SmallVector ArchiveBufferVector; raw_svector_ostream ArchiveStream(ArchiveBufferVector); 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,121 @@ +## REQUIRES: system-aix +## Test the -X option. +## The option specifies the type of object file llvm-ranlib will operate on. + +# 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 OBJECT_MODE environment variable when adding symbol table +# RUN: env OBJECT_MODE=32 llvm-ranlib t_X32.a +# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32,GL64 %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,GL32 %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.a +# RUN: cp t_all.a t_X64.a +# RUN: cp t_all.a t_X32_64.a + +## Test -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,GL64 %s + +# RUN: llvm-ranlib -X64 t_X64.a +# RUN: llvm-nm --print-armap t_X64.a 2>&1 | FileCheck --check-prefixes=GLOB64,GL32 %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.a +# RUN: cp t_all.a t_X64.a + +## Test -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,GL64 %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,GL32 %s + +#GLOB32: var_0x1DF in t32_1.o +#GLOB32-NEXT: array_0x1DF in t32_1.o +#GLOB32-NEXT: func_0x1DF in t32_2.o +#GLOB32-NEXT: bar_0x1DF in t32_2.o + +#GL64-NOT: var_0x1F7 in t64_1.o +#GL64-NOT: array_0x1F7 in t64_1.o +#GL64-NOT: func_0x1F7 in t64_2.o +#GL64-NOT: bar_0x1F7 in t64_2.o + +#GLOB64: var_0x1F7 in t64_1.o +#GLOB64-NEXT: array_0x1F7 in t64_1.o +#GLOB64-NEXT: func_0x1F7 in t64_2.o +#GLOB64-NEXT: bar_0x1F7 in t64_2.o + +#GL32-NOT: var_0x1DF in t32_1.o +#GL32-NOT: array_0x1DF in t32_1.o +#GL32-NOT: func_0x1DF in t32_2.o +#GL32-NOT: bar_0x1DF in t32_2.o + +#GLOB1: var_0x1DF in t32_1.o +#GLOB1-NEXT: array_0x1DF in t32_1.o +#GLOB1-NEXT: var_0x1F7 in t64_1.o +#GLOB1-NEXT: array_0x1F7 in t64_1.o + +--- !XCOFF +FileHeader: + MagicNumber: [[FLAG]] +Sections: + - Name: .data + Flags: [ STYP_DATA ] +Symbols: + - Name: var_[[FLAG]] + Section: .data + Type: 0x4000 + StorageClass: C_EXT + AuxEntries: + - Type: AUX_CSECT + SymbolAlignmentAndType: 0x09 + StorageMappingClass: XMC_RW + - Name: array_[[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: func_[[FLAG]] + Section: .text + Type: 0x4000 + StorageClass: C_EXT + AuxEntries: + - Type: AUX_CSECT + SymbolAlignmentAndType: 0x09 + StorageMappingClass: XMC_PR + - Name: bar_[[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 @@ -76,7 +76,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) - Specific the bit_mode of golbal symbol " + "table generated (AIX OS only)\n"; } static void printArHelp(StringRef ToolName) { @@ -232,7 +234,7 @@ 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 WriteSymTabType Symtab = true; ///< 's' modifier static bool Deterministic = true; ///< 'D' and 'U' modifiers static bool Thin = false; ///< 'T' modifier static bool AddLibrary = false; ///< 'L' modifier @@ -1415,6 +1417,16 @@ static int ranlib_main(int argc, char **argv) { std::vector Archives; + + // Get BitMode from enviorment variable "OBJECT_MODE" for AIX OS, if + // specified. + if (object::Archive::getDefaultKindForHost() == object::Archive::K_AIXBIG) { + BitMode = getBitMode(getenv("OBJECT_MODE")); + // -X option in ranlib do not accept "any" + if (BitMode == BitModeTy::Unknown || BitMode == BitModeTy::Any) + BitMode = BitModeTy::Bit32; + } + for (int i = 1; i < argc; ++i) { StringRef arg(argv[i]); if (handleGenericOption(arg)) { @@ -1432,6 +1444,20 @@ } else if (arg.front() == 'v') { cl::PrintVersionMessage(); return 0; + } else if (arg.front() == 'X') { + if (object::Archive::getDefaultKindForHost() == + object::Archive::K_AIXBIG) { + arg.consume_front("X"); + BitMode = getBitMode(arg.data()); + // -X option in ranlib do not accept "any" + if (BitMode == BitModeTy::Unknown || BitMode == BitModeTy::Any) + fail(Twine("invalid bit mode: ") + arg); + + } 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 + "'"); @@ -1443,6 +1469,20 @@ } } + if (object::Archive::getDefaultKindForHost() == object::Archive::K_AIXBIG) { + switch (BitMode) { + case BitModeTy::Bit32: + Symtab.SetBit32Only(); + break; + case BitModeTy::Bit64: + Symtab.SetBit64Only(); + break; + default: + Symtab = true; + break; + } + } + for (StringRef Archive : Archives) { ArchiveName = Archive.str(); performOperation(CreateSymTab);