Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -305,7 +305,8 @@ InputSectionBase *getRelocatedSection(); template - void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef Rels); + void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef Rels, + StringRef Name); // Used by ICF. uint32_t Class[2] = {0, 0}; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -542,6 +542,17 @@ llvm_unreachable("Invalid expression"); } +static bool isInDiscardedSection(SymbolBody &Body) { + DefinedRegular *D = dyn_cast(&Body); + if (!D || !D->isSection()) + return false; + + SectionBase *IS = D->Section; + if (auto *ISB = dyn_cast_or_null(IS)) + IS = ISB->Repl; + return IS == &InputSection::Discarded || !IS->Live; +} + // 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 @@ -550,8 +561,11 @@ // So, we handle relocations for non-alloc sections directly in this // function as a performance optimization. template -void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef Rels) { +void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef Rels, + StringRef Name) { typedef typename ELFT::uint uintX_t; + bool IsDebugRanges = Name == ".debug_ranges"; + for (const RelTy &Rel : Rels) { uint32_t Type = Rel.getType(Config->IsMips64EL); uint64_t Offset = getOffset(Rel.r_offset); @@ -574,6 +588,14 @@ if (!Sym.isTls() || Out::TlsPhdr) SymVA = SignExtend64( getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS)); + // If an address range list contains an entry that belongs to a discarded + // section, we should perform a fix-up. We cannot write zero as the start + // and end address because such a pair is an end of range list marker in the + // .debug_ranges section. We put a placeholder value equal to 1, which is + // fine because a range list entry whose beginning and end address are equal + // has no effect, because the size of the range is zero in such case. + if (IsDebugRanges && isInDiscardedSection(Sym)) + SymVA = 1; Target->relocateOne(BufLoc, Type, SymVA); } } @@ -590,9 +612,9 @@ auto *IS = dyn_cast(this); if (IS && !(IS->Flags & SHF_ALLOC)) { if (IS->AreRelocsRela) - IS->relocateNonAlloc(Buf, IS->template relas()); + IS->relocateNonAlloc(Buf, IS->template relas(), IS->Name); else - IS->relocateNonAlloc(Buf, IS->template rels()); + IS->relocateNonAlloc(Buf, IS->template rels(), IS->Name); return; } Index: test/ELF/debug-ranges-reloc.s =================================================================== --- test/ELF/debug-ranges-reloc.s +++ test/ELF/debug-ranges-reloc.s @@ -0,0 +1,44 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o +# RUN: ld.lld %t1.o -o %t -gc-sections +# RUN: llvm-dwarfdump -debug-dump=all %t | FileCheck %s + +# CHECK: .debug_ranges contents: +# CHECK-NEXT: 00000000 0000000000000001 0000000000000001 +# CHECK-NEXT: 00000000 0000000000201000 0000000000201002 +# CHECK-NEXT: 00000000 + +.section .text._Z3aaav,"ax",@progbits +.Lfunc_begin0: +nop +nop +.Lfunc_end0: + +.section .text.start,"ax",@progbits +.globl _start +_start: +.Lfunc_begin1: +nop +nop +.Lfunc_end1: + +.section .debug_abbrev,"",@progbits + .byte 85 # DW_AT_ranges + +.section .debug_info,"",@progbits +.Lcu_begin0: + .long 12 # Length of Unit + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit + .long .Ldebug_ranges0 # DW_AT_ranges + +.section .debug_ranges,"",@progbits +.Ldebug_ranges0: + .quad .Lfunc_begin0 + .quad .Lfunc_end0 + .quad .Lfunc_begin1 + .quad .Lfunc_end1 + .quad 0 + .quad 0