Index: lld/ELF/InputSection.h =================================================================== --- lld/ELF/InputSection.h +++ lld/ELF/InputSection.h @@ -72,6 +72,9 @@ unsigned Bss : 1; + // True if this is a debuginfo section. + unsigned Debug : 1; + // Set for sections that should not be folded by ICF. unsigned KeepUnique : 1; @@ -109,7 +112,7 @@ uint64_t Entsize, uint64_t Alignment, uint32_t Type, uint32_t Info, uint32_t Link) : Name(Name), Repl(this), SectionKind(SectionKind), Assigned(false), - Bss(false), KeepUnique(false), Partition(0), Alignment(Alignment), + Bss(false), Debug(false), KeepUnique(false), Partition(0), Alignment(Alignment), Flags(Flags), Entsize(Entsize), Type(Type), Link(Link), Info(Info) {} }; Index: lld/ELF/InputSection.cpp =================================================================== --- lld/ELF/InputSection.cpp +++ lld/ELF/InputSection.cpp @@ -71,6 +71,7 @@ NumRelocations = 0; AreRelocsRela = false; + Debug = Name.startswith(".debug") || Name.startswith(".zdebug"); // The ELF spec states that a value of 0 means the section has // no alignment constraits. @@ -867,8 +868,21 @@ if (Sym.isTls() && !Out::TlsPhdr) Target->relocateOne(BufLoc, Type, 0); - else + else if (Sym.getOutputSection() || !Debug) Target->relocateOne(BufLoc, Type, SignExtend64(Sym.getVA(Addend))); + // If the relocation points to a deleted section, e.g. due to + // --gc-sections, then it is neccessary to make the start offset + // be outside the module address range to not overlap with the module's + // ranges. https://bugs.llvm.org/show_bug.cgi?id=41124 + // We use UINT32_MAX-1 as maximal value of an address on 32-bit + // address space within 64-bit binary(ILP32) because UINT32_MAX + // has special usage in .debug_ranges. + else if (Config->Is64 && Config->EMachine == EM_X86_64 && Type == R_X86_64_32) + Target->relocateOne(BufLoc, Type, 0x00000000fffffffeULL); + // We use UINT64_MAX-1 as maximal value of an address on 64-bit + // address space because UINT64_MAX has special usage in .debug_ranges. + else + Target->relocateOne(BufLoc, Type, 0xfffffffffffffffeULL); } } Index: lld/test/ELF/gc-sections-debuginfo.s =================================================================== --- /dev/null +++ lld/test/ELF/gc-sections-debuginfo.s @@ -0,0 +1,44 @@ +# REQUIRES: x86 + +# RUN: echo '.section .text,"a"; .byte 0; .section .debug_foo,"",@progbits; .quad .text' \ +# RUN: | llvm-mc --filetype=obj -triple=x86_64-unknown-linux - -o %t +# RUN: ld.lld %t -o %t2 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s --check-prefixes=CHECK,CHECK64 + +# RUN: echo '.section .text,"a"; .byte 0; .section .debug_foo,"",@progbits; .long .text' \ +# RUN: | llvm-mc --filetype=obj -triple=i386-unknown-linux - -o %t +# RUN: ld.lld %t -o %t2 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s --check-prefixes=CHECK,CHECK32 + +# RUN: echo '.section .text,"a"; .byte 0; .section .debug_foo,"",@progbits; .long .text' \ +# RUN: | llvm-mc --filetype=obj -triple=x86_64-unknown-linux32 - -o %t +# RUN: ld.lld %t -o %t2 --gc-sections +# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s --check-prefixes=CHECK,CHECK32 + +# 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 an address which is out of the +# module address space. That test checks that relocations from the .debug_foo +# section pointing to a deleted .text section would be resolved +# to 0xfffffffffffffffe. + +# CHECK-NOT: Name: .text + +# CHECK: Name: .debug_foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK64-NEXT: Size: 8 +# CHECK32-NEXT: Size: 4 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK64-NEXT: 0000: FEFFFFFF FFFFFFFF +# CHECK32-NEXT: 0000: FEFFFFFF +# CHECK-NEXT: )