[llvm] 0654005 - [llvm-readobj] - Don't crash when dumping invalid dynamic relocation.

Georgii Rymar via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 31 02:21:08 PST 2020


Author: Georgii Rymar
Date: 2020-01-31T13:20:51+03:00
New Revision: 0654005ab2782a1294158ecfddd1337d8be7e3a4

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

LOG: [llvm-readobj] - Don't crash when dumping invalid dynamic relocation.

Currently when we dump dynamic relocation with use of
DT_RELA/DT_RELASZ/DT_RELAENT tags, we crash when a symbol index
is larger than the number of dynamic symbols or
when there is no dynamic symbol table.

This patch adds test cases and fixes the issues.

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

Added: 
    llvm/test/tools/llvm-readobj/ELF/dynamic-reloc-no-section-headers.test

Modified: 
    llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test
    llvm/tools/llvm-readobj/ELFDumper.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test b/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test
index 5f3e4d4de36d..595a680d06bd 100644
--- a/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test
+++ b/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test
@@ -373,3 +373,102 @@ ProgramHeaders:
     Sections:
       - Section: .rela.plt
       - Section: .dynamic
+
+## Show we print a warning when dumping dynamic relocations if there is no dynamic symbol table.
+# RUN: yaml2obj --docnum=11 %s -o %t11
+# RUN: llvm-readobj --dyn-relocations %t11 2>&1 | FileCheck %s -DFILE=%t11 --check-prefix=LLVM-NO-DYNSYM
+# RUN: llvm-readelf --dyn-relocations %t11 2>&1 | FileCheck %s -DFILE=%t11 --check-prefix=GNU-NO-DYNSYM
+
+# LLVM-NO-DYNSYM:      Dynamic Relocations {
+# LLVM-NO-DYNSYM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 0: no dynamic symbol table found
+# LLVM-NO-DYNSYM-NEXT:   0x0 R_X86_64_NONE <corrupt> 0x0
+# LLVM-NO-DYNSYM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 1: no dynamic symbol table found
+# LLVM-NO-DYNSYM-NEXT:   0x0 R_X86_64_NONE <corrupt> 0x0
+# LLVM-NO-DYNSYM-NEXT: }
+
+# GNU-NO-DYNSYM:      'RELA' relocation section at offset 0x78 contains 48 bytes:
+# GNU-NO-DYNSYM-NEXT: Offset            Info             Type             Symbol's Value   Symbol's Name + Addend
+# GNU-NO-DYNSYM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 0: no dynamic symbol table found
+# GNU-NO-DYNSYM-NEXT: 0000000000000000  0000000000000000 R_X86_64_NONE                     <corrupt> + 0
+# GNU-NO-DYNSYM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 1: no dynamic symbol table found
+# GNU-NO-DYNSYM-NEXT: 0000000000000000  0000000100000000 R_X86_64_NONE                     <corrupt> + 0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_X86_64
+Sections:
+  - Name:    .rela.dyn
+    Type:    SHT_RELA
+    Relocations:
+      - Offset: 0x0
+        Type:   R_X86_64_NONE
+      - Offset: 0x0
+        Type:   R_X86_64_NONE
+        Symbol: 0x1
+  - Name: .dynamic
+    Type: SHT_DYNAMIC
+    Entries:
+      - Tag:   DT_RELA
+        Value: 0x0
+      - Tag:   DT_RELASZ
+        Value: 0x30
+      - Tag:   DT_RELAENT
+        Value: 0x18
+      - Tag:   DT_NULL
+        Value: 0x0
+ProgramHeaders:
+  - Type:  PT_LOAD
+    Sections:
+      - Section: .rela.dyn
+      - Section: .dynamic
+
+## Show we print a warning when the symbol index of a dynamic relocation is too
+## large (goes past the end of the dynamic symbol table).
+# RUN: yaml2obj --docnum=12 %s -o %t12
+# RUN: llvm-readobj --dyn-relocations %t12 2>&1 | FileCheck %s -DFILE=%t12 --check-prefix=LLVM-INVALID-DYNSYM
+# RUN: llvm-readelf --dyn-relocations %t12 2>&1 | FileCheck %s -DFILE=%t12 --check-prefix=GNU-INVALID-DYNSYM
+
+# LLVM-INVALID-DYNSYM:      Dynamic Relocations {
+# LLVM-INVALID-DYNSYM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 2: index is greater than or equal to the number of dynamic symbols (2)
+# LLVM-INVALID-DYNSYM-NEXT:   0x0 R_X86_64_NONE <corrupt> 0x0
+# LLVM-INVALID-DYNSYM-NEXT: }
+
+# GNU-INVALID-DYNSYM:      'RELA' relocation section at offset 0x78 contains 24 bytes:
+# GNU-INVALID-DYNSYM-NEXT: Offset            Info             Type             Symbol's Value   Symbol's Name + Addend
+# GNU-INVALID-DYNSYM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 2: index is greater than or equal to the number of dynamic symbols (2)
+# GNU-INVALID-DYNSYM-NEXT: 0000000000000000  0000000200000000 R_X86_64_NONE                     <corrupt> + 0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_X86_64
+Sections:
+  - Name:    .rela.dyn
+    Type:    SHT_RELA
+    Relocations:
+      - Offset: 0x0
+        Type:   R_X86_64_NONE
+        Symbol: 0x2
+  - Name: .dynamic
+    Type: SHT_DYNAMIC
+    Entries:
+      - Tag:   DT_RELA
+        Value: 0x0
+      - Tag:   DT_RELASZ
+        Value: 0x18
+      - Tag:   DT_RELAENT
+        Value: 0x18
+      - Tag:   DT_NULL
+        Value: 0x0
+DynamicSymbols:
+  - Name: foo
+ProgramHeaders:
+  - Type:  PT_LOAD
+    Sections:
+      - Section: .rela.dyn
+      - Section: .dynamic

diff  --git a/llvm/test/tools/llvm-readobj/ELF/dynamic-reloc-no-section-headers.test b/llvm/test/tools/llvm-readobj/ELF/dynamic-reloc-no-section-headers.test
new file mode 100644
index 000000000000..444f4518d7c0
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/dynamic-reloc-no-section-headers.test
@@ -0,0 +1,69 @@
+## Test that we are able to print dynamic relocations with --dyn-relocations
+## even when there are no section headers.
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj --dyn-relocations %t 2>&1 \
+# RUN:  | FileCheck %s -DFILE=%t --implicit-check-not="warning:" --check-prefix=LLVM-NO-SEC-TABLE
+# RUN: llvm-readelf --dyn-relocations %t 2>&1 \
+# RUN:  | FileCheck %s -DFILE=%t --implicit-check-not="warning:" --check-prefix=GNU-NO-SEC-TABLE
+
+# LLVM-NO-SEC-TABLE:      Dynamic Relocations {
+# LLVM-NO-SEC-TABLE-NEXT:   0x0 R_X86_64_NONE foo 0x0
+# LLVM-NO-SEC-TABLE-NEXT: }
+
+# GNU-NO-SEC-TABLE:      'RELA' relocation section at offset 0xb0 contains 24 bytes:
+# GNU-NO-SEC-TABLE-NEXT: Offset            Info             Type             Symbol's Value   Symbol's Name + Addend
+# GNU-NO-SEC-TABLE-NEXT: 0000000000000000  0000000100000000 R_X86_64_NONE    0000000000000000 foo + 0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_X86_64
+## We simulate no section header table by
+## overriding the ELF header properties.
+  SHOff:   0x0
+  SHNum:   0x0
+Sections:
+  - Name:    .rela.dyn
+    Type:    SHT_RELA
+    Relocations:
+      - Offset: 0x0
+        Type:   R_X86_64_NONE
+        Symbol: 0x1
+  - Name: .dynamic
+    Type: SHT_DYNAMIC
+    Entries:
+      - Tag:   DT_RELA
+        Value: 0x0
+      - Tag:   DT_RELASZ
+        Value: 0x18
+      - Tag:   DT_RELAENT
+        Value: 0x18
+## Offset of .dynsym is 0x138. Offset of PT_LOAD is 0xb0.
+## 0x138 - 0xb0 == 0x88
+      - Tag:   DT_SYMTAB
+        Value: 0x88
+      - Tag:   DT_STRSZ
+        Value: 0x5
+## Offset of .dynstr is 0x19f. Offset of PT_LOAD is 0xb0.
+## 0x19f - 0xb0 == 0xef
+      - Tag:   DT_STRTAB
+        Value: 0xef
+      - Tag:   DT_NULL
+        Value: 0x0
+  - Name:    .dynsym
+    Type:    SHT_DYNSYM
+DynamicSymbols:
+  - Name: foo
+ProgramHeaders:
+  - Type:  PT_LOAD
+    Sections:
+      - Section: .rela.dyn
+      - Section: .dynamic
+        Section: .dynsym
+        Section: .dynstr
+  - Type:  PT_DYNAMIC
+    Sections:
+      - Section: .dynamic

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 5671b6cf0f74..5a5c4ca34259 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -4030,21 +4030,35 @@ RelSymbol<ELFT> getSymbolForReloc(const ELFFile<ELFT> *Obj, StringRef FileName,
                                   const ELFDumper<ELFT> *Dumper,
                                   const typename ELFT::Rela &Reloc) {
   uint32_t SymIndex = Reloc.getSymbol(Obj->isMips64EL());
-  const typename ELFT::Sym *Sym = Dumper->dynamic_symbols().begin() + SymIndex;
-  Expected<StringRef> ErrOrName = Sym->getName(Dumper->getDynamicStringTable());
-
-  std::string Name;
-  if (ErrOrName) {
-    Name = maybeDemangle(*ErrOrName);
-  } else {
+  auto WarnAndReturn = [&](const typename ELFT::Sym *Sym,
+                           const Twine &Reason) -> RelSymbol<ELFT> {
     reportWarning(
         createError("unable to get name of the dynamic symbol with index " +
-                    Twine(SymIndex) + ": " + toString(ErrOrName.takeError())),
+                    Twine(SymIndex) + ": " + Reason),
         FileName);
-    Name = "<corrupt>";
-  }
+    return {Sym, "<corrupt>"};
+  };
+
+  ArrayRef<typename ELFT::Sym> Symbols = Dumper->dynamic_symbols();
+  const typename ELFT::Sym *FirstSym = Symbols.begin();
+  if (!FirstSym)
+    return WarnAndReturn(nullptr, "no dynamic symbol table found");
+
+  // We might have an object without a section header. In this case the size of
+  // Symbols is zero, because there is no way to know the size of the dynamic
+  // table. We should allow this case and not print a warning.
+  if (!Symbols.empty() && SymIndex >= Symbols.size())
+    return WarnAndReturn(
+        nullptr,
+        "index is greater than or equal to the number of dynamic symbols (" +
+            Twine(Symbols.size()) + ")");
+
+  const typename ELFT::Sym *Sym = FirstSym + SymIndex;
+  Expected<StringRef> ErrOrName = Sym->getName(Dumper->getDynamicStringTable());
+  if (!ErrOrName)
+    return WarnAndReturn(Sym, toString(ErrOrName.takeError()));
 
-  return {Sym, std::move(Name)};
+  return {Sym, maybeDemangle(*ErrOrName)};
 }
 } // namespace
 


        


More information about the llvm-commits mailing list