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 @@ -522,10 +522,10 @@ }; struct VerdefEntry { - uint16_t Version; - uint16_t Flags; - uint16_t VersionNdx; - uint32_t Hash; + Optional Version; + Optional Flags; + Optional VersionNdx; + Optional Hash; std::vector VerNames; }; 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 @@ -1456,10 +1456,10 @@ const ELFYAML::VerdefEntry &E = (*Section.Entries)[I]; Elf_Verdef VerDef; - VerDef.vd_version = E.Version; - VerDef.vd_flags = E.Flags; - VerDef.vd_ndx = E.VersionNdx; - VerDef.vd_hash = E.Hash; + VerDef.vd_version = E.Version.getValueOr(1); + VerDef.vd_flags = E.Flags.getValueOr(0); + VerDef.vd_ndx = E.VersionNdx.getValueOr(0); + VerDef.vd_hash = E.Hash.getValueOr(0); VerDef.vd_aux = sizeof(Elf_Verdef); VerDef.vd_cnt = E.VerNames.size(); if (I == Section.Entries->size() - 1) 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 @@ -1584,10 +1584,10 @@ ELFYAML::VerdefEntry &E) { assert(IO.getContext() && "The IO context is not initialized"); - IO.mapRequired("Version", E.Version); - IO.mapRequired("Flags", E.Flags); - IO.mapRequired("VersionNdx", E.VersionNdx); - IO.mapRequired("Hash", E.Hash); + IO.mapOptional("Version", E.Version); + IO.mapOptional("Flags", E.Flags); + IO.mapOptional("VersionNdx", E.VersionNdx); + IO.mapOptional("Hash", E.Hash); IO.mapRequired("Names", E.VerNames); } diff --git a/llvm/test/tools/obj2yaml/ELF/verdef-section.yaml b/llvm/test/tools/obj2yaml/ELF/verdef-section.yaml --- a/llvm/test/tools/obj2yaml/ELF/verdef-section.yaml +++ b/llvm/test/tools/obj2yaml/ELF/verdef-section.yaml @@ -1,42 +1,37 @@ +## Check how we dump SHT_GNU_verdef sections. + # RUN: yaml2obj %s -o %t # RUN: obj2yaml %t | FileCheck %s -## Check we are able to yamalize SHT_GNU_verdef section. - -# CHECK: - Name: .gnu.version_d -# CHECK-NEXT: Type: SHT_GNU_verdef -# CHECK-NEXT: Flags: [ SHF_ALLOC ] -# CHECK-NEXT: Address: 0x230 -# CHECK-NEXT: Link: .dynstr -# CHECK-NEXT: AddressAlign: 0x4 -# CHECK-NEXT: Info: 0x4 -# CHECK-NEXT: Entries: -# CHECK-NEXT: - Version: 1 -# CHECK-NEXT: Flags: 1 -# CHECK-NEXT: VersionNdx: 1 -# CHECK-NEXT: Hash: 170240160 -# CHECK-NEXT: Names: -# CHECK-NEXT: - dso.so.0 -# CHECK-NEXT: - Version: 1 -# CHECK-NEXT: Flags: 2 -# CHECK-NEXT: VersionNdx: 2 -# CHECK-NEXT: Hash: 108387921 -# CHECK-NEXT: Names: -# CHECK-NEXT: - VERSION_1 -# CHECK-NEXT: - Version: 1 -# CHECK-NEXT: Flags: 3 -# CHECK-NEXT: VersionNdx: 3 -# CHECK-NEXT: Hash: 108387922 -# CHECK-NEXT: Names: -# CHECK-NEXT: - VERSION_2 -# CHECK-NEXT: - VERSION_3 +# CHECK: - Name: .gnu.version_d +# CHECK-NEXT: Type: SHT_GNU_verdef +# CHECK-NEXT: Flags: [ SHF_ALLOC ] +# CHECK-NEXT: Address: 0x230 +# CHECK-NEXT: Link: .dynstr +# CHECK-NEXT: AddressAlign: 0x4 +# CHECK-NEXT: Info: 0x4 +# CHECK-NEXT: Entries: +# CHECK-NEXT: - Names: +# CHECK-NEXT: - VERSION_0 +# CHECK-NEXT: - Flags: 2 +# CHECK-NEXT: VersionNdx: 2 +# CHECK-NEXT: Hash: 108387921 +# CHECK-NEXT: Names: +# CHECK-NEXT: - VERSION_1 +# CHECK-NEXT: - Flags: 3 +# CHECK-NEXT: VersionNdx: 3 +# CHECK-NEXT: Hash: 108387922 +# CHECK-NEXT: Names: +# CHECK-NEXT: - VERSION_2 +# CHECK-NEXT: - VERSION_3 +# CHECK-NEXT: - VERSION_4 +# CHECK-NEXT: - Name: --- !ELF FileHeader: Class: ELFCLASS64 Data: ELFDATA2LSB Type: ET_DYN - Entry: 0x1000 Sections: - Name: .gnu.version_d Type: SHT_GNU_verdef @@ -46,26 +41,36 @@ AddressAlign: 0x4 Info: 0x4 Entries: - - Version: 1 - Flags: 1 - VersionNdx: 1 - Hash: 170240160 +## An entry that has all fields explicitly set to their default values. +## Used to check that we don't dump them. + - Version: [[VERSION=1]] + Flags: 0 + VersionNdx: 0 + Hash: 0 Names: - - dso.so.0 - - Version: 1 - Flags: 2 - VersionNdx: 2 - Hash: 108387921 + - VERSION_0 +## An entry with arbitrary values. + - Flags: 2 + VersionNdx: 2 + Hash: 108387921 Names: - VERSION_1 - - Version: 1 - Flags: 3 - VersionNdx: 3 - Hash: 108387922 +## Another entry with arbitrary values and version predecessors. + - Flags: 3 + VersionNdx: 3 + Hash: 108387922 Names: - VERSION_2 - VERSION_3 -DynamicSymbols: - - Name: foo - Binding: STB_GLOBAL -... + - VERSION_4 +## Needed to emit the .dynstr section. +DynamicSymbols: [] + +## Document that we are not able to dump a version definition which +## has a version revision (vd_version) that is not equal to 1. + +# RUN: yaml2obj %s -DVERSION=2 -o %t.version +# RUN: not obj2yaml %t.version 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.version --check-prefix=VERSION-ERR + +# VERSION-ERR: Error reading file: [[FILE]]: invalid SHT_GNU_verdef section version: 2 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,4 +1,4 @@ -## Check we are able to handle SHT_GNU_verdef sections. +## Test how we create SHT_GNU_verdef sections. # RUN: yaml2obj --docnum=1 %s -o %t1 # RUN: llvm-readobj -V %t1 | FileCheck %s @@ -6,6 +6,15 @@ # CHECK: VersionDefinitions [ # CHECK-NEXT: Definition { # CHECK-NEXT: Version: 1 +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: Hash: 0 +# CHECK-NEXT: Name: +# CHECK-NEXT: Predecessors: [] +# CHECK-NEXT: } +# CHECK-NEXT: Definition { +# CHECK-NEXT: Version: 1 # CHECK-NEXT: Flags [ (0x1) # CHECK-NEXT: Base (0x1) # CHECK-NEXT: ] @@ -26,14 +35,15 @@ # CHECK-NEXT: } # CHECK-NEXT: Definition { # CHECK-NEXT: Version: 1 -# CHECK-NEXT: Flags [ (0x3) +# CHECK-NEXT: Flags [ (0xFFFF) # CHECK-NEXT: Base (0x1) +# CHECK-NEXT: Info (0x4) # CHECK-NEXT: Weak (0x2) # CHECK-NEXT: ] # CHECK-NEXT: Index: 3 # CHECK-NEXT: Hash: 108387922 # CHECK-NEXT: Name: VERSION_2 -# CHECK-NEXT: Predecessors: [VERSION_3] +# CHECK-NEXT: Predecessors: [VERSION_3, VERSION_4] # CHECK-NEXT: } # CHECK-NEXT: ] @@ -42,39 +52,54 @@ Class: ELFCLASS64 Data: ELFDATA2LSB Type: ET_DYN - Entry: 0x0000000000001000 Sections: - - Name: .gnu.version_d - Type: SHT_GNU_verdef - Flags: [ SHF_ALLOC ] - Address: 0x0000000000000230 - Link: .dynstr - AddressAlign: 0x0000000000000004 - Info: 0x0000000000000003 + - Name: .gnu.version_d + Type: SHT_GNU_verdef + Flags: [ SHF_ALLOC ] + Link: .dynstr + Info: 0x4 Entries: - - Version: 1 - Flags: 1 - VersionNdx: 1 - Hash: 170240160 +## Case 1: an entry that has no Version, Flags, VersionNdx or Hash fields set. +## Used to check values that are written by default. Also shows +## that we are able to use the "=" syntax for these fields. + - Version: [[VERSION=]] + Flags: [[FLAGS=]] + VersionNdx: [[VERNDX=]] + Hash: [[HASH=]] + Names: [] +## Case 2: an arbitrary entry. + - Flags: 1 + VersionNdx: 1 + Hash: 170240160 Names: - dso.so.0 - - Version: 1 - Flags: 2 - VersionNdx: 2 - Hash: 108387921 +## Case 3: one more arbitrary entry with different values. + - Flags: 2 + VersionNdx: 2 + Hash: 108387921 Names: - VERSION_1 - - Version: 1 - Flags: 3 - VersionNdx: 3 - Hash: 108387922 +## Case 4: an entry that has version predecessors. Also, it sets +## all known flags as well as few unknown. + - Flags: 0xffff + VersionNdx: 3 + Hash: 108387922 Names: - VERSION_2 - VERSION_3 + - VERSION_4 DynamicSymbols: - Name: foo Binding: STB_GLOBAL +## Check we are able to emit a version definition which has a version revision +## (vd_version) field value that is not equal to 1. + +# RUN: yaml2obj --docnum=1 -DVERSION=2 %s -o %t.version +# RUN: llvm-readobj -V %t.version 2>&1 | FileCheck %s --check-prefix=VERSION-ERR + +# VERSION-ERR: unable to dump SHT_GNU_verdef section with index 1: version 2 is not yet supported + ## Check we can use "Content" to describe the content. # RUN: yaml2obj --docnum=2 %s -o %t2 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 @@ -1315,10 +1315,19 @@ while (Buf) { const Elf_Verdef *Verdef = reinterpret_cast(Buf); ELFYAML::VerdefEntry Entry; - Entry.Version = Verdef->vd_version; - Entry.Flags = Verdef->vd_flags; - Entry.VersionNdx = Verdef->vd_ndx; - Entry.Hash = Verdef->vd_hash; + if (Verdef->vd_version != 1) + return createStringError(errc::invalid_argument, + "invalid SHT_GNU_verdef section version: " + + Twine(Verdef->vd_version)); + + if (Verdef->vd_flags != 0) + Entry.Flags = Verdef->vd_flags; + + if (Verdef->vd_ndx != 0) + Entry.VersionNdx = Verdef->vd_ndx; + + if (Verdef->vd_hash != 0) + Entry.Hash = Verdef->vd_hash; const uint8_t *BufAux = Buf + Verdef->vd_aux; while (BufAux) {