Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -195,8 +195,6 @@ // List of all symbols referenced or defined by this file. std::vector SymbolBodies; - // MIPS .reginfo section defined by this file. - std::unique_ptr> MipsReginfo; // MIPS .MIPS.options section defined by this file. std::unique_ptr> MipsOptions; // MIPS .MIPS.abiflags section defined by this file. Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -163,8 +163,6 @@ template uint32_t elf::ObjectFile::getMipsGp0() const { if (ELFT::Is64Bits && MipsOptions && MipsOptions->Reginfo) return MipsOptions->Reginfo->ri_gp_value; - if (!ELFT::Is64Bits && MipsReginfo && MipsReginfo->Reginfo) - return MipsReginfo->Reginfo->ri_gp_value; return 0; } @@ -349,12 +347,6 @@ // 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_REGINFO: - if (MipsReginfo) - fatal(getFilename(this) + - ": multiple SHT_MIPS_REGINFO sections are not allowed"); - MipsReginfo.reset(new MipsReginfoInputSection(this, &Sec, Name)); - return MipsReginfo.get(); case SHT_MIPS_OPTIONS: if (MipsOptions) fatal(getFilename(this) + Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -39,7 +39,7 @@ // section class InputSectionData { public: - enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions, MipsAbiFlags }; + enum Kind { Regular, EHFrame, Merge, MipsOptions, MipsAbiFlags }; // The garbage collector sets sections' Live bits. // If GC is disabled, all sections are considered live by default. @@ -293,18 +293,6 @@ // of the `_gp` symbol. For details: Chapter 4 / "Register Information" at // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf template -class MipsReginfoInputSection : public InputSectionBase { - typedef typename ELFT::Shdr Elf_Shdr; - -public: - MipsReginfoInputSection(ObjectFile *F, const Elf_Shdr *Hdr, - StringRef Name); - static bool classof(const InputSectionData *S); - - const llvm::object::Elf_Mips_RegInfo *Reginfo = nullptr; -}; - -template class MipsOptionsInputSection : public InputSectionBase { typedef typename ELFT::Shdr Elf_Shdr; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -103,10 +103,9 @@ return Offset; case Merge: return cast>(this)->getOffset(Offset); - case MipsReginfo: case MipsOptions: case MipsAbiFlags: - // MIPS .reginfo, .MIPS.options, and .MIPS.abiflags sections are consumed + // .MIPS.options, and .MIPS.abiflags sections are 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. @@ -754,28 +753,6 @@ } template -MipsReginfoInputSection::MipsReginfoInputSection(elf::ObjectFile *F, - const Elf_Shdr *Hdr, - StringRef Name) - : InputSectionBase(F, Hdr, Name, - InputSectionBase::MipsReginfo) { - ArrayRef Data = this->Data; - // Initialize this->Reginfo. - if (Data.size() != sizeof(Elf_Mips_RegInfo)) { - error(getName(this) + ": invalid size of .reginfo section"); - return; - } - Reginfo = reinterpret_cast *>(Data.data()); - if (Config->Relocatable && Reginfo->ri_gp_value) - error(getName(this) + ": unsupported non-zero ri_gp_value"); -} - -template -bool MipsReginfoInputSection::classof(const InputSectionData *S) { - return S->kind() == InputSectionBase::MipsReginfo; -} - -template MipsOptionsInputSection::MipsOptionsInputSection(elf::ObjectFile *F, const Elf_Shdr *Hdr, StringRef Name) @@ -845,11 +822,6 @@ template class elf::MergeInputSection; template class elf::MergeInputSection; -template class elf::MipsReginfoInputSection; -template class elf::MipsReginfoInputSection; -template class elf::MipsReginfoInputSection; -template class elf::MipsReginfoInputSection; - template class elf::MipsOptionsInputSection; template class elf::MipsOptionsInputSection; template class elf::MipsOptionsInputSection; Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -31,7 +31,6 @@ template class InputSection; template class InputSectionBase; template class MergeInputSection; -template class MipsReginfoInputSection; template class OutputSection; template class ObjectFile; template class SharedFile; @@ -57,7 +56,6 @@ GotPlt, HashTable, Merge, - MipsReginfo, MipsOptions, MipsAbiFlags, Plt, @@ -640,24 +638,6 @@ }; template -class MipsReginfoOutputSection final : public OutputSectionBase { - typedef llvm::object::Elf_Mips_RegInfo Elf_Mips_RegInfo; - typedef OutputSectionBase Base; - -public: - MipsReginfoOutputSection(); - void writeTo(uint8_t *Buf) override; - void addSection(InputSectionBase *S) override; - typename Base::Kind getKind() const override { return Base::MipsReginfo; } - static bool classof(const Base *B) { - return B->getKind() == Base::MipsReginfo; - } - -private: - uint32_t GprMask = 0; -}; - -template class MipsOptionsOutputSection final : public OutputSectionBase { typedef llvm::object::Elf_Mips_Options Elf_Mips_Options; typedef llvm::object::Elf_Mips_RegInfo Elf_Mips_RegInfo; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -921,6 +921,8 @@ this->Header.sh_entsize = sizeof(Elf_Rela); else if (Type == SHT_REL) this->Header.sh_entsize = sizeof(Elf_Rel); + else if (Type == SHT_MIPS_REGINFO) + this->Header.sh_entsize = sizeof(llvm::object::Elf_Mips_RegInfo); } template void OutputSection::finalize() { @@ -1731,32 +1733,6 @@ } template -MipsReginfoOutputSection::MipsReginfoOutputSection() - : OutputSectionBase(".reginfo", SHT_MIPS_REGINFO, SHF_ALLOC) { - this->Header.sh_addralign = 4; - this->Header.sh_entsize = sizeof(Elf_Mips_RegInfo); - this->Header.sh_size = sizeof(Elf_Mips_RegInfo); -} - -template -void MipsReginfoOutputSection::writeTo(uint8_t *Buf) { - auto *R = reinterpret_cast(Buf); - if (Config->Relocatable) - R->ri_gp_value = 0; - else - R->ri_gp_value = Out::Got->getVA() + MipsGPOffset; - R->ri_gprmask = GprMask; -} - -template -void MipsReginfoOutputSection::addSection(InputSectionBase *C) { - // Copy input object file's .reginfo gprmask to output. - auto *S = cast>(C); - GprMask |= S->Reginfo->ri_gprmask; - S->OutSec = this; -} - -template MipsOptionsOutputSection::MipsOptionsOutputSection() : OutputSectionBase(".MIPS.options", SHT_MIPS_OPTIONS, SHF_ALLOC | SHF_MIPS_NOSTRIP) { @@ -1882,9 +1858,6 @@ case InputSectionBase::Merge: Sec = make>(Key.Name, Type, Flags, Key.Alignment); break; - case InputSectionBase::MipsReginfo: - Sec = make>(); - break; case InputSectionBase::MipsOptions: Sec = make>(); break; @@ -1984,11 +1957,6 @@ template class EhOutputSection; template class EhOutputSection; -template class MipsReginfoOutputSection; -template class MipsReginfoOutputSection; -template class MipsReginfoOutputSection; -template class MipsReginfoOutputSection; - template class MipsOptionsOutputSection; template class MipsOptionsOutputSection; template class MipsOptionsOutputSection; Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -27,6 +27,19 @@ InterpSection(); }; +// MIPS .reginfo section. +template +class MipsReginfoSection final : public InputSection { + typedef llvm::object::Elf_Mips_RegInfo Elf_Mips_RegInfo; + +public: + MipsReginfoSection(); + void finalize(); + +private: + Elf_Mips_RegInfo Reginfo = {}; +}; + // .note.gnu.build-id section. template class BuildIdSection : public InputSection { public: @@ -76,12 +89,14 @@ template struct In { static BuildIdSection *BuildId; static CommonSection *Common; + static MipsReginfoSection *MipsReginfo; static InterpSection *Interp; }; template BuildIdSection *In::BuildId; template CommonSection *In::Common; template InterpSection *In::Interp; +template MipsReginfoSection *In::MipsReginfo; } // namespace elf } // namespace lld Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -22,6 +22,7 @@ #include "OutputSections.h" #include "Strings.h" #include "SymbolTable.h" +#include "Target.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MD5.h" @@ -75,6 +76,50 @@ this->Data = makeArrayRef(nullptr, Size); } +// Returns a vector of section contents that matches a given section type. +// Returned sections are "killed" by turning off "Live" flag, so that they +// won't be included in the final output. +template +static std::vector getSectionContents(uint32_t Type) { + std::vector V; + for (InputSectionBase *Sec : Symtab::X->Sections) { + if (!Sec || !Sec->Live || Sec->Type != Type) + continue; + if (Sec->Data.size() != sizeof(T)) { + error(getFilename(Sec->getFile()) + ": " + Sec->Name + ": invalid size"); + return V; + } + Sec->Live = false; + V.push_back(reinterpret_cast(Sec->Data.data())); + } + return V; +} + +// MIPS .reginfo section. +template +MipsReginfoSection::MipsReginfoSection() + : InputSection(SHF_ALLOC, SHT_MIPS_REGINFO, 4, ArrayRef(), + ".reginfo") { + std::vector Inputs = + getSectionContents(SHT_MIPS_REGINFO); + if (Inputs.empty()) + return; + + for (const Elf_Mips_RegInfo *RI : Inputs) { + if (Config->Relocatable && RI->ri_gp_value) + error("supported non-zero ri_gp_value"); + Reginfo.ri_gprmask |= RI->ri_gprmask; + } + + this->Data = ArrayRef((const uint8_t *)&Reginfo, sizeof(Reginfo)); + this->Live = true; +} + +template void MipsReginfoSection::finalize() { + if (!Config->Relocatable) + Reginfo.ri_gp_value = Out::Got->getVA() + MipsGPOffset; +} + static ArrayRef createInterp() { // StringSaver guarantees that the returned string ends with '\0'. StringRef S = Saver.save(Config->DynamicLinker); @@ -159,6 +204,11 @@ template class elf::InterpSection; template class elf::InterpSection; +template class elf::MipsReginfoSection; +template class elf::MipsReginfoSection; +template class elf::MipsReginfoSection; +template class elf::MipsReginfoSection; + template class elf::BuildIdSection; template class elf::BuildIdSection; template class elf::BuildIdSection; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -270,7 +270,7 @@ if (!Config->VersionDefinitions.empty()) Out::VerDef = make>(); - // Initialize linker generated sections + // .note.gnu.build-id if (Config->BuildId == BuildIdKind::Fast) In::BuildId = make>(); else if (Config->BuildId == BuildIdKind::Md5) @@ -287,11 +287,21 @@ if (In::BuildId) Symtab::X->Sections.push_back(In::BuildId); + // .common CommonSection *Common = make>(); if (!Common->Data.empty()) { In::Common = Common; Symtab::X->Sections.push_back(Common); } + + // MIPS .reginfo + if (Config->EMachine == EM_MIPS) { + auto *Sec = make>(); + if (Sec->Live) { + In::MipsReginfo = Sec; + Symtab::X->Sections.push_back(Sec); + } + } } template @@ -1413,6 +1423,10 @@ template void Writer::writeSections() { uint8_t *Buf = Buffer->getBufferStart(); + // Finalize MIPS .reginfo because it contains offsets to .got and _gp. + if (In::MipsReginfo) + In::MipsReginfo->finalize(); + // PPC64 needs to process relocations in the .opd section // before processing relocations in code-containing sections. Out::Opd = findSection(".opd"); Index: test/ELF/basic-mips.s =================================================================== --- test/ELF/basic-mips.s +++ test/ELF/basic-mips.s @@ -57,23 +57,23 @@ # CHECK-NEXT: } # CHECK-NEXT: Section { # CHECK-NEXT: Index: 1 -# CHECK-NEXT: Name: .reginfo -# CHECK-NEXT: Type: SHT_MIPS_REGINFO (0x70000006) +# CHECK-NEXT: Name: .MIPS.abiflags +# CHECK-NEXT: Type: SHT_MIPS_ABIFLAGS (0x7000002A) # CHECK-NEXT: Flags [ (0x2) # CHECK-NEXT: SHF_ALLOC (0x2) # CHECK-NEXT: ] -# CHECK-NEXT: Address: 0x100F4 -# CHECK-NEXT: Offset: 0xF4 +# CHECK-NEXT: Address: 0x100F8 +# CHECK-NEXT: Offset: 0xF8 # CHECK-NEXT: Size: 24 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 -# CHECK-NEXT: AddressAlignment: 4 +# CHECK-NEXT: AddressAlignment: 8 # CHECK-NEXT: EntrySize: 24 # CHECK-NEXT: } # CHECK-NEXT: Section { # CHECK-NEXT: Index: 2 -# CHECK-NEXT: Name: .MIPS.abiflags -# CHECK-NEXT: Type: SHT_MIPS_ABIFLAGS (0x7000002A) +# CHECK-NEXT: Name: .reginfo +# CHECK-NEXT: Type: SHT_MIPS_REGINFO (0x70000006) # CHECK-NEXT: Flags [ (0x2) # CHECK-NEXT: SHF_ALLOC (0x2) # CHECK-NEXT: ] @@ -82,7 +82,7 @@ # CHECK-NEXT: Size: 24 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 -# CHECK-NEXT: AddressAlignment: 8 +# CHECK-NEXT: AddressAlignment: 4 # CHECK-NEXT: EntrySize: 24 # CHECK-NEXT: } # CHECK-NEXT: Section { Index: test/ELF/invalid/mips-multiple-reginfo.test =================================================================== --- test/ELF/invalid/mips-multiple-reginfo.test +++ /dev/null @@ -1,25 +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_REGINFO - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - AddressAlign: 16 - Content: "000000000000000000000000000000000000000000000000" - - - Name: .foo2 - Type: SHT_MIPS_REGINFO - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - AddressAlign: 16 - Content: "000000000000000000000000000000000000000000000000" - -# CHECK: multiple SHT_MIPS_REGINFO sections are not allowed Index: test/ELF/mips-64.s =================================================================== --- test/ELF/mips-64.s +++ test/ELF/mips-64.s @@ -30,7 +30,7 @@ # SYM: 00030008 g .data 00000008 v2 # CHECK: Relocations [ -# CHECK-NEXT: Section (7) .rela.dyn { +# CHECK-NEXT: Section (8) .rela.dyn { # CHECK-NEXT: 0x30010 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE - 0x30000 # ^-- v1 # CHECK-NEXT: 0x30008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE v2 0x8 Index: test/ELF/mips-tls-64.s =================================================================== --- test/ELF/mips-tls-64.s +++ test/ELF/mips-tls-64.s @@ -35,7 +35,7 @@ # DIS: 0000000000000000 g *UND* 00000000 foo # CHECK: Relocations [ -# CHECK-NEXT: Section (7) .rela.dyn { +# CHECK-NEXT: Section (8) .rela.dyn { # CHECK-NEXT: 0x30018 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE foo 0x0 # CHECK-NEXT: 0x30020 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0 # CHECK-NEXT: 0x30028 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0 @@ -67,7 +67,7 @@ # DIS-SO-NEXT: 20048 00000000 00000000 00000000 00000000 # SO: Relocations [ -# SO-NEXT: Section (7) .rela.dyn { +# SO-NEXT: Section (8) .rela.dyn { # SO-NEXT: 0x20030 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE - 0x0 # SO-NEXT: 0x20040 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE bar 0x0 # SO-NEXT: 0x20048 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE bar 0x0