[ELF][MIPS] Convert .MIPS.abiflags section to synthetic input section

Previously, we have both input and output section for .MIPS.abiflags.
Now we have only one class for .MIPS.abiflags, which is MipsAbiFlagsSection.
This class is a synthetic input section.

.MIPS.abiflags sections are handled as regular sections until
the control reaches Writer. Writer then aggregates all sections
whose type is SHT_MIPS_ABIFLAGS to create a single synthesized
input section. The synthesized section is then processed normally
as if it came from an input file.

llvm-svn: 286398
This commit is contained in:
Simon Atanasyan 2016-11-09 21:37:06 +00:00
parent ce02cf0099
commit fa03b0fafa
11 changed files with 66 additions and 144 deletions

View File

@ -340,12 +340,6 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec,
// FIXME: ARM meta-data section. At present attributes are ignored, // FIXME: ARM meta-data section. At present attributes are ignored,
// they can be used to reason about object compatibility. // they can be used to reason about object compatibility.
return &InputSection<ELFT>::Discarded; return &InputSection<ELFT>::Discarded;
case SHT_MIPS_ABIFLAGS:
if (MipsAbiFlags)
fatal(getFilename(this) +
": multiple SHT_MIPS_ABIFLAGS sections are not allowed");
MipsAbiFlags.reset(new MipsAbiFlagsInputSection<ELFT>(this, &Sec, Name));
return MipsAbiFlags.get();
case SHT_RELA: case SHT_RELA:
case SHT_REL: { case SHT_REL: {
// This section contains relocation information. // This section contains relocation information.

View File

@ -194,9 +194,6 @@ private:
// List of all symbols referenced or defined by this file. // List of all symbols referenced or defined by this file.
std::vector<SymbolBody *> SymbolBodies; std::vector<SymbolBody *> SymbolBodies;
// MIPS .MIPS.abiflags section defined by this file.
std::unique_ptr<MipsAbiFlagsInputSection<ELFT>> MipsAbiFlags;
// Debugging information to retrieve source file and line for error // Debugging information to retrieve source file and line for error
// reporting. Linker may find reasonable number of errors in a // reporting. Linker may find reasonable number of errors in a
// single object file, so we cache debugging information in order to // single object file, so we cache debugging information in order to

View File

@ -103,15 +103,6 @@ typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
return Offset; return Offset;
case Merge: case Merge:
return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset); return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset);
case MipsAbiFlags:
// .MIPS.abiflags sections is consumed
// by the linker, and the linker produces a single output section. It is
// possible that input files contain section symbol points to the
// corresponding input section. Redirect it to the produced output section.
if (Offset != 0)
fatal(getName(this) + ": unsupported reference to the middle of '" +
Name + "' section");
return this->OutSec->Addr;
} }
llvm_unreachable("invalid section kind"); llvm_unreachable("invalid section kind");
} }
@ -798,25 +789,6 @@ template <class ELFT> void MergeInputSection<ELFT>::finalizePieces() {
} }
} }
template <class ELFT>
MipsAbiFlagsInputSection<ELFT>::MipsAbiFlagsInputSection(
elf::ObjectFile<ELFT> *F, const Elf_Shdr *Hdr, StringRef Name)
: InputSectionBase<ELFT>(F, Hdr, Name,
InputSectionBase<ELFT>::MipsAbiFlags) {
// Initialize this->Flags.
ArrayRef<uint8_t> Data = this->Data;
if (Data.size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) {
error("invalid size of .MIPS.abiflags section");
return;
}
Flags = reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(Data.data());
}
template <class ELFT>
bool MipsAbiFlagsInputSection<ELFT>::classof(const InputSectionData *S) {
return S->kind() == InputSectionBase<ELFT>::MipsAbiFlags;
}
template class elf::InputSectionBase<ELF32LE>; template class elf::InputSectionBase<ELF32LE>;
template class elf::InputSectionBase<ELF32BE>; template class elf::InputSectionBase<ELF32BE>;
template class elf::InputSectionBase<ELF64LE>; template class elf::InputSectionBase<ELF64LE>;
@ -836,8 +808,3 @@ template class elf::MergeInputSection<ELF32LE>;
template class elf::MergeInputSection<ELF32BE>; template class elf::MergeInputSection<ELF32BE>;
template class elf::MergeInputSection<ELF64LE>; template class elf::MergeInputSection<ELF64LE>;
template class elf::MergeInputSection<ELF64BE>; template class elf::MergeInputSection<ELF64BE>;
template class elf::MipsAbiFlagsInputSection<ELF32LE>;
template class elf::MipsAbiFlagsInputSection<ELF32BE>;
template class elf::MipsAbiFlagsInputSection<ELF64LE>;
template class elf::MipsAbiFlagsInputSection<ELF64BE>;

View File

@ -39,7 +39,7 @@ template <class ELFT> class OutputSectionBase;
// section // section
class InputSectionData { class InputSectionData {
public: public:
enum Kind { Regular, EHFrame, Merge, MipsAbiFlags }; enum Kind { Regular, EHFrame, Merge };
// The garbage collector sets sections' Live bits. // The garbage collector sets sections' Live bits.
// If GC is disabled, all sections are considered live by default. // If GC is disabled, all sections are considered live by default.
@ -288,18 +288,6 @@ private:
template <class ELFT> InputSection<ELFT> InputSection<ELFT>::Discarded; template <class ELFT> InputSection<ELFT> InputSection<ELFT>::Discarded;
template <class ELFT>
class MipsAbiFlagsInputSection : public InputSectionBase<ELFT> {
typedef typename ELFT::Shdr Elf_Shdr;
public:
MipsAbiFlagsInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr,
StringRef Name);
static bool classof(const InputSectionData *S);
const llvm::object::Elf_Mips_ABIFlags<ELFT> *Flags = nullptr;
};
} // namespace elf } // namespace elf
} // namespace lld } // namespace lld

View File

@ -918,6 +918,8 @@ OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type, uintX_t Flags)
else if (Type == SHT_MIPS_OPTIONS) else if (Type == SHT_MIPS_OPTIONS)
this->Entsize = this->Entsize =
sizeof(Elf_Mips_Options<ELFT>) + sizeof(Elf_Mips_RegInfo<ELFT>); sizeof(Elf_Mips_Options<ELFT>) + sizeof(Elf_Mips_RegInfo<ELFT>);
else if (Type == SHT_MIPS_ABIFLAGS)
this->Entsize = sizeof(Elf_Mips_ABIFlags<ELFT>);
} }
template <class ELFT> void OutputSection<ELFT>::finalize() { template <class ELFT> void OutputSection<ELFT>::finalize() {
@ -1729,46 +1731,6 @@ template <class ELFT> void VersionNeedSection<ELFT>::finalize() {
this->Size = Size; this->Size = Size;
} }
template <class ELFT>
MipsAbiFlagsOutputSection<ELFT>::MipsAbiFlagsOutputSection()
: OutputSectionBase<ELFT>(".MIPS.abiflags", SHT_MIPS_ABIFLAGS, SHF_ALLOC) {
this->Addralign = 8;
this->Entsize = sizeof(Elf_Mips_ABIFlags);
this->Size = sizeof(Elf_Mips_ABIFlags);
memset(&Flags, 0, sizeof(Flags));
}
template <class ELFT>
void MipsAbiFlagsOutputSection<ELFT>::writeTo(uint8_t *Buf) {
memcpy(Buf, &Flags, sizeof(Flags));
}
template <class ELFT>
void MipsAbiFlagsOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
// Check compatibility and merge fields from input .MIPS.abiflags
// to the output one.
auto *S = cast<MipsAbiFlagsInputSection<ELFT>>(C);
S->OutSec = this;
if (S->Flags->version != 0) {
error(getFilename(S->getFile()) + ": unexpected .MIPS.abiflags version " +
Twine(S->Flags->version));
return;
}
// LLD checks ISA compatibility in getMipsEFlags(). Here we just
// select the highest number of ISA/Rev/Ext.
Flags.isa_level = std::max(Flags.isa_level, S->Flags->isa_level);
Flags.isa_rev = std::max(Flags.isa_rev, S->Flags->isa_rev);
Flags.isa_ext = std::max(Flags.isa_ext, S->Flags->isa_ext);
Flags.gpr_size = std::max(Flags.gpr_size, S->Flags->gpr_size);
Flags.cpr1_size = std::max(Flags.cpr1_size, S->Flags->cpr1_size);
Flags.cpr2_size = std::max(Flags.cpr2_size, S->Flags->cpr2_size);
Flags.ases |= S->Flags->ases;
Flags.flags1 |= S->Flags->flags1;
Flags.flags2 |= S->Flags->flags2;
Flags.fp_abi = elf::getMipsFpAbiFlag(Flags.fp_abi, S->Flags->fp_abi,
getFilename(S->getFile()));
}
template <class ELFT> template <class ELFT>
static typename ELFT::uint getOutFlags(InputSectionBase<ELFT> *S) { static typename ELFT::uint getOutFlags(InputSectionBase<ELFT> *S) {
return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED; return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED;
@ -1823,9 +1785,6 @@ OutputSectionFactory<ELFT>::create(const SectionKey<ELFT::Is64Bits> &Key,
case InputSectionBase<ELFT>::Merge: case InputSectionBase<ELFT>::Merge:
Sec = make<MergeOutputSection<ELFT>>(Key.Name, Type, Flags, Key.Alignment); Sec = make<MergeOutputSection<ELFT>>(Key.Name, Type, Flags, Key.Alignment);
break; break;
case InputSectionBase<ELFT>::MipsAbiFlags:
Sec = make<MipsAbiFlagsOutputSection<ELFT>>();
break;
} }
return {Sec, true}; return {Sec, true};
} }
@ -1919,11 +1878,6 @@ template class EhOutputSection<ELF32BE>;
template class EhOutputSection<ELF64LE>; template class EhOutputSection<ELF64LE>;
template class EhOutputSection<ELF64BE>; template class EhOutputSection<ELF64BE>;
template class MipsAbiFlagsOutputSection<ELF32LE>;
template class MipsAbiFlagsOutputSection<ELF32BE>;
template class MipsAbiFlagsOutputSection<ELF64LE>;
template class MipsAbiFlagsOutputSection<ELF64BE>;
template class MergeOutputSection<ELF32LE>; template class MergeOutputSection<ELF32LE>;
template class MergeOutputSection<ELF32BE>; template class MergeOutputSection<ELF32BE>;
template class MergeOutputSection<ELF64LE>; template class MergeOutputSection<ELF64LE>;

View File

@ -56,7 +56,6 @@ public:
GotPlt, GotPlt,
HashTable, HashTable,
Merge, Merge,
MipsAbiFlags,
Plt, Plt,
Regular, Regular,
Reloc, Reloc,
@ -630,24 +629,6 @@ private:
void Add(Entry E) { Entries.push_back(E); } void Add(Entry E) { Entries.push_back(E); }
}; };
template <class ELFT>
class MipsAbiFlagsOutputSection final : public OutputSectionBase<ELFT> {
typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
typedef OutputSectionBase<ELFT> Base;
public:
MipsAbiFlagsOutputSection();
void writeTo(uint8_t *Buf) override;
void addSection(InputSectionBase<ELFT> *S) override;
typename Base::Kind getKind() const override { return Base::MipsAbiFlags; }
static bool classof(const Base *B) {
return B->getKind() == Base::MipsAbiFlags;
}
private:
Elf_Mips_ABIFlags Flags;
};
// --eh-frame-hdr option tells linker to construct a header for all the // --eh-frame-hdr option tells linker to construct a header for all the
// .eh_frame sections. This header is placed to a section named .eh_frame_hdr // .eh_frame sections. This header is placed to a section named .eh_frame_hdr
// and also to a PT_GNU_EH_FRAME segment. // and also to a PT_GNU_EH_FRAME segment.

View File

@ -23,6 +23,7 @@
#include "Strings.h" #include "Strings.h"
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Target.h" #include "Target.h"
#include "Writer.h"
#include "lld/Core/Parallel.h" #include "lld/Core/Parallel.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
@ -92,6 +93,42 @@ static void iterateSectionContents(
} }
} }
// .MIPS.abiflags section.
template <class ELFT>
MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection()
: InputSection<ELFT>(SHF_ALLOC, SHT_MIPS_ABIFLAGS, 8, ArrayRef<uint8_t>(),
".MIPS.abiflags") {
auto Func = [this](ObjectFile<ELFT> *F, ArrayRef<uint8_t> D) {
if (D.size() != sizeof(Elf_Mips_ABIFlags)) {
error(getFilename(F) + ": invalid size of .MIPS.abiflags section");
return;
}
auto *S = reinterpret_cast<const Elf_Mips_ABIFlags *>(D.data());
if (S->version != 0) {
error(getFilename(F) + ": unexpected .MIPS.abiflags version " +
Twine(S->version));
return;
}
// LLD checks ISA compatibility in getMipsEFlags(). Here we just
// select the highest number of ISA/Rev/Ext.
Flags.isa_level = std::max(Flags.isa_level, S->isa_level);
Flags.isa_rev = std::max(Flags.isa_rev, S->isa_rev);
Flags.isa_ext = std::max(Flags.isa_ext, S->isa_ext);
Flags.gpr_size = std::max(Flags.gpr_size, S->gpr_size);
Flags.cpr1_size = std::max(Flags.cpr1_size, S->cpr1_size);
Flags.cpr2_size = std::max(Flags.cpr2_size, S->cpr2_size);
Flags.ases |= S->ases;
Flags.flags1 |= S->flags1;
Flags.flags2 |= S->flags2;
Flags.fp_abi =
elf::getMipsFpAbiFlag(Flags.fp_abi, S->fp_abi, getFilename(F));
};
iterateSectionContents<ELFT>(SHT_MIPS_ABIFLAGS, Func);
this->Data = ArrayRef<uint8_t>((const uint8_t *)&Flags, sizeof(Flags));
this->Live = true;
}
// .MIPS.options section. // .MIPS.options section.
template <class ELFT> template <class ELFT>
MipsOptionsSection<ELFT>::MipsOptionsSection() MipsOptionsSection<ELFT>::MipsOptionsSection()
@ -282,6 +319,11 @@ template InputSection<ELF32BE> *elf::createInterpSection();
template InputSection<ELF64LE> *elf::createInterpSection(); template InputSection<ELF64LE> *elf::createInterpSection();
template InputSection<ELF64BE> *elf::createInterpSection(); template InputSection<ELF64BE> *elf::createInterpSection();
template class elf::MipsAbiFlagsSection<ELF32LE>;
template class elf::MipsAbiFlagsSection<ELF32BE>;
template class elf::MipsAbiFlagsSection<ELF64LE>;
template class elf::MipsAbiFlagsSection<ELF64BE>;
template class elf::MipsOptionsSection<ELF32LE>; template class elf::MipsOptionsSection<ELF32LE>;
template class elf::MipsOptionsSection<ELF32BE>; template class elf::MipsOptionsSection<ELF32BE>;
template class elf::MipsOptionsSection<ELF64LE>; template class elf::MipsOptionsSection<ELF64LE>;

View File

@ -15,6 +15,18 @@
namespace lld { namespace lld {
namespace elf { namespace elf {
// .MIPS.abiflags section.
template <class ELFT>
class MipsAbiFlagsSection final : public InputSection<ELFT> {
typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
public:
MipsAbiFlagsSection();
private:
Elf_Mips_ABIFlags Flags = {};
};
// .MIPS.options section. // .MIPS.options section.
template <class ELFT> template <class ELFT>
class MipsOptionsSection final : public InputSection<ELFT> { class MipsOptionsSection final : public InputSection<ELFT> {
@ -105,6 +117,7 @@ template <class ELFT> struct In {
static BuildIdSection<ELFT> *BuildId; static BuildIdSection<ELFT> *BuildId;
static InputSection<ELFT> *Common; static InputSection<ELFT> *Common;
static InputSection<ELFT> *Interp; static InputSection<ELFT> *Interp;
static MipsAbiFlagsSection<ELFT> *MipsAbiFlags;
static MipsOptionsSection<ELFT> *MipsOptions; static MipsOptionsSection<ELFT> *MipsOptions;
static MipsReginfoSection<ELFT> *MipsReginfo; static MipsReginfoSection<ELFT> *MipsReginfo;
}; };
@ -112,6 +125,7 @@ template <class ELFT> struct In {
template <class ELFT> BuildIdSection<ELFT> *In<ELFT>::BuildId; template <class ELFT> BuildIdSection<ELFT> *In<ELFT>::BuildId;
template <class ELFT> InputSection<ELFT> *In<ELFT>::Common; template <class ELFT> InputSection<ELFT> *In<ELFT>::Common;
template <class ELFT> InputSection<ELFT> *In<ELFT>::Interp; template <class ELFT> InputSection<ELFT> *In<ELFT>::Interp;
template <class ELFT> MipsAbiFlagsSection<ELFT> *In<ELFT>::MipsAbiFlags;
template <class ELFT> MipsOptionsSection<ELFT> *In<ELFT>::MipsOptions; template <class ELFT> MipsOptionsSection<ELFT> *In<ELFT>::MipsOptions;
template <class ELFT> MipsReginfoSection<ELFT> *In<ELFT>::MipsReginfo; template <class ELFT> MipsReginfoSection<ELFT> *In<ELFT>::MipsReginfo;

View File

@ -293,6 +293,12 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
} }
if (Config->EMachine == EM_MIPS) { if (Config->EMachine == EM_MIPS) {
// .MIPS.abiflags
auto *AbiFlags = make<MipsAbiFlagsSection<ELFT>>();
if (AbiFlags->Live) {
In<ELFT>::MipsAbiFlags = AbiFlags;
Symtab<ELFT>::X->Sections.push_back(AbiFlags);
}
// .MIPS.options // .MIPS.options
auto *OptSec = make<MipsOptionsSection<ELFT>>(); auto *OptSec = make<MipsOptionsSection<ELFT>>();
if (OptSec->Live) { if (OptSec->Live) {

View File

@ -1,21 +0,0 @@
# RUN: yaml2obj %s -o %t
# RUN: not ld.lld %t -o %tout 2>&1 | FileCheck %s
--- !ELF
FileHeader:
Class: ELFCLASS32
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
Sections:
- Name: .foo1
Type: SHT_MIPS_ABIFLAGS
ISA: MIPS64
- Name: .foo2
Type: SHT_MIPS_ABIFLAGS
ISA: MIPS64
# CHECK: multiple SHT_MIPS_ABIFLAGS sections are not allowed

View File

@ -38,7 +38,7 @@
# ^-- %lo(0x17ff0) # ^-- %lo(0x17ff0)
# CHECK: Contents of section .rodata: # CHECK: Contents of section .rodata:
# CHECK-NEXT: 10110 00020004 # CHECK-NEXT: 100f4 00020004
# ^-- loc # ^-- loc
# CHECK: 00020004 .text 00000000 loc # CHECK: 00020004 .text 00000000 loc