Index: include/llvm/Object/ELFYAML.h =================================================================== --- include/llvm/Object/ELFYAML.h +++ include/llvm/Object/ELFYAML.h @@ -72,14 +72,20 @@ std::vector Global; std::vector Weak; }; + +struct SectionOrType { + StringRef sectionNameOrType; +}; + struct Section { - enum class SectionKind { RawContent, Relocation }; + enum class SectionKind { Group, RawContent, Relocation }; SectionKind Kind; StringRef Name; ELF_SHT Type; ELF_SHF Flags; llvm::yaml::Hex64 Address; StringRef Link; + StringRef Info; llvm::yaml::Hex64 AddressAlign; Section(SectionKind Kind) : Kind(Kind) {} virtual ~Section(); @@ -92,6 +98,17 @@ return S->Kind == SectionKind::RawContent; } }; + +struct Group : Section { + // Members of a group contain a flag and a list of section indices + // that are part of the group. + std::vector Members; + Group() : Section(SectionKind::Group) {} + static bool classof(const Section *S) { + return S->Kind == SectionKind::Group; + } +}; + struct Relocation { llvm::yaml::Hex64 Offset; int64_t Addend; @@ -99,7 +116,6 @@ StringRef Symbol; }; struct RelocationSection : Section { - StringRef Info; std::vector Relocations; RelocationSection() : Section(SectionKind::Relocation) {} static bool classof(const Section *S) { @@ -122,6 +138,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType) namespace llvm { namespace yaml { @@ -221,6 +238,10 @@ static void mapping(IO &IO, ELFYAML::Object &Object); }; +template <> struct MappingTraits { + static void mapping(IO &IO, ELFYAML::SectionOrType §ionOrType); +}; + } // end namespace yaml } // end namespace llvm Index: lib/Object/ELFYAML.cpp =================================================================== --- lib/Object/ELFYAML.cpp +++ lib/Object/ELFYAML.cpp @@ -506,6 +506,7 @@ IO.mapOptional("Address", Section.Address, Hex64(0)); IO.mapOptional("Link", Section.Link, StringRef()); IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0)); + IO.mapOptional("Info", Section.Info, StringRef()); } static void sectionMapping(IO &IO, ELFYAML::RawContentSection &Section) { @@ -516,10 +517,19 @@ static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) { commonSectionMapping(IO, Section); - IO.mapOptional("Info", Section.Info, StringRef()); IO.mapOptional("Relocations", Section.Relocations); } +static void groupSectionMapping(IO &IO, ELFYAML::Group &group) { + commonSectionMapping(IO, group); + IO.mapRequired("Members", group.Members); +} + +void MappingTraits::mapping( + IO &IO, ELFYAML::SectionOrType §ionOrType) { + IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType); +} + void MappingTraits>::mapping( IO &IO, std::unique_ptr &Section) { ELFYAML::ELF_SHT sectionType; @@ -535,6 +545,11 @@ Section.reset(new ELFYAML::RelocationSection()); sectionMapping(IO, *cast(Section.get())); break; + case ELF::SHT_GROUP: + if (!IO.outputting()) + Section.reset(new ELFYAML::Group()); + groupSectionMapping(IO, *cast(Section.get())); + break; default: if (!IO.outputting()) Section.reset(new ELFYAML::RawContentSection()); Index: test/Object/obj2yaml-sectiongroup.test =================================================================== --- /dev/null +++ test/Object/obj2yaml-sectiongroup.test @@ -0,0 +1,26 @@ +# Checks that the tool is able to read section groups with ELF. +RUN: obj2yaml %p/Inputs/sectionGroup.elf.x86-64 > %t1.sectiongroup.yaml +RUN: FileCheck %s --check-prefix ELF-GROUP < %t1.sectiongroup.yaml +RUN: yaml2obj -format=elf %t1.sectiongroup.yaml -o %t2.o.elf +RUN: llvm-readobj -sections %t2.o.elf | FileCheck %s -check-prefix=SECTIONS +#ELF-GROUP: - Name: .group +#ELF-GROUP: Type: SHT_GROUP +#ELF-GROUP: Link: .symtab +#ELF-GROUP: Info: a +#ELF-GROUP: Members: +#ELF-GROUP: - SectionOrType: GRP_COMDAT +#ELF-GROUP: - SectionOrType: .rodata.a +#SECTIONS: Format: ELF64-x86-64 +#SECTIONS: Arch: x86_64 +#SECTIONS: AddressSize: 64bit +#SECTIONS: Section { +#SECTIONS: Index: 1 +#SECTIONS: Name: .group (21) +#SECTIONS: Type: SHT_GROUP (0x11) +#SECTIONS: Flags [ (0x0) +#SECTIONS: ] +#SECTIONS: Address: 0x0 +#SECTIONS: Size: 8 +#SECTIONS: AddressAlignment: 4 +#SECTIONS: EntrySize: 4 +#SECTIONS: } Index: tools/obj2yaml/elf2yaml.cpp =================================================================== --- tools/obj2yaml/elf2yaml.cpp +++ tools/obj2yaml/elf2yaml.cpp @@ -21,8 +21,10 @@ template class ELFDumper { + typedef object::Elf_Sym_Impl Elf_Sym; typedef typename object::ELFFile::Elf_Shdr Elf_Shdr; typedef typename object::ELFFile::Elf_Sym_Iter Elf_Sym_Iter; + typedef typename object::ELFFile::Elf_Word Elf_Word; const object::ELFFile &Obj; @@ -38,6 +40,7 @@ ErrorOr dumpRelaSection(const Elf_Shdr *Shdr); ErrorOr dumpContentSection(const Elf_Shdr *Shdr); + ErrorOr dumpGroup(const Elf_Shdr *Shdr); public: ELFDumper(const object::ELFFile &O); @@ -86,7 +89,13 @@ Y->Sections.push_back(std::unique_ptr(S.get())); break; } - // FIXME: Support SHT_GROUP section format. + case ELF::SHT_GROUP: { + ErrorOr G = dumpGroup(&Sec); + if (std::error_code EC = G.getError()) + return EC; + Y->Sections.push_back(std::unique_ptr(G.get())); + break; + } default: { ErrorOr S = dumpContentSection(&Sec); if (std::error_code EC = S.getError()) @@ -275,6 +284,41 @@ } template +ErrorOr ELFDumper::dumpGroup(const Elf_Shdr *Shdr) { + auto S = make_unique(); + + if (std::error_code EC = dumpCommonSection(Shdr, *S)) + return EC; + // Get sh_info which is the signature. + const Elf_Sym *symbol = Obj.getSymbol(Shdr->sh_info); + const Elf_Shdr *symtab = Obj.getSection(Shdr->sh_link); + auto sectionContents = Obj.getSectionContents(Shdr); + if (std::error_code ec = sectionContents.getError()) + return ec; + ErrorOr symbolName = Obj.getSymbolName(symtab, symbol); + if (std::error_code EC = symbolName.getError()) + return EC; + S->Info = *symbolName; + const Elf_Word *groupMembers = + reinterpret_cast(sectionContents->data()); + const long count = (Shdr->sh_size) / sizeof(Elf_Word); + ELFYAML::SectionOrType s; + for (int i = 0; i < count; i++) { + if (groupMembers[i] == llvm::ELF::GRP_COMDAT) { + s.sectionNameOrType = "GRP_COMDAT"; + } else { + const Elf_Shdr *sHdr = Obj.getSection(groupMembers[i]); + ErrorOr sectionName = Obj.getSectionName(sHdr); + if (std::error_code ec = sectionName.getError()) + return ec; + s.sectionNameOrType = *sectionName; + } + S->Members.push_back(s); + } + return S.release(); +} + +template static std::error_code elf2yaml(raw_ostream &Out, const object::ELFFile &Obj) { ELFDumper Dumper(Obj); Index: tools/yaml2obj/yaml2elf.cpp =================================================================== --- tools/yaml2obj/yaml2elf.cpp +++ tools/yaml2obj/yaml2elf.cpp @@ -131,6 +131,8 @@ bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::RelocationSection &Section, ContiguousBlobAccumulator &CBA); + bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::Group &Group, + ContiguousBlobAccumulator &CBA); // - SHT_NULL entry (placed first, i.e. 0'th entry) // - symbol table (.symtab) (placed third to last) @@ -223,6 +225,16 @@ if (!writeSectionContent(SHeader, *S, CBA)) return false; + } else if (auto S = dyn_cast(Sec.get())) { + unsigned SymIdx; + if (SymN2I.lookup(S->Info, SymIdx)) { + errs() << "error: Unknown symbol referenced: '" << S->Info + << "' at YAML section '" << S->Name << "'.\n"; + return false; + } + SHeader.sh_info = SymIdx; + if (!writeSectionContent(SHeader, *S, CBA)) + return false; } else llvm_unreachable("Unknown section type"); @@ -370,6 +382,38 @@ return true; } +template +bool ELFState::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::Group &Section, + ContiguousBlobAccumulator &CBA) { + typedef typename object::ELFFile::Elf_Word Elf_Word; + if (Section.Type != llvm::ELF::SHT_GROUP) { + errs() << "error: Invalid section type.\n"; + return false; + } + + SHeader.sh_entsize = sizeof(Elf_Word); + SHeader.sh_size = SHeader.sh_entsize * Section.Members.size(); + + auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset); + + for (auto member : Section.Members) { + Elf_Word SIdx; + unsigned int sectionIndex = 0; + if (member.sectionNameOrType == "GRP_COMDAT") + sectionIndex = llvm::ELF::GRP_COMDAT; + else if (SN2I.lookup(member.sectionNameOrType, sectionIndex)) { + errs() << "error: Unknown section referenced: '" + << member.sectionNameOrType << "' at YAML section' " + << Section.Name << "\n"; + return false; + } + SIdx = sectionIndex; + OS.write((const char *)&SIdx, sizeof(SIdx)); + } + return true; +} + template bool ELFState::buildSectionIndex() { SN2I.addName(".symtab", getDotSymTabSecNo()); SN2I.addName(".strtab", getDotStrTabSecNo());