diff options
author | Haowei Wu <haowei@google.com> | 2020-12-08 17:23:53 -0800 |
---|---|---|
committer | Haowei Wu <haowei@google.com> | 2020-12-29 14:43:47 -0800 |
commit | fddb41744958d21635a60622cfb4067122810bcc (patch) | |
tree | 47f14dc18af1be47f1d2d9654f5ae491b673092d /llvm/lib/InterfaceStub/ELFObjHandler.cpp | |
parent | 7e5a187de31358741f9868cdee7b0c63c1343d8d (diff) | |
download | llvm-fddb41744958d21635a60622cfb4067122810bcc.zip llvm-fddb41744958d21635a60622cfb4067122810bcc.tar.gz llvm-fddb41744958d21635a60622cfb4067122810bcc.tar.bz2 |
[llvm-elfabi] Add flag to preserve timestamp when output is the same
This change adds '--write-if-changed' flag to llvm-elfabi tool. When
enabled, llvm-elfabi will not overwrite the existing file if the
content of the file will not be changed, which preserves the
timestamp.
Differential Revision: https://reviews.llvm.org/D92902
Diffstat (limited to 'llvm/lib/InterfaceStub/ELFObjHandler.cpp')
-rw-r--r-- | llvm/lib/InterfaceStub/ELFObjHandler.cpp | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/llvm/lib/InterfaceStub/ELFObjHandler.cpp b/llvm/lib/InterfaceStub/ELFObjHandler.cpp index e50ebd7..40d8afa 100644 --- a/llvm/lib/InterfaceStub/ELFObjHandler.cpp +++ b/llvm/lib/InterfaceStub/ELFObjHandler.cpp @@ -17,6 +17,7 @@ #include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Process.h" using llvm::MemoryBufferRef; using llvm::object::ELFObjectFile; @@ -663,8 +664,25 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) { /// @param FilePath File path for writing the ELF binary. /// @param Stub Source ELFStub to generate a binary ELF stub from. template <class ELFT> -static Error writeELFBinaryToFile(StringRef FilePath, const ELFStub &Stub) { +static Error writeELFBinaryToFile(StringRef FilePath, const ELFStub &Stub, + bool WriteIfChanged) { ELFStubBuilder<ELFT> Builder{Stub}; + // Write Stub to memory first. + std::vector<uint8_t> Buf(Builder.getSize()); + Builder.write(Buf.data()); + + if (WriteIfChanged) { + if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError = + MemoryBuffer::getFile(FilePath)) { + // Compare Stub output with existing Stub file. + // If Stub file unchanged, abort updating. + if ((*BufOrError)->getBufferSize() == Builder.getSize() && + !memcmp((*BufOrError)->getBufferStart(), Buf.data(), + Builder.getSize())) + return Error::success(); + } + } + Expected<std::unique_ptr<FileOutputBuffer>> BufOrError = FileOutputBuffer::create(FilePath, Builder.getSize()); if (!BufOrError) @@ -674,13 +692,10 @@ static Error writeELFBinaryToFile(StringRef FilePath, const ELFStub &Stub) { "` for writing"); // Write binary to file. - std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufOrError); - Builder.write(Buf->getBufferStart()); + std::unique_ptr<FileOutputBuffer> FileBuf = std::move(*BufOrError); + memcpy(FileBuf->getBufferStart(), Buf.data(), Buf.size()); - if (Error E = Buf->commit()) - return E; - - return Error::success(); + return FileBuf->commit(); } Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf) { @@ -705,15 +720,15 @@ Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf) { // This function wraps the ELFT writeELFBinaryToFile() so writeBinaryStub() // can be called without having to use ELFType templates directly. Error writeBinaryStub(StringRef FilePath, const ELFStub &Stub, - ELFTarget OutputFormat) { + ELFTarget OutputFormat, bool WriteIfChanged) { if (OutputFormat == ELFTarget::ELF32LE) - return writeELFBinaryToFile<ELF32LE>(FilePath, Stub); + return writeELFBinaryToFile<ELF32LE>(FilePath, Stub, WriteIfChanged); if (OutputFormat == ELFTarget::ELF32BE) - return writeELFBinaryToFile<ELF32BE>(FilePath, Stub); + return writeELFBinaryToFile<ELF32BE>(FilePath, Stub, WriteIfChanged); if (OutputFormat == ELFTarget::ELF64LE) - return writeELFBinaryToFile<ELF64LE>(FilePath, Stub); + return writeELFBinaryToFile<ELF64LE>(FilePath, Stub, WriteIfChanged); if (OutputFormat == ELFTarget::ELF64BE) - return writeELFBinaryToFile<ELF64BE>(FilePath, Stub); + return writeELFBinaryToFile<ELF64BE>(FilePath, Stub, WriteIfChanged); llvm_unreachable("invalid binary output target"); } |