diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 3023cbfae4a59..413fa3856a142 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -463,7 +463,13 @@ void InputSection::copyRelocations(uint8_t *buf, if (RelTy::IsRela) p->r_addend = sym.getVA(addend) - section->getOutputSection()->addr; - else if (config->relocatable && type != target.noneRel) + // For SHF_ALLOC sections relocated by REL, append a relocation to + // sec->relocations so that relocateAlloc transitively called by + // writeSections will update the implicit addend. Non-SHF_ALLOC sections + // utilize relocateNonAlloc to process raw relocations and do not need + // this sec->relocations change. + else if (config->relocatable && (sec->flags & SHF_ALLOC) && + type != target.noneRel) sec->addReloc({R_ABS, type, rel.offset, addend, &sym}); } else if (config->emachine == EM_PPC && type == R_PPC_PLTREL24 && p->r_addend >= 0x8000 && sec->file->ppc32Got2) { @@ -954,8 +960,10 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { } } - // For a relocatable link, only tombstone values are applied. - if (config->relocatable) + // For a relocatable link, content relocated by RELA remains unchanged and + // we can stop here, while content relocated by REL referencing STT_SECTION + // needs updating implicit addends. + if (config->relocatable && (RelTy::IsRela || sym.type != STT_SECTION)) continue; if (expr == R_SIZE) { @@ -987,30 +995,18 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { // relocations without any errors and relocate them as if they were at // address 0. For bug-compatibility, we accept them with warnings. We // know Steel Bank Common Lisp as of 2018 have this bug. - warn(msg); + // + // RELA -r stopped earlier and does not get the warning. Suppress the + // warning for REL -r as well + // (https://github.com/ClangBuiltLinux/linux/issues/1937). + if (RelTy::IsRela || !config->relocatable) + warn(msg); target.relocateNoSym( bufLoc, type, SignExtend64(sym.getVA(addend - offset - outSecOff))); } } -// 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 function does the same for -// non-allocatable sections, such as sections with debug information. -static void relocateNonAllocForRelocatable(InputSection *sec, uint8_t *buf) { - const unsigned bits = config->is64 ? 64 : 32; - - for (const Relocation &rel : sec->relocs()) { - // InputSection::copyRelocations() adds only R_ABS relocations. - assert(rel.expr == R_ABS); - uint8_t *bufLoc = buf + rel.offset; - uint64_t targetVA = SignExtend64(rel.sym->getVA(rel.addend), bits); - target->relocate(bufLoc, rel, targetVA); - } -} - template void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) { if ((flags & SHF_EXECINSTR) && LLVM_UNLIKELY(getFile()->splitStack)) @@ -1022,8 +1018,6 @@ void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) { } auto *sec = cast(this); - if (config->relocatable) - relocateNonAllocForRelocatable(sec, buf); // For a relocatable link, also call relocateNonAlloc() to rewrite applicable // locations with tombstone values. const RelsOrRelas rels = sec->template relsOrRelas(); diff --git a/lld/test/ELF/relocatable-section-symbol.s b/lld/test/ELF/relocatable-section-symbol.s index 9d8892236304b..2ee1e7692cf2c 100644 --- a/lld/test/ELF/relocatable-section-symbol.s +++ b/lld/test/ELF/relocatable-section-symbol.s @@ -30,10 +30,11 @@ # RUN: llvm-mc -filetype=obj -triple=i686 %s -o %t1.o # RUN: ld.lld -r -o %t1 %t1.o %t1.o -# RUN: llvm-readelf -r -x .data -x .bar -x .debug_line %t1 | FileCheck %s --check-prefixes=REL,REL0 +# RUN: llvm-readelf -r -x .data -x .bar -x .debug_line %t1 | FileCheck %s --check-prefix=REL +## https://github.com/llvm/llvm-project/issues/66738 Update implicit addends for -r and --compress-debug-sections # RUN: ld.lld -r --compress-debug-sections=zlib -o %t1.zlib %t1.o %t1.o # RUN: llvm-objcopy --decompress-debug-sections %t1.zlib %t1.zlib.de -# RUN: llvm-readelf -r -x .data -x .bar -x .debug_line %t1.zlib.de | FileCheck %s --check-prefixes=REL,REL1 +# RUN: llvm-readelf -r -x .data -x .bar -x .debug_line %t1.zlib.de | FileCheck %s --check-prefix=REL # REL: Offset Info Type Sym. Value Symbol's Name # REL-NEXT: 00000000 {{.*}} R_386_32 00000000 .text @@ -55,11 +56,8 @@ # REL-NEXT: 0x00000000 01000000 05000000 ........ # REL: Hex dump of section '.bar': # REL-NEXT: 0x00000000 01000000 00000000 02000000 04000000 ................ -# REL0: Hex dump of section '.debug_line': -# REL0-NEXT: 0x00000000 01000000 00000000 02000000 04000000 ................ -## FIXME: https://github.com/llvm/llvm-project/issues/66738 The implicit addends for the second input section are wrong. -# REL1: Hex dump of section '.debug_line': -# REL1-NEXT: 0x00000000 01000000 00000000 01000000 00000000 ................ +# REL: Hex dump of section '.debug_line': +# REL-NEXT: 0x00000000 01000000 00000000 02000000 04000000 ................ .long 42 .data