aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/bad-output-format.test2
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/binary-input-error.test4
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/compress-and-decompress-debug-sections-error.test2
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-invalid-format.test2
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/input-output-target.test2
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/rename-section-flag.test2
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test4
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/set-section-flags.test2
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/strip-multiple-files.test2
-rw-r--r--llvm/tools/llvm-objcopy/CopyConfig.cpp203
-rw-r--r--llvm/tools/llvm-objcopy/CopyConfig.h5
-rw-r--r--llvm/tools/llvm-objcopy/llvm-objcopy.cpp58
12 files changed, 188 insertions, 100 deletions
diff --git a/llvm/test/tools/llvm-objcopy/ELF/bad-output-format.test b/llvm/test/tools/llvm-objcopy/ELF/bad-output-format.test
index e01d955111b8..f190a16a2b5b 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/bad-output-format.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/bad-output-format.test
@@ -10,4 +10,4 @@ FileHeader:
Type: ET_EXEC
Machine: EM_386
-# BAD-OUTPUT-FORMAT: Invalid output format: 'xyz'.
+# BAD-OUTPUT-FORMAT: Invalid output format: 'xyz'
diff --git a/llvm/test/tools/llvm-objcopy/ELF/binary-input-error.test b/llvm/test/tools/llvm-objcopy/ELF/binary-input-error.test
index 820e569ad7b4..4b7736e19005 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/binary-input-error.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/binary-input-error.test
@@ -6,5 +6,5 @@
# RUN: not llvm-objcopy -I binary -B xyz %t.txt %t.o 2>&1 \
# RUN: | FileCheck %s --check-prefix=BAD-BINARY-ARCH
-# MISSING-BINARY-ARCH: Specified binary input without specifiying an architecture.
-# BAD-BINARY-ARCH: Invalid architecture: 'xyz'.
+# MISSING-BINARY-ARCH: Specified binary input without specifiying an architecture
+# BAD-BINARY-ARCH: Invalid architecture: 'xyz'
diff --git a/llvm/test/tools/llvm-objcopy/ELF/compress-and-decompress-debug-sections-error.test b/llvm/test/tools/llvm-objcopy/ELF/compress-and-decompress-debug-sections-error.test
index 0866e2009e93..aac9bb3042f9 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/compress-and-decompress-debug-sections-error.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/compress-and-decompress-debug-sections-error.test
@@ -3,5 +3,5 @@
# RUN: yaml2obj %p/Inputs/compress-debug-sections.yaml -o %t.o
# RUN: not llvm-objcopy --compress-debug-sections=zlib --decompress-debug-sections %t.o 2>&1 | FileCheck %s
-# CHECK: Cannot specify --compress-debug-sections at the same time as --decompress-debug-sections at the same time.
+# CHECK: Cannot specify --compress-debug-sections at the same time as --decompress-debug-sections at the same time
diff --git a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-invalid-format.test b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-invalid-format.test
index 854dfe26560b..8aa8ab4f2937 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-invalid-format.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-invalid-format.test
@@ -1,5 +1,5 @@
# RUN: yaml2obj %p/Inputs/compress-debug-sections.yaml -o %t.o
# RUN: not llvm-objcopy --compress-debug-sections=zlib-fake %t.o 2>&1 | FileCheck %s
-# CHECK: Invalid or unsupported --compress-debug-sections format: zlib-fake.
+# CHECK: Invalid or unsupported --compress-debug-sections format: zlib-fake
diff --git a/llvm/test/tools/llvm-objcopy/ELF/input-output-target.test b/llvm/test/tools/llvm-objcopy/ELF/input-output-target.test
index 7a7df9fd5039..0661aca7bc92 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/input-output-target.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/input-output-target.test
@@ -19,4 +19,4 @@
# RUN: %t.txt %t.4.txt 2>&1 \
# RUN: | FileCheck %s --check-prefix=BAD-FLAG
-# BAD-FLAG: --target cannot be used with --input-target or --output-target.
+# BAD-FLAG: --target cannot be used with --input-target or --output-target
diff --git a/llvm/test/tools/llvm-objcopy/ELF/rename-section-flag.test b/llvm/test/tools/llvm-objcopy/ELF/rename-section-flag.test
index 75f35af4b301..3215f4abd35d 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/rename-section-flag.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/rename-section-flag.test
@@ -57,4 +57,4 @@ Sections:
# WRITE-NEXT: SHF_WRITE (0x1)
# CHECK-NEXT: ]
-# BAD-FLAG: Unrecognized section flag 'xyzzy'. Flags supported for GNU compatibility: alloc, load, noload, readonly, debug, code, data, rom, share, contents, merge, strings.
+# BAD-FLAG: Unrecognized section flag 'xyzzy'. Flags supported for GNU compatibility: alloc, load, noload, readonly, debug, code, data, rom, share, contents, merge, strings
diff --git a/llvm/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test b/llvm/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test
index 88f7243f4ca7..15ea3aeec161 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test
@@ -10,5 +10,5 @@ FileHeader:
Type: ET_REL
Machine: EM_X86_64
-# SET-FOO: --set-section-flags=.foo conflicts with --rename-section=.foo=.bar.
-# SET-BAR: --set-section-flags=.bar conflicts with --rename-section=.foo=.bar.
+# SET-FOO: --set-section-flags=.foo conflicts with --rename-section=.foo=.bar
+# SET-BAR: --set-section-flags=.bar conflicts with --rename-section=.foo=.bar
diff --git a/llvm/test/tools/llvm-objcopy/ELF/set-section-flags.test b/llvm/test/tools/llvm-objcopy/ELF/set-section-flags.test
index 6fde33e0749f..3af3f1b8b132 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/set-section-flags.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/set-section-flags.test
@@ -65,4 +65,4 @@ Sections:
# BAD-FORMAT: Bad format for --set-section-flags: missing '='
# MULTIPLE-SETS: --set-section-flags set multiple times for section .foo
-# BAD-FLAG: Unrecognized section flag 'xyzzy'. Flags supported for GNU compatibility: alloc, load, noload, readonly, debug, code, data, rom, share, contents, merge, strings.
+# BAD-FLAG: Unrecognized section flag 'xyzzy'. Flags supported for GNU compatibility: alloc, load, noload, readonly, debug, code, data, rom, share, contents, merge, strings
diff --git a/llvm/test/tools/llvm-objcopy/ELF/strip-multiple-files.test b/llvm/test/tools/llvm-objcopy/ELF/strip-multiple-files.test
index 9aef87284436..dcbd57e1f3da 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/strip-multiple-files.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/strip-multiple-files.test
@@ -72,4 +72,4 @@ Symbols:
# CHECK-NEXT: }
# CHECK-NEXT: ]
-# BAD-O-FLAG: Multiple input files cannot be used in combination with -o.
+# BAD-O-FLAG: Multiple input files cannot be used in combination with -o
diff --git a/llvm/tools/llvm-objcopy/CopyConfig.cpp b/llvm/tools/llvm-objcopy/CopyConfig.cpp
index 811f8b753e07..1432b8591cab 100644
--- a/llvm/tools/llvm-objcopy/CopyConfig.cpp
+++ b/llvm/tools/llvm-objcopy/CopyConfig.cpp
@@ -129,15 +129,18 @@ static SectionFlag parseSectionRenameFlag(StringRef SectionName) {
.Default(SectionFlag::SecNone);
}
-static uint64_t parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) {
+static Expected<uint64_t>
+parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) {
SectionFlag ParsedFlags = SectionFlag::SecNone;
for (StringRef Flag : SectionFlags) {
SectionFlag ParsedFlag = parseSectionRenameFlag(Flag);
if (ParsedFlag == SectionFlag::SecNone)
- error("Unrecognized section flag '" + Flag +
- "'. Flags supported for GNU compatibility: alloc, load, noload, "
- "readonly, debug, code, data, rom, share, contents, merge, "
- "strings.");
+ return createStringError(
+ errc::invalid_argument,
+ "Unrecognized section flag '%s'. Flags supported for GNU "
+ "compatibility: alloc, load, noload, readonly, debug, code, data, "
+ "rom, share, contents, merge, strings",
+ Flag.str().c_str());
ParsedFlags |= ParsedFlag;
}
@@ -155,9 +158,10 @@ static uint64_t parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) {
return NewFlags;
}
-static SectionRename parseRenameSectionValue(StringRef FlagValue) {
+static Expected<SectionRename> parseRenameSectionValue(StringRef FlagValue) {
if (!FlagValue.contains('='))
- error("Bad format for --rename-section: missing '='");
+ return createStringError(errc::invalid_argument,
+ "Bad format for --rename-section: missing '='");
// Initial split: ".foo" = ".bar,f1,f2,..."
auto Old2New = FlagValue.split('=');
@@ -169,15 +173,22 @@ static SectionRename parseRenameSectionValue(StringRef FlagValue) {
Old2New.second.split(NameAndFlags, ',');
SR.NewName = NameAndFlags[0];
- if (NameAndFlags.size() > 1)
- SR.NewFlags = parseSectionFlagSet(makeArrayRef(NameAndFlags).drop_front());
+ if (NameAndFlags.size() > 1) {
+ Expected<uint64_t> ParsedFlagSet =
+ parseSectionFlagSet(makeArrayRef(NameAndFlags).drop_front());
+ if (!ParsedFlagSet)
+ return ParsedFlagSet.takeError();
+ SR.NewFlags = *ParsedFlagSet;
+ }
return SR;
}
-static SectionFlagsUpdate parseSetSectionFlagValue(StringRef FlagValue) {
+static Expected<SectionFlagsUpdate>
+parseSetSectionFlagValue(StringRef FlagValue) {
if (!StringRef(FlagValue).contains('='))
- error("Bad format for --set-section-flags: missing '='");
+ return createStringError(errc::invalid_argument,
+ "Bad format for --set-section-flags: missing '='");
// Initial split: ".foo" = "f1,f2,..."
auto Section2Flags = StringRef(FlagValue).split('=');
@@ -187,7 +198,10 @@ static SectionFlagsUpdate parseSetSectionFlagValue(StringRef FlagValue) {
// Flags split: "f1" "f2" ...
SmallVector<StringRef, 6> SectionFlags;
Section2Flags.second.split(SectionFlags, ',');
- SFU.NewFlags = parseSectionFlagSet(SectionFlags);
+ Expected<uint64_t> ParsedFlagSet = parseSectionFlagSet(SectionFlags);
+ if (!ParsedFlagSet)
+ return ParsedFlagSet.takeError();
+ SFU.NewFlags = *ParsedFlagSet;
return SFU;
}
@@ -203,10 +217,11 @@ static const StringMap<MachineInfo> ArchMap{
{"x86-64", {ELF::EM_X86_64, true, true}},
};
-static const MachineInfo &getMachineInfo(StringRef Arch) {
+static Expected<const MachineInfo &> getMachineInfo(StringRef Arch) {
auto Iter = ArchMap.find(Arch);
if (Iter == std::end(ArchMap))
- error("Invalid architecture: '" + Arch + "'");
+ return createStringError(errc::invalid_argument,
+ "Invalid architecture: '%s'", Arch.str().c_str());
return Iter->getValue();
}
@@ -219,21 +234,24 @@ static const StringMap<MachineInfo> OutputFormatMap{
{"elf64-x86-64", {ELF::EM_X86_64, true, true}},
};
-static const MachineInfo &getOutputFormatMachineInfo(StringRef Format) {
+static Expected<const MachineInfo &>
+getOutputFormatMachineInfo(StringRef Format) {
auto Iter = OutputFormatMap.find(Format);
if (Iter == std::end(OutputFormatMap))
- error("Invalid output format: '" + Format + "'");
+ return createStringError(errc::invalid_argument,
+ "Invalid output format: '%s'",
+ Format.str().c_str());
return Iter->getValue();
}
-static void addSymbolsFromFile(std::vector<NameOrRegex> &Symbols,
- BumpPtrAllocator &Alloc, StringRef Filename,
- bool UseRegex) {
+static Error addSymbolsFromFile(std::vector<NameOrRegex> &Symbols,
+ BumpPtrAllocator &Alloc, StringRef Filename,
+ bool UseRegex) {
StringSaver Saver(Alloc);
SmallVector<StringRef, 16> Lines;
auto BufOrErr = MemoryBuffer::getFile(Filename);
if (!BufOrErr)
- reportError(Filename, BufOrErr.getError());
+ return createFileError(Filename, BufOrErr.getError());
BufOrErr.get()->getBuffer().split(Lines, '\n');
for (StringRef Line : Lines) {
@@ -243,6 +261,8 @@ static void addSymbolsFromFile(std::vector<NameOrRegex> &Symbols,
if (!TrimmedLine.empty())
Symbols.emplace_back(Saver.save(TrimmedLine), UseRegex);
}
+
+ return Error::success();
}
NameOrRegex::NameOrRegex(StringRef Pattern, bool IsRegex) {
@@ -285,7 +305,7 @@ static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
// ParseObjcopyOptions returns the config and sets the input arguments. If a
// help flag is set then ParseObjcopyOptions will print the help messege and
// exit.
-DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
+Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
DriverConfig DC;
ObjcopyOptTable T;
unsigned MissingArgumentIndex, MissingArgumentCount;
@@ -311,16 +331,18 @@ DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
SmallVector<const char *, 2> Positional;
for (auto Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
- error("unknown argument '" + Arg->getAsString(InputArgs) + "'");
+ return createStringError(errc::invalid_argument, "unknown argument '%s'",
+ Arg->getAsString(InputArgs).c_str());
for (auto Arg : InputArgs.filtered(OBJCOPY_INPUT))
Positional.push_back(Arg->getValue());
if (Positional.empty())
- error("No input file specified");
+ return createStringError(errc::invalid_argument, "No input file specified");
if (Positional.size() > 2)
- error("Too many positional arguments");
+ return createStringError(errc::invalid_argument,
+ "Too many positional arguments");
CopyConfig Config;
Config.InputFilename = Positional[0];
@@ -328,7 +350,9 @@ DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
if (InputArgs.hasArg(OBJCOPY_target) &&
(InputArgs.hasArg(OBJCOPY_input_target) ||
InputArgs.hasArg(OBJCOPY_output_target)))
- error("--target cannot be used with --input-target or --output-target");
+ return createStringError(
+ errc::invalid_argument,
+ "--target cannot be used with --input-target or --output-target");
bool UseRegex = InputArgs.hasArg(OBJCOPY_regex);
if (InputArgs.hasArg(OBJCOPY_target)) {
@@ -341,11 +365,21 @@ DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
if (Config.InputFormat == "binary") {
auto BinaryArch = InputArgs.getLastArgValue(OBJCOPY_binary_architecture);
if (BinaryArch.empty())
- error("Specified binary input without specifiying an architecture");
- Config.BinaryArch = getMachineInfo(BinaryArch);
+ return createStringError(
+ errc::invalid_argument,
+ "Specified binary input without specifiying an architecture");
+ Expected<const MachineInfo &> MI = getMachineInfo(BinaryArch);
+ if (!MI)
+ return MI.takeError();
+ Config.BinaryArch = *MI;
+ }
+ if (!Config.OutputFormat.empty() && Config.OutputFormat != "binary") {
+ Expected<const MachineInfo &> MI =
+ getOutputFormatMachineInfo(Config.OutputFormat);
+ if (!MI)
+ return MI.takeError();
+ Config.OutputArch = *MI;
}
- if (!Config.OutputFormat.empty() && Config.OutputFormat != "binary")
- Config.OutputArch = getOutputFormatMachineInfo(Config.OutputFormat);
if (auto Arg = InputArgs.getLastArg(OBJCOPY_compress_debug_sections,
OBJCOPY_compress_debug_sections_eq)) {
@@ -359,10 +393,16 @@ DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
.Case("zlib", DebugCompressionType::Z)
.Default(DebugCompressionType::None);
if (Config.CompressionType == DebugCompressionType::None)
- error("Invalid or unsupported --compress-debug-sections format: " +
- InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq));
+ return createStringError(
+ errc::invalid_argument,
+ "Invalid or unsupported --compress-debug-sections format: %s",
+ InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq)
+ .str()
+ .c_str());
if (!zlib::isAvailable())
- error("LLVM was not compiled with LLVM_ENABLE_ZLIB: can not compress.");
+ return createStringError(
+ errc::invalid_argument,
+ "LLVM was not compiled with LLVM_ENABLE_ZLIB: can not compress");
}
}
@@ -379,39 +419,57 @@ DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
if (!StringRef(Arg->getValue()).contains('='))
- error("Bad format for --redefine-sym");
+ return createStringError(errc::invalid_argument,
+ "Bad format for --redefine-sym");
auto Old2New = StringRef(Arg->getValue()).split('=');
if (!Config.SymbolsToRename.insert(Old2New).second)
- error("Multiple redefinition of symbol " + Old2New.first);
+ return createStringError(errc::invalid_argument,
+ "Multiple redefinition of symbol %s",
+ Old2New.first.str().c_str());
}
for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbols))
if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc,
Arg->getValue()))
- error(std::move(E));
+ return std::move(E);
for (auto Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
- SectionRename SR = parseRenameSectionValue(StringRef(Arg->getValue()));
- if (!Config.SectionsToRename.try_emplace(SR.OriginalName, SR).second)
- error("Multiple renames of section " + SR.OriginalName);
+ Expected<SectionRename> SR =
+ parseRenameSectionValue(StringRef(Arg->getValue()));
+ if (!SR)
+ return SR.takeError();
+ if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second)
+ return createStringError(errc::invalid_argument,
+ "Multiple renames of section %s",
+ SR->OriginalName.str().c_str());
}
for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
- SectionFlagsUpdate SFU = parseSetSectionFlagValue(Arg->getValue());
- if (!Config.SetSectionFlags.try_emplace(SFU.Name, SFU).second)
- error("--set-section-flags set multiple times for section " + SFU.Name);
+ Expected<SectionFlagsUpdate> SFU =
+ parseSetSectionFlagValue(Arg->getValue());
+ if (!SFU)
+ return SFU.takeError();
+ if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second)
+ return createStringError(
+ errc::invalid_argument,
+ "--set-section-flags set multiple times for section %s",
+ SFU->Name.str().c_str());
}
// Prohibit combinations of --set-section-flags when the section name is used
// by --rename-section, either as a source or a destination.
for (const auto &E : Config.SectionsToRename) {
const SectionRename &SR = E.second;
if (Config.SetSectionFlags.count(SR.OriginalName))
- error("--set-section-flags=" + SR.OriginalName +
- " conflicts with --rename-section=" + SR.OriginalName + "=" +
- SR.NewName);
+ return createStringError(
+ errc::invalid_argument,
+ "--set-section-flags=%s conflicts with --rename-section=%s=%s",
+ SR.OriginalName.str().c_str(), SR.OriginalName.str().c_str(),
+ SR.NewName.str().c_str());
if (Config.SetSectionFlags.count(SR.NewName))
- error("--set-section-flags=" + SR.NewName +
- " conflicts with --rename-section=" + SR.OriginalName + "=" +
- SR.NewName);
+ return createStringError(
+ errc::invalid_argument,
+ "--set-section-flags=%s conflicts with --rename-section=%s=%s",
+ SR.NewName.str().c_str(), SR.OriginalName.str().c_str(),
+ SR.NewName.str().c_str());
}
for (auto Arg : InputArgs.filtered(OBJCOPY_remove_section))
@@ -446,33 +504,39 @@ DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
Config.SymbolsToLocalize.emplace_back(Arg->getValue(), UseRegex);
for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbols))
- addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc, Arg->getValue(),
- UseRegex);
+ if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc,
+ Arg->getValue(), UseRegex))
+ return std::move(E);
for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol))
Config.SymbolsToKeepGlobal.emplace_back(Arg->getValue(), UseRegex);
for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols))
- addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc, Arg->getValue(),
- UseRegex);
+ if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc,
+ Arg->getValue(), UseRegex))
+ return std::move(E);
for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
Config.SymbolsToGlobalize.emplace_back(Arg->getValue(), UseRegex);
for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbols))
- addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc, Arg->getValue(),
- UseRegex);
+ if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc,
+ Arg->getValue(), UseRegex))
+ return std::move(E);
for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
Config.SymbolsToWeaken.emplace_back(Arg->getValue(), UseRegex);
for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbols))
- addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc, Arg->getValue(),
- UseRegex);
+ if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc,
+ Arg->getValue(), UseRegex))
+ return std::move(E);
for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
Config.SymbolsToRemove.emplace_back(Arg->getValue(), UseRegex);
for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
- addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc, Arg->getValue(),
- UseRegex);
+ if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc,
+ Arg->getValue(), UseRegex))
+ return std::move(E);
for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol))
Config.UnneededSymbolsToRemove.emplace_back(Arg->getValue(), UseRegex);
for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols))
- addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc,
- Arg->getValue(), UseRegex);
+ if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc,
+ Arg->getValue(), UseRegex))
+ return std::move(E);
for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
Config.SymbolsToKeep.emplace_back(Arg->getValue(), UseRegex);
@@ -484,12 +548,16 @@ DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
if (Config.DecompressDebugSections &&
Config.CompressionType != DebugCompressionType::None) {
- error("Cannot specify --compress-debug-sections at the same time as "
- "--decompress-debug-sections at the same time");
+ return createStringError(
+ errc::invalid_argument,
+ "Cannot specify --compress-debug-sections at the same time as "
+ "--decompress-debug-sections at the same time");
}
if (Config.DecompressDebugSections && !zlib::isAvailable())
- error("LLVM was not compiled with LLVM_ENABLE_ZLIB: cannot decompress.");
+ return createStringError(
+ errc::invalid_argument,
+ "LLVM was not compiled with LLVM_ENABLE_ZLIB: cannot decompress");
DC.CopyConfigs.push_back(std::move(Config));
return DC;
@@ -498,7 +566,7 @@ DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
// ParseStripOptions returns the config and sets the input arguments. If a
// help flag is set then ParseStripOptions will print the help messege and
// exit.
-DriverConfig parseStripOptions(ArrayRef<const char *> ArgsArr) {
+Expected<DriverConfig> parseStripOptions(ArrayRef<const char *> ArgsArr) {
StripOptTable T;
unsigned MissingArgumentIndex, MissingArgumentCount;
llvm::opt::InputArgList InputArgs =
@@ -522,15 +590,18 @@ DriverConfig parseStripOptions(ArrayRef<const char *> ArgsArr) {
SmallVector<const char *, 2> Positional;
for (auto Arg : InputArgs.filtered(STRIP_UNKNOWN))
- error("unknown argument '" + Arg->getAsString(InputArgs) + "'");
+ return createStringError(errc::invalid_argument, "unknown argument '%s'",
+ Arg->getAsString(InputArgs).c_str());
for (auto Arg : InputArgs.filtered(STRIP_INPUT))
Positional.push_back(Arg->getValue());
if (Positional.empty())
- error("No input file specified");
+ return createStringError(errc::invalid_argument, "No input file specified");
if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
- error("Multiple input files cannot be used in combination with -o");
+ return createStringError(
+ errc::invalid_argument,
+ "Multiple input files cannot be used in combination with -o");
CopyConfig Config;
bool UseRegexp = InputArgs.hasArg(STRIP_regex);
diff --git a/llvm/tools/llvm-objcopy/CopyConfig.h b/llvm/tools/llvm-objcopy/CopyConfig.h
index f1d5cf2c10cb..7dc60bcc8435 100644
--- a/llvm/tools/llvm-objcopy/CopyConfig.h
+++ b/llvm/tools/llvm-objcopy/CopyConfig.h
@@ -15,6 +15,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/Regex.h"
// Necessary for llvm::DebugCompressionType::None
#include "llvm/Target/TargetOptions.h"
@@ -131,12 +132,12 @@ struct DriverConfig {
// ParseObjcopyOptions returns the config and sets the input arguments. If a
// help flag is set then ParseObjcopyOptions will print the help messege and
// exit.
-DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr);
+Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr);
// ParseStripOptions returns the config and sets the input arguments. If a
// help flag is set then ParseStripOptions will print the help messege and
// exit.
-DriverConfig parseStripOptions(ArrayRef<const char *> ArgsArr);
+Expected<DriverConfig> parseStripOptions(ArrayRef<const char *> ArgsArr);
} // namespace objcopy
} // namespace llvm
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index fdf1c305b61e..28d7ee2e2a9f 100644
--- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -183,70 +183,86 @@ static Error executeObjcopyOnArchive(const CopyConfig &Config,
Config.DeterministicArchives, Ar.isThin());
}
-static void restoreDateOnFile(StringRef Filename,
- const sys::fs::file_status &Stat) {
+static Error restoreDateOnFile(StringRef Filename,
+ const sys::fs::file_status &Stat) {
int FD;
if (auto EC =
sys::fs::openFileForWrite(Filename, FD, sys::fs::CD_OpenExisting))
- reportError(Filename, EC);
+ return createFileError(Filename, EC);
if (auto EC = sys::fs::setLastAccessAndModificationTime(
FD, Stat.getLastAccessedTime(), Stat.getLastModificationTime()))
- reportError(Filename, EC);
+ return createFileError(Filename, EC);
if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))
- reportError(Filename, EC);
+ return createFileError(Filename, EC);
+
+ return Error::success();
}
/// The function executeObjcopy does the higher level dispatch based on the type
/// of input (raw binary, archive or single object file) and takes care of the
/// format-agnostic modifications, i.e. preserving dates.
-static void executeObjcopy(const CopyConfig &Config) {
+static Error executeObjcopy(const CopyConfig &Config) {
sys::fs::file_status Stat;
if (Config.PreserveDates)
if (auto EC = sys::fs::status(Config.InputFilename, Stat))
- reportError(Config.InputFilename, EC);
+ return createFileError(Config.InputFilename, EC);
if (Config.InputFormat == "binary") {
auto BufOrErr = MemoryBuffer::getFile(Config.InputFilename);
if (!BufOrErr)
- reportError(Config.InputFilename, BufOrErr.getError());
+ return createFileError(Config.InputFilename, BufOrErr.getError());
FileBuffer FB(Config.OutputFilename);
if (Error E = executeObjcopyOnRawBinary(Config, *BufOrErr->get(), FB))
- error(std::move(E));
+ return E;
} else {
Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr =
createBinary(Config.InputFilename);
if (!BinaryOrErr)
- reportError(Config.InputFilename, BinaryOrErr.takeError());
+ return createFileError(Config.InputFilename, BinaryOrErr.takeError());
if (Archive *Ar = dyn_cast<Archive>(BinaryOrErr.get().getBinary())) {
if (Error E = executeObjcopyOnArchive(Config, *Ar))
- error(std::move(E));
+ return E;
} else {
FileBuffer FB(Config.OutputFilename);
if (Error E = executeObjcopyOnBinary(Config,
*BinaryOrErr.get().getBinary(), FB))
- error(std::move(E));
+ return E;
}
}
if (Config.PreserveDates) {
- restoreDateOnFile(Config.OutputFilename, Stat);
+ if (Error E = restoreDateOnFile(Config.OutputFilename, Stat))
+ return E;
if (!Config.SplitDWO.empty())
- restoreDateOnFile(Config.SplitDWO, Stat);
+ if (Error E = restoreDateOnFile(Config.SplitDWO, Stat))
+ return E;
}
+
+ return Error::success();
}
int main(int argc, char **argv) {
InitLLVM X(argc, argv);
ToolName = argv[0];
- DriverConfig DriverConfig;
- if (sys::path::stem(ToolName).contains("strip"))
- DriverConfig = parseStripOptions(makeArrayRef(argv + 1, argc));
- else
- DriverConfig = parseObjcopyOptions(makeArrayRef(argv + 1, argc));
- for (const CopyConfig &CopyConfig : DriverConfig.CopyConfigs)
- executeObjcopy(CopyConfig);
+ bool IsStrip = sys::path::stem(ToolName).contains("strip");
+ Expected<DriverConfig> DriverConfig =
+ IsStrip ? parseStripOptions(makeArrayRef(argv + 1, argc))
+ : parseObjcopyOptions(makeArrayRef(argv + 1, argc));
+ if (!DriverConfig) {
+ logAllUnhandledErrors(DriverConfig.takeError(),
+ WithColor::error(errs(), ToolName));
+ return 1;
+ }
+ for (const CopyConfig &CopyConfig : DriverConfig->CopyConfigs) {
+ if (Error E = executeObjcopy(CopyConfig)) {
+ logAllUnhandledErrors(std::move(E), WithColor::error(errs(), ToolName));
+ return 1;
+ }
+ }
+
+ return 0;
}