[ELF] - Do not allow -r to eat comdats.

This is PR33052, "Bug 33052 - -r eats comdats ".

To fix it I stop removing group section from out when -r is given
and fixing SHT_GROUP content when writing it just like we do some
other fixup, e.g. for Rel[a]. (it needs fix for section indices that
are in group).

Differential revision: https://reviews.llvm.org/D33485

llvm-svn: 304140
This commit is contained in:
George Rimar 2017-05-29 08:37:50 +00:00
parent ac9cd3080d
commit 3b189d1643
5 changed files with 110 additions and 7 deletions

View File

@ -305,13 +305,22 @@ void elf::ObjectFile<ELFT>::initializeSections(
}
switch (Sec.sh_type) {
case SHT_GROUP:
this->Sections[I] = &InputSection::Discarded;
if (ComdatGroups
.insert(
CachedHashStringRef(getShtGroupSignature(ObjSections, Sec)))
.second)
case SHT_GROUP: {
// We discard comdat sections usually. When -r we should not do that. We
// still do deduplication in this case to simplify implementation, because
// otherwise merging group sections together would requre additional
// regeneration of its contents.
bool New = ComdatGroups
.insert(CachedHashStringRef(
getShtGroupSignature(ObjSections, Sec)))
.second;
if (New && Config->Relocatable)
this->Sections[I] = createInputSection(Sec, SectionStringTable);
else
this->Sections[I] = &InputSection::Discarded;
if (New)
continue;
for (uint32_t SecIndex : getShtGroupEntries(Sec)) {
if (SecIndex >= Size)
fatal(toString(this) +
@ -319,6 +328,7 @@ void elf::ObjectFile<ELFT>::initializeSections(
this->Sections[SecIndex] = &InputSection::Discarded;
}
break;
}
case SHT_SYMTAB:
this->initSymtab(ObjSections, &Sec);
break;

View File

@ -295,6 +295,24 @@ bool InputSectionBase::classof(const SectionBase *S) {
return S->kind() != Output;
}
void InputSection::copyShtGroup(uint8_t *Buf) {
assert(this->Type == SHT_GROUP);
ArrayRef<uint32_t> From = getDataAs<uint32_t>();
uint32_t *To = reinterpret_cast<uint32_t *>(Buf);
// First entry is a flag word, we leave it unchanged.
*To++ = From[0];
// Here we adjust indices of sections that belong to group as it
// might change during linking.
ArrayRef<InputSectionBase *> Sections = this->File->getSections();
for (uint32_t Val : From.slice(1)) {
uint32_t Index = read32(&Val, Config->Endianness);
write32(To++, Sections[Index]->OutSec->SectionIndex, Config->Endianness);
}
}
InputSectionBase *InputSection::getRelocatedSection() {
assert(this->Type == SHT_RELA || this->Type == SHT_REL);
ArrayRef<InputSectionBase *> Sections = this->File->getSections();
@ -680,6 +698,13 @@ template <class ELFT> void InputSection::writeTo(uint8_t *Buf) {
return;
}
// If -r is given, linker should keep SHT_GROUP sections. We should fixup
// them, see copyShtGroup().
if (this->Type == SHT_GROUP) {
copyShtGroup(Buf + OutSecOff);
return;
}
// Copy section contents from source object file to output file
// and then apply relocations.
memcpy(Buf + OutSecOff, Data.data(), Data.size());

View File

@ -319,6 +319,8 @@ public:
private:
template <class ELFT, class RelTy>
void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
void copyShtGroup(uint8_t *Buf);
};
// The list of all input sections.

View File

@ -112,6 +112,19 @@ template <class ELFT> void OutputSection::maybeCompress() {
Flags |= SHF_COMPRESSED;
}
template <class ELFT> static void finalizeShtGroup(OutputSection *Sec) {
// sh_link field for SHT_GROUP sections should contain the section index of
// the symbol table.
Sec->Link = InX::SymTab->OutSec->SectionIndex;
// sh_link then contain index of an entry in symbol table section which
// provides signature of the section group.
elf::ObjectFile<ELFT> *Obj = Sec->Sections[0]->getFile<ELFT>();
assert(Config->Relocatable && Sec->Sections.size() == 1);
ArrayRef<SymbolBody *> Symbols = Obj->getSymbols();
Sec->Info = InX::SymTab->getSymbolIndex(Symbols[Sec->Sections[0]->Info - 1]);
}
template <class ELFT> void OutputSection::finalize() {
if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) {
std::sort(Sections.begin(), Sections.end(), compareByFilePosition);
@ -126,6 +139,11 @@ template <class ELFT> void OutputSection::finalize() {
}
uint32_t Type = this->Type;
if (Type == SHT_GROUP) {
finalizeShtGroup<ELFT>(this);
return;
}
if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))
return;
@ -355,7 +373,10 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS,
return;
}
uint64_t Flags = IS->Flags & ~(uint64_t)SHF_GROUP;
uint64_t Flags = IS->Flags;
if (!Config->Relocatable)
Flags &= ~(uint64_t)SHF_GROUP;
if (Sec) {
if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags))
error("incompatible section flags for " + Sec->Name +

View File

@ -0,0 +1,45 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
# RUN: ld.lld -r %t.o %t.o -o %t
# RUN: llvm-readobj -elf-section-groups -sections %t | FileCheck %s
# CHECK: Name: .text.bar
# CHECK-NEXT: Type: SHT_PROGBITS
# CHECK-NEXT: Flags [
# CHECK-NEXT: SHF_ALLOC
# CHECK-NEXT: SHF_EXECINSTR
# CHECK-NEXT: SHF_GROUP
# CHECK-NEXT: ]
# CHECK-NEXT: Address:
# CHECK-NEXT: Offset:
# CHECK-NEXT: Size: 8
# CHECK: Section {
# CHECK-NEXT: Index: 4
# CHECK-NEXT: Name: .text.foo
# CHECK-NEXT: Type: SHT_PROGBITS
# CHECK-NEXT: Flags [
# CHECK-NEXT: SHF_ALLOC
# CHECK-NEXT: SHF_EXECINSTR
# CHECK-NEXT: SHF_GROUP
# CHECK-NEXT: ]
# CHECK-NEXT: Address:
# CHECK-NEXT: Offset:
# CHECK-NEXT: Size: 4
# CHECK: Groups {
# CHECK-NEXT: Group {
# CHECK-NEXT: Name: .group
# CHECK-NEXT: Index: 2
# CHECK-NEXT: Type: COMDAT
# CHECK-NEXT: Signature: abc
# CHECK-NEXT: Section(s) in group [
# CHECK-NEXT: .text.bar
# CHECK-NEXT: .text.foo
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: }
.section .text.bar,"axG",@progbits,abc,comdat
.quad 42
.section .text.foo,"axG",@progbits,abc,comdat
.long 42