diff options
author | George Rimar <grimar@accesssoftek.com> | 2019-08-08 07:17:35 +0000 |
---|---|---|
committer | George Rimar <grimar@accesssoftek.com> | 2019-08-08 07:17:35 +0000 |
commit | 67ea32a00709f5f2d999002d747c58ac357223fd (patch) | |
tree | 997907a1a6b02d74da239524972b3beacef356b7 /llvm/tools | |
parent | 6fd13f0849573aeec26f28ab0927eea0b5a7ccb9 (diff) | |
download | llvm-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.cpp | 43 | ||||
-rw-r--r-- | llvm/tools/llvm-readobj/llvm-readobj.cpp | 6 | ||||
-rw-r--r-- | llvm/tools/llvm-readobj/llvm-readobj.h | 10 |
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 { |