From b07e870d785fcebc2e6cc00f46fb4765abd8fa7d Mon Sep 17 00:00:00 2001
From: Maksim Panchenko <maks@fb.com>
Date: Wed, 20 Nov 2019 00:16:19 -0800
Subject: [PATCH] [BOLT] Add BinarySection::flushPendingRelocations()

(cherry picked from FBD18623527)
---
 bolt/src/BinarySection.cpp   | 20 ++++++++++++++++++++
 bolt/src/BinarySection.h     |  3 +++
 bolt/src/RewriteInstance.cpp | 19 ++-----------------
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/bolt/src/BinarySection.cpp b/bolt/src/BinarySection.cpp
index ed110a73be29..4be31f093b79 100644
--- a/bolt/src/BinarySection.cpp
+++ b/bolt/src/BinarySection.cpp
@@ -109,6 +109,26 @@ void BinarySection::emitAsData(MCStreamer &Streamer, StringRef NewName) const {
     Streamer.EmitLabel(BC.Ctx->getOrCreateSymbol("__hot_data_end"));
 }
 
+void BinarySection::flushPendingRelocations(raw_pwrite_stream &OS) {
+  DEBUG(dbgs() << "BOLT-DEBUG: flushing pending relocs for section "
+               << getName() << '\n');
+  for (auto &Reloc : PendingRelocations) {
+    DEBUG(dbgs() << "BOLT-DEBUG: writing value 0x"
+                 << Twine::utohexstr(Reloc.Addend)
+                 << " of size " << Relocation::getSizeForType(Reloc.Type)
+                 << " at offset 0x"
+                 << Twine::utohexstr(Reloc.Offset) << '\n');
+    assert(Reloc.Type == ELF::R_X86_64_32 &&
+           "only R_X86_64_32 relocations are supported at the moment");
+    const uint32_t Value = Reloc.Addend;
+    OS.pwrite(reinterpret_cast<const char*>(&Value),
+              Relocation::getSizeForType(Reloc.Type),
+              FileOffset + Reloc.Offset);
+  }
+
+  clearList(PendingRelocations);
+}
+
 BinarySection::~BinarySection() {
   if (isReordered()) {
     delete[] getData();
diff --git a/bolt/src/BinarySection.h b/bolt/src/BinarySection.h
index 401b391ecfb0..d212f1e829a4 100644
--- a/bolt/src/BinarySection.h
+++ b/bolt/src/BinarySection.h
@@ -414,6 +414,9 @@ public:
   //  for the section during emission if non-empty.
   void emitAsData(MCStreamer &Streamer, StringRef NewName = StringRef()) const;
 
+  /// Flush all pending relocations to the emitted section.
+  void flushPendingRelocations(raw_pwrite_stream &OS);
+
   /// Reorder the contents of this section according to /p Order.  If
   /// /p Inplace is true, the entire contents of the section is reordered,
   /// otherwise the new contents contain only the reordered data.
diff --git a/bolt/src/RewriteInstance.cpp b/bolt/src/RewriteInstance.cpp
index 838560cafb8d..bd55ed23e888 100644
--- a/bolt/src/RewriteInstance.cpp
+++ b/bolt/src/RewriteInstance.cpp
@@ -3748,23 +3748,8 @@ void RewriteInstance::rewriteNoteSections() {
         Size += BSec->getOutputSize();
       }
 
-      if (BSec->hasPendingRelocations()) {
-        DEBUG(dbgs() << "BOLT-DEBUG: processing relocs for section "
-                     << SectionName << '\n');
-        for (auto &Reloc : BSec->pendingRelocations()) {
-          DEBUG(dbgs() << "BOLT-DEBUG: writing value 0x"
-                       << Twine::utohexstr(Reloc.Addend)
-                       << " of size " << Relocation::getSizeForType(Reloc.Type)
-                       << " at offset 0x"
-                       << Twine::utohexstr(Reloc.Offset) << '\n');
-          assert(Reloc.Type == ELF::R_X86_64_32 &&
-                 "only R_X86_64_32 relocations are supported at the moment");
-          uint32_t Value = Reloc.Addend;
-          OS.pwrite(reinterpret_cast<const char*>(&Value),
-                    Relocation::getSizeForType(Reloc.Type),
-                    NextAvailableOffset + Reloc.Offset);
-        }
-      }
+      BSec->setFileOffset(NextAvailableOffset);
+      BSec->flushPendingRelocations(OS);
     }
 
     // Set/modify section info.