diff --git a/llvm/docs/CommandGuide/llvm-ar.rst b/llvm/docs/CommandGuide/llvm-ar.rst --- a/llvm/docs/CommandGuide/llvm-ar.rst +++ b/llvm/docs/CommandGuide/llvm-ar.rst @@ -289,6 +289,25 @@ Display the version of the :program:`llvm-ar` executable. +.. option:: -X mode + + Specifies the type of object file :program:`llvm-ar` will recognise. The mode must be + one of the following: + + 32 + Process only 32-bit object files. + 64 + Process only 64-bit object files. + 32_64 + Process both 32-bit and 64-bit object files. + any + Process all object files. + + The default is to process 32-bit object files (ignore 64-bit objects). The mode can also + be set with the OBJECT_MODE environment variable. For example, OBJECT_MODE=64 causes ar to + process any 64-bit objects and ignore 32-bit objects. The -X flag overrides the OBJECT_MODE + variable. + .. option:: @ Read command-line options and commands from response file ````. diff --git a/llvm/test/Object/X86/archive-symbol-table.s b/llvm/test/Object/X86/archive-symbol-table.s --- a/llvm/test/Object/X86/archive-symbol-table.s +++ b/llvm/test/Object/X86/archive-symbol-table.s @@ -1,3 +1,4 @@ +# RUN: export "OBJECT_MODE=any" # RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux # RUN: rm -f %t # RUN: llvm-ar rcs %t %t.o diff --git a/llvm/test/Object/archive-symtab.test b/llvm/test/Object/archive-symtab.test --- a/llvm/test/Object/archive-symtab.test +++ b/llvm/test/Object/archive-symtab.test @@ -1,3 +1,4 @@ +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj --docnum=1 %s -o %t.elf-x86-64 # RUN: yaml2obj --docnum=2 %s -o %t2.elf-x86-64 diff --git a/llvm/test/tools/llvm-ar/add-library.test b/llvm/test/tools/llvm-ar/add-library.test --- a/llvm/test/tools/llvm-ar/add-library.test +++ b/llvm/test/tools/llvm-ar/add-library.test @@ -1,3 +1,4 @@ +RUN: export "OBJECT_MODE=any" RUN: yaml2obj %S/Inputs/add-lib1.yaml -o %t-add-lib1.o RUN: yaml2obj %S/Inputs/add-lib2.yaml -o %t-add-lib2.o RUN: yaml2obj %S/Inputs/add-lib2.yaml -o %t-add-lib3.o diff --git a/llvm/test/tools/llvm-ar/default-add.test b/llvm/test/tools/llvm-ar/default-add.test --- a/llvm/test/tools/llvm-ar/default-add.test +++ b/llvm/test/tools/llvm-ar/default-add.test @@ -1,3 +1,4 @@ +RUN: export "OBJECT_MODE=any" RUN: yaml2obj %S/Inputs/macho.yaml -o %t-macho.o RUN: yaml2obj %S/Inputs/coff.yaml -o %t-coff.o RUN: yaml2obj %S/Inputs/elf.yaml -o %t-elf.o @@ -17,4 +18,4 @@ RUN: rm -f %t.ar Test with the options in a different order. RUN: llvm-ar rsc %t.ar %t-macho.o -RUN: grep -q __.SYMDEF %t.ar \ No newline at end of file +RUN: grep -q __.SYMDEF %t.ar diff --git a/llvm/test/tools/llvm-ar/default-macho.test b/llvm/test/tools/llvm-ar/default-macho.test --- a/llvm/test/tools/llvm-ar/default-macho.test +++ b/llvm/test/tools/llvm-ar/default-macho.test @@ -1,3 +1,4 @@ +RUN: export "OBJECT_MODE=any" RUN: yaml2obj %S/Inputs/macho.yaml -o %t.o RUN: rm -f %t.ar diff --git a/llvm/test/tools/llvm-ar/invalid-option-X.test b/llvm/test/tools/llvm-ar/invalid-option-X.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ar/invalid-option-X.test @@ -0,0 +1,6 @@ +# REQUIRES: !system-aix +## Test not support "-X" option in no AIX OS + +# RUN: not llvm-ar -q -X32 %t.a xcoff32.o 2>&1 | \ +# RUN: FileCheck %s --check-prefixes=ERR +# ERR: error: -X32 option not supported on non AIX OS diff --git a/llvm/test/tools/llvm-ar/macho-edit.test b/llvm/test/tools/llvm-ar/macho-edit.test --- a/llvm/test/tools/llvm-ar/macho-edit.test +++ b/llvm/test/tools/llvm-ar/macho-edit.test @@ -1,5 +1,6 @@ ## Make sure the darwin format specifics are preserved when updating archives. +# RUN: export "OBJECT_MODE=any" # RUN: rm -rf %t && mkdir -p %t # RUN: yaml2obj %p/Inputs/macho.yaml > %t/dup.o diff --git a/llvm/test/tools/llvm-ar/move.test b/llvm/test/tools/llvm-ar/move.test --- a/llvm/test/tools/llvm-ar/move.test +++ b/llvm/test/tools/llvm-ar/move.test @@ -1,5 +1,6 @@ ## Test the move command without modifiers moves members to the end +# RUN: export "OBJECT_MODE=any" # RUN: rm -rf %t && mkdir -p %t # RUN: yaml2obj %s -o %t/1.o --docnum=1 # RUN: yaml2obj %s -o %t/2.o --docnum=2 diff --git a/llvm/test/tools/llvm-ar/mri-addlib.test b/llvm/test/tools/llvm-ar/mri-addlib.test --- a/llvm/test/tools/llvm-ar/mri-addlib.test +++ b/llvm/test/tools/llvm-ar/mri-addlib.test @@ -1,5 +1,6 @@ ## Test the ADDLIB MRI command. +# RUN: export "OBJECT_MODE=any" # RUN: rm -rf %t && mkdir -p %t # RUN: yaml2obj %s -o %t/f.o # RUN: llvm-ar r %t/f.a %t/f.o diff --git a/llvm/test/tools/llvm-ar/mri-addmod.test b/llvm/test/tools/llvm-ar/mri-addmod.test --- a/llvm/test/tools/llvm-ar/mri-addmod.test +++ b/llvm/test/tools/llvm-ar/mri-addmod.test @@ -1,5 +1,6 @@ ## Test the ADDMOD MRI command. +# RUN: export "OBJECT_MODE=any" # RUN: rm -rf %t && mkdir -p %t # RUN: yaml2obj %s -o %t/f.o diff --git a/llvm/test/tools/llvm-ar/mri-comments.test b/llvm/test/tools/llvm-ar/mri-comments.test --- a/llvm/test/tools/llvm-ar/mri-comments.test +++ b/llvm/test/tools/llvm-ar/mri-comments.test @@ -1,5 +1,6 @@ # Test different MRI comment formats and white space. +RUN: export "OBJECT_MODE=any" RUN: rm -rf %t && mkdir -p %t RUN: yaml2obj %S/Inputs/elf.yaml -o %t/elf.o diff --git a/llvm/test/tools/llvm-ar/mri-end.test b/llvm/test/tools/llvm-ar/mri-end.test --- a/llvm/test/tools/llvm-ar/mri-end.test +++ b/llvm/test/tools/llvm-ar/mri-end.test @@ -1,5 +1,6 @@ # The END MRI command is optional. Scripts that omit # or include END should be handled by llvm-ar. +RUN: export "OBJECT_MODE=any" RUN: rm -rf %t && mkdir -p %t # Empty File diff --git a/llvm/test/tools/llvm-ar/mri-thin-archive.test b/llvm/test/tools/llvm-ar/mri-thin-archive.test --- a/llvm/test/tools/llvm-ar/mri-thin-archive.test +++ b/llvm/test/tools/llvm-ar/mri-thin-archive.test @@ -1,3 +1,4 @@ +RUN: export "OBJECT_MODE=any" RUN: rm -rf %t && mkdir -p %t/addlib/ RUN: yaml2obj %S/Inputs/elf.yaml -o %t/elf.o diff --git a/llvm/test/tools/llvm-ar/option-X.test b/llvm/test/tools/llvm-ar/option-X.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ar/option-X.test @@ -0,0 +1,219 @@ +# REQUIRES: system-aix +## Test the "-X" option. +## The option specifies the type of object file to be operate in llvm-ar. + +# RUN: rm -rf %t +# RUN: mkdir %t +# RUN: cd %t +# RUN: yaml2obj --docnum=1 -DCLASS=ELFCLASS32 %s -o elf32.o +# RUN: yaml2obj --docnum=1 -DCLASS=ELFCLASS64 %s -o elf64.o + +# RUN: yaml2obj --docnum=2 -DFLAG=0x1DF %s -o xcoff32.o +# RUN: yaml2obj --docnum=2 -DFLAG=0x1F7 %s -o xcoff64.o + +## Test -X option for the create a new archive operation +# RUN: rm -f %t.a +# RUN: llvm-ar -q -c %t.a xcoff32.o elf32.o xcoff64.o elf64.o 2>&1 | \ +# RUN: FileCheck %s --check-prefixes=INFO_64 +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32 + +# INFO_64: xcoff64.o is not valid with the current object file mode. +# INFO_64: elf64.o is not valid with the current object file mode. + +# RUN: rm -f %t32.a +# RUN: llvm-ar -q -c -X 32 %t32.a xcoff32.o elf32.o xcoff64.o elf64.o 2>&1 +# RUN: llvm-ar -t -Xany %t32.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32 + +# RUN: rm -f %t.a +# RUN: export "OBJECT_MODE=64" +# RUN: llvm-ar -q -c -X32 %t.a xcoff32.o elf32.o xcoff64.o elf64.o +# unset OBJECT_MODE +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32 + +# RUN: rm -f %t.a +# RUN: llvm-ar -q -c -X 64 %t.a xcoff32.o elf32.o xcoff64.o elf64.o 2>&1 | \ +# RUN: FileCheck %s --check-prefixes=INFO_32 +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ64 + +# INFO_32: xcoff32.o is not valid with the current object file mode. +# INFO_32: elf32.o is not valid with the current object file mode. + +# RUN: rm -f %t.a +# RUN: export "OBJECT_MODE=64" +# RUN: llvm-ar -q -c %t.a xcoff32.o elf32.o xcoff64.o elf64.o +# RUN: unset OBJECT_MODE +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ64 + +# RUN: rm -f %t.a +# RUN: llvm-ar -q -c -Xany %t.a xcoff32.o elf32.o xcoff64.o elf64.o +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32_64 + +# RUN: rm -f %t.a +# RUN: llvm-ar -q -c -X32_64 %t.a xcoff32.o elf32.o xcoff64.o elf64.o +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32_64 + +# RUN: rm -f %t.a +# RUN: export "OBJECT_MODE=32_64" +# RUN: llvm-ar -q -c %t.a xcoff32.o elf32.o xcoff64.o elf64.o +# RUN: unset OBJECT_MODE +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32_64 + +# RUN: rm -f %t.a +# RUN: export "OBJECT_MODE=any" +# RUN: llvm-ar -q -c %t.a xcoff32.o elf32.o xcoff64.o elf64.o +# RUN: unset OBJECT_MODE +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32_64 + +## Test -X option for print operation. + +# RUN: llvm-ar -t -X32 %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32 + +# RUN: llvm-ar -t -X64 %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ64 + +# RUN: llvm-ar -t -X32_64 %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32_64 + +## Test -X option for extract operation. +# RUN: rm -rf *.o +# RUN: llvm-ar -x -X32 %t.a +# RUN: test -f xcoff32.o +# RUN: test -f elf32.o +# RUN: not test -f xcoff64.o +# RUN: not test -f elf64.o + +# RUN: rm -rf *.o +# RUN: llvm-ar -x -X64 %t.a +# RUN: test -f xcoff64.o +# RUN: test -f elf64.o +# RUN: not test -f xcoff32.o +# RUN: not test -f elf32.o + +# RUN: rm -rf *.o +# RUN: llvm-ar -x -X32_64 %t.a +# RUN: test -f xcoff32.o +# RUN: test -f elf32.o +# RUN: test -f xcoff64.o +# RUN: test -f elf64.o + +# RUN: rm -rf *.o +# RUN: llvm-ar -x -Xany %t.a +# RUN: test -f xcoff32.o +# RUN: test -f elf32.o +# RUN: test -f xcoff64.o +# RUN: test -f elf64.o + +## Extract a 64bit object file with option -X32 +# RUN: rm -rf *.o +# RUN: not llvm-ar -x %t.a xcoff64.o 2>&1 | \ +# RUN: FileCheck %s -DFILE=xcoff64.o --check-prefixes=ERR64 +# RUN: not llvm-ar -x -X32 %t.a xcoff64.o 2>&1 | \ +# RUN: FileCheck %s -DFILE=xcoff64.o --check-prefixes=ERR64 + +# ERR64: llvm-ar: error: '[[FILE]]' was not found +# RUN: not test -f xcoff64.o + +## Test deleting a object file from big archive file. +# RUN: cp %t.a %t_bak.a +# RUN: llvm-ar -d -X32 %t.a xcoff64.o elf64.o +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32_64 + +# RUN: cp %t_bak.a %t.a +# RUN: llvm-ar -d -X64 %t.a xcoff64.o elf64.o +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32 + +# RUN: cp %t_bak.a %t.a +# RUN: llvm-ar -d -Xany %t.a xcoff64.o elf64.o +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32 + +## Test replace/insert a object file from big archive file. +## xcoff32.o is 64 bits object file here. without -X64 or -X32_64 +# RUN: rm -rf *.o +# RUN: yaml2obj --docnum=2 -DFLAG=0x1F7 %s -o xcoff32.o + +## Without -X64, -X32_64 or -Xany, nothing changed here, +## since xcoff32.o is 64 bits object file. +# RUN: llvm-ar -ru %t32.a xcoff32.o +# RUN: llvm-ar -t -Xany %t32.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32 +# RUN: llvm-nm -Xany --format=just-symbols %t32.a | \ +# RUN: FileCheck %s --check-prefixes=SYM32 + +## With option -X64, -X32_64 or -Xany, +## the old 32bit xcoff32.o is still in the archive +## and a new 64bits object file is added into the archive. +# RUN: llvm-ar -ru -X64 %t32.a xcoff32.o +# RUN: llvm-ar -t -Xany %t32.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32,OBJ32_DUP +# RUN: llvm-nm -Xany --format=just-symbols %t32.a | \ +# RUN: FileCheck %s --check-prefixes=SYM32_64 + +## Test move mumber +# RUN: cp %t_bak.a %t.a +## Not move 64bits object without -X64 +# RUN: not llvm-ar -ma elf64.o %t.a xcoff64.o 2>&1| \ +# RUN: FileCheck %s --check-prefixes=MOVE_ERR + +# MOVE_ERR: llvm-ar: error: xcoff64.o: No such file or directory + +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=OBJ32_64 + +# RUN: llvm-ar -ma -X64 elf64.o %t.a xcoff64.o +# RUN: llvm-ar -t -Xany %t.a | \ +# RUN: FileCheck %s --check-prefixes=MOVE +# MOVE: xcoff32.o +# MOVE-NEXT: elf32.o +# MOVE-NEXT: elf64.o +# MOVE-NEXT: xcoff64.o +# MOVE-EMPTY: + +#OBJ32: xcoff32.o +#OBJ32-NEXT: elf32.o +#OBJ32_DUP-NEXT: xcoff32.o +#OBJ32-EMPTY: + +#OBJ64: xcoff64.o +#OBJ64-NEXT: elf64.o +#OBJ64-EMPTY: + +#OBJ32_64: xcoff32.o +#OBJ32_64-NEXT: elf32.o +#OBJ32_64-NEXT: xcoff64.o +#OBJ32_64-NEXT: elf64.o +#OBJ32_64-EMPTY: + +#SYM32: var_0x1DF +#SYM32-NOT: var_0x1F7 + +#SYM32_64: var_0x1DF +#SYM32_64: var_0x1F7 + + +--- !ELF +FileHeader: + Class: [[CLASS]] + Data: ELFDATA2LSB + Type: ET_REL +Symbols: + - Name: [[CLASS]]_var + +--- !XCOFF +FileHeader: + MagicNumber: [[FLAG]] +Symbols: + - Name: var_[[FLAG]] + diff --git a/llvm/test/tools/llvm-ar/quick-append.test b/llvm/test/tools/llvm-ar/quick-append.test --- a/llvm/test/tools/llvm-ar/quick-append.test +++ b/llvm/test/tools/llvm-ar/quick-append.test @@ -1,5 +1,6 @@ ## Test quick append +# RUN: export "OBJECT_MODE=any" # RUN: rm -rf %t && mkdir -p %t # RUN: yaml2obj %s -o %t/1.o --docnum=1 # RUN: yaml2obj %s -o %t/2.o --docnum=2 diff --git a/llvm/test/tools/llvm-ar/reduce-thin-path.test b/llvm/test/tools/llvm-ar/reduce-thin-path.test --- a/llvm/test/tools/llvm-ar/reduce-thin-path.test +++ b/llvm/test/tools/llvm-ar/reduce-thin-path.test @@ -1,3 +1,4 @@ +RUN: export "OBJECT_MODE=any" RUN: rm -rf %t && mkdir -p %t/foo/bar/ RUN: mkdir -p %t/baz/ RUN: yaml2obj %S/Inputs/elf.yaml -o %t/elf.o diff --git a/llvm/test/tools/llvm-ar/regex-cmd.test b/llvm/test/tools/llvm-ar/regex-cmd.test --- a/llvm/test/tools/llvm-ar/regex-cmd.test +++ b/llvm/test/tools/llvm-ar/regex-cmd.test @@ -1,3 +1,4 @@ +RUN: export "OBJECT_MODE=any" RUN: yaml2obj %S/Inputs/elf.yaml -o %t.o RUN: rm -f %t.ar diff --git a/llvm/test/tools/llvm-ar/replace-update.test b/llvm/test/tools/llvm-ar/replace-update.test --- a/llvm/test/tools/llvm-ar/replace-update.test +++ b/llvm/test/tools/llvm-ar/replace-update.test @@ -1,5 +1,6 @@ ## Test that the replace command with "u" updates the relevant members. +# RUN: export "OBJECT_MODE=any" # RUN: rm -rf %t && mkdir -p %t/new/other # RUN: yaml2obj %s -o %t/1.o --docnum=1 diff --git a/llvm/test/tools/llvm-ar/replace.test b/llvm/test/tools/llvm-ar/replace.test --- a/llvm/test/tools/llvm-ar/replace.test +++ b/llvm/test/tools/llvm-ar/replace.test @@ -1,5 +1,6 @@ ## Test the replace command without modifiers replaces the relevant members. +# RUN: export "OBJECT_MODE=any" # RUN: rm -rf %t && mkdir -p %t/new/other # RUN: yaml2obj %s -o %t/1.o --docnum=1 # RUN: yaml2obj %s -o %t/2.o --docnum=2 diff --git a/llvm/test/tools/llvm-ar/symtab.test b/llvm/test/tools/llvm-ar/symtab.test --- a/llvm/test/tools/llvm-ar/symtab.test +++ b/llvm/test/tools/llvm-ar/symtab.test @@ -1,5 +1,6 @@ ## Test the s and S modifiers. Build and do not build a symbol table. +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %s -o %t.o # RUN: touch %t-other.txt diff --git a/llvm/test/tools/llvm-ar/thin-archive.test b/llvm/test/tools/llvm-ar/thin-archive.test --- a/llvm/test/tools/llvm-ar/thin-archive.test +++ b/llvm/test/tools/llvm-ar/thin-archive.test @@ -1,3 +1,4 @@ +RUN: export "OBJECT_MODE=any" RUN: rm -rf %t && mkdir -p %t/foo/bar/ RUN: yaml2obj %S/Inputs/elf.yaml -o %t/foo/elf.o diff --git a/llvm/test/tools/llvm-dwarfdump/X86/section_sizes_archive.test b/llvm/test/tools/llvm-dwarfdump/X86/section_sizes_archive.test --- a/llvm/test/tools/llvm-dwarfdump/X86/section_sizes_archive.test +++ b/llvm/test/tools/llvm-dwarfdump/X86/section_sizes_archive.test @@ -1,6 +1,7 @@ ## Check how llvm-dwarfdump calculates section sizes ## with --show-section-sizes on an archive. +# RUN: export "OBJECT_MODE=any" # RUN: rm -rf %t && mkdir -p %t # RUN: yaml2obj --docnum=1 %s -o %t/1.o # RUN: yaml2obj --docnum=2 %s -o %t/2.o diff --git a/llvm/test/tools/llvm-libtool-darwin/L-and-l.test b/llvm/test/tools/llvm-libtool-darwin/L-and-l.test --- a/llvm/test/tools/llvm-libtool-darwin/L-and-l.test +++ b/llvm/test/tools/llvm-libtool-darwin/L-and-l.test @@ -1,5 +1,6 @@ ## This test checks that -l and -L options work correctly. +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o # RUN: yaml2obj %S/Inputs/input2.yaml -o %t-input2.o 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,5 +1,6 @@ ## This test checks that an archive is flattened correctly. +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o # RUN: yaml2obj %S/Inputs/input2.yaml -o %t-input2.o # RUN: llvm-as %S/Inputs/x86_64-osx.ll -o %t-x86_64.bc diff --git a/llvm/test/tools/llvm-libtool-darwin/cpu-subtype-matching.test b/llvm/test/tools/llvm-libtool-darwin/cpu-subtype-matching.test --- a/llvm/test/tools/llvm-libtool-darwin/cpu-subtype-matching.test +++ b/llvm/test/tools/llvm-libtool-darwin/cpu-subtype-matching.test @@ -1,5 +1,6 @@ ## This test checks that the CPU subtype matching logic is handled correctly. +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %s --docnum=1 -o %t-armv6.obj # RUN: yaml2obj %s --docnum=2 -o %t-armv7.obj # RUN: llvm-as %p/Inputs/arm64-ios.ll -o %t-arm64.bc diff --git a/llvm/test/tools/llvm-libtool-darwin/create-static-lib.test b/llvm/test/tools/llvm-libtool-darwin/create-static-lib.test --- a/llvm/test/tools/llvm-libtool-darwin/create-static-lib.test +++ b/llvm/test/tools/llvm-libtool-darwin/create-static-lib.test @@ -1,5 +1,6 @@ ## This test checks that a correct static library is created. +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o # RUN: yaml2obj %S/Inputs/input2.yaml -o %t-input2.o # RUN: llvm-as %S/Inputs/x86_64-osx.ll -o %t-x86_64.bc diff --git a/llvm/test/tools/llvm-libtool-darwin/deterministic-library.test b/llvm/test/tools/llvm-libtool-darwin/deterministic-library.test --- a/llvm/test/tools/llvm-libtool-darwin/deterministic-library.test +++ b/llvm/test/tools/llvm-libtool-darwin/deterministic-library.test @@ -4,6 +4,7 @@ ## We only test timestamps as a proxy for full deterministic writing; i.e. we ## assume UID/GIDs are preserved if timestamps are preserved. +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o # RUN: touch -t 199505050555.55 %t-input1.o diff --git a/llvm/test/tools/llvm-libtool-darwin/filelist.test b/llvm/test/tools/llvm-libtool-darwin/filelist.test --- a/llvm/test/tools/llvm-libtool-darwin/filelist.test +++ b/llvm/test/tools/llvm-libtool-darwin/filelist.test @@ -1,5 +1,6 @@ ## This test checks that the -filelist option works correctly. +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o # RUN: yaml2obj %S/Inputs/input2.yaml -o %t-input2.o # RUN: llvm-as %S/Inputs/x86_64-osx.ll -o %t-x86_64.bc diff --git a/llvm/test/tools/llvm-libtool-darwin/universal-object-flattening.test b/llvm/test/tools/llvm-libtool-darwin/universal-object-flattening.test --- a/llvm/test/tools/llvm-libtool-darwin/universal-object-flattening.test +++ b/llvm/test/tools/llvm-libtool-darwin/universal-object-flattening.test @@ -1,5 +1,6 @@ ## This test checks that a universal object file is flattened correctly. +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %s -o %t-universal.o # RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o # RUN: yaml2obj %S/Inputs/input2.yaml -o %t-input2.o 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 @@ -1,3 +1,4 @@ +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %p/Inputs/i386-slice.yaml -o %t-i386.o # RUN: yaml2obj %p/Inputs/x86_64-slice.yaml -o %t-x86_64.o # RUN: yaml2obj %p/Inputs/i386-x86_64-universal.yaml -o %t-universal.o diff --git a/llvm/test/tools/llvm-nm/X86/archive-no-llvm-bc.test b/llvm/test/tools/llvm-nm/X86/archive-no-llvm-bc.test --- a/llvm/test/tools/llvm-nm/X86/archive-no-llvm-bc.test +++ b/llvm/test/tools/llvm-nm/X86/archive-no-llvm-bc.test @@ -1,3 +1,4 @@ +; RUN: export "OBJECT_MODE=any" ; RUN: rm -rf %t && mkdir -p %t ; RUN: grep -v "module asm" %s | llvm-as -o %t/embedded.bc ; RUN: llc -I=%t -filetype=obj -o %t/obj.o %s 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 @@ -1,6 +1,7 @@ ## Test the "-X" option. ## The option specifies the type of object file to examine. +# RUN: export "OBJECT_MODE=any" # RUN: llvm-as -o %t32.bc %p/Inputs/bitcode-sym32.ll # RUN: llvm-as -o %t64.bc %p/Inputs/bitcode-sym64.ll diff --git a/llvm/test/tools/llvm-objcopy/ELF/basic-archive-copy.test b/llvm/test/tools/llvm-objcopy/ELF/basic-archive-copy.test --- a/llvm/test/tools/llvm-objcopy/ELF/basic-archive-copy.test +++ b/llvm/test/tools/llvm-objcopy/ELF/basic-archive-copy.test @@ -1,3 +1,4 @@ +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %s -o %t # RUN: rm -f %t.a diff --git a/llvm/test/tools/llvm-objcopy/ELF/deterministic-archive.test b/llvm/test/tools/llvm-objcopy/ELF/deterministic-archive.test --- a/llvm/test/tools/llvm-objcopy/ELF/deterministic-archive.test +++ b/llvm/test/tools/llvm-objcopy/ELF/deterministic-archive.test @@ -1,3 +1,4 @@ +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %s -o %t.o # Create an archive, specifying U so that timestamps/etc. are preserved. diff --git a/llvm/test/tools/llvm-objcopy/ELF/strip-all.test b/llvm/test/tools/llvm-objcopy/ELF/strip-all.test --- a/llvm/test/tools/llvm-objcopy/ELF/strip-all.test +++ b/llvm/test/tools/llvm-objcopy/ELF/strip-all.test @@ -1,3 +1,4 @@ +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %s -o %t # RUN: cp %t %t3 # RUN: llvm-objcopy --strip-all %t %t2 diff --git a/llvm/test/tools/llvm-objcopy/ELF/strip-debug.test b/llvm/test/tools/llvm-objcopy/ELF/strip-debug.test --- a/llvm/test/tools/llvm-objcopy/ELF/strip-debug.test +++ b/llvm/test/tools/llvm-objcopy/ELF/strip-debug.test @@ -1,3 +1,4 @@ +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %s -o %t # RUN: cp %t %t3 # RUN: llvm-objcopy --strip-debug %t %t2 diff --git a/llvm/test/tools/llvm-objcopy/MachO/archive-format.test b/llvm/test/tools/llvm-objcopy/MachO/archive-format.test --- a/llvm/test/tools/llvm-objcopy/MachO/archive-format.test +++ b/llvm/test/tools/llvm-objcopy/MachO/archive-format.test @@ -2,6 +2,7 @@ ## Make sure the darwin format specifics are preserved when updating archives. +# RUN: export "OBJECT_MODE=any" # RUN: rm -rf %t && mkdir -p %t # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %p/Inputs/macho.64.s -o %t/dup.o # RUN: llvm-ar --format=darwin crD %t/lib.a %t/dup.o %t/dup.o diff --git a/llvm/test/tools/llvm-objdump/X86/disassemble-archive-with-source.ll b/llvm/test/tools/llvm-objdump/X86/disassemble-archive-with-source.ll --- a/llvm/test/tools/llvm-objdump/X86/disassemble-archive-with-source.ll +++ b/llvm/test/tools/llvm-objdump/X86/disassemble-archive-with-source.ll @@ -4,6 +4,7 @@ ; the source file ad-hoc in this test, we don't know the path beforehand to ; create the object and archive. +; RUN: export "OBJECT_MODE=any" ; RUN: rm -rf %t && mkdir -p %t/subdir && cd %t ; RUN: echo -e "int foo(int a)\n\n{ return a+1; }" > subdir/a.c ; RUN: sed -e "s,DIRNAME,%/t/subdir," %s | llc --filetype=obj -mtriple=x86_64-pc-linux -o a.o diff --git a/llvm/test/tools/llvm-objdump/X86/warn-missing-disasm-func.test b/llvm/test/tools/llvm-objdump/X86/warn-missing-disasm-func.test --- a/llvm/test/tools/llvm-objdump/X86/warn-missing-disasm-func.test +++ b/llvm/test/tools/llvm-objdump/X86/warn-missing-disasm-func.test @@ -1,5 +1,6 @@ ## Warn if --disassemble-symbols specifies an unknown symbol. +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj -o %t.o %s # RUN: rm -f %t.a # RUN: llvm-ar qc %t.a %t.o %t.o diff --git a/llvm/test/tools/llvm-objdump/all-headers.test b/llvm/test/tools/llvm-objdump/all-headers.test --- a/llvm/test/tools/llvm-objdump/all-headers.test +++ b/llvm/test/tools/llvm-objdump/all-headers.test @@ -1,3 +1,4 @@ +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %s -o %t # RUN: llvm-objdump --all-headers %t | FileCheck %s # RUN: llvm-objdump -x %t | FileCheck %s diff --git a/llvm/test/tools/llvm-objdump/warn-missing-section.test b/llvm/test/tools/llvm-objdump/warn-missing-section.test --- a/llvm/test/tools/llvm-objdump/warn-missing-section.test +++ b/llvm/test/tools/llvm-objdump/warn-missing-section.test @@ -1,6 +1,8 @@ ## This test checks the warning message when no user specified sections are ## found in the object file. +# RUN: export "OBJECT_MODE=any" + ## Test relocatable file. # RUN: yaml2obj --docnum=1 %s -o %t.1.o # RUN: yaml2obj --docnum=2 %s -o %t.2.o diff --git a/llvm/test/tools/llvm-ranlib/D-flag.test b/llvm/test/tools/llvm-ranlib/D-flag.test --- a/llvm/test/tools/llvm-ranlib/D-flag.test +++ b/llvm/test/tools/llvm-ranlib/D-flag.test @@ -1,6 +1,7 @@ ## Test the -D and -U flags of llvm-ranlib ## Create an archive with timestamps but without symbol table ## Important: all `llvm-ar tv` calls must use TZ=UTC to produce identical values +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %S/../llvm-ar/Inputs/add-lib1.yaml -o %t.o # RUN: env TZ=UTC touch -t 200001020304 %t.o # RUN: rm -f %t.a %t-no-index.a && llvm-ar cqSU %t-no-index.a %t.o diff --git a/llvm/test/tools/llvm-readobj/ELF/file-summary-json.test b/llvm/test/tools/llvm-readobj/ELF/file-summary-json.test --- a/llvm/test/tools/llvm-readobj/ELF/file-summary-json.test +++ b/llvm/test/tools/llvm-readobj/ELF/file-summary-json.test @@ -1,5 +1,6 @@ ## Test how we output JSON file summaries. +# RUN: export "OBJECT_MODE=any" # RUN: rm -rf %t.dir # RUN: mkdir -p %t.dir # RUN: yaml2obj %s -o %t.dir/obj diff --git a/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test b/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test --- a/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test +++ b/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test @@ -1,6 +1,7 @@ ## Check that we correctly display the contents of the .stack_sizes section ## in a relocatable object file. +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj --docnum=1 %s -o %t01 # RUN: llvm-readelf --stack-sizes %t01 \ # RUN: | FileCheck %s --check-prefix=RELOC-GNU --strict-whitespace --match-full-lines diff --git a/llvm/test/tools/llvm-readobj/ELF/wrong-shstrtab-type.test b/llvm/test/tools/llvm-readobj/ELF/wrong-shstrtab-type.test --- a/llvm/test/tools/llvm-readobj/ELF/wrong-shstrtab-type.test +++ b/llvm/test/tools/llvm-readobj/ELF/wrong-shstrtab-type.test @@ -2,7 +2,7 @@ ## a .shstrtab section does not have a SHT_STRTAB type. ## Check we report only one warning for the issue for each input object. - +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %s -o %t1 # RUN: llvm-readobj -S %t1 2>&1 | FileCheck %s -DFILE=%t1 --implicit-check-not warning --check-prefix LLVM # RUN: llvm-readelf -S %t1 2>&1 | FileCheck %s -DFILE=%t1 --implicit-check-not warning --check-prefix GNU diff --git a/llvm/test/tools/llvm-readobj/archive.test b/llvm/test/tools/llvm-readobj/archive.test --- a/llvm/test/tools/llvm-readobj/archive.test +++ b/llvm/test/tools/llvm-readobj/archive.test @@ -2,6 +2,7 @@ ## Show that dumping operations apply to all members in an archive. +# RUN: export "OBJECT_MODE=any" # RUN: rm -f %t.a # RUN: rm -rf %t.dir # RUN: mkdir -p %t.dir diff --git a/llvm/test/tools/llvm-readobj/thin-archive.test b/llvm/test/tools/llvm-readobj/thin-archive.test --- a/llvm/test/tools/llvm-readobj/thin-archive.test +++ b/llvm/test/tools/llvm-readobj/thin-archive.test @@ -1,3 +1,4 @@ +# RUN: export "OBJECT_MODE=any" # RUN: rm -f %t.a # RUN: rm -rf %t # RUN: mkdir -p %t 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 @@ -1,5 +1,6 @@ ## Show how llvm-size behaves when passed in an archive. +# RUN: export "OBJECT_MODE=any" # RUN: yaml2obj %s --docnum=1 -o %t1 # RUN: yaml2obj %s --docnum=2 -o %t2 diff --git a/llvm/test/tools/llvm-size/totals.test b/llvm/test/tools/llvm-size/totals.test --- a/llvm/test/tools/llvm-size/totals.test +++ b/llvm/test/tools/llvm-size/totals.test @@ -1,5 +1,6 @@ ## Show that llvm-size prints the total sizes when --totals is specified. +# RUN: export "OBJECT_MODE=any" # RUN: rm -f %t.a # RUN: yaml2obj %s --docnum=1 -o %t.o # RUN: yaml2obj %s --docnum=2 -o %t2.o diff --git a/llvm/test/tools/llvm-tli-checker/multi-file.yaml b/llvm/test/tools/llvm-tli-checker/multi-file.yaml --- a/llvm/test/tools/llvm-tli-checker/multi-file.yaml +++ b/llvm/test/tools/llvm-tli-checker/multi-file.yaml @@ -4,6 +4,7 @@ ## # REQUIRES: x86-registered-target # +# RUN: export "OBJECT_MODE=any" # RUN: mkdir -p %t.dir # RUN: yaml2obj --docnum=1 %s -o %t.dir/file1 # RUN: yaml2obj --docnum=2 %s -o %t.dir/file2 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 @@ -18,10 +18,14 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ArchiveWriter.h" +#include "llvm/Object/COFFImportFile.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/SymbolicFile.h" +#include "llvm/Object/TapiFile.h" +#include "llvm/Object/Wasm.h" #include "llvm/Object/XCOFFObjectFile.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/CommandLine.h" @@ -55,6 +59,7 @@ #endif using namespace llvm; +using namespace llvm::object; // The name this program was invoked as. static StringRef ToolName; @@ -90,6 +95,7 @@ =windows - windows --thin - create a thin archive --version - print the version and exit + -X{32|64|32_64|any} - object mode (only for AIX OS) @ - read options from OPERATIONS: @@ -208,6 +214,10 @@ CreateSymTab ///< Create a symbol table in an existing archive }; +enum class BitModeTy { Bit32, Bit64, Bit32_64, Any, Unknown }; + +static BitModeTy BitMode = BitModeTy::Bit32; + // Modifiers to follow operation to vary behavior static bool AddAfter = false; ///< 'a' modifier static bool AddBefore = false; ///< 'b' modifier @@ -607,6 +617,61 @@ llvm_unreachable("Missing entry in covered switch."); } +static bool is64BitSymbolicFile(SymbolicFile &Obj) { + if (auto *IRObj = dyn_cast(&Obj)) + return Triple(IRObj->getTargetTriple()).isArch64Bit(); + if (isa(Obj) || isa(Obj)) + return false; + if (XCOFFObjectFile *XCOFFObj = dyn_cast(&Obj)) + return XCOFFObj->is64Bit(); + if (isa(Obj)) + return false; + if (TapiFile *Tapi = dyn_cast(&Obj)) + return Tapi->is64Bit(); + if (MachOObjectFile *MachO = dyn_cast(&Obj)) + return MachO->is64Bit(); + return cast(Obj).getBytesInAddress() == 8; +} + +static bool isValidInBitMode(Binary &Bin) { + if (BitMode == BitModeTy::Bit32_64 || BitMode == BitModeTy::Any) + return true; + + if (SymbolicFile *SymFile = dyn_cast(&Bin)) { + bool Is64Bit = is64BitSymbolicFile(*SymFile); + if ((Is64Bit && (BitMode == BitModeTy::Bit32)) || + (!Is64Bit && (BitMode == BitModeTy::Bit64))) + return false; + } + // In AIX "ar", non-object files are always considered to have a valid bit + // mode. + return true; +} + +Expected> getAsBinary(const NewArchiveMember &NM) { + auto BinaryOrErr = createBinary(NM.Buf->getMemBufferRef()); + if (BinaryOrErr) + return std::move(*BinaryOrErr); + return BinaryOrErr.takeError(); +} + +Expected> getAsBinary(const Archive::Child &C) { + return C.getAsBinary(); +} + +template static bool isValidInBitMode(const A &Member) { + if (object::Archive::getDefaultKindForHost() != object::Archive::K_AIXBIG) + return true; + Expected> BinOrErr = getAsBinary(Member); + // In AIX "ar", If there is member which is not a object file, it also always + // be consider as valid bit mode. + if (!BinOrErr) { + consumeError(BinOrErr.takeError()); + return true; + } + return isValidInBitMode(*BinOrErr.get()); +} + static void performReadOperation(ArchiveOperation Operation, object::Archive *OldArchive) { if (Operation == Extract && OldArchive->isThin()) @@ -621,12 +686,17 @@ failIfError(NameOrErr.takeError()); StringRef Name = NameOrErr.get(); + // Check whether the object mode is permit to output. + if (!isValidInBitMode(C)) + continue; + if (Filter) { auto I = find_if(Members, [Name](StringRef Path) { return comparePaths(Name, Path); }); if (I == Members.end()) continue; + if (CountParam && ++MemberCount[Name] != CountParam) continue; Members.erase(I); @@ -697,8 +767,7 @@ Members.push_back(std::move(*NMOrErr)); } -static void addMember(std::vector &Members, - StringRef FileName, bool FlattenArchive = false) { +static NewArchiveMember getArchiveMember(StringRef FileName) { Expected NMOrErr = NewArchiveMember::getFile(FileName, Deterministic); failIfError(NMOrErr.takeError(), FileName); @@ -718,9 +787,24 @@ PathOrErr ? *PathOrErr : sys::path::convert_to_slash(FileName)); } } + return std::move(*NMOrErr); +} + +static void addMember(std::vector &Members, + NewArchiveMember &NM) { + Members.push_back(std::move(NM)); +} + +static void addMember(std::vector &Members, + StringRef FileName, bool FlattenArchive = false) { + NewArchiveMember NM = getArchiveMember(FileName); + if (!isValidInBitMode(NM)) { + outs() << FileName << " is not valid with the current object file mode.\n"; + return; + } if (FlattenArchive && - identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) { + identify_magic(NM.Buf->getBuffer()) == file_magic::archive) { object::Archive &Lib = readLibrary(FileName); // When creating thin archives, only flatten if the member is also thin. if (!Thin || Lib.isThin()) { @@ -732,7 +816,7 @@ return; } } - Members.push_back(std::move(*NMOrErr)); + Members.push_back(std::move(NM)); } enum InsertAction { @@ -748,6 +832,9 @@ StringRef Name, std::vector::iterator &Pos, StringMap &MemberCount) { + if (!isValidInBitMode(Member)) + return IA_AddOldMember; + if (Operation == QuickAppend || Members.empty()) return IA_AddOldMember; auto MI = find_if( @@ -824,17 +911,33 @@ case IA_AddOldMember: addChildMember(Ret, Child, /*FlattenArchive=*/Thin); break; - case IA_AddNewMember: - addMember(Ret, *MemberI); - break; + case IA_AddNewMember: { + NewArchiveMember NM = getArchiveMember(*MemberI); + if (isValidInBitMode(NM)) + addMember(Ret, NM); + else { + // If a new member is not a valid object mode, add old member back. + outs() << *MemberI + << " is not valid with the current object file mode\n"; + addChildMember(Ret, Child, /*FlattenArchive=*/Thin); + } + } break; case IA_Delete: break; case IA_MoveOldMember: addChildMember(Moved, Child, /*FlattenArchive=*/Thin); break; - case IA_MoveNewMember: - addMember(Moved, *MemberI); - break; + case IA_MoveNewMember: { + NewArchiveMember NM = getArchiveMember(*MemberI); + if (isValidInBitMode(NM)) + addMember(Moved, NM); + else { + //If a new member is not a valid object mode, move old member. + outs() << *MemberI + << " is not valid with the current object file mode\n"; + addChildMember(Moved, Child, /*FlattenArchive=*/Thin); + } + } break; } // When processing elements with the count param, we need to preserve the // full members list when iterating over all archive members. For @@ -1122,6 +1225,15 @@ return false; } +static BitModeTy getBitMode(const char *RawBitMode) { + return StringSwitch(RawBitMode) + .Case("32", BitModeTy::Bit32) + .Case("64", BitModeTy::Bit64) + .Case("32_64", BitModeTy::Bit32_64) + .Case("any", BitModeTy::Any) + .Default(BitModeTy::Unknown); +} + static const char *matchFlagWithArg(StringRef Expected, ArrayRef::iterator &ArgIt, ArrayRef Args) { @@ -1171,6 +1283,14 @@ cl::ExpandResponseFiles(Saver, getRspQuoting(makeArrayRef(argv, argc)), Argv); + // 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")); + if (BitMode == BitModeTy::Unknown) + BitMode = BitModeTy::Bit32; + } + for (ArrayRef::iterator ArgIt = Argv.begin(); ArgIt != Argv.end(); ++ArgIt) { const char *Match = nullptr; @@ -1220,6 +1340,19 @@ matchFlagWithArg("rsp-quoting", ArgIt, Argv)) continue; + if (strncmp(*ArgIt, "-X", 2) == 0) { + if (object::Archive::getDefaultKindForHost() == + object::Archive::K_AIXBIG) { + Match = *(*ArgIt + 2) != '\0' ? *ArgIt + 2 : *(++ArgIt); + BitMode = getBitMode(Match); + if (BitMode == BitModeTy::Unknown) + fail(std::string("invalid bit mode: ") + Match); + continue; + } else { + fail(Twine(*ArgIt) + " option not supported on non AIX OS"); + } + } + Options += *ArgIt + 1; }