[llvm] 275bed8 - [llvm-readelf/obj] - Change the return type of the `createDRI(...)` to `Expected<>`

Georgii Rymar via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 25 02:19:43 PDT 2020


Author: Georgii Rymar
Date: 2020-08-25T12:11:26+03:00
New Revision: 275bed899e96e384e90ad5e9874171aa86412f65

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

LOG: [llvm-readelf/obj] - Change the return type of the `createDRI(...)` to `Expected<>`

This allows to get rid of "Invalid data was encountered while parsing the file"
error reported in cases when sh_size/sh_offset of sections are broken.

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

Added: 
    

Modified: 
    llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test
    llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
    llvm/tools/llvm-readobj/ELFDumper.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test b/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test
index 7cf34452a574..f57b21cb6e97 100644
--- a/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test
+++ b/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test
@@ -458,8 +458,8 @@ Sections:
       - Tag:   DT_NULL
         Value: 0
 
-## Check we report a warning when the DT_STRSZ value is broken so that the dynamic string
-## table goes past the end of the file. Document we stop dumping symbols and report an error.
+## Case 10: Check we report a warning when the DT_STRSZ value is broken so that the dynamic string
+##          table goes past the end of the file. Document we stop dumping symbols and report an error.
 
 # RUN: yaml2obj %s --docnum=13 -o %t14
 # RUN: llvm-readobj --dyn-symbols %t14 2>&1 | \
@@ -539,17 +539,19 @@ ProgramHeaders:
       - Section: .dynstr
       - Section: .dynamic
 
-## Check we report a warning when the entry size of the dynamic symbol table is zero.
-# RUN: yaml2obj %s --docnum=14 -o %t15
-# RUN: llvm-readobj --dyn-symbols %t15 2>&1 | FileCheck %s -DFILE=%t15 --check-prefix=DYNSYM-ZERO-ENTSIZE-LLVM
-# RUN: llvm-readelf --dyn-symbols %t15 2>&1 | \
-# RUN:   FileCheck %s -DFILE=%t15 --check-prefix=DYNSYM-ZERO-ENTSIZE-GNU --implicit-check-not="Symbol table"
+## Case 11: check various warnings we report when fields of the SHT_DYNSYM section are broken.
+
+## a) check we report a warning when the entry size of the dynamic symbol table is zero.
+# RUN: yaml2obj %s --docnum=14 -DENTSIZE=0x0 -o %t15.entsize
+# RUN: llvm-readobj --dyn-symbols %t15.entsize 2>&1 | FileCheck %s -DFILE=%t15.entsize --check-prefix=DYNSYM-ZERO-ENTSIZE-LLVM
+# RUN: llvm-readelf --dyn-symbols %t15.entsize 2>&1 | \
+# RUN:   FileCheck %s -DFILE=%t15.entsize --check-prefix=DYNSYM-ZERO-ENTSIZE-GNU --implicit-check-not="Symbol table"
 
 # DYNSYM-ZERO-ENTSIZE-LLVM:      DynamicSymbols [
-# DYNSYM-ZERO-ENTSIZE-LLVM-NEXT:  warning: '[[FILE]]': SHT_DYNSYM section with index 1 has invalid size (0x10) or entry size (0x0)
+# DYNSYM-ZERO-ENTSIZE-LLVM-NEXT:  warning: '[[FILE]]': SHT_DYNSYM section with index 1 has invalid size (0x20) or entry size (0x0)
 # DYNSYM-ZERO-ENTSIZE-LLVM-NEXT: ]
 
-# DYNSYM-ZERO-ENTSIZE-GNU:  warning: '[[FILE]]': SHT_DYNSYM section with index 1 has invalid size (0x10) or entry size (0x0)
+# DYNSYM-ZERO-ENTSIZE-GNU:  warning: '[[FILE]]': SHT_DYNSYM section with index 1 has invalid size (0x20) or entry size (0x0)
 
 --- !ELF
 FileHeader:
@@ -557,6 +559,38 @@ FileHeader:
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
-  - Name:    .dynsym
-    Type:    SHT_DYNSYM
-    EntSize: 0x0
+  - Name:     .dynsym
+    Type:     SHT_DYNSYM
+    EntSize:  [[ENTSIZE=<none>]]
+    ShOffset: [[OFFSET=<none>]]
+    ShSize:   [[SIZE=<none>]]
+DynamicSymbols:
+  - Name: foo
+
+## b) check we report a warning when the sh_offset field of the SHT_DYNSYM section is
+##    invalid (sh_offset + sh_size is greater than the file size). Check we don't dump
+##    dynamic symbols in this case.
+# RUN: yaml2obj --docnum=14 %s -DOFFSET=0xffffffff -o %t15.offset
+# RUN: llvm-readobj %t15.offset --dyn-symbols 2>&1 | FileCheck %s -DFILE=%t15.offset \
+# RUN:   --check-prefixes=OFFSET-BROKEN,OFFSET-BROKEN-LLVM
+# RUN: llvm-readelf %t15.offset --dyn-symbols 2>&1 | FileCheck %s -DFILE=%t15.offset \
+# RUN:   --implicit-check-not="Symbol table" --check-prefix=OFFSET-BROKEN
+
+# OFFSET-BROKEN: warning: '[[FILE]]': unable to read dynamic symbols from SHT_DYNSYM section with index 1: offset (0xffffffff) + size (0x20) is greater than the file size (0x148)
+
+# OFFSET-BROKEN-LLVM:      DynamicSymbols [
+# OFFSET-BROKEN-LLVM-NEXT: ]
+
+## c) check we report a warning when the sh_size field of the SHT_DYNSYM section is
+##    invalid (sh_offset + sh_size is greater than the file size). Check we don't dump
+##    dynamic symbols in this case.
+# RUN: yaml2obj --docnum=14 %s -DSIZE=0xffffffff -o %t15.size
+# RUN: llvm-readobj %t15.size --dyn-symbols 2>&1 | FileCheck %s -DFILE=%t15.size \
+# RUN:   --check-prefixes=SIZE-BROKEN,SIZE-BROKEN-LLVM
+# RUN: llvm-readelf %t15.size --dyn-symbols 2>&1 | FileCheck %s -DFILE=%t15.size \
+# RUN:   --implicit-check-not="Symbol table" --check-prefix=SIZE-BROKEN
+
+# SIZE-BROKEN: warning: '[[FILE]]': unable to read dynamic symbols from SHT_DYNSYM section with index 1: offset (0x34) + size (0xffffffff) is greater than the file size (0x148)
+
+# SIZE-BROKEN-LLVM:      DynamicSymbols [
+# SIZE-BROKEN-LLVM-NEXT: ]

diff  --git a/llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test b/llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
index b7a44a7bc0f7..4c22b318432c 100644
--- a/llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
+++ b/llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
@@ -33,14 +33,16 @@
 ## Case B: Test case where the offset of the PT_DYNAMIC header is too large to be in the file.
 
 ## Case B.1: the section header table is present in the object. Check that we report a warning about the
-##           broken PT_DYNAMIC header, but document that we do not dump the dynamic table, because
-##           return an error earlier.
+##           broken PT_DYNAMIC header. Check we also report a warning about broken fields of the SHT_DYNAMIC section.
 # RUN: yaml2obj %s -DOFFSET=0x1131 -o %t2
-# RUN: not llvm-readobj %t2 --dynamic-table 2>&1 | FileCheck -DFILE=%t2 %s --check-prefix=WARN2
-# RUN: not llvm-readelf %t2 --dynamic-table 2>&1 | FileCheck -DFILE=%t2 %s --check-prefix=WARN2
+# RUN: llvm-readobj %t2 --dynamic-table 2>&1 | FileCheck -DFILE=%t2 %s \
+# RUN:   --check-prefix=WARN2 --implicit-check-not=warning:
+# RUN: llvm-readelf %t2 --dynamic-table 2>&1 | FileCheck -DFILE=%t2 %s \
+# RUN:   --check-prefix=WARN2 --implicit-check-not=warning:
 
 # WARN2: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x1131) + file size (0x10) exceeds the size of the file (0x1130)
-# WARN2: error: '[[FILE]]': Invalid data was encountered while parsing the file
+# WARN2: warning: '[[FILE]]': unable to read the dynamic table from SHT_DYNAMIC section with index 1: offset (0x1131) + size (0x10) is greater than the file size (0x1130)
+# WARN2: warning: '[[FILE]]': no valid dynamic table was found
 
 ## Case B.2: in this case we drop section headers. The dynamic table is not dumped.
 # RUN: yaml2obj %s -DOFFSET=0x1119 -DNOHEADERS=true -o %t2.noheaders
@@ -52,14 +54,18 @@
 # WARN2-NOHEADERS: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x1119) + file size (0x10) exceeds the size of the file (0x1118)
 
 ## Case C: test we report a warning when the offset + the file size of the PT_DYNAMIC is so large a
-##         value that it overflows the platform address size type.
+##         value that it overflows the platform address size type. Check we also report a warning about
+##         broken fields of the SHT_DYNAMIC section.
 
 # RUN: yaml2obj %s -DOFFSET=0xffffffffffffffff -o %t3
-# RUN: not llvm-readobj %t3 --dynamic-table 2>&1 | FileCheck -DFILE=%t3 %s --check-prefix=WARN3
-# RUN: not llvm-readelf %t3 --dynamic-table 2>&1 | FileCheck -DFILE=%t3 %s --check-prefix=WARN3
+# RUN: llvm-readobj %t3 --dynamic-table 2>&1 | FileCheck -DFILE=%t3 %s \
+# RUN:   --check-prefix=WARN3 --implicit-check-not=warning:
+# RUN: llvm-readelf %t3 --dynamic-table 2>&1 | FileCheck -DFILE=%t3 %s \
+# RUN:   --check-prefix=WARN3 --implicit-check-not=warning:
 
 # WARN3: warning: '[[FILE]]': PT_DYNAMIC segment offset (0xffffffffffffffff) + file size (0x10) exceeds the size of the file (0x1130)
-# WARN3: error:   '[[FILE]]': Invalid data was encountered while parsing the file
+# WARN3: warning: '[[FILE]]': unable to read the dynamic table from SHT_DYNAMIC section with index 1: offset (0xffffffffffffffff) + size (0x10) is greater than the file size (0x1130)
+# WARN3: warning: '[[FILE]]': no valid dynamic table was found
 
 # RUN: yaml2obj %s -DNOHEADERS=true -DOFFSET=0xffffffffffffffff -o %t3.noheaders
 # RUN: llvm-readobj %t3.noheaders --dynamic-table 2>&1 | \
@@ -86,11 +92,14 @@
 ## Case D: the same as "Case C", but for a 32-bit object.
 
 # RUN: yaml2obj %s -DBITS=32 -DOFFSET=0xffffffff -o %t5
-# RUN: not llvm-readobj %t5 --dynamic-table 2>&1 | FileCheck -DFILE=%t5 %s --check-prefix=WARN5
-# RUN: not llvm-readelf %t5 --dynamic-table 2>&1 | FileCheck -DFILE=%t5 %s --check-prefix=WARN5
+# RUN: llvm-readobj %t5 --dynamic-table 2>&1 | FileCheck -DFILE=%t5 %s \
+# RUN:   --check-prefix=WARN5 --implicit-check-not=warning:
+# RUN: llvm-readelf %t5 --dynamic-table 2>&1 | FileCheck -DFILE=%t5 %s \
+# RUN:   --check-prefix=WARN5 --implicit-check-not=warning:
 
 # WARN5: warning: '[[FILE]]': PT_DYNAMIC segment offset (0xffffffff) + file size (0x8) exceeds the size of the file (0x10c8)
-# WARN5: error:   '[[FILE]]': Invalid data was encountered while parsing the file
+# WARN5: warning: '[[FILE]]': unable to read the dynamic table from SHT_DYNAMIC section with index 1: offset (0xffffffff) + size (0x8) is greater than the file size (0x10c8)
+# WARN5: warning: '[[FILE]]': no valid dynamic table was found
 
 # RUN: yaml2obj %s -DNOHEADERS=true -DBITS=32 -DOFFSET=0xffffffff -o %t5.noheaders
 # RUN: llvm-readobj %t5.noheaders --dynamic-table 2>&1 | \

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 23c58678a4a2..748cd77bd71d 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -243,12 +243,16 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
 
   TYPEDEF_ELF_TYPES(ELFT)
 
-  DynRegionInfo createDRI(uint64_t Offset, uint64_t Size, uint64_t EntSize) {
+  Expected<DynRegionInfo> createDRI(uint64_t Offset, uint64_t Size,
+                                    uint64_t EntSize) {
     const ELFFile<ELFT> *Obj = ObjF->getELFFile();
     if (Offset + Size < Offset || Offset + Size > Obj->getBufSize())
-      reportError(errorCodeToError(llvm::object::object_error::parse_failed),
-                  ObjF->getFileName());
-    return {Obj->base() + Offset, Size, EntSize, ObjF->getFileName()};
+      return createError("offset (0x" + Twine::utohexstr(Offset) +
+                         ") + size (0x" + Twine::utohexstr(Size) +
+                         ") is greater than the file size (0x" +
+                         Twine::utohexstr(Obj->getBufSize()) + ")");
+    return DynRegionInfo(Obj->base() + Offset, Size, EntSize,
+                         ObjF->getFileName());
   }
 
   void printAttributes();
@@ -1925,11 +1929,12 @@ void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) {
   DynRegionInfo FromPhdr(ObjF->getFileName());
   bool IsPhdrTableValid = false;
   if (DynamicPhdr) {
-    FromPhdr = createDRI(DynamicPhdr->p_offset, DynamicPhdr->p_filesz,
-                         sizeof(Elf_Dyn));
+    // Use cantFail(), because p_offset/p_filesz fields of a PT_DYNAMIC are
+    // validated in findDynamic() and so createDRI() is not expected to fail.
+    FromPhdr = cantFail(createDRI(DynamicPhdr->p_offset, DynamicPhdr->p_filesz,
+                                  sizeof(Elf_Dyn)));
     FromPhdr.SizePrintName = "PT_DYNAMIC size";
     FromPhdr.EntSizePrintName = "";
-
     IsPhdrTableValid = !FromPhdr.getAsArrayRef<Elf_Dyn>().empty();
   }
 
@@ -1940,12 +1945,18 @@ void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) {
   DynRegionInfo FromSec(ObjF->getFileName());
   bool IsSecTableValid = false;
   if (DynamicSec) {
-    FromSec =
+    Expected<DynRegionInfo> RegOrErr =
         createDRI(DynamicSec->sh_offset, DynamicSec->sh_size, sizeof(Elf_Dyn));
-    FromSec.Context = describe(*DynamicSec);
-    FromSec.EntSizePrintName = "";
-
-    IsSecTableValid = !FromSec.getAsArrayRef<Elf_Dyn>().empty();
+    if (RegOrErr) {
+      FromSec = *RegOrErr;
+      FromSec.Context = describe(*DynamicSec);
+      FromSec.EntSizePrintName = "";
+      IsSecTableValid = !FromSec.getAsArrayRef<Elf_Dyn>().empty();
+    } else {
+      reportUniqueWarning(createError("unable to read the dynamic table from " +
+                                      describe(*DynamicSec) + ": " +
+                                      toString(RegOrErr.takeError())));
+    }
   }
 
   // When we only have information from one of the SHT_DYNAMIC section header or
@@ -2029,13 +2040,21 @@ ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> *ObjF,
         DotDynsymSec = &Sec;
 
       if (!DynSymRegion) {
-        DynSymRegion = createDRI(Sec.sh_offset, Sec.sh_size, Sec.sh_entsize);
-        DynSymRegion->Context = describe(Sec);
-
-        if (Expected<StringRef> E = Obj->getStringTableForSymtab(Sec))
-          DynamicStringTable = *E;
-        else
-          reportWarning(E.takeError(), ObjF->getFileName());
+        Expected<DynRegionInfo> RegOrErr =
+            createDRI(Sec.sh_offset, Sec.sh_size, Sec.sh_entsize);
+        if (RegOrErr) {
+          DynSymRegion = *RegOrErr;
+          DynSymRegion->Context = describe(Sec);
+
+          if (Expected<StringRef> E = Obj->getStringTableForSymtab(Sec))
+            DynamicStringTable = *E;
+          else
+            reportWarning(E.takeError(), ObjF->getFileName());
+        } else {
+          reportUniqueWarning(createError(
+              "unable to read dynamic symbols from " + describe(Sec) + ": " +
+              toString(RegOrErr.takeError())));
+        }
       }
       break;
     case ELF::SHT_SYMTAB_SHNDX:


        


More information about the llvm-commits mailing list