Index: ELF/ICF.cpp =================================================================== --- ELF/ICF.cpp +++ ELF/ICF.cpp @@ -279,6 +279,12 @@ A->getSize() != B->getSize() || A->Data != B->Data) return false; + const InputSection *LinkSecA = A->getLinkOrderSec(); + const InputSection *LinkSecB = B->getLinkOrderSec(); + if (LinkSecA || LinkSecB) + if (!LinkSecA || !LinkSecB || !equalsConstant(LinkSecA, LinkSecB)) + return false; + if (A->AreRelocsRela) return constantEq(A, A->template relas(), B, B->template relas()); @@ -423,20 +429,9 @@ return; log("selected " + Sections[Begin]->Name); - for (size_t I = Begin + 1; I < End; ++I) { - log(" removed " + Sections[I]->Name); + for (size_t I = Begin + 1; I < End; ++I) Sections[Begin]->replace(Sections[I]); - } }); - - // Mark ARM Exception Index table sections that refer to folded code - // sections as not live. These sections have an implict dependency - // via the link order dependency. - if (Config->EMachine == EM_ARM) - for (InputSectionBase *Sec : InputSections) - if (auto *S = dyn_cast(Sec)) - if (S->Flags & SHF_LINK_ORDER) - S->Live = S->getLinkOrderDep()->Live; } // ICF entry point function. Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -164,6 +164,7 @@ } InputSection *getLinkOrderDep() const; + InputSection *getLinkOrderSec() const; void uncompress(); Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -241,6 +241,19 @@ return nullptr; } +InputSection *InputSectionBase::getLinkOrderSec() const { + InputSection *Ret = nullptr; + for (InputSectionBase *Sec : DependentSections) { + if (!(Sec->Flags & SHF_LINK_ORDER)) + continue; + if (Ret) + error("multiple SHF_LINK_ORDER sections are not supported: " + + toString(this)); + Ret = cast(Sec); + } + return Ret; +} + // Returns a source location string. Used to construct an error message. template std::string InputSectionBase::getLocation(uint64_t Offset) { @@ -800,9 +813,15 @@ } void InputSection::replace(InputSection *Other) { + log(" removed " + Other->Name); this->Alignment = std::max(this->Alignment, Other->Alignment); Other->Repl = this->Repl; Other->Live = false; + + // Handle SHF_LINK_ORDER sections. These sections have an + // implicit dependency via the link order dependency. + if (InputSection *LinkOrder = getLinkOrderSec()) + LinkOrder->replace(Other->getLinkOrderSec()); } template Index: test/ELF/icf-link-order-err.s =================================================================== --- test/ELF/icf-link-order-err.s +++ test/ELF/icf-link-order-err.s @@ -0,0 +1,19 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: not ld.lld %t.o -o %t2 --icf=all 2>&1 | FileCheck %s +# CHECK: multiple SHF_LINK_ORDER sections are not supported: {{.*}}.o:(.text.bar) + +.section .text.foo, "ax" +nop + +.section .text.bar, "ax" +nop + +.section .order_foo,"ao",@progbits,.text.foo +.quad 0 + +.section .order_bar1,"ao",@progbits,.text.bar +.quad 0 + +.section .order_bar2,"ao",@progbits,.text.bar +.quad 0 Index: test/ELF/icf-link-order.s =================================================================== --- test/ELF/icf-link-order.s +++ test/ELF/icf-link-order.s @@ -0,0 +1,29 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: ld.lld %t -o %t2 --icf=all --verbose | FileCheck %s +# CHECK: selected .text.foo +# CHECK-NEXT: removed .text.bar +# CHECK-NEXT: removed .order_bar +# CHECK-NOT: selected +# CHECK-NOT: removed + +.section .text.foo, "ax" +nop + +.section .text.bar, "ax" +nop + +.section .text.dah, "ax" +nop + +.section .text.zed, "ax" +nop + +.section .order_foo,"ao",@progbits,.text.foo +.quad 0 + +.section .order_bar,"ao",@progbits,.text.bar +.quad 0 + +.section .order_dah,"ao",@progbits,.text.dah +.quad 1