forked from OSchip/llvm-project
[llvm-objcopy][NFC] More error cleanup
Summary: This removes calls to `error()`/`reportError()` in the main driver (llvm-objcopy.cpp) as well as the associated argv-parsing (CopyConfig.cpp). `logAllUnhandledErrors()` is now the main way to print errors. There are still a few uses from within the per-arch drivers, so we can't delete them yet... but almost! Reviewers: jhenderson, alexshap, espindola Reviewed By: jhenderson Subscribers: emaste, arichardson, jakehehrlich, jdoerfert, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D58316 llvm-svn: 354600
This commit is contained in:
parent
1ed3a0467c
commit
ad29d29130
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue