Index: llvm/include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- llvm/include/llvm/ObjectYAML/ELFYAML.h +++ llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -81,6 +81,10 @@ ELF_EF Flags; llvm::yaml::Hex64 Entry; + Optional PhOff; + Optional PhEntSize; + Optional PhNum; + Optional SHEntSize; Optional SHOff; Optional SHNum; Index: llvm/lib/ObjectYAML/ELFEmitter.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFEmitter.cpp +++ llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -393,11 +393,29 @@ Header.e_machine = Doc.Header.Machine; Header.e_version = EV_CURRENT; Header.e_entry = Doc.Header.Entry; - Header.e_phoff = Doc.ProgramHeaders.size() ? sizeof(Header) : 0; Header.e_flags = Doc.Header.Flags; Header.e_ehsize = sizeof(Elf_Ehdr); - Header.e_phentsize = Doc.ProgramHeaders.size() ? sizeof(Elf_Phdr) : 0; - Header.e_phnum = Doc.ProgramHeaders.size(); + + if (Doc.Header.PhOff) + Header.e_phoff = *Doc.Header.PhOff; + else if (!Doc.ProgramHeaders.empty()) + Header.e_phoff = sizeof(Header); + else + Header.e_phoff = 0; + + if (Doc.Header.PhEntSize) + Header.e_phentsize = *Doc.Header.PhEntSize; + else if (!Doc.ProgramHeaders.empty()) + Header.e_phentsize = sizeof(Elf_Phdr); + else + Header.e_phentsize = 0; + + if (Doc.Header.PhNum) + Header.e_phnum = *Doc.Header.PhNum; + else if (!Doc.ProgramHeaders.empty()) + Header.e_phnum = Doc.ProgramHeaders.size(); + else + Header.e_phnum = 0; Header.e_shentsize = Doc.Header.SHEntSize ? (uint16_t)*Doc.Header.SHEntSize : sizeof(Elf_Shdr); Index: llvm/lib/ObjectYAML/ELFYAML.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFYAML.cpp +++ llvm/lib/ObjectYAML/ELFYAML.cpp @@ -866,6 +866,14 @@ IO.mapOptional("Flags", FileHdr.Flags, ELFYAML::ELF_EF(0)); IO.mapOptional("Entry", FileHdr.Entry, Hex64(0)); + // obj2yaml does not dump these fields. + assert(!IO.outputting() || + (!FileHdr.PhOff.hasValue() && !FileHdr.PhEntSize.hasValue() && + !FileHdr.PhNum.hasValue())); + IO.mapOptional("PhOff", FileHdr.PhOff); + IO.mapOptional("PhEntSize", FileHdr.PhEntSize); + IO.mapOptional("PhNum", FileHdr.PhNum); + IO.mapOptional("SHEntSize", FileHdr.SHEntSize); IO.mapOptional("SHOff", FileHdr.SHOff); IO.mapOptional("SHNum", FileHdr.SHNum); Index: llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml =================================================================== --- llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml +++ llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml @@ -1,32 +1,18 @@ ## In this test case we check that we can override the default values for -## e_shentsize, e_shoff, e_shnum and e_shstrndx fields in the YAML. +## ELF header fields in the YAML. ## First we check the default values. -# RUN: yaml2obj --docnum=1 %s -o %t1 -# RUN: llvm-readelf --file-headers %t1 | FileCheck %s --check-prefix=DEFAULT +# RUN: yaml2obj %s -o %t-default +# RUN: llvm-readelf --file-headers %t-default | FileCheck %s --check-prefix=DEFAULT -# DEFAULT: Start of section headers: 88 (bytes into file) -# DEFAULT: Size of section headers: 64 (bytes) -# DEFAULT: Number of section headers: 3 -# DEFAULT: Section header string table index: 2 - ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_REL - Machine: EM_X86_64 - -## Override 3 fields: e_shoff, e_shnum and e_shstrndx. Check the output. - -# RUN: yaml2obj --docnum=2 %s -o %t2 -# RUN: llvm-readelf --file-headers %t2 | FileCheck %s --check-prefix=CUSTOM - -# CUSTOM: Start of section headers: 2 (bytes into file) -# CUSTOM: Size of section headers: 64 (bytes) -# CUSTOM: Number of section headers: 3 -# CUSTOM: Section header string table index: 4 +# DEFAULT: Start of program headers: 64 (bytes into file) +# DEFAULT: Start of section headers: 88 (bytes into file) +# DEFAULT: Size of program headers: 56 (bytes) +# DEFAULT: Number of program headers: 2 +# DEFAULT: Size of section headers: 64 (bytes) +# DEFAULT: Number of section headers: 3 +# DEFAULT: Section header string table index: 2 --- !ELF FileHeader: @@ -34,28 +20,63 @@ Data: ELFDATA2LSB Type: ET_REL Machine: EM_X86_64 - SHEntSize: 64 - SHOff: 2 - SHNum: 3 - SHStrNdx: 4 + SHEntSize: [[SHENTSIZE=64]] + SHOff: [[SHOFF=88]] + SHNum: [[SHNUM=3]] + SHStrNdx: [[SHSTRNDX=2]] + PhOff: [[PHOFF=64]] + PhEntSize: [[PHENTSIZE=56]] + PhNum: [[PHNUM=2]] +ProgramHeaders: + - Type: PT_LOAD + Sections: [] + - Type: PT_LOAD + Sections: [] + +## Override different fields to check the output produced. + +## Override the e_shoff field. +# RUN: yaml2obj %s -DSHOFF=3 -o %t2 +# RUN: llvm-readelf --file-headers %t2 | FileCheck %s --check-prefix=SHOFF + +# SHOFF: Start of section headers: 3 (bytes into file) + +## Override the e_shnum field. +# RUN: yaml2obj %s -DSHNUM=2 -o %t3 +# RUN: llvm-readelf --file-headers %t3 | FileCheck %s --check-prefix=SHNUM + +# SHNUM: Number of section headers: 2{{$}} + +## Override the e_shstrndx field. +# RUN: yaml2obj %s -DSHSTRNDX=4 -o %t4 +# RUN: llvm-readelf --file-headers %t4 | FileCheck %s --check-prefix=SHSTRNDX -## Finally, we use the same YAML as above, but set e_shentsize to 1. +# SHSTRNDX: Section header string table index: 4{{$}} + +## Override the e_shentsize field. ## Check the result using raw output from 'od' because llvm-readelf ## is unable to dump such headers. -# RUN: yaml2obj --docnum=3 %s -o %t3 -# RUN: od -A n -t x1 -v -j 0x3a -N 1 %t3 | FileCheck %s --check-prefix=NEWSIZE -# RUN: od -A n -t x1 -v -j 0x3a -N 1 %t2 | FileCheck %s --check-prefix=OLDSIZE +# RUN: yaml2obj %s -DSHENTSIZE=1 -o %t5 +# RUN: od -A n -t x1 -v -j 0x3a -N 1 %t5 | FileCheck %s --check-prefix=NEWSIZE +# RUN: od -A n -t x1 -v -j 0x3a -N 1 %t-default | FileCheck %s --check-prefix=OLDSIZE # NEWSIZE: 01 # OLDSIZE: 40 ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_REL - Machine: EM_X86_64 - SHEntSize: 1 - SHOff: 2 - SHNum: 3 - SHStrNdx: 4 +## Override the e_phoff field. +# RUN: yaml2obj %s -DPHOFF=3 -o %t6 +# RUN: llvm-readelf --file-headers %t6 | FileCheck %s --check-prefix=PHOFF + +# PHOFF: Start of program headers: 3 (bytes into file){{$}} + +## Override the e_phnum field. +# RUN: yaml2obj %s -DPHNUM=1 -o %t7 +# RUN: llvm-readelf --file-headers %t7 | FileCheck %s --check-prefix=PHNUM + +# PHNUM: Number of program headers: 1{{$}} + +## Override the e_phentsize field. +# RUN: yaml2obj %s -DPHENTSIZE=1 -o %t8 +# RUN: not llvm-readelf --file-headers %t8 2>&1 | FileCheck %s --check-prefix=PHENTSIZE + +# PHENTSIZE: invalid e_phentsize: 1{{$}} Index: llvm/tools/obj2yaml/elf2yaml.cpp =================================================================== --- llvm/tools/obj2yaml/elf2yaml.cpp +++ llvm/tools/obj2yaml/elf2yaml.cpp @@ -200,9 +200,9 @@ template Expected ELFDumper::dump() { auto Y = std::make_unique(); - // Dump header. We do not dump SHEntSize, SHOff, SHNum and SHStrNdx fields. - // When not explicitly set, the values are set by yaml2obj automatically - // and there is no need to dump them here. + // Dump header. We do not dump Ph* and SH* fields. When not explicitly set, + // the values are set by yaml2obj automatically and there is no need to dump + // them here. Y->Header.Class = ELFYAML::ELF_ELFCLASS(Obj.getHeader()->getFileClass()); Y->Header.Data = ELFYAML::ELF_ELFDATA(Obj.getHeader()->getDataEncoding()); Y->Header.OSABI = Obj.getHeader()->e_ident[ELF::EI_OSABI];