forked from OSchip/llvm-project
ELF: Don't merge SHF_LINK_ORDER sections for different output sections in relocatable links.
Merging SHF_LINK_ORDER sections can affect semantics if the sh_link fields point to different sections. Specifically, for SHF_LINK_ORDER sections, the sh_link field acts as a reverse dependency from the linked section, causing the SHF_LINK_ORDER section to be included if the linked section is included. Merging sections with different sh_link fields will cause the entire contents of the SHF_LINK_ORDER section to be associated with a single (arbitrarily chosen) output section, whereas the correct semantics are for the individual pieces of the SHF_LINK_ORDER section to be associated with their linked output sections. As a result we can end up incorrectly dropping SHF_LINK_ORDER section contents or including the wrong section contents, depending on which linked sections were chosen. Differential Revision: https://reviews.llvm.org/D68094 llvm-svn: 373255
This commit is contained in:
parent
0fa07f4276
commit
97e251e05a
|
@ -645,6 +645,20 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
|
||||||
for (OutputSection *sec : v) {
|
for (OutputSection *sec : v) {
|
||||||
if (sec->partition != isec->partition)
|
if (sec->partition != isec->partition)
|
||||||
continue;
|
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<InputSectionBase>(
|
||||||
|
cast<InputSectionDescription>(sec->sectionCommands[0])
|
||||||
|
->sectionBases[0]);
|
||||||
|
if (firstIsec->getLinkOrderDep()->getOutputSection() !=
|
||||||
|
isec->getLinkOrderDep()->getOutputSection())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
sec->recordSection(isec);
|
sec->recordSection(isec);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -659,26 +673,30 @@ void LinkerScript::addOrphanSections() {
|
||||||
StringMap<TinyPtrVector<OutputSection *>> map;
|
StringMap<TinyPtrVector<OutputSection *>> map;
|
||||||
std::vector<OutputSection *> v;
|
std::vector<OutputSection *> v;
|
||||||
|
|
||||||
auto add = [&](InputSectionBase *s) {
|
std::function<void(InputSectionBase *)> add;
|
||||||
if (!s->isLive() || s->parent)
|
add = [&](InputSectionBase *s) {
|
||||||
return;
|
if (s->isLive() && !s->parent) {
|
||||||
|
StringRef name = getOutputSectionName(s);
|
||||||
|
|
||||||
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 (config->orphanHandling == OrphanHandlingPolicy::Error)
|
if (OutputSection *sec = findByName(sectionCommands, name)) {
|
||||||
error(toString(s) + " is being placed in '" + name + "'");
|
sec->recordSection(s);
|
||||||
else if (config->orphanHandling == OrphanHandlingPolicy::Warn)
|
} else {
|
||||||
warn(toString(s) + " is being placed in '" + name + "'");
|
if (OutputSection *os = addInputSec(map, s, name))
|
||||||
|
v.push_back(os);
|
||||||
if (OutputSection *sec = findByName(sectionCommands, name)) {
|
assert(isa<MergeInputSection>(s) ||
|
||||||
sec->recordSection(s);
|
s->getOutputSection()->sectionIndex == UINT32_MAX);
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OutputSection *os = addInputSec(map, s, name))
|
if (config->relocatable)
|
||||||
v.push_back(os);
|
for (InputSectionBase *depSec : s->dependentSections)
|
||||||
assert(isa<MergeInputSection>(s) ||
|
if (depSec->flags & SHF_LINK_ORDER)
|
||||||
s->getOutputSection()->sectionIndex == UINT32_MAX);
|
add(depSec);
|
||||||
};
|
};
|
||||||
|
|
||||||
// For futher --emit-reloc handling code we need target output section
|
// For futher --emit-reloc handling code we need target output section
|
||||||
|
@ -686,6 +704,12 @@ void LinkerScript::addOrphanSections() {
|
||||||
// to create target sections first. We do not want priority handling
|
// to create target sections first. We do not want priority handling
|
||||||
// for synthetic sections because them are special.
|
// for synthetic sections because them are special.
|
||||||
for (InputSectionBase *isec : inputSections) {
|
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<InputSection>(isec))
|
if (auto *sec = dyn_cast<InputSection>(isec))
|
||||||
if (InputSectionBase *rel = sec->getRelocatedSection())
|
if (InputSectionBase *rel = sec->getRelocatedSection())
|
||||||
if (auto *relIS = dyn_cast_or_null<InputSectionBase>(rel->parent))
|
if (auto *relIS = dyn_cast_or_null<InputSectionBase>(rel->parent))
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue