--- /dev/null
+# RUN: yaml2obj %s > %t.o
+
+# Run llvm-strip normally. This will create a stripped object file for later
+# tests so we only have to run FileCheck on it once.
+# RUN: cp %t.o %t.1.o
+# RUN: llvm-strip --keep-symbol=foo %t.1.o -o %t.stripped.o
+# RUN: llvm-readobj -symbols %t.stripped.o | FileCheck %s
+
+# llvm-strip on two files:
+# RUN: cp %t.o %t.1.o
+# RUN: cp %t.o %t.2.o
+# RUN: llvm-strip --keep-symbol=foo %t.1.o %t.2.o
+# RUN: cmp %t.1.o %t.stripped.o
+# RUN: cmp %t.2.o %t.stripped.o
+
+# llvm-strip on three files:
+# RUN: cp %t.o %t.1.o
+# RUN: cp %t.o %t.2.o
+# RUN: cp %t.o %t.3.o
+# RUN: llvm-strip --keep-symbol=foo %t.1.o %t.2.o %t.3.o
+# RUN: cmp %t.1.o %t.stripped.o
+# RUN: cmp %t.2.o %t.stripped.o
+# RUN: cmp %t.3.o %t.stripped.o
+
+# -o cannot be used with multiple input files
+# RUN: cp %t.o %t.1.o
+# RUN: cp %t.o %t.2.o
+# RUN: not llvm-strip --keep-symbol=foo -o %t.stripped.o %t.1.o %t.2.o 2>&1 \
+# RUN: | FileCheck %s --check-prefix=BAD-O-FLAG
+
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+Symbols:
+ Local:
+ - Name: foo
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x1234
+ Size: 8
+ - Name: bar
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x5678
+ Size: 8
+
+# CHECK: Symbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name:
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: foo
+# CHECK-NEXT: Value: 0x1234
+# CHECK-NEXT: Size: 8
+# CHECK-NEXT: Binding: Local
+# CHECK-NEXT: Type: Function
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .text
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+# BAD-O-FLAG: Multiple input files cannot be used in combination with -o.
Optional<uint64_t> NewFlags;
};
+// Configuration for copying/stripping a single file.
struct CopyConfig {
// Main input/output options
StringRef InputFilename;
bool Weaken = false;
};
+// Configuration for the overall invocation of this tool. When invoked as
+// objcopy, will always contain exactly one CopyConfig. When invoked as strip,
+// will contain one or more CopyConfigs.
+struct DriverConfig {
+ SmallVector<CopyConfig, 1> CopyConfigs;
+};
+
using SectionPred = std::function<bool(const SectionBase &Sec)>;
enum SectionFlag {
// ParseObjcopyOptions returns the config and sets the input arguments. If a
// help flag is set then ParseObjcopyOptions will print the help messege and
// exit.
-static CopyConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
+static DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
ObjcopyOptTable T;
unsigned MissingArgumentIndex, MissingArgumentCount;
llvm::opt::InputArgList InputArgs =
Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);
- return Config;
+ DriverConfig DC;
+ DC.CopyConfigs.push_back(std::move(Config));
+ return DC;
}
// ParseStripOptions returns the config and sets the input arguments. If a
// help flag is set then ParseStripOptions will print the help messege and
// exit.
-static CopyConfig parseStripOptions(ArrayRef<const char *> ArgsArr) {
+static DriverConfig parseStripOptions(ArrayRef<const char *> ArgsArr) {
StripOptTable T;
unsigned MissingArgumentIndex, MissingArgumentCount;
llvm::opt::InputArgList InputArgs =
if (Positional.empty())
error("No input file specified");
- if (Positional.size() > 1)
- error("Support for multiple input files is not implemented yet");
+ if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
+ error("Multiple input files cannot be used in combination with -o");
CopyConfig Config;
- Config.InputFilename = Positional[0];
- Config.OutputFilename =
- InputArgs.getLastArgValue(STRIP_output, Positional[0]);
-
Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
Config.DiscardAll = InputArgs.hasArg(STRIP_discard_all);
Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates);
- return Config;
+ DriverConfig DC;
+ if (Positional.size() == 1) {
+ Config.InputFilename = Positional[0];
+ Config.OutputFilename =
+ InputArgs.getLastArgValue(STRIP_output, Positional[0]);
+ DC.CopyConfigs.push_back(std::move(Config));
+ } else {
+ for (const char *Filename : Positional) {
+ Config.InputFilename = Filename;
+ Config.OutputFilename = Filename;
+ DC.CopyConfigs.push_back(Config);
+ }
+ }
+
+ return DC;
}
int main(int argc, char **argv) {
InitLLVM X(argc, argv);
ToolName = argv[0];
- CopyConfig Config;
+ DriverConfig DriverConfig;
if (sys::path::stem(ToolName).endswith_lower("strip"))
- Config = parseStripOptions(makeArrayRef(argv + 1, argc));
+ DriverConfig = parseStripOptions(makeArrayRef(argv + 1, argc));
else
- Config = parseObjcopyOptions(makeArrayRef(argv + 1, argc));
- executeElfObjcopy(Config);
+ DriverConfig = parseObjcopyOptions(makeArrayRef(argv + 1, argc));
+ for (const CopyConfig &CopyConfig : DriverConfig.CopyConfigs)
+ executeElfObjcopy(CopyConfig);
}