From 1720219a1dea5c9b99df6dd1fdfb9dc8e77054fd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 18 Sep 2024 23:06:12 -0700 Subject: [PATCH] [ELF] --icf: don't fold a section without relocation and a section with relocations for SHT_CREL Similar to commit 686cff17cc310884e48ae963bf7507f96950cc90 for SHT_REL (#57693). CREL hasn't been tested with ICF before. And avoid a pitfall that eqClass[0] might interfere with ICF. (cherry picked from commit e82f0838ae88ad69515ebec234765e3e2607bebf) --- lld/ELF/ICF.cpp | 4 ++-- lld/ELF/InputSection.cpp | 6 +++--- lld/ELF/InputSection.h | 4 ++++ lld/test/ELF/icf10.s | 3 +++ 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp index 44e8a71cc62869..5591c5e71e0b1a 100644 --- a/lld/ELF/ICF.cpp +++ b/lld/ELF/ICF.cpp @@ -324,7 +324,7 @@ bool ICF::equalsConstant(const InputSection *a, const InputSection *b) { const RelsOrRelas ra = a->template relsOrRelas(); const RelsOrRelas rb = b->template relsOrRelas(); - if (ra.areRelocsCrel()) + if (ra.areRelocsCrel() || rb.areRelocsCrel()) return constantEq(a, ra.crels, b, rb.crels); return ra.areRelocsRel() || rb.areRelocsRel() ? constantEq(a, ra.rels, b, rb.rels) @@ -376,7 +376,7 @@ template bool ICF::equalsVariable(const InputSection *a, const InputSection *b) { const RelsOrRelas ra = a->template relsOrRelas(); const RelsOrRelas rb = b->template relsOrRelas(); - if (ra.areRelocsCrel()) + if (ra.areRelocsCrel() || rb.areRelocsCrel()) return variableEq(a, ra.crels, b, rb.crels); return ra.areRelocsRel() || rb.areRelocsRel() ? variableEq(a, ra.rels, b, rb.rels) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 570e485455bade..a165c813d4259c 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -150,12 +150,12 @@ RelsOrRelas InputSectionBase::relsOrRelas(bool supportsCrel) const { InputSectionBase *const &relSec = f->getSections()[relSecIdx]; // Otherwise, allocate a buffer to hold the decoded RELA relocations. When // called for the first time, relSec is null (without --emit-relocs) or an - // InputSection with zero eqClass[0]. - if (!relSec || !cast(relSec)->eqClass[0]) { + // InputSection with false decodedCrel. + if (!relSec || !cast(relSec)->decodedCrel) { auto *sec = makeThreadLocal(*f, shdr, name); f->cacheDecodedCrel(relSecIdx, sec); sec->type = SHT_RELA; - sec->eqClass[0] = SHT_RELA; + sec->decodedCrel = true; RelocsCrel entries(sec->content_); sec->size = entries.size() * sizeof(typename ELFT::Rela); diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 6659530a9c9c26..afa6ee5bd0826f 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -176,6 +176,10 @@ class InputSectionBase : public SectionBase { mutable bool compressed = false; + // Whether this section is SHT_CREL and has been decoded to RELA by + // relsOrRelas. + bool decodedCrel = false; + // Whether the section needs to be padded with a NOP filler due to // deleteFallThruJmpInsn. bool nopFiller = false; diff --git a/lld/test/ELF/icf10.s b/lld/test/ELF/icf10.s index 3c18c431c3b9da..ff926d0e16b103 100644 --- a/lld/test/ELF/icf10.s +++ b/lld/test/ELF/icf10.s @@ -5,6 +5,9 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-freebsd %s -o %t.o # RUN: ld.lld --icf=all %t.o -o /dev/null --print-icf-sections 2>&1 | FileCheck %s +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o --crel +# RUN: ld.lld --icf=all %t.o -o /dev/null --print-icf-sections 2>&1 | FileCheck %s + # Checks that ICF does not merge 2 sections the offset of # the relocations of which differ.