[llvm-readobj] - Introduce warnings for cases when unable to read strings from string tables.

Currently we have no dedicated warnings, but we return error message instead of a result.
It is generally not consistent with another warnings we have.

This change was suggested and discussed here:
https://reviews.llvm.org/D77216#1954873

This change refines error messages we report and also I had to update the API
to implement it.

Differential revision: https://reviews.llvm.org/D77399
This commit is contained in:
Georgii Rymar 2020-04-02 14:40:07 +03:00
parent e268ec8e0d
commit 7fc599ceb0
4 changed files with 165 additions and 111 deletions

View File

@ -90,26 +90,54 @@ ProgramHeaders:
## Test handling of string references pointing past the end of the dynamic string table.
# RUN: yaml2obj %s --docnum=3 -o %t.bad-string
# RUN: llvm-readobj --dynamic-table %t.bad-string | FileCheck %s --check-prefix BAD-STRING-LLVM
# RUN: llvm-readelf --dynamic-table %t.bad-string | FileCheck %s --check-prefix BAD-STRING-GNU
# RUN: llvm-readobj --dynamic-table %t.bad-string 2>&1 | \
# RUN: FileCheck %s --implicit-check-not=warning: --check-prefix BAD-STRING-LLVM -DFILE=%t.bad-string
# RUN: llvm-readelf --dynamic-table %t.bad-string 2>&1 | \
# RUN: FileCheck %s --implicit-check-not=warning: --check-prefix BAD-STRING-GNU -DFILE=%t.bad-string
# BAD-STRING-LLVM: 0x000000000000000A STRSZ 1 (bytes)
# BAD-STRING-LLVM: 0x0000000000000001 NEEDED Shared library: [<Invalid offset 0x1>]
# BAD-STRING-LLVM: 0x000000007FFFFFFF FILTER Filter library: [<Invalid offset 0x1>]
# BAD-STRING-LLVM: 0x000000007FFFFFFD AUXILIARY Auxiliary library: [<Invalid offset 0x1>]
# BAD-STRING-LLVM: 0x000000007FFFFFFE USED Not needed object: [<Invalid offset 0x1>]
# BAD-STRING-LLVM: 0x000000000000000E SONAME Library soname: [<Invalid offset 0x1>]
# BAD-STRING-LLVM: 0x000000000000000F RPATH Library rpath: [<Invalid offset 0x1>]
# BAD-STRING-LLVM: 0x000000000000001D RUNPATH Library runpath: [<Invalid offset 0x1>]
# BAD-STRING-LLVM: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb6, it goes past the end of the table (0xb1)
# BAD-STRING-LLVM: LoadName: <?>
# BAD-STRING-LLVM: DynamicSection [ (10 entries)
# BAD-STRING-LLVM-NEXT: Tag Type Name/Value
# BAD-STRING-LLVM-NEXT: 0x0000000000000005 STRTAB 0x1000
# BAD-STRING-LLVM-NEXT: 0x000000000000000A STRSZ 1 (bytes)
# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb2, it goes past the end of the table (0xb1)
# BAD-STRING-LLVM-NEXT: 0x0000000000000001 NEEDED Shared library: [<?>]
# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb3, it goes past the end of the table (0xb1)
# BAD-STRING-LLVM-NEXT: 0x000000007FFFFFFF FILTER Filter library: [<?>]
# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb4, it goes past the end of the table (0xb1)
# BAD-STRING-LLVM-NEXT: 0x000000007FFFFFFD AUXILIARY Auxiliary library: [<?>]
# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb5, it goes past the end of the table (0xb1)
# BAD-STRING-LLVM-NEXT: 0x000000007FFFFFFE USED Not needed object: [<?>]
## Note: there is no "string table at offset 0xb0..." warning here, because it was printed earlier.
# BAD-STRING-LLVM-NEXT: 0x000000000000000E SONAME Library soname: [<?>]
# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb7, it goes past the end of the table (0xb1)
# BAD-STRING-LLVM-NEXT: 0x000000000000000F RPATH Library rpath: [<?>]
# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb8, it goes past the end of the table (0xb1)
# BAD-STRING-LLVM-NEXT: 0x000000000000001D RUNPATH Library runpath: [<?>]
# BAD-STRING-LLVM-NEXT: 0x0000000000000000 NULL 0x0
# BAD-STRING-LLVM-NEXT: ]
# BAD-STRING-GNU: 0x000000000000000a (STRSZ) 1 (bytes)
# BAD-STRING-GNU: 0x0000000000000001 (NEEDED) Shared library: [<Invalid offset 0x1>]
# BAD-STRING-GNU: 0x000000007fffffff (FILTER) Filter library: [<Invalid offset 0x1>]
# BAD-STRING-GNU: 0x000000007ffffffd (AUXILIARY) Auxiliary library: [<Invalid offset 0x1>]
# BAD-STRING-GNU: 0x000000007ffffffe (USED) Not needed object: [<Invalid offset 0x1>]
# BAD-STRING-GNU: 0x000000000000000e (SONAME) Library soname: [<Invalid offset 0x1>]
# BAD-STRING-GNU: 0x000000000000000f (RPATH) Library rpath: [<Invalid offset 0x1>]
# BAD-STRING-GNU: 0x000000000000001d (RUNPATH) Library runpath: [<Invalid offset 0x1>]
# BAD-STRING-GNU: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb6, it goes past the end of the table (0xb1)
# BAD-STRING-GNU-NEXT: Dynamic section at offset 0xb1 contains 10 entries:
# BAD-STRING-GNU-NEXT: Tag Type Name/Value
# BAD-STRING-GNU-NEXT: 0x0000000000000005 (STRTAB) 0x1000
# BAD-STRING-GNU-NEXT: 0x000000000000000a (STRSZ) 1 (bytes)
# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb2, it goes past the end of the table (0xb1)
# BAD-STRING-GNU-NEXT: 0x0000000000000001 (NEEDED) Shared library: [<?>]
# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb3, it goes past the end of the table (0xb1)
# BAD-STRING-GNU-NEXT: 0x000000007fffffff (FILTER) Filter library: [<?>]
# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb4, it goes past the end of the table (0xb1)
# BAD-STRING-GNU-NEXT: 0x000000007ffffffd (AUXILIARY) Auxiliary library: [<?>]
# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb5, it goes past the end of the table (0xb1)
# BAD-STRING-GNU-NEXT: 0x000000007ffffffe (USED) Not needed object: [<?>]
## Note: there is no "string table at offset 0xb6..." warning here, because it was printed earlier.
# BAD-STRING-GNU-NEXT: 0x000000000000000e (SONAME) Library soname: [<?>]
# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb7, it goes past the end of the table (0xb1)
# BAD-STRING-GNU-NEXT: 0x000000000000000f (RPATH) Library rpath: [<?>]
# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb8, it goes past the end of the table (0xb1)
# BAD-STRING-GNU-NEXT: 0x000000000000001d (RUNPATH) Library runpath: [<?>]
# BAD-STRING-GNU-NEXT: 0x0000000000000000 (NULL) 0x0
--- !ELF
FileHeader:
@ -130,19 +158,19 @@ Sections:
- Tag: DT_STRSZ
Value: 1
- Tag: DT_NEEDED
Value: 1
Value: 2
- Tag: DT_FILTER
Value: 1
Value: 3
- Tag: DT_AUXILIARY
Value: 1
Value: 4
- Tag: DT_USED
Value: 1
Value: 5
- Tag: DT_SONAME
Value: 1
Value: 6
- Tag: DT_RPATH
Value: 1
Value: 7
- Tag: DT_RUNPATH
Value: 1
Value: 8
- Tag: DT_NULL
Value: 0
Symbols: []
@ -160,17 +188,23 @@ ProgramHeaders:
## Test handling of DT_STRTAB pointing outside the file's address space.
# RUN: yaml2obj %s --docnum=4 -o %t.bad-strtab
# RUN: llvm-readobj --dynamic-table %t.bad-strtab 2>&1 >/dev/null | FileCheck -DFILE=%t.bad-strtab %s --check-prefix BAD-STRTAB-ERR
# RUN: llvm-readelf --dynamic-table %t.bad-strtab 2>&1 >/dev/null | FileCheck -DFILE=%t.bad-strtab %s --check-prefix BAD-STRTAB-ERR
# RUN: llvm-readobj --dynamic-table %t.bad-strtab 2>&1 >/dev/null | \
# RUN: FileCheck -DFILE=%t.bad-strtab %s --check-prefix BAD-STRTAB-ERR
# RUN: llvm-readelf --dynamic-table %t.bad-strtab 2>&1 >/dev/null | \
# RUN: FileCheck -DFILE=%t.bad-strtab %s --check-prefix BAD-STRTAB-ERR
# BAD-STRTAB-ERR: warning: '[[FILE]]': Unable to parse DT_STRTAB: virtual address is not in any segment: 0x2000000
# BAD-STRTAB-ERR: warning: '[[FILE]]': string table was not found
# RUN: llvm-readobj --dynamic-table --needed-libs %t.bad-strtab | FileCheck %s --check-prefixes=BAD-STRTAB,BAD-STRTAB-LLVM
# RUN: llvm-readelf --dynamic-table --needed-libs %t.bad-strtab | FileCheck %s --check-prefixes=BAD-STRTAB,BAD-STRTAB-GNU
# BAD-STRTAB-LLVM: LoadName: <String table is empty or was not found>
# BAD-STRTAB-LLVM: 0x0000000000000001 NEEDED Shared library: [<String table is empty or was not found>]
# BAD-STRTAB-GNU: 0x0000000000000001 (NEEDED) Shared library: [<String table is empty or was not found>]
# RUN: llvm-readobj --dynamic-table --needed-libs %t.bad-strtab 2>&1 | \
# RUN: FileCheck -DFILE=%t.bad-strtab %s --check-prefixes=BAD-STRTAB-ERR,BAD-STRTAB,BAD-STRTAB-LLVM
# RUN: llvm-readelf --dynamic-table --needed-libs %t.bad-strtab 2>&1 | \
# RUN: FileCheck -DFILE=%t.bad-strtab %s --check-prefixes=BAD-STRTAB-ERR,BAD-STRTAB,BAD-STRTAB-GNU
# BAD-STRTAB-LLVM: LoadName: <?>
# BAD-STRTAB-LLVM: 0x0000000000000001 NEEDED Shared library: [<?>]
# BAD-STRTAB-GNU: 0x0000000000000001 (NEEDED) Shared library: [<?>]
# BAD-STRTAB: NeededLibraries [
# BAD-STRTAB: <String table is empty or was not found>
# BAD-STRTAB: <?>
# BAD-STRTAB: ]
--- !ELF

View File

@ -61,5 +61,6 @@ ProgramHeaders:
# RUN: llvm-readelf --dynamic-table %t.err.1.o 2>&1 | FileCheck %s -DFILE=%t.err.1.o --check-prefixes=BROKEN-OFFSET,BROKEN-OFFSET-GNU
# BROKEN-OFFSET: warning: '[[FILE]]': Unable to parse DT_STRTAB: can't map virtual address 0xfffe to the segment with index 1: the segment ends at 0x10077, which is greater than the file size (0x228)
# BROKEN-OFFSET-LLVM: LoadName: <String table is empty or was not found>
# BROKEN-OFFSET-GNU: 0x000000000000000e (SONAME) Library soname: [<String table is empty or was not found>]
# BROKEN-OFFSET: warning: '[[FILE]]': string table was not found
# BROKEN-OFFSET-LLVM: LoadName: <?>
# BROKEN-OFFSET-GNU: 0x000000000000000e (SONAME) Library soname: [<?>]

View File

@ -1,21 +1,23 @@
## In this test we check the --needed-libs option.
# RUN: yaml2obj %s --docnum=1 -o %t1
# RUN: llvm-readobj --needed-libs %t1 \
# RUN: | FileCheck %s --strict-whitespace --match-full-lines --check-prefix=NEEDED-LIBS
# RUN: llvm-readelf --needed-libs %t1 \
# RUN: | FileCheck %s --strict-whitespace --match-full-lines --check-prefix=NEEDED-LIBS
# RUN: llvm-readobj --needed-libs %t1 2>&1 \
# RUN: | FileCheck %s -DFILE=%t1 --implicit-check-not=warning: --strict-whitespace --check-prefix=NEEDED-LIBS
# RUN: llvm-readelf --needed-libs %t1 2>&1 \
# RUN: | FileCheck %s -DFILE=%t1 --implicit-check-not=warning: --strict-whitespace --check-prefix=NEEDED-LIBS
## Check that library names are sorted when printed.
## Document that we also sort error entries.
# NEEDED-LIBS:NeededLibraries [
# NEEDED-LIBS-NEXT: <Invalid offset 0x1111111>
# NEEDED-LIBS-NEXT: <Invalid offset 0x9999999>
# NEEDED-LIBS-NEXT: aaa
# NEEDED-LIBS-NEXT: bbb
# NEEDED-LIBS-NEXT: ccc
# NEEDED-LIBS-NEXT:]
# NEEDED-LIBS:{{^}}NeededLibraries [{{$}}
# NEEDED-LIBS-NEXT: warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x9999a11, it goes past the end of the table (0x85){{$}}
# NEEDED-LIBS-NEXT: warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x1111189, it goes past the end of the table (0x85){{$}}
# NEEDED-LIBS-NEXT:{{^}} <?>{{$}}
# NEEDED-LIBS-NEXT:{{^}} <?>{{$}}
# NEEDED-LIBS-NEXT:{{^}} aaa{{$}}
# NEEDED-LIBS-NEXT:{{^}} bbb{{$}}
# NEEDED-LIBS-NEXT:{{^}} ccc{{$}}
# NEEDED-LIBS-NEXT:{{^}}]{{$}}
--- !ELF
FileHeader:
@ -56,11 +58,18 @@ ProgramHeaders:
## Check what we print when the dynamic string table is empty.
# RUN: yaml2obj %s --docnum=2 -o %t2
# RUN: llvm-readobj --needed-libs %t2 | FileCheck %s --check-prefix=EMPTY-DYNSTR
# RUN: llvm-readelf --needed-libs %t2 | FileCheck %s --check-prefix=EMPTY-DYNSTR
# RUN: llvm-readobj --needed-libs %t2 2>&1 | \
# RUN: FileCheck %s -DFILE=%t2 --implicit-check-not=warning: --check-prefixes=EMPTY-DYNSTR,EMPTY-DYNSTR-LLVM
# RUN: llvm-readelf --needed-libs %t2 2>&1 | \
# RUN: FileCheck %s -DFILE=%t2 --implicit-check-not=warning: --check-prefix=EMPTY-DYNSTR
# EMPTY-DYNSTR: warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x78, it goes past the end of the table (0x78)
# EMPTY-DYNSTR-LLVM: LoadName: <?>
# EMPTY-DYNSTR: NeededLibraries [
# EMPTY-DYNSTR-NEXT: <String table is empty or was not found>
# EMPTY-DYNSTR-NEXT: warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x79, it goes past the end of the table (0x78)
# EMPTY-DYNSTR-NEXT: warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x7a, it goes past the end of the table (0x78)
# EMPTY-DYNSTR-NEXT: <?>
# EMPTY-DYNSTR-NEXT: <?>
# EMPTY-DYNSTR-NEXT: ]
--- !ELF
@ -82,6 +91,8 @@ Sections:
Value: 0x0000000000000000
- Tag: DT_NEEDED
Value: 1
- Tag: DT_NEEDED
Value: 2
- Tag: DT_STRSZ
Value: 0x0
- Tag: DT_NULL

View File

@ -288,7 +288,7 @@ private:
Optional<DynRegionInfo> DynSymRegion;
DynRegionInfo DynamicTable;
StringRef DynamicStringTable;
std::string SOName = "<Not found>";
StringRef SOName = "<Not found>";
const Elf_Hash *HashTable = nullptr;
const Elf_GnuHash *GnuHashTable = nullptr;
const Elf_Shdr *DotSymtabSec = nullptr;
@ -341,12 +341,12 @@ public:
Expected<StringRef> getSymbolSectionName(const Elf_Sym *Symbol,
unsigned SectionIndex) const;
Expected<std::string> getStaticSymbolName(uint32_t Index) const;
std::string getDynamicString(uint64_t Value) const;
StringRef getDynamicString(uint64_t Value) const;
Expected<StringRef> getSymbolVersionByIndex(uint32_t VersionSymbolIndex,
bool &IsDefault) const;
void printSymbolsHelper(bool IsDynamic) const;
void printDynamicEntry(raw_ostream &OS, uint64_t Type, uint64_t Value) const;
std::string getDynamicEntry(uint64_t Type, uint64_t Value) const;
const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; }
@ -2387,10 +2387,24 @@ void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) {
}
template <class ELFT>
void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
uint64_t Value) const {
const char *ConvChar =
(opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64;
std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type,
uint64_t Value) const {
auto FormatHexValue = [](uint64_t V) {
std::string Str;
raw_string_ostream OS(Str);
const char *ConvChar =
(opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64;
OS << format(ConvChar, V);
return OS.str();
};
auto FormatFlags = [](uint64_t V,
llvm::ArrayRef<llvm::EnumEntry<unsigned int>> Array) {
std::string Str;
raw_string_ostream OS(Str);
printFlags(V, Array, OS);
return OS.str();
};
// Handle custom printing of architecture specific tags
switch (ObjF->getELFFile()->getHeader()->e_machine) {
@ -2398,8 +2412,7 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
switch (Type) {
case DT_AARCH64_BTI_PLT:
case DT_AARCH64_PAC_PLT:
OS << Value;
return;
return std::to_string(Value);
default:
break;
}
@ -2407,12 +2420,10 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
case EM_HEXAGON:
switch (Type) {
case DT_HEXAGON_VER:
OS << Value;
return;
return std::to_string(Value);
case DT_HEXAGON_SYMSZ:
case DT_HEXAGON_PLT:
OS << format(ConvChar, Value);
return;
return FormatHexValue(Value);
default:
break;
}
@ -2423,8 +2434,7 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
case DT_MIPS_LOCAL_GOTNO:
case DT_MIPS_SYMTABNO:
case DT_MIPS_UNREFEXTNO:
OS << Value;
return;
return std::to_string(Value);
case DT_MIPS_TIME_STAMP:
case DT_MIPS_ICHECKSUM:
case DT_MIPS_IVERSION:
@ -2465,11 +2475,9 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
case DT_MIPS_PLTGOT:
case DT_MIPS_RWPLT:
case DT_MIPS_RLD_MAP_REL:
OS << format(ConvChar, Value);
return;
return FormatHexValue(Value);
case DT_MIPS_FLAGS:
printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS);
return;
return FormatFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags));
default:
break;
}
@ -2480,13 +2488,10 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
switch (Type) {
case DT_PLTREL:
if (Value == DT_REL) {
OS << "REL";
break;
} else if (Value == DT_RELA) {
OS << "RELA";
break;
}
if (Value == DT_REL)
return "REL";
if (Value == DT_RELA)
return "RELA";
LLVM_FALLTHROUGH;
case DT_PLTGOT:
case DT_HASH:
@ -2506,14 +2511,12 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
case DT_VERSYM:
case DT_GNU_HASH:
case DT_NULL:
OS << format(ConvChar, Value);
break;
return FormatHexValue(Value);
case DT_RELACOUNT:
case DT_RELCOUNT:
case DT_VERDEFNUM:
case DT_VERNEEDNUM:
OS << Value;
break;
return std::to_string(Value);
case DT_PLTRELSZ:
case DT_RELASZ:
case DT_RELAENT:
@ -2526,8 +2529,7 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
case DT_PREINIT_ARRAYSZ:
case DT_ANDROID_RELSZ:
case DT_ANDROID_RELASZ:
OS << Value << " (bytes)";
break;
return std::to_string(Value) + " (bytes)";
case DT_NEEDED:
case DT_SONAME:
case DT_AUXILIARY:
@ -2535,37 +2537,45 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
case DT_FILTER:
case DT_RPATH:
case DT_RUNPATH: {
const std::map<uint64_t, const char*> TagNames = {
{DT_NEEDED, "Shared library"},
{DT_SONAME, "Library soname"},
{DT_AUXILIARY, "Auxiliary library"},
{DT_USED, "Not needed object"},
{DT_FILTER, "Filter library"},
{DT_RPATH, "Library rpath"},
{DT_RUNPATH, "Library runpath"},
const std::map<uint64_t, const char *> TagNames = {
{DT_NEEDED, "Shared library"}, {DT_SONAME, "Library soname"},
{DT_AUXILIARY, "Auxiliary library"}, {DT_USED, "Not needed object"},
{DT_FILTER, "Filter library"}, {DT_RPATH, "Library rpath"},
{DT_RUNPATH, "Library runpath"},
};
OS << TagNames.at(Type) << ": [" << getDynamicString(Value) << "]";
break;
return (Twine(TagNames.at(Type)) + ": [" + getDynamicString(Value) + "]")
.str();
}
case DT_FLAGS:
printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS);
break;
return FormatFlags(Value, makeArrayRef(ElfDynamicDTFlags));
case DT_FLAGS_1:
printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS);
break;
return FormatFlags(Value, makeArrayRef(ElfDynamicDTFlags1));
default:
OS << format(ConvChar, Value);
break;
return FormatHexValue(Value);
}
}
template <class ELFT>
std::string ELFDumper<ELFT>::getDynamicString(uint64_t Value) const {
if (DynamicStringTable.empty())
return "<String table is empty or was not found>";
StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const {
auto WarnAndReturn = [this](const Twine &Msg) {
reportUniqueWarning(createError(Msg));
return "<?>";
};
if (DynamicStringTable.empty() && !DynamicStringTable.data())
return WarnAndReturn("string table was not found");
if (Value < DynamicStringTable.size())
return DynamicStringTable.data() + Value;
return Twine("<Invalid offset 0x" + utohexstr(Value) + ">").str();
const uint64_t Offset =
(const uint8_t *)DynamicStringTable.data() - ObjF->getELFFile()->base();
return WarnAndReturn(
"string table at offset 0x" + Twine::utohexstr(Offset) +
": unable to read the string at 0x" + Twine::utohexstr(Offset + Value) +
", it goes past the end of the table (0x" +
Twine::utohexstr(Offset + DynamicStringTable.size()) + ")");
}
template <class ELFT> void ELFDumper<ELFT>::printUnwindInfo() {
@ -2596,14 +2606,14 @@ template <class ELFT> void ELFDumper<ELFT>::printDynamicTable() {
template <class ELFT> void ELFDumper<ELFT>::printNeededLibraries() {
ListScope D(W, "NeededLibraries");
std::vector<std::string> Libs;
std::vector<StringRef> Libs;
for (const auto &Entry : dynamic_table())
if (Entry.d_tag == ELF::DT_NEEDED)
Libs.push_back(getDynamicString(Entry.d_un.d_val));
llvm::sort(Libs);
for (const std::string &L : Libs)
for (StringRef L : Libs)
W.startLine() << L << "\n";
}
@ -4235,12 +4245,11 @@ template <class ELFT> void GNUStyle<ELFT>::printDynamic(const ELFO *Obj) {
std::string ValueFmt = " %-" + std::to_string(MaxTagSize) + "s ";
for (auto Entry : Table) {
uintX_t Tag = Entry.getTag();
std::string TypeString =
std::string Type =
std::string("(") + Obj->getDynamicTagAsString(Tag).c_str() + ")";
std::string Value = this->dumper()->getDynamicEntry(Tag, Entry.getVal());
OS << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10)
<< format(ValueFmt.c_str(), TypeString.c_str());
this->dumper()->printDynamicEntry(OS, Tag, Entry.getVal());
OS << "\n";
<< format(ValueFmt.c_str(), Type.c_str()) << Value << "\n";
}
}
@ -6051,7 +6060,6 @@ template <class ELFT> void LLVMStyle<ELFT>::printDynamic(const ELFFile<ELFT> *Ob
if (Table.empty())
return;
raw_ostream &OS = W.getOStream();
W.startLine() << "DynamicSection [ (" << Table.size() << " entries)\n";
size_t MaxTagSize = getMaxDynamicTagSize(Obj, Table);
@ -6064,12 +6072,12 @@ template <class ELFT> void LLVMStyle<ELFT>::printDynamic(const ELFFile<ELFT> *Ob
std::string ValueFmt = "%-" + std::to_string(MaxTagSize) + "s ";
for (auto Entry : Table) {
uintX_t Tag = Entry.getTag();
std::string Value = this->dumper()->getDynamicEntry(Tag, Entry.getVal());
W.startLine() << " " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10, true)
<< " "
<< format(ValueFmt.c_str(),
Obj->getDynamicTagAsString(Tag).c_str());
this->dumper()->printDynamicEntry(OS, Tag, Entry.getVal());
OS << "\n";
Obj->getDynamicTagAsString(Tag).c_str())
<< Value << "\n";
}
W.startLine() << "]\n";
}