diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/ObjectYAML/ELFEmitter.cpp | 69 | ||||
-rw-r--r-- | llvm/lib/ObjectYAML/ELFYAML.cpp | 46 |
2 files changed, 115 insertions, 0 deletions
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index 64b5cd4df5b..be733dca696 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -182,6 +182,9 @@ template <class ELFT> class ELFState { void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::NoteSection &Section, ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::GnuHashSection &Section, + ContiguousBlobAccumulator &CBA); ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH); @@ -440,6 +443,8 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::NoteSection>(Sec)) { writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast<ELFYAML::GnuHashSection>(Sec)) { + writeSectionContent(SHeader, *S, CBA); } else { llvm_unreachable("Unknown section type"); } @@ -1091,6 +1096,70 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, SHeader.sh_size = OS.tell() - Offset; } +template <class ELFT> +void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::GnuHashSection &Section, + ContiguousBlobAccumulator &CBA) { + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + + unsigned Link = 0; + if (Section.Link.empty() && SN2I.lookup(".dynsym", Link)) + SHeader.sh_link = Link; + + if (Section.Content) { + SHeader.sh_size = writeContent(OS, Section.Content, None); + return; + } + + // We write the header first, starting with the hash buckets count. Normally + // it is the number of entries in HashBuckets, but the "NBuckets" property can + // be used to override this field, which is useful for producing broken + // objects. + if (Section.Header->NBuckets) + support::endian::write<uint32_t>(OS, *Section.Header->NBuckets, + ELFT::TargetEndianness); + else + support::endian::write<uint32_t>(OS, Section.HashBuckets->size(), + ELFT::TargetEndianness); + + // Write the index of the first symbol in the dynamic symbol table accessible + // via the hash table. + support::endian::write<uint32_t>(OS, Section.Header->SymNdx, + ELFT::TargetEndianness); + + // Write the number of words in the Bloom filter. As above, the "MaskWords" + // property can be used to set this field to any value. + if (Section.Header->MaskWords) + support::endian::write<uint32_t>(OS, *Section.Header->MaskWords, + ELFT::TargetEndianness); + else + support::endian::write<uint32_t>(OS, Section.BloomFilter->size(), + ELFT::TargetEndianness); + + // Write the shift constant used by the Bloom filter. + support::endian::write<uint32_t>(OS, Section.Header->Shift2, + ELFT::TargetEndianness); + + // We've finished writing the header. Now write the Bloom filter. + for (llvm::yaml::Hex64 Val : *Section.BloomFilter) + support::endian::write<typename ELFT::uint>(OS, Val, + ELFT::TargetEndianness); + + // Write an array of hash buckets. + for (llvm::yaml::Hex32 Val : *Section.HashBuckets) + support::endian::write<uint32_t>(OS, Val, ELFT::TargetEndianness); + + // Write an array of hash values. + for (llvm::yaml::Hex32 Val : *Section.HashValues) + support::endian::write<uint32_t>(OS, Val, ELFT::TargetEndianness); + + SHeader.sh_size = 16 /*Header size*/ + + Section.BloomFilter->size() * sizeof(typename ELFT::uint) + + Section.HashBuckets->size() * 4 + + Section.HashValues->size() * 4; +} + template <class ELFT> void ELFState<ELFT>::buildSectionIndex() { for (unsigned I = 0, E = Doc.Sections.size(); I != E; ++I) { StringRef Name = Doc.Sections[I]->Name; diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index f362b9c23a7..5872cbbe515 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1039,6 +1039,15 @@ static void sectionMapping(IO &IO, ELFYAML::NoteSection &Section) { IO.mapOptional("Notes", Section.Notes); } + +static void sectionMapping(IO &IO, ELFYAML::GnuHashSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Content", Section.Content); + IO.mapOptional("Header", Section.Header); + IO.mapOptional("BloomFilter", Section.BloomFilter); + IO.mapOptional("HashBuckets", Section.HashBuckets); + IO.mapOptional("HashValues", Section.HashValues); +} static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { commonSectionMapping(IO, Section); IO.mapOptional("Size", Section.Size, Hex64(0)); @@ -1155,6 +1164,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( Section.reset(new ELFYAML::NoteSection()); sectionMapping(IO, *cast<ELFYAML::NoteSection>(Section.get())); break; + case ELF::SHT_GNU_HASH: + if (!IO.outputting()) + Section.reset(new ELFYAML::GnuHashSection()); + sectionMapping(IO, *cast<ELFYAML::GnuHashSection>(Section.get())); + break; case ELF::SHT_MIPS_ABIFLAGS: if (!IO.outputting()) Section.reset(new ELFYAML::MipsABIFlags()); @@ -1300,6 +1314,29 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( return {}; } + if (const auto *Sec = dyn_cast<ELFYAML::GnuHashSection>(Section.get())) { + if (!Sec->Content && !Sec->Header && !Sec->BloomFilter && + !Sec->HashBuckets && !Sec->HashValues) + return "either \"Content\" or \"Header\", \"BloomFilter\", " + "\"HashBuckets\" and \"HashBuckets\" must be specified"; + + if (Sec->Header || Sec->BloomFilter || Sec->HashBuckets || + Sec->HashValues) { + if (!Sec->Header || !Sec->BloomFilter || !Sec->HashBuckets || + !Sec->HashValues) + return "\"Header\", \"BloomFilter\", " + "\"HashBuckets\" and \"HashValues\" must be used together"; + if (Sec->Content) + return "\"Header\", \"BloomFilter\", " + "\"HashBuckets\" and \"HashValues\" can't be used together with " + "\"Content\""; + return {}; + } + + // Only Content is specified. + return {}; + } + return {}; } @@ -1335,6 +1372,15 @@ void MappingTraits<ELFYAML::StackSizeEntry>::mapping( IO.mapRequired("Size", E.Size); } +void MappingTraits<ELFYAML::GnuHashHeader>::mapping(IO &IO, + ELFYAML::GnuHashHeader &E) { + assert(IO.getContext() && "The IO context is not initialized"); + IO.mapOptional("NBuckets", E.NBuckets); + IO.mapRequired("SymNdx", E.SymNdx); + IO.mapOptional("MaskWords", E.MaskWords); + IO.mapRequired("Shift2", E.Shift2); +} + void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO, ELFYAML::DynamicEntry &Rel) { assert(IO.getContext() && "The IO context is not initialized"); |