diff --git a/llvm/docs/CommandGuide/llvm-ranlib.rst b/llvm/docs/CommandGuide/llvm-ranlib.rst index ec4a1335c19cf..5cc5a6a839d1c 100644 --- a/llvm/docs/CommandGuide/llvm-ranlib.rst +++ b/llvm/docs/CommandGuide/llvm-ranlib.rst @@ -6,13 +6,13 @@ llvm-ranlib - generates an archive index SYNOPSIS -------- -:program:`llvm-ranlib` [*options*] +:program:`llvm-ranlib` [*options*] *archive...* DESCRIPTION ----------- :program:`llvm-ranlib` is an alias for the :doc:`llvm-ar ` tool that -generates an index for an archive. It can be used as a replacement for GNU's +generates an index for one or more archives. It can be used as a replacement for GNU's :program:`ranlib` tool. Running :program:`llvm-ranlib` is equivalent to running ``llvm-ar s``. diff --git a/llvm/test/tools/llvm-ranlib/D-flag.test b/llvm/test/tools/llvm-ranlib/D-flag.test index f6a3ec9cc272f..49d0bd6ae8110 100644 --- a/llvm/test/tools/llvm-ranlib/D-flag.test +++ b/llvm/test/tools/llvm-ranlib/D-flag.test @@ -22,9 +22,11 @@ # RUN: cp %t-no-index.a %t.a && llvm-ranlib -UUD %t.a # RUN: env TZ=UTC llvm-ar tv %t.a | FileCheck %s --check-prefix=DETERMINISTIC-VALUES -## Check arguments can be passed before and after the file name -# RUN: cp %t-no-index.a %t.a && llvm-ranlib -U %t.a -D -U +## Check multiple archives can be specified and arguments can be specified anywhere. +# RUN: cp %t-no-index.a %t.a && cp %t-no-index.a %t2.a +# RUN: llvm-ranlib -U %t.a -D %t2.a -U # RUN: env TZ=UTC llvm-ar tv %t.a | FileCheck %s --check-prefix=REAL-VALUES +# RUN: env TZ=UTC llvm-ar tv %t2.a | FileCheck %s --check-prefix=REAL-VALUES ## Check that the -D/-U option is only accepted with a single dash. This matches ## the GNU ranlib behaviour. diff --git a/llvm/test/tools/llvm-ranlib/error-opening-permission.test b/llvm/test/tools/llvm-ranlib/error-opening-permission.test new file mode 100644 index 0000000000000..1b1bb0def78d7 --- /dev/null +++ b/llvm/test/tools/llvm-ranlib/error-opening-permission.test @@ -0,0 +1,41 @@ +## Unsupported on windows as marking files "unreadable" is non-trivial on windows. +# UNSUPPORTED: system-windows + +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: yaml2obj 1.yaml -o 1.o +# RUN: llvm-ar rcS a.a 1.o +# RUN: cp a.a b.a && cp a.a c.a && cp a.a d.a +# RUN: chmod 100 c.a +# RUN: not llvm-ranlib a.a b.a c.a d.a 2>&1 | FileCheck %s --check-prefix=NO-PERMISSION -DMSG=%errc_EACCES + +# NO-PERMISSION: error: unable to open 'c.a': [[MSG]] +# NO-PERMISSION-NOT: {{.}} + +## The archives before c.a (a.a and b.a) have been processed. +# RUN: llvm-nm --print-armap a.a | FileCheck %s +# RUN: cmp a.a b.a +## The others (c.a and d.a) do not have a symbol table. +# RUN: chmod 700 c.a +# RUN: llvm-nm --print-armap c.a | FileCheck %s --check-prefix=NOMAP +# RUN: cmp c.a d.a + +# CHECK: Archive map +# CHECK-NEXT: foo in 1.o +# CHECK-EMPTY: + +# NOMAP-NOT: Archive map + +#--- 1.yaml +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS +Symbols: + - Name: foo + Binding: STB_GLOBAL + Section: .text diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp index 960c7a3d8713e..4ffc5cf337a24 100644 --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -68,9 +68,9 @@ static StringRef ToolName; static StringRef Stem; static void printRanLibHelp(StringRef ToolName) { - outs() << "OVERVIEW: LLVM Ranlib\n\n" - << "This program generates an index to speed access to archives\n\n" - << "USAGE: " + ToolName + " \n\n" + outs() << "OVERVIEW: LLVM ranlib\n\n" + << "Generate an index for archives\n\n" + << "USAGE: " + ToolName + " archive...\n\n" << "OPTIONS:\n" << " -h --help - Display available options\n" << " -v --version - Display the version of this program\n" @@ -1406,7 +1406,7 @@ static int ar_main(int argc, char **argv) { } static int ranlib_main(int argc, char **argv) { - bool ArchiveSpecified = false; + std::vector Archives; for (int i = 1; i < argc; ++i) { StringRef arg(argv[i]); if (handleGenericOption(arg)) { @@ -1431,16 +1431,17 @@ static int ranlib_main(int argc, char **argv) { arg = arg.drop_front(1); } } else { - if (ArchiveSpecified) - fail("exactly one archive should be specified"); - ArchiveSpecified = true; - ArchiveName = arg.str(); + Archives.push_back(arg); } } - if (!ArchiveSpecified) { - badUsage("an archive name must be specified"); + + for (StringRef Archive : Archives) { + ArchiveName = Archive.str(); + performOperation(CreateSymTab); } - return performOperation(CreateSymTab); + if (Archives.empty()) + badUsage("an archive name must be specified"); + return 0; } int llvm_ar_main(int argc, char **argv) {