Index: include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFContext.h +++ include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -263,10 +263,10 @@ const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U); /// Get a pointer to a parsed line table corresponding to a compile unit. - /// Report any parsing warnings using the callback. + /// Report any recoverable parsing problems using the callback. Expected getLineTableForUnit(DWARFUnit *U, - std::function WarnCallback); + std::function RecoverableErrorCallback); DataExtractor getStringExtractor() const { return DataExtractor(DObj->getStringSection(), false, 0); Index: include/llvm/DebugInfo/DWARF/DWARFDebugLine.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -249,7 +249,7 @@ /// Parse prologue and all rows. Error parse(DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, const DWARFContext &Ctx, const DWARFUnit *U, - std::function WarnCallback = warn, + std::function RecoverableErrorCallback = warn, raw_ostream *OS = nullptr); using RowVector = std::vector; @@ -270,10 +270,10 @@ }; const LineTable *getLineTable(uint32_t Offset) const; - Expected - getOrParseLineTable(DWARFDataExtractor &DebugLineData, uint32_t Offset, - const DWARFContext &Ctx, const DWARFUnit *U, - std::function WarnCallback = warn); + Expected getOrParseLineTable( + DWARFDataExtractor &DebugLineData, uint32_t Offset, + const DWARFContext &Ctx, const DWARFUnit *U, + std::function RecoverableErrorCallback = warn); /// Helper to allow for parsing of an entire .debug_line section in sequence. class SectionParser { @@ -289,23 +289,23 @@ /// Get the next line table from the section. Report any issues via the /// callbacks. /// - /// \param StringCallback - any issues that don't indicate that the line - /// table is invalid are reported using this function. - /// \param ErrorCallback - any issues that mean that the line table is - /// invalid are reported using this callback. + /// \param RecoverableErrorCallback - any issues that don't prevent further + /// parsing of the table will be reported through this callback. + /// \param UnrecoverableErrorCallback - any issues that prevent further + /// parsing of the table will be reported through this callback. /// \param OS - if not null, the parser will print information about the /// table as it parses it. - LineTable parseNext( - function_ref StringCallback = warn, - function_ref ErrorCallback = warnForError, - raw_ostream *OS = nullptr); + LineTable + parseNext(function_ref RecoverableErrorCallback = warn, + function_ref UnrecoverableErrorCallback = warn, + raw_ostream *OS = nullptr); /// Skip the current line table and go to the following line table (if /// present) immediately. /// /// \param ErrorCallback - report any prologue parsing issues via this /// callback. - void skip(function_ref ErrorCallback = warnForError); + void skip(function_ref ErrorCallback = warn); /// Indicates if the parser has parsed as much as possible. /// @@ -328,17 +328,11 @@ bool Done = false; }; - /// Helper function for DWARFDebugLine parse functions, to report issues that - /// don't prevent parsing the remainder of the table as warnings. - /// - /// \param Message The message to report. - static void warn(StringRef Message); - - /// Helper function for DWARFDebugLine parse functions, to report issues that - /// prevent parsing the remainder of the table as warnings. + /// Helper function for DWARFDebugLine parse functions, to report issues + /// identified during parsing. /// /// \param Err The Error to report. - static void warnForError(Error Err); + static void warn(Error Err); private: struct ParsingState { Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -363,8 +363,7 @@ } OS << "debug_line[" << format("0x%8.8x", Parser.getOffset()) << "]\n"; if (DumpOpts.Verbose) { - Parser.parseNext(DWARFDebugLine::warn, DWARFDebugLine::warnForError, - &OS); + Parser.parseNext(DWARFDebugLine::warn, DWARFDebugLine::warn, &OS); } else { DWARFDebugLine::LineTable LineTable = Parser.parseNext(); LineTable.dump(OS, DumpOpts); @@ -750,15 +749,14 @@ Expected ExpectedLineTable = getLineTableForUnit(U, DWARFDebugLine::warn); if (!ExpectedLineTable) { - DWARFDebugLine::warnForError(ExpectedLineTable.takeError()); + DWARFDebugLine::warn(ExpectedLineTable.takeError()); return nullptr; } return *ExpectedLineTable; } -Expected -DWARFContext::getLineTableForUnit(DWARFUnit *U, - std::function WarnCallback) { +Expected DWARFContext::getLineTableForUnit( + DWARFUnit *U, std::function RecoverableErrorCallback) { if (!Line) Line.reset(new DWARFDebugLine); @@ -783,7 +781,7 @@ DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(), U->getAddressByteSize()); return Line->getOrParseLineTable(lineData, stmtOffset, *this, U, - WarnCallback); + RecoverableErrorCallback); } void DWARFContext::parseCompileUnits() { Index: lib/DebugInfo/DWARF/DWARFDebugLine.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -287,6 +287,10 @@ inconvertibleErrorCode()); } +static Error createError(char const *Msg) { + return make_error(Msg, inconvertibleErrorCode()); +} + Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, const DWARFContext &Ctx, @@ -464,7 +468,7 @@ Expected DWARFDebugLine::getOrParseLineTable( DWARFDataExtractor &DebugLineData, uint32_t Offset, const DWARFContext &Ctx, - const DWARFUnit *U, std::function WarnCallback) { + const DWARFUnit *U, std::function RecoverableErrorCallback) { if (!DebugLineData.isValidOffset(Offset)) return createError("offset 0x%8.8" PRIx32 " is not a valid debug line section offset", @@ -474,7 +478,8 @@ LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable())); LineTable *LT = &Pos.first->second; if (Pos.second) { - if (Error Err = LT->parse(DebugLineData, &Offset, Ctx, U, WarnCallback)) + if (Error Err = + LT->parse(DebugLineData, &Offset, Ctx, U, RecoverableErrorCallback)) return std::move(Err); return LT; } @@ -484,7 +489,7 @@ Error DWARFDebugLine::LineTable::parse( DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, const DWARFContext &Ctx, const DWARFUnit *U, - std::function WarnCallback, raw_ostream *OS) { + std::function RecoverableErrorCallback, raw_ostream *OS) { const uint32_t DebugLineOffset = *OffsetPtr; clear(); @@ -841,7 +846,8 @@ } if (!State.Sequence.Empty) - WarnCallback("last sequence in debug line table is not terminated!"); + RecoverableErrorCallback( + createError("last sequence in debug line table is not terminated!")); // Sort all sequences so that address lookup will work faster. if (!Sequences.empty()) { @@ -1069,15 +1075,16 @@ } DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext( - function_ref StringCallback, - function_ref ErrorCallback, raw_ostream *OS) { + function_ref RecoverableErrorCallback, + function_ref UnrecoverableErrorCallback, raw_ostream *OS) { assert(DebugLineData.isValidOffset(Offset) && "parsing should have terminated"); DWARFUnit *U = prepareToParse(Offset); uint32_t OldOffset = Offset; LineTable LT; - Error Err = LT.parse(DebugLineData, &Offset, Context, U, StringCallback, OS); - ErrorCallback(std::move(Err)); + if (Error Err = LT.parse(DebugLineData, &Offset, Context, U, + RecoverableErrorCallback, OS)) + UnrecoverableErrorCallback(std::move(Err)); moveToNextTable(OldOffset, LT.Prologue); return LT; } @@ -1089,8 +1096,8 @@ DWARFUnit *U = prepareToParse(Offset); uint32_t OldOffset = Offset; LineTable LT; - Error Err = LT.Prologue.parse(DebugLineData, &Offset, Context, U); - ErrorCallback(std::move(Err)); + if (Error Err = LT.Prologue.parse(DebugLineData, &Offset, Context, U)) + ErrorCallback(std::move(Err)); moveToNextTable(OldOffset, LT.Prologue); } @@ -1119,11 +1126,8 @@ } } -void DWARFDebugLine::warn(StringRef Message) { - WithColor::warning() << Message << '\n'; -} - -void DWARFDebugLine::warnForError(Error Err) { - handleAllErrors(std::move(Err), - [](ErrorInfoBase &Info) { warn(Info.message()); }); +void DWARFDebugLine::warn(Error Err) { + handleAllErrors(std::move(Err), [](ErrorInfoBase &Info) { + WithColor::warning() << Info.message() << '\n'; + }); } Index: tools/dsymutil/DwarfLinker.cpp =================================================================== --- tools/dsymutil/DwarfLinker.cpp +++ tools/dsymutil/DwarfLinker.cpp @@ -3606,7 +3606,7 @@ Error Err = LineTable.parse(LineExtractor, &StmtOffset, OrigDwarf, &Unit.getOrigUnit()); - DWARFDebugLine::warnForError(std::move(Err)); + DWARFDebugLine::warn(std::move(Err)); // This vector is the output line table. std::vector NewRows; Index: unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp =================================================================== --- unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp +++ unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp @@ -25,14 +25,17 @@ namespace { struct CommonFixture { CommonFixture() - : LineData("", true, 0), - RecordIssue(std::bind(&CommonFixture::recordIssue, this, - std::placeholders::_1)), - FoundError(Error::success()), - RecordError(std::bind(&CommonFixture::recordError, this, - std::placeholders::_1)){}; - - ~CommonFixture() { EXPECT_FALSE(FoundError); } + : LineData("", true, 0), Recoverable(Error::success()), + RecordRecoverable(std::bind(&CommonFixture::recordRecoverable, this, + std::placeholders::_1)), + Unrecoverable(Error::success()), + RecordUnrecoverable(std::bind(&CommonFixture::recordUnrecoverable, this, + std::placeholders::_1)){}; + + ~CommonFixture() { + EXPECT_FALSE(Recoverable); + EXPECT_FALSE(Unrecoverable); + } bool setupGenerator(uint16_t Version = 4) { Triple T = getHostTripleForAddrSize(8); @@ -82,9 +85,11 @@ return DWARFDebugLine::SectionParser(LineData, *Context, CUs, TUs); } - void recordIssue(StringRef Message) { IssueMessage = Message; } - void recordError(Error Err) { - FoundError = joinErrors(std::move(FoundError), std::move(Err)); + void recordRecoverable(Error Err) { + Recoverable = joinErrors(std::move(Recoverable), std::move(Err)); + } + void recordUnrecoverable(Error Err) { + Unrecoverable = joinErrors(std::move(Unrecoverable), std::move(Err)); } void checkError(ArrayRef ExpectedMsgs, Error Err) { @@ -108,9 +113,9 @@ void checkGetOrParseLineTableEmitsError(StringRef ExpectedMsg, uint64_t Offset = 0) { auto ExpectedLineTable = Line.getOrParseLineTable( - LineData, Offset, *Context, nullptr, RecordIssue); + LineData, Offset, *Context, nullptr, RecordRecoverable); EXPECT_FALSE(ExpectedLineTable); - EXPECT_TRUE(IssueMessage.empty()); + EXPECT_FALSE(Recoverable); checkError(ExpectedMsg, ExpectedLineTable.takeError()); } @@ -119,10 +124,10 @@ std::unique_ptr Context; DWARFDataExtractor LineData; DWARFDebugLine Line; - std::string IssueMessage; - std::function RecordIssue; - Error FoundError; - std::function RecordError; + Error Recoverable; + std::function RecordRecoverable; + Error Unrecoverable; + std::function RecordUnrecoverable; SmallVector, 2> CUs; std::deque> TUs; @@ -240,21 +245,21 @@ generate(); - auto ExpectedLineTable = - Line.getOrParseLineTable(LineData, 0, *Context, nullptr, RecordIssue); + auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, + nullptr, RecordRecoverable); ASSERT_TRUE(ExpectedLineTable.operator bool()); - EXPECT_TRUE(IssueMessage.empty()); + EXPECT_FALSE(Recoverable); const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable; checkDefaultPrologue(Version, Format, Expected->Prologue, 16); EXPECT_EQ(Expected->Sequences.size(), 1u); uint64_t SecondOffset = Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength; - IssueMessage.clear(); + Recoverable = Error::success(); auto ExpectedLineTable2 = Line.getOrParseLineTable( - LineData, SecondOffset, *Context, nullptr, RecordIssue); + LineData, SecondOffset, *Context, nullptr, RecordRecoverable); ASSERT_TRUE(ExpectedLineTable2.operator bool()); - EXPECT_TRUE(IssueMessage.empty()); + EXPECT_FALSE(Recoverable); const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2; checkDefaultPrologue(Version, Format, Expected2->Prologue, 32); EXPECT_EQ(Expected2->Sequences.size(), 2u); @@ -263,18 +268,18 @@ // Check that if the same offset is requested, the exact same pointer is // returned. - IssueMessage.clear(); - auto ExpectedLineTable3 = - Line.getOrParseLineTable(LineData, 0, *Context, nullptr, RecordIssue); + Recoverable = Error::success(); + auto ExpectedLineTable3 = Line.getOrParseLineTable( + LineData, 0, *Context, nullptr, RecordRecoverable); ASSERT_TRUE(ExpectedLineTable3.operator bool()); - EXPECT_TRUE(IssueMessage.empty()); + EXPECT_FALSE(Recoverable); EXPECT_EQ(Expected, *ExpectedLineTable3); - IssueMessage.clear(); + Recoverable = Error::success(); auto ExpectedLineTable4 = Line.getOrParseLineTable( - LineData, SecondOffset, *Context, nullptr, RecordIssue); + LineData, SecondOffset, *Context, nullptr, RecordRecoverable); ASSERT_TRUE(ExpectedLineTable4.operator bool()); - EXPECT_TRUE(IssueMessage.empty()); + EXPECT_FALSE(Recoverable); EXPECT_EQ(Expected2, *ExpectedLineTable4); // TODO: Add tests that show that the body of the programs have been read @@ -404,7 +409,7 @@ 2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32. std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields. std::make_pair(4, DWARF64), // Test v4 fields and DWARF64. - std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)),); + std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)), ); TEST_F(DebugLineBasicFixture, ErrorForInvalidExtendedOpcodeLength) { if (!setupGenerator()) @@ -455,10 +460,10 @@ generate(); - auto ExpectedLineTable = - Line.getOrParseLineTable(LineData, 0, *Context, nullptr, RecordIssue); - EXPECT_EQ(IssueMessage, - "last sequence in debug line table is not terminated!"); + auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, + nullptr, RecordRecoverable); + checkError("last sequence in debug line table is not terminated!", + std::move(Recoverable)); ASSERT_TRUE(ExpectedLineTable.operator bool()); EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u); // The unterminated sequence is not added to the sequence list. @@ -474,21 +479,22 @@ EXPECT_EQ(Parser.getOffset(), 0u); ASSERT_FALSE(Parser.done()); - DWARFDebugLine::LineTable Parsed = Parser.parseNext(RecordIssue, RecordError); + DWARFDebugLine::LineTable Parsed = + Parser.parseNext(RecordRecoverable, RecordUnrecoverable); checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16); EXPECT_EQ(Parsed.Sequences.size(), 1u); EXPECT_EQ(Parser.getOffset(), 62u); ASSERT_FALSE(Parser.done()); DWARFDebugLine::LineTable Parsed2 = - Parser.parseNext(RecordIssue, RecordError); + Parser.parseNext(RecordRecoverable, RecordUnrecoverable); checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16); EXPECT_EQ(Parsed2.Sequences.size(), 1u); EXPECT_EQ(Parser.getOffset(), 136u); EXPECT_TRUE(Parser.done()); - EXPECT_TRUE(IssueMessage.empty()); - EXPECT_FALSE(FoundError); + EXPECT_FALSE(Recoverable); + EXPECT_FALSE(Unrecoverable); } TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) { @@ -500,15 +506,15 @@ EXPECT_EQ(Parser.getOffset(), 0u); ASSERT_FALSE(Parser.done()); - Parser.skip(RecordError); + Parser.skip(RecordUnrecoverable); EXPECT_EQ(Parser.getOffset(), 62u); ASSERT_FALSE(Parser.done()); - Parser.skip(RecordError); + Parser.skip(RecordUnrecoverable); EXPECT_EQ(Parser.getOffset(), 136u); EXPECT_TRUE(Parser.done()); - EXPECT_FALSE(FoundError); + EXPECT_FALSE(Unrecoverable); } TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) { @@ -531,15 +537,15 @@ generate(); DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); - Parser.parseNext(RecordIssue, RecordError); + Parser.parseNext(RecordRecoverable, RecordUnrecoverable); EXPECT_EQ(Parser.getOffset(), 4u); EXPECT_TRUE(Parser.done()); - EXPECT_TRUE(IssueMessage.empty()); + EXPECT_FALSE(Recoverable); checkError("parsing line table prologue at offset 0x00000000 unsupported " "reserved unit length found of value 0xffffff00", - std::move(FoundError)); + std::move(Unrecoverable)); } TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) { @@ -552,14 +558,14 @@ generate(); DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); - Parser.skip(RecordError); + Parser.skip(RecordUnrecoverable); EXPECT_EQ(Parser.getOffset(), 4u); EXPECT_TRUE(Parser.done()); checkError("parsing line table prologue at offset 0x00000000 unsupported " "reserved unit length found of value 0xffffff00", - std::move(FoundError)); + std::move(Unrecoverable)); } TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) { @@ -573,18 +579,18 @@ generate(); DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); - Parser.parseNext(RecordIssue, RecordError); + Parser.parseNext(RecordRecoverable, RecordUnrecoverable); ASSERT_FALSE(Parser.done()); - Parser.parseNext(RecordIssue, RecordError); + Parser.parseNext(RecordRecoverable, RecordUnrecoverable); EXPECT_TRUE(Parser.done()); - EXPECT_TRUE(IssueMessage.empty()); + EXPECT_FALSE(Recoverable); checkError({"parsing line table prologue at offset 0x00000000 found " "unsupported version 0x00", "parsing line table prologue at offset 0x00000006 found " "unsupported version 0x01"}, - std::move(FoundError)); + std::move(Unrecoverable)); } TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) { @@ -601,21 +607,21 @@ generate(); DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); - Parser.parseNext(RecordIssue, RecordError); - EXPECT_TRUE(IssueMessage.empty()); + Parser.parseNext(RecordRecoverable, RecordUnrecoverable); + EXPECT_FALSE(Recoverable); ASSERT_FALSE(Parser.done()); checkError( "unexpected line op length at offset 0x00000030 expected 0x42 found 0x01", - std::move(FoundError)); + std::move(Unrecoverable)); // Reset the error state so that it does not confuse the next set of checks. - FoundError = Error::success(); - Parser.parseNext(RecordIssue, RecordError); + Unrecoverable = Error::success(); + Parser.parseNext(RecordRecoverable, RecordUnrecoverable); EXPECT_TRUE(Parser.done()); - EXPECT_EQ(IssueMessage, - "last sequence in debug line table is not terminated!"); - EXPECT_TRUE(!FoundError); + checkError("last sequence in debug line table is not terminated!", + std::move(Recoverable)); + EXPECT_FALSE(Unrecoverable); } TEST_F(DebugLineBasicFixture, @@ -630,9 +636,9 @@ generate(); DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); - Parser.skip(RecordError); + Parser.skip(RecordUnrecoverable); ASSERT_FALSE(Parser.done()); - Parser.skip(RecordError); + Parser.skip(RecordUnrecoverable); EXPECT_TRUE(Parser.done()); @@ -640,7 +646,7 @@ "unsupported version 0x00", "parsing line table prologue at offset 0x00000006 found " "unsupported version 0x01"}, - std::move(FoundError)); + std::move(Unrecoverable)); } TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) { @@ -652,10 +658,10 @@ generate(); DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); - Parser.skip(RecordError); + Parser.skip(RecordUnrecoverable); EXPECT_TRUE(Parser.done()); - EXPECT_TRUE(!FoundError); + EXPECT_FALSE(Unrecoverable); } } // end anonymous namespace