[lld] [LLD][COFF] Add basic ARM64X dynamic relocations support (PR #118035)

Jacek Caban via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 3 12:26:38 PST 2024


https://github.com/cjacek updated https://github.com/llvm/llvm-project/pull/118035

>From f840fe78ab75d7b438bc4fb435ae02a27eb35914 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Tue, 3 Dec 2024 20:22:37 +0100
Subject: [PATCH 1/3] [LLD][COFF] Check load config size before setting its
 DependentLoadFlags

Merge prepareLoadConfig and checkLoadConfigGuardData to share helper macros.
---
 lld/COFF/Writer.cpp                   | 14 +++++---------
 lld/test/COFF/deploadflag-cfg-short.s | 12 ++++++++++++
 2 files changed, 17 insertions(+), 9 deletions(-)
 create mode 100644 lld/test/COFF/deploadflag-cfg-short.s

diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index d3e326378ed2d4..fe78b8cf4ecff7 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -277,7 +277,6 @@ class Writer {
 
   void prepareLoadConfig();
   template <typename T> void prepareLoadConfig(T *loadConfig);
-  template <typename T> void checkLoadConfigGuardData(const T *loadConfig);
 
   std::unique_ptr<FileOutputBuffer> &buffer;
   std::map<PartialSectionKey, PartialSection *> partialSections;
@@ -2631,14 +2630,6 @@ void Writer::prepareLoadConfig() {
 }
 
 template <typename T> void Writer::prepareLoadConfig(T *loadConfig) {
-  if (ctx.config.dependentLoadFlags)
-    loadConfig->DependentLoadFlags = ctx.config.dependentLoadFlags;
-
-  checkLoadConfigGuardData(loadConfig);
-}
-
-template <typename T>
-void Writer::checkLoadConfigGuardData(const T *loadConfig) {
   size_t loadConfigSize = loadConfig->Size;
 
 #define RETURN_IF_NOT_CONTAINS(field)                                          \
@@ -2660,6 +2651,11 @@ void Writer::checkLoadConfigGuardData(const T *loadConfig) {
     if (loadConfig->field != s->getVA())                                       \
       warn(#field " not set correctly in '_load_config_used'");
 
+  if (ctx.config.dependentLoadFlags) {
+    RETURN_IF_NOT_CONTAINS(DependentLoadFlags)
+    loadConfig->DependentLoadFlags = ctx.config.dependentLoadFlags;
+  }
+
   if (ctx.config.guardCF == GuardCFLevel::Off)
     return;
   RETURN_IF_NOT_CONTAINS(GuardFlags)
diff --git a/lld/test/COFF/deploadflag-cfg-short.s b/lld/test/COFF/deploadflag-cfg-short.s
new file mode 100644
index 00000000000000..9cc5248044d8a3
--- /dev/null
+++ b/lld/test/COFF/deploadflag-cfg-short.s
@@ -0,0 +1,12 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -triple x86_64-windows-msvc -filetype=obj %s -o %t.obj
+# RUN: lld-link %t.obj -out:%t.dll -dll -noentry -nodefaultlib -dependentloadflag:0x800 2>&1 | FileCheck %s
+# CHECK: lld-link: warning: '_load_config_used' structure too small to include DependentLoadFlags
+
+        .section .rdata,"dr"
+        .balign 8
+.globl _load_config_used
+_load_config_used:
+        .long 0x4c
+        .fill 0x48, 1, 0

>From 8c6d4b2e16b8153926ed561e0c1e8df06392720a Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Thu, 28 Nov 2024 00:31:24 +0100
Subject: [PATCH 2/3] [LLD][COFF] Add basic ARM64X dynamic relocations support

This update modifies the machine field in the hybrid view to be AMD64, aligning it with
expectations from ARM64EC modules. While this provides initial support, additional
relocations will be necessary for full functionality. Many of these cases depend on
implementing separate namespace support first.
---
 lld/COFF/COFFLinkerContext.h      |  2 +
 lld/COFF/Chunks.cpp               | 82 +++++++++++++++++++++++++++++++
 lld/COFF/Chunks.h                 | 37 ++++++++++++++
 lld/COFF/Writer.cpp               | 57 +++++++++++++++++++--
 lld/test/COFF/arm64x-loadconfig.s | 68 +++++++++++++++++++++++++
 5 files changed, 243 insertions(+), 3 deletions(-)
 create mode 100644 lld/test/COFF/arm64x-loadconfig.s

diff --git a/lld/COFF/COFFLinkerContext.h b/lld/COFF/COFFLinkerContext.h
index 059d4aeddc6e56..5d89e97a7f7761 100644
--- a/lld/COFF/COFFLinkerContext.h
+++ b/lld/COFF/COFFLinkerContext.h
@@ -88,6 +88,8 @@ class COFFLinkerContext : public CommonLinkerContext {
   Timer diskCommitTimer;
 
   Configuration config;
+
+  DynamicRelocsChunk *dynamicRelocs = nullptr;
 };
 
 } // namespace lld::coff
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index a82e37ff052303..a4bd6df6c0ec0d 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -25,6 +25,7 @@
 
 using namespace llvm;
 using namespace llvm::object;
+using namespace llvm::support;
 using namespace llvm::support::endian;
 using namespace llvm::COFF;
 using llvm::support::ulittle32_t;
@@ -1147,4 +1148,85 @@ uint32_t ImportThunkChunkARM64EC::extendRanges() {
   return sizeof(arm64Thunk) - sizeof(uint32_t);
 }
 
+size_t Arm64XDynamicRelocEntry::getSize() const {
+  switch (type) {
+  case IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE:
+    return sizeof(uint16_t) + size; // A header and a payload.
+  case IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA:
+  case IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL:
+    llvm_unreachable("unsupported type");
+  }
+}
+
+void Arm64XDynamicRelocEntry::writeTo(uint8_t *buf) const {
+  auto out = reinterpret_cast<ulittle16_t *>(buf);
+  *out = (offset & 0xfff) | (type << 12);
+
+  switch (type) {
+  case IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE:
+    *out |= ((bit_width(size) - 1) << 14); // Encode the size.
+    switch (size) {
+    case 2:
+      out[1] = value;
+      break;
+    case 4:
+      *reinterpret_cast<ulittle32_t *>(out + 1) = value;
+      break;
+    case 8:
+      *reinterpret_cast<ulittle64_t *>(out + 1) = value;
+      break;
+    default:
+      llvm_unreachable("invalid size");
+    }
+    break;
+  case IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA:
+  case IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL:
+    llvm_unreachable("unsupported type");
+  }
+}
+
+void DynamicRelocsChunk::finalize() {
+  llvm::stable_sort(arm64xRelocs, [=](const Arm64XDynamicRelocEntry &a,
+                                      const Arm64XDynamicRelocEntry &b) {
+    return a.offset < b.offset;
+  });
+
+  size = sizeof(coff_dynamic_reloc_table) + sizeof(coff_dynamic_relocation64) +
+         sizeof(coff_base_reloc_block_header);
+
+  for (const Arm64XDynamicRelocEntry &entry : arm64xRelocs) {
+    assert(!(entry.offset & ~0xfff)); // Not yet supported.
+    size += entry.getSize();
+  }
+
+  size = alignTo(size, sizeof(uint32_t));
+}
+
+void DynamicRelocsChunk::writeTo(uint8_t *buf) const {
+  auto table = reinterpret_cast<coff_dynamic_reloc_table *>(buf);
+  table->Version = 1;
+  table->Size = sizeof(coff_dynamic_relocation64);
+  buf += sizeof(*table);
+
+  auto header = reinterpret_cast<coff_dynamic_relocation64 *>(buf);
+  header->Symbol = IMAGE_DYNAMIC_RELOCATION_ARM64X;
+  buf += sizeof(*header);
+
+  auto pageHeader = reinterpret_cast<coff_base_reloc_block_header *>(buf);
+  pageHeader->BlockSize = sizeof(*pageHeader);
+  size_t relocSize = sizeof(*pageHeader);
+  for (const Arm64XDynamicRelocEntry &entry : arm64xRelocs) {
+    entry.writeTo(buf + relocSize);
+    size_t entrySize = entry.getSize();
+    pageHeader->BlockSize += entrySize;
+    relocSize += entrySize;
+  }
+  pageHeader->BlockSize = alignTo(pageHeader->BlockSize, sizeof(uint32_t));
+  relocSize = alignTo(relocSize, sizeof(uint32_t));
+
+  header->BaseRelocSize = relocSize;
+  table->Size += relocSize;
+  assert(size == sizeof(*table) + sizeof(*header) + relocSize);
+}
+
 } // namespace lld::coff
diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
index 42284f485e5c07..1c219f2365f669 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -835,6 +835,43 @@ class ECExportThunkChunk : public NonSectionCodeChunk {
   Defined *target;
 };
 
+// ARM64X entry for dynamic relocations.
+class Arm64XDynamicRelocEntry {
+public:
+  Arm64XDynamicRelocEntry(llvm::COFF::Arm64XFixupType type, uint8_t size,
+                          uint32_t offset, uint64_t value)
+      : offset(offset), value(value), type(type), size(size) {}
+
+  size_t getSize() const;
+  void writeTo(uint8_t *buf) const;
+
+  uint32_t offset;
+  uint64_t value;
+
+private:
+  llvm::COFF::Arm64XFixupType type;
+  uint8_t size;
+};
+
+// Dynamic relocation chunk containing ARM64X relocations for the hybrid image.
+class DynamicRelocsChunk : public NonSectionChunk {
+public:
+  DynamicRelocsChunk() {}
+  size_t getSize() const override { return size; }
+  void writeTo(uint8_t *buf) const override;
+  void finalize();
+
+  uint32_t add(llvm::COFF::Arm64XFixupType type, uint8_t size, uint32_t offset,
+               uint64_t value) {
+    arm64xRelocs.emplace_back(type, size, offset, value);
+    return arm64xRelocs.size() - 1;
+  }
+
+private:
+  std::vector<Arm64XDynamicRelocEntry> arm64xRelocs;
+  size_t size;
+};
+
 // MinGW specific, for the "automatic import of variables from DLLs" feature.
 // This provides the table of runtime pseudo relocations, for variable
 // references that turned out to need to be imported from a DLL even though
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index fe78b8cf4ecff7..a25971402d0724 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -272,6 +272,7 @@ class Writer {
   OutputSection *findSection(StringRef name);
   void addBaserels();
   void addBaserelBlocks(std::vector<Baserel> &v);
+  void createDynamicRelocs();
 
   uint32_t getSizeOfInitializedData();
 
@@ -753,6 +754,8 @@ void Writer::run() {
     llvm::TimeTraceScope timeScope("Write PE");
     ScopedTimer t1(ctx.codeLayoutTimer);
 
+    if (ctx.config.machine == ARM64X)
+      ctx.dynamicRelocs = make<DynamicRelocsChunk>();
     createImportTables();
     createSections();
     appendImportThunks();
@@ -763,6 +766,7 @@ void Writer::run() {
     mergeSections();
     sortECChunks();
     appendECImportTables();
+    createDynamicRelocs();
     removeUnusedSections();
     finalizeAddresses();
     removeEmptySections();
@@ -1595,8 +1599,13 @@ void Writer::assignAddresses() {
 
   for (OutputSection *sec : ctx.outputSections) {
     llvm::TimeTraceScope timeScope("Section: ", sec->name);
-    if (sec == relocSec)
+    if (sec == relocSec) {
       addBaserels();
+      if (ctx.dynamicRelocs) {
+        ctx.dynamicRelocs->finalize();
+        relocSec->addChunk(ctx.dynamicRelocs);
+      }
+    }
     uint64_t rawSize = 0, virtualSize = 0;
     sec->header.VirtualAddress = rva;
 
@@ -1797,9 +1806,12 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
                                 exceptionTable.last->getSize() -
                                 exceptionTable.first->getRVA();
   }
-  if (relocSec->getVirtualSize()) {
+  size_t relocSize = relocSec->getVirtualSize();
+  if (ctx.dynamicRelocs)
+    relocSize -= ctx.dynamicRelocs->getSize();
+  if (relocSize) {
     dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = relocSec->getRVA();
-    dir[BASE_RELOCATION_TABLE].Size = relocSec->getVirtualSize();
+    dir[BASE_RELOCATION_TABLE].Size = relocSize;
   }
   if (Symbol *sym = ctx.symtab.findUnderscore("_tls_used")) {
     if (Defined *b = dyn_cast<Defined>(sym)) {
@@ -2554,6 +2566,33 @@ void Writer::addBaserelBlocks(std::vector<Baserel> &v) {
   relocSec->addChunk(make<BaserelChunk>(page, &v[i], &v[0] + j));
 }
 
+void Writer::createDynamicRelocs() {
+  if (!ctx.dynamicRelocs)
+    return;
+
+  const uint32_t coffHeaderOffset = dosStubSize + sizeof(PEMagic);
+  const uint32_t peHeaderOffset = coffHeaderOffset + sizeof(coff_file_header);
+  const uint32_t dataDirOffset = peHeaderOffset + sizeof(pe32plus_header);
+
+  // Adjust the Machine field in the COFF header to AMD64.
+  ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint16_t),
+                         coffHeaderOffset + offsetof(coff_file_header, Machine),
+                         AMD64);
+
+  // Adjust the load config directory.
+  // FIXME: Use the hybrid load config value instead.
+  ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
+                         dataDirOffset +
+                             LOAD_CONFIG_TABLE * sizeof(data_directory) +
+                             offsetof(data_directory, RelativeVirtualAddress),
+                         0);
+  ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
+                         dataDirOffset +
+                             LOAD_CONFIG_TABLE * sizeof(data_directory) +
+                             offsetof(data_directory, Size),
+                         0);
+}
+
 PartialSection *Writer::createPartialSection(StringRef name,
                                              uint32_t outChars) {
   PartialSection *&pSec = partialSections[{name, outChars}];
@@ -2656,6 +2695,18 @@ template <typename T> void Writer::prepareLoadConfig(T *loadConfig) {
     loadConfig->DependentLoadFlags = ctx.config.dependentLoadFlags;
   }
 
+  if (ctx.dynamicRelocs) {
+    IF_CONTAINS(DynamicValueRelocTableSection) {
+      loadConfig->DynamicValueRelocTableSection = relocSec->sectionIndex;
+      loadConfig->DynamicValueRelocTableOffset =
+          ctx.dynamicRelocs->getRVA() - relocSec->getRVA();
+    }
+    else {
+      warn("'_load_config_used' structure too small to include dynamic "
+           "relocations");
+    }
+  }
+
   if (ctx.config.guardCF == GuardCFLevel::Off)
     return;
   RETURN_IF_NOT_CONTAINS(GuardFlags)
diff --git a/lld/test/COFF/arm64x-loadconfig.s b/lld/test/COFF/arm64x-loadconfig.s
new file mode 100644
index 00000000000000..53f42b8f6e680d
--- /dev/null
+++ b/lld/test/COFF/arm64x-loadconfig.s
@@ -0,0 +1,68 @@
+// REQUIRES: aarch64
+// RUN: split-file %s %t.dir && cd %t.dir
+
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows test.s -o test.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows loadconfig.s -o loadconfig.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows loadconfig-short.s -o loadconfig-short.obj
+
+// RUN: lld-link -machine:arm64x -out:out.dll -dll -noentry loadconfig.obj test.obj
+
+// RUN: llvm-readobj --coff-load-config out.dll | FileCheck -check-prefix=DYNRELOCS %s
+// DYNRELOCS:      DynamicValueRelocTableOffset: 0xC
+// DYNRELOCS-NEXT: DynamicValueRelocTableSection: 4
+// DYNRELOCS:      DynamicRelocations [
+// DYNRELOCS-NEXT:   Version: 0x1
+// DYNRELOCS-NEXT:   Arm64X [
+// DYNRELOCS-NEXT:     Entry [
+// DYNRELOCS-NEXT:       RVA: 0x7C
+// DYNRELOCS-NEXT:       Type: VALUE
+// DYNRELOCS-NEXT:       Size: 0x2
+// DYNRELOCS-NEXT:       Value: 0x8664
+// DYNRELOCS-NEXT:     ]
+// DYNRELOCS-NEXT:     Entry [
+// DYNRELOCS-NEXT:       RVA: 0x150
+// DYNRELOCS-NEXT:       Type: VALUE
+// DYNRELOCS-NEXT:       Size: 0x4
+// DYNRELOCS-NEXT:       Value: 0x0
+// DYNRELOCS-NEXT:     ]
+// DYNRELOCS-NEXT:     Entry [
+// DYNRELOCS-NEXT:       RVA: 0x154
+// DYNRELOCS-NEXT:       Type: VALUE
+// DYNRELOCS-NEXT:       Size: 0x4
+// DYNRELOCS-NEXT:       Value: 0x0
+// DYNRELOCS-NEXT:     ]
+// DYNRELOCS-NEXT:   ]
+// DYNRELOCS-NEXT: ]
+
+// RUN: llvm-readobj --headers out.dll | FileCheck -check-prefix=HEADERS %s
+// HEADERS:      BaseRelocationTableRVA: 0x4000
+// HEADERS-NEXT: BaseRelocationTableSize: 0xC
+// HEADERS:       LoadConfigTableRVA: 0x1000
+// HEADERS-NEXT:  LoadConfigTableSize: 0x140
+// HEADERS:       Name: .reloc (2E 72 65 6C 6F 63 00 00)
+// HEADERS-NEXT:  VirtualSize: 0x38
+
+// RUN: lld-link -machine:arm64x -out:out-short.dll -dll -noentry loadconfig-short.obj 2>&1 | FileCheck --check-prefix=WARN-RELOC-SIZE %s
+// WARN-RELOC-SIZE: lld-link: warning: '_load_config_used' structure too small to include dynamic relocations
+
+#--- test.s
+        .data
+sym:
+        // Emit a basereloc to make the loadconfig test more meaningful.
+        .xword sym
+
+#--- loadconfig.s
+        .section .rdata,"dr"
+        .globl _load_config_used
+        .p2align 3, 0
+_load_config_used:
+        .word 0x140
+        .fill 0x13c,1,0
+
+#--- loadconfig-short.s
+        .section .rdata,"dr"
+        .globl _load_config_used
+        .p2align 3, 0
+_load_config_used:
+        .word 0xe4
+        .fill 0xe0,1,0

>From 2f43992830d6d22d449eb5adc9b60c948277f65a Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Tue, 3 Dec 2024 21:25:27 +0100
Subject: [PATCH 3/3] Address review comments

---
 lld/COFF/Chunks.cpp | 14 +++++---------
 lld/COFF/Chunks.h   |  5 ++---
 lld/COFF/Writer.cpp | 21 +++++++++++++--------
 3 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index a4bd6df6c0ec0d..23fab0e66bb67f 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -1214,19 +1214,15 @@ void DynamicRelocsChunk::writeTo(uint8_t *buf) const {
 
   auto pageHeader = reinterpret_cast<coff_base_reloc_block_header *>(buf);
   pageHeader->BlockSize = sizeof(*pageHeader);
-  size_t relocSize = sizeof(*pageHeader);
   for (const Arm64XDynamicRelocEntry &entry : arm64xRelocs) {
-    entry.writeTo(buf + relocSize);
-    size_t entrySize = entry.getSize();
-    pageHeader->BlockSize += entrySize;
-    relocSize += entrySize;
+    entry.writeTo(buf + pageHeader->BlockSize);
+    pageHeader->BlockSize += entry.getSize();
   }
   pageHeader->BlockSize = alignTo(pageHeader->BlockSize, sizeof(uint32_t));
-  relocSize = alignTo(relocSize, sizeof(uint32_t));
 
-  header->BaseRelocSize = relocSize;
-  table->Size += relocSize;
-  assert(size == sizeof(*table) + sizeof(*header) + relocSize);
+  header->BaseRelocSize = pageHeader->BlockSize;
+  table->Size += header->BaseRelocSize;
+  assert(size == sizeof(*table) + sizeof(*header) + header->BaseRelocSize);
 }
 
 } // namespace lld::coff
diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
index 1c219f2365f669..0d2b2ac0f15ea9 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -861,10 +861,9 @@ class DynamicRelocsChunk : public NonSectionChunk {
   void writeTo(uint8_t *buf) const override;
   void finalize();
 
-  uint32_t add(llvm::COFF::Arm64XFixupType type, uint8_t size, uint32_t offset,
-               uint64_t value) {
+  void add(llvm::COFF::Arm64XFixupType type, uint8_t size, uint32_t offset,
+           uint64_t value) {
     arm64xRelocs.emplace_back(type, size, offset, value);
-    return arm64xRelocs.size() - 1;
   }
 
 private:
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index a25971402d0724..fbaeb321fc4d18 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -79,6 +79,11 @@ static_assert(sizeof(dosProgram) % 8 == 0,
 
 static const int dosStubSize = sizeof(dos_header) + sizeof(dosProgram);
 static_assert(dosStubSize % 8 == 0, "DOSStub size must be multiple of 8");
+static const uint32_t coffHeaderOffset = dosStubSize + sizeof(PEMagic);
+static const uint32_t peHeaderOffset =
+    coffHeaderOffset + sizeof(coff_file_header);
+static const uint32_t dataDirOffset64 =
+    peHeaderOffset + sizeof(pe32plus_header);
 
 static const int numberOfDataDirectory = 16;
 
@@ -1600,6 +1605,7 @@ void Writer::assignAddresses() {
   for (OutputSection *sec : ctx.outputSections) {
     llvm::TimeTraceScope timeScope("Section: ", sec->name);
     if (sec == relocSec) {
+      sec->chunks.clear();
       addBaserels();
       if (ctx.dynamicRelocs) {
         ctx.dynamicRelocs->finalize();
@@ -1680,6 +1686,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
   buf += sizeof(PEMagic);
 
   // Write COFF header
+  assert(coffHeaderOffset == buf - buffer->getBufferStart());
   auto *coff = reinterpret_cast<coff_file_header *>(buf);
   buf += sizeof(*coff);
   switch (config->machine) {
@@ -1712,6 +1719,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
       sizeof(PEHeaderTy) + sizeof(data_directory) * numberOfDataDirectory;
 
   // Write PE header
+  assert(peHeaderOffset == buf - buffer->getBufferStart());
   auto *pe = reinterpret_cast<PEHeaderTy *>(buf);
   buf += sizeof(*pe);
   pe->Magic = config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32;
@@ -1777,6 +1785,8 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
   pe->SizeOfInitializedData = getSizeOfInitializedData();
 
   // Write data directory
+  assert(!ctx.config.is64() ||
+         dataDirOffset64 == buf - buffer->getBufferStart());
   auto *dir = reinterpret_cast<data_directory *>(buf);
   buf += sizeof(*dir) * numberOfDataDirectory;
   if (edataStart) {
@@ -2532,7 +2542,6 @@ uint32_t Writer::getSizeOfInitializedData() {
 void Writer::addBaserels() {
   if (!ctx.config.relocatable)
     return;
-  relocSec->chunks.clear();
   std::vector<Baserel> v;
   for (OutputSection *sec : ctx.outputSections) {
     if (sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
@@ -2570,24 +2579,20 @@ void Writer::createDynamicRelocs() {
   if (!ctx.dynamicRelocs)
     return;
 
-  const uint32_t coffHeaderOffset = dosStubSize + sizeof(PEMagic);
-  const uint32_t peHeaderOffset = coffHeaderOffset + sizeof(coff_file_header);
-  const uint32_t dataDirOffset = peHeaderOffset + sizeof(pe32plus_header);
-
   // Adjust the Machine field in the COFF header to AMD64.
   ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint16_t),
                          coffHeaderOffset + offsetof(coff_file_header, Machine),
                          AMD64);
 
-  // Adjust the load config directory.
+  // Clear the load config directory.
   // FIXME: Use the hybrid load config value instead.
   ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
-                         dataDirOffset +
+                         dataDirOffset64 +
                              LOAD_CONFIG_TABLE * sizeof(data_directory) +
                              offsetof(data_directory, RelativeVirtualAddress),
                          0);
   ctx.dynamicRelocs->add(IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE, sizeof(uint32_t),
-                         dataDirOffset +
+                         dataDirOffset64 +
                              LOAD_CONFIG_TABLE * sizeof(data_directory) +
                              offsetof(data_directory, Size),
                          0);



More information about the llvm-commits mailing list