[lld] r268485 - [ELF][MIPS] Read/write .MIPS.options section
Simon Atanasyan via llvm-commits
llvm-commits at lists.llvm.org
Wed May 4 03:07:39 PDT 2016
Author: atanasyan
Date: Wed May 4 05:07:38 2016
New Revision: 268485
URL: http://llvm.org/viewvc/llvm-project?rev=268485&view=rev
Log:
[ELF][MIPS] Read/write .MIPS.options section
MIPS N64 ABI introduces .MIPS.options section which specifies miscellaneous
options to be applied to an object/shared/executable file. LLVM as well as
modern versions of GNU tools read and write the only type of the options -
ODK_REGINFO. It is exact copy of .reginfo section used by O32 ABI.
Added:
lld/trunk/test/ELF/mips-options.s
Modified:
lld/trunk/ELF/InputFiles.cpp
lld/trunk/ELF/InputFiles.h
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/InputSection.h
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/OutputSections.h
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=268485&r1=268484&r2=268485&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Wed May 4 05:07:38 2016
@@ -105,7 +105,9 @@ ArrayRef<SymbolBody *> elf::ObjectFile<E
}
template <class ELFT> uint32_t elf::ObjectFile<ELFT>::getMipsGp0() const {
- if (MipsReginfo)
+ 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;
}
@@ -278,11 +280,17 @@ elf::ObjectFile<ELFT>::createInputSectio
if (Config->StripDebug && Name.startswith(".debug"))
return &InputSection<ELFT>::Discarded;
- // A MIPS object file has a special section that contains register
- // usage info, which needs to be handled by the linker specially.
- if (Config->EMachine == EM_MIPS && Name == ".reginfo") {
- MipsReginfo.reset(new MipsReginfoInputSection<ELFT>(this, &Sec));
- return MipsReginfo.get();
+ // A MIPS object file has a special sections that contain register
+ // usage info, which need to be handled by the linker specially.
+ if (Config->EMachine == EM_MIPS) {
+ if (Name == ".reginfo") {
+ MipsReginfo.reset(new MipsReginfoInputSection<ELFT>(this, &Sec));
+ return MipsReginfo.get();
+ }
+ if (Name == ".MIPS.options") {
+ MipsOptions.reset(new MipsOptionsInputSection<ELFT>(this, &Sec));
+ return MipsOptions.get();
+ }
}
// We dont need special handling of .eh_frame sections if relocatable
Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=268485&r1=268484&r2=268485&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Wed May 4 05:07:38 2016
@@ -162,6 +162,8 @@ private:
// MIPS .reginfo section defined by this file.
std::unique_ptr<MipsReginfoInputSection<ELFT>> MipsReginfo;
+ // MIPS .MIPS.options section defined by this file.
+ std::unique_ptr<MipsOptionsInputSection<ELFT>> MipsOptions;
llvm::BumpPtrAllocator Alloc;
llvm::SpecificBumpPtrAllocator<InputSection<ELFT>> IAlloc;
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=268485&r1=268484&r2=268485&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Wed May 4 05:07:38 2016
@@ -64,9 +64,10 @@ typename ELFT::uint InputSectionBase<ELF
case Merge:
return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset);
case MipsReginfo:
- // MIPS .reginfo sections are consumed by the linker,
+ case MipsOptions:
+ // MIPS .reginfo and .MIPS.options sections are consumed by the linker,
// so it should never be copied to output.
- llvm_unreachable("MIPS .reginfo reached writeTo().");
+ llvm_unreachable("MIPS reginfo/options section reached writeTo().");
}
llvm_unreachable("invalid section kind");
}
@@ -493,8 +494,10 @@ MipsReginfoInputSection<ELFT>::MipsRegin
: InputSectionBase<ELFT>(F, Hdr, InputSectionBase<ELFT>::MipsReginfo) {
// Initialize this->Reginfo.
ArrayRef<uint8_t> D = this->getSectionData();
- if (D.size() != sizeof(Elf_Mips_RegInfo<ELFT>))
- fatal("invalid size of .reginfo section");
+ if (D.size() != sizeof(Elf_Mips_RegInfo<ELFT>)) {
+ error("invalid size of .reginfo section");
+ return;
+ }
Reginfo = reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(D.data());
}
@@ -503,6 +506,31 @@ bool MipsReginfoInputSection<ELFT>::clas
return S->SectionKind == InputSectionBase<ELFT>::MipsReginfo;
}
+template <class ELFT>
+MipsOptionsInputSection<ELFT>::MipsOptionsInputSection(elf::ObjectFile<ELFT> *F,
+ const Elf_Shdr *Hdr)
+ : InputSectionBase<ELFT>(F, Hdr, InputSectionBase<ELFT>::MipsOptions) {
+ // Find ODK_REGINFO option in the section's content.
+ ArrayRef<uint8_t> D = this->getSectionData();
+ while (!D.empty()) {
+ if (D.size() < sizeof(Elf_Mips_Options<ELFT>)) {
+ error("invalid size of .MIPS.options section");
+ break;
+ }
+ auto *O = reinterpret_cast<const Elf_Mips_Options<ELFT> *>(D.data());
+ if (O->kind == ODK_REGINFO) {
+ Reginfo = &O->getRegInfo();
+ break;
+ }
+ D = D.slice(O->size);
+ }
+}
+
+template <class ELFT>
+bool MipsOptionsInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
+ return S->SectionKind == InputSectionBase<ELFT>::MipsOptions;
+}
+
template class elf::InputSectionBase<ELF32LE>;
template class elf::InputSectionBase<ELF32BE>;
template class elf::InputSectionBase<ELF64LE>;
@@ -532,3 +560,8 @@ template class elf::MipsReginfoInputSect
template class elf::MipsReginfoInputSection<ELF32BE>;
template class elf::MipsReginfoInputSection<ELF64LE>;
template class elf::MipsReginfoInputSection<ELF64BE>;
+
+template class elf::MipsOptionsInputSection<ELF32LE>;
+template class elf::MipsOptionsInputSection<ELF32BE>;
+template class elf::MipsOptionsInputSection<ELF64LE>;
+template class elf::MipsOptionsInputSection<ELF64BE>;
Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=268485&r1=268484&r2=268485&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Wed May 4 05:07:38 2016
@@ -88,7 +88,7 @@ protected:
ObjectFile<ELFT> *File;
public:
- enum Kind { Regular, EHFrame, Merge, MipsReginfo };
+ enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions };
Kind SectionKind;
InputSectionBase() : Repl(this) {}
@@ -249,7 +249,18 @@ public:
MipsReginfoInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr);
static bool classof(const InputSectionBase<ELFT> *S);
- const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo;
+ const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo = nullptr;
+};
+
+template <class ELFT>
+class MipsOptionsInputSection : public InputSectionBase<ELFT> {
+ typedef typename ELFT::Shdr Elf_Shdr;
+
+public:
+ MipsOptionsInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr);
+ static bool classof(const InputSectionBase<ELFT> *S);
+
+ const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo = nullptr;
};
} // namespace elf
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=268485&r1=268484&r2=268485&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Wed May 4 05:07:38 2016
@@ -1691,6 +1691,34 @@ void MipsReginfoOutputSection<ELFT>::add
GprMask |= S->Reginfo->ri_gprmask;
}
+template <class ELFT>
+MipsOptionsOutputSection<ELFT>::MipsOptionsOutputSection()
+ : OutputSectionBase<ELFT>(".MIPS.options", SHT_MIPS_OPTIONS,
+ SHF_ALLOC | SHF_MIPS_NOSTRIP) {
+ this->Header.sh_addralign = 8;
+ this->Header.sh_entsize = 1;
+ this->Header.sh_size = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);
+}
+
+template <class ELFT>
+void MipsOptionsOutputSection<ELFT>::writeTo(uint8_t *Buf) {
+ auto *Opt = reinterpret_cast<Elf_Mips_Options *>(Buf);
+ Opt->kind = ODK_REGINFO;
+ Opt->size = this->Header.sh_size;
+ Opt->section = 0;
+ Opt->info = 0;
+ auto *Reg = reinterpret_cast<Elf_Mips_RegInfo *>(Buf + sizeof(*Opt));
+ Reg->ri_gp_value = Out<ELFT>::Got->getVA() + MipsGPOffset;
+ Reg->ri_gprmask = GprMask;
+}
+
+template <class ELFT>
+void MipsOptionsOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
+ auto *S = cast<MipsOptionsInputSection<ELFT>>(C);
+ if (S->Reginfo)
+ GprMask |= S->Reginfo->ri_gprmask;
+}
+
namespace lld {
namespace elf {
template class OutputSectionBase<ELF32LE>;
@@ -1758,6 +1786,11 @@ template class MipsReginfoOutputSection<
template class MipsReginfoOutputSection<ELF64LE>;
template class MipsReginfoOutputSection<ELF64BE>;
+template class MipsOptionsOutputSection<ELF32LE>;
+template class MipsOptionsOutputSection<ELF32BE>;
+template class MipsOptionsOutputSection<ELF64LE>;
+template class MipsOptionsOutputSection<ELF64BE>;
+
template class MergeOutputSection<ELF32LE>;
template class MergeOutputSection<ELF32BE>;
template class MergeOutputSection<ELF64LE>;
Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=268485&r1=268484&r2=268485&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Wed May 4 05:07:38 2016
@@ -501,6 +501,20 @@ private:
uint32_t GprMask = 0;
};
+template <class ELFT>
+class MipsOptionsOutputSection final : public OutputSectionBase<ELFT> {
+ typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
+ typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+
+public:
+ MipsOptionsOutputSection();
+ void writeTo(uint8_t *Buf) override;
+ void addSection(InputSectionBase<ELFT> *S) override;
+
+private:
+ uint32_t GprMask = 0;
+};
+
// --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.
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=268485&r1=268484&r2=268485&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed May 4 05:07:38 2016
@@ -1166,6 +1166,9 @@ OutputSectionFactory<ELFT>::create(Input
case InputSectionBase<ELFT>::MipsReginfo:
Sec = new MipsReginfoOutputSection<ELFT>();
break;
+ case InputSectionBase<ELFT>::MipsOptions:
+ Sec = new MipsOptionsOutputSection<ELFT>();
+ break;
}
return {Sec, true};
}
Added: lld/trunk/test/ELF/mips-options.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-options.s?rev=268485&view=auto
==============================================================================
--- lld/trunk/test/ELF/mips-options.s (added)
+++ lld/trunk/test/ELF/mips-options.s Wed May 4 05:07:38 2016
@@ -0,0 +1,28 @@
+# Check MIPS .MIPS.options section generation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux \
+# RUN: %S/Inputs/mips-dynamic.s -o %t2.o
+# RUN: ld.lld %t1.o %t2.o -shared -o %t.so
+# RUN: llvm-readobj -symbols -mips-options %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+ .text
+ .globl __start
+__start:
+ lw $t0,%call16(g1)($gp)
+
+# CHECK: Name: _gp
+# CHECK-NEXT: Value: 0x[[GP:[0-9A-F]+]]
+
+# CHECK: MIPS Options {
+# CHECK-NEXT: ODK_REGINFO {
+# CHECK-NEXT: GP: 0x[[GP]]
+# CHECK-NEXT: General Mask: 0x10001001
+# CHECK-NEXT: Co-Proc Mask0: 0x0
+# CHECK-NEXT: Co-Proc Mask1: 0x0
+# CHECK-NEXT: Co-Proc Mask2: 0x0
+# CHECK-NEXT: Co-Proc Mask3: 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
More information about the llvm-commits
mailing list