forked from OSchip/llvm-project
[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:
parent
ce02cf0099
commit
fa03b0fafa
|
@ -340,12 +340,6 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec,
|
|||
// FIXME: ARM meta-data section. At present attributes are ignored,
|
||||
// they can be used to reason about object compatibility.
|
||||
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_REL: {
|
||||
// This section contains relocation information.
|
||||
|
|
|
@ -194,9 +194,6 @@ private:
|
|||
// List of all symbols referenced or defined by this file.
|
||||
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
|
||||
// reporting. Linker may find reasonable number of errors in a
|
||||
// single object file, so we cache debugging information in order to
|
||||
|
|
|
@ -103,15 +103,6 @@ typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
|
|||
return Offset;
|
||||
case Merge:
|
||||
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");
|
||||
}
|
||||
|
@ -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<ELF32BE>;
|
||||
template class elf::InputSectionBase<ELF64LE>;
|
||||
|
@ -836,8 +808,3 @@ template class elf::MergeInputSection<ELF32LE>;
|
|||
template class elf::MergeInputSection<ELF32BE>;
|
||||
template class elf::MergeInputSection<ELF64LE>;
|
||||
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>;
|
||||
|
|
|
@ -39,7 +39,7 @@ template <class ELFT> class OutputSectionBase;
|
|||
// section
|
||||
class InputSectionData {
|
||||
public:
|
||||
enum Kind { Regular, EHFrame, Merge, MipsAbiFlags };
|
||||
enum Kind { Regular, EHFrame, Merge };
|
||||
|
||||
// The garbage collector sets sections' Live bits.
|
||||
// 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>
|
||||
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 lld
|
||||
|
||||
|
|
|
@ -918,6 +918,8 @@ OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type, uintX_t Flags)
|
|||
else if (Type == SHT_MIPS_OPTIONS)
|
||||
this->Entsize =
|
||||
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() {
|
||||
|
@ -1729,46 +1731,6 @@ template <class ELFT> void VersionNeedSection<ELFT>::finalize() {
|
|||
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>
|
||||
static typename ELFT::uint getOutFlags(InputSectionBase<ELFT> *S) {
|
||||
return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED;
|
||||
|
@ -1823,9 +1785,6 @@ OutputSectionFactory<ELFT>::create(const SectionKey<ELFT::Is64Bits> &Key,
|
|||
case InputSectionBase<ELFT>::Merge:
|
||||
Sec = make<MergeOutputSection<ELFT>>(Key.Name, Type, Flags, Key.Alignment);
|
||||
break;
|
||||
case InputSectionBase<ELFT>::MipsAbiFlags:
|
||||
Sec = make<MipsAbiFlagsOutputSection<ELFT>>();
|
||||
break;
|
||||
}
|
||||
return {Sec, true};
|
||||
}
|
||||
|
@ -1919,11 +1878,6 @@ template class EhOutputSection<ELF32BE>;
|
|||
template class EhOutputSection<ELF64LE>;
|
||||
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<ELF32BE>;
|
||||
template class MergeOutputSection<ELF64LE>;
|
||||
|
|
|
@ -56,7 +56,6 @@ public:
|
|||
GotPlt,
|
||||
HashTable,
|
||||
Merge,
|
||||
MipsAbiFlags,
|
||||
Plt,
|
||||
Regular,
|
||||
Reloc,
|
||||
|
@ -630,24 +629,6 @@ private:
|
|||
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 sections. This header is placed to a section named .eh_frame_hdr
|
||||
// and also to a PT_GNU_EH_FRAME segment.
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "Strings.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Target.h"
|
||||
#include "Writer.h"
|
||||
|
||||
#include "lld/Core/Parallel.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.
|
||||
template <class ELFT>
|
||||
MipsOptionsSection<ELFT>::MipsOptionsSection()
|
||||
|
@ -282,6 +319,11 @@ template InputSection<ELF32BE> *elf::createInterpSection();
|
|||
template InputSection<ELF64LE> *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<ELF32BE>;
|
||||
template class elf::MipsOptionsSection<ELF64LE>;
|
||||
|
|
|
@ -15,6 +15,18 @@
|
|||
namespace lld {
|
||||
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.
|
||||
template <class ELFT>
|
||||
class MipsOptionsSection final : public InputSection<ELFT> {
|
||||
|
@ -105,6 +117,7 @@ template <class ELFT> struct In {
|
|||
static BuildIdSection<ELFT> *BuildId;
|
||||
static InputSection<ELFT> *Common;
|
||||
static InputSection<ELFT> *Interp;
|
||||
static MipsAbiFlagsSection<ELFT> *MipsAbiFlags;
|
||||
static MipsOptionsSection<ELFT> *MipsOptions;
|
||||
static MipsReginfoSection<ELFT> *MipsReginfo;
|
||||
};
|
||||
|
@ -112,6 +125,7 @@ template <class ELFT> struct In {
|
|||
template <class ELFT> BuildIdSection<ELFT> *In<ELFT>::BuildId;
|
||||
template <class ELFT> InputSection<ELFT> *In<ELFT>::Common;
|
||||
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> MipsReginfoSection<ELFT> *In<ELFT>::MipsReginfo;
|
||||
|
||||
|
|
|
@ -293,6 +293,12 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
|
|||
}
|
||||
|
||||
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
|
||||
auto *OptSec = make<MipsOptionsSection<ELFT>>();
|
||||
if (OptSec->Live) {
|
||||
|
|
|
@ -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
|
|
@ -38,7 +38,7 @@
|
|||
# ^-- %lo(0x17ff0)
|
||||
|
||||
# CHECK: Contents of section .rodata:
|
||||
# CHECK-NEXT: 10110 00020004
|
||||
# CHECK-NEXT: 100f4 00020004
|
||||
# ^-- loc
|
||||
|
||||
# CHECK: 00020004 .text 00000000 loc
|
||||
|
|
Loading…
Reference in New Issue