[llvm-objcopy] Add support for response files in llvm-strip and llvm-objcopy
Summary: Addresses https://bugs.llvm.org/show_bug.cgi?id=42671
Reviewers: jhenderson, espindola, alexshap, rupprecht
Reviewed By: jhenderson
Subscribers: seiya, emaste, arichardson, jakehehrlich, MaskRay, abrachet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65372
llvm-svn: 371911
diff --git a/llvm/docs/CommandGuide/llvm-objcopy.rst b/llvm/docs/CommandGuide/llvm-objcopy.rst
index 0472117..401bc5b 100644
--- a/llvm/docs/CommandGuide/llvm-objcopy.rst
+++ b/llvm/docs/CommandGuide/llvm-objcopy.rst
@@ -129,6 +129,10 @@
Display the version of this program.
+.. option:: @<FILE>
+
+ Read command-line options and commands from response file `<FILE>`.
+
COFF-SPECIFIC OPTIONS
---------------------
diff --git a/llvm/docs/CommandGuide/llvm-strip.rst b/llvm/docs/CommandGuide/llvm-strip.rst
index a4f497a..546a0a2 100644
--- a/llvm/docs/CommandGuide/llvm-strip.rst
+++ b/llvm/docs/CommandGuide/llvm-strip.rst
@@ -104,6 +104,10 @@
Display the version of this program.
+.. option:: @<FILE>
+
+ Read command-line options and commands from response file `<FILE>`.
+
COFF-SPECIFIC OPTIONS
---------------------
diff --git a/llvm/test/tools/llvm-objcopy/ELF/help-message.test b/llvm/test/tools/llvm-objcopy/ELF/help-message.test
index 2f199a3..0a093fe 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/help-message.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/help-message.test
@@ -14,6 +14,10 @@
# OBJCOPY-USAGE: USAGE: llvm-objcopy
+# OBJCOPY-USAGE: @FILE
+
# STRIP-USAGE: USAGE: llvm-strip
+# STRIP-USAGE: @FILE
+
# UNKNOWN-ARG: unknown argument '{{-+}}abcabc'
# NO-INPUT-FILES: no input file specified
diff --git a/llvm/test/tools/llvm-objcopy/ELF/response-file.test b/llvm/test/tools/llvm-objcopy/ELF/response-file.test
new file mode 100644
index 0000000..45784cc
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/response-file.test
@@ -0,0 +1,20 @@
+## Check that we support response files.
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo "--strip-debug %t.o" > %t-response
+# RUN: llvm-objcopy @%t-response %t2.o
+# RUN: llvm-strip @%t-response
+
+# RUN: llvm-readobj -S %t.o | FileCheck %s
+# RUN: cmp %t.o %t2.o
+
+# CHECK-NOT: .debug_foo
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .debug_foo
+ Type: SHT_PROGBITS
diff --git a/llvm/tools/llvm-objcopy/CopyConfig.cpp b/llvm/tools/llvm-objcopy/CopyConfig.cpp
index b3a62a3..d235f23 100644
--- a/llvm/tools/llvm-objcopy/CopyConfig.cpp
+++ b/llvm/tools/llvm-objcopy/CopyConfig.cpp
@@ -410,6 +410,16 @@
return Result;
}
+static void printHelp(const opt::OptTable &OptTable, raw_ostream &OS,
+ StringRef ToolName) {
+ OptTable.PrintHelp(OS, (ToolName + " input [output]").str().c_str(),
+ (ToolName + " tool").str().c_str());
+ // TODO: Replace this with libOption call once it adds extrahelp support.
+ // The CommandLine library has a cl::extrahelp class to support this,
+ // but libOption does not have that yet.
+ OS << "\nPass @FILE as argument to read options from FILE.\n";
+}
+
// ParseObjcopyOptions returns the config and sets the input arguments. If a
// help flag is set then ParseObjcopyOptions will print the help messege and
// exit.
@@ -421,12 +431,12 @@
T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
if (InputArgs.size() == 0) {
- T.PrintHelp(errs(), "llvm-objcopy input [output]", "objcopy tool");
+ printHelp(T, errs(), "llvm-objcopy");
exit(1);
}
if (InputArgs.hasArg(OBJCOPY_help)) {
- T.PrintHelp(outs(), "llvm-objcopy input [output]", "objcopy tool");
+ printHelp(T, outs(), "llvm-objcopy");
exit(0);
}
@@ -790,12 +800,12 @@
T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
if (InputArgs.size() == 0) {
- T.PrintHelp(errs(), "llvm-strip [options] file...", "strip tool");
+ printHelp(T, errs(), "llvm-strip");
exit(1);
}
if (InputArgs.hasArg(STRIP_help)) {
- T.PrintHelp(outs(), "llvm-strip [options] file...", "strip tool");
+ printHelp(T, outs(), "llvm-strip");
exit(0);
}
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index 9c0145f..e9094f2 100644
--- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -29,6 +29,7 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
@@ -36,6 +37,7 @@
#include "llvm/Support/Memory.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/StringSaver.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -310,9 +312,25 @@
InitLLVM X(argc, argv);
ToolName = argv[0];
bool IsStrip = sys::path::stem(ToolName).contains("strip");
+
+ // Expand response files.
+ // TODO: Move these lines, which are copied from lib/Support/CommandLine.cpp,
+ // into a separate function in the CommandLine library and call that function
+ // here. This is duplicated code.
+ SmallVector<const char *, 20> NewArgv(argv, argv + argc);
+ BumpPtrAllocator A;
+ StringSaver Saver(A);
+ cl::ExpandResponseFiles(Saver,
+ Triple(sys::getProcessTriple()).isOSWindows()
+ ? cl::TokenizeWindowsCommandLine
+ : cl::TokenizeGNUCommandLine,
+ NewArgv);
+
+ auto Args = makeArrayRef(NewArgv).drop_front();
+
Expected<DriverConfig> DriverConfig =
- IsStrip ? parseStripOptions(makeArrayRef(argv + 1, argc), reportWarning)
- : parseObjcopyOptions(makeArrayRef(argv + 1, argc));
+ IsStrip ? parseStripOptions(Args, reportWarning)
+ : parseObjcopyOptions(Args);
if (!DriverConfig) {
logAllUnhandledErrors(DriverConfig.takeError(),
WithColor::error(errs(), ToolName));