diff options
author | georgerim <georgerim@gmail.com> | 2019-10-25 13:03:19 +0300 |
---|---|---|
committer | georgerim <georgerim@gmail.com> | 2019-10-25 13:25:56 +0300 |
commit | de3cef1d5d33212059164d6095aca5c5b0284001 (patch) | |
tree | ba617e1ffe517fbf1622d98b21ef6e5a25a3d659 /llvm/lib/ObjectYAML | |
parent | 8aa84ad37db7ddbff5c1a2e4ef8ff2a616f1da57 (diff) | |
download | bcm5719-llvm-de3cef1d5d33212059164d6095aca5c5b0284001.tar.gz bcm5719-llvm-de3cef1d5d33212059164d6095aca5c5b0284001.zip |
[yaml2obj, obj2yaml] - Add support for SHT_NOTE sections.
SHT_NOTE is the section that consists of
namesz, descsz, type, name + padding, desc + padding data.
This patch teaches yaml2obj, obj2yaml to dump and parse them.
This patch implements the section how it is described here:
https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-18048.html
Which says: "For 64–bit objects and 32–bit objects, each entry is an array of 4-byte words in
the format of the target processor"
The official specification is different
http://www.sco.com/developers/gabi/latest/ch5.pheader.html#note_section
And says: "n 64-bit objects (files with e_ident[EI_CLASS] equal to ELFCLASS64), each entry is an array
of 8-byte words in the format of the target processor. In 32-bit objects (files with e_ident[EI_CLASS]
equal to ELFCLASS32), each entry is an array of 4-byte words in the format of the target processor"
Since LLVM uses the first, 32-bit way, this patch follows it.
Differential revision: https://reviews.llvm.org/D68983
Diffstat (limited to 'llvm/lib/ObjectYAML')
-rw-r--r-- | llvm/lib/ObjectYAML/ELFEmitter.cpp | 72 | ||||
-rw-r--r-- | llvm/lib/ObjectYAML/ELFYAML.cpp | 38 |
2 files changed, 102 insertions, 8 deletions
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index 8ba1608254b..dae3f395993 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -36,6 +36,16 @@ class ContiguousBlobAccumulator { SmallVector<char, 128> Buf; raw_svector_ostream OS; +public: + ContiguousBlobAccumulator(uint64_t InitialOffset_) + : InitialOffset(InitialOffset_), Buf(), OS(Buf) {} + + template <class Integer> + raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) { + Offset = padToAlignment(Align); + return OS; + } + /// \returns The new offset. uint64_t padToAlignment(unsigned Align) { if (Align == 0) @@ -46,14 +56,6 @@ class ContiguousBlobAccumulator { return AlignedOffset; // == CurrentOffset; } -public: - ContiguousBlobAccumulator(uint64_t InitialOffset_) - : InitialOffset(InitialOffset_), Buf(), OS(Buf) {} - template <class Integer> - raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) { - Offset = padToAlignment(Align); - return OS; - } void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); } }; @@ -177,6 +179,9 @@ template <class ELFT> class ELFState { void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::AddrsigSection &Section, ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::NoteSection &Section, + ContiguousBlobAccumulator &CBA); ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH); @@ -440,6 +445,8 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::AddrsigSection>(Sec)) { writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast<ELFYAML::NoteSection>(Sec)) { + writeSectionContent(SHeader, *S, CBA); } else { llvm_unreachable("Unknown section type"); } @@ -1035,6 +1042,55 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, } } +template <class ELFT> +void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::NoteSection &Section, + ContiguousBlobAccumulator &CBA) { + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + uint64_t Offset = OS.tell(); + + if (Section.Content || Section.Size) { + SHeader.sh_size = writeContent(OS, Section.Content, Section.Size); + return; + } + + for (const ELFYAML::NoteEntry &NE : *Section.Notes) { + // Write name size. + if (NE.Name.empty()) + support::endian::write<uint32_t>(OS, 0, ELFT::TargetEndianness); + else + support::endian::write<uint32_t>(OS, NE.Name.size() + 1, + ELFT::TargetEndianness); + + // Write description size. + if (NE.Desc.binary_size() == 0) + support::endian::write<uint32_t>(OS, 0, ELFT::TargetEndianness); + else + support::endian::write<uint32_t>(OS, NE.Desc.binary_size(), + ELFT::TargetEndianness); + + // Write type. + support::endian::write<uint32_t>(OS, NE.Type, ELFT::TargetEndianness); + + // Write name, null terminator and padding. + if (!NE.Name.empty()) { + support::endian::write<uint8_t>(OS, arrayRefFromStringRef(NE.Name), + ELFT::TargetEndianness); + support::endian::write<uint8_t>(OS, 0, ELFT::TargetEndianness); + CBA.padToAlignment(4); + } + + // Write description and padding. + if (NE.Desc.binary_size() != 0) { + NE.Desc.writeAsBinary(OS); + CBA.padToAlignment(4); + } + } + + SHeader.sh_size = OS.tell() - Offset; +} + 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 29585abe6e8..ad316be85e8 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1032,6 +1032,13 @@ static void sectionMapping(IO &IO, ELFYAML::HashSection &Section) { IO.mapOptional("Size", Section.Size); } +static void sectionMapping(IO &IO, ELFYAML::NoteSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Content", Section.Content); + IO.mapOptional("Size", Section.Size); + IO.mapOptional("Notes", Section.Notes); +} + static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { commonSectionMapping(IO, Section); IO.mapOptional("Size", Section.Size, Hex64(0)); @@ -1143,6 +1150,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( Section.reset(new ELFYAML::HashSection()); sectionMapping(IO, *cast<ELFYAML::HashSection>(Section.get())); break; + case ELF::SHT_NOTE: + if (!IO.outputting()) + Section.reset(new ELFYAML::NoteSection()); + sectionMapping(IO, *cast<ELFYAML::NoteSection>(Section.get())); + break; case ELF::SHT_MIPS_ABIFLAGS: if (!IO.outputting()) Section.reset(new ELFYAML::MipsABIFlags()); @@ -1270,6 +1282,24 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( return {}; } + if (const auto *NS = dyn_cast<ELFYAML::NoteSection>(Section.get())) { + if (!NS->Content && !NS->Size && !NS->Notes) + return "one of \"Content\", \"Size\" or \"Notes\" must be " + "specified"; + + if (!NS->Content && !NS->Size) + return {}; + + if (NS->Size && NS->Content && + (uint64_t)*NS->Size < NS->Content->binary_size()) + return "\"Size\" must be greater than or equal to the content " + "size"; + + if (NS->Notes) + return "\"Notes\" cannot be used with \"Content\" or \"Size\""; + return {}; + } + return {}; } @@ -1313,6 +1343,14 @@ void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO, IO.mapRequired("Value", Rel.Val); } +void MappingTraits<ELFYAML::NoteEntry>::mapping(IO &IO, ELFYAML::NoteEntry &N) { + assert(IO.getContext() && "The IO context is not initialized"); + + IO.mapOptional("Name", N.Name); + IO.mapOptional("Desc", N.Desc); + IO.mapRequired("Type", N.Type); +} + void MappingTraits<ELFYAML::VerdefEntry>::mapping(IO &IO, ELFYAML::VerdefEntry &E) { assert(IO.getContext() && "The IO context is not initialized"); |