[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