Index: llvm/test/Object/obj2yaml.test =================================================================== --- llvm/test/Object/obj2yaml.test +++ llvm/test/Object/obj2yaml.test @@ -664,7 +664,6 @@ # ELF-AVR-NEXT: Flags: [ PF_X, PF_R ] # ELF-AVR-NEXT: Sections: # ELF-AVR-NEXT: - Section: .text -# ELF-AVR-NEXT: - Section: .data # ELF-AVR-NEXT: Align: 0x0000000000000002 # ELF-AVR-NEXT: - Type: PT_LOAD # ELF-AVR-NEXT: Flags: [ PF_W, PF_R ] Index: llvm/test/tools/obj2yaml/program-headers.yaml =================================================================== --- llvm/test/tools/obj2yaml/program-headers.yaml +++ llvm/test/tools/obj2yaml/program-headers.yaml @@ -419,3 +419,70 @@ Type: SHT_PROGBITS Flags: [ SHF_ALLOC ] Size: 0x1 + +## Check how we dump segments which contain empty sections. +# RUN: yaml2obj --docnum=5 %s -o %t5 + +## Show the layout of the object before we dump it using obj2yaml. +## Notes: 1) '.empty.foo', '.empty.bar1' and '.bar' have the same file offset, but '.empty.foo' +## has VA that is outside of the segment, hence we should not include it into it. +## 2) '.bar1' ends at 0x79, which is the starting file offset of both '.empty.bar2' +## and '.empty.zed'. We should only include '.empty.bar2', because the VA of the +## '.empty.zed' section is outside of segment's virtual space. +# RUN: llvm-readelf -sections %t5 | FileCheck %s --check-prefix=ZERO-SIZE-MAPPING + +# ZERO-SIZE-MAPPING: Section Headers: +# ZERO-SIZE-MAPPING: [Nr] Name Type Address Off Size +# ZERO-SIZE-MAPPING: [ 1] .empty.foo PROGBITS 0000000000001000 000078 000000 +# ZERO-SIZE-MAPPING-NEXT: [ 2] .empty.bar1 PROGBITS 0000000000002000 000078 000000 +# ZERO-SIZE-MAPPING-NEXT: [ 3] .bar PROGBITS 0000000000002000 000078 000001 +# ZERO-SIZE-MAPPING-NEXT: [ 4] .empty.bar2 PROGBITS 0000000000002001 000079 000000 +# ZERO-SIZE-MAPPING-NEXT: [ 5] .empty.zed PROGBITS 0000000000003000 000079 000000 + +# RUN: obj2yaml %t5 | FileCheck %s --check-prefix=ZERO-SIZE + +# ZERO-SIZE: ProgramHeaders: +# ZERO-SIZE-NEXT: - Type: PT_LOAD +# ZERO-SIZE-NEXT: Flags: [ PF_W, PF_R ] +# ZERO-SIZE-NEXT: Sections: +# ZERO-SIZE-NEXT: - Section: .empty.bar1 +# ZERO-SIZE-NEXT: - Section: .bar +# ZERO-SIZE-NEXT: - Section: .empty.bar2 +# ZERO-SIZE-NEXT: VAddr: 0x0000000000002000 +# ZERO-SIZE-NEXT: Align: 0x0000000000000001 +# ZERO-SIZE-NEXT: Sections: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_W, PF_R ] + Sections: + - Section: .bar + VAddr: 0x2000 +Sections: + - Name: .empty.foo + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1000 + - Name: .empty.bar1 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x2000 + - Name: .bar + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x2000 + Size: 0x1 + - Name: .empty.bar2 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x2001 + - Name: .empty.zed + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x3000 Index: llvm/tools/obj2yaml/elf2yaml.cpp =================================================================== --- llvm/tools/obj2yaml/elf2yaml.cpp +++ llvm/tools/obj2yaml/elf2yaml.cpp @@ -298,8 +298,24 @@ const typename ELFT::Phdr &Phdr) { if (Sec.Type == ELF::SHT_NULL) return false; - return SHdr.sh_offset >= Phdr.p_offset && - (SHdr.sh_offset + SHdr.sh_size <= Phdr.p_offset + Phdr.p_filesz); + + // A section is within a segment when its location in a file is within the + // [p_offset, p_offset + p_filesz] region. + bool FileOffsetsMatch = + SHdr.sh_offset >= Phdr.p_offset && + (SHdr.sh_offset + SHdr.sh_size <= Phdr.p_offset + Phdr.p_filesz); + + if (!FileOffsetsMatch) + return false; + + // An empty section can share the file offset with another section, so we need + // to do an additional check to confirm that such section is not outside of + // the virtual address space of the segment. + if (!SHdr.sh_size) + return SHdr.sh_addr >= Phdr.p_vaddr && + SHdr.sh_addr <= Phdr.p_vaddr + Phdr.p_memsz; + + return true; } template