diff --git a/llvm/test/tools/llvm-elfabi/preserve-dates.test b/llvm/test/tools/llvm-elfabi/preserve-dates.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-elfabi/preserve-dates.test @@ -0,0 +1,8 @@ +## Test writing unchanged content to TBE file with --preserve-dates flag. + +# RUN: llvm-elfabi --elf %p/Inputs/gnu_hash.so --emit-tbe=%t +# RUN: touch -m -d "1970-01-01 00:00:00" %t +# RUN: llvm-elfabi --elf %p/Inputs/gnu_hash.so --emit-tbe=%t --preserve-dates +# RUN: ls -l %t | FileCheck %s + +# CHECK: {{[[:space:]]1970}} diff --git a/llvm/tools/llvm-elfabi/llvm-elfabi.cpp b/llvm/tools/llvm-elfabi/llvm-elfabi.cpp --- a/llvm/tools/llvm-elfabi/llvm-elfabi.cpp +++ b/llvm/tools/llvm-elfabi/llvm-elfabi.cpp @@ -57,22 +57,42 @@ clEnumValN(ELFTarget::ELF64BE, "elf64-big", "64-bit big-endian ELF stub"))); cl::opt BinaryOutputFilePath(cl::Positional, cl::desc("output")); +cl::opt + PreserveDates("preserve-dates", + cl::desc("preserve the timestamp of the output file " + "if the content is not changed")); +cl::alias PreserveDatesA("p", cl::desc("Alias for --preserve-dates"), + cl::aliasopt(PreserveDates)); /// writeTBE() writes a Text-Based ELF stub to a file using the latest version /// of the YAML parser. static Error writeTBE(StringRef FilePath, ELFStub &Stub) { + // Write TBE to memory first. + std::string TBEStr; + raw_string_ostream OutStr(TBEStr); + Error YAMLErr = writeTBEToOutputStream(OutStr, Stub); + if (YAMLErr) + return YAMLErr; + OutStr.str(); + + if (PreserveDates) { + ErrorOr> BufOrError = + MemoryBuffer::getFile(FilePath); + if (BufOrError) { + // Compare TBE output with existing TBE file. + std::unique_ptr FileReadBuffer = std::move(*BufOrError); + // If TBE file unchanged, abort updating. + if (FileReadBuffer->getBuffer().equals(TBEStr)) + return Error::success(); + } + } + // Open TBE file for writing. std::error_code SysErr; - - // Open file for writing. raw_fd_ostream Out(FilePath, SysErr); if (SysErr) return createStringError(SysErr, "Couldn't open `%s` for writing", FilePath.data()); - // Write file. - Error YAMLErr = writeTBEToOutputStream(Out, Stub); - if (YAMLErr) - return YAMLErr; - + Out << TBEStr; return Error::success(); }