diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -81,6 +81,10 @@ ELF_EF Flags; llvm::yaml::Hex64 Entry; + Optional EPhOff; + Optional EPhEntSize; + Optional EPhNum; + Optional SHEntSize; Optional SHOff; Optional SHNum; diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/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.EPhOff) + Header.e_phoff = *Doc.Header.EPhOff; + else if (!Doc.ProgramHeaders.empty()) + Header.e_phoff = sizeof(Header); + else + Header.e_phoff = 0; + + if (Doc.Header.EPhEntSize) + Header.e_phentsize = *Doc.Header.EPhEntSize; + else if (!Doc.ProgramHeaders.empty()) + Header.e_phentsize = sizeof(Elf_Phdr); + else + Header.e_phentsize = 0; + + if (Doc.Header.EPhNum) + Header.e_phnum = *Doc.Header.EPhNum; + 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); diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/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.EPhOff && !FileHdr.EPhEntSize && !FileHdr.EPhNum)); + IO.mapOptional("EPhOff", FileHdr.EPhOff); + IO.mapOptional("EPhEntSize", FileHdr.EPhEntSize); + IO.mapOptional("EPhNum", FileHdr.EPhNum); + IO.mapOptional("SHEntSize", FileHdr.SHEntSize); IO.mapOptional("SHOff", FileHdr.SHOff); IO.mapOptional("SHNum", FileHdr.SHNum); diff --git a/llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml b/llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml --- a/llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml +++ b/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. @@ -29,10 +37,18 @@ Data: ELFDATA2LSB Type: ET_REL Machine: EM_X86_64 - SHEntSize: [[SHENTSIZE=64]] - SHOff: [[SHOFF=88]] - SHNum: [[SHNUM=3]] - SHStrNdx: [[SHSTRNDX=2]] + SHEntSize: [[SHENTSIZE=64]] + SHOff: [[SHOFF=200]] + SHNum: [[SHNUM=3]] + SHStrNdx: [[SHSTRNDX=2]] + EPhOff: [[PHOFF=64]] + EPhEntSize: [[PHENTSIZE=56]] + EPhNum: [[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{{$}} diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/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 EPh* 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];