mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:59:56 +00:00
Move to llvm-readobj code that is only used there.
lld might end up using a small part of this, but it will be in a much refactored form. For now this unblocks avoiding the full section scan in the ELFFile constructor. This also has a (very small) error handling improvement. llvm-svn: 244282
This commit is contained in:
parent
16f420a9d2
commit
833df2a833
@ -105,36 +105,6 @@ private:
|
||||
const Elf_Shdr *SymbolTableSectionHeaderIndex = nullptr;
|
||||
DenseMap<const Elf_Sym *, ELF::Elf64_Word> ExtendedSymbolTable;
|
||||
|
||||
const Elf_Shdr *dot_gnu_version_sec = nullptr; // .gnu.version
|
||||
const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r
|
||||
const Elf_Shdr *dot_gnu_version_d_sec = nullptr; // .gnu.version_d
|
||||
|
||||
// Records for each version index the corresponding Verdef or Vernaux entry.
|
||||
// This is filled the first time LoadVersionMap() is called.
|
||||
class VersionMapEntry : public PointerIntPair<const void*, 1> {
|
||||
public:
|
||||
// If the integer is 0, this is an Elf_Verdef*.
|
||||
// If the integer is 1, this is an Elf_Vernaux*.
|
||||
VersionMapEntry() : PointerIntPair<const void*, 1>(nullptr, 0) { }
|
||||
VersionMapEntry(const Elf_Verdef *verdef)
|
||||
: PointerIntPair<const void*, 1>(verdef, 0) { }
|
||||
VersionMapEntry(const Elf_Vernaux *vernaux)
|
||||
: PointerIntPair<const void*, 1>(vernaux, 1) { }
|
||||
bool isNull() const { return getPointer() == nullptr; }
|
||||
bool isVerdef() const { return !isNull() && getInt() == 0; }
|
||||
bool isVernaux() const { return !isNull() && getInt() == 1; }
|
||||
const Elf_Verdef *getVerdef() const {
|
||||
return isVerdef() ? (const Elf_Verdef*)getPointer() : nullptr;
|
||||
}
|
||||
const Elf_Vernaux *getVernaux() const {
|
||||
return isVernaux() ? (const Elf_Vernaux*)getPointer() : nullptr;
|
||||
}
|
||||
};
|
||||
mutable SmallVector<VersionMapEntry, 16> VersionMap;
|
||||
void LoadVersionDefs(const Elf_Shdr *sec) const;
|
||||
void LoadVersionNeeds(const Elf_Shdr *ec) const;
|
||||
void LoadVersionMap() const;
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
const T *getEntry(uint32_t Section, uint32_t Entry) const;
|
||||
@ -147,8 +117,6 @@ public:
|
||||
ErrorOr<StringRef> getStringTable(const Elf_Shdr *Section) const;
|
||||
ErrorOr<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const;
|
||||
|
||||
ErrorOr<StringRef> getSymbolVersion(StringRef StrTab, const Elf_Sym *Symb,
|
||||
bool &IsDefault) const;
|
||||
void VerifyStrTab(const Elf_Shdr *sh) const;
|
||||
|
||||
StringRef getRelocationTypeName(uint32_t Type) const;
|
||||
@ -282,87 +250,6 @@ typedef ELFFile<ELFType<support::little, true>> ELF64LEFile;
|
||||
typedef ELFFile<ELFType<support::big, false>> ELF32BEFile;
|
||||
typedef ELFFile<ELFType<support::big, true>> ELF64BEFile;
|
||||
|
||||
// Iterate through the version definitions, and place each Elf_Verdef
|
||||
// in the VersionMap according to its index.
|
||||
template <class ELFT>
|
||||
void ELFFile<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const {
|
||||
unsigned vd_size = sec->sh_size; // Size of section in bytes
|
||||
unsigned vd_count = sec->sh_info; // Number of Verdef entries
|
||||
const char *sec_start = (const char*)base() + sec->sh_offset;
|
||||
const char *sec_end = sec_start + vd_size;
|
||||
// The first Verdef entry is at the start of the section.
|
||||
const char *p = sec_start;
|
||||
for (unsigned i = 0; i < vd_count; i++) {
|
||||
if (p + sizeof(Elf_Verdef) > sec_end)
|
||||
report_fatal_error("Section ended unexpectedly while scanning "
|
||||
"version definitions.");
|
||||
const Elf_Verdef *vd = reinterpret_cast<const Elf_Verdef *>(p);
|
||||
if (vd->vd_version != ELF::VER_DEF_CURRENT)
|
||||
report_fatal_error("Unexpected verdef version");
|
||||
size_t index = vd->vd_ndx & ELF::VERSYM_VERSION;
|
||||
if (index >= VersionMap.size())
|
||||
VersionMap.resize(index + 1);
|
||||
VersionMap[index] = VersionMapEntry(vd);
|
||||
p += vd->vd_next;
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through the versions needed section, and place each Elf_Vernaux
|
||||
// in the VersionMap according to its index.
|
||||
template <class ELFT>
|
||||
void ELFFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const {
|
||||
unsigned vn_size = sec->sh_size; // Size of section in bytes
|
||||
unsigned vn_count = sec->sh_info; // Number of Verneed entries
|
||||
const char *sec_start = (const char *)base() + sec->sh_offset;
|
||||
const char *sec_end = sec_start + vn_size;
|
||||
// The first Verneed entry is at the start of the section.
|
||||
const char *p = sec_start;
|
||||
for (unsigned i = 0; i < vn_count; i++) {
|
||||
if (p + sizeof(Elf_Verneed) > sec_end)
|
||||
report_fatal_error("Section ended unexpectedly while scanning "
|
||||
"version needed records.");
|
||||
const Elf_Verneed *vn = reinterpret_cast<const Elf_Verneed *>(p);
|
||||
if (vn->vn_version != ELF::VER_NEED_CURRENT)
|
||||
report_fatal_error("Unexpected verneed version");
|
||||
// Iterate through the Vernaux entries
|
||||
const char *paux = p + vn->vn_aux;
|
||||
for (unsigned j = 0; j < vn->vn_cnt; j++) {
|
||||
if (paux + sizeof(Elf_Vernaux) > sec_end)
|
||||
report_fatal_error("Section ended unexpected while scanning auxiliary "
|
||||
"version needed records.");
|
||||
const Elf_Vernaux *vna = reinterpret_cast<const Elf_Vernaux *>(paux);
|
||||
size_t index = vna->vna_other & ELF::VERSYM_VERSION;
|
||||
if (index >= VersionMap.size())
|
||||
VersionMap.resize(index + 1);
|
||||
VersionMap[index] = VersionMapEntry(vna);
|
||||
paux += vna->vna_next;
|
||||
}
|
||||
p += vn->vn_next;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void ELFFile<ELFT>::LoadVersionMap() const {
|
||||
// If there is no dynamic symtab or version table, there is nothing to do.
|
||||
if (!DotDynSymSec || !dot_gnu_version_sec)
|
||||
return;
|
||||
|
||||
// Has the VersionMap already been loaded?
|
||||
if (VersionMap.size() > 0)
|
||||
return;
|
||||
|
||||
// The first two version indexes are reserved.
|
||||
// Index 0 is LOCAL, index 1 is GLOBAL.
|
||||
VersionMap.push_back(VersionMapEntry());
|
||||
VersionMap.push_back(VersionMapEntry());
|
||||
|
||||
if (dot_gnu_version_d_sec)
|
||||
LoadVersionDefs(dot_gnu_version_d_sec);
|
||||
|
||||
if (dot_gnu_version_r_sec)
|
||||
LoadVersionNeeds(dot_gnu_version_r_sec);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
ELF::Elf64_Word
|
||||
ELFFile<ELFT>::getExtendedSymbolTableIndex(const Elf_Sym *symb) const {
|
||||
@ -530,30 +417,6 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC)
|
||||
DotDynSymSec = &Sec;
|
||||
break;
|
||||
}
|
||||
case ELF::SHT_GNU_versym:
|
||||
if (dot_gnu_version_sec != nullptr) {
|
||||
// More than one .gnu.version section!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
dot_gnu_version_sec = &Sec;
|
||||
break;
|
||||
case ELF::SHT_GNU_verdef:
|
||||
if (dot_gnu_version_d_sec != nullptr) {
|
||||
// More than one .gnu.version_d section!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
dot_gnu_version_d_sec = &Sec;
|
||||
break;
|
||||
case ELF::SHT_GNU_verneed:
|
||||
if (dot_gnu_version_r_sec != nullptr) {
|
||||
// More than one .gnu.version_r section!
|
||||
EC = object_error::parse_failed;
|
||||
return;
|
||||
}
|
||||
dot_gnu_version_r_sec = &Sec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -668,61 +531,6 @@ ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section) const {
|
||||
return StringRef(DotShstrtab.data() + Offset);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(StringRef StrTab,
|
||||
const Elf_Sym *symb,
|
||||
bool &IsDefault) const {
|
||||
// This is a dynamic symbol. Look in the GNU symbol version table.
|
||||
if (!dot_gnu_version_sec) {
|
||||
// No version table.
|
||||
IsDefault = false;
|
||||
return StringRef("");
|
||||
}
|
||||
|
||||
// Determine the position in the symbol table of this entry.
|
||||
size_t entry_index =
|
||||
(reinterpret_cast<uintptr_t>(symb) - DotDynSymSec->sh_offset -
|
||||
reinterpret_cast<uintptr_t>(base())) /
|
||||
sizeof(Elf_Sym);
|
||||
|
||||
// Get the corresponding version index entry
|
||||
const Elf_Versym *vs = getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index);
|
||||
size_t version_index = vs->vs_index & ELF::VERSYM_VERSION;
|
||||
|
||||
// Special markers for unversioned symbols.
|
||||
if (version_index == ELF::VER_NDX_LOCAL ||
|
||||
version_index == ELF::VER_NDX_GLOBAL) {
|
||||
IsDefault = false;
|
||||
return StringRef("");
|
||||
}
|
||||
|
||||
// Lookup this symbol in the version table
|
||||
LoadVersionMap();
|
||||
if (version_index >= VersionMap.size() || VersionMap[version_index].isNull())
|
||||
return object_error::parse_failed;
|
||||
const VersionMapEntry &entry = VersionMap[version_index];
|
||||
|
||||
// Get the version name string
|
||||
size_t name_offset;
|
||||
if (entry.isVerdef()) {
|
||||
// The first Verdaux entry holds the name.
|
||||
name_offset = entry.getVerdef()->getAux()->vda_name;
|
||||
} else {
|
||||
name_offset = entry.getVernaux()->vna_name;
|
||||
}
|
||||
|
||||
// Set IsDefault
|
||||
if (entry.isVerdef()) {
|
||||
IsDefault = !(vs->vs_index & ELF::VERSYM_HIDDEN);
|
||||
} else {
|
||||
IsDefault = false;
|
||||
}
|
||||
|
||||
if (name_offset >= StrTab.size())
|
||||
return object_error::parse_failed;
|
||||
return StringRef(StrTab.data() + name_offset);
|
||||
}
|
||||
|
||||
/// This function returns the hash value for a symbol in the .dynsym section
|
||||
/// Name of the API remains consistent as specified in the libelf
|
||||
/// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash
|
||||
|
@ -23,7 +23,7 @@ SYMNAME: Error reading file: Invalid data was encountered while parsing the file
|
||||
RUN: not llvm-readobj %p/Inputs/corrupt-version.elf-x86_64 -dt \
|
||||
RUN: 2>&1 | FileCheck --check-prefix=VER %s
|
||||
|
||||
VER: Error reading file: Invalid data was encountered while parsing the file.
|
||||
VER: Error reading file: Invalid version entry.
|
||||
|
||||
|
||||
// The file is missing the dynamic string table but has references to it.
|
||||
|
@ -78,6 +78,10 @@ private:
|
||||
typedef typename ELFO::Elf_Hash Elf_Hash;
|
||||
typedef typename ELFO::Elf_Ehdr Elf_Ehdr;
|
||||
typedef typename ELFO::uintX_t uintX_t;
|
||||
typedef typename ELFO::Elf_Versym Elf_Versym;
|
||||
typedef typename ELFO::Elf_Verneed Elf_Verneed;
|
||||
typedef typename ELFO::Elf_Vernaux Elf_Vernaux;
|
||||
typedef typename ELFO::Elf_Verdef Elf_Verdef;
|
||||
|
||||
/// \brief Represents a region described by entries in the .dynamic table.
|
||||
struct DynRegionInfo {
|
||||
@ -106,6 +110,12 @@ private:
|
||||
return make_range(dynamic_table_begin(), dynamic_table_end());
|
||||
}
|
||||
|
||||
StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb,
|
||||
bool &IsDefault);
|
||||
void LoadVersionMap();
|
||||
void LoadVersionNeeds(const Elf_Shdr *ec) const;
|
||||
void LoadVersionDefs(const Elf_Shdr *sec) const;
|
||||
|
||||
const ELFO *Obj;
|
||||
DynRegionInfo DynRelaRegion;
|
||||
DynRegionInfo DynamicRegion;
|
||||
@ -113,6 +123,37 @@ private:
|
||||
const Elf_Sym *DynSymStart = nullptr;
|
||||
StringRef SOName;
|
||||
const Elf_Hash *HashTable = nullptr;
|
||||
|
||||
const Elf_Shdr *dot_gnu_version_sec = nullptr; // .gnu.version
|
||||
const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r
|
||||
const Elf_Shdr *dot_gnu_version_d_sec = nullptr; // .gnu.version_d
|
||||
|
||||
// Records for each version index the corresponding Verdef or Vernaux entry.
|
||||
// This is filled the first time LoadVersionMap() is called.
|
||||
class VersionMapEntry : public PointerIntPair<const void *, 1> {
|
||||
public:
|
||||
// If the integer is 0, this is an Elf_Verdef*.
|
||||
// If the integer is 1, this is an Elf_Vernaux*.
|
||||
VersionMapEntry() : PointerIntPair<const void *, 1>(nullptr, 0) {}
|
||||
VersionMapEntry(const Elf_Verdef *verdef)
|
||||
: PointerIntPair<const void *, 1>(verdef, 0) {}
|
||||
VersionMapEntry(const Elf_Vernaux *vernaux)
|
||||
: PointerIntPair<const void *, 1>(vernaux, 1) {}
|
||||
bool isNull() const { return getPointer() == nullptr; }
|
||||
bool isVerdef() const { return !isNull() && getInt() == 0; }
|
||||
bool isVernaux() const { return !isNull() && getInt() == 1; }
|
||||
const Elf_Verdef *getVerdef() const {
|
||||
return isVerdef() ? (const Elf_Verdef *)getPointer() : nullptr;
|
||||
}
|
||||
const Elf_Vernaux *getVernaux() const {
|
||||
return isVernaux() ? (const Elf_Vernaux *)getPointer() : nullptr;
|
||||
}
|
||||
};
|
||||
mutable SmallVector<VersionMapEntry, 16> VersionMap;
|
||||
|
||||
public:
|
||||
std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,
|
||||
bool IsDynamic);
|
||||
};
|
||||
|
||||
template <class T> T errorOrDefault(ErrorOr<T> Val, T Default = T()) {
|
||||
@ -159,10 +200,145 @@ std::error_code createELFDumper(const object::ObjectFile *Obj,
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
template <typename ELFO>
|
||||
static std::string getFullSymbolName(const ELFO &Obj,
|
||||
const typename ELFO::Elf_Sym *Symbol,
|
||||
StringRef StrTable, bool IsDynamic) {
|
||||
// Iterate through the versions needed section, and place each Elf_Vernaux
|
||||
// in the VersionMap according to its index.
|
||||
template <class ELFT>
|
||||
void ELFDumper<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const {
|
||||
unsigned vn_size = sec->sh_size; // Size of section in bytes
|
||||
unsigned vn_count = sec->sh_info; // Number of Verneed entries
|
||||
const char *sec_start = (const char *)Obj->base() + sec->sh_offset;
|
||||
const char *sec_end = sec_start + vn_size;
|
||||
// The first Verneed entry is at the start of the section.
|
||||
const char *p = sec_start;
|
||||
for (unsigned i = 0; i < vn_count; i++) {
|
||||
if (p + sizeof(Elf_Verneed) > sec_end)
|
||||
report_fatal_error("Section ended unexpectedly while scanning "
|
||||
"version needed records.");
|
||||
const Elf_Verneed *vn = reinterpret_cast<const Elf_Verneed *>(p);
|
||||
if (vn->vn_version != ELF::VER_NEED_CURRENT)
|
||||
report_fatal_error("Unexpected verneed version");
|
||||
// Iterate through the Vernaux entries
|
||||
const char *paux = p + vn->vn_aux;
|
||||
for (unsigned j = 0; j < vn->vn_cnt; j++) {
|
||||
if (paux + sizeof(Elf_Vernaux) > sec_end)
|
||||
report_fatal_error("Section ended unexpected while scanning auxiliary "
|
||||
"version needed records.");
|
||||
const Elf_Vernaux *vna = reinterpret_cast<const Elf_Vernaux *>(paux);
|
||||
size_t index = vna->vna_other & ELF::VERSYM_VERSION;
|
||||
if (index >= VersionMap.size())
|
||||
VersionMap.resize(index + 1);
|
||||
VersionMap[index] = VersionMapEntry(vna);
|
||||
paux += vna->vna_next;
|
||||
}
|
||||
p += vn->vn_next;
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through the version definitions, and place each Elf_Verdef
|
||||
// in the VersionMap according to its index.
|
||||
template <class ELFT>
|
||||
void ELFDumper<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const {
|
||||
unsigned vd_size = sec->sh_size; // Size of section in bytes
|
||||
unsigned vd_count = sec->sh_info; // Number of Verdef entries
|
||||
const char *sec_start = (const char *)Obj->base() + sec->sh_offset;
|
||||
const char *sec_end = sec_start + vd_size;
|
||||
// The first Verdef entry is at the start of the section.
|
||||
const char *p = sec_start;
|
||||
for (unsigned i = 0; i < vd_count; i++) {
|
||||
if (p + sizeof(Elf_Verdef) > sec_end)
|
||||
report_fatal_error("Section ended unexpectedly while scanning "
|
||||
"version definitions.");
|
||||
const Elf_Verdef *vd = reinterpret_cast<const Elf_Verdef *>(p);
|
||||
if (vd->vd_version != ELF::VER_DEF_CURRENT)
|
||||
report_fatal_error("Unexpected verdef version");
|
||||
size_t index = vd->vd_ndx & ELF::VERSYM_VERSION;
|
||||
if (index >= VersionMap.size())
|
||||
VersionMap.resize(index + 1);
|
||||
VersionMap[index] = VersionMapEntry(vd);
|
||||
p += vd->vd_next;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT> void ELFDumper<ELFT>::LoadVersionMap() {
|
||||
// If there is no dynamic symtab or version table, there is nothing to do.
|
||||
if (!DynSymStart || !dot_gnu_version_sec)
|
||||
return;
|
||||
|
||||
// Has the VersionMap already been loaded?
|
||||
if (VersionMap.size() > 0)
|
||||
return;
|
||||
|
||||
// The first two version indexes are reserved.
|
||||
// Index 0 is LOCAL, index 1 is GLOBAL.
|
||||
VersionMap.push_back(VersionMapEntry());
|
||||
VersionMap.push_back(VersionMapEntry());
|
||||
|
||||
if (dot_gnu_version_d_sec)
|
||||
LoadVersionDefs(dot_gnu_version_d_sec);
|
||||
|
||||
if (dot_gnu_version_r_sec)
|
||||
LoadVersionNeeds(dot_gnu_version_r_sec);
|
||||
}
|
||||
|
||||
template <typename ELFT>
|
||||
StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab,
|
||||
const Elf_Sym *symb,
|
||||
bool &IsDefault) {
|
||||
// This is a dynamic symbol. Look in the GNU symbol version table.
|
||||
if (!dot_gnu_version_sec) {
|
||||
// No version table.
|
||||
IsDefault = false;
|
||||
return StringRef("");
|
||||
}
|
||||
|
||||
// Determine the position in the symbol table of this entry.
|
||||
size_t entry_index = (reinterpret_cast<uintptr_t>(symb) -
|
||||
reinterpret_cast<uintptr_t>(DynSymStart)) /
|
||||
sizeof(Elf_Sym);
|
||||
|
||||
// Get the corresponding version index entry
|
||||
const Elf_Versym *vs =
|
||||
Obj->template getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index);
|
||||
size_t version_index = vs->vs_index & ELF::VERSYM_VERSION;
|
||||
|
||||
// Special markers for unversioned symbols.
|
||||
if (version_index == ELF::VER_NDX_LOCAL ||
|
||||
version_index == ELF::VER_NDX_GLOBAL) {
|
||||
IsDefault = false;
|
||||
return StringRef("");
|
||||
}
|
||||
|
||||
// Lookup this symbol in the version table
|
||||
LoadVersionMap();
|
||||
if (version_index >= VersionMap.size() || VersionMap[version_index].isNull())
|
||||
reportError("Invalid version entry");
|
||||
const VersionMapEntry &entry = VersionMap[version_index];
|
||||
|
||||
// Get the version name string
|
||||
size_t name_offset;
|
||||
if (entry.isVerdef()) {
|
||||
// The first Verdaux entry holds the name.
|
||||
name_offset = entry.getVerdef()->getAux()->vda_name;
|
||||
} else {
|
||||
name_offset = entry.getVernaux()->vna_name;
|
||||
}
|
||||
|
||||
// Set IsDefault
|
||||
if (entry.isVerdef()) {
|
||||
IsDefault = !(vs->vs_index & ELF::VERSYM_HIDDEN);
|
||||
} else {
|
||||
IsDefault = false;
|
||||
}
|
||||
|
||||
if (name_offset >= StrTab.size())
|
||||
reportError("Invalid string offset");
|
||||
return StringRef(StrTab.data() + name_offset);
|
||||
}
|
||||
|
||||
template <typename ELFT>
|
||||
std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol,
|
||||
StringRef StrTable,
|
||||
bool IsDynamic) {
|
||||
StringRef SymbolName = errorOrDefault(Symbol->getName(StrTable));
|
||||
if (!IsDynamic)
|
||||
return SymbolName;
|
||||
@ -170,13 +346,9 @@ static std::string getFullSymbolName(const ELFO &Obj,
|
||||
std::string FullSymbolName(SymbolName);
|
||||
|
||||
bool IsDefault;
|
||||
ErrorOr<StringRef> Version =
|
||||
Obj.getSymbolVersion(StrTable, &*Symbol, IsDefault);
|
||||
if (Version) {
|
||||
FullSymbolName += (IsDefault ? "@@" : "@");
|
||||
FullSymbolName += *Version;
|
||||
} else
|
||||
error(Version.getError());
|
||||
StringRef Version = getSymbolVersion(StrTable, &*Symbol, IsDefault);
|
||||
FullSymbolName += (IsDefault ? "@@" : "@");
|
||||
FullSymbolName += Version;
|
||||
return FullSymbolName;
|
||||
}
|
||||
|
||||
@ -671,6 +843,26 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer)
|
||||
DynamicStringTable = StringRef(StringTableBegin, StringTableSize);
|
||||
if (SONameOffset)
|
||||
SOName = getDynamicString(SONameOffset);
|
||||
|
||||
for (const Elf_Shdr &Sec : Obj->sections()) {
|
||||
switch (Sec.sh_type) {
|
||||
case ELF::SHT_GNU_versym:
|
||||
if (dot_gnu_version_sec != nullptr)
|
||||
reportError("Multiple SHT_GNU_versym");
|
||||
dot_gnu_version_sec = &Sec;
|
||||
break;
|
||||
case ELF::SHT_GNU_verdef:
|
||||
if (dot_gnu_version_d_sec != nullptr)
|
||||
reportError("Multiple SHT_GNU_verdef");
|
||||
dot_gnu_version_d_sec = &Sec;
|
||||
break;
|
||||
case ELF::SHT_GNU_verneed:
|
||||
if (dot_gnu_version_r_sec != nullptr)
|
||||
reportError("Multilpe SHT_GNU_verneed");
|
||||
dot_gnu_version_r_sec = &Sec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ELFT>
|
||||
@ -946,8 +1138,7 @@ void ELFDumper<ELFT>::printSymbol(const Elf_Sym *Symbol, StringRef StrTable,
|
||||
unsigned SectionIndex = 0;
|
||||
StringRef SectionName;
|
||||
getSectionNameIndex(*Obj, Symbol, SectionName, SectionIndex);
|
||||
std::string FullSymbolName =
|
||||
getFullSymbolName(*Obj, Symbol, StrTable, IsDynamic);
|
||||
std::string FullSymbolName = getFullSymbolName(Symbol, StrTable, IsDynamic);
|
||||
|
||||
DictScope D(W, "Symbol");
|
||||
W.printNumber("Name", FullSymbolName, Symbol->st_name);
|
||||
@ -1346,12 +1537,14 @@ public:
|
||||
typedef typename ELFO::Elf_Rel Elf_Rel;
|
||||
typedef typename ELFO::Elf_Rela Elf_Rela;
|
||||
|
||||
MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, StreamWriter &W);
|
||||
MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj,
|
||||
Elf_Dyn_Range DynTable, StreamWriter &W);
|
||||
|
||||
void parseGOT();
|
||||
void parsePLT();
|
||||
|
||||
private:
|
||||
ELFDumper<ELFT> *Dumper;
|
||||
const ELFO *Obj;
|
||||
StreamWriter &W;
|
||||
llvm::Optional<uint64_t> DtPltGot;
|
||||
@ -1377,9 +1570,9 @@ private:
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
MipsGOTParser<ELFT>::MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable,
|
||||
StreamWriter &W)
|
||||
: Obj(Obj), W(W) {
|
||||
MipsGOTParser<ELFT>::MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj,
|
||||
Elf_Dyn_Range DynTable, StreamWriter &W)
|
||||
: Dumper(Dumper), Obj(Obj), W(W) {
|
||||
for (const auto &Entry : DynTable) {
|
||||
switch (Entry.getTag()) {
|
||||
case ELF::DT_PLTGOT:
|
||||
@ -1606,7 +1799,7 @@ void MipsGOTParser<ELFT>::printGlobalGotEntry(
|
||||
W.printHex("Section", SectionName, SectionIndex);
|
||||
|
||||
std::string FullSymbolName =
|
||||
getFullSymbolName(*Obj, Sym, StrTable, IsDynamic);
|
||||
Dumper->getFullSymbolName(Sym, StrTable, IsDynamic);
|
||||
W.printNumber("Name", FullSymbolName, Sym->st_name);
|
||||
}
|
||||
|
||||
@ -1638,7 +1831,7 @@ void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr,
|
||||
getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex);
|
||||
W.printHex("Section", SectionName, SectionIndex);
|
||||
|
||||
std::string FullSymbolName = getFullSymbolName(*Obj, Sym, StrTable, true);
|
||||
std::string FullSymbolName = Dumper->getFullSymbolName(Sym, StrTable, true);
|
||||
W.printNumber("Name", FullSymbolName, Sym->st_name);
|
||||
}
|
||||
|
||||
@ -1648,7 +1841,7 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
|
||||
return;
|
||||
}
|
||||
|
||||
MipsGOTParser<ELFT> GOTParser(Obj, dynamic_table(), W);
|
||||
MipsGOTParser<ELFT> GOTParser(this, Obj, dynamic_table(), W);
|
||||
GOTParser.parseGOT();
|
||||
GOTParser.parsePLT();
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ namespace opts {
|
||||
namespace llvm {
|
||||
|
||||
void reportError(Twine Msg) {
|
||||
outs() << Msg << "\n";
|
||||
outs() << "\nError reading file: " << Msg << ".\n";
|
||||
outs().flush();
|
||||
exit(1);
|
||||
}
|
||||
@ -200,7 +200,7 @@ void error(std::error_code EC) {
|
||||
if (!EC)
|
||||
return;
|
||||
|
||||
reportError(Twine("\nError reading file: ") + EC.message() + ".");
|
||||
reportError(EC.message());
|
||||
}
|
||||
|
||||
bool relocAddressLess(RelocationRef a, RelocationRef b) {
|
||||
|
Loading…
Reference in New Issue
Block a user