17
17
#include " llvm/Support/FileOutputBuffer.h"
18
18
#include " llvm/Support/MathExtras.h"
19
19
#include " llvm/Support/MemoryBuffer.h"
20
+ #include " llvm/Support/Process.h"
20
21
21
22
using llvm::MemoryBufferRef;
22
23
using llvm::object::ELFObjectFile;
@@ -663,8 +664,25 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) {
663
664
// / @param FilePath File path for writing the ELF binary.
664
665
// / @param Stub Source ELFStub to generate a binary ELF stub from.
665
666
template <class ELFT >
666
- static Error writeELFBinaryToFile (StringRef FilePath, const ELFStub &Stub) {
667
+ static Error writeELFBinaryToFile (StringRef FilePath, const ELFStub &Stub,
668
+ bool WriteIfChanged) {
667
669
ELFStubBuilder<ELFT> Builder{Stub};
670
+ // Write Stub to memory first.
671
+ std::vector<uint8_t > Buf (Builder.getSize ());
672
+ Builder.write (Buf.data ());
673
+
674
+ if (WriteIfChanged) {
675
+ if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
676
+ MemoryBuffer::getFile (FilePath)) {
677
+ // Compare Stub output with existing Stub file.
678
+ // If Stub file unchanged, abort updating.
679
+ if ((*BufOrError)->getBufferSize () == Builder.getSize () &&
680
+ !memcmp ((*BufOrError)->getBufferStart (), Buf.data (),
681
+ Builder.getSize ()))
682
+ return Error::success ();
683
+ }
684
+ }
685
+
668
686
Expected<std::unique_ptr<FileOutputBuffer>> BufOrError =
669
687
FileOutputBuffer::create (FilePath, Builder.getSize ());
670
688
if (!BufOrError)
@@ -674,13 +692,10 @@ static Error writeELFBinaryToFile(StringRef FilePath, const ELFStub &Stub) {
674
692
" ` for writing" );
675
693
676
694
// Write binary to file.
677
- std::unique_ptr<FileOutputBuffer> Buf = std::move (*BufOrError);
678
- Builder. write (Buf ->getBufferStart ());
695
+ std::unique_ptr<FileOutputBuffer> FileBuf = std::move (*BufOrError);
696
+ memcpy (FileBuf ->getBufferStart (), Buf. data (), Buf. size ());
679
697
680
- if (Error E = Buf->commit ())
681
- return E;
682
-
683
- return Error::success ();
698
+ return FileBuf->commit ();
684
699
}
685
700
686
701
Expected<std::unique_ptr<ELFStub>> readELFFile (MemoryBufferRef Buf) {
@@ -705,15 +720,15 @@ Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf) {
705
720
// This function wraps the ELFT writeELFBinaryToFile() so writeBinaryStub()
706
721
// can be called without having to use ELFType templates directly.
707
722
Error writeBinaryStub (StringRef FilePath, const ELFStub &Stub,
708
- ELFTarget OutputFormat) {
723
+ ELFTarget OutputFormat, bool WriteIfChanged ) {
709
724
if (OutputFormat == ELFTarget::ELF32LE)
710
- return writeELFBinaryToFile<ELF32LE>(FilePath, Stub);
725
+ return writeELFBinaryToFile<ELF32LE>(FilePath, Stub, WriteIfChanged );
711
726
if (OutputFormat == ELFTarget::ELF32BE)
712
- return writeELFBinaryToFile<ELF32BE>(FilePath, Stub);
727
+ return writeELFBinaryToFile<ELF32BE>(FilePath, Stub, WriteIfChanged );
713
728
if (OutputFormat == ELFTarget::ELF64LE)
714
- return writeELFBinaryToFile<ELF64LE>(FilePath, Stub);
729
+ return writeELFBinaryToFile<ELF64LE>(FilePath, Stub, WriteIfChanged );
715
730
if (OutputFormat == ELFTarget::ELF64BE)
716
- return writeELFBinaryToFile<ELF64BE>(FilePath, Stub);
731
+ return writeELFBinaryToFile<ELF64BE>(FilePath, Stub, WriteIfChanged );
717
732
llvm_unreachable (" invalid binary output target" );
718
733
}
719
734
0 commit comments