From 7570d387c21935b58afa67cb9ee17250e38721fa Mon Sep 17 00:00:00 2001 From: Georgii Rymar Date: Wed, 15 Jan 2020 14:29:29 +0300 Subject: [PATCH] [yaml2obj/obj2yaml] - Add support for SHT_RELR sections. Note: this is a reland with a trivial 2 lines fix in ELFState::writeSectionContent. It adds a check similar to ones we already have for other sections to fix the case revealed by bots, like http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/builds/60744. The encoded sequence of Elf*_Relr entries in a SHT_RELR section looks like [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ] i.e. start with an address, followed by any number of bitmaps. The address entry encodes 1 relocation. The subsequent bitmap entries encode up to 63(31) relocations each, at subsequent offsets following the last address entry. More information is here: https://github.com/llvm-mirror/llvm/blob/master/lib/Object/ELF.cpp#L272 This patch adds a support for these sections. Differential revision: https://reviews.llvm.org/D71872 --- llvm/include/llvm/ObjectYAML/ELFYAML.h | 12 ++++++++++ llvm/lib/ObjectYAML/ELFEmitter.cpp | 40 ++++++++++++++++++++++++++++------ llvm/lib/ObjectYAML/ELFYAML.cpp | 17 +++++++++++++++ llvm/tools/obj2yaml/elf2yaml.cpp | 33 ++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 7 deletions(-) diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h index c9f1458..f87135e 100644 --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -138,6 +138,7 @@ struct Chunk { Group, RawContent, Relocation, + Relr, NoBits, Note, Hash, @@ -440,6 +441,17 @@ struct RelocationSection : Section { } }; +struct RelrSection : Section { + Optional> Entries; + Optional Content; + + RelrSection() : Section(ChunkKind::Relr) {} + + static bool classof(const Chunk *S) { + return S->Kind == ChunkKind::Relr; + } +}; + struct SymtabShndxSection : Section { std::vector Entries; diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index 69f5510..ee7d5f6 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -110,6 +110,7 @@ template class ELFState { typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::Relr Elf_Relr; typedef typename ELFT::Dyn Elf_Dyn; + typedef typename ELFT::uint uintX_t; enum class SymtabType { Static, Dynamic }; @@ -165,6 +166,9 @@ template class ELFState { void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::RelocationSection &Section, ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::RelrSection &Section, + ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::Group &Group, ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, @@ -454,6 +458,8 @@ void ELFState::initSectionHeaders(std::vector &SHeaders, writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast(Sec)) { writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast(Sec)) { + writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast(Sec)) { writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast(Sec)) { @@ -770,10 +776,6 @@ void ELFState::writeSectionContent( if (Section.EntSize) SHeader.sh_entsize = *Section.EntSize; - else if (Section.Type == llvm::ELF::SHT_RELR) - SHeader.sh_entsize = sizeof(Elf_Relr); - else - SHeader.sh_entsize = 0; if (Section.Info) SHeader.sh_info = *Section.Info; @@ -828,6 +830,33 @@ void ELFState::writeSectionContent( } template +void ELFState::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::RelrSection &Section, + ContiguousBlobAccumulator &CBA) { + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + SHeader.sh_entsize = + Section.EntSize ? uint64_t(*Section.EntSize) : sizeof(Elf_Relr); + + if (Section.Content) { + SHeader.sh_size = writeContent(OS, Section.Content, None); + return; + } + + if (!Section.Entries) + return; + + for (llvm::yaml::Hex64 E : *Section.Entries) { + if (!ELFT::Is64Bits && E > UINT32_MAX) + reportError(Section.Name + ": the value is too large for 32-bits: 0x" + + Twine::utohexstr(E)); + support::endian::write(OS, E, ELFT::TargetEndianness); + } + + SHeader.sh_size = sizeof(uintX_t) * Section.Entries->size(); +} + +template void ELFState::writeSectionContent( Elf_Shdr &SHeader, const ELFYAML::SymtabShndxSection &Shndx, ContiguousBlobAccumulator &CBA) { @@ -889,7 +918,6 @@ template void ELFState::writeSectionContent( Elf_Shdr &SHeader, const ELFYAML::StackSizesSection &Section, ContiguousBlobAccumulator &CBA) { - using uintX_t = typename ELFT::uint; raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); @@ -1115,8 +1143,6 @@ template void ELFState::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::DynamicSection &Section, ContiguousBlobAccumulator &CBA) { - typedef typename ELFT::uint uintX_t; - assert(Section.Type == llvm::ELF::SHT_DYNAMIC && "Section type is not SHT_DYNAMIC"); diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index 21ae850..efa7ecb 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1101,6 +1101,12 @@ static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) { IO.mapOptional("Relocations", Section.Relocations); } +static void sectionMapping(IO &IO, ELFYAML::RelrSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Entries", Section.Entries); + IO.mapOptional("Content", Section.Content); +} + static void groupSectionMapping(IO &IO, ELFYAML::Group &Group) { commonSectionMapping(IO, Group); IO.mapOptional("Info", Group.Signature); @@ -1200,6 +1206,11 @@ void MappingTraits>::mapping( Section.reset(new ELFYAML::RelocationSection()); sectionMapping(IO, *cast(Section.get())); break; + case ELF::SHT_RELR: + if (!IO.outputting()) + Section.reset(new ELFYAML::RelrSection()); + sectionMapping(IO, *cast(Section.get())); + break; case ELF::SHT_GROUP: if (!IO.outputting()) Section.reset(new ELFYAML::Group()); @@ -1441,6 +1452,12 @@ StringRef MappingTraits>::validate( return {}; } + if (const auto *RS = dyn_cast(C.get())) { + if (RS->Entries && RS->Content) + return "\"Entries\" and \"Content\" can't be used together"; + return {}; + } + return {}; } diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp index 75d2e42..904d1ad 100644 --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/llvm/tools/obj2yaml/elf2yaml.cpp @@ -27,6 +27,7 @@ class ELFDumper { typedef typename ELFT::Word Elf_Word; typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; + using Elf_Relr = typename ELFT::Relr; using Elf_Nhdr = typename ELFT::Nhdr; using Elf_Note = typename ELFT::Note; @@ -66,6 +67,7 @@ class ELFDumper { dumpDependentLibrariesSection(const Elf_Shdr *Shdr); Expected dumpDynamicSection(const Elf_Shdr *Shdr); Expected dumpRelocSection(const Elf_Shdr *Shdr); + Expected dumpRelrSection(const Elf_Shdr *Shdr); Expected dumpContentSection(const Elf_Shdr *Shdr); Expected @@ -251,6 +253,13 @@ template Expected ELFDumper::dump() { Y->Chunks.emplace_back(*SecOrErr); break; } + case ELF::SHT_RELR: { + Expected SecOrErr = dumpRelrSection(&Sec); + if (!SecOrErr) + return SecOrErr.takeError(); + Y->Chunks.emplace_back(*SecOrErr); + break; + } case ELF::SHT_GROUP: { Expected GroupOrErr = dumpGroup(&Sec); if (!GroupOrErr) @@ -724,6 +733,30 @@ ELFDumper::dumpRelocSection(const Elf_Shdr *Shdr) { } template +Expected +ELFDumper::dumpRelrSection(const Elf_Shdr *Shdr) { + auto S = std::make_unique(); + if (auto E = dumpCommonSection(Shdr, *S)) + return std::move(E); + + if (Expected> Relrs = Obj.relrs(Shdr)) { + S->Entries.emplace(); + for (Elf_Relr Rel : *Relrs) + S->Entries->emplace_back(Rel); + return S.release(); + } else { + // Ignore. We are going to dump the data as raw content below. + consumeError(Relrs.takeError()); + } + + Expected> ContentOrErr = Obj.getSectionContents(Shdr); + if (!ContentOrErr) + return ContentOrErr.takeError(); + S->Content = *ContentOrErr; + return S.release(); +} + +template Expected ELFDumper::dumpContentSection(const Elf_Shdr *Shdr) { auto S = std::make_unique(); -- 2.7.4