[yaml2obj/obj2yaml] - Add support for SHT_HASH sections.
SHT_HASH specification is:
http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash
In short the format is the following: it has 2 uint32 fields
in its header: nbucket and nchain followed by (nbucket + nchain)
uint32 values.
This patch allows dumping and parsing such sections.
Differential revision: https://reviews.llvm.org/D68085
llvm-svn: 373315
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 6edc3c8..5acb02a 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -171,6 +171,9 @@
void writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::StackSizesSection &Section,
ContiguousBlobAccumulator &CBA);
+ void writeSectionContent(Elf_Shdr &SHeader,
+ const ELFYAML::HashSection &Section,
+ ContiguousBlobAccumulator &CBA);
ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);
public:
@@ -417,7 +420,9 @@
} else if (auto S = dyn_cast<ELFYAML::VerdefSection>(Sec)) {
writeSectionContent(SHeader, *S, CBA);
} else if (auto S = dyn_cast<ELFYAML::StackSizesSection>(Sec)) {
- writeSectionContent(SHeader, *S, CBA);
+ writeSectionContent(SHeader, *S, CBA);
+ } else if (auto S = dyn_cast<ELFYAML::HashSection>(Sec)) {
+ writeSectionContent(SHeader, *S, CBA);
} else {
llvm_unreachable("Unknown section type");
}
@@ -810,6 +815,34 @@
template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
+ const ELFYAML::HashSection &Section,
+ ContiguousBlobAccumulator &CBA) {
+ raw_ostream &OS =
+ CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
+
+ unsigned Link = 0;
+ if (SN2I.lookup(".dynsym", Link))
+ SHeader.sh_link = Link;
+
+ if (Section.Content) {
+ SHeader.sh_size = writeContent(OS, Section.Content, None);
+ return;
+ }
+
+ support::endian::write<uint32_t>(OS, Section.Bucket->size(),
+ ELFT::TargetEndianness);
+ support::endian::write<uint32_t>(OS, Section.Chain->size(),
+ ELFT::TargetEndianness);
+ for (uint32_t Val : *Section.Bucket)
+ support::endian::write<uint32_t>(OS, Val, ELFT::TargetEndianness);
+ for (uint32_t Val : *Section.Chain)
+ support::endian::write<uint32_t>(OS, Val, ELFT::TargetEndianness);
+
+ SHeader.sh_size = (2 + Section.Bucket->size() + Section.Chain->size()) * 4;
+}
+
+template <class ELFT>
+void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::VerdefSection &Section,
ContiguousBlobAccumulator &CBA) {
typedef typename ELFT::Verdef Elf_Verdef;
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 94b1df1..3a09a11 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -1024,6 +1024,13 @@
IO.mapOptional("Entries", Section.Entries);
}
+static void sectionMapping(IO &IO, ELFYAML::HashSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapOptional("Content", Section.Content);
+ IO.mapOptional("Bucket", Section.Bucket);
+ IO.mapOptional("Chain", Section.Chain);
+}
+
static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) {
commonSectionMapping(IO, Section);
IO.mapOptional("Size", Section.Size, Hex64(0));
@@ -1123,6 +1130,11 @@
Section.reset(new ELFYAML::NoBitsSection());
sectionMapping(IO, *cast<ELFYAML::NoBitsSection>(Section.get()));
break;
+ case ELF::SHT_HASH:
+ if (!IO.outputting())
+ Section.reset(new ELFYAML::HashSection());
+ sectionMapping(IO, *cast<ELFYAML::HashSection>(Section.get()));
+ break;
case ELF::SHT_MIPS_ABIFLAGS:
if (!IO.outputting())
Section.reset(new ELFYAML::MipsABIFlags());
@@ -1196,6 +1208,24 @@
return ".stack_sizes: Content and Entries cannot be used together";
return {};
}
+
+ if (const auto *HS = dyn_cast<ELFYAML::HashSection>(Section.get())) {
+ if (!HS->Content && !HS->Bucket && !HS->Chain)
+ return "one of \"Content\", \"Bucket\" or \"Chain\" must be specified";
+
+ if (HS->Content) {
+ if (HS->Bucket)
+ return "\"Content\" and \"Bucket\" cannot be used together";
+ if (HS->Chain)
+ return "\"Content\" and \"Chain\" cannot be used together";
+ return {};
+ }
+
+ if ((HS->Bucket && !HS->Chain) || (!HS->Bucket && HS->Chain))
+ return "\"Bucket\" and \"Chain\" must be used together";
+ return {};
+ }
+
return {};
}