[llvm] b3f13bc - [obj2yaml] - Teach tool to dump program headers.

Georgii Rymar via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 31 08:10:46 PDT 2020


Author: Georgii Rymar
Date: 2020-03-31T18:10:19+03:00
New Revision: b3f13bc165754ba26b93524367521d39deb21073

URL: https://github.com/llvm/llvm-project/commit/b3f13bc165754ba26b93524367521d39deb21073
DIFF: https://github.com/llvm/llvm-project/commit/b3f13bc165754ba26b93524367521d39deb21073.diff

LOG: [obj2yaml] - Teach tool to dump program headers.

Currently obj2yaml does not dump program headers,
this patch teaches it to do that.

Differential revision: https://reviews.llvm.org/D75342

Added: 
    llvm/test/tools/obj2yaml/program-headers.yaml

Modified: 
    llvm/test/Object/obj2yaml.test
    llvm/tools/obj2yaml/elf2yaml.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/Object/obj2yaml.test b/llvm/test/Object/obj2yaml.test
index a5f008ffd238..808e9fa0a34c 100644
--- a/llvm/test/Object/obj2yaml.test
+++ b/llvm/test/Object/obj2yaml.test
@@ -659,6 +659,20 @@ Symbols:
 # ELF-AVR-NEXT:   Type:            ET_EXEC
 # ELF-AVR-NEXT:   Machine:         EM_AVR
 # ELF-AVR-NEXT:   Flags:           [ EF_AVR_ARCH_AVR2 ]
+# ELF-AVR-NEXT: ProgramHeaders:
+# ELF-AVR-NEXT:  - Type:  PT_LOAD
+# 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 ]
+# ELF-AVR-NEXT:    Sections:
+# ELF-AVR-NEXT:     - Section: .data
+# ELF-AVR-NEXT:    VAddr: 0x0000000000800060
+# ELF-AVR-NEXT:    PAddr: 0x0000000000000004
+# ELF-AVR-NEXT:    Align: 0x0000000000000001
 # ELF-AVR-NEXT: Sections:
 # ELF-AVR-NEXT:   - Name:            .text
 # ELF-AVR-NEXT:     Type:            SHT_PROGBITS

diff  --git a/llvm/test/tools/obj2yaml/program-headers.yaml b/llvm/test/tools/obj2yaml/program-headers.yaml
new file mode 100644
index 000000000000..1c784f17b6e5
--- /dev/null
+++ b/llvm/test/tools/obj2yaml/program-headers.yaml
@@ -0,0 +1,421 @@
+## Show that obj2yaml is able to dump program headers.
+
+## Part I. Base check. All simple cases that look OK as a part of a single large test live here.
+
+# RUN: yaml2obj %s -o %t1
+
+## Show the layout of the object before we dump it using obj2yaml.
+## The check is here to make it clear what the layout should look like.
+# RUN: llvm-readelf --segments %t1 | FileCheck %s --check-prefix=SEGMENT-MAPPING
+
+# SEGMENT-MAPPING:      Program Headers:
+# SEGMENT-MAPPING-NEXT:   Type      Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
+# SEGMENT-MAPPING-NEXT:   LOAD      0x000000 0x0000000000000000 0x0000000000000000 0x000281 0x000281 R   0x1000
+# SEGMENT-MAPPING-NEXT:   LOAD      0x000281 0x0000000000001000 0x0000000000001000 0x000010 0x000010 R E 0x1000
+# SEGMENT-MAPPING-NEXT:   LOAD      0x000291 0x0000000000002000 0x0000000000002000 0x000009 0x000009 R   0x1000
+# SEGMENT-MAPPING-NEXT:   LOAD      0x00029a 0x0000000000003ef0 0x0000000000003ef0 0x000011 0x000011 RW  0x1000
+# SEGMENT-MAPPING-NEXT:   DYNAMIC   0x00029a 0x0000000000003ef0 0x0000000000003ef0 0x000010 0x000010 RW  0x8
+# SEGMENT-MAPPING-NEXT:   GNU_RELRO 0x00029a 0x0000000000003ef0 0x0000000000003ef0 0x000010 0x000010 R   0x1
+# SEGMENT-MAPPING-NEXT:   LOAD      0x000000 0x0000000000004000 0x0000000000004000 0x000000 0x000000 R   0x1
+# SEGMENT-MAPPING-NEXT:   LOAD      0x000248 0x00000000000001a0 0x00000000000001a0 0x000020 0x000020 R   0x1
+# SEGMENT-MAPPING-NEXT:   LOAD      0x000248 0x00000000000001a0 0x00000000000001a0 0x000020 0x000020 R   0x1
+# SEGMENT-MAPPING:      Section to Segment mapping:
+# SEGMENT-MAPPING-NEXT:  Segment Sections...
+# SEGMENT-MAPPING-NEXT:   00     .hash .gnu.hash .dynsym .dynstr {{$}}
+# SEGMENT-MAPPING-NEXT:   01     .foo .zed {{$}}
+# SEGMENT-MAPPING-NEXT:   02     .foo .baz {{$}}
+# SEGMENT-MAPPING-NEXT:   03     .dynamic .dynamic.tail {{$}}
+# SEGMENT-MAPPING-NEXT:   04     .dynamic {{$}}
+# SEGMENT-MAPPING-NEXT:   05     .dynamic {{$}}
+# SEGMENT-MAPPING-NEXT:   06{{ *$}}
+# SEGMENT-MAPPING-NEXT:   07     .gnu.hash {{$}}
+# SEGMENT-MAPPING-NEXT:   08     .gnu.hash {{$}}
+# SEGMENT-MAPPING-NEXT:   None   .symtab .strtab .shstrtab {{$}}
+
+## Check that obj2yaml produced a correct program headers description.
+
+# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=YAML
+
+# YAML:      ProgramHeaders:
+# YAML-NEXT:  - Type:  PT_LOAD
+# YAML-NEXT:    Flags: [ PF_R ]
+# YAML-NEXT:    Sections:
+# YAML-NEXT:      - Section: .hash
+# YAML-NEXT:      - Section: .gnu.hash
+# YAML-NEXT:      - Section: .dynsym
+# YAML-NEXT:      - Section: .dynstr
+# YAML-NEXT:    Align: 0x0000000000001000
+# YAML-NEXT:  - Type:  PT_LOAD
+# YAML-NEXT:    Flags: [ PF_X, PF_R ]
+# YAML-NEXT:    Sections:
+# YAML-NEXT:      - Section: .foo
+# YAML-NEXT:      - Section: .zed
+# YAML-NEXT:    VAddr: 0x0000000000001000
+# YAML-NEXT:    Align: 0x0000000000001000
+# YAML-NEXT:  - Type:  PT_LOAD
+# YAML-NEXT:    Flags: [ PF_R ]
+# YAML-NEXT:    Sections:
+# YAML-NEXT:      - Section: '.foo [1]'
+# YAML-NEXT:      - Section: .baz
+# YAML-NEXT:    VAddr: 0x0000000000002000
+# YAML-NEXT:    Align: 0x0000000000001000
+# YAML-NEXT:  - Type:  PT_LOAD
+# YAML-NEXT:    Flags: [ PF_W, PF_R ]
+# YAML-NEXT:    Sections:
+# YAML-NEXT:      - Section: .dynamic
+# YAML-NEXT:      - Section: .dynamic.tail
+# YAML-NEXT:    VAddr: 0x0000000000003EF0
+# YAML-NEXT:    Align: 0x0000000000001000
+# YAML-NEXT:  - Type:  PT_DYNAMIC
+# YAML-NEXT:    Flags: [ PF_W, PF_R ]
+# YAML-NEXT:    Sections:
+# YAML-NEXT:      - Section: .dynamic
+# YAML-NEXT:    VAddr: 0x0000000000003EF0
+# YAML-NEXT:    Align: 0x0000000000000008
+# YAML-NEXT:  - Type:  PT_GNU_RELRO
+# YAML-NEXT:    Flags: [ PF_R ]
+# YAML-NEXT:    Sections:
+# YAML-NEXT:      - Section: .dynamic
+# YAML-NEXT:    VAddr: 0x0000000000003EF0
+# YAML-NEXT:    Align: 0x0000000000000001
+# YAML-NEXT:  - Type:  PT_LOAD
+# YAML-NEXT:    Flags: [ PF_R ]
+# YAML-NEXT:    VAddr: 0x0000000000004000
+# YAML-NEXT:    Align: 0x0000000000000001
+# YAML-NEXT:  - Type:  PT_LOAD
+# YAML-NEXT:    Flags: [ PF_R ]
+# YAML-NEXT:    Sections:
+# YAML-NEXT:      - Section: .gnu.hash
+# YAML-NEXT:    VAddr: 0x00000000000001A0
+# YAML-NEXT:    Align: 0x0000000000000001
+# YAML-NEXT:  - Type:  PT_LOAD
+# YAML-NEXT:    Flags: [ PF_R ]
+# YAML-NEXT:    Sections:
+# YAML-NEXT:      - Section: .gnu.hash
+# YAML-NEXT:    VAddr: 0x00000000000001A0
+# YAML-NEXT:    Align: 0x0000000000000001
+# YAML-NEXT: Sections:
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_X86_64
+ProgramHeaders:
+## Check we can create a PT_LOAD with arbitrary (we used .hash, .gnu.hash)
+## and implicit sections (we use .dynsym, .dynstr). It also checks that the
+## SHT_NULL section at index 0 is not included in the segment.
+  - Type:  PT_LOAD
+    Flags: [ PF_R ]
+    Sections:
+      - Section: .hash
+      - Section: .gnu.hash
+      - Section: .dynsym
+      - Section: .dynstr
+    Align:  0x1000
+    Offset: 0x0
+## Check we can create a PT_LOAD with a 
diff erent set of properties and sections.
+  - Type:  PT_LOAD
+    Flags: [ PF_X, PF_R ]
+    Sections:
+      - Section: .foo
+      - Section: .zed
+    VAddr: 0x1000
+    Align: 0x1000
+## Create a PT_LOAD to demonstate we are able to refer to output sections with the same name.
+  - Type:  PT_LOAD
+    Flags: [ PF_R ]
+    Sections:
+      - Section: '.foo [1]'
+      - Section: .baz
+    VAddr: 0x2000
+    Align: 0x1000
+## Show we can create a writeable PT_LOAD segment and put an arbitrary section into it.
+## Here we test both regular (SHT_PROGBITS) and a special section (SHT_DYNAMIC).
+  - Type:  PT_LOAD
+    Flags: [ PF_W, PF_R ]
+    Sections:
+      - Section: .dynamic
+      - Section: .dynamic.tail
+    VAddr: 0x3EF0
+    Align: 0x1000
+## Show we can create a nested dynamic segment and put a section into it.
+  - Type:  PT_DYNAMIC
+    Flags: [ PF_W, PF_R ]
+    Sections:
+      - Section: .dynamic
+    VAddr: 0x3EF0
+    Align: 0x8
+## Show we can create a relro segment and put a section into it.
+## We used .dynamic here and in tests above to demonstrate that
+## we can place a section in any number of segments.
+  - Type:  PT_GNU_RELRO
+    Flags: [ PF_R ]
+    Sections:
+      - Section: .dynamic
+    VAddr: 0x3EF0
+    Align: 0x1
+## Show we can dump a standalone empty segment.
+  - Type:  PT_LOAD
+    Flags: [ PF_R ]
+    Sections: [ ]
+    VAddr: 0x4000
+    Align: 0x1
+## ELF specification says that loadable segment entries in the
+## program header are sorted by virtual address.
+## Show we can dump an out of order segment.
+  - Type:  PT_LOAD
+    Flags: [ PF_R ]
+    Sections:
+      - Section: .gnu.hash
+    VAddr: 0x1A0
+    Align: 0x1
+## Test we are able to dump duplicated segments.
+## We use a segment that is the same as the previous one for this.
+  - Type:  PT_LOAD
+    Flags: [ PF_R ]
+    Sections:
+      - Section: .gnu.hash
+    VAddr: 0x1A0
+    Align: 0x1
+Sections:
+  - Name:    .hash
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC ]
+    Address: 0x190
+    Size:    0x10
+  - Name:    .gnu.hash
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC ]
+    Address: 0x1A0
+    Size:    0x20
+  - Name:    .dynsym
+    Type:    SHT_DYNSYM
+    Flags:   [ SHF_ALLOC ]
+    Address: 0x1C0
+    Link:    .dynstr
+    EntSize: 0x18
+  - Name:    .dynstr
+    Type:    SHT_STRTAB
+    Flags:   [ SHF_ALLOC ]
+    Address: 0x1D8
+  - Name:    .foo
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address: 0x1000
+    Size:    0x8
+  - Name:    .zed
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address: 0x1008
+    Size:    0x8
+  - Name:    '.foo [1]'
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC ]
+    Address: 0x2000
+    Size:    0x8
+  - Name:    .baz
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC ]
+    Address: 0x2008
+    Size:    0x1
+  - Name:    .dynamic
+    Type:    SHT_DYNAMIC
+    Flags:   [ SHF_WRITE, SHF_ALLOC ]
+    Address: 0x0000000000003EF0
+    Link:    .dynstr
+    Entries:
+      - Tag:   DT_NULL
+        Value: 0x0
+  - Name:    .dynamic.tail
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_WRITE, SHF_ALLOC ]
+    Content: "FE"
+Symbols: []
+DynamicSymbols: []
+
+## Part II. More specific tests.
+
+## Check we are able to dump segments that are empty or
+## contain empty sections.
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=EMPTY
+
+# EMPTY:      - Type:  PT_LOAD
+# EMPTY-NEXT:   Flags: [ PF_W, PF_R ]
+# EMPTY-NEXT:   Sections:
+# EMPTY-NEXT:     - Section: .empty.tls.start
+# EMPTY-NEXT:     - Section: .section.1
+# EMPTY-NEXT:     - Section: .empty.tls.middle
+# EMPTY-NEXT:     - Section: .section.2
+# EMPTY-NEXT:     - Section: .empty.tls.end
+# EMPTY-NEXT:   VAddr: 0x0000000000001000
+# EMPTY-NEXT:   Align: 0x0000000000001000
+# EMPTY-NEXT: - Type:            PT_TLS
+# EMPTY-NEXT:   Flags:           [ PF_W, PF_R ]
+# EMPTY-NEXT:   Sections:
+# EMPTY-NEXT:     - Section:         .empty.tls.start
+# EMPTY-NEXT:   VAddr:           0x0000000000001000
+# EMPTY-NEXT:   Align:           0x0000000000000001
+# EMPTY-NEXT: - Type:            PT_TLS
+# EMPTY-NEXT:   Flags:           [ PF_W, PF_R ]
+# EMPTY-NEXT:   Sections:
+# EMPTY-NEXT:     - Section:         .empty.tls.middle
+# EMPTY-NEXT:   VAddr:           0x0000000000001100
+# EMPTY-NEXT:   Align:           0x0000000000000001
+# EMPTY-NEXT: - Type:            PT_TLS
+# EMPTY-NEXT:   Flags:           [ PF_W, PF_R ]
+# EMPTY-NEXT:   Sections:
+# EMPTY-NEXT:     - Section:         .empty.tls.end
+# EMPTY-NEXT:   VAddr:           0x0000000000001200
+# EMPTY-NEXT:   Align:           0x0000000000000001
+# EMPTY-NEXT: Sections:
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_X86_64
+ProgramHeaders:
+  - Type:  PT_LOAD
+    Flags: [ PF_W, PF_R ]
+    Sections:
+      - Section: .empty.tls.start
+      - Section: .section.1
+      - Section: .empty.tls.middle
+      - Section: .section.2
+      - Section: .empty.tls.end
+    VAddr: 0x1000
+    Align: 0x1000
+  - Type:  PT_TLS
+    Flags: [ PF_W, PF_R ]
+    Sections:
+      - Section: .empty.tls.start
+    VAddr: 0x1000
+    Align: 0x1
+  - Type:  PT_TLS
+    Flags: [ PF_W, PF_R ]
+    Sections:
+      - Section: .empty.tls.middle
+    VAddr: 0x1100
+    Align: 0x1
+  - Type:  PT_TLS
+    Flags: [ PF_W, PF_R ]
+    Sections:
+      - Section: .empty.tls.end
+    VAddr: 0x1200
+    Align: 0x1
+Sections:
+  - Name:    .empty.tls.start
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC, SHF_TLS ]
+    Size:    0x0
+    Address: 0x1000
+  - Name:  .section.1
+    Type:  SHT_PROGBITS
+    Flags: [ SHF_ALLOC ]
+    Size:  0x100
+  - Name:  .empty.tls.middle
+    Type:  SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_TLS ]
+    Size:  0x0
+  - Name:  .section.2
+    Type:  SHT_PROGBITS
+    Flags: [ SHF_ALLOC ]
+    Size:  0x100
+  - Name:  .empty.tls.end
+    Type:  SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_TLS ]
+    Size:  0x0
+
+## Document we are able to dump misaligned segments.
+## I.e. segments where (p_offset % p_align) != (p_vaddr % p_align).
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: llvm-readelf --segments --sections %t3 | FileCheck %s --check-prefix=MISALIGNED-READELF
+# RUN: obj2yaml %t3 | FileCheck %s --check-prefix=MISALIGNED-YAML
+
+## As a misaligned p_offset value we use (`.foo` section offset - 1).
+# MISALIGNED-READELF:      [Nr] Name Type     Address          Off
+# MISALIGNED-READELF:      [ 1] .foo PROGBITS 0000000000001000 000078
+# MISALIGNED-READELF:      Type Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
+# MISALIGNED-READELF-NEXT: LOAD 0x000077 0x0000000000001000 0x0000000000001000 0x000078 0x000078 R   0x1000
+
+# MISALIGNED-YAML:      ProgramHeaders:
+# MISALIGNED-YAML-NEXT:  - Type:  PT_LOAD
+# MISALIGNED-YAML-NEXT:    Flags: [ PF_R ]
+# MISALIGNED-YAML-NEXT:    Sections:
+# MISALIGNED-YAML-NEXT:     - Section: .foo
+# MISALIGNED-YAML-NEXT:    VAddr: 0x0000000000001000
+# MISALIGNED-YAML-NEXT:    Align: 0x0000000000001000
+# MISALIGNED-YAML-NEXT: Sections:
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_X86_64
+ProgramHeaders:
+  - Type:  PT_LOAD
+    Flags: [ PF_R ]
+    Sections:
+      - Section: .foo
+    VAddr:  0x1000
+    Align:  0x1000
+    Offset: 0x000077
+Sections:
+  - Name:    .foo
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC ]
+    Size:    0x77
+    Address: 0x1000
+
+## Test we include non-allocatable sections in segments.
+## We also document that SHT_NULL sections are not considered to be inside a segment.
+# RUN: yaml2obj --docnum=4 %s -o %t4
+# RUN: obj2yaml %t4 | FileCheck %s --check-prefix=NON-ALLOC
+
+# NON-ALLOC:      ProgramHeaders:
+# NON-ALLOC-NEXT:   - Type:  PT_LOAD
+# NON-ALLOC-NEXT:     Flags: [ PF_R ]
+# NON-ALLOC-NEXT:     Sections:
+# NON-ALLOC-NEXT:      - Section: .alloc.1
+# NON-ALLOC-NEXT:      - Section: .non-alloc.1
+# NON-ALLOC-NEXT:      - Section: .alloc.2
+# NON-ALLOC-NEXT:     VAddr: 0x0000000000001000
+# NON-ALLOC-NEXT:     Align: 0x0000000000000001
+# NON-ALLOC-NEXT: Sections:
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_X86_64
+ProgramHeaders:
+  - Type:  PT_LOAD
+    Flags: [ PF_R ]
+    Sections:
+      - Section: .alloc.1
+      - Section: .alloc.2
+    VAddr:  0x1000
+Sections:
+  - Name:    .alloc.1
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC ]
+    Size:    0x100
+    Address: 0x1000
+  - Name:    .non-alloc.1
+    Type:    SHT_PROGBITS
+    Flags:   [ ]
+    Size:    0x10
+  - Name:    .non-alloc.2
+    Type:    SHT_NULL
+    Flags:   [ ]
+    Size:    0x10
+  - Name:    .alloc.2
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC ]
+    Size:    0x1

diff  --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index bf6d9657e76e..464f899352f4 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -51,6 +51,9 @@ class ELFDumper {
   const object::ELFFile<ELFT> &Obj;
   ArrayRef<Elf_Word> ShndxTable;
 
+  Expected<std::vector<ELFYAML::ProgramHeader>>
+  dumpProgramHeaders(ArrayRef<std::unique_ptr<ELFYAML::Chunk>> Sections);
+
   Error dumpSymbols(const Elf_Shdr *Symtab,
                     std::vector<ELFYAML::Symbol> &Symbols);
   Error dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
@@ -271,8 +274,15 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
       dumpSections();
   if (!ChunksOrErr)
     return ChunksOrErr.takeError();
-
   std::vector<std::unique_ptr<ELFYAML::Chunk>> Chunks = std::move(*ChunksOrErr);
+
+  // Dump program headers.
+  Expected<std::vector<ELFYAML::ProgramHeader>> PhdrsOrErr =
+      dumpProgramHeaders(Chunks);
+  if (!PhdrsOrErr)
+    return PhdrsOrErr.takeError();
+  Y->ProgramHeaders = std::move(*PhdrsOrErr);
+
   llvm::erase_if(Chunks, [this](const std::unique_ptr<ELFYAML::Chunk> &C) {
     const ELFYAML::Section &S = cast<ELFYAML::Section>(*C.get());
     return !shouldPrintSection(S, Sections[S.OriginalSecNdx]);
@@ -282,6 +292,48 @@ template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
   return Y.release();
 }
 
+template <class ELFT>
+static bool isInSegment(const ELFYAML::Section &Sec,
+                        const typename ELFT::Shdr &SHdr,
+                        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);
+}
+
+template <class ELFT>
+Expected<std::vector<ELFYAML::ProgramHeader>>
+ELFDumper<ELFT>::dumpProgramHeaders(
+    ArrayRef<std::unique_ptr<ELFYAML::Chunk>> Chunks) {
+  std::vector<ELFYAML::ProgramHeader> Ret;
+  Expected<typename ELFT::PhdrRange> PhdrsOrErr = Obj.program_headers();
+  if (!PhdrsOrErr)
+    return PhdrsOrErr.takeError();
+
+  for (const typename ELFT::Phdr &Phdr : *PhdrsOrErr) {
+    ELFYAML::ProgramHeader PH;
+    PH.Type = Phdr.p_type;
+    PH.Flags = Phdr.p_flags;
+    PH.VAddr = Phdr.p_vaddr;
+    PH.PAddr = Phdr.p_paddr;
+    PH.Align = static_cast<llvm::yaml::Hex64>(Phdr.p_align);
+
+    // Here we match sections with segments.
+    // It is not possible to have a non-Section chunk, because
+    // obj2yaml does not create Fill chunks.
+    for (const std::unique_ptr<ELFYAML::Chunk> &C : Chunks) {
+      ELFYAML::Section &S = cast<ELFYAML::Section>(*C.get());
+      if (isInSegment<ELFT>(S, Sections[S.OriginalSecNdx], Phdr))
+        PH.Sections.push_back({S.Name});
+    }
+
+    Ret.push_back(PH);
+  }
+
+  return Ret;
+}
+
 template <class ELFT>
 Expected<ELFYAML::RawContentSection *>
 ELFDumper<ELFT>::dumpPlaceholderSection(const Elf_Shdr *Shdr) {


        


More information about the llvm-commits mailing list