diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -386,6 +386,7 @@ private: template void copyRelocations(uint8_t *buf, llvm::ArrayRef rels); + uint64_t getRelocValueForDeletedCode(RelType type, bool isDebugLocOrRanges); template void copyShtGroup(uint8_t *buf); }; diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -842,6 +842,22 @@ } } +// This function returns a special value which is used to indicate +// a reference from a debug section into the deleted code. +uint64_t InputSection::getRelocValueForDeletedCode(RelType type, + bool isDebugLocOrRanges) { + uint64_t res = + isDebugLocOrRanges ? 0xfffffffffffffffeULL : 0xffffffffffffffffULL; + + if (config->is64) { + if ((config->emachine == EM_X86_64 && type == R_X86_64_32) || + (config->emachine == EM_SPARCV9 && type == R_SPARC_32)) + res &= 0x00000000ffffffffULL; + } + + return res; +} + // This function applies relocations to sections without SHF_ALLOC bit. // Such sections are never mapped to memory at runtime. Debug sections are // an example. Relocations in non-alloc sections are much easier to @@ -853,6 +869,11 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { const unsigned bits = sizeof(typename ELFT::uint) * 8; + bool isDebug = isDebugSection(*this); + StringRef noPrefixName = name.substr(name.find_first_not_of(".z")); + bool isDebugLocOrRanges = + noPrefixName == "debug_loc" || noPrefixName == "debug_ranges"; + for (const RelTy &rel : rels) { RelType type = rel.getType(config->isMips64EL); @@ -904,9 +925,15 @@ if (sym.isTls() && !Out::tlsPhdr) target->relocateNoSym(bufLoc, type, 0); - else + else if (sym.getOutputSection() || !isDebug) target->relocateNoSym(bufLoc, type, SignExtend64(sym.getVA(addend))); + // If the relocation from .debug* section points to a deleted section, + // e.g. due to --gc-sections, then it is neccessary to resolve it + // to the special value indicating deleted code. + else + target->relocateNoSym( + bufLoc, type, getRelocValueForDeletedCode(type, isDebugLocOrRanges)); } } diff --git a/lld/test/ELF/aarch64-gc-sections-debug-data-32.s b/lld/test/ELF/aarch64-gc-sections-debug-data-32.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/aarch64-gc-sections-debug-data-32.s @@ -0,0 +1,76 @@ +# REQUIRES: aarch64 + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=aarch64_32-unknown-linux %s -o %t.32 +# RUN: ld.lld %t.32 -o %t2.32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.32 | FileCheck %s + +# RUN: llvm-mc --filetype=obj -triple=aarch64_32-unknown-linux32 %s -o %t.ilp32 +# RUN: ld.lld %t.ilp32 -o %t2.ilp32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.ilp32 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .long .text; +.section .debug_loc,"",@progbits; + .long .text +.section .debug_ranges,"",@progbits; + .long .text diff --git a/lld/test/ELF/aarch64-gc-sections-debug-data-64.s b/lld/test/ELF/aarch64-gc-sections-debug-data-64.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/aarch64-gc-sections-debug-data-64.s @@ -0,0 +1,72 @@ +# REQUIRES: aarch64 + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=aarch64-unknown-linux %s -o %t.64 +# RUN: ld.lld %t.64 -o %t2.64 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.64 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .quad .text; +.section .debug_loc,"",@progbits; + .quad .text; +.section .debug_ranges,"",@progbits; + .quad .text; diff --git a/lld/test/ELF/arm-gc-sections-debug-data-32.s b/lld/test/ELF/arm-gc-sections-debug-data-32.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/arm-gc-sections-debug-data-32.s @@ -0,0 +1,76 @@ +# REQUIRES: arm + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=arm64_32-unknown-linux %s -o %t.32 +# RUN: ld.lld %t.32 -o %t2.32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.32 | FileCheck %s + +# RUN: llvm-mc --filetype=obj -triple=arm64_32-unknown-linux32 %s -o %t.ilp32 +# RUN: ld.lld %t.ilp32 -o %t2.ilp32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.ilp32 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .long .text; +.section .debug_loc,"",@progbits; + .long .text +.section .debug_ranges,"",@progbits; + .long .text diff --git a/lld/test/ELF/arm-gc-sections-debug-data-64.s b/lld/test/ELF/arm-gc-sections-debug-data-64.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/arm-gc-sections-debug-data-64.s @@ -0,0 +1,72 @@ +# REQUIRES: arm + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=arm64-unknown-linux %s -o %t.64 +# RUN: ld.lld %t.64 -o %t2.64 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.64 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .quad .text; +.section .debug_loc,"",@progbits; + .quad .text; +.section .debug_ranges,"",@progbits; + .quad .text; diff --git a/lld/test/ELF/mips-gc-sections-debug-data-32.s b/lld/test/ELF/mips-gc-sections-debug-data-32.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/mips-gc-sections-debug-data-32.s @@ -0,0 +1,76 @@ +# REQUIRES: mips + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=mips-unknown-linux %s -o %t.32 +# RUN: ld.lld %t.32 -o %t2.32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.32 | FileCheck %s + +# RUN: llvm-mc --filetype=obj -triple=mips64-unknown-linux32 %s -o %t.ilp32 +# RUN: ld.lld %t.ilp32 -o %t2.ilp32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.ilp32 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_MIPS_DWARF (0x7000001E) +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_MIPS_DWARF (0x7000001E) +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFE +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_MIPS_DWARF (0x7000001E) +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFE +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@0x7000001e; + .long .text; +.section .debug_loc,"",@0x7000001e; + .long .text +.section .debug_ranges,"",@0x7000001e; + .long .text diff --git a/lld/test/ELF/mips-gc-sections-debug-data-64.s b/lld/test/ELF/mips-gc-sections-debug-data-64.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/mips-gc-sections-debug-data-64.s @@ -0,0 +1,72 @@ +# REQUIRES: mips + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=mips64-unknown-linux %s -o %t.64 +# RUN: ld.lld %t.64 -o %t2.64 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.64 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_MIPS_DWARF (0x7000001E) +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_MIPS_DWARF (0x7000001E) +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFE +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_MIPS_DWARF (0x7000001E) +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFE +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@0x7000001e; + .quad .text; +.section .debug_loc,"",@0x7000001e; + .quad .text; +.section .debug_ranges,"",@0x7000001e; + .quad .text; diff --git a/lld/test/ELF/ppc-gc-sections-debug-data-32.s b/lld/test/ELF/ppc-gc-sections-debug-data-32.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/ppc-gc-sections-debug-data-32.s @@ -0,0 +1,76 @@ +# REQUIRES: ppc + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=ppc-unknown-linux %s -o %t.32 +# RUN: ld.lld %t.32 -o %t2.32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.32 | FileCheck %s + +# RUN: llvm-mc --filetype=obj -triple=ppc64-unknown-linux32 %s -o %t.ilp32 +# RUN: ld.lld %t.ilp32 -o %t2.ilp32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.ilp32 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFE +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFE +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .long .text; +.section .debug_loc,"",@progbits; + .long .text +.section .debug_ranges,"",@progbits; + .long .text diff --git a/lld/test/ELF/ppc-gc-sections-debug-data-64.s b/lld/test/ELF/ppc-gc-sections-debug-data-64.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/ppc-gc-sections-debug-data-64.s @@ -0,0 +1,72 @@ +# REQUIRES: ppc + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=ppc64-unknown-linux %s -o %t.64 +# RUN: ld.lld %t.64 -o %t2.64 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.64 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFE +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFE +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .quad .text; +.section .debug_loc,"",@progbits; + .quad .text; +.section .debug_ranges,"",@progbits; + .quad .text; diff --git a/lld/test/ELF/riscv-gc-sections-debug-data-32.s b/lld/test/ELF/riscv-gc-sections-debug-data-32.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/riscv-gc-sections-debug-data-32.s @@ -0,0 +1,76 @@ +# REQUIRES: riscv + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=riscv32-unknown-linux %s -o %t.32 +# RUN: ld.lld %t.32 -o %t2.32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.32 | FileCheck %s + +# RUN: llvm-mc --filetype=obj -triple=riscv64-unknown-linux32 %s -o %t.ilp32 +# RUN: ld.lld %t.ilp32 -o %t2.ilp32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.ilp32 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .long .text; +.section .debug_loc,"",@progbits; + .long .text +.section .debug_ranges,"",@progbits; + .long .text diff --git a/lld/test/ELF/riscv-gc-sections-debug-data-64.s b/lld/test/ELF/riscv-gc-sections-debug-data-64.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/riscv-gc-sections-debug-data-64.s @@ -0,0 +1,72 @@ +# REQUIRES: riscv + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=riscv64-unknown-linux %s -o %t.64 +# RUN: ld.lld %t.64 -o %t2.64 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.64 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .quad .text; +.section .debug_loc,"",@progbits; + .quad .text; +.section .debug_ranges,"",@progbits; + .quad .text; diff --git a/lld/test/ELF/sparc-gc-sections-debug-data-32.s b/lld/test/ELF/sparc-gc-sections-debug-data-32.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/sparc-gc-sections-debug-data-32.s @@ -0,0 +1,72 @@ +# REQUIRES: sparc + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=sparcv9-unknown-linux32 %s -o %t.ilp32 +# RUN: ld.lld %t.ilp32 -o %t2.ilp32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.ilp32 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFE +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFE +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .long .text; +.section .debug_loc,"",@progbits; + .long .text +.section .debug_ranges,"",@progbits; + .long .text diff --git a/lld/test/ELF/sparc-gc-sections-debug-data-64.s b/lld/test/ELF/sparc-gc-sections-debug-data-64.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/sparc-gc-sections-debug-data-64.s @@ -0,0 +1,72 @@ +# REQUIRES: sparc + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=sparcv9-unknown-linux %s -o %t.64 +# RUN: ld.lld %t.64 -o %t2.64 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.64 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFE +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFE +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .quad .text; +.section .debug_loc,"",@progbits; + .quad .text; +.section .debug_ranges,"",@progbits; + .quad .text; diff --git a/lld/test/ELF/x86-gc-sections-debug-data-32.s b/lld/test/ELF/x86-gc-sections-debug-data-32.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/x86-gc-sections-debug-data-32.s @@ -0,0 +1,76 @@ +# REQUIRES: x86 + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=i386-unknown-linux %s -o %t.32 +# RUN: ld.lld %t.32 -o %t2.32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.32 | FileCheck %s + +# RUN: llvm-mc --filetype=obj -triple=x86_64-unknown-linux32 %s -o %t.ilp32 +# RUN: ld.lld %t.ilp32 -o %t2.ilp32 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.ilp32 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .long .text; +.section .debug_loc,"",@progbits; + .long .text +.section .debug_ranges,"",@progbits; + .long .text diff --git a/lld/test/ELF/x86-gc-sections-debug-data-64.s b/lld/test/ELF/x86-gc-sections-debug-data-64.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/x86-gc-sections-debug-data-64.s @@ -0,0 +1,72 @@ +# REQUIRES: x86 + +# When --gc-sections is used, the linker deletes unused text sections, +# but their debug data is left in the binary. That debug data could have relocations +# pointing to deleted sections. Address ranges of such debug data could overlap +# with other address ranges for correct debug data. To prevent addresses clashing +# it is neccessary to resolve such relocations to a predefined value. +# This test checks that relocations from the .debug_foo +# section pointing to a deleted .text section are resolved +# to 0xffffffffffffffff and relocations from the .debug_loc and .debug_ranges +# sections pointing to a deleted .text section are resolved +# to 0xfffffffffffffffe. + +# RUN: llvm-mc --filetype=obj -triple=x86_64-unknown-linux %s -o %t.64 +# RUN: ld.lld %t.64 -o %t2.64 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2.64 | FileCheck %s + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FFFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_loc +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +# CHECK: Name: .debug_ranges +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: FEFFFFFF FFFFFFFF +# CHECK-NEXT: ) + +.section .text,"a"; + .byte 0; +.section .debug_foo,"",@progbits; + .quad .text; +.section .debug_loc,"",@progbits; + .quad .text; +.section .debug_ranges,"",@progbits; + .quad .text;