Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -303,7 +303,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 @@ -484,6 +484,17 @@ llvm_unreachable("Invalid expression"); } +static bool isDiscardedSection(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 @@ -492,8 +503,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); @@ -516,6 +530,14 @@ if (!Sym.isTls() || Out::TlsPhdr) SymVA = SignExtend64( getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS)); + // If address range list contains entry that belongs to discarded + // section, we should perform a fix up. We can not write zero as start and + // end address because that would mean unexpected end of range. So we put a + // placeholder value equal to 1, that is correct to do because a range list + // entry whose begining and end adress are equal has no effect, because size + // of range is zero in such case. + if (IsDebugRanges && isDiscardedSection(Sym)) + SymVA = 1; Target->relocateOne(BufLoc, Type, SymVA); } } @@ -532,9 +554,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,74 @@ +# 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 -e main +# 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 + +.text +.section .text._Z3aaav,"ax",@progbits +.globl _Z3aaav +.type _Z3aaav,@function +_Z3aaav: +.Lfunc_begin0: +nop +nop +.Lfunc_end0: + +.section .text.main,"ax",@progbits +.globl main +.type main,@function +main: +.Lfunc_begin1: +nop +nop +.Lfunc_end1: + +.section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .ascii "\260B" # DW_AT_GNU_dwo_name + .byte 14 # DW_FORM_strp + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .ascii "\263B" # DW_AT_GNU_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 85 # DW_AT_ranges + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + +.section .debug_info,"",@progbits +.Lcu_begin0: + .long 44 # Length of Unit + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit + .long 0 # DW_AT_stmt_list + .long 0 # DW_AT_GNU_dwo_name + .long 0 # DW_AT_comp_dir + .quad -943190174132613613 # DW_AT_GNU_dwo_id + .long 0 # DW_AT_GNU_addr_base + .quad 0 # DW_AT_low_pc + .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