Index: include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- include/llvm/ObjectYAML/ELFYAML.h +++ include/llvm/ObjectYAML/ELFYAML.h @@ -122,6 +122,7 @@ Relocation, NoBits, Verneed, + Symver, MipsABIFlags }; SectionKind Kind; @@ -192,6 +193,16 @@ } }; +struct SymverSection : Section { + std::vector Entries; + + SymverSection() : Section(SectionKind::Symver) {} + + static bool classof(const Section *S) { + return S->Kind == SectionKind::Symver; + } +}; + struct Group : Section { // Members of a group contain a flag and a list of section indices // that are part of the group. Index: lib/ObjectYAML/ELFYAML.cpp =================================================================== --- lib/ObjectYAML/ELFYAML.cpp +++ lib/ObjectYAML/ELFYAML.cpp @@ -872,6 +872,11 @@ IO.mapOptional("Size", Section.Size, Hex64(0)); } +static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) { + commonSectionMapping(IO, Section); + IO.mapRequired("Entries", Section.Entries); +} + static void sectionMapping(IO &IO, ELFYAML::VerneedSection &Section) { commonSectionMapping(IO, Section); IO.mapRequired("Info", Section.Info); @@ -955,6 +960,11 @@ Section.reset(new ELFYAML::MipsABIFlags()); sectionMapping(IO, *cast(Section.get())); break; + case ELF::SHT_GNU_versym: + if (!IO.outputting()) + Section.reset(new ELFYAML::SymverSection()); + sectionMapping(IO, *cast(Section.get())); + break; case ELF::SHT_GNU_verneed: if (!IO.outputting()) Section.reset(new ELFYAML::VerneedSection()); Index: test/tools/obj2yaml/versym-section.yaml =================================================================== --- /dev/null +++ test/tools/obj2yaml/versym-section.yaml @@ -0,0 +1,48 @@ +# RUN: yaml2obj %s -o %t +# RUN: obj2yaml %t | FileCheck %s + +## Check we are able to yamalize the SHT_GNU_versym section. + +# CHECK: --- !ELF +# CHECK-NEXT: FileHeader: +# CHECK-NEXT: Class: ELFCLASS64 +# CHECK-NEXT: Data: ELFDATA2LSB +# CHECK-NEXT: Type: ET_EXEC +# CHECK-NEXT: Machine: EM_X86_64 +# CHECK-NEXT: Entry: 0x0000000000201000 +# CHECK-NEXT: Sections: +# CHECK-NEXT: - Name: .gnu.version +# CHECK-NEXT: Type: SHT_GNU_versym +# CHECK-NEXT: Flags: [ SHF_ALLOC ] +# CHECK-NEXT: Address: 0x0000000000200210 +# CHECK-NEXT: Link: .dynsym +# CHECK-NEXT: AddressAlign: 0x0000000000000002 +# CHECK-NEXT: EntSize: 0x0000000000000002 +# CHECK-NEXT: Entries: [ 0, 3, 4 ] +# CHECK-NEXT: Symbols: {} +# CHECK-NEXT: DynamicSymbols: +# CHECK-NEXT: Global: +# CHECK-NEXT: - Name: f1 +# CHECK-NEXT: - Name: f2 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x0000000000201000 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Flags: [ SHF_ALLOC ] + Address: 0x0000000000200210 + Link: .dynsym + AddressAlign: 0x0000000000000002 + EntSize: 0x0000000000000002 + Entries: [ 0, 3, 4 ] +DynamicSymbols: + Global: + - Name: f1 + - Name: f2 +... Index: test/tools/yaml2obj/versym-section.yaml =================================================================== --- /dev/null +++ test/tools/yaml2obj/versym-section.yaml @@ -0,0 +1,88 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readelf -V %t | FileCheck %s + +## Check we are able to produce a valid SHT_GNU_versym +## section from its description. + +# CHECK: Version symbols { +# CHECK-NEXT: Section Name: .gnu.version +# CHECK-NEXT: Address: 0x200210 +# CHECK-NEXT: Offset: 0x240 +# CHECK-NEXT: Link: 6 +# CHECK-NEXT: Symbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Version: 0 +# CHECK-NEXT: Name: +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Version: 3 +# CHECK-NEXT: Name: f1@v1 +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Version: 4 +# CHECK-NEXT: Name: f2@v2 +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: SHT_GNU_verdef { +# CHECK-NEXT: } +# CHECK-NEXT: SHT_GNU_verneed { +# CHECK-NEXT: Dependency { +# CHECK-NEXT: Version: 1 +# CHECK-NEXT: Count: 2 +# CHECK-NEXT: FileName: dso.so.0 +# CHECK-NEXT: Entry { +# CHECK-NEXT: Hash: 1937 +# CHECK-NEXT: Flags: 0x0 +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: Name: v1 +# CHECK-NEXT: } +# CHECK-NEXT: Entry { +# CHECK-NEXT: Hash: 1938 +# CHECK-NEXT: Flags: 0x0 +# CHECK-NEXT: Index: 4 +# CHECK-NEXT: Name: v2 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: } + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x0000000000201000 +Sections: + - Name: .gnu.version + Type: SHT_GNU_versym + Flags: [ SHF_ALLOC ] + Address: 0x0000000000200210 + Link: .dynsym + AddressAlign: 0x0000000000000002 + EntSize: 0x0000000000000002 + Entries: [ 0, 3, 4 ] + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Flags: [ SHF_ALLOC ] + Address: 0x0000000000200250 + Link: .dynstr + AddressAlign: 0x0000000000000004 + Info: 0x0000000000000001 + Dependencies: + - Version: 1 + File: dso.so.0 + Entries: + - Name: v1 + Hash: 1937 + Flags: 0 + Other: 3 + - Name: v2 + Hash: 1938 + Flags: 0 + Other: 4 +DynamicSymbols: + Global: + - Name: f1 + - Name: f2 +... Index: tools/obj2yaml/elf2yaml.cpp =================================================================== --- tools/obj2yaml/elf2yaml.cpp +++ tools/obj2yaml/elf2yaml.cpp @@ -57,6 +57,7 @@ ErrorOr dumpContentSection(const Elf_Shdr *Shdr); ErrorOr dumpNoBitsSection(const Elf_Shdr *Shdr); + ErrorOr dumpSymverSection(const Elf_Shdr *Shdr); ErrorOr dumpVerneedSection(const Elf_Shdr *Shdr); ErrorOr dumpGroup(const Elf_Shdr *Shdr); ErrorOr dumpMipsABIFlags(const Elf_Shdr *Shdr); @@ -185,6 +186,13 @@ Y->Sections.push_back(std::unique_ptr(S.get())); break; } + case ELF::SHT_GNU_versym: { + ErrorOr S = dumpSymverSection(&Sec); + if (std::error_code EC = S.getError()) + return EC; + Y->Sections.push_back(std::unique_ptr(S.get())); + break; + } case ELF::SHT_GNU_verneed: { ErrorOr S = dumpVerneedSection(&Sec); if (std::error_code EC = S.getError()) @@ -451,6 +459,24 @@ return S.release(); } +template +ErrorOr +ELFDumper::dumpSymverSection(const Elf_Shdr *Shdr) { + typedef typename ELFT::Half Elf_Half; + + auto S = make_unique(); + if (std::error_code EC = dumpCommonSection(Shdr, *S)) + return EC; + + auto VersionsOrErr = Obj.template getSectionContentsAsArray(Shdr); + if (!VersionsOrErr) + return errorToErrorCode(VersionsOrErr.takeError()); + for (const Elf_Half &E : *VersionsOrErr) + S->Entries.push_back(E); + + return S.release(); +} + template ErrorOr ELFDumper::dumpVerneedSection(const Elf_Shdr *Shdr) { Index: tools/yaml2obj/yaml2elf.cpp =================================================================== --- tools/yaml2obj/yaml2elf.cpp +++ tools/yaml2obj/yaml2elf.cpp @@ -156,6 +156,9 @@ ContiguousBlobAccumulator &CBA); bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::Group &Group, ContiguousBlobAccumulator &CBA); + bool writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::SymverSection &Section, + ContiguousBlobAccumulator &CBA); bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::VerneedSection &Section, ContiguousBlobAccumulator &CBA); @@ -303,6 +306,8 @@ CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); } else if (auto S = dyn_cast(Sec.get())) { writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast(Sec.get())) { + writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast(Sec.get())) { writeSectionContent(SHeader, *S, CBA); } else @@ -549,6 +554,23 @@ return true; } +template +bool ELFState::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::SymverSection &Section, + ContiguousBlobAccumulator &CBA) { + typedef typename ELFT::Half Elf_Half; + + auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + for (uint16_t V : Section.Entries) { + Elf_Half Version = (Elf_Half)V; + OS.write((const char *)&Version, sizeof(Elf_Half)); + } + + SHeader.sh_size = Section.Entries.size() * sizeof(Elf_Half); + SHeader.sh_entsize = sizeof(Elf_Half); + return true; +} + template bool ELFState::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::VerneedSection &Section,