diff options
-rw-r--r-- | llvm/test/tools/llvm-objcopy/COFF/Inputs/x86_64-xrelocs.obj.gz | bin | 0 -> 88299 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-objcopy/COFF/add-section.test | 32 | ||||
-rw-r--r-- | llvm/tools/llvm-objcopy/COFF/Reader.cpp | 4 | ||||
-rw-r--r-- | llvm/tools/llvm-objcopy/COFF/Writer.cpp | 22 |
4 files changed, 52 insertions, 6 deletions
diff --git a/llvm/test/tools/llvm-objcopy/COFF/Inputs/x86_64-xrelocs.obj.gz b/llvm/test/tools/llvm-objcopy/COFF/Inputs/x86_64-xrelocs.obj.gz Binary files differnew file mode 100644 index 00000000000..9b3cf4ad0e0 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/COFF/Inputs/x86_64-xrelocs.obj.gz diff --git a/llvm/test/tools/llvm-objcopy/COFF/add-section.test b/llvm/test/tools/llvm-objcopy/COFF/add-section.test index 4422e31a99c..e8492c2c653 100644 --- a/llvm/test/tools/llvm-objcopy/COFF/add-section.test +++ b/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 diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.cpp b/llvm/tools/llvm-objcopy/COFF/Reader.cpp index 2fcec0057c0..7be9cce2be3 100644 --- a/llvm/tools/llvm-objcopy/COFF/Reader.cpp +++ b/llvm/tools/llvm-objcopy/COFF/Reader.cpp @@ -63,6 +63,7 @@ Error COFFReader::readSections(Object &Obj) const { Sections.push_back(Section()); Section &S = Sections.back(); S.Header = *Sec; + S.Header.Characteristics &= ~COFF::IMAGE_SCN_LNK_NRELOC_OVFL; ArrayRef<uint8_t> Contents; if (Error E = COFFObj.getSectionContents(Sec, Contents)) return E; @@ -74,9 +75,6 @@ Error COFFReader::readSections(Object &Obj) const { 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(); diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp index 6db37435fd9..e35e0474a36 100644 --- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp +++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp @@ -97,9 +97,16 @@ void COFFWriter::layoutSections() { 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 @@ void COFFWriter::writeSections() { 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); |