Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -179,6 +179,7 @@ // the mmap'ed output buffer. template void relocate(uint8_t *Buf, uint8_t *BufEnd); void relocateAlloc(uint8_t *Buf, uint8_t *BufEnd); + void relocateNonAllocForRelocatable(uint8_t *Buf, uint8_t *BufEnd); // The native ELF reloc data type is not very convenient to handle. // So we convert ELF reloc records to our own records in Relocations.cpp. Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -734,6 +734,11 @@ return; } + if (Config->Relocatable) { + relocateNonAllocForRelocatable(Buf, BufEnd); + return; + } + auto *Sec = cast(this); if (Sec->AreRelocsRela) Sec->relocateNonAlloc(Buf, Sec->template relas()); @@ -804,6 +809,30 @@ } } +// This is used when '-r' is given. +// For REL targets, InputSection::copyRelocations() may store artificial +// relocations aimed to update addends. They are handled in relocateAlloc() +// for allocatable sections, and this method does the same for non-allocatable +// sections, such as sections with debug information. +void InputSectionBase::relocateNonAllocForRelocatable(uint8_t *Buf, + uint8_t *BufEnd) { + const unsigned Bits = Config->Wordsize * 8; + + for (const Relocation &Rel : Relocations) { + // InputSection::copyRelocations() adds only R_ABS relocations. + // We don't expect to see here anything else. + assert(Rel.Expr == R_ABS); + + auto *Sec = cast(this); + uint64_t Offset = Rel.Offset + Sec->OutSecOff; + uint8_t *BufLoc = Buf + Offset; + RelType Type = Rel.Type; + uint64_t TargetVA = SignExtend64(Rel.Sym->getVA(Rel.Addend), Bits); + + Target->relocateOne(BufLoc, Type, TargetVA); + } +} + template void InputSection::writeTo(uint8_t *Buf) { if (Type == SHT_NOBITS) return; Index: test/ELF/pr37735.s =================================================================== --- /dev/null +++ test/ELF/pr37735.s @@ -0,0 +1,12 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=i386-pc-linux-gnu %s -o %t.o +# RUN: ld.lld -r %t.o %t.o -o %t1.o +# RUN: llvm-objdump -s -section=.bar %t1.o | FileCheck %s + +.section .foo + .byte 0 + +# CHECK: Contents of section .bar: +# CHECK-NEXT: 0000 00000000 01000000 +.section .bar + .dc.a .foo