1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

Recommit "[ELF] - Add ability for DWARFContextInMemory to exit early when any error happen."

With fix in include folder character case:
#include "llvm/Codegen/AsmPrinter.h" -> #include "llvm/CodeGen/AsmPrinter.h"

Original commit message:

Change introduces error reporting policy for DWARFContextInMemory.
New callback provided by client is able to handle error on it's
side and return Halt or Continue.

That allows to either keep current behavior when parser prints all errors
but continues parsing object or implement something very different, like
stop parsing on a first error and report an error in a client style.

Differential revision: https://reviews.llvm.org/D34328

llvm-svn: 306517
This commit is contained in:
George Rimar 2017-06-28 08:21:19 +00:00
parent 7d64810efd
commit 2ca9fa318b
4 changed files with 81 additions and 11 deletions

View File

@ -289,6 +289,11 @@ private:
DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
};
/// Used as a return value for a error callback passed to DWARF context.
/// Callback should return Halt if client application wants to stop
/// object parsing, or should return Continue otherwise.
enum class ErrorPolicy { Halt, Continue };
/// DWARFContextInMemory is the simplest possible implementation of a
/// DWARFContext. It assumes all content is available in memory and stores
/// pointers to it.
@ -346,9 +351,14 @@ class DWARFContextInMemory : public DWARFContext {
Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
StringRef &Data);
/// Function used to handle default error reporting policy. Prints a error
/// message and returns Continue, so DWARF context ignores the error.
static ErrorPolicy defaultErrorHandler(Error E);
public:
DWARFContextInMemory(const object::ObjectFile &Obj,
const LoadedObjectInfo *L = nullptr);
DWARFContextInMemory(
const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler);
DWARFContextInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
uint8_t AddrSize,

View File

@ -870,13 +870,13 @@ static Expected<SymInfo> getSymbolInfo(const object::ObjectFile &Obj,
Expected<uint64_t> SymAddrOrErr = Sym->getAddress();
if (!SymAddrOrErr)
return createError("error: failed to compute symbol address: ",
return createError("failed to compute symbol address: ",
SymAddrOrErr.takeError());
// Also remember what section this symbol is in for later
auto SectOrErr = Sym->getSection();
if (!SectOrErr)
return createError("error: failed to get symbol section: ",
return createError("failed to get symbol section: ",
SectOrErr.takeError());
RSec = *SectOrErr;
@ -937,8 +937,14 @@ Error DWARFContextInMemory::maybeDecompress(const SectionRef &Sec,
return Error::success();
}
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
const LoadedObjectInfo *L)
ErrorPolicy DWARFContextInMemory::defaultErrorHandler(Error E) {
errs() << "error: " + toString(std::move(E)) << '\n';
return ErrorPolicy::Continue;
}
DWARFContextInMemory::DWARFContextInMemory(
const object::ObjectFile &Obj, const LoadedObjectInfo *L,
function_ref<ErrorPolicy(Error)> HandleError)
: FileName(Obj.getFileName()), IsLittleEndian(Obj.isLittleEndian()),
AddressSize(Obj.getBytesInAddress()) {
for (const SectionRef &Section : Obj.sections()) {
@ -961,9 +967,10 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
Section.getContents(data);
if (auto Err = maybeDecompress(Section, name, data)) {
errs() << "error: failed to decompress '" + name + "', " +
toString(std::move(Err))
<< '\n';
ErrorPolicy EP = HandleError(
createError("failed to decompress '" + name + "', ", std::move(Err)));
if (EP == ErrorPolicy::Halt)
return;
continue;
}
@ -1055,7 +1062,8 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
Expected<SymInfo> SymInfoOrErr = getSymbolInfo(Obj, Reloc, L, AddrCache);
if (!SymInfoOrErr) {
errs() << toString(SymInfoOrErr.takeError()) << '\n';
if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt)
return;
continue;
}
@ -1064,7 +1072,11 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
if (V.error()) {
SmallString<32> Name;
Reloc.getTypeName(Name);
errs() << "error: failed to compute relocation: " << Name << "\n";
ErrorPolicy EP = HandleError(
createError("failed to compute relocation: " + name + ", ",
errorCodeToError(object_error::parse_failed)));
if (EP == ErrorPolicy::Halt)
return;
continue;
}
RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val};

View File

@ -15,10 +15,14 @@
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/ObjectYAML/DWARFEmitter.h"
#include "llvm/ObjectYAML/DWARFYAML.h"
@ -2146,4 +2150,47 @@ TEST(DWARFDebugInfo, TestDwarfVerifyCUDontShareLineTable) {
"offset:");
}
TEST(DWARFDebugInfo, TestErrorReportingPolicy) {
initLLVMIfNeeded();
auto ExpectedDG = dwarfgen::Generator::create(Triple("x86_64-pc-linux"),
4 /*DwarfVersion*/);
if (HandleExpectedError(ExpectedDG))
return;
dwarfgen::Generator *DG = ExpectedDG.get().get();
AsmPrinter *AP = DG->getAsmPrinter();
MCContext *MC = DG->getMCContext();
// Emit two compressed sections with broken headers.
AP->OutStreamer->SwitchSection(
MC->getELFSection(".zdebug_foo", 0 /*Type*/, 0 /*Flags*/));
AP->OutStreamer->EmitBytes("0");
AP->OutStreamer->SwitchSection(
MC->getELFSection(".zdebug_bar", 0 /*Type*/, 0 /*Flags*/));
AP->OutStreamer->EmitBytes("0");
MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
// Case 1: error handler handles all errors. That allows
// DWARFContextInMemory
// to parse whole file and find both two errors we know about.
int Errors = 0;
DWARFContextInMemory Ctx1(*Obj.get(), nullptr, [&](Error E) {
++Errors;
consumeError(std::move(E));
return ErrorPolicy::Continue;
});
EXPECT_TRUE(Errors == 2);
// Case 2: error handler stops parsing of object after first error.
Errors = 0;
DWARFContextInMemory Ctx2(*Obj.get(), nullptr, [&](Error E) {
++Errors;
consumeError(std::move(E));
return ErrorPolicy::Halt;
});
EXPECT_TRUE(Errors == 1);
}
} // end anonymous namespace

View File

@ -215,6 +215,7 @@ public:
BumpPtrAllocator &getAllocator() { return Allocator; }
AsmPrinter *getAsmPrinter() const { return Asm.get(); }
MCContext *getMCContext() const { return MC.get(); }
DIEAbbrevSet &getAbbrevSet() { return Abbreviations; }
DwarfStringPool &getStringPool() { return *StringPool; }