[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.

llvm-svn: 268485
This commit is contained in:
Simon Atanasyan
2016-05-04 10:07:38 +00:00
parent 13e2c1a709
commit add74f37f2
8 changed files with 144 additions and 12 deletions

View File

@@ -64,9 +64,10 @@ typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) {
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>::MipsReginfoInputSection(elf::ObjectFile<ELFT> *F,
: 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>::classof(const InputSectionBase<ELFT> *S) {
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::MipsReginfoInputSection<ELF32LE>;
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>;