From fa03b0fafa33e6e279bd90f0e5f7ab6547017d93 Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Wed, 9 Nov 2016 21:37:06 +0000 Subject: [PATCH] [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 --- lld/ELF/InputFiles.cpp | 6 --- lld/ELF/InputFiles.h | 3 -- lld/ELF/InputSection.cpp | 33 ------------ lld/ELF/InputSection.h | 14 +----- lld/ELF/OutputSections.cpp | 50 +------------------ lld/ELF/OutputSections.h | 19 ------- lld/ELF/SyntheticSections.cpp | 42 ++++++++++++++++ lld/ELF/SyntheticSections.h | 14 ++++++ lld/ELF/Writer.cpp | 6 +++ .../ELF/invalid/mips-multiple-abiflags.test | 21 -------- lld/test/ELF/mips-n32-rels.s | 2 +- 11 files changed, 66 insertions(+), 144 deletions(-) delete mode 100644 lld/test/ELF/invalid/mips-multiple-abiflags.test diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index e7e2c5f48248..75f683f518b1 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -340,12 +340,6 @@ elf::ObjectFile::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::Discarded; - case SHT_MIPS_ABIFLAGS: - if (MipsAbiFlags) - fatal(getFilename(this) + - ": multiple SHT_MIPS_ABIFLAGS sections are not allowed"); - MipsAbiFlags.reset(new MipsAbiFlagsInputSection(this, &Sec, Name)); - return MipsAbiFlags.get(); case SHT_RELA: case SHT_REL: { // This section contains relocation information. diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 87774b4d1b2b..e867acf5bfd9 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -194,9 +194,6 @@ private: // List of all symbols referenced or defined by this file. std::vector SymbolBodies; - // MIPS .MIPS.abiflags section defined by this file. - std::unique_ptr> 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 diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 5cb5f2da37a2..da261c6e8c01 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -103,15 +103,6 @@ typename ELFT::uint InputSectionBase::getOffset(uintX_t Offset) const { return Offset; case Merge: return cast>(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 void MergeInputSection::finalizePieces() { } } -template -MipsAbiFlagsInputSection::MipsAbiFlagsInputSection( - elf::ObjectFile *F, const Elf_Shdr *Hdr, StringRef Name) - : InputSectionBase(F, Hdr, Name, - InputSectionBase::MipsAbiFlags) { - // Initialize this->Flags. - ArrayRef Data = this->Data; - if (Data.size() != sizeof(Elf_Mips_ABIFlags)) { - error("invalid size of .MIPS.abiflags section"); - return; - } - Flags = reinterpret_cast *>(Data.data()); -} - -template -bool MipsAbiFlagsInputSection::classof(const InputSectionData *S) { - return S->kind() == InputSectionBase::MipsAbiFlags; -} - template class elf::InputSectionBase; template class elf::InputSectionBase; template class elf::InputSectionBase; @@ -836,8 +808,3 @@ template class elf::MergeInputSection; template class elf::MergeInputSection; template class elf::MergeInputSection; template class elf::MergeInputSection; - -template class elf::MipsAbiFlagsInputSection; -template class elf::MipsAbiFlagsInputSection; -template class elf::MipsAbiFlagsInputSection; -template class elf::MipsAbiFlagsInputSection; diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 9e6fcaf1b945..89a5fd79291a 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -39,7 +39,7 @@ template 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 InputSection InputSection::Discarded; -template -class MipsAbiFlagsInputSection : public InputSectionBase { - typedef typename ELFT::Shdr Elf_Shdr; - -public: - MipsAbiFlagsInputSection(ObjectFile *F, const Elf_Shdr *Hdr, - StringRef Name); - static bool classof(const InputSectionData *S); - - const llvm::object::Elf_Mips_ABIFlags *Flags = nullptr; -}; - } // namespace elf } // namespace lld diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 45587d0a49e5..ab6ec62782f1 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -918,6 +918,8 @@ OutputSection::OutputSection(StringRef Name, uint32_t Type, uintX_t Flags) else if (Type == SHT_MIPS_OPTIONS) this->Entsize = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo); + else if (Type == SHT_MIPS_ABIFLAGS) + this->Entsize = sizeof(Elf_Mips_ABIFlags); } template void OutputSection::finalize() { @@ -1729,46 +1731,6 @@ template void VersionNeedSection::finalize() { this->Size = Size; } -template -MipsAbiFlagsOutputSection::MipsAbiFlagsOutputSection() - : OutputSectionBase(".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 -void MipsAbiFlagsOutputSection::writeTo(uint8_t *Buf) { - memcpy(Buf, &Flags, sizeof(Flags)); -} - -template -void MipsAbiFlagsOutputSection::addSection(InputSectionBase *C) { - // Check compatibility and merge fields from input .MIPS.abiflags - // to the output one. - auto *S = cast>(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 static typename ELFT::uint getOutFlags(InputSectionBase *S) { return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED; @@ -1823,9 +1785,6 @@ OutputSectionFactory::create(const SectionKey &Key, case InputSectionBase::Merge: Sec = make>(Key.Name, Type, Flags, Key.Alignment); break; - case InputSectionBase::MipsAbiFlags: - Sec = make>(); - break; } return {Sec, true}; } @@ -1919,11 +1878,6 @@ template class EhOutputSection; template class EhOutputSection; template class EhOutputSection; -template class MipsAbiFlagsOutputSection; -template class MipsAbiFlagsOutputSection; -template class MipsAbiFlagsOutputSection; -template class MipsAbiFlagsOutputSection; - template class MergeOutputSection; template class MergeOutputSection; template class MergeOutputSection; diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index afc7050bbd6e..7ca4399c3560 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -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 MipsAbiFlagsOutputSection final : public OutputSectionBase { - typedef llvm::object::Elf_Mips_ABIFlags Elf_Mips_ABIFlags; - typedef OutputSectionBase Base; - -public: - MipsAbiFlagsOutputSection(); - void writeTo(uint8_t *Buf) override; - void addSection(InputSectionBase *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. diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 1c2a2b5a4d3c..6d89ccd259e8 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -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 +MipsAbiFlagsSection::MipsAbiFlagsSection() + : InputSection(SHF_ALLOC, SHT_MIPS_ABIFLAGS, 8, ArrayRef(), + ".MIPS.abiflags") { + auto Func = [this](ObjectFile *F, ArrayRef D) { + if (D.size() != sizeof(Elf_Mips_ABIFlags)) { + error(getFilename(F) + ": invalid size of .MIPS.abiflags section"); + return; + } + auto *S = reinterpret_cast(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(SHT_MIPS_ABIFLAGS, Func); + + this->Data = ArrayRef((const uint8_t *)&Flags, sizeof(Flags)); + this->Live = true; +} + // .MIPS.options section. template MipsOptionsSection::MipsOptionsSection() @@ -282,6 +319,11 @@ template InputSection *elf::createInterpSection(); template InputSection *elf::createInterpSection(); template InputSection *elf::createInterpSection(); +template class elf::MipsAbiFlagsSection; +template class elf::MipsAbiFlagsSection; +template class elf::MipsAbiFlagsSection; +template class elf::MipsAbiFlagsSection; + template class elf::MipsOptionsSection; template class elf::MipsOptionsSection; template class elf::MipsOptionsSection; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 2d4291edb085..ece9ee7e53b1 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -15,6 +15,18 @@ namespace lld { namespace elf { +// .MIPS.abiflags section. +template +class MipsAbiFlagsSection final : public InputSection { + typedef llvm::object::Elf_Mips_ABIFlags Elf_Mips_ABIFlags; + +public: + MipsAbiFlagsSection(); + +private: + Elf_Mips_ABIFlags Flags = {}; +}; + // .MIPS.options section. template class MipsOptionsSection final : public InputSection { @@ -105,6 +117,7 @@ template struct In { static BuildIdSection *BuildId; static InputSection *Common; static InputSection *Interp; + static MipsAbiFlagsSection *MipsAbiFlags; static MipsOptionsSection *MipsOptions; static MipsReginfoSection *MipsReginfo; }; @@ -112,6 +125,7 @@ template struct In { template BuildIdSection *In::BuildId; template InputSection *In::Common; template InputSection *In::Interp; +template MipsAbiFlagsSection *In::MipsAbiFlags; template MipsOptionsSection *In::MipsOptions; template MipsReginfoSection *In::MipsReginfo; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 2a45022178a3..7e370648b027 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -293,6 +293,12 @@ template void Writer::createSyntheticSections() { } if (Config->EMachine == EM_MIPS) { + // .MIPS.abiflags + auto *AbiFlags = make>(); + if (AbiFlags->Live) { + In::MipsAbiFlags = AbiFlags; + Symtab::X->Sections.push_back(AbiFlags); + } // .MIPS.options auto *OptSec = make>(); if (OptSec->Live) { diff --git a/lld/test/ELF/invalid/mips-multiple-abiflags.test b/lld/test/ELF/invalid/mips-multiple-abiflags.test deleted file mode 100644 index 797233e2bd68..000000000000 --- a/lld/test/ELF/invalid/mips-multiple-abiflags.test +++ /dev/null @@ -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 diff --git a/lld/test/ELF/mips-n32-rels.s b/lld/test/ELF/mips-n32-rels.s index e6561d6ea816..633995b1135a 100644 --- a/lld/test/ELF/mips-n32-rels.s +++ b/lld/test/ELF/mips-n32-rels.s @@ -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