llvm.org GIT mirror llvm / 75f5720
[ELF] - Add ability for DWARFContextInMemory to exit early when any error happen. 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306512 91177308-0d34-0410-b5e6-96231b3b80d8 George Rimar 2 years ago
4 changed file(s) with 81 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
288288 DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
289289 };
290290
291 /// Used as a return value for a error callback passed to DWARF context.
292 /// Callback should return Halt if client application wants to stop
293 /// object parsing, or should return Continue otherwise.
294 enum class ErrorPolicy { Halt, Continue };
295
291296 /// DWARFContextInMemory is the simplest possible implementation of a
292297 /// DWARFContext. It assumes all content is available in memory and stores
293298 /// pointers to it.
345350 Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
346351 StringRef &Data);
347352
353 /// Function used to handle default error reporting policy. Prints a error
354 /// message and returns Continue, so DWARF context ignores the error.
355 static ErrorPolicy defaultErrorHandler(Error E);
356
348357 public:
349 DWARFContextInMemory(const object::ObjectFile &Obj,
350 const LoadedObjectInfo *L = nullptr);
358 DWARFContextInMemory(
359 const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
360 function_ref HandleError = defaultErrorHandler);
351361
352362 DWARFContextInMemory(const StringMap> &Sections,
353363 uint8_t AddrSize,
869869
870870 Expected SymAddrOrErr = Sym->getAddress();
871871 if (!SymAddrOrErr)
872 return createError("error: failed to compute symbol address: ",
872 return createError("failed to compute symbol address: ",
873873 SymAddrOrErr.takeError());
874874
875875 // Also remember what section this symbol is in for later
876876 auto SectOrErr = Sym->getSection();
877877 if (!SectOrErr)
878 return createError("error: failed to get symbol section: ",
878 return createError("failed to get symbol section: ",
879879 SectOrErr.takeError());
880880
881881 RSec = *SectOrErr;
936936 return Error::success();
937937 }
938938
939 DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
940 const LoadedObjectInfo *L)
939 ErrorPolicy DWARFContextInMemory::defaultErrorHandler(Error E) {
940 errs() << "error: " + toString(std::move(E)) << '\n';
941 return ErrorPolicy::Continue;
942 }
943
944 DWARFContextInMemory::DWARFContextInMemory(
945 const object::ObjectFile &Obj, const LoadedObjectInfo *L,
946 function_ref HandleError)
941947 : FileName(Obj.getFileName()), IsLittleEndian(Obj.isLittleEndian()),
942948 AddressSize(Obj.getBytesInAddress()) {
943949 for (const SectionRef &Section : Obj.sections()) {
960966 Section.getContents(data);
961967
962968 if (auto Err = maybeDecompress(Section, name, data)) {
963 errs() << "error: failed to decompress '" + name + "', " +
964 toString(std::move(Err))
965 << '\n';
969 ErrorPolicy EP = HandleError(
970 createError("failed to decompress '" + name + "', ", std::move(Err)));
971 if (EP == ErrorPolicy::Halt)
972 return;
966973 continue;
967974 }
968975
10541061
10551062 Expected SymInfoOrErr = getSymbolInfo(Obj, Reloc, L, AddrCache);
10561063 if (!SymInfoOrErr) {
1057 errs() << toString(SymInfoOrErr.takeError()) << '\n';
1064 if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt)
1065 return;
10581066 continue;
10591067 }
10601068
10631071 if (V.error()) {
10641072 SmallString<32> Name;
10651073 Reloc.getTypeName(Name);
1066 errs() << "error: failed to compute relocation: " << Name << "\n";
1074 ErrorPolicy EP = HandleError(
1075 createError("failed to compute relocation: " + name + ", ",
1076 errorCodeToError(object_error::parse_failed)));
1077 if (EP == ErrorPolicy::Halt)
1078 return;
10671079 continue;
10681080 }
10691081 RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val};
1414 #include "llvm/ADT/Triple.h"
1515 #include "llvm/BinaryFormat/Dwarf.h"
1616 #include "llvm/Config/llvm-config.h"
17 #include "llvm/Codegen/AsmPrinter.h"
1718 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
1819 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
1920 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
2021 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
22 #include "llvm/MC/MCContext.h"
23 #include "llvm/MC/MCSectionELF.h"
24 #include "llvm/MC/MCStreamer.h"
2125 #include "llvm/Object/ObjectFile.h"
2226 #include "llvm/ObjectYAML/DWARFEmitter.h"
2327 #include "llvm/ObjectYAML/DWARFYAML.h"
21452149 "offset:");
21462150 }
21472151
2152 TEST(DWARFDebugInfo, TestErrorReportingPolicy) {
2153 initLLVMIfNeeded();
2154 auto ExpectedDG = dwarfgen::Generator::create(Triple("x86_64-pc-linux"),
2155 4 /*DwarfVersion*/);
2156 if (HandleExpectedError(ExpectedDG))
2157 return;
2158 dwarfgen::Generator *DG = ExpectedDG.get().get();
2159 AsmPrinter *AP = DG->getAsmPrinter();
2160 MCContext *MC = DG->getMCContext();
2161
2162 // Emit two compressed sections with broken headers.
2163 AP->OutStreamer->SwitchSection(
2164 MC->getELFSection(".zdebug_foo", 0 /*Type*/, 0 /*Flags*/));
2165 AP->OutStreamer->EmitBytes("0");
2166 AP->OutStreamer->SwitchSection(
2167 MC->getELFSection(".zdebug_bar", 0 /*Type*/, 0 /*Flags*/));
2168 AP->OutStreamer->EmitBytes("0");
2169
2170 MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
2171 auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
2172 EXPECT_TRUE((bool)Obj);
2173
2174 // Case 1: error handler handles all errors. That allows
2175 // DWARFContextInMemory
2176 // to parse whole file and find both two errors we know about.
2177 int Errors = 0;
2178 DWARFContextInMemory Ctx1(*Obj.get(), nullptr, [&](Error E) {
2179 ++Errors;
2180 consumeError(std::move(E));
2181 return ErrorPolicy::Continue;
2182 });
2183 EXPECT_TRUE(Errors == 2);
2184
2185 // Case 2: error handler stops parsing of object after first error.
2186 Errors = 0;
2187 DWARFContextInMemory Ctx2(*Obj.get(), nullptr, [&](Error E) {
2188 ++Errors;
2189 consumeError(std::move(E));
2190 return ErrorPolicy::Halt;
2191 });
2192 EXPECT_TRUE(Errors == 1);
2193 }
2194
21482195 } // end anonymous namespace
214214
215215 BumpPtrAllocator &getAllocator() { return Allocator; }
216216 AsmPrinter *getAsmPrinter() const { return Asm.get(); }
217 MCContext *getMCContext() const { return MC.get(); }
217218 DIEAbbrevSet &getAbbrevSet() { return Abbreviations; }
218219 DwarfStringPool &getStringPool() { return *StringPool; }
219220