--- /dev/null
+# 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
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);
+ if (YamlPhdr.Offset) {
+ PHeader.p_offset = *YamlPhdr.Offset;
+ } else {
+ 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;
- 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;
+ // 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;
+ }
}
- // 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;
+ // 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