[llvm] 2bf5674 - [yaml2obj] - Program headers: add an additional check for `Offset`

Georgii Rymar via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 22 02:55:54 PDT 2020


Author: Georgii Rymar
Date: 2020-04-22T12:49:05+03:00
New Revision: 2bf56743172c536b201a6f68b497694253236bd4

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

LOG: [yaml2obj] - Program headers: add an additional check for `Offset`

The `Offset` field is used to set the file offset of a program header.
In a normal object it should not be greater than the minimal offset
of sections included into segment.

This patch adds a check for that and adds tests.

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

Added: 
    

Modified: 
    llvm/lib/ObjectYAML/ELFEmitter.cpp
    llvm/test/Object/invalid.test
    llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test
    llvm/test/tools/llvm-readobj/ELF/gnu-notes.test
    llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml

Removed: 
    


################################################################################
diff  --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 450856daa874..c32c42b795e7 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -759,12 +759,16 @@ void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
       reportError("sections in the program header with index " +
                   Twine(PhdrIdx) + " are not sorted by their file offset");
 
-    if (YamlPhdr.Offset)
-      PHeader.p_offset = *YamlPhdr.Offset;
-    else if (!Fragments.empty())
-      PHeader.p_offset = Fragments.front().Offset;
-    else
-      PHeader.p_offset = 0;
+    uint64_t PhdrFileOffset = Fragments.empty() ? 0 : Fragments.front().Offset;
+    if (YamlPhdr.Offset) {
+      if (!Fragments.empty() && *YamlPhdr.Offset > PhdrFileOffset)
+        reportError("'Offset' for segment with index " + Twine(PhdrIdx) +
+                    " must be less than or equal to the minimum file offset of "
+                    "all included sections (0x" +
+                    Twine::utohexstr(PhdrFileOffset) + ")");
+      PhdrFileOffset = *YamlPhdr.Offset;
+    }
+    PHeader.p_offset = PhdrFileOffset;
 
     // Find the maximum offset of the end of a section in order to set p_filesz
     // and p_memsz. When setting p_filesz, trailing SHT_NOBITS sections are not

diff  --git a/llvm/test/Object/invalid.test b/llvm/test/Object/invalid.test
index 3a1ef2b3318c..a7363abcace0 100644
--- a/llvm/test/Object/invalid.test
+++ b/llvm/test/Object/invalid.test
@@ -485,17 +485,9 @@ FileHeader:
   Data:    ELFDATA2LSB
   Type:    ET_EXEC
   Machine: EM_X86_64
-Sections:
-  - Name: .dynamic
-    Type: SHT_DYNAMIC
-    Entries:
-      - Tag:   DT_NULL
-        Value: 0
 ProgramHeaders:
   - Type:   PT_DYNAMIC
     Offset: 0xffff0000
-    Sections:
-      - Section: .dynamic
 
 ## PT_DYNAMIC's p_filesz field is so large that p_offset + p_filesz is larger
 ## than the object size. Check llvm-readobj reports it.

diff  --git a/llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test b/llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test
index b2f746e04200..db6b59189fb0 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test
@@ -33,13 +33,7 @@ FileHeader:
   Data:    ELFDATA2LSB
   Type:    ET_EXEC
   Machine: EM_X86_64
-Sections:
-  - Name: .foo
-    Type: SHT_PROGBITS
-    Size: 1
 ProgramHeaders:
-  - Type:        PT_LOAD
-    Offset:      0x100000
-    FileSize:    1
-    Sections:
-      - Section: .foo
+  - Type:     PT_LOAD
+    Offset:   0x100000
+    FileSize: 1

diff  --git a/llvm/test/tools/llvm-readobj/ELF/gnu-notes.test b/llvm/test/tools/llvm-readobj/ELF/gnu-notes.test
index cb4ea1da48f7..366d435e8e48 100644
--- a/llvm/test/tools/llvm-readobj/ELF/gnu-notes.test
+++ b/llvm/test/tools/llvm-readobj/ELF/gnu-notes.test
@@ -165,15 +165,9 @@ FileHeader:
   Data:    ELFDATA2LSB
   Type:    ET_CORE
   Machine: EM_X86_64
-Sections:
-  - Name:  .note
-    Type:  SHT_NOTE
-    Notes: []
 ProgramHeaders:
-  - Type: PT_NOTE
+  - Type:   PT_NOTE
     Offset: 0xffff0000
-    Sections:
-      - Section: .note
 
 ## Test tools report an error if a note program header has an invalid size that
 ## goes past the end of file.

diff  --git a/llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml b/llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml
index a2f727dab5fd..9b16b32e50a5 100644
--- a/llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml
@@ -1,8 +1,8 @@
 ## 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
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: llvm-readobj %t1 --program-headers | FileCheck %s
 
 # CHECK: ProgramHeaders [
 # CHECK:    Offset: 0x1234
@@ -34,7 +34,7 @@
 # CHECK:    MemSize: 6
 # CHECK: ]
 
-!ELF
+--- !ELF
 FileHeader:
   Class:           ELFCLASS64
   Data:            ELFDATA2LSB
@@ -92,13 +92,11 @@ ProgramHeaders:
     MemSize:  9
     Sections:
       - Section: .text
-  # Program header with sections, invalid properties.
+  # Program header with invalid properties.
   - Type:     0x6abcdef0
     Offset:   0x3000
     FileSize: 3
     MemSize:  2
-    Sections:
-      - Section: .data
   # Program header with 2 SHT_NOBITS sections.
   - Type:     0x6abcdef0
     Offset:   0x2004
@@ -106,3 +104,113 @@ ProgramHeaders:
       - Section: .data
       - Section: .nobits1
       - Section: .nobits2
+
+## Test the "Offset" property.
+
+## Check that by default the p_offset field of a segment is set to the
+## offset of the section with the minimum offset.
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: llvm-readelf %t2 --sections --program-headers | \
+# RUN:   FileCheck %s --check-prefixes=DEFAULT-OFFSET
+
+# DEFAULT-OFFSET:      [Nr] Name Type     Address          Off
+# DEFAULT-OFFSET:      [ 1] .foo PROGBITS 0000000000001000 0000b0
+# DEFAULT-OFFSET-NEXT: [ 2] .bar PROGBITS 0000000000001001 0000b1
+
+# DEFAULT-OFFSET:       Type Offset
+# DEFAULT-OFFSET-NEXT:  LOAD 0x0000b0
+# DEFAULT-OFFSET-NEXT:  LOAD 0x0000b1
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:    .foo
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC ]
+    Size:    0x1
+    Address: 0x1000
+  - Name:  .bar
+    Type:  SHT_PROGBITS
+    Flags: [ SHF_ALLOC ]
+    Size:  0x1
+ProgramHeaders:
+  - Type: PT_LOAD
+    Sections:
+      - Section: .foo
+      - Section: .bar
+  - Type: PT_LOAD
+    Sections:
+      - Section: .bar
+
+## Check we can set the "Offset" value explicitly to be less than or equal to
+## the offset of a section in the segment.
+# RUN: yaml2obj --docnum=3 -DOFFSET=0x77 %s -o %t3
+# RUN: llvm-readelf %t3 --sections --program-headers | \
+# RUN:   FileCheck %s --check-prefixes=VALID-OFFSET,VALID-OFFSET-LESS
+# RUN: yaml2obj --docnum=3 -DOFFSET=0x78 %s -o %t4
+# RUN: llvm-readelf %t4 --sections --program-headers | \
+# RUN:   FileCheck %s --check-prefixes=VALID-OFFSET,VALID-OFFSET-EQ
+
+# VALID-OFFSET: [Nr] Name Type     Address          Off
+# VALID-OFFSET: [ 1] .foo PROGBITS 0000000000000000 000078
+
+# VALID-OFFSET:      Type Offset
+# VALID-OFFSET-EQ:   LOAD 0x000078
+# VALID-OFFSET-LESS: LOAD 0x000077
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:  .foo
+    Type:  SHT_PROGBITS
+    Flags: [ SHF_ALLOC ]
+    Size:  0x1
+ProgramHeaders:
+  - Type: PT_LOAD
+    Offset: [[OFFSET]]
+    Sections:
+      - Section: .foo
+
+## Check we report an error when the "Offset" value is larger than the offset of a section in the segment.
+# RUN: not yaml2obj --docnum=3 -DOFFSET=0x79 %s -o /dev/null 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=INVALID-OFFSET
+
+# INVALID-OFFSET: yaml2obj: error: 'Offset' for segment with index 1 must be less than or equal to the minimum file offset of all included sections (0x78)
+
+## Document that the "Offset" value is checked after the section offset is overriden using "ShOffset".
+# RUN: yaml2obj --docnum=4 %s -o %t5
+# RUN: llvm-readelf %t5 --sections --program-headers | FileCheck %s --check-prefix=SHOFFSET
+
+# SHOFFSET: [Nr] Name Type     Address          Off
+# SHOFFSET: [ 1] .foo PROGBITS 0000000000000000 ffffffff
+
+# SHOFFSET:      Type Offset
+# SHOFFSET-NEXT: LOAD 0xffffff00
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:     .foo
+    Type:     SHT_PROGBITS
+    Flags:    [ SHF_ALLOC ]
+    Size:     0x1
+## Note: the real .foo offset is much less than 0xFFFFFFFF or
+##       0xFFFFFF00, but no error is reported.
+    ShOffset: 0xFFFFFFFF
+ProgramHeaders:
+  - Type:   PT_LOAD
+    Offset: 0xFFFFFF00
+    Sections:
+      - Section: .foo


        


More information about the llvm-commits mailing list