mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204418 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		@@ -250,6 +250,13 @@ struct coff_section {
 | 
				
			|||||||
  support::ulittle16_t NumberOfRelocations;
 | 
					  support::ulittle16_t NumberOfRelocations;
 | 
				
			||||||
  support::ulittle16_t NumberOfLinenumbers;
 | 
					  support::ulittle16_t NumberOfLinenumbers;
 | 
				
			||||||
  support::ulittle32_t Characteristics;
 | 
					  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 {
 | 
					struct coff_relocation {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -367,25 +367,46 @@ error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef,
 | 
				
			|||||||
relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
 | 
					relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
 | 
				
			||||||
  const coff_section *Sec = toSec(Ref);
 | 
					  const coff_section *Sec = toSec(Ref);
 | 
				
			||||||
  DataRefImpl Ret;
 | 
					  DataRefImpl Ret;
 | 
				
			||||||
  if (Sec->NumberOfRelocations == 0)
 | 
					  if (Sec->NumberOfRelocations == 0) {
 | 
				
			||||||
    Ret.p = 0;
 | 
					    Ret.p = 0;
 | 
				
			||||||
  else
 | 
					  } else {
 | 
				
			||||||
    Ret.p = reinterpret_cast<uintptr_t>(base() + Sec->PointerToRelocations);
 | 
					    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));
 | 
					  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 {
 | 
					relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
 | 
				
			||||||
  const coff_section *Sec = toSec(Ref);
 | 
					  const coff_section *Sec = toSec(Ref);
 | 
				
			||||||
  DataRefImpl Ret;
 | 
					  DataRefImpl Ret;
 | 
				
			||||||
  if (Sec->NumberOfRelocations == 0)
 | 
					  if (Sec->NumberOfRelocations == 0) {
 | 
				
			||||||
    Ret.p = 0;
 | 
					    Ret.p = 0;
 | 
				
			||||||
  else
 | 
					  } else {
 | 
				
			||||||
    Ret.p = reinterpret_cast<uintptr_t>(
 | 
					    auto begin = reinterpret_cast<const coff_relocation*>(
 | 
				
			||||||
              reinterpret_cast<const coff_relocation*>(
 | 
					        base() + Sec->PointerToRelocations);
 | 
				
			||||||
                base() + Sec->PointerToRelocations)
 | 
					    uint32_t NumReloc = getNumberOfRelocations(Sec, base());
 | 
				
			||||||
              + Sec->NumberOfRelocations);
 | 
					    Ret.p = reinterpret_cast<uintptr_t>(begin + NumReloc);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  return relocation_iterator(RelocationRef(Ret, this));
 | 
					  return relocation_iterator(RelocationRef(Ret, this));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								test/tools/llvm-objdump/Inputs/many-relocs.obj-i386
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								test/tools/llvm-objdump/Inputs/many-relocs.obj-i386
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										14
									
								
								test/tools/llvm-objdump/coff-many-relocs.test
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								test/tools/llvm-objdump/coff-many-relocs.test
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
				
			||||||
		Reference in New Issue
	
	Block a user