aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgii Rymar <grimar@accesssoftek.com>2020-04-07 18:20:51 +0300
committerGeorgii Rymar <grimar@accesssoftek.com>2020-04-22 12:36:00 +0300
commit317c4913c642f8f7fa0fb150fd5e656b59f20a4a (patch)
treec80336292de5207367719716e970c8bfa5cdd828
parent0736d1ccf32ba4e6fe860942d8a6d05f964f058e (diff)
downloadllvm-317c4913c642f8f7fa0fb150fd5e656b59f20a4a.zip
llvm-317c4913c642f8f7fa0fb150fd5e656b59f20a4a.tar.gz
llvm-317c4913c642f8f7fa0fb150fd5e656b59f20a4a.tar.bz2
[obj2yaml] - Fix the issue with dumping empty sections when dumping program headers.
Imagine we have: ``` ProgramHeaders: - Type: PT_LOAD Flags: [ PF_W, PF_R ] Sections: - Section: .bar VAddr: 0x2000 Sections: - Name: .foo Type: SHT_PROGBITS Flags: [ SHF_ALLOC, SHF_EXECINSTR ] Address: 0x1000 - Name: .bar Type: SHT_PROGBITS Flags: [ SHF_ALLOC, SHF_EXECINSTR ] Address: 0x2000 ``` Both `.foo` and `.bar` share the same starting file offset, but `VA(.foo)` < `VA(PT_LOAD)`, we should not include it into segment. This patch fixes the issue. Differential revision: https://reviews.llvm.org/D77652
-rw-r--r--llvm/test/Object/obj2yaml.test1
-rw-r--r--llvm/test/tools/obj2yaml/program-headers.yaml115
-rw-r--r--llvm/tools/obj2yaml/elf2yaml.cpp16
3 files changed, 127 insertions, 5 deletions
diff --git a/llvm/test/Object/obj2yaml.test b/llvm/test/Object/obj2yaml.test
index a4398fb..a1b0d1e 100644
--- a/llvm/test/Object/obj2yaml.test
+++ b/llvm/test/Object/obj2yaml.test
@@ -664,7 +664,6 @@ Symbols:
# 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 ]
diff --git a/llvm/test/tools/obj2yaml/program-headers.yaml b/llvm/test/tools/obj2yaml/program-headers.yaml
index 5d56487..740d349 100644
--- a/llvm/test/tools/obj2yaml/program-headers.yaml
+++ b/llvm/test/tools/obj2yaml/program-headers.yaml
@@ -574,3 +574,118 @@ Sections:
Flags: [ SHF_ALLOC ]
Size: 0x1
ShOffset: 0x0
+
+## Check how we dump segments which contain empty sections.
+# RUN: yaml2obj --docnum=7 %s -o %t7
+
+## 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 a VA that is outside of the segment, hence we should not include it in 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 the segment's virtual space.
+# RUN: llvm-readelf -sections %t7 | FileCheck %s --check-prefix=ZERO-SIZE-MAPPING
+
+# ZERO-SIZE-MAPPING: Section Headers:
+# ZERO-SIZE-MAPPING-NEXT: [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 %t7 | 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: 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
+
+## Check how we dump a segment when we have sections that are outside of the virtual
+## address space of a segment, but inside its file space. We do not include such sections
+## in a segment when they are at the edges of a segment, because this is a normal case and
+## it may mean they belong to a different segment.
+# RUN: yaml2obj --docnum=8 %s -o %t8
+# RUN: obj2yaml %t8 | FileCheck %s --check-prefix=BROKEN-VA
+
+# BROKEN-VA: ProgramHeaders:
+# BROKEN-VA-NEXT: - Type: PT_LOAD
+# BROKEN-VA-NEXT: Flags: [ PF_W, PF_R ]
+# BROKEN-VA-NEXT: Sections:
+# BROKEN-VA-NEXT: - Section: .empty_middle
+# BROKEN-VA-NEXT: VAddr: 0x0000000000001000
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_W, PF_R ]
+ VAddr: 0x1000
+ Sections:
+ - Section: .empty_begin
+ - Section: .empty_middle
+ - Section: .empty_end
+Sections:
+ - Name: .empty_begin
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0xFEFEFEFE
+ - Type: Fill
+ Pattern: "00"
+ Size: 1
+ Name: begin
+ - Name: .empty_middle
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0xFEFEFEFE
+ - Type: Fill
+ Pattern: "00"
+ Size: 1
+ - Name: .empty_end
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0xFEFEFEFE
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index c145142..fe3f36f 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -305,17 +305,25 @@ static bool isInSegment(const ELFYAML::Section &Sec,
SHdr.sh_offset >= Phdr.p_offset &&
(SHdr.sh_offset + SHdr.sh_size <= Phdr.p_offset + Phdr.p_filesz);
- if (FileOffsetsMatch)
+ bool VirtualAddressesMatch = SHdr.sh_addr >= Phdr.p_vaddr &&
+ SHdr.sh_addr <= Phdr.p_vaddr + Phdr.p_memsz;
+
+ if (FileOffsetsMatch) {
+ // An empty section on the edges of a program header can be outside of the
+ // virtual address space of the segment. This means it is not included in
+ // the segment and we should ignore it.
+ if (SHdr.sh_size == 0 && (SHdr.sh_offset == Phdr.p_offset ||
+ SHdr.sh_offset == Phdr.p_offset + Phdr.p_filesz))
+ return VirtualAddressesMatch;
return true;
+ }
// SHT_NOBITS sections usually occupy no physical space in a file. Such
// sections belong to a segment when they reside in the segment's virtual
// address space.
if (Sec.Type != ELF::SHT_NOBITS)
return false;
-
- return SHdr.sh_addr >= Phdr.p_vaddr &&
- SHdr.sh_addr <= Phdr.p_vaddr + Phdr.p_memsz;
+ return VirtualAddressesMatch;
}
template <class ELFT>