[PATCH] Object/COFF: Support large relocation table.
Rui Ueyama
ruiu at google.com
Thu Mar 20 17:03:11 PDT 2014
Hi majnemer,
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.
http://llvm-reviews.chandlerc.com/D3139
Files:
lib/Object/COFFObjectFile.cpp
test/tools/llvm-objdump/Inputs/many-relocs.obj-i386
test/tools/llvm-objdump/coff-many-relocs.test
Index: lib/Object/COFFObjectFile.cpp
===================================================================
--- lib/Object/COFFObjectFile.cpp
+++ lib/Object/COFFObjectFile.cpp
@@ -367,25 +367,48 @@
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->Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL &&
+ Sec->NumberOfRelocations == UINT16_MAX) {
+ // 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->Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL &&
+ Sec->NumberOfRelocations == UINT16_MAX) {
+ 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));
}
Index: test/tools/llvm-objdump/coff-many-relocs.test
===================================================================
--- /dev/null
+++ test/tools/llvm-objdump/coff-many-relocs.test
@@ -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: 10 IMAGE_REL_I386_DIR16 foo
+CHECK-NEXT: 17 IMAGE_REL_I386_REL16 foo
+CHECK-NEXT: 24 IMAGE_REL_I386_DIR32 foo
+CHECK-NEXT: 31 IMAGE_REL_I386_DIR32NB foo
+CHECK-NEXT: 38 IMAGE_REL_I386_SEG12 foo
+CHECK-NEXT: 45 IMAGE_REL_I386_SECTION foo
+CHECK-NEXT: 52 IMAGE_REL_I386_SECREL foo
+CHECK-NEXT: 59 IMAGE_REL_I386_TOKEN foo
+CHECK-NEXT: 66 IMAGE_REL_I386_SECREL7 foo
+CHECK-NEXT: 73 IMAGE_REL_I386_REL32 foo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3139.1.patch
Type: text/x-patch
Size: 3276 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140320/84f645e0/attachment.bin>
More information about the llvm-commits
mailing list