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,13 @@ 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 && !FileHdr.PHEntSize && !FileHdr.PHNum)); + 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,15 +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 %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 +# DEFAULT: Start of program headers: 64 (bytes into file) +# DEFAULT: Start of section headers: 200 (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: @@ -17,6 +20,11 @@ Data: ELFDATA2LSB Type: ET_REL Machine: EM_X86_64 +ProgramHeaders: + - Type: PT_LOAD + Sections: [] + - Type: PT_LOAD + Sections: [] ## Check we can override all default values using the same values ## and that this does not change the output. @@ -30,9 +38,17 @@ Type: ET_REL Machine: EM_X86_64 SHEntSize: [[SHENTSIZE=64]] - SHOff: [[SHOFF=88]] + SHOff: [[SHOFF=200]] 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. @@ -63,3 +79,21 @@ # RUN: od -A n -t x1 -v -j 0x3a -N 1 %t-default | FileCheck %s --check-prefix=OLDSIZE # NEWSIZE: 01 # OLDSIZE: 40 + +## Override the e_phoff field. +# RUN: yaml2obj --docnum=2 %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 --docnum=2 %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 --docnum=2 %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];