From: Jonas Devlieghere Date: Fri, 22 Sep 2017 09:20:57 +0000 (+0000) Subject: [dwarfdump] Add support for redirecting output to a file X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7080e068b5cec2acd8bca9cbefac511226cec450;p=llvm [dwarfdump] Add support for redirecting output to a file This patch adds the -o and --out-file options for compatibility with Darwin's dwarfdump. Differential revision: https://reviews.llvm.org/D38125 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313969 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/tools/llvm-dwarfdump/X86/brief.s b/test/tools/llvm-dwarfdump/X86/brief.s index 06a9d24dd0d..a4a34176dbc 100644 --- a/test/tools/llvm-dwarfdump/X86/brief.s +++ b/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: # diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 5c9fe2421be..e1021b204fe 100644 --- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/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 list 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 alias VerboseAlias("v", desc("Alias for -verbose"), aliasopt(Verbose), /// @} //===----------------------------------------------------------------------===// - -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 @@ static bool filterArch(ObjectFile &Obj) { 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 verifyObjectFile(ObjectFile &Obj, DWARFContext &DICtx, } 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 @@ static bool handleArchive(StringRef Filename, Archive &Arch, 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 handleArchive(StringRef Filename, Archive &Arch, } 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 @@ static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer, 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 @@ static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer, 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 @@ int main(int argc, char **argv) { 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 @@ int main(int argc, char **argv) { 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; }