Index: llvm/include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- llvm/include/llvm/ObjectYAML/ELFYAML.h +++ llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -279,6 +279,11 @@ Optional> Bucket; Optional> Chain; + // The following members are used to override section fields which is + // useful for creating invalid objects. + Optional NBucket; + Optional NChain; + HashSection() : Section(ChunkKind::Hash) {} static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Hash; } Index: llvm/lib/ObjectYAML/ELFEmitter.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFEmitter.cpp +++ llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -1065,10 +1065,13 @@ return; } - support::endian::write(OS, Section.Bucket->size(), - ELFT::TargetEndianness); - support::endian::write(OS, Section.Chain->size(), - ELFT::TargetEndianness); + support::endian::write( + OS, Section.NBucket.getValueOr(Section.Bucket->size()), + ELFT::TargetEndianness); + support::endian::write( + OS, Section.NChain.getValueOr(Section.Chain->size()), + ELFT::TargetEndianness); + for (uint32_t Val : *Section.Bucket) support::endian::write(OS, Val, ELFT::TargetEndianness); for (uint32_t Val : *Section.Chain) Index: llvm/lib/ObjectYAML/ELFYAML.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFYAML.cpp +++ llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1088,6 +1088,13 @@ IO.mapOptional("Bucket", Section.Bucket); IO.mapOptional("Chain", Section.Chain); IO.mapOptional("Size", Section.Size); + + // obj2yaml does not dump these fields. They can be used to override nchain + // and nbucket values for creating broken sections. + assert(!IO.outputting() || + (!Section.NBucket.hasValue() && !Section.NChain.hasValue())); + IO.mapOptional("NChain", Section.NChain); + IO.mapOptional("NBucket", Section.NBucket); } static void sectionMapping(IO &IO, ELFYAML::NoteSection &Section) { Index: llvm/test/tools/yaml2obj/ELF/hash-section.yaml =================================================================== --- llvm/test/tools/yaml2obj/ELF/hash-section.yaml +++ llvm/test/tools/yaml2obj/ELF/hash-section.yaml @@ -276,3 +276,39 @@ Type: SHT_HASH Size: 0x1 Chain: [ 1 ] + +## Check we can override "nbucket" and "nchain" values of a SHT_HASH section using "NBucket" and "NChain" tags. +## Check that the section size is unaffected when we do this. + +# RUN: yaml2obj --docnum=14 %s -o %t14 +# RUN: llvm-readobj --sections --section-data %t14 | FileCheck %s --check-prefix=OVERRIDE + +# OVERRIDE: Name: .hash +# OVERRIDE-NEXT: Type: SHT_HASH +# OVERRIDE-NEXT: Flags [ +# OVERRIDE-NEXT: ] +# OVERRIDE-NEXT: Address: 0x0 +# OVERRIDE-NEXT: Offset: 0x34 +# OVERRIDE-NEXT: Size: 28 +# OVERRIDE-NEXT: Link: 0 +# OVERRIDE-NEXT: Info: 0 +# OVERRIDE-NEXT: AddressAlignment: 0 +# OVERRIDE-NEXT: EntrySize: 0 +# OVERRIDE-NEXT: SectionData ( +# OVERRIDE-NEXT: 0000: AA000000 BB000000 01000000 02000000 +# OVERRIDE-NEXT: 0010: 03000000 04000000 05000000 +# OVERRIDE-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 +Sections: + - Name: .hash + Type: SHT_HASH + Bucket: [ 1, 2 ] + Chain: [ 3, 4, 5 ] + NBucket: 0xAA + NChain: 0xBB