diff --git a/llvm/test/tools/llvm-objcopy/ELF/invalid-preserve-dates.test b/llvm/test/tools/llvm-objcopy/ELF/invalid-preserve-dates.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/ELF/invalid-preserve-dates.test @@ -0,0 +1,5 @@ +# RUN: not llvm-objcopy --preserve-dates - %t < %p/Inputs/alloc-symtab.o +# CHECK: error: --preserve-dates requires a file + +# RUN: not llvm-objcopy --preserve-dates %p/Inputs/alloc-symtab.o - +# CHECK: error: --preserve-dates requires a file diff --git a/llvm/test/tools/llvm-objcopy/ELF/preserve-dates.test b/llvm/test/tools/llvm-objcopy/ELF/preserve-dates.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/ELF/preserve-dates.test @@ -0,0 +1,5 @@ +# RUN: llvm-objcopy %p/Inputs/alloc-symtab.o %t +# RUN: test %t -nt %p/Inputs/alloc-symtab.o + +# RUN: llvm-objcopy %p/Inputs/alloc-symtab.o %t --preserve-dates +# RUN: test ! %t -nt %p/Inputs/alloc-symtab.o diff --git a/llvm/tools/llvm-objcopy/CopyConfig.cpp b/llvm/tools/llvm-objcopy/CopyConfig.cpp --- a/llvm/tools/llvm-objcopy/CopyConfig.cpp +++ b/llvm/tools/llvm-objcopy/CopyConfig.cpp @@ -118,7 +118,7 @@ if (ParsedFlag == SectionFlag::SecNone) return createStringError( errc::invalid_argument, - "Unrecognized section flag '%s'. Flags supported for GNU " + "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()); @@ -131,7 +131,7 @@ static Expected parseRenameSectionValue(StringRef FlagValue) { if (!FlagValue.contains('=')) return createStringError(errc::invalid_argument, - "Bad format for --rename-section: missing '='"); + "bad format for --rename-section: missing '='"); // Initial split: ".foo" = ".bar,f1,f2,..." auto Old2New = FlagValue.split('='); @@ -158,7 +158,7 @@ parseSetSectionFlagValue(StringRef FlagValue) { if (!StringRef(FlagValue).contains('=')) return createStringError(errc::invalid_argument, - "Bad format for --set-section-flags: missing '='"); + "bad format for --set-section-flags: missing '='"); // Initial split: ".foo" = "f1,f2,..." auto Section2Flags = StringRef(FlagValue).split('='); @@ -271,7 +271,7 @@ auto Iter = ArchMap.find(Arch); if (Iter == std::end(ArchMap)) return createStringError(errc::invalid_argument, - "Invalid architecture: '%s'", Arch.str().c_str()); + "invalid architecture: '%s'", Arch.str().c_str()); return Iter->getValue(); } @@ -313,7 +313,7 @@ auto Iter = OutputFormatMap.find(Format); if (Iter == std::end(OutputFormatMap)) return createStringError(errc::invalid_argument, - "Invalid output format: '%s'", + "invalid output format: '%s'", OriginalFormat.str().c_str()); MachineInfo MI = Iter->getValue(); if (IsFreeBSD) @@ -423,11 +423,11 @@ Positional.push_back(Arg->getValue()); if (Positional.empty()) - return createStringError(errc::invalid_argument, "No input file specified"); + return createStringError(errc::invalid_argument, "no input file specified"); if (Positional.size() > 2) return createStringError(errc::invalid_argument, - "Too many positional arguments"); + "too many positional arguments"); CopyConfig Config; Config.InputFilename = Positional[0]; @@ -452,7 +452,7 @@ if (BinaryArch.empty()) return createStringError( errc::invalid_argument, - "Specified binary input without specifiying an architecture"); + "specified binary input without specifiying an architecture"); Expected MI = getMachineInfo(BinaryArch); if (!MI) return MI.takeError(); @@ -480,7 +480,7 @@ if (Config.CompressionType == DebugCompressionType::None) return createStringError( errc::invalid_argument, - "Invalid or unsupported --compress-debug-sections format: %s", + "invalid or unsupported --compress-debug-sections format: %s", InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq) .str() .c_str()); @@ -523,11 +523,11 @@ for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) { if (!StringRef(Arg->getValue()).contains('=')) return createStringError(errc::invalid_argument, - "Bad format for --redefine-sym"); + "bad format for --redefine-sym"); auto Old2New = StringRef(Arg->getValue()).split('='); if (!Config.SymbolsToRename.insert(Old2New).second) return createStringError(errc::invalid_argument, - "Multiple redefinition of symbol %s", + "multiple redefinition of symbol '%s'", Old2New.first.str().c_str()); } @@ -543,7 +543,7 @@ return SR.takeError(); if (!Config.SectionsToRename.try_emplace(SR->OriginalName, *SR).second) return createStringError(errc::invalid_argument, - "Multiple renames of section %s", + "multiple renames of section '%s'", SR->OriginalName.str().c_str()); } for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) { @@ -554,7 +554,7 @@ if (!Config.SetSectionFlags.try_emplace(SFU->Name, *SFU).second) return createStringError( errc::invalid_argument, - "--set-section-flags set multiple times for section %s", + "--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 @@ -663,6 +663,10 @@ Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates); + if (Config.OutputFilename == "-" || Config.InputFilename == "-") + if (Config.PreserveDates) + return createStringError(errc::invalid_argument, "--preserve-dates requires a file"); + for (auto Arg : InputArgs) if (Arg->getOption().matches(OBJCOPY_set_start)) { auto EAddr = getAsInteger(Arg->getValue()); @@ -688,7 +692,7 @@ Config.CompressionType != DebugCompressionType::None) { return createStringError( errc::invalid_argument, - "Cannot specify --compress-debug-sections at the same time as " + "cannot specify --compress-debug-sections at the same time as " "--decompress-debug-sections at the same time"); } @@ -734,12 +738,12 @@ Positional.push_back(Arg->getValue()); if (Positional.empty()) - return createStringError(errc::invalid_argument, "No input file specified"); + return createStringError(errc::invalid_argument, "no input file specified"); if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output)) return createStringError( errc::invalid_argument, - "Multiple input files cannot be used in combination with -o"); + "multiple input files cannot be used in combination with -o"); CopyConfig Config; bool UseRegexp = InputArgs.hasArg(STRIP_regex); @@ -798,6 +802,10 @@ } } + if (Config.OutputFilename == "-" || Config.InputFilename == "-") + if (Config.PreserveDates) + return createStringError(errc::invalid_argument, "--preserve-dates requires a file"); + return std::move(DC); } diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp --- 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/Errc.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" @@ -53,7 +54,7 @@ StringRef ToolName; LLVM_ATTRIBUTE_NORETURN void error(Twine Message) { - WithColor::error(errs(), ToolName) << Message << ".\n"; + WithColor::error(errs(), ToolName) << Message << "\n"; errs().flush(); exit(1); } @@ -209,7 +210,7 @@ if (Config.PreserveDates) if (auto EC = sys::fs::status(Config.InputFilename, Stat)) return createFileError(Config.InputFilename, EC); - + if (Config.InputFormat == "binary") { auto BufOrErr = MemoryBuffer::getFile(Config.InputFilename); if (!BufOrErr)