diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -513,7 +513,6 @@ } OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset()) << "]\n"; - OS.flush(); if (DumpOpts.Verbose) { Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler, &OS); } else { @@ -521,7 +520,6 @@ Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler); LineTable.dump(OS, DumpOpts); } - OS.flush(); } }; diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test @@ -4,39 +4,41 @@ ## Show that a bad length stops parsing of the section. # RUN: llvm-mc -triple x86_64-pc-linux %S/Inputs/debug_line_reserved_length.s -filetype=obj -o %t-reserved.o # RUN: llvm-dwarfdump -debug-line %t-reserved.o 2>&1 \ -# RUN: | FileCheck %s --check-prefixes=FIRST,FATAL,RESERVED +# RUN: | FileCheck %s --check-prefixes=HEADER,FIRST,FATAL,RESERVED # RUN: llvm-dwarfdump -debug-line %t-reserved.o -verbose 2>&1 \ -# RUN: | FileCheck %s --check-prefixes=FIRST,FATAL,RESERVED +# RUN: | FileCheck %s --check-prefixes=HEADER,FIRST,FATAL,RESERVED ## We only produce warnings for malformed tables after the specified unit if ## parsing can continue. # RUN: llvm-dwarfdump -debug-line=0 %t-reserved.o 2>&1 \ -# RUN: | FileCheck %s --check-prefixes=FIRST,NOLATER,RESERVED +# RUN: | FileCheck %s --check-prefixes=HEADER,FIRST,NOLATER,RESERVED ## Stop looking for the specified unit, if a fatally-bad prologue is detected. # RUN: llvm-dwarfdump -debug-line=0x4b %t-reserved.o 2>&1 \ -# RUN: | FileCheck %s --check-prefixes=NOFIRST,NOLATER,RESERVED +# RUN: | FileCheck %s --check-prefixes=HEADER,NOFIRST,NOLATER,RESERVED ## Show that non-fatal errors do not prevent parsing the rest of the section. # RUN: llvm-mc -triple x86_64-pc-linux %S/Inputs/debug_line_malformed.s -filetype=obj -o %t-malformed.o # RUN: llvm-dwarfdump -debug-line %t-malformed.o 2> %t-malformed.err \ -# RUN: | FileCheck %s --check-prefixes=FIRST,NONFATAL,LAST --implicit-check-not='debug_line[{{.*}}]' +# RUN: | FileCheck %s --check-prefixes=HEADER,FIRST,NONFATAL,LAST --implicit-check-not='debug_line[{{.*}}]' # RUN: FileCheck %s --input-file=%t-malformed.err --check-prefixes=ALL,OTHER # RUN: llvm-dwarfdump -debug-line %t-malformed.o -verbose 2> %t-malformed-verbose.err \ -# RUN: | FileCheck %s --check-prefixes=FIRST,VERBOSE,NONFATAL,LAST --implicit-check-not='debug_line[{{.*}}]' \ +# RUN: | FileCheck %s --check-prefixes=HEADER,FIRST,VERBOSE,NONFATAL,LAST --implicit-check-not='debug_line[{{.*}}]' \ # RUN: --implicit-check-not=' DW_LNS' --implicit-check-not=' DW_LNE' --implicit-check-not='address +=' # RUN: FileCheck %s --input-file=%t-malformed-verbose.err --check-prefixes=ALL,OTHER ## We should still produce warnings for malformed tables after the specified unit. # RUN: llvm-dwarfdump -debug-line=0 %t-malformed.o 2> %t-malformed-off-first.err \ -# RUN: | FileCheck %s --check-prefixes=FIRST,NOLATER +# RUN: | FileCheck %s --check-prefixes=HEADER,FIRST,NOLATER # RUN: FileCheck %s --input-file=%t-malformed-off-first.err --check-prefix=ALL ## Don't stop looking for the later unit if non-fatal issues are found. # RUN: llvm-dwarfdump -debug-line=0x419 %t-malformed.o 2> %t-malformed-off-last.err \ -# RUN: | FileCheck %s --check-prefix=LAST --implicit-check-not='debug_line[{{.*}}]' +# RUN: | FileCheck %s --check-prefixes=HEADER,LAST --implicit-check-not='debug_line[{{.*}}]' # RUN: FileCheck %s --input-file=%t-malformed-off-last.err --check-prefix=ALL +# HEADER: .debug_line contents: + # FIRST: debug_line[0x00000000] # VERBOSE: DW_LNE_set_address (0x000000000badbeef) # VERBOSE-NEXT: DW_LNE_end_sequence diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp --- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -252,6 +252,7 @@ DumpOpts.SummarizeTypes = SummarizeTypes; DumpOpts.Verbose = Verbose; DumpOpts.RecoverableErrorHandler = C.getRecoverableErrorHandler(); + DumpOpts.WarningHandler = C.getWarningHandler(); // In -verify mode, print DIEs without children in error messages. if (Verify) return DumpOpts.noImplicitRecursion(); @@ -495,27 +496,36 @@ error(Filename, errorToErrorCode(BinOrErr.takeError())); bool Result = true; + auto ReportMessage = [&](function_ref ErrorHandler, Error E) { + // Flush the main output stream before reporting the error to ensure it + // appears in the right place if the two are directed to the same location. + OS.flush(); + ErrorHandler(std::move(E)); + }; auto RecoverableErrorHandler = [&](Error E) { Result = false; - WithColor::defaultErrorHandler(std::move(E)); + ReportMessage(WithColor::defaultErrorHandler, std::move(E)); + }; + auto WarningHandler = [&](Error E) { + ReportMessage(WithColor::defaultWarningHandler, std::move(E)); }; + if (auto *Obj = dyn_cast(BinOrErr->get())) { if (filterArch(*Obj)) { - std::unique_ptr DICtx = - DWARFContext::create(*Obj, nullptr, "", RecoverableErrorHandler); + std::unique_ptr DICtx = DWARFContext::create( + *Obj, nullptr, "", RecoverableErrorHandler, WarningHandler); if (!HandleObj(*Obj, *DICtx, Filename, OS)) Result = false; } - } - else if (auto *Fat = dyn_cast(BinOrErr->get())) + } else if (auto *Fat = dyn_cast(BinOrErr->get())) for (auto &ObjForArch : Fat->objects()) { std::string ObjName = (Filename + "(" + ObjForArch.getArchFlagName() + ")").str(); if (auto MachOOrErr = ObjForArch.getAsObjectFile()) { auto &Obj = **MachOOrErr; if (filterArch(Obj)) { - std::unique_ptr DICtx = - DWARFContext::create(Obj, nullptr, "", RecoverableErrorHandler); + std::unique_ptr DICtx = DWARFContext::create( + Obj, nullptr, "", RecoverableErrorHandler, WarningHandler); if (!HandleObj(Obj, *DICtx, ObjName, OS)) Result = false; }