diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -397,7 +397,9 @@ }; struct VerdefSection : Section { - std::vector Entries; + Optional> Entries; + Optional Content; + llvm::yaml::Hex64 Info; VerdefSection() : Section(ChunkKind::Verdef) {} diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -985,9 +985,19 @@ raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + SHeader.sh_info = Section.Info; + + if (Section.Content) { + SHeader.sh_size = writeContent(OS, Section.Content, None); + return; + } + + if (!Section.Entries) + return; + uint64_t AuxCnt = 0; - for (size_t I = 0; I < Section.Entries.size(); ++I) { - const ELFYAML::VerdefEntry &E = Section.Entries[I]; + for (size_t I = 0; I < Section.Entries->size(); ++I) { + const ELFYAML::VerdefEntry &E = (*Section.Entries)[I]; Elf_Verdef VerDef; VerDef.vd_version = E.Version; @@ -996,7 +1006,7 @@ VerDef.vd_hash = E.Hash; VerDef.vd_aux = sizeof(Elf_Verdef); VerDef.vd_cnt = E.VerNames.size(); - if (I == Section.Entries.size() - 1) + if (I == Section.Entries->size() - 1) VerDef.vd_next = 0; else VerDef.vd_next = @@ -1014,9 +1024,8 @@ } } - SHeader.sh_size = Section.Entries.size() * sizeof(Elf_Verdef) + + SHeader.sh_size = Section.Entries->size() * sizeof(Elf_Verdef) + AuxCnt * sizeof(Elf_Verdaux); - SHeader.sh_info = Section.Info; } template @@ -1341,9 +1350,10 @@ DotDynstr.add(Aux.Name); } } else if (auto VerDef = dyn_cast(Sec)) { - for (const ELFYAML::VerdefEntry &E : VerDef->Entries) - for (StringRef Name : E.VerNames) - DotDynstr.add(Name); + if (VerDef->Entries) + for (const ELFYAML::VerdefEntry &E : *VerDef->Entries) + for (StringRef Name : E.VerNames) + DotDynstr.add(Name); } } diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1074,7 +1074,8 @@ static void sectionMapping(IO &IO, ELFYAML::VerdefSection &Section) { commonSectionMapping(IO, Section); IO.mapRequired("Info", Section.Info); - IO.mapRequired("Entries", Section.Entries); + IO.mapOptional("Entries", Section.Entries); + IO.mapOptional("Content", Section.Content); } static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) { @@ -1419,6 +1420,13 @@ return {}; } + if (const auto *VD = dyn_cast(C.get())) { + if (VD->Entries && VD->Content) + return "SHT_GNU_verdef: \"Entries\" and \"Content\" can't be used " + "together"; + return {}; + } + return {}; } diff --git a/llvm/test/tools/yaml2obj/ELF/verdef-section.yaml b/llvm/test/tools/yaml2obj/ELF/verdef-section.yaml --- a/llvm/test/tools/yaml2obj/ELF/verdef-section.yaml +++ b/llvm/test/tools/yaml2obj/ELF/verdef-section.yaml @@ -1,6 +1,6 @@ ## Check we are able to handle SHT_GNU_verdef sections. -# RUN: yaml2obj %s -o %t +# RUN: yaml2obj --docnum=1 %s -o %t1 # RUN: llvm-readobj -V %t | FileCheck %s # CHECK: VersionDefinitions [ @@ -73,4 +73,83 @@ DynamicSymbols: - Name: foo Binding: STB_GLOBAL -... + +## Check we can use "Content" to describe the content. + +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s --check-prefix=CONTENT + +# CONTENT: Name: .gnu.version_d +# CONTENT-NEXT: Type: SHT_GNU_verdef +# CONTENT-NEXT: Flags [ (0x2) +# CONTENT-NEXT: SHF_ALLOC (0x2) +# CONTENT-NEXT: ] +# CONTENT-NEXT: Address: 0x0 +# CONTENT-NEXT: Offset: 0x40 +# CONTENT-NEXT: Size: 3 +# CONTENT-NEXT: Link: 0 +# CONTENT-NEXT: Info: 1 +# CONTENT-NEXT: AddressAlignment: +# CONTENT-NEXT: EntrySize: +# CONTENT-NEXT: SectionData ( +# CONTENT-NEXT: 0000: 112233 +# CONTENT-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.version_d + Type: SHT_GNU_verdef + Flags: [ SHF_ALLOC ] + Info: 0x0000000000000001 + Content: "112233" + +## Check we can omit "Content" and "Entries" fields to produce an empty SHT_GNU_verdef section. + +# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: llvm-readelf --sections %t3 | FileCheck %s --check-prefix=NO-PROPS + +# NO-PROPS: [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# NO-PROPS: [ 1] .gnu.version_d VERDEF 0000000000000000 000040 000000 00 A 0 1 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.version_d + Type: SHT_GNU_verdef + Flags: [ SHF_ALLOC ] + Info: 0x0000000000000001 + +## Check we can't use both "Entries" and "Content" together. + +# RUN: not yaml2obj --docnum=4 %s -o %t4 2>&1 | FileCheck %s --check-prefix=BOTH + +# BOTH: error: SHT_GNU_verdef: "Entries" and "Content" can't be used together + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .gnu.version_d + Type: SHT_GNU_verdef + Flags: [ SHF_ALLOC ] + Info: 0x0000000000000001 + Content: "112233" + Entries: + - Version: 0 + Flags: 0 + VersionNdx: 0 + Hash: 0 + Names: + - foo diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/llvm/tools/obj2yaml/elf2yaml.cpp @@ -923,6 +923,8 @@ if (!Contents) return Contents.takeError(); + S->Entries.emplace(); + llvm::ArrayRef Data = *Contents; const uint8_t *Buf = Data.data(); while (Buf) { @@ -942,7 +944,7 @@ BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr; } - S->Entries.push_back(Entry); + S->Entries->push_back(Entry); Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr; }