Index: llvm/trunk/test/tools/llvm-dwarfdump/X86/brief.s =================================================================== --- llvm/trunk/test/tools/llvm-dwarfdump/X86/brief.s +++ llvm/trunk/test/tools/llvm-dwarfdump/X86/brief.s @@ -1,6 +1,9 @@ # RUN: llvm-mc %s -filetype obj -triple x86_64-apple-darwin -o - \ # RUN: | llvm-dwarfdump --debug-info --debug-line - \ # RUN: | FileCheck %s +# RUN: llvm-mc %s -filetype obj -triple x86_64-apple-darwin -o - \ +# RUN: | llvm-dwarfdump --debug-info --debug-line - -o %t +# RUN: cat %t | FileCheck %s # CHECK-NOT: .debug_abbrev contents: # Index: llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp =================================================================== --- llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -28,6 +28,7 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -136,7 +137,13 @@ static opt DumpUUID("uuid", desc("Show the UUID for each architecture"), cat(DwarfDumpCategory)); static alias DumpUUIDAlias("u", desc("Alias for -uuid"), aliasopt(DumpUUID)); - +static opt + OutputFilename("out-file", cl::init(""), + cl::desc("Redirect output to the specified file"), + cl::value_desc("filename")); +static alias OutputFilenameAlias("o", desc("Alias for -out-file"), + aliasopt(OutputFilename), + cat(DwarfDumpCategory)); static opt ShowChildren("show-children", desc("Show a debug info entry's children when selectively " @@ -175,11 +182,10 @@ /// @} //===----------------------------------------------------------------------===// - -static void error(StringRef Filename, std::error_code EC) { +static void error(StringRef Prefix, std::error_code EC) { if (!EC) return; - errs() << Filename << ": " << EC.message() << "\n"; + errs() << Prefix << ": " << EC.message() << "\n"; exit(1); } @@ -223,26 +229,27 @@ return false; } -using HandlerFn = std::function; +using HandlerFn = std::function; -static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx, - Twine Filename) { +static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename, + raw_ostream &OS) { logAllUnhandledErrors(DICtx.loadRegisterInfo(Obj), errs(), Filename.str() + ": "); // The UUID dump already contains all the same information. if (!(DumpType & DIDT_UUID) || DumpType == DIDT_All) - outs() << Filename << ":\tfile format " << Obj.getFileFormatName() << '\n'; + OS << Filename << ":\tfile format " << Obj.getFileFormatName() << '\n'; // Dump the complete DWARF structure. - DICtx.dump(outs(), getDumpOpts(), DumpOffsets); + DICtx.dump(OS, getDumpOpts(), DumpOffsets); return true; } static bool verifyObjectFile(ObjectFile &Obj, DWARFContext &DICtx, - Twine Filename) { + Twine Filename, raw_ostream &OS) { // Verify the DWARF and exit with non-zero exit status if verification // fails. - raw_ostream &stream = Quiet ? nulls() : outs(); + raw_ostream &stream = Quiet ? nulls() : OS; stream << "Verifying " << Filename.str() << ":\tfile format " << Obj.getFileFormatName() << "\n"; bool Result = DICtx.verify(stream, getDumpOpts()); @@ -254,10 +261,10 @@ } static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer, - HandlerFn HandleObj); + HandlerFn HandleObj, raw_ostream &OS); static bool handleArchive(StringRef Filename, Archive &Arch, - HandlerFn HandleObj) { + HandlerFn HandleObj, raw_ostream &OS) { bool Result = true; Error Err = Error::success(); for (auto Child : Arch.children(Err)) { @@ -266,7 +273,7 @@ auto NameOrErr = Child.getName(); error(Filename, errorToErrorCode(NameOrErr.takeError())); std::string Name = (Filename + "(" + NameOrErr.get() + ")").str(); - Result &= handleBuffer(Name, BuffOrErr.get(), HandleObj); + Result &= handleBuffer(Name, BuffOrErr.get(), HandleObj, OS); } error(Filename, errorToErrorCode(std::move(Err))); @@ -274,7 +281,7 @@ } static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer, - HandlerFn HandleObj) { + HandlerFn HandleObj, raw_ostream &OS) { Expected> BinOrErr = object::createBinary(Buffer); error(Filename, errorToErrorCode(BinOrErr.takeError())); @@ -282,7 +289,7 @@ if (auto *Obj = dyn_cast(BinOrErr->get())) { if (filterArch(*Obj)) { std::unique_ptr DICtx = DWARFContext::create(*Obj); - Result = HandleObj(*Obj, *DICtx, Filename); + Result = HandleObj(*Obj, *DICtx, Filename, OS); } } else if (auto *Fat = dyn_cast(BinOrErr->get())) @@ -293,29 +300,30 @@ auto &Obj = **MachOOrErr; if (filterArch(Obj)) { std::unique_ptr DICtx = DWARFContext::create(Obj); - Result &= HandleObj(Obj, *DICtx, ObjName); + Result &= HandleObj(Obj, *DICtx, ObjName, OS); } continue; } else consumeError(MachOOrErr.takeError()); if (auto ArchiveOrErr = ObjForArch.getAsArchive()) { error(ObjName, errorToErrorCode(ArchiveOrErr.takeError())); - Result &= handleArchive(ObjName, *ArchiveOrErr.get(), HandleObj); + Result &= handleArchive(ObjName, *ArchiveOrErr.get(), HandleObj, OS); continue; } else consumeError(ArchiveOrErr.takeError()); } else if (auto *Arch = dyn_cast(BinOrErr->get())) - Result = handleArchive(Filename, *Arch, HandleObj); + Result = handleArchive(Filename, *Arch, HandleObj, OS); return Result; } -static bool handleFile(StringRef Filename, HandlerFn HandleObj) { +static bool handleFile(StringRef Filename, HandlerFn HandleObj, + raw_ostream &OS) { ErrorOr> BuffOrErr = MemoryBuffer::getFileOrSTDIN(Filename); error(Filename, BuffOrErr.getError()); std::unique_ptr Buffer = std::move(BuffOrErr.get()); - return handleBuffer(Filename, *Buffer, HandleObj); + return handleBuffer(Filename, *Buffer, HandleObj, OS); } /// If the input path is a .dSYM bundle (as created by the dsymutil tool), @@ -371,6 +379,18 @@ return 0; } + std::unique_ptr OutputFile; + if (!OutputFilename.empty()) { + std::error_code EC; + OutputFile = + make_unique(OutputFilename, EC, sys::fs::F_None); + error("Unable to open output file" + OutputFilename, EC); + // Don't remove output file if we exit with an error. + OutputFile->keep(); + } + + raw_ostream &OS = OutputFile ? OutputFile->os() : outs(); + // Defaults to dumping all sections, unless brief mode is specified in which // case only the .debug_info section in dumped. #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \ @@ -405,13 +425,13 @@ if (Verify) { // If we encountered errors during verify, exit with a non-zero exit status. - if (!std::all_of(Objects.begin(), Objects.end(), [](std::string Object) { - return handleFile(Object, verifyObjectFile); + if (!std::all_of(Objects.begin(), Objects.end(), [&](std::string Object) { + return handleFile(Object, verifyObjectFile, OS); })) exit(1); } else for (auto Object : Objects) - handleFile(Object, dumpObjectFile); + handleFile(Object, dumpObjectFile, OS); return EXIT_SUCCESS; }