Convert MipsOptionsSection to SyntheticSection.

llvm-svn: 287615
This commit is contained in:
Rui Ueyama 2016-11-22 04:13:09 +00:00
parent b71cae90de
commit 9cfac8a849
3 changed files with 76 additions and 70 deletions

View File

@ -112,21 +112,6 @@ template <class ELFT> MergeInputSection<ELFT> *elf::createCommentSection() {
return Ret; return Ret;
} }
// Iterate over sections of the specified type. For each section call
// provided function. After that "kill" the section by turning off
// "Live" flag, so that they won't be included in the final output.
template <class ELFT>
static void iterateSectionContents(
uint32_t Type,
std::function<void(elf::ObjectFile<ELFT> *, ArrayRef<uint8_t>)> F) {
for (InputSectionBase<ELFT> *Sec : Symtab<ELFT>::X->Sections) {
if (Sec && Sec->Live && Sec->Type == Type) {
Sec->Live = false;
F(Sec->getFile(), Sec->Data);
}
}
}
// .MIPS.abiflags section. // .MIPS.abiflags section.
template <class ELFT> template <class ELFT>
MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection(Elf_Mips_ABIFlags Flags) MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection(Elf_Mips_ABIFlags Flags)
@ -181,42 +166,62 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
// .MIPS.options section. // .MIPS.options section.
template <class ELFT> template <class ELFT>
MipsOptionsSection<ELFT>::MipsOptionsSection() MipsOptionsSection<ELFT>::MipsOptionsSection(Elf_Mips_RegInfo Reginfo)
: InputSection<ELFT>(SHF_ALLOC, SHT_MIPS_OPTIONS, 8, ArrayRef<uint8_t>(), : SyntheticSection<ELFT>(SHF_ALLOC, SHT_MIPS_OPTIONS, 8, ".MIPS.options"),
".MIPS.options") { Reginfo(Reginfo) {}
Buf.resize(sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo));
getOptions()->kind = ODK_REGINFO;
getOptions()->size = Buf.size();
auto Func = [this](ObjectFile<ELFT> *F, ArrayRef<uint8_t> D) {
while (!D.empty()) {
if (D.size() < sizeof(Elf_Mips_Options)) {
error(getFilename(F) + ": invalid size of .MIPS.options section");
break;
}
auto *O = reinterpret_cast<const Elf_Mips_Options *>(D.data());
if (O->kind == ODK_REGINFO) {
if (Config->Relocatable && O->getRegInfo().ri_gp_value)
error(getFilename(F) + ": unsupported non-zero ri_gp_value");
getOptions()->getRegInfo().ri_gprmask |= O->getRegInfo().ri_gprmask;
F->MipsGp0 = O->getRegInfo().ri_gp_value;
break;
}
if (!O->size)
fatal(getFilename(F) + ": zero option descriptor size");
D = D.slice(O->size);
}
};
iterateSectionContents<ELFT>(SHT_MIPS_OPTIONS, Func);
this->Data = ArrayRef<uint8_t>(Buf); template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *Buf) {
// Section should be alive for N64 ABI only. auto *Options = reinterpret_cast<Elf_Mips_Options *>(Buf);
this->Live = ELFT::Is64Bits; Options->kind = ODK_REGINFO;
Options->size = getSize();
if (!Config->Relocatable)
Reginfo.ri_gp_value = In<ELFT>::MipsGot->getVA() + MipsGPOffset;
memcpy(Buf + sizeof(Options), &Reginfo, sizeof(Reginfo));
} }
template <class ELFT> void MipsOptionsSection<ELFT>::finalize() { template <class ELFT>
if (!Config->Relocatable) MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {
getOptions()->getRegInfo().ri_gp_value = // N64 ABI only.
In<ELFT>::MipsGot->getVA() + MipsGPOffset; if (!ELFT::Is64Bits)
return nullptr;
Elf_Mips_RegInfo Reginfo = {};
bool Create = false;
for (InputSectionBase<ELFT> *Sec : Symtab<ELFT>::X->Sections) {
if (!Sec->Live || Sec->Type != SHT_MIPS_OPTIONS)
continue;
Sec->Live = false;
Create = true;
std::string Filename = getFilename(Sec->getFile());
ArrayRef<uint8_t> D = Sec->Data;
while (!D.empty()) {
if (D.size() < sizeof(Elf_Mips_Options)) {
error(Filename + ": invalid size of .MIPS.options section");
break;
}
auto *Opt = reinterpret_cast<const Elf_Mips_Options *>(D.data());
if (Opt->kind == ODK_REGINFO) {
if (Config->Relocatable && Opt->getRegInfo().ri_gp_value)
error(Filename + ": unsupported non-zero ri_gp_value");
Reginfo.ri_gprmask |= Opt->getRegInfo().ri_gprmask;
Sec->getFile()->MipsGp0 = Opt->getRegInfo().ri_gp_value;
break;
}
if (!Opt->size)
fatal(Filename + ": zero option descriptor size");
D = D.slice(Opt->size);
}
};
if (Create)
return new MipsOptionsSection<ELFT>(Reginfo);
return nullptr;
} }
// MIPS .reginfo section. // MIPS .reginfo section.

View File

@ -17,24 +17,6 @@
namespace lld { namespace lld {
namespace elf { namespace elf {
// .MIPS.options section.
template <class ELFT>
class MipsOptionsSection final : public InputSection<ELFT> {
typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
public:
MipsOptionsSection();
void finalize();
private:
std::vector<uint8_t> Buf;
Elf_Mips_Options *getOptions() {
return reinterpret_cast<Elf_Mips_Options *>(Buf.data());
}
};
template <class ELFT> class SyntheticSection : public InputSection<ELFT> { template <class ELFT> class SyntheticSection : public InputSection<ELFT> {
typedef typename ELFT::uint uintX_t; typedef typename ELFT::uint uintX_t;
@ -580,6 +562,26 @@ private:
Elf_Mips_ABIFlags Flags; Elf_Mips_ABIFlags Flags;
}; };
// .MIPS.options section.
template <class ELFT>
class MipsOptionsSection final : public SyntheticSection<ELFT> {
typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
public:
static MipsOptionsSection *create();
MipsOptionsSection(Elf_Mips_RegInfo Reginfo);
void writeTo(uint8_t *Buf) override;
size_t getSize() const override {
return sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);
}
private:
Elf_Mips_RegInfo Reginfo;
};
// MIPS .reginfo section. // MIPS .reginfo section.
template <class ELFT> template <class ELFT>
class MipsReginfoSection final : public SyntheticSection<ELFT> { class MipsReginfoSection final : public SyntheticSection<ELFT> {

View File

@ -312,10 +312,9 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
Symtab<ELFT>::X->Sections.push_back(Sec); Symtab<ELFT>::X->Sections.push_back(Sec);
} }
// .MIPS.options // .MIPS.options
auto *OptSec = make<MipsOptionsSection<ELFT>>(); if (auto *Sec = MipsOptionsSection<ELFT>::create()) {
if (OptSec->Live) { In<ELFT>::MipsOptions = Sec;
In<ELFT>::MipsOptions = OptSec; Symtab<ELFT>::X->Sections.push_back(Sec);
Symtab<ELFT>::X->Sections.push_back(OptSec);
} }
// MIPS .reginfo // MIPS .reginfo
if (auto *Sec = MipsReginfoSection<ELFT>::create()) { if (auto *Sec = MipsReginfoSection<ELFT>::create()) {