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:
parent
7d64810efd
commit
2ca9fa318b
@ -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,
|
||||
|
@ -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};
|
||||
|
@ -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
|
||||
|
@ -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; }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user