[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:
Jordan Rupprecht 2019-02-21 17:05:19 +00:00
parent 1ed3a0467c
commit ad29d29130
12 changed files with 188 additions and 100 deletions

View File

@ -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'

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
}