diff options
| author | Georgii Rymar <grimar@accesssoftek.com> | 2020-04-07 18:20:51 +0300 |
|---|---|---|
| committer | Georgii Rymar <grimar@accesssoftek.com> | 2020-04-22 12:36:00 +0300 |
| commit | 317c4913c642f8f7fa0fb150fd5e656b59f20a4a (patch) | |
| tree | c80336292de5207367719716e970c8bfa5cdd828 | |
| parent | 0736d1ccf32ba4e6fe860942d8a6d05f964f058e (diff) | |
| download | llvm-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.test | 1 | ||||
| -rw-r--r-- | llvm/test/tools/obj2yaml/program-headers.yaml | 115 | ||||
| -rw-r--r-- | llvm/tools/obj2yaml/elf2yaml.cpp | 16 |
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> |
