diff --git a/llvm/lib/ObjectYAML/COFFEmitter.cpp b/llvm/lib/ObjectYAML/COFFEmitter.cpp --- a/llvm/lib/ObjectYAML/COFFEmitter.cpp +++ b/llvm/lib/ObjectYAML/COFFEmitter.cpp @@ -260,9 +260,12 @@ CurrentSectionDataOffset += S.Header.SizeOfRawData; if (!S.Relocations.empty()) { S.Header.PointerToRelocations = CurrentSectionDataOffset; - S.Header.NumberOfRelocations = S.Relocations.size(); - CurrentSectionDataOffset += - S.Header.NumberOfRelocations * COFF::RelocationSize; + if (S.Header.Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) { + S.Header.NumberOfRelocations = 0xffff; + CurrentSectionDataOffset += COFF::RelocationSize; + } else + S.Header.NumberOfRelocations = S.Relocations.size(); + CurrentSectionDataOffset += S.Relocations.size() * COFF::RelocationSize; } } else { // Leave SizeOfRawData unaltered. For .bss sections in object files, it @@ -506,6 +509,10 @@ S.SectionData.writeAsBinary(OS); assert(S.Header.SizeOfRawData >= S.SectionData.binary_size()); OS.write_zeros(S.Header.SizeOfRawData - S.SectionData.binary_size()); + if (S.Header.Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) + OS << binary_le(/*VirtualAddress=*/ S.Relocations.size() + 1) + << binary_le(/*SymbolTableIndex=*/ 0) + << binary_le(/*Type=*/ 0); for (const COFFYAML::Relocation &R : S.Relocations) { uint32_t SymbolTableIndex; if (R.SymbolTableIndex) { diff --git a/llvm/test/tools/yaml2obj/coff-xrelocs.yaml b/llvm/test/tools/yaml2obj/coff-xrelocs.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/yaml2obj/coff-xrelocs.yaml @@ -0,0 +1,71 @@ +## This test checks that yaml2obj correctly handles COFF sections with +## extended relocation tables (IMAGE_SCN_LNK_NRELOC_OVFL). +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj --sections --relocations %t | FileCheck %s --check-prefix=CHECK-OBJ +# RUN: obj2yaml %t | FileCheck %s --check-prefix=CHECK-YAML + +# CHECK-OBJ: Sections [ +# CHECK-OBJ-NEXT: Section { +# CHECK-OBJ-NEXT: Number: 1 +# CHECK-OBJ-NEXT: Name: .data +# CHECK-OBJ: RawDataSize: 16 +# CHECK-OBJ: RelocationCount: 65535 +# CHECK-OBJ: Characteristics [ +# CHECK-OBJ-NEXT: IMAGE_SCN_ALIGN_16BYTES +# CHECK-OBJ-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA +# CHECK-OBJ-NEXT: IMAGE_SCN_LNK_NRELOC_OVFL +# CHECK-OBJ-NEXT: IMAGE_SCN_MEM_READ +# CHECK-OBJ-NEXT: ] +# CHECK-OBJ-NEXT: } +# CHECK-OBJ-NEXT: ] +# CHECK-OBJ-NEXT: Relocations [ +# CHECK-OBJ-NEXT: Section (1) .data { +# CHECK-OBJ-NEXT: 0x0 IMAGE_REL_AMD64_ADDR64 foo (0) +# CHECK-OBJ-NEXT: 0x8 IMAGE_REL_AMD64_ADDR64 bar (1) +# CHECK-OBJ-NEXT: } +# CHECK-OBJ-NEXT: ] + +# CHECK-YAML: sections: +# CHECK-YAML-NEXT: - Name: .data +# CHECK-YAML-NEXT: Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_NRELOC_OVFL, IMAGE_SCN_MEM_READ ] +# CHECK-YAML-NEXT: Alignment: 16 +# CHECK-YAML-NEXT: SectionData: '00000000000000000000000000000000' +# CHECK-YAML-NEXT: Relocations: +# CHECK-YAML-NEXT: - VirtualAddress: 0 +# CHECK-YAML-NEXT: SymbolName: foo +# CHECK-YAML-NEXT: Type: IMAGE_REL_AMD64_ADDR64 +# CHECK-YAML-NEXT: - VirtualAddress: 8 +# CHECK-YAML-NEXT: SymbolName: bar +# CHECK-YAML-NEXT: Type: IMAGE_REL_AMD64_ADDR64 +# CHECK-YAML-NEXT: symbols: + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_NRELOC_OVFL, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: '00000000000000000000000000000000' + Relocations: + - VirtualAddress: 0 + SymbolName: foo + Type: IMAGE_REL_AMD64_ADDR64 + - VirtualAddress: 8 + SymbolName: bar + Type: IMAGE_REL_AMD64_ADDR64 +symbols: + - Name: foo + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: bar + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +...