Index: llvm/include/llvm/ObjectYAML/DWARFYAML.h =================================================================== --- llvm/include/llvm/ObjectYAML/DWARFYAML.h +++ llvm/include/llvm/ObjectYAML/DWARFYAML.h @@ -161,8 +161,6 @@ } // end namespace DWARFYAML } // end namespace llvm -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex64) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex8) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::AttributeAbbrev) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Abbrev) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::ARangeDescriptor) Index: llvm/include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- llvm/include/llvm/ObjectYAML/ELFYAML.h +++ llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -132,6 +132,7 @@ Relocation, NoBits, Hash, + GnuHash, Verdef, Verneed, StackSizes, @@ -233,6 +234,39 @@ static bool classof(const Section *S) { return S->Kind == SectionKind::Hash; } }; +struct GnuHashHeader { + // The number of hash buckets. + // Not used when dumping the object, but can be used to override + // the real number of buckets when emiting an object from the YAML document. + Optional NBuckets; + + // Index of the first symbol in the dynamic symbol table + // included into the hash table. + llvm::yaml::Hex32 SymNdx; + + // The number of words in the Bloom filter. + // Not used when dumping the object, but can be used to override + // the real number of words in the Bloom filter when emiting an object from + // the YAML document. + Optional MaskWords; + + // A shift constant used by the Bloom filter. + llvm::yaml::Hex32 Shift2; +}; + +struct GnuHashSection : Section { + Optional Content; + + Optional Header; + Optional> BloomFilter; + Optional> HashBuckets; + Optional> HashValues; + + GnuHashSection() : Section(SectionKind::GnuHash) {} + + static bool classof(const Section *S) { return S->Kind == SectionKind::GnuHash; } +}; + struct VernauxEntry { uint32_t Hash; uint16_t Flags; @@ -524,6 +558,10 @@ static void mapping(IO &IO, ELFYAML::StackSizeEntry &Rel); }; +template <> struct MappingTraits { + static void mapping(IO &IO, ELFYAML::GnuHashHeader &Rel); +}; + template <> struct MappingTraits { static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel); }; Index: llvm/include/llvm/Support/YAMLTraits.h =================================================================== --- llvm/include/llvm/Support/YAMLTraits.h +++ llvm/include/llvm/Support/YAMLTraits.h @@ -2035,4 +2035,8 @@ } \ } +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex32) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex8) + #endif // LLVM_SUPPORT_YAMLTRAITS_H Index: llvm/lib/ObjectYAML/ELFEmitter.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFEmitter.cpp +++ llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -177,6 +177,9 @@ void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::AddrsigSection &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 @@ 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 { llvm_unreachable("Unknown section type"); } @@ -1035,6 +1040,68 @@ } } +template +void ELFState::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. Here we write hash buckets count. Normally it is + // the number of entries in HashBuckets, but "NBuckets" property can be + // used to override this field, what is useful for producing broken objects. + if (Section.Header->NBuckets) + support::endian::write(OS, *Section.Header->NBuckets, + ELFT::TargetEndianness); + else + support::endian::write(OS, Section.HashBuckets->size(), + ELFT::TargetEndianness); + + // Write index of the first symbol in the dynamic symbol table. + support::endian::write(OS, Section.Header->SymNdx, + ELFT::TargetEndianness); + + // Write the number of words in the Bloom filter. Just like above, the + // "MaskWords" property can be used to put any value to this field. + if (Section.Header->MaskWords) + support::endian::write(OS, *Section.Header->MaskWords, + ELFT::TargetEndianness); + else + support::endian::write(OS, Section.BloomFilter->size(), + ELFT::TargetEndianness); + + // Write the shift constant used by the Bloom filter. + support::endian::write(OS, Section.Header->Shift2, + ELFT::TargetEndianness); + + // We've finished writing the header. Here we write the bloom filter. + for (llvm::yaml::Hex64 Val : *Section.BloomFilter) + support::endian::write(OS, Val, + ELFT::TargetEndianness); + + // Write an array of hash buckets. + for (llvm::yaml::Hex32 Val : *Section.HashBuckets) + support::endian::write(OS, Val, ELFT::TargetEndianness); + + // Write an array of hash values. + for (llvm::yaml::Hex32 Val : *Section.HashValues) + support::endian::write(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 void ELFState::buildSectionIndex() { for (unsigned I = 0, E = Doc.Sections.size(); I != E; ++I) { StringRef Name = Doc.Sections[I]->Name; Index: llvm/lib/ObjectYAML/ELFYAML.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFYAML.cpp +++ llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1032,6 +1032,16 @@ IO.mapOptional("Size", Section.Size); } + +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)); @@ -1143,6 +1153,11 @@ Section.reset(new ELFYAML::HashSection()); sectionMapping(IO, *cast(Section.get())); break; + case ELF::SHT_GNU_HASH: + if (!IO.outputting()) + Section.reset(new ELFYAML::GnuHashSection()); + sectionMapping(IO, *cast(Section.get())); + break; case ELF::SHT_MIPS_ABIFLAGS: if (!IO.outputting()) Section.reset(new ELFYAML::MipsABIFlags()); @@ -1270,6 +1285,29 @@ return {}; } + if (const auto *Sec = dyn_cast(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->HashBuckets) + 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 {}; } @@ -1305,6 +1343,15 @@ IO.mapRequired("Size", E.Size); } +void MappingTraits::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::mapping(IO &IO, ELFYAML::DynamicEntry &Rel) { assert(IO.getContext() && "The IO context is not initialized"); Index: llvm/test/ObjectYAML/MachO/DWARF-debug_info.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/DWARF-debug_info.yaml +++ llvm/test/ObjectYAML/MachO/DWARF-debug_info.yaml @@ -531,8 +531,7 @@ #CHECK: - Value: 0x0000000100000F50 #CHECK: - Value: 0x0000000000000034 #CHECK: - Value: 0x0000000000000001 -#CHECK: BlockData: -#CHECK: - 0x56 +#CHECK: BlockData: [ 0x56 ] #CHECK: - Value: 0x0000000000000076 #CHECK: - Value: 0x0000000000000001 #CHECK: - Value: 0x0000000000000003 @@ -542,9 +541,7 @@ #CHECK: - AbbrCode: 0x00000003 #CHECK: Values: #CHECK: - Value: 0x0000000000000002 -#CHECK: BlockData: -#CHECK: - 0x91 -#CHECK: - 0x78 +#CHECK: BlockData: [ 0x91, 0x78 ] #CHECK: - Value: 0x000000000000007B #CHECK: - Value: 0x0000000000000001 #CHECK: - Value: 0x0000000000000003 @@ -552,9 +549,7 @@ #CHECK: - AbbrCode: 0x00000003 #CHECK: Values: #CHECK: - Value: 0x0000000000000002 -#CHECK: BlockData: -#CHECK: - 0x91 -#CHECK: - 0x70 +#CHECK: BlockData: [ 0x91, 0x70 ] #CHECK: - Value: 0x0000000000000080 #CHECK: - Value: 0x0000000000000001 #CHECK: - Value: 0x0000000000000003 Index: llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml +++ llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml @@ -438,53 +438,17 @@ #CHECK: Values: #CHECK: - Value: 0x0123456789ABCDEF #CHECK: - Value: 0x000000000000000A -#CHECK: BlockData: -#CHECK: - 0x01 -#CHECK: - 0x02 -#CHECK: - 0x03 -#CHECK: - 0x04 -#CHECK: - 0x05 -#CHECK: - 0x06 -#CHECK: - 0x07 -#CHECK: - 0x08 -#CHECK: - 0x09 -#CHECK: - 0x00 +#CHECK: BlockData: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +#CHECK: 0x08, 0x09, 0x00 ] #CHECK: - Value: 0x000000000000000A -#CHECK: BlockData: -#CHECK: - 0x01 -#CHECK: - 0x02 -#CHECK: - 0x03 -#CHECK: - 0x04 -#CHECK: - 0x05 -#CHECK: - 0x06 -#CHECK: - 0x07 -#CHECK: - 0x08 -#CHECK: - 0x09 -#CHECK: - 0x00 +#CHECK: BlockData: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +#CHECK: 0x08, 0x09, 0x00 ] #CHECK: - Value: 0x000000000000000A -#CHECK: BlockData: -#CHECK: - 0x01 -#CHECK: - 0x02 -#CHECK: - 0x03 -#CHECK: - 0x04 -#CHECK: - 0x05 -#CHECK: - 0x06 -#CHECK: - 0x07 -#CHECK: - 0x08 -#CHECK: - 0x09 -#CHECK: - 0x00 +#CHECK: BlockData: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +#CHECK: 0x08, 0x09, 0x00 ] #CHECK: - Value: 0x000000000000000A -#CHECK: BlockData: -#CHECK: - 0x01 -#CHECK: - 0x02 -#CHECK: - 0x03 -#CHECK: - 0x04 -#CHECK: - 0x05 -#CHECK: - 0x06 -#CHECK: - 0x07 -#CHECK: - 0x08 -#CHECK: - 0x09 -#CHECK: - 0x00 +#CHECK: BlockData: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +#CHECK: 0x08, 0x09, 0x00 ] #CHECK: - Value: 0x0000000000000001 #CHECK: - Value: 0x0000000000002345 #CHECK: - Value: 0x000000006789ABCD Index: llvm/test/ObjectYAML/MachO/DWARF5-debug_info.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/DWARF5-debug_info.yaml +++ llvm/test/ObjectYAML/MachO/DWARF5-debug_info.yaml @@ -532,8 +532,7 @@ #CHECK: - Value: 0x0000000100000F50 #CHECK: - Value: 0x0000000000000034 #CHECK: - Value: 0x0000000000000001 -#CHECK: BlockData: -#CHECK: - 0x56 +#CHECK: BlockData: [ 0x56 ] #CHECK: - Value: 0x0000000000000076 #CHECK: - Value: 0x0000000000000001 #CHECK: - Value: 0x0000000000000003 @@ -543,9 +542,7 @@ #CHECK: - AbbrCode: 0x00000003 #CHECK: Values: #CHECK: - Value: 0x0000000000000002 -#CHECK: BlockData: -#CHECK: - 0x91 -#CHECK: - 0x78 +#CHECK: BlockData: [ 0x91, 0x78 ] #CHECK: - Value: 0x000000000000007B #CHECK: - Value: 0x0000000000000001 #CHECK: - Value: 0x0000000000000003 @@ -553,9 +550,7 @@ #CHECK: - AbbrCode: 0x00000003 #CHECK: Values: #CHECK: - Value: 0x0000000000000002 -#CHECK: BlockData: -#CHECK: - 0x91 -#CHECK: - 0x70 +#CHECK: BlockData: [ 0x91, 0x70 ] #CHECK: - Value: 0x0000000000000080 #CHECK: - Value: 0x0000000000000001 #CHECK: - Value: 0x0000000000000003 Index: llvm/test/ObjectYAML/MachO/bind_opcode.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/bind_opcode.yaml +++ llvm/test/ObjectYAML/MachO/bind_opcode.yaml @@ -107,8 +107,7 @@ #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000000 +#CHECK: ULEBExtraData: [ 0x0000000000000000 ] #CHECK: - Opcode: BIND_OPCODE_DO_BIND #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM Index: llvm/test/ObjectYAML/MachO/bogus_load_command.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/bogus_load_command.yaml +++ llvm/test/ObjectYAML/MachO/bogus_load_command.yaml @@ -36,17 +36,6 @@ #CHECK: ZeroPadBytes: #CHECK: - cmd: 0xDEADBEEF #CHECK: cmdsize: 24 -#CHECK: PayloadBytes: -#CHECK: - 0x01 -#CHECK: - 0x02 -#CHECK: - 0x03 -#CHECK: - 0x04 -#CHECK: - 0x05 -#CHECK: - 0x06 -#CHECK: - 0x07 -#CHECK: - 0x08 -#CHECK: - 0x09 -#CHECK: - 0x0A -#CHECK: - 0x0B -#CHECK: - 0x0C +#CHECK: PayloadBytes: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, +#CHECK: 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x00, 0x00, 0x00 ] #CHECK-NOT: LinkEditData: Index: llvm/test/ObjectYAML/MachO/lazy_bind_opcode.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/lazy_bind_opcode.yaml +++ llvm/test/ObjectYAML/MachO/lazy_bind_opcode.yaml @@ -267,8 +267,7 @@ #CHECK: LazyBindOpcodes: #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000028 +#CHECK: ULEBExtraData: [ 0x0000000000000028 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -280,8 +279,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000030 +#CHECK: ULEBExtraData: [ 0x0000000000000030 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -293,8 +291,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000038 +#CHECK: ULEBExtraData: [ 0x0000000000000038 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -306,8 +303,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000040 +#CHECK: ULEBExtraData: [ 0x0000000000000040 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -319,8 +315,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000048 +#CHECK: ULEBExtraData: [ 0x0000000000000048 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -332,8 +327,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000050 +#CHECK: ULEBExtraData: [ 0x0000000000000050 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -345,8 +339,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000058 +#CHECK: ULEBExtraData: [ 0x0000000000000058 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -358,8 +351,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000060 +#CHECK: ULEBExtraData: [ 0x0000000000000060 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -371,8 +363,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000068 +#CHECK: ULEBExtraData: [ 0x0000000000000068 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -384,8 +375,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000070 +#CHECK: ULEBExtraData: [ 0x0000000000000070 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -397,8 +387,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000078 +#CHECK: ULEBExtraData: [ 0x0000000000000078 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -410,8 +399,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000080 +#CHECK: ULEBExtraData: [ 0x0000000000000080 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -423,8 +411,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000088 +#CHECK: ULEBExtraData: [ 0x0000000000000088 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 2 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -436,8 +423,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000090 +#CHECK: ULEBExtraData: [ 0x0000000000000090 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 2 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM @@ -449,8 +435,7 @@ #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000098 +#CHECK: ULEBExtraData: [ 0x0000000000000098 ] #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM #CHECK: Imm: 2 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM Index: llvm/test/ObjectYAML/MachO/out_of_order_linkedit.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/out_of_order_linkedit.yaml +++ llvm/test/ObjectYAML/MachO/out_of_order_linkedit.yaml @@ -214,12 +214,10 @@ #CHECK: Imm: 1 #CHECK: - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ExtraData: -#CHECK: - 0x0000000000000028 +#CHECK: ExtraData: [ 0x0000000000000028 ] #CHECK: - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES #CHECK: Imm: 0 -#CHECK: ExtraData: -#CHECK: - 0x000000000000000F +#CHECK: ExtraData: [ 0x000000000000000F ] #CHECK: - Opcode: REBASE_OPCODE_DONE #CHECK: Imm: 0 #CHECK: BindOpcodes: @@ -234,8 +232,7 @@ #CHECK: Symbol: '' #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000000 +#CHECK: ULEBExtraData: [ 0x0000000000000000 ] #CHECK: Symbol: '' #CHECK: - Opcode: BIND_OPCODE_DO_BIND #CHECK: Imm: 0 Index: llvm/test/ObjectYAML/MachO/rebase_opcode.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/rebase_opcode.yaml +++ llvm/test/ObjectYAML/MachO/rebase_opcode.yaml @@ -82,11 +82,9 @@ #CHECK: Imm: 1 #CHECK: - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ExtraData: -#CHECK: - 0x0000000000000028 +#CHECK: ExtraData: [ 0x0000000000000028 ] #CHECK: - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES #CHECK: Imm: 0 -#CHECK: ExtraData: -#CHECK: - 0x000000000000000F +#CHECK: ExtraData: [ 0x000000000000000F ] #CHECK: - Opcode: REBASE_OPCODE_DONE #CHECK: Imm: 0 Index: llvm/test/ObjectYAML/MachO/weak_bind_opcode.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/weak_bind_opcode.yaml +++ llvm/test/ObjectYAML/MachO/weak_bind_opcode.yaml @@ -107,8 +107,7 @@ #CHECK: Imm: 1 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB #CHECK: Imm: 2 -#CHECK: ULEBExtraData: -#CHECK: - 0x0000000000000000 +#CHECK: ULEBExtraData: [ 0x0000000000000000 ] #CHECK: - Opcode: BIND_OPCODE_DO_BIND #CHECK: Imm: 0 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM Index: llvm/test/tools/llvm-readobj/elf-section-types.test =================================================================== --- llvm/test/tools/llvm-readobj/elf-section-types.test +++ llvm/test/tools/llvm-readobj/elf-section-types.test @@ -209,6 +209,7 @@ Type: SHT_GNU_ATTRIBUTES - Name: gnu_hash Type: SHT_GNU_HASH + Content: "" - Name: gnu_verdef Type: SHT_GNU_verdef Info: 0 Index: llvm/test/tools/obj2yaml/elf-gnu-hash-section.yaml =================================================================== --- /dev/null +++ llvm/test/tools/obj2yaml/elf-gnu-hash-section.yaml @@ -0,0 +1,132 @@ +## Check how obj2yaml produces SHT_GNU_HASH section descriptions. + +## Check that obj2yaml uses "Header", "BloomFilter", "HashBuckets" and "HashValues" +## tags to describe a SHT_GNU_HASH section when it has content of a correct size. + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=FIELDS + +# FIELDS: - Name: .gnu.hash +# FIELDS-NEXT: Type: SHT_GNU_HASH +# FIELDS-NEXT: Flags: [ SHF_ALLOC ] +# FIELDS-NEXT: Header: +# FIELDS-NEXT: SymNdx: 0x00000001 +# FIELDS-NEXT: Shift2: 0x00000002 +# FIELDS-NEXT: BloomFilter: [ 0x0000000000000003, 0x0000000000000004 ] +# FIELDS-NEXT: HashBuckets: [ 0x00000005, 0x00000006, 0x00000007 ] +# FIELDS-NEXT: HashValues: [ 0x00000008, 0x00000009, 0x0000000A, 0x0000000B ] + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: + - Name: .gnu.hash + Type: SHT_GNU_HASH + Flags: [ SHF_ALLOC ] + Header: + SymNdx: 0x1 + Shift2: 0x2 + BloomFilter: [0x3, 0x4] + HashBuckets: [0x5, 0x6, 0x7] + HashValues: [0x8, 0x9, 0xA, 0xB] + +## Check how we handle broken cases. + +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=INVALID + +# INVALID: - Name: .gnu.hash.tooshort +# INVALID-NEXT: Type: SHT_GNU_HASH +# INVALID-NEXT: Flags: [ SHF_ALLOC ] +# INVALID-NEXT: Content: 112233445566778899AABBCCDDEEFF +# INVALID-NEXT: - Name: .gnu.hash.empty +# INVALID-NEXT: Type: SHT_GNU_HASH +# INVALID-NEXT: Flags: [ SHF_ALLOC ] +# INVALID-NEXT: Header: +# INVALID-NEXT: SymNdx: 0x00000000 +# INVALID-NEXT: Shift2: 0x00000000 +# INVALID-NEXT: BloomFilter: [ ] +# INVALID-NEXT: HashBuckets: [ ] +# INVALID-NEXT: HashValues: [ ] +# INVALID-NEXT: - Name: .gnu.hash.broken.maskwords +# INVALID-NEXT: Type: SHT_GNU_HASH +# INVALID-NEXT: Content: '00000000000000000100000000000000' +# INVALID-NEXT: - Name: .gnu.hash.broken.nbuckets +# INVALID-NEXT: Type: SHT_GNU_HASH +# INVALID-NEXT: Content: '01000000000000000000000000000000' +# INVALID-NEXT: - Name: .gnu.hash.hashvalues.ok +# INVALID-NEXT: Type: SHT_GNU_HASH +# INVALID-NEXT: Header: +# INVALID-NEXT: SymNdx: 0x00000000 +# INVALID-NEXT: Shift2: 0x00000000 +# INVALID-NEXT: BloomFilter: [ ] +# INVALID-NEXT: HashBuckets: [ ] +# INVALID-NEXT: HashValues: [ 0x00000000 ] +# INVALID-NEXT: - Name: .gnu.hash.hashvalues.fail +# INVALID-NEXT: Type: SHT_GNU_HASH +# INVALID-NEXT: Content: '000000000000000000000000000000000000000000' + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: +## Case 1: Content is less than 16 bytes. + - Name: .gnu.hash.tooshort + Type: SHT_GNU_HASH + Flags: [ SHF_ALLOC ] + Content: "112233445566778899AABBCCDDEEFF" +## Case2: Check how we handle a fully empty hash section. +## It is almost technically valid, but uncommon. Modern linkers +## create at least one entry in bloom filter if they want to disable it, +## also the dynamic symbol table has a null entry and having SymNdx = 0 +## here is at least strange. + - Name: .gnu.hash.empty + Type: SHT_GNU_HASH + Flags: [ SHF_ALLOC ] + Header: + SymNdx: 0x0 + Shift2: 0x0 + MaskWords: 0x0 + NBuckets: 0x0 + BloomFilter: [] + HashBuckets: [] + HashValues: [] +## Case 3: MaskWords field is broken, it says that the number of entries +## in the bloom filter is 1, but the bloom filter is empty. + - Name: .gnu.hash.broken.maskwords + Type: SHT_GNU_HASH + Header: + SymNdx: 0x0 + Shift2: 0x0 + MaskWords: 0x1 + NBuckets: 0x0 + BloomFilter: [] + HashBuckets: [] + HashValues: [] +## Case 3: NBuckets field is broken, it says that the number of entries +## in the hash buckets is 1, but it is empty. + - Name: .gnu.hash.broken.nbuckets + Type: SHT_GNU_HASH + Header: + SymNdx: 0x0 + Shift2: 0x0 + MaskWords: 0x0 + NBuckets: 0x1 + BloomFilter: [] + HashBuckets: [] + HashValues: [] +## Case 5: Check that when hash values data size contains a set of 4 byte words, +## we use the "HashValues" property to dump it, but fallback to dumping the whole +## section using the "Content" property otherwise. + - Name: .gnu.hash.hashvalues.ok + Type: SHT_GNU_HASH + Content: "0000000000000000000000000000000000000000" + - Name: .gnu.hash.hashvalues.fail + Type: SHT_GNU_HASH + Content: "000000000000000000000000000000000000000000" Index: llvm/test/tools/yaml2obj/elf-gnu-hash-section.yaml =================================================================== --- /dev/null +++ llvm/test/tools/yaml2obj/elf-gnu-hash-section.yaml @@ -0,0 +1,276 @@ +## Check how yaml2obj produces SHT_GNU_HASH sections. + +## Check we can describe a SHT_GNU_HASH section using the "Content" tag. +## Check we set sh_link to index of the .dynsym by default. + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: llvm-readobj --sections --section-data %t1 | FileCheck %s --check-prefix=CONTENT + +# CONTENT: Name: .gnu.hash +# CONTENT-NEXT: Type: SHT_GNU_HASH +# CONTENT-NEXT: Flags [ +# CONTENT-NEXT: ] +# CONTENT-NEXT: Address: 0x0 +# CONTENT-NEXT: Offset: 0x40 +# CONTENT-NEXT: Size: 3 +# CONTENT-NEXT: Link: 4 +# CONTENT-NEXT: Info: 0 +# CONTENT-NEXT: AddressAlignment: 0 +# CONTENT-NEXT: EntrySize: 0 +# CONTENT-NEXT: SectionData ( +# CONTENT-NEXT: 0000: 001122 | +# CONTENT-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.hash + Type: SHT_GNU_HASH + Content: "001122" +## Used to trigger .dynsym creation. +DynamicSymbols: + - Name: foo + Binding: STB_GLOBAL + +## Check we can use "Header", "BloomFilter", "HashBuckets" and "HashValues" keys to describe +## the hash section. Check we can set sh_link to any arbitrary value. Check both ELFCLASS32 and 64 bit output. + +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s --check-prefix=CONTENT32 +# RUN: llvm-readobj --sections --section-data %t3 | FileCheck %s --check-prefix=CONTENT64 + +# CONTENT32: Name: .gnu.hash +# CONTENT32-NEXT: Type: SHT_GNU_HASH +# CONTENT32-NEXT: Flags [ +# CONTENT32-NEXT: SHF_ALLOC +# CONTENT32-NEXT: ] +# CONTENT32-NEXT: Address: 0x0 +# CONTENT32-NEXT: Offset: 0x34 +# CONTENT32-NEXT: Size: 52 +# CONTENT32-NEXT: Link: 254 +# CONTENT32-NEXT: Info: 0 +# CONTENT32-NEXT: AddressAlignment: 0 +# CONTENT32-NEXT: EntrySize: 0 +# CONTENT32-NEXT: SectionData ( +# CONTENT32-NEXT: 0000: 03000000 01000000 02000000 02000000 | +# CONTENT32-NEXT: 0010: 03000000 04000000 05000000 06000000 | +# CONTENT32-NEXT: 0020: 07000000 08000000 09000000 0A000000 | +# CONTENT32-NEXT: 0030: 0B000000 | +# CONTENT32-NEXT: ) + +# CONTENT64: Name: .gnu.hash +# CONTENT64-NEXT: Type: SHT_GNU_HASH +# CONTENT64-NEXT: Flags [ +# CONTENT64-NEXT: SHF_ALLOC +# CONTENT64-NEXT: ] +# CONTENT64-NEXT: Address: 0x0 +# CONTENT64-NEXT: Offset: 0x40 +# CONTENT64-NEXT: Size: 60 +# CONTENT64-NEXT: Link: 254 +# CONTENT64-NEXT: Info: 0 +# CONTENT64-NEXT: AddressAlignment: 0 +# CONTENT64-NEXT: EntrySize: 0 +# CONTENT64-NEXT: SectionData ( +# CONTENT64-NEXT: 0000: 03000000 01000000 02000000 02000000 | +# CONTENT64-NEXT: 0010: 03000000 00000000 04000000 00000000 | +# CONTENT64-NEXT: 0020: 05000000 06000000 07000000 08000000 | +# CONTENT64-NEXT: 0030: 09000000 0A000000 0B000000 | +# CONTENT64-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: + - Name: .gnu.hash + Type: SHT_GNU_HASH + Flags: [ SHF_ALLOC ] + Header: + SymNdx: 0x1 + Shift2: 0x2 + BloomFilter: [0x3, 0x4] + HashBuckets: [0x5, 0x6, 0x7] + HashValues: [0x8, 0x9, 0xA, 0xB] + Link: 0xFE + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.hash + Type: SHT_GNU_HASH + Flags: [ SHF_ALLOC ] + Header: + SymNdx: 0x1 + Shift2: 0x2 + BloomFilter: [0x3, 0x4] + HashBuckets: [0x5, 0x6, 0x7] + HashValues: [0x8, 0x9, 0xA, 0xB] + Link: 0xFE + +## Check we only can use "Header", "BloomFilter", "HashBuckets" and "HashValues" together. + +# RUN: not yaml2obj --docnum=4 %s -o %t4 2>&1 | FileCheck %s --check-prefix=ERR +# RUN: not yaml2obj --docnum=5 %s -o %t5 2>&1 | FileCheck %s --check-prefix=ERR +# RUN: not yaml2obj --docnum=6 %s -o %t6 2>&1 | FileCheck %s --check-prefix=ERR +# RUN: not yaml2obj --docnum=7 %s -o %t7 2>&1 | FileCheck %s --check-prefix=ERR + +# ERR: error: "Header", "BloomFilter", "HashBuckets" and "HashValues" must be used together + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.hash.only.header + Type: SHT_GNU_HASH + Header: + SymNdx: 0x0 + Shift2: 0x0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.hash.only.bloomfilter + Type: SHT_GNU_HASH + BloomFilter: [] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.hash.only.hashbuckets + Type: SHT_GNU_HASH + HashBuckets: [] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.hash.only.hashvalues + Type: SHT_GNU_HASH + HashValues: [] + +## Check that "SymNdx" and "Shift2" fields are mandatory when we specify the "Header". + +# RUN: not yaml2obj --docnum=8 %s -o %t8 2>&1 | FileCheck %s --check-prefix=ERR2 +# ERR2: error: missing required key 'SymNdx' + +# RUN: not yaml2obj --docnum=9 %s -o %t9 2>&1 | FileCheck %s --check-prefix=ERR3 +# ERR3: error: missing required key 'Shift2' + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.hash + Type: SHT_GNU_HASH + Header: + Shift2: 0x0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.hash + Type: SHT_GNU_HASH + Header: + SymNdx: 0x0 + +## Either "Content" or "Header", "BloomFilter", "HashBuckets" and "HashBuckets" must be +## specified when declaring a SHT_GNU_HASH section. + +# RUN: not yaml2obj --docnum=10 %s -o %t10 2>&1 | FileCheck %s --check-prefix=NOKEYS + +# NOKEYS: error: either "Content" or "Header", "BloomFilter", "HashBuckets" and "HashBuckets" must be specified + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.hash + Type: SHT_GNU_HASH + +## Test that "Header", "BloomFilter", "HashBuckets" and "HashValues" can't be used together with "Content". + +# RUN: not yaml2obj --docnum=11 %s -o %t11 2>&1 | FileCheck %s --check-prefix=TOGETHER + +# TOGETHER: error: "Header", "BloomFilter", "HashBuckets" and "HashValues" can't be used together with "Content" + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: + - Name: .gnu.hash + Type: SHT_GNU_HASH + Content: "" + Header: + SymNdx: 0x0 + Shift2: 0x0 + BloomFilter: [] + HashBuckets: [] + HashValues: [] + +## Test we can override the number of buckets and the number of words in the bloom filter +## using the "NBuckets" and "Shift2" keys. + +# RUN: yaml2obj --docnum=12 %s -o %t12 +# RUN: llvm-readobj --sections --section-data %t12 | FileCheck %s --check-prefix=OVERRIDE-CONTENT + +# OVERRIDE-CONTENT: Name: .gnu.hash +# OVERRIDE-CONTENT: SectionData ( +# OVERRIDE-CONTENT-NEXT: 0000: 01000000 02000000 03000000 04000000 | +# OVERRIDE-CONTENT-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: +Sections: + - Name: .gnu.hash + Type: SHT_GNU_HASH + Header: + NBuckets: 0x1 + SymNdx: 0x2 + MaskWords: 0x3 + Shift2: 0x4 + BloomFilter: [] + HashBuckets: [] + HashValues: [] Index: llvm/tools/obj2yaml/elf2yaml.cpp =================================================================== --- llvm/tools/obj2yaml/elf2yaml.cpp +++ llvm/tools/obj2yaml/elf2yaml.cpp @@ -66,6 +66,7 @@ dumpSymtabShndxSection(const Elf_Shdr *Shdr); Expected dumpNoBitsSection(const Elf_Shdr *Shdr); Expected dumpHashSection(const Elf_Shdr *Shdr); + Expected dumpGnuHashSection(const Elf_Shdr *Shdr); Expected dumpVerdefSection(const Elf_Shdr *Shdr); Expected dumpSymverSection(const Elf_Shdr *Shdr); Expected dumpVerneedSection(const Elf_Shdr *Shdr); @@ -269,6 +270,13 @@ Y->Sections.emplace_back(*SecOrErr); break; } + case ELF::SHT_GNU_HASH: { + Expected SecOrErr = dumpGnuHashSection(&Sec); + if (!SecOrErr) + return SecOrErr.takeError(); + Y->Sections.emplace_back(*SecOrErr); + break; + } case ELF::SHT_GNU_verdef: { Expected SecOrErr = dumpVerdefSection(&Sec); if (!SecOrErr) @@ -718,6 +726,57 @@ llvm_unreachable("entries were not read correctly"); } +template +Expected +ELFDumper::dumpGnuHashSection(const Elf_Shdr *Shdr) { + auto S = std::make_unique(); + if (Error E = dumpCommonSection(Shdr, *S)) + return std::move(E); + + auto ContentOrErr = Obj.getSectionContents(Shdr); + if (!ContentOrErr) + return ContentOrErr.takeError(); + + unsigned AddrSize = ELFT::Is64Bits ? 8 : 4; + ArrayRef Content = *ContentOrErr; + DataExtractor Data(Content, Obj.isLE(), AddrSize); + + ELFYAML::GnuHashHeader Header; + DataExtractor::Cursor Cur(0); + uint32_t NBuckets = Data.getU32(Cur); + Header.SymNdx = Data.getU32(Cur); + uint32_t MaskWords = Data.getU32(Cur); + Header.Shift2 = Data.getU32(Cur); + + // Set just the raw binary content if we were unable to read the header + // or when the section data is truncated or malformed. + uint64_t Size = Data.getData().size() - Cur.tell(); + if (!Cur || (Size < MaskWords * AddrSize + NBuckets * 4) || + (Size % 4 != 0)) { + consumeError(Cur.takeError()); + S->Content = yaml::BinaryRef(Content); + return S.release(); + } + + S->Header = Header; + + S->BloomFilter.emplace(MaskWords); + for (llvm::yaml::Hex64 &Val : *S->BloomFilter) + Val = Data.getAddress(Cur); + + S->HashBuckets.emplace(NBuckets); + for (llvm::yaml::Hex32 &Val : *S->HashBuckets) + Val = Data.getU32(Cur); + + S->HashValues.emplace((Data.getData().size() - Cur.tell()) / 4); + for (llvm::yaml::Hex32 &Val : *S->HashValues) + Val = Data.getU32(Cur); + + if (Cur) + return S.release(); + llvm_unreachable("GnuHashSection was not read correctly"); +} + template Expected ELFDumper::dumpVerdefSection(const Elf_Shdr *Shdr) { Index: llvm/unittests/Support/YAMLIOTest.cpp =================================================================== --- llvm/unittests/Support/YAMLIOTest.cpp +++ llvm/unittests/Support/YAMLIOTest.cpp @@ -2189,7 +2189,6 @@ // // Test error handling reading built-in Hex8 type // -LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8) TEST(YAMLIO, TestReadBuiltInTypesHex8Error) { std::vector seq; Input yin("---\n" @@ -2226,7 +2225,6 @@ // // Test error handling reading built-in Hex32 type // -LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32) TEST(YAMLIO, TestReadBuiltInTypesHex32Error) { std::vector seq; Input yin("---\n" @@ -2244,7 +2242,6 @@ // // Test error handling reading built-in Hex64 type // -LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64) TEST(YAMLIO, TestReadBuiltInTypesHex64Error) { std::vector seq; Input yin("---\n"