Index: include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- include/llvm/ObjectYAML/ELFYAML.h +++ include/llvm/ObjectYAML/ELFYAML.h @@ -33,12 +33,14 @@ // In the future, these would probably be better suited by C++11 enum // class's with appropriate fixed underlying type. LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_ET) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PT) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_EM) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFCLASS) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PF) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS) @@ -66,6 +68,19 @@ ELF_EF Flags; llvm::yaml::Hex64 Entry; }; +struct SectionName { + StringRef Section; +}; +struct ProgramHeader { + ELF_PT Type; + ELF_PF Flags; + llvm::yaml::Hex64 VAddr; + llvm::yaml::Hex64 PAddr; + llvm::yaml::Hex64 FileSize; + llvm::yaml::Hex64 MemSize; + llvm::yaml::Hex64 Align; + std::vector Sections; +}; struct Symbol { StringRef Name; ELF_STT Type; @@ -165,6 +180,7 @@ struct Object { FileHeader Header; + std::vector ProgramHeaders; std::vector> Sections; // Although in reality the symbols reside in a section, it is a lot // cleaner and nicer if we read them from the YAML as a separate @@ -176,10 +192,12 @@ } // end namespace ELFYAML } // end namespace llvm +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader) 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) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionName) namespace llvm { namespace yaml { @@ -189,6 +207,10 @@ static void enumeration(IO &IO, ELFYAML::ELF_ET &Value); }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_PT &Value); +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, ELFYAML::ELF_EM &Value); @@ -214,6 +236,10 @@ static void bitset(IO &IO, ELFYAML::ELF_EF &Value); }; +template <> struct ScalarBitSetTraits { + static void bitset(IO &IO, ELFYAML::ELF_PF &Value); +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, ELFYAML::ELF_SHT &Value); @@ -284,6 +310,10 @@ static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); }; +template <> struct MappingTraits { + static void mapping(IO &IO, ELFYAML::ProgramHeader &FileHdr); +}; + template <> struct MappingTraits { static void mapping(IO &IO, ELFYAML::Symbol &Symbol); @@ -313,6 +343,10 @@ static void mapping(IO &IO, ELFYAML::SectionOrType §ionOrType); }; +template <> struct MappingTraits { + static void mapping(IO &IO, ELFYAML::SectionName §ionName); +}; + } // end namespace yaml } // end namespace llvm Index: lib/ObjectYAML/ELFYAML.cpp =================================================================== --- lib/ObjectYAML/ELFYAML.cpp +++ lib/ObjectYAML/ELFYAML.cpp @@ -33,6 +33,21 @@ IO.enumFallback(Value); } +void ScalarEnumerationTraits::enumeration( + IO &IO, ELFYAML::ELF_PT &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X) + ECase(PT_NULL); + ECase(PT_LOAD); + ECase(PT_DYNAMIC); + ECase(PT_INTERP); + ECase(PT_NOTE); + ECase(PT_SHLIB); + ECase(PT_PHDR); + ECase(PT_TLS); +#undef ECase + IO.enumFallback(Value); +} + void ScalarEnumerationTraits::enumeration( IO &IO, ELFYAML::ELF_EM &Value) { #define ECase(X) IO.enumCase(Value, #X, ELF::X) @@ -405,6 +420,14 @@ #undef ECase } +void ScalarBitSetTraits::bitset(IO &IO, + ELFYAML::ELF_PF &Value) { +#define BCase(X) IO.bitSetCase(Value, #X, ELF::X) + BCase(PF_X); + BCase(PF_W); + BCase(PF_R); +} + void ScalarBitSetTraits::bitset(IO &IO, ELFYAML::ELF_SHF &Value) { const auto *Object = static_cast(IO.getContext()); @@ -647,6 +670,18 @@ IO.mapOptional("Entry", FileHdr.Entry, Hex64(0)); } +void MappingTraits::mapping( + IO &IO, ELFYAML::ProgramHeader &Phdr) { + IO.mapRequired("Type", Phdr.Type); + IO.mapOptional("Flags", Phdr.Flags, ELFYAML::ELF_PF(0)); + IO.mapOptional("Sections", Phdr.Sections); + IO.mapOptional("VAddr", Phdr.VAddr, Hex64(0)); + IO.mapOptional("PAddr", Phdr.PAddr, Hex64(0)); + IO.mapOptional("FileSize", Phdr.FileSize, Hex64(0)); + IO.mapOptional("MemSize", Phdr.MemSize, Hex64(0)); + IO.mapOptional("Align", Phdr.Align, Hex64(1)); +} + namespace { struct NormalizedOther { NormalizedOther(IO &) @@ -716,6 +751,11 @@ IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType); } +void MappingTraits::mapping( + IO &IO, ELFYAML::SectionName §ionName) { + IO.mapRequired("Section", sectionName.Section); +} + static void sectionMapping(IO &IO, ELFYAML::MipsABIFlags &Section) { commonSectionMapping(IO, Section); IO.mapOptional("Version", Section.Version, Hex16(0)); @@ -831,6 +871,7 @@ IO.setContext(&Object); IO.mapTag("!ELF", true); IO.mapRequired("FileHeader", Object.Header); + IO.mapOptional("ProgramHeaders", Object.ProgramHeaders); IO.mapOptional("Sections", Object.Sections); IO.mapOptional("Symbols", Object.Symbols); IO.setContext(nullptr); Index: tools/yaml2obj/yaml2elf.cpp =================================================================== --- tools/yaml2obj/yaml2elf.cpp +++ tools/yaml2obj/yaml2elf.cpp @@ -99,6 +99,7 @@ template class ELFState { typedef typename object::ELFFile::Elf_Ehdr Elf_Ehdr; + typedef typename object::ELFFile::Elf_Phdr Elf_Phdr; typedef typename object::ELFFile::Elf_Shdr Elf_Shdr; typedef typename object::ELFFile::Elf_Sym Elf_Sym; typedef typename object::ELFFile::Elf_Rel Elf_Rel; @@ -118,6 +119,7 @@ bool buildSymbolIndex(std::size_t &StartIndex, const std::vector &Symbols); void initELFHeader(Elf_Ehdr &Header); + void initProgramHeaders(std::vector &PHeaders); bool initSectionHeaders(std::vector &SHeaders, ContiguousBlobAccumulator &CBA); void initSymtabSectionHeader(Elf_Shdr &SHeader, @@ -173,15 +175,34 @@ Header.e_machine = Doc.Header.Machine; Header.e_version = EV_CURRENT; Header.e_entry = Doc.Header.Entry; + Header.e_phoff = sizeof(Header); Header.e_flags = Doc.Header.Flags; Header.e_ehsize = sizeof(Elf_Ehdr); + Header.e_phentsize = sizeof(Elf_Phdr); + Header.e_phnum = Doc.ProgramHeaders.size(); Header.e_shentsize = sizeof(Elf_Shdr); - // Immediately following the ELF header. - Header.e_shoff = sizeof(Header); + // Immediately following the ELF header and program headers. + Header.e_shoff = + sizeof(Header) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size(); Header.e_shnum = getSectionCount(); Header.e_shstrndx = getDotShStrTabSecNo(); } +template +void ELFState::initProgramHeaders(std::vector &PHeaders) { + for (const auto &YamlPhdr : Doc.ProgramHeaders) { + Elf_Phdr Phdr; + Phdr.p_type = YamlPhdr.Type; + Phdr.p_flags = YamlPhdr.Flags; + Phdr.p_vaddr = YamlPhdr.VAddr; + Phdr.p_paddr = YamlPhdr.PAddr; + Phdr.p_filesz = YamlPhdr.FileSize; + Phdr.p_memsz = YamlPhdr.MemSize; + Phdr.p_align = YamlPhdr.Align; + PHeaders.push_back(Phdr); + } +} + template bool ELFState::initSectionHeaders(std::vector &SHeaders, ContiguousBlobAccumulator &CBA) { @@ -508,12 +529,15 @@ State.initELFHeader(Header); // TODO: Flesh out section header support. - // TODO: Program headers. + + std::vector PHeaders; + State.initProgramHeaders(PHeaders); // XXX: This offset is tightly coupled with the order that we write // things to `OS`. - const size_t SectionContentBeginOffset = - Header.e_ehsize + Header.e_shentsize * Header.e_shnum; + const size_t SectionContentBeginOffset = Header.e_ehsize + + Header.e_phentsize * Header.e_phnum + + Header.e_shentsize * Header.e_shnum; ContiguousBlobAccumulator CBA(SectionContentBeginOffset); // Doc might not contain .symtab, .strtab and .shstrtab sections, @@ -543,7 +567,24 @@ CBA); SHeaders.push_back(ShStrTabSHeader); + // Now we can decide segment offsets + uint32_t PhdrIdx = 0; + for (auto &YamlPhdr : Doc.ProgramHeaders) { + auto &PHeader = PHeaders[PhdrIdx++]; + if (YamlPhdr.Sections.size()) + PHeader.p_offset = UINT32_MAX; + else + PHeader.p_offset = 0; + for (auto SecName : YamlPhdr.Sections) { + uint32_t Index = 0; + State.SN2I.lookup(SecName.Section, Index); + const auto &SHeader = SHeaders[Index]; + PHeader.p_offset = std::min(PHeader.p_offset, SHeader.sh_offset); + } + } + OS.write((const char *)&Header, sizeof(Header)); + writeArrayData(OS, makeArrayRef(PHeaders)); writeArrayData(OS, makeArrayRef(SHeaders)); CBA.writeBlobToStream(OS); return 0;