Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -645,6 +645,20 @@ for (OutputSection *sec : v) { if (sec->partition != isec->partition) continue; + + if (config->relocatable && (isec->flags & SHF_LINK_ORDER)) { + // Merging two SHF_LINK_ORDER sections with different sh_link fields will + // change their semantics, so we only merge them in -r links if they will + // end up being linked to the same output section. The casts are fine + // because everything in the map was created by the orphan placement code. + auto *firstIsec = cast( + cast(sec->sectionCommands[0]) + ->sectionBases[0]); + if (firstIsec->getLinkOrderDep()->getOutputSection() != + isec->getLinkOrderDep()->getOutputSection()) + continue; + } + sec->recordSection(isec); return nullptr; } @@ -659,26 +673,30 @@ StringMap> map; std::vector v; - auto add = [&](InputSectionBase *s) { - if (!s->isLive() || s->parent) - return; - - StringRef name = getOutputSectionName(s); - - if (config->orphanHandling == OrphanHandlingPolicy::Error) - error(toString(s) + " is being placed in '" + name + "'"); - else if (config->orphanHandling == OrphanHandlingPolicy::Warn) - warn(toString(s) + " is being placed in '" + name + "'"); - - if (OutputSection *sec = findByName(sectionCommands, name)) { - sec->recordSection(s); - return; + std::function add; + add = [&](InputSectionBase *s) { + if (s->isLive() && !s->parent) { + StringRef name = getOutputSectionName(s); + + if (config->orphanHandling == OrphanHandlingPolicy::Error) + error(toString(s) + " is being placed in '" + name + "'"); + else if (config->orphanHandling == OrphanHandlingPolicy::Warn) + warn(toString(s) + " is being placed in '" + name + "'"); + + if (OutputSection *sec = findByName(sectionCommands, name)) { + sec->recordSection(s); + } else { + if (OutputSection *os = addInputSec(map, s, name)) + v.push_back(os); + assert(isa(s) || + s->getOutputSection()->sectionIndex == UINT32_MAX); + } } - if (OutputSection *os = addInputSec(map, s, name)) - v.push_back(os); - assert(isa(s) || - s->getOutputSection()->sectionIndex == UINT32_MAX); + if (config->relocatable) + for (InputSectionBase *depSec : s->dependentSections) + if (depSec->flags & SHF_LINK_ORDER) + add(depSec); }; // For futher --emit-reloc handling code we need target output section @@ -686,6 +704,12 @@ // to create target sections first. We do not want priority handling // for synthetic sections because them are special. for (InputSectionBase *isec : inputSections) { + // In -r links, SHF_LINK_ORDER sections are added while adding their parent + // sections because we need to know the parent's output section before we + // can select an output section for the SHF_LINK_ORDER section. + if (config->relocatable && (isec->flags & SHF_LINK_ORDER)) + continue; + if (auto *sec = dyn_cast(isec)) if (InputSectionBase *rel = sec->getRelocatedSection()) if (auto *relIS = dyn_cast_or_null(rel->parent)) Index: lld/trunk/test/ELF/relocatable-linkorder.s =================================================================== --- lld/trunk/test/ELF/relocatable-linkorder.s +++ lld/trunk/test/ELF/relocatable-linkorder.s @@ -0,0 +1,36 @@ +// REQUIRES: x86 +// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux +// RUN: ld.lld %t.o -o %t -r +// RUN: llvm-readelf -S %t | FileCheck --check-prefix=DIFFERENT %s +// RUN: echo 'SECTIONS { .text.f1 : { *(.text.f1) } .text.f2 : { *(.text.f2) } }' > %t.lds +// RUN: ld.lld %t.o -o %t -r %t.lds +// RUN: llvm-readelf -S %t | FileCheck --check-prefix=DIFFERENT %s +// RUN: echo 'SECTIONS { .text : { *(.text.f1) *(.text.f2) } }' > %t.lds +// RUN: ld.lld %t.o -o %t -r %t.lds +// RUN: llvm-readelf -S -x foo %t | FileCheck --check-prefix=SAME %s + +/// Test that SHF_LINK_ORDER sections with different linked sections +/// aren't merged. + +.section .text.f1,"ax",@progbits +.globl f1 +f1: +ret + +.section .text.f2,"ax",@progbits +.globl f2 +f2: +ret + +// SAME: foo +// DIFFERENT: foo +.section foo,"ao",@progbits,.text.f2,unique,2 +.quad 2 + +// SAME-NOT: foo +// DIFFERENT: foo +.section foo,"ao",@progbits,.text.f1,unique,1 +.quad 1 + +// SAME: Hex dump of section 'foo': +// SAME: 01000000 00000000 02000000 00000000