aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools
diff options
context:
space:
mode:
authorGeorge Rimar <grimar@accesssoftek.com>2019-08-08 07:17:35 +0000
committerGeorge Rimar <grimar@accesssoftek.com>2019-08-08 07:17:35 +0000
commit67ea32a00709f5f2d999002d747c58ac357223fd (patch)
tree997907a1a6b02d74da239524972b3beacef356b7 /llvm/tools
parent6fd13f0849573aeec26f28ab0927eea0b5a7ccb9 (diff)
downloadllvm-67ea32a00709f5f2d999002d747c58ac357223fd.zip
llvm-67ea32a00709f5f2d999002d747c58ac357223fd.tar.gz
llvm-67ea32a00709f5f2d999002d747c58ac357223fd.tar.bz2
[llvm-readobj/libObject] - Introduce a custom warning handler for `ELFFile<ELFT>` methods.
Currently, we have a code duplication in llvm-readobj which was introduced in D63266. The duplication was introduced to allow llvm-readobj to dump the partially broken object. Methods in ELFFile<ELFT> perform a strict validation of the inputs, what is itself good, but not for dumper tools, that might want to dump the information, even if some pieces are broken/unexpected. This patch introduces a warning handler which can be passed to ELFFile<ELFT> methods and can allow skipping the non-critical errors when needed/possible. For demonstration, I removed the duplication from llvm-readobj and implemented a warning using the new custom warning handler. It also deduplicates the strings printed, making the output less verbose. Differential revision: https://reviews.llvm.org/D65515 llvm-svn: 368260
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp43
-rw-r--r--llvm/tools/llvm-readobj/llvm-readobj.cpp6
-rw-r--r--llvm/tools/llvm-readobj/llvm-readobj.h10
3 files changed, 36 insertions, 23 deletions
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 0f33ecd..aa6bb41 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -63,6 +63,7 @@
#include <memory>
#include <string>
#include <system_error>
+#include <unordered_set>
#include <vector>
using namespace llvm;
@@ -352,7 +353,17 @@ public:
using Elf_Sym = typename ELFT::Sym;
using Elf_Addr = typename ELFT::Addr;
- DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {}
+ DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {
+ // Dumper reports all non-critical errors as warnings.
+ // It does not print the same warning more than once.
+ WarningHandler = [this](const Twine &Msg) {
+ StringRef FileName = this->Dumper->getElfObject()->getFileName();
+ if (Warnings.insert(Msg.str()).second)
+ reportWarning(FileName, createError(Msg));
+ return Error::success();
+ };
+ }
+
virtual ~DumpStyle() = default;
virtual void printFileHeaders(const ELFFile<ELFT> *Obj) = 0;
@@ -401,7 +412,11 @@ public:
virtual void printMipsPLT(const MipsGOTParser<ELFT> &Parser) = 0;
const ELFDumper<ELFT> *dumper() const { return Dumper; }
+protected:
+ std::function<Error(const Twine &Msg)> WarningHandler;
+
private:
+ std::unordered_set<std::string> Warnings;
const ELFDumper<ELFT> *Dumper;
};
@@ -3032,26 +3047,6 @@ static std::string getSectionTypeString(unsigned Arch, unsigned Type) {
}
template <class ELFT>
-static StringRef getSectionName(const typename ELFT::Shdr &Sec,
- const ELFObjectFile<ELFT> &ElfObj,
- ArrayRef<typename ELFT::Shdr> Sections) {
- const ELFFile<ELFT> &Obj = *ElfObj.getELFFile();
- uint32_t Index = Obj.getHeader()->e_shstrndx;
- if (Index == ELF::SHN_XINDEX)
- Index = Sections[0].sh_link;
- if (!Index) // no section string table.
- return "";
- // TODO: Test a case when the sh_link of the section with index 0 is broken.
- if (Index >= Sections.size())
- reportError(ElfObj.getFileName(),
- createError("section header string table index " +
- Twine(Index) + " does not exist"));
- StringRef Data = toStringRef(unwrapOrError(
- Obj.template getSectionContentsAsArray<uint8_t>(&Sections[Index])));
- return unwrapOrError(Obj.getSectionName(&Sec, Data));
-}
-
-template <class ELFT>
void GNUStyle<ELFT>::printSectionHeaders(const ELFO *Obj) {
unsigned Bias = ELFT::Is64Bits ? 0 : 8;
ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections());
@@ -3072,7 +3067,8 @@ void GNUStyle<ELFT>::printSectionHeaders(const ELFO *Obj) {
size_t SectionIndex = 0;
for (const Elf_Shdr &Sec : Sections) {
Fields[0].Str = to_string(SectionIndex);
- Fields[1].Str = getSectionName(Sec, *ElfObj, Sections);
+ Fields[1].Str = unwrapOrError<StringRef>(
+ ElfObj->getFileName(), Obj->getSectionName(&Sec, this->WarningHandler));
Fields[2].Str =
getSectionTypeString(Obj->getHeader()->e_machine, Sec.sh_type);
Fields[3].Str =
@@ -4984,7 +4980,8 @@ void LLVMStyle<ELFT>::printSectionHeaders(const ELFO *Obj) {
ArrayRef<Elf_Shdr> Sections = unwrapOrError(Obj->sections());
const ELFObjectFile<ELFT> *ElfObj = this->dumper()->getElfObject();
for (const Elf_Shdr &Sec : Sections) {
- StringRef Name = getSectionName(Sec, *ElfObj, Sections);
+ StringRef Name = unwrapOrError(
+ ElfObj->getFileName(), Obj->getSectionName(&Sec, this->WarningHandler));
DictScope SectionD(W, "Section");
W.printNumber("Index", ++SectionIndex);
W.printNumber("Name", Name, Sec.sh_name);
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index bb629c2..f607490 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -394,6 +394,12 @@ void reportWarning(Twine Msg) {
WithColor::warning(errs()) << Msg << "\n";
}
+void reportWarning(StringRef Input, Error Err) {
+ if (Input == "-")
+ Input = "<stdin>";
+ warn(createFileError(Input, std::move(Err)));
+}
+
void warn(Error Err) {
handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
reportWarning(EI.message());
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.h b/llvm/tools/llvm-readobj/llvm-readobj.h
index 0e02da4..7ca1dfb 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.h
+++ b/llvm/tools/llvm-readobj/llvm-readobj.h
@@ -24,6 +24,7 @@ namespace llvm {
LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
void reportError(StringRef Input, Error Err);
void reportWarning(Twine Msg);
+ void reportWarning(StringRef Input, Error Err);
void warn(llvm::Error Err);
void error(std::error_code EC);
void error(llvm::Error EC);
@@ -37,6 +38,8 @@ namespace llvm {
return *EO;
reportError(EO.getError().message());
}
+
+ // TODO: This one is deprecated. Use one with a Input name below.
template <class T> T unwrapOrError(Expected<T> EO) {
if (EO)
return *EO;
@@ -46,6 +49,13 @@ namespace llvm {
OS.flush();
reportError(Buf);
}
+
+ template <class T> T unwrapOrError(StringRef Input, Expected<T> EO) {
+ if (EO)
+ return *EO;
+ reportError(Input, EO.takeError());
+ llvm_unreachable("reportError shouldn't return in this case");
+ }
} // namespace llvm
namespace opts {