Index: llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h +++ llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h @@ -86,6 +86,9 @@ llvm::yaml::Hex64 VAddr; llvm::yaml::Hex64 PAddr; Optional Align; + Optional FileSize; + Optional MemSize; + Optional Offset; std::vector Sections; }; Index: llvm/trunk/lib/ObjectYAML/ELFYAML.cpp =================================================================== --- llvm/trunk/lib/ObjectYAML/ELFYAML.cpp +++ llvm/trunk/lib/ObjectYAML/ELFYAML.cpp @@ -819,6 +819,9 @@ IO.mapOptional("VAddr", Phdr.VAddr, Hex64(0)); IO.mapOptional("PAddr", Phdr.PAddr, Hex64(0)); IO.mapOptional("Align", Phdr.Align); + IO.mapOptional("FileSize", Phdr.FileSize); + IO.mapOptional("MemSize", Phdr.MemSize); + IO.mapOptional("Offset", Phdr.Offset); } namespace { Index: llvm/trunk/test/tools/yaml2obj/program-header-size-offset.yaml =================================================================== --- llvm/trunk/test/tools/yaml2obj/program-header-size-offset.yaml +++ llvm/trunk/test/tools/yaml2obj/program-header-size-offset.yaml @@ -0,0 +1,85 @@ +# Show that yaml2obj properly emits program headers with explicit file size, +# memory size and offset parameters. + +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj %t --program-headers | FileCheck %s + +# CHECK: ProgramHeaders [ +# CHECK: Offset: 0x1234 +# CHECK: FileSize: 1111 +# CHECK: MemSize: 9999 + +# CHECK: Offset: 0x2000 +# CHECK: FileSize: 6 +# CHECK: MemSize: 6 + +# CHECK: Offset: 0x2000 +# CHECK: FileSize: 4 +# CHECK: MemSize: 6 + +# CHECK: Offset: 0x1FFF +# CHECK: FileSize: 5 +# CHECK: MemSize: 5 + +# CHECK: Offset: 0xFFE +# CHECK: FileSize: 7 +# CHECK: MemSize: 9 + +# CHECK: Offset: 0x3000 +# CHECK: FileSize: 3 +# CHECK: MemSize: 2 +# CHECK: ] + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Size: 4 + AddressAlign: 0x1000 + - Name: .rodata + Type: SHT_PROGBITS + Size: 4 + AddressAlign: 0x1000 + - Name: .data + Type: SHT_PROGBITS + Size: 4 +ProgramHeaders: + # Program header with no sections. + - Type: 0x6abcdef0 # arbitrary type + Offset: 0x1234 + FileSize: 1111 + MemSize: 9999 + # Program header with only file size set. + - Type: 0x6abcdef0 + FileSize: 6 + Sections: + - Section: .rodata + # Program header with only mem size set. + - Type: 0x6abcdef0 + MemSize: 6 + Sections: + - Section: .rodata + # Program header with only offset set. + - Type: 0x6abcdef0 + Offset: 0x1fff + Sections: + - Section: .rodata + # Program header with sections, valid properties. + - Type: 0x6abcdef0 + Offset: 0xffe + FileSize: 7 + MemSize: 9 + Sections: + - Section: .text + # Program header with sections, invalid properties. + - Type: 0x6abcdef0 + Offset: 0x3000 + FileSize: 3 + MemSize: 2 + Sections: + - Section: .data Index: llvm/trunk/tools/yaml2obj/yaml2elf.cpp =================================================================== --- llvm/trunk/tools/yaml2obj/yaml2elf.cpp +++ llvm/trunk/tools/yaml2obj/yaml2elf.cpp @@ -397,44 +397,58 @@ for (auto &YamlPhdr : Doc.ProgramHeaders) { auto &PHeader = PHeaders[PhdrIdx++]; - if (YamlPhdr.Sections.size()) - PHeader.p_offset = UINT32_MAX; - else - PHeader.p_offset = 0; - - // Find the minimum offset for the program header. - for (auto SecName : YamlPhdr.Sections) { - uint32_t Index = 0; - SN2I.lookup(SecName.Section, Index); - const auto &SHeader = SHeaders[Index]; - PHeader.p_offset = std::min(PHeader.p_offset, SHeader.sh_offset); - } - - // Find the maximum offset of the end of a section in order to set p_filesz. - PHeader.p_filesz = 0; - for (auto SecName : YamlPhdr.Sections) { - uint32_t Index = 0; - SN2I.lookup(SecName.Section, Index); - const auto &SHeader = SHeaders[Index]; - uint64_t EndOfSection; - if (SHeader.sh_type == llvm::ELF::SHT_NOBITS) - EndOfSection = SHeader.sh_offset; + if (YamlPhdr.Offset) { + PHeader.p_offset = *YamlPhdr.Offset; + } else { + if (YamlPhdr.Sections.size()) + PHeader.p_offset = UINT32_MAX; else - EndOfSection = SHeader.sh_offset + SHeader.sh_size; - uint64_t EndOfSegment = PHeader.p_offset + PHeader.p_filesz; - EndOfSegment = std::max(EndOfSegment, EndOfSection); - PHeader.p_filesz = EndOfSegment - PHeader.p_offset; + PHeader.p_offset = 0; + + // Find the minimum offset for the program header. + for (auto SecName : YamlPhdr.Sections) { + uint32_t Index = 0; + SN2I.lookup(SecName.Section, Index); + const auto &SHeader = SHeaders[Index]; + PHeader.p_offset = std::min(PHeader.p_offset, SHeader.sh_offset); + } } - // Find the memory size by adding the size of sections at the end of the - // segment. These should be empty (size of zero) and NOBITS sections. - PHeader.p_memsz = PHeader.p_filesz; - for (auto SecName : YamlPhdr.Sections) { - uint32_t Index = 0; - SN2I.lookup(SecName.Section, Index); - const auto &SHeader = SHeaders[Index]; - if (SHeader.sh_offset == PHeader.p_offset + PHeader.p_filesz) - PHeader.p_memsz += SHeader.sh_size; + // Find the maximum offset of the end of a section in order to set p_filesz, + // if not set explicitly. + if (YamlPhdr.FileSize) { + PHeader.p_filesz = *YamlPhdr.FileSize; + } else { + PHeader.p_filesz = 0; + for (auto SecName : YamlPhdr.Sections) { + uint32_t Index = 0; + SN2I.lookup(SecName.Section, Index); + const auto &SHeader = SHeaders[Index]; + uint64_t EndOfSection; + if (SHeader.sh_type == llvm::ELF::SHT_NOBITS) + EndOfSection = SHeader.sh_offset; + else + EndOfSection = SHeader.sh_offset + SHeader.sh_size; + uint64_t EndOfSegment = PHeader.p_offset + PHeader.p_filesz; + EndOfSegment = std::max(EndOfSegment, EndOfSection); + PHeader.p_filesz = EndOfSegment - PHeader.p_offset; + } + } + + // If not set explicitly, find the memory size by adding the size of + // sections at the end of the segment. These should be empty (size of zero) + // and NOBITS sections. + if (YamlPhdr.MemSize) { + PHeader.p_memsz = *YamlPhdr.MemSize; + } else { + PHeader.p_memsz = PHeader.p_filesz; + for (auto SecName : YamlPhdr.Sections) { + uint32_t Index = 0; + SN2I.lookup(SecName.Section, Index); + const auto &SHeader = SHeaders[Index]; + if (SHeader.sh_offset == PHeader.p_offset + PHeader.p_filesz) + PHeader.p_memsz += SHeader.sh_size; + } } // Set the alignment of the segment to be the same as the maximum alignment