[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