summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-readobj
diff options
context:
space:
mode:
authorGeorgii Rymar <grimar@accesssoftek.com>2019-11-28 12:19:50 +0300
committerGeorgii Rymar <grimar@accesssoftek.com>2019-12-02 12:27:31 +0300
commitc653a52c85ff913bcbef007082763dbc754d6933 (patch)
tree621f31772c6761378609e2ac47f5c40f32d7904c /llvm/tools/llvm-readobj
parentbd23859f390aa81ddb1bf0b16684cce50ad9d66d (diff)
downloadbcm5719-llvm-c653a52c85ff913bcbef007082763dbc754d6933.tar.gz
bcm5719-llvm-c653a52c85ff913bcbef007082763dbc754d6933.zip
[llvm-readobj/llvm-readelf] - Reimplement dumping of the SHT_GNU_verneed section.
This is similar to D70495, but for SHT_GNU_verneed section. It solves the same problems: different implementations, lack of error reporting and no test coverage. DIfferential revision: https://reviews.llvm.org/D70826
Diffstat (limited to 'llvm/tools/llvm-readobj')
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp252
1 files changed, 168 insertions, 84 deletions
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 51ea599f4be..1031e0a181d 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -167,6 +167,23 @@ struct VerDef {
std::string Name;
std::vector<VerdAux> AuxV;
};
+
+struct VernAux {
+ unsigned Hash;
+ unsigned Flags;
+ unsigned Other;
+ unsigned Offset;
+ std::string Name;
+};
+
+struct VerNeed {
+ unsigned Version;
+ unsigned Cnt;
+ unsigned Offset;
+ std::string File;
+ std::vector<VernAux> AuxV;
+};
+
} // namespace
template <typename ELFT> class ELFDumper : public ObjDumper {
@@ -345,25 +362,50 @@ public:
Expected<std::vector<VerDef>>
getVersionDefinitions(const Elf_Shdr *Sec) const;
+ Expected<std::vector<VerNeed>>
+ getVersionDependencies(const Elf_Shdr *Sec) const;
};
+static StringRef getSecTypeName(unsigned Type) {
+ if (Type == ELF::SHT_GNU_versym)
+ return "SHT_GNU_versym";
+ if (Type == ELF::SHT_GNU_verdef)
+ return "SHT_GNU_verdef";
+ if (Type == ELF::SHT_GNU_verneed)
+ return "SHT_GNU_verneed";
+ llvm_unreachable("unexpected section type");
+}
+
+template <class ELFT>
+static Expected<StringRef> getLinkAsStrtab(const ELFFile<ELFT> *Obj,
+ const typename ELFT::Shdr *Sec,
+ unsigned SecNdx) {
+ Expected<const typename ELFT::Shdr *> StrTabSecOrErr =
+ Obj->getSection(Sec->sh_link);
+ if (!StrTabSecOrErr)
+ return createError("invalid section linked to " +
+ getSecTypeName(Sec->sh_type) + " section with index " +
+ Twine(SecNdx) + ": " +
+ toString(StrTabSecOrErr.takeError()));
+
+ Expected<StringRef> StrTabOrErr = Obj->getStringTable(*StrTabSecOrErr);
+ if (!StrTabOrErr)
+ return createError("invalid string table linked to " +
+ getSecTypeName(Sec->sh_type) + " section with index " +
+ Twine(SecNdx) + ": " +
+ toString(StrTabOrErr.takeError()));
+ return *StrTabOrErr;
+}
+
template <class ELFT>
Expected<std::vector<VerDef>>
ELFDumper<ELFT>::getVersionDefinitions(const Elf_Shdr *Sec) const {
const ELFFile<ELFT> *Obj = ObjF->getELFFile();
unsigned SecNdx = Sec - &cantFail(Obj->sections()).front();
- Expected<const Elf_Shdr *> StrTabSecOrErr = Obj->getSection(Sec->sh_link);
- if (!StrTabSecOrErr)
- return createError(
- "invalid section linked to SHT_GNU_verdef section with index " +
- Twine(SecNdx) + ": " + toString(StrTabSecOrErr.takeError()));
-
- Expected<StringRef> StrTabOrErr = Obj->getStringTable(*StrTabSecOrErr);
+ Expected<StringRef> StrTabOrErr = getLinkAsStrtab(Obj, Sec, SecNdx);
if (!StrTabOrErr)
- return createError(
- "invalid string table linked to SHT_GNU_verdef section with index " +
- Twine(SecNdx) + ": " + toString(StrTabOrErr.takeError()));
+ return StrTabOrErr.takeError();
Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj->getSectionContents(Sec);
if (!ContentsOrErr)
@@ -449,6 +491,90 @@ ELFDumper<ELFT>::getVersionDefinitions(const Elf_Shdr *Sec) const {
}
template <class ELFT>
+Expected<std::vector<VerNeed>>
+ELFDumper<ELFT>::getVersionDependencies(const Elf_Shdr *Sec) const {
+ const ELFFile<ELFT> *Obj = ObjF->getELFFile();
+ unsigned SecNdx = Sec - &cantFail(Obj->sections()).front();
+
+ StringRef StrTab;
+ Expected<StringRef> StrTabOrErr = getLinkAsStrtab(Obj, Sec, SecNdx);
+ if (!StrTabOrErr)
+ ELFDumperStyle->reportUniqueWarning(StrTabOrErr.takeError());
+ else
+ StrTab = *StrTabOrErr;
+
+ Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj->getSectionContents(Sec);
+ if (!ContentsOrErr)
+ return createError(
+ "cannot read content of SHT_GNU_verneed section with index " +
+ Twine(SecNdx) + ": " + toString(ContentsOrErr.takeError()));
+
+ const uint8_t *Start = ContentsOrErr->data();
+ const uint8_t *End = Start + ContentsOrErr->size();
+ const uint8_t *VerneedBuf = Start;
+
+ std::vector<VerNeed> Ret;
+ for (unsigned I = 1; I <= /*VerneedNum=*/Sec->sh_info; ++I) {
+ if (VerneedBuf + sizeof(Elf_Verdef) > End)
+ return createError("invalid SHT_GNU_verneed section with index " +
+ Twine(SecNdx) + ": version dependency " + Twine(I) +
+ " goes past the end of the section");
+
+ if (uintptr_t(VerneedBuf) % sizeof(uint32_t) != 0)
+ return createError(
+ "invalid SHT_GNU_verneed section with index " + Twine(SecNdx) +
+ ": found a misaligned version dependency entry at offset 0x" +
+ Twine::utohexstr(VerneedBuf - Start));
+
+ const Elf_Verneed *Verneed =
+ reinterpret_cast<const Elf_Verneed *>(VerneedBuf);
+
+ VerNeed &VN = *Ret.emplace(Ret.end());
+ VN.Version = Verneed->vn_version;
+ VN.Cnt = Verneed->vn_cnt;
+ VN.Offset = VerneedBuf - Start;
+
+ if (Verneed->vn_file < StrTab.size())
+ VN.File = StrTab.drop_front(Verneed->vn_file);
+ else
+ VN.File = "<corrupt vn_file: " + to_string(Verneed->vn_file) + ">";
+
+ const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux;
+ for (unsigned J = 0; J < Verneed->vn_cnt; ++J) {
+ if (uintptr_t(VernauxBuf) % sizeof(uint32_t) != 0)
+ return createError("invalid SHT_GNU_verneed section with index " +
+ Twine(SecNdx) +
+ ": found a misaligned auxiliary entry at offset 0x" +
+ Twine::utohexstr(VernauxBuf - Start));
+
+ if (VernauxBuf + sizeof(Elf_Vernaux) > End)
+ return createError(
+ "invalid SHT_GNU_verneed section with index " + Twine(SecNdx) +
+ ": version dependency " + Twine(I) +
+ " refers to an auxiliary entry that goes past the end "
+ "of the section");
+
+ const Elf_Vernaux *Vernaux =
+ reinterpret_cast<const Elf_Vernaux *>(VernauxBuf);
+
+ VernAux &Aux = *VN.AuxV.emplace(VN.AuxV.end());
+ Aux.Hash = Vernaux->vna_hash;
+ Aux.Flags = Vernaux->vna_flags;
+ Aux.Other = Vernaux->vna_other;
+ Aux.Offset = VernauxBuf - Start;
+ if (StrTab.size() <= Vernaux->vna_name)
+ Aux.Name = "<corrupt>";
+ else
+ Aux.Name = StrTab.drop_front(Vernaux->vna_name);
+
+ VernauxBuf += Vernaux->vna_next;
+ }
+ VerneedBuf += Verneed->vn_next;
+ }
+ return Ret;
+}
+
+template <class ELFT>
void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
StringRef StrTable, SymtabName;
size_t Entries = 0;
@@ -3946,9 +4072,10 @@ void GNUStyle<ELFT>::printGNUVersionSectionProlog(
SymTabName =
unwrapOrError(this->FileName, Obj->getSectionName(*SymTabOrErr));
else
- this->reportUniqueWarning(createError(
- "invalid section linked to SHT_GNU_verdef section with index " +
- Twine(SecNdx) + ": " + toString(SymTabOrErr.takeError())));
+ this->reportUniqueWarning(
+ createError("invalid section linked to " +
+ getSecTypeName(Sec->sh_type) + " section with index " +
+ Twine(SecNdx) + ": " + toString(SymTabOrErr.takeError())));
OS << " Addr: " << format_hex_no_prefix(Sec->sh_addr, 16)
<< " Offset: " << format_hex(Sec->sh_offset, 8)
@@ -4064,45 +4191,20 @@ void GNUStyle<ELFT>::printVersionDependencySection(const ELFFile<ELFT> *Obj,
unsigned VerneedNum = Sec->sh_info;
printGNUVersionSectionProlog(Obj, Sec, "Version needs", VerneedNum);
- ArrayRef<uint8_t> SecData =
- unwrapOrError(this->FileName, Obj->getSectionContents(Sec));
-
- const Elf_Shdr *StrTabSec =
- unwrapOrError(this->FileName, Obj->getSection(Sec->sh_link));
- StringRef StringTable = {
- reinterpret_cast<const char *>(Obj->base() + StrTabSec->sh_offset),
- (size_t)StrTabSec->sh_size};
-
- const uint8_t *VerneedBuf = SecData.data();
- for (unsigned I = 0; I < VerneedNum; ++I) {
- const Elf_Verneed *Verneed =
- reinterpret_cast<const Elf_Verneed *>(VerneedBuf);
-
- StringRef File = StringTable.size() > Verneed->vn_file
- ? StringTable.drop_front(Verneed->vn_file)
- : "<invalid>";
-
- OS << format(" 0x%04x: Version: %u File: %s Cnt: %u\n",
- reinterpret_cast<const uint8_t *>(Verneed) - SecData.begin(),
- (unsigned)Verneed->vn_version, File.data(),
- (unsigned)Verneed->vn_cnt);
-
- const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux;
- for (unsigned J = 0; J < Verneed->vn_cnt; ++J) {
- const Elf_Vernaux *Vernaux =
- reinterpret_cast<const Elf_Vernaux *>(VernauxBuf);
-
- StringRef Name = StringTable.size() > Vernaux->vna_name
- ? StringTable.drop_front(Vernaux->vna_name)
- : "<invalid>";
+ Expected<std::vector<VerNeed>> V =
+ this->dumper()->getVersionDependencies(Sec);
+ if (!V) {
+ this->reportUniqueWarning(V.takeError());
+ return;
+ }
- OS << format(" 0x%04x: Name: %s Flags: %s Version: %u\n",
- reinterpret_cast<const uint8_t *>(Vernaux) - SecData.begin(),
- Name.data(), versionFlagToString(Vernaux->vna_flags).c_str(),
- (unsigned)Vernaux->vna_other);
- VernauxBuf += Vernaux->vna_next;
- }
- VerneedBuf += Verneed->vn_next;
+ for (const VerNeed &VN : *V) {
+ OS << format(" 0x%04x: Version: %u File: %s Cnt: %u\n", VN.Offset,
+ VN.Version, VN.File.data(), VN.Cnt);
+ for (const VernAux &Aux : VN.AuxV)
+ OS << format(" 0x%04x: Name: %s Flags: %s Version: %u\n", Aux.Offset,
+ Aux.Name.data(), versionFlagToString(Aux.Flags).c_str(),
+ Aux.Other);
}
OS << '\n';
}
@@ -5853,45 +5955,27 @@ void LLVMStyle<ELFT>::printVersionDependencySection(const ELFFile<ELFT> *Obj,
if (!Sec)
return;
- const uint8_t *SecData =
- reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
- const Elf_Shdr *StrTabSec =
- unwrapOrError(this->FileName, Obj->getSection(Sec->sh_link));
- StringRef StringTable = {
- reinterpret_cast<const char *>(Obj->base() + StrTabSec->sh_offset),
- (size_t)StrTabSec->sh_size};
+ Expected<std::vector<VerNeed>> V =
+ this->dumper()->getVersionDependencies(Sec);
+ if (!V) {
+ this->reportUniqueWarning(V.takeError());
+ return;
+ }
- const uint8_t *VerneedBuf = SecData;
- unsigned VerneedNum = Sec->sh_info;
- for (unsigned I = 0; I < VerneedNum; ++I) {
- const Elf_Verneed *Verneed =
- reinterpret_cast<const Elf_Verneed *>(VerneedBuf);
+ for (const VerNeed &VN : *V) {
DictScope Entry(W, "Dependency");
- W.printNumber("Version", Verneed->vn_version);
- W.printNumber("Count", Verneed->vn_cnt);
-
- StringRef FileName = StringTable.size() > Verneed->vn_file
- ? StringTable.drop_front(Verneed->vn_file)
- : "<invalid>";
- W.printString("FileName", FileName.data());
+ W.printNumber("Version", VN.Version);
+ W.printNumber("Count", VN.Cnt);
+ W.printString("FileName", VN.File.c_str());
- const uint8_t *VernauxBuf = VerneedBuf + Verneed->vn_aux;
ListScope L(W, "Entries");
- for (unsigned J = 0; J < Verneed->vn_cnt; ++J) {
- const Elf_Vernaux *Vernaux =
- reinterpret_cast<const Elf_Vernaux *>(VernauxBuf);
+ for (const VernAux &Aux : VN.AuxV) {
DictScope Entry(W, "Entry");
- W.printNumber("Hash", Vernaux->vna_hash);
- W.printFlags("Flags", Vernaux->vna_flags, makeArrayRef(SymVersionFlags));
- W.printNumber("Index", Vernaux->vna_other);
-
- StringRef Name = StringTable.size() > Vernaux->vna_name
- ? StringTable.drop_front(Vernaux->vna_name)
- : "<invalid>";
- W.printString("Name", Name.data());
- VernauxBuf += Vernaux->vna_next;
+ W.printNumber("Hash", Aux.Hash);
+ W.printFlags("Flags", Aux.Flags, makeArrayRef(SymVersionFlags));
+ W.printNumber("Index", Aux.Other);
+ W.printString("Name", Aux.Name.c_str());
}
- VerneedBuf += Verneed->vn_next;
}
}
OpenPOWER on IntegriCloud