Index: llvm/lib/ObjectYAML/ELFEmitter.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFEmitter.cpp +++ llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -754,18 +754,21 @@ Elf_Phdr &PHeader = PHeaders[PhdrIdx++]; std::vector<Fragment> Fragments = getPhdrFragments(YamlPhdr, SHeaders); - if (YamlPhdr.Offset) { - PHeader.p_offset = *YamlPhdr.Offset; - } else { - if (YamlPhdr.Sections.size()) - PHeader.p_offset = UINT32_MAX; - else - PHeader.p_offset = 0; + uint64_t PhdrFileOffset = Fragments.empty() ? 0 : UINT64_MAX; + // Find the minimum section file offset. + for (const Fragment &F : Fragments) + PhdrFileOffset = std::min(PhdrFileOffset, F.Offset); - // Find the minimum offset for the program header. - for (const Fragment &F : Fragments) - PHeader.p_offset = std::min((uint64_t)PHeader.p_offset, F.Offset); + if (YamlPhdr.Offset) { + if (!Fragments.empty() && *YamlPhdr.Offset > PhdrFileOffset) + reportError("the 'Offset' specified for the segment with index " + + Twine(PhdrIdx) + + " must be less or equal than the minimal file offset of a " + "section included into it (0x" + + Twine::utohexstr(PhdrFileOffset) + ")"); + PhdrFileOffset = *YamlPhdr.Offset; } + PHeader.p_offset = PhdrFileOffset; // Find the maximum offset of the end of a section in order to set p_filesz // and p_memsz. When setting p_filesz, trailing SHT_NOBITS sections are not Index: llvm/test/Object/invalid.test =================================================================== --- llvm/test/Object/invalid.test +++ llvm/test/Object/invalid.test @@ -485,17 +485,9 @@ Data: ELFDATA2LSB Type: ET_EXEC Machine: EM_X86_64 -Sections: - - Name: .dynamic - Type: SHT_DYNAMIC - Entries: - - Tag: DT_NULL - Value: 0 ProgramHeaders: - Type: PT_DYNAMIC Offset: 0xffff0000 - Sections: - - Section: .dynamic ## PT_DYNAMIC's p_filesz field is so large that p_offset + p_filesz is larger ## than the object size. Check llvm-readobj reports it. Index: llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test =================================================================== --- llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test +++ llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test @@ -33,13 +33,7 @@ Data: ELFDATA2LSB Type: ET_EXEC Machine: EM_X86_64 -Sections: - - Name: .foo - Type: SHT_PROGBITS - Size: 1 ProgramHeaders: - - Type: PT_LOAD - Offset: 0x100000 - FileSize: 1 - Sections: - - Section: .foo + - Type: PT_LOAD + Offset: 0x100000 + FileSize: 1 Index: llvm/test/tools/llvm-readobj/ELF/gnu-notes.test =================================================================== --- llvm/test/tools/llvm-readobj/ELF/gnu-notes.test +++ llvm/test/tools/llvm-readobj/ELF/gnu-notes.test @@ -165,15 +165,9 @@ Data: ELFDATA2LSB Type: ET_CORE Machine: EM_X86_64 -Sections: - - Name: .note - Type: SHT_NOTE - Notes: [] ProgramHeaders: - - Type: PT_NOTE + - Type: PT_NOTE Offset: 0xffff0000 - Sections: - - Section: .note ## Test tools report an error if a note program header has an invalid size that ## goes past the end of file. Index: llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml =================================================================== --- llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml +++ llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml @@ -1,8 +1,8 @@ ## 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 +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: llvm-readobj %t1 --program-headers | FileCheck %s # CHECK: ProgramHeaders [ # CHECK: Offset: 0x1234 @@ -34,7 +34,7 @@ # CHECK: MemSize: 6 # CHECK: ] -!ELF +--- !ELF FileHeader: Class: ELFCLASS64 Data: ELFDATA2LSB @@ -97,8 +97,6 @@ Offset: 0x3000 FileSize: 3 MemSize: 2 - Sections: - - Section: .data # Program header with 2 SHT_NOBITS sections. - Type: 0x6abcdef0 Offset: 0x2004 @@ -106,3 +104,79 @@ - Section: .data - Section: .nobits1 - Section: .nobits2 + +## Test the "Offset" property. + +## Check that by default the p_offset field of a segment is set to the +## offset of the section with the minimal section offset. +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: llvm-readelf %t2 --sections --program-headers | \ +# RUN: FileCheck %s --check-prefixes=DEFAULT-OFFSET + +# DEFAULT-OFFSET: [Nr] Name Type Address Off +# DEFAULT-OFFSET: [ 1] .foo PROGBITS 0000000000001000 0000b0 +# DEFAULT-OFFSET-NEXT: [ 2] .bar PROGBITS 0000000000001001 0000b1 + +# DEFAULT-OFFSET: Type Offset +# DEFAULT-OFFSET-NEXT: LOAD 0x0000b0 +# DEFAULT-OFFSET-NEXT: LOAD 0x0000b1 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Size: 0x1 + Address: 0x1000 + - Name: .bar + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Size: 0x1 +ProgramHeaders: + - Type: PT_LOAD + Sections: + - Section: .foo + - Section: .bar + - Type: PT_LOAD + Sections: + - Section: .bar + +## Check we can set the "Offset" value explicitly when it is less or equal to +## the offset of a section in the segment. +# RUN: yaml2obj --docnum=3 -DOFFSET=0x78 %s -o %t3 +# RUN: llvm-readelf %t3 --sections --program-headers | \ +# RUN: FileCheck %s --check-prefixes=VALID-OFFSET + +# VALID-OFFSET: [Nr] Name Type Address Off +# VALID-OFFSET: [ 1] .foo PROGBITS 0000000000000000 000078 + +# VALID-OFFSET: Type Offset +# VALID-OFFSET: LOAD 0x000078 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Size: 0x1 +ProgramHeaders: + - Type: PT_LOAD + Offset: [[OFFSET]] + Sections: + - Section: .foo + +## Check we report an error when the "Offset" value is larger than the offset of a section in the segment. +# RUN: not yaml2obj --docnum=3 -DOFFSET=0x79 %s -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-OFFSET + +# INVALID-OFFSET: yaml2obj: error: the 'Offset' specified for the segment with index 1 must be less or equal than the minimal file offset of a section included into it (0x78)