[llvm] r204418 - Object/COFF: Support large relocation table.

Rui Ueyama ruiu at google.com
Thu Mar 20 17:44:19 PDT 2014


Author: ruiu
Date: Thu Mar 20 19:44:19 2014
New Revision: 204418

URL: http://llvm.org/viewvc/llvm-project?rev=204418&view=rev
Log:
Object/COFF: Support large relocation table.

NumberOfRelocations field in COFF section table is only 16-bit wide. If an
object has more than 65535 relocations, the number of relocations is stored
to VirtualAddress field in the first relocation field, and a special flag
(IMAGE_SCN_LNK_NRELOC_OVFL) is set to Characteristics field.

In test we cheated a bit. I made up a test file so that it has
IMAGE_SCN_LNK_NRELOC_OVFL flag but the number of relocations is much smaller
than 65535. This is to avoid checking in a large test file just to test a
file with many relocations.

Differential Revision: http://llvm-reviews.chandlerc.com/D3139

Added:
    llvm/trunk/test/tools/llvm-objdump/Inputs/many-relocs.obj-i386
    llvm/trunk/test/tools/llvm-objdump/coff-many-relocs.test
Modified:
    llvm/trunk/include/llvm/Object/COFF.h
    llvm/trunk/lib/Object/COFFObjectFile.cpp

Modified: llvm/trunk/include/llvm/Object/COFF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/COFF.h?rev=204418&r1=204417&r2=204418&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/COFF.h (original)
+++ llvm/trunk/include/llvm/Object/COFF.h Thu Mar 20 19:44:19 2014
@@ -250,6 +250,13 @@ struct coff_section {
   support::ulittle16_t NumberOfRelocations;
   support::ulittle16_t NumberOfLinenumbers;
   support::ulittle32_t Characteristics;
+
+  // Returns true if the actual number of relocations is stored in
+  // VirtualAddress field of the first relocation table entry.
+  bool hasExtendedRelocations() const {
+    return Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL &&
+        NumberOfRelocations == UINT16_MAX;
+  };
 };
 
 struct coff_relocation {

Modified: llvm/trunk/lib/Object/COFFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/COFFObjectFile.cpp?rev=204418&r1=204417&r2=204418&view=diff
==============================================================================
--- llvm/trunk/lib/Object/COFFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/COFFObjectFile.cpp Thu Mar 20 19:44:19 2014
@@ -367,25 +367,46 @@ error_code COFFObjectFile::sectionContai
 relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
   const coff_section *Sec = toSec(Ref);
   DataRefImpl Ret;
-  if (Sec->NumberOfRelocations == 0)
+  if (Sec->NumberOfRelocations == 0) {
     Ret.p = 0;
-  else
-    Ret.p = reinterpret_cast<uintptr_t>(base() + Sec->PointerToRelocations);
-
+  } else {
+    auto begin = reinterpret_cast<const coff_relocation*>(
+        base() + Sec->PointerToRelocations);
+    if (Sec->hasExtendedRelocations()) {
+      // Skip the first relocation entry repurposed to store the number of
+      // relocations.
+      begin++;
+    }
+    Ret.p = reinterpret_cast<uintptr_t>(begin);
+  }
   return relocation_iterator(RelocationRef(Ret, this));
 }
 
+static uint32_t getNumberOfRelocations(const coff_section *Sec,
+                                       const uint8_t *base) {
+  // The field for the number of relocations in COFF section table is only
+  // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
+  // NumberOfRelocations field, and the actual relocation count is stored in the
+  // VirtualAddress field in the first relocation entry.
+  if (Sec->hasExtendedRelocations()) {
+    auto *FirstReloc = reinterpret_cast<const coff_relocation*>(
+        base + Sec->PointerToRelocations);
+    return FirstReloc->VirtualAddress;
+  }
+  return Sec->NumberOfRelocations;
+}
+
 relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
   const coff_section *Sec = toSec(Ref);
   DataRefImpl Ret;
-  if (Sec->NumberOfRelocations == 0)
+  if (Sec->NumberOfRelocations == 0) {
     Ret.p = 0;
-  else
-    Ret.p = reinterpret_cast<uintptr_t>(
-              reinterpret_cast<const coff_relocation*>(
-                base() + Sec->PointerToRelocations)
-              + Sec->NumberOfRelocations);
-
+  } else {
+    auto begin = reinterpret_cast<const coff_relocation*>(
+        base() + Sec->PointerToRelocations);
+    uint32_t NumReloc = getNumberOfRelocations(Sec, base());
+    Ret.p = reinterpret_cast<uintptr_t>(begin + NumReloc);
+  }
   return relocation_iterator(RelocationRef(Ret, this));
 }
 

Added: llvm/trunk/test/tools/llvm-objdump/Inputs/many-relocs.obj-i386
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/Inputs/many-relocs.obj-i386?rev=204418&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/llvm-objdump/Inputs/many-relocs.obj-i386 (added) and llvm/trunk/test/tools/llvm-objdump/Inputs/many-relocs.obj-i386 Thu Mar 20 19:44:19 2014 differ

Added: llvm/trunk/test/tools/llvm-objdump/coff-many-relocs.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/coff-many-relocs.test?rev=204418&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objdump/coff-many-relocs.test (added)
+++ llvm/trunk/test/tools/llvm-objdump/coff-many-relocs.test Thu Mar 20 19:44:19 2014
@@ -0,0 +1,14 @@
+// Test that llvm-objdump can handle IMAGE_SCN_LNK_NRELOC_OVFL.
+// RUN: llvm-objdump -r %p/Inputs/many-relocs.obj-i386 | FileCheck %s
+
+CHECK:      RELOCATION RECORDS FOR [.text]:
+CHECK-NEXT: IMAGE_REL_I386_DIR16 foo
+CHECK-NEXT: IMAGE_REL_I386_REL16 foo
+CHECK-NEXT: IMAGE_REL_I386_DIR32 foo
+CHECK-NEXT: IMAGE_REL_I386_DIR32NB foo
+CHECK-NEXT: IMAGE_REL_I386_SEG12 foo
+CHECK-NEXT: IMAGE_REL_I386_SECTION foo
+CHECK-NEXT: IMAGE_REL_I386_SECREL foo
+CHECK-NEXT: IMAGE_REL_I386_TOKEN foo
+CHECK-NEXT: IMAGE_REL_I386_SECREL7 foo
+CHECK-NEXT: IMAGE_REL_I386_REL32 foo





More information about the llvm-commits mailing list