]> granicus.if.org Git - llvm/commitdiff
[yaml2obj]Allow explicit setting of p_filesz, p_memsz, and p_offset
authorJames Henderson <jh7370@my.bristol.ac.uk>
Fri, 15 Mar 2019 10:35:27 +0000 (10:35 +0000)
committerJames Henderson <jh7370@my.bristol.ac.uk>
Fri, 15 Mar 2019 10:35:27 +0000 (10:35 +0000)
yaml2obj currently derives the p_filesz, p_memsz, and p_offset values of
program headers from their sections. This makes writing tests for
certain formats more complex, and sometimes impossible. This patch
allows setting these fields explicitly, overriding the default value,
when relevant.

Reviewed by: jakehehrlich, Higuoxing

Differential Revision: https://reviews.llvm.org/D59372

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@356247 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ObjectYAML/ELFYAML.h
lib/ObjectYAML/ELFYAML.cpp
test/tools/yaml2obj/program-header-size-offset.yaml [new file with mode: 0644]
tools/yaml2obj/yaml2elf.cpp

index c7bcfcbb4f42cb8ba80f486e99fa5f3c722bbaee..72c72826c94c3ce231ed3f8cfa7001267dab41b3 100644 (file)
@@ -86,6 +86,9 @@ struct ProgramHeader {
   llvm::yaml::Hex64 VAddr;
   llvm::yaml::Hex64 PAddr;
   Optional<llvm::yaml::Hex64> Align;
+  Optional<llvm::yaml::Hex64> FileSize;
+  Optional<llvm::yaml::Hex64> MemSize;
+  Optional<llvm::yaml::Hex64> Offset;
   std::vector<SectionName> Sections;
 };
 
index c8585bd3b1ed26513d201aabee04a7e0082883c6..818d54cee98eb3a59c4d283d60f175d2e37d5ade 100644 (file)
@@ -819,6 +819,9 @@ void MappingTraits<ELFYAML::ProgramHeader>::mapping(
   IO.mapOptional("VAddr", Phdr.VAddr, Hex64(0));
   IO.mapOptional("PAddr", Phdr.PAddr, Hex64(0));
   IO.mapOptional("Align", Phdr.Align);
+  IO.mapOptional("FileSize", Phdr.FileSize);
+  IO.mapOptional("MemSize", Phdr.MemSize);
+  IO.mapOptional("Offset", Phdr.Offset);
 }
 
 namespace {
diff --git a/test/tools/yaml2obj/program-header-size-offset.yaml b/test/tools/yaml2obj/program-header-size-offset.yaml
new file mode 100644 (file)
index 0000000..53ceee2
--- /dev/null
@@ -0,0 +1,85 @@
+# 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
+
+# CHECK: ProgramHeaders [
+# CHECK:    Offset: 0x1234
+# CHECK:    FileSize: 1111
+# CHECK:    MemSize: 9999
+
+# CHECK:    Offset: 0x2000
+# CHECK:    FileSize: 6
+# CHECK:    MemSize: 6
+
+# CHECK:    Offset: 0x2000
+# CHECK:    FileSize: 4
+# CHECK:    MemSize: 6
+
+# CHECK:    Offset: 0x1FFF
+# CHECK:    FileSize: 5
+# CHECK:    MemSize: 5
+
+# CHECK:    Offset: 0xFFE
+# CHECK:    FileSize: 7
+# CHECK:    MemSize: 9
+
+# CHECK:    Offset: 0x3000
+# CHECK:    FileSize: 3
+# CHECK:    MemSize: 2
+# CHECK: ]
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+Sections:
+  - Name: .text
+    Type: SHT_PROGBITS
+    Size: 4
+    AddressAlign: 0x1000
+  - Name: .rodata
+    Type: SHT_PROGBITS
+    Size: 4
+    AddressAlign: 0x1000
+  - Name: .data
+    Type: SHT_PROGBITS
+    Size: 4
+ProgramHeaders:
+  # Program header with no sections.
+  - Type:     0x6abcdef0 # arbitrary type
+    Offset:   0x1234
+    FileSize: 1111
+    MemSize:  9999
+  # Program header with only file size set.
+  - Type:     0x6abcdef0
+    FileSize: 6
+    Sections:
+      - Section: .rodata
+  # Program header with only mem size set.
+  - Type:     0x6abcdef0
+    MemSize: 6
+    Sections:
+      - Section: .rodata
+  # Program header with only offset set.
+  - Type:     0x6abcdef0
+    Offset:   0x1fff
+    Sections:
+      - Section: .rodata
+  # Program header with sections, valid properties.
+  - Type:     0x6abcdef0
+    Offset:   0xffe
+    FileSize: 7
+    MemSize:  9
+    Sections:
+      - Section: .text
+  # Program header with sections, invalid properties.
+  - Type:     0x6abcdef0
+    Offset:   0x3000
+    FileSize: 3
+    MemSize:  2
+    Sections:
+      - Section: .data
index df4bdb7d2dd8455f58fa249ba44a02905ea9e508..a70b15e49a3f404b08b427e7f4f5106a9686b573 100644 (file)
@@ -397,44 +397,58 @@ void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
   for (auto &YamlPhdr : Doc.ProgramHeaders) {
     auto &PHeader = PHeaders[PhdrIdx++];
 
-    if (YamlPhdr.Sections.size())
-      PHeader.p_offset = UINT32_MAX;
-    else
-      PHeader.p_offset = 0;
-
-    // Find the minimum offset for the program header.
-    for (auto SecName : YamlPhdr.Sections) {
-      uint32_t Index = 0;
-      SN2I.lookup(SecName.Section, Index);
-      const auto &SHeader = SHeaders[Index];
-      PHeader.p_offset = std::min(PHeader.p_offset, SHeader.sh_offset);
+    if (YamlPhdr.Offset) {
+      PHeader.p_offset = *YamlPhdr.Offset;
+    } else {
+      if (YamlPhdr.Sections.size())
+        PHeader.p_offset = UINT32_MAX;
+      else
+        PHeader.p_offset = 0;
+
+      // Find the minimum offset for the program header.
+      for (auto SecName : YamlPhdr.Sections) {
+        uint32_t Index = 0;
+        SN2I.lookup(SecName.Section, Index);
+        const auto &SHeader = SHeaders[Index];
+        PHeader.p_offset = std::min(PHeader.p_offset, SHeader.sh_offset);
+      }
     }
 
-    // Find the maximum offset of the end of a section in order to set p_filesz.
-    PHeader.p_filesz = 0;
-    for (auto SecName : YamlPhdr.Sections) {
-      uint32_t Index = 0;
-      SN2I.lookup(SecName.Section, Index);
-      const auto &SHeader = SHeaders[Index];
-      uint64_t EndOfSection;
-      if (SHeader.sh_type == llvm::ELF::SHT_NOBITS)
-        EndOfSection = SHeader.sh_offset;
-      else
-        EndOfSection = SHeader.sh_offset + SHeader.sh_size;
-      uint64_t EndOfSegment = PHeader.p_offset + PHeader.p_filesz;
-      EndOfSegment = std::max(EndOfSegment, EndOfSection);
-      PHeader.p_filesz = EndOfSegment - PHeader.p_offset;
+    // Find the maximum offset of the end of a section in order to set p_filesz,
+    // if not set explicitly.
+    if (YamlPhdr.FileSize) {
+      PHeader.p_filesz = *YamlPhdr.FileSize;
+    } else {
+      PHeader.p_filesz = 0;
+      for (auto SecName : YamlPhdr.Sections) {
+        uint32_t Index = 0;
+        SN2I.lookup(SecName.Section, Index);
+        const auto &SHeader = SHeaders[Index];
+        uint64_t EndOfSection;
+        if (SHeader.sh_type == llvm::ELF::SHT_NOBITS)
+          EndOfSection = SHeader.sh_offset;
+        else
+          EndOfSection = SHeader.sh_offset + SHeader.sh_size;
+        uint64_t EndOfSegment = PHeader.p_offset + PHeader.p_filesz;
+        EndOfSegment = std::max(EndOfSegment, EndOfSection);
+        PHeader.p_filesz = EndOfSegment - PHeader.p_offset;
+      }
     }
 
-    // Find the memory size by adding the size of sections at the end of the
-    // segment. These should be empty (size of zero) and NOBITS sections.
-    PHeader.p_memsz = PHeader.p_filesz;
-    for (auto SecName : YamlPhdr.Sections) {
-      uint32_t Index = 0;
-      SN2I.lookup(SecName.Section, Index);
-      const auto &SHeader = SHeaders[Index];
-      if (SHeader.sh_offset == PHeader.p_offset + PHeader.p_filesz)
-        PHeader.p_memsz += SHeader.sh_size;
+    // If not set explicitly, find the memory size by adding the size of
+    // sections at the end of the segment. These should be empty (size of zero)
+    // and NOBITS sections.
+    if (YamlPhdr.MemSize) {
+      PHeader.p_memsz = *YamlPhdr.MemSize;
+    } else {
+      PHeader.p_memsz = PHeader.p_filesz;
+      for (auto SecName : YamlPhdr.Sections) {
+        uint32_t Index = 0;
+        SN2I.lookup(SecName.Section, Index);
+        const auto &SHeader = SHeaders[Index];
+        if (SHeader.sh_offset == PHeader.p_offset + PHeader.p_filesz)
+          PHeader.p_memsz += SHeader.sh_size;
+      }
     }
 
     // Set the alignment of the segment to be the same as the maximum alignment