Index: llvm/test/tools/llvm-objcopy/COFF/add-section.test =================================================================== --- llvm/test/tools/llvm-objcopy/COFF/add-section.test +++ llvm/test/tools/llvm-objcopy/COFF/add-section.test @@ -32,6 +32,38 @@ # CHECK-ADD-EMPTY-NAME-NEXT: 0000: {{.+}}|DEADBEEF{{.+}}| # CHECK-ADD-EMPTY-NAME-NEXT: ) +## Test that llvm-objcopy can add a section to an object with extended +## relocations. +# RUN: %python %p/../Inputs/ungzip.py %p/Inputs/x86_64-xrelocs.obj.gz > %t.in.xrelocs.obj +# RUN: llvm-objcopy --add-section=.test.section=%t.sec %t.in.xrelocs.obj %t1.xrelocs.obj +# RUN: llvm-readobj --file-headers --sections --section-data %t1.xrelocs.obj | FileCheck %s --check-prefixes=CHECK-EXTENDED-RELOCS + +# CHECK-EXTENDED-RELOCS: SectionCount: 5 +# CHECK-EXTENDED-RELOCS: Name: .data +# CHECK-EXTENDED-RELOCS-NEXT: VirtualSize: +# CHECK-EXTENDED-RELOCS-NEXT: VirtualAddress: +# CHECK-EXTENDED-RELOCS-NEXT: RawDataSize: +# CHECK-EXTENDED-RELOCS-NEXT: PointerToRawData: +# CHECK-EXTENDED-RELOCS-NEXT: PointerToRelocations: +# CHECK-EXTENDED-RELOCS-NEXT: PointerToLineNumbers: +# CHECK-EXTENDED-RELOCS-NEXT: RelocationCount: 65535 +# CHECK-EXTENDED-RELOCS-NEXT: LineNumberCount: 0 +# CHECK-EXTENDED-RELOCS-NEXT: Characteristics [ +# CHECK-EXTENDED-RELOCS-NEXT: IMAGE_SCN_ALIGN_16BYTES +# CHECK-EXTENDED-RELOCS-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA +# CHECK-EXTENDED-RELOCS-NEXT: IMAGE_SCN_LNK_NRELOC_OVFL +# CHECK-EXTENDED-RELOCS-NEXT: IMAGE_SCN_MEM_READ +# CHECK-EXTENDED-RELOCS-NEXT: IMAGE_SCN_MEM_WRITE +# CHECK-EXTENDED-RELOCS-NEXT: ] +# CHECK-EXTENDED-RELOCS: Name: .test.section +# CHECK-EXTENDED-RELOCS: Characteristics [ +# CHECK-EXTENDED-RELOCS-NEXT: IMAGE_SCN_ALIGN_1BYTES +# CHECK-EXTENDED-RELOCS-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA +# CHECK-EXTENDED-RELOCS-NEXT: ] +# CHECK-EXTENDED-RELOCS: SectionData ( +# CHECK-EXTENDED-RELOCS-NEXT: 0000: {{.+}}|DEADBEEF{{.+}}| +# CHECK-EXTENDED-RELOCS-NEXT: ) + ## Test that llvm-objcopy produces an error if the file with section contents ## to be added does not exist. # RUN: not llvm-objcopy --add-section=.another.section=%t2 %t %t3 2>&1 | FileCheck -DFILE1=%t -DFILE2=%t2 %s --check-prefixes=ERR1 Index: llvm/tools/llvm-objcopy/COFF/Reader.cpp =================================================================== --- llvm/tools/llvm-objcopy/COFF/Reader.cpp +++ llvm/tools/llvm-objcopy/COFF/Reader.cpp @@ -63,6 +63,7 @@ Sections.push_back(Section()); Section &S = Sections.back(); S.Header = *Sec; + S.Header.Characteristics &= ~COFF::IMAGE_SCN_LNK_NRELOC_OVFL; ArrayRef Contents; if (Error E = COFFObj.getSectionContents(Sec, Contents)) return E; @@ -74,9 +75,6 @@ S.Name = *NameOrErr; else return NameOrErr.takeError(); - if (Sec->hasExtendedRelocations()) - return createStringError(object_error::parse_failed, - "extended relocations not supported yet"); } Obj.addSections(Sections); return Error::success(); Index: llvm/tools/llvm-objcopy/COFF/Writer.cpp =================================================================== --- llvm/tools/llvm-objcopy/COFF/Writer.cpp +++ llvm/tools/llvm-objcopy/COFF/Writer.cpp @@ -97,9 +97,16 @@ S.Header.PointerToRawData = FileSize; FileSize += S.Header.SizeOfRawData; // For executables, this is already // aligned to FileAlignment. - S.Header.NumberOfRelocations = S.Relocs.size(); - S.Header.PointerToRelocations = - S.Header.NumberOfRelocations > 0 ? FileSize : 0; + if (S.Relocs.size() >= 0xffff) { + S.Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; + S.Header.NumberOfRelocations = 0xffff; + S.Header.PointerToRelocations = FileSize; + FileSize += sizeof(coff_relocation); + } else { + S.Header.NumberOfRelocations = S.Relocs.size(); + S.Header.PointerToRelocations = S.Relocs.size() ? FileSize : 0; + } + FileSize += S.Relocs.size() * sizeof(coff_relocation); FileSize = alignTo(FileSize, FileAlignment); @@ -307,6 +314,15 @@ S.Header.SizeOfRawData - Contents.size()); Ptr += S.Header.SizeOfRawData; + + if (S.Relocs.size() >= 0xffff) { + object::coff_relocation R; + R.VirtualAddress = S.Relocs.size() + 1; + R.SymbolTableIndex = 0; + R.Type = 0; + memcpy(Ptr, &R, sizeof(R)); + Ptr += sizeof(R); + } for (const auto &R : S.Relocs) { memcpy(Ptr, &R.Reloc, sizeof(R.Reloc)); Ptr += sizeof(R.Reloc);