diff options
-rw-r--r-- | lld/COFF/DriverUtils.cpp | 3 | ||||
-rw-r--r-- | llvm/include/llvm/Object/WindowsResource.h | 3 | ||||
-rw-r--r-- | llvm/lib/Object/WindowsResource.cpp | 26 | ||||
-rw-r--r-- | llvm/test/tools/llvm-cvtres/help.test | 1 | ||||
-rw-r--r-- | llvm/test/tools/llvm-cvtres/timestamp.test | 10 | ||||
-rw-r--r-- | llvm/tools/llvm-cvtres/Opts.td | 5 | ||||
-rw-r--r-- | llvm/tools/llvm-cvtres/llvm-cvtres.cpp | 20 |
7 files changed, 50 insertions, 18 deletions
diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index 34cfa2ff014..5c720b712dd 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -718,7 +718,8 @@ MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> MBs) { } Expected<std::unique_ptr<MemoryBuffer>> E = - llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser); + llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser, + Config->Timestamp); if (!E) fatal("failed to write .res to COFF: " + toString(E.takeError())); diff --git a/llvm/include/llvm/Object/WindowsResource.h b/llvm/include/llvm/Object/WindowsResource.h index d5e0bb8edde..356dcb03abb 100644 --- a/llvm/include/llvm/Object/WindowsResource.h +++ b/llvm/include/llvm/Object/WindowsResource.h @@ -232,7 +232,8 @@ private: Expected<std::unique_ptr<MemoryBuffer>> writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType, - const WindowsResourceParser &Parser); + const WindowsResourceParser &Parser, + uint32_t TimeDateStamp); void printResourceTypeName(uint16_t TypeID, raw_ostream &OS); } // namespace object diff --git a/llvm/lib/Object/WindowsResource.cpp b/llvm/lib/Object/WindowsResource.cpp index 0fdbcc2cae7..7347d3079e0 100644 --- a/llvm/lib/Object/WindowsResource.cpp +++ b/llvm/lib/Object/WindowsResource.cpp @@ -400,13 +400,13 @@ class WindowsResourceCOFFWriter { public: WindowsResourceCOFFWriter(COFF::MachineTypes MachineType, const WindowsResourceParser &Parser, Error &E); - std::unique_ptr<MemoryBuffer> write(); + std::unique_ptr<MemoryBuffer> write(uint32_t TimeDateStamp); private: void performFileLayout(); void performSectionOneLayout(); void performSectionTwoLayout(); - void writeCOFFHeader(); + void writeCOFFHeader(uint32_t TimeDateStamp); void writeFirstSectionHeader(); void writeSecondSectionHeader(); void writeFirstSection(); @@ -499,17 +499,11 @@ void WindowsResourceCOFFWriter::performSectionTwoLayout() { FileSize = alignTo(FileSize, SECTION_ALIGNMENT); } -static std::time_t getTime() { - std::time_t Now = time(nullptr); - if (Now < 0 || !isUInt<32>(Now)) - return UINT32_MAX; - return Now; -} - -std::unique_ptr<MemoryBuffer> WindowsResourceCOFFWriter::write() { +std::unique_ptr<MemoryBuffer> +WindowsResourceCOFFWriter::write(uint32_t TimeDateStamp) { BufferStart = OutputBuffer->getBufferStart(); - writeCOFFHeader(); + writeCOFFHeader(TimeDateStamp); writeFirstSectionHeader(); writeSecondSectionHeader(); writeFirstSection(); @@ -520,16 +514,17 @@ std::unique_ptr<MemoryBuffer> WindowsResourceCOFFWriter::write() { return std::move(OutputBuffer); } -void WindowsResourceCOFFWriter::writeCOFFHeader() { +void WindowsResourceCOFFWriter::writeCOFFHeader(uint32_t TimeDateStamp) { // Write the COFF header. auto *Header = reinterpret_cast<coff_file_header *>(BufferStart); Header->Machine = MachineType; Header->NumberOfSections = 2; - Header->TimeDateStamp = getTime(); + Header->TimeDateStamp = TimeDateStamp; Header->PointerToSymbolTable = SymbolTableOffset; // One symbol for every resource plus 2 for each section and @feat.00 Header->NumberOfSymbols = Data.size() + 5; Header->SizeOfOptionalHeader = 0; + // cvtres.exe sets 32BIT_MACHINE even for 64-bit machine types. Match it. Header->Characteristics = COFF::IMAGE_FILE_32BIT_MACHINE; } @@ -794,12 +789,13 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() { Expected<std::unique_ptr<MemoryBuffer>> writeWindowsResourceCOFF(COFF::MachineTypes MachineType, - const WindowsResourceParser &Parser) { + const WindowsResourceParser &Parser, + uint32_t TimeDateStamp) { Error E = Error::success(); WindowsResourceCOFFWriter Writer(MachineType, Parser, E); if (E) return std::move(E); - return Writer.write(); + return Writer.write(TimeDateStamp); } } // namespace object diff --git a/llvm/test/tools/llvm-cvtres/help.test b/llvm/test/tools/llvm-cvtres/help.test index 7df6264ac0a..3be7c96fa02 100644 --- a/llvm/test/tools/llvm-cvtres/help.test +++ b/llvm/test/tools/llvm-cvtres/help.test @@ -10,4 +10,5 @@ ; HELP_TEST-DAG: /NOLOGO ; HELP_TEST-NEXT: /OUT:filename ; HELP_TEST-NEXT: /READONLY +; HELP_TEST-NEXT: /TIMESTAMP:<value> Timestamp for coff header, defaults to current time ; HELP_TEST-NEXT: /VERBOSE diff --git a/llvm/test/tools/llvm-cvtres/timestamp.test b/llvm/test/tools/llvm-cvtres/timestamp.test new file mode 100644 index 00000000000..7e7c2207b9e --- /dev/null +++ b/llvm/test/tools/llvm-cvtres/timestamp.test @@ -0,0 +1,10 @@ +RUN: llvm-cvtres /timestamp:0x12345678 /out:%t %p/Inputs/test_resource.res +RUN: llvm-readobj -h %t | FileCheck %s --check-prefix=1TO8 + +1TO8: TimeDateStamp: 1979-09-05 22:51:36 (0x12345678) + + +RUN: not llvm-cvtres /timestamp:0x123456789 /out:%t \ +RUN: %p/Inputs/test_resource.res 2>&1 | FileCheck %s --check-prefix=ERR + +ERR: invalid timestamp: 0x123456789. Expected 32-bit integer diff --git a/llvm/tools/llvm-cvtres/Opts.td b/llvm/tools/llvm-cvtres/Opts.td index 29428cec180..8687d4701ce 100644 --- a/llvm/tools/llvm-cvtres/Opts.td +++ b/llvm/tools/llvm-cvtres/Opts.td @@ -12,3 +12,8 @@ def VERBOSE : Flag<["/", "-"], "VERBOSE">, HelpText<"">; def HELP : Flag<["/", "-"], "HELP">; def H : Flag<["/", "-"], "H">, Alias<HELP>; def HELP_Q : Flag<["/?", "-?"], "">, Alias<HELP>; + +// Extensions. + +def TIMESTAMP : Joined<["/", "-"], "TIMESTAMP:">, + HelpText<"Timestamp for coff header, defaults to current time">; diff --git a/llvm/tools/llvm-cvtres/llvm-cvtres.cpp b/llvm/tools/llvm-cvtres/llvm-cvtres.cpp index 7ce618a1c0e..c2e46f0f680 100644 --- a/llvm/tools/llvm-cvtres/llvm-cvtres.cpp +++ b/llvm/tools/llvm-cvtres/llvm-cvtres.cpp @@ -88,6 +88,13 @@ void error(Error EC) { [&](const ErrorInfoBase &EI) { reportError(EI.message()); }); } +static uint32_t getTime() { + std::time_t Now = time(nullptr); + if (Now < 0 || !isUInt<32>(Now)) + return UINT32_MAX; + return static_cast<uint32_t>(Now); +} + template <typename T> T error(Expected<T> EC) { if (!EC) error(EC.takeError()); @@ -142,6 +149,16 @@ int main(int Argc, const char **Argv) { sys::path::replace_extension(OutputFile, ".obj"); } + uint32_t DateTimeStamp; + if (llvm::opt::Arg *Arg = InputArgs.getLastArg(OPT_TIMESTAMP)) { + StringRef Value(Arg->getValue()); + if (Value.getAsInteger(0, DateTimeStamp)) + reportError(Twine("invalid timestamp: ") + Value + + ". Expected 32-bit integer\n"); + } else { + DateTimeStamp = getTime(); + } + if (Verbose) { outs() << "Machine: "; switch (MachineType) { @@ -194,7 +211,8 @@ int main(int Argc, const char **Argv) { } std::unique_ptr<MemoryBuffer> OutputBuffer = - error(llvm::object::writeWindowsResourceCOFF(MachineType, Parser)); + error(llvm::object::writeWindowsResourceCOFF(MachineType, Parser, + DateTimeStamp)); auto FileOrErr = FileOutputBuffer::create(OutputFile, OutputBuffer->getBufferSize()); if (!FileOrErr) |