1c28a977bSCarlos Alberto Enciso //===-- llvm-debuginfo-analyzer.cpp - LLVM Debug info analysis utility ---===// 2c28a977bSCarlos Alberto Enciso // 3c28a977bSCarlos Alberto Enciso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c28a977bSCarlos Alberto Enciso // See https://llvm.org/LICENSE.txt for license information. 5c28a977bSCarlos Alberto Enciso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c28a977bSCarlos Alberto Enciso // 7c28a977bSCarlos Alberto Enciso //===----------------------------------------------------------------------===// 8c28a977bSCarlos Alberto Enciso // 9c28a977bSCarlos Alberto Enciso // This program is a utility that displays the logical view for the debug 10c28a977bSCarlos Alberto Enciso // information. 11c28a977bSCarlos Alberto Enciso // 12c28a977bSCarlos Alberto Enciso //===----------------------------------------------------------------------===// 13c28a977bSCarlos Alberto Enciso 14c28a977bSCarlos Alberto Enciso #include "Options.h" 15c28a977bSCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVOptions.h" 164f06d46fSCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/LVReaderHandler.h" 17c28a977bSCarlos Alberto Enciso #include "llvm/Support/COM.h" 18c28a977bSCarlos Alberto Enciso #include "llvm/Support/CommandLine.h" 19c28a977bSCarlos Alberto Enciso #include "llvm/Support/InitLLVM.h" 20c28a977bSCarlos Alberto Enciso #include "llvm/Support/TargetSelect.h" 21c28a977bSCarlos Alberto Enciso #include "llvm/Support/ToolOutputFile.h" 22c28a977bSCarlos Alberto Enciso #include "llvm/Support/WithColor.h" 23c28a977bSCarlos Alberto Enciso 24c28a977bSCarlos Alberto Enciso using namespace llvm; 25c28a977bSCarlos Alberto Enciso using namespace logicalview; 26c28a977bSCarlos Alberto Enciso using namespace cmdline; 27c28a977bSCarlos Alberto Enciso 28c28a977bSCarlos Alberto Enciso /// Create formatted StringError object. 29c28a977bSCarlos Alberto Enciso static StringRef ToolName = "llvm-debuginfo-analyzer"; 30c28a977bSCarlos Alberto Enciso template <typename... Ts> 31c28a977bSCarlos Alberto Enciso static void error(std::error_code EC, char const *Fmt, const Ts &...Vals) { 32c28a977bSCarlos Alberto Enciso if (!EC) 33c28a977bSCarlos Alberto Enciso return; 34c28a977bSCarlos Alberto Enciso std::string Buffer; 35c28a977bSCarlos Alberto Enciso raw_string_ostream Stream(Buffer); 36c28a977bSCarlos Alberto Enciso Stream << format(Fmt, Vals...); 37*6c0b1e75SJOE1994 WithColor::error(errs(), ToolName) << Buffer << "\n"; 38c28a977bSCarlos Alberto Enciso exit(1); 39c28a977bSCarlos Alberto Enciso } 40c28a977bSCarlos Alberto Enciso 414f06d46fSCarlos Alberto Enciso static void error(Error EC) { 424f06d46fSCarlos Alberto Enciso if (!EC) 434f06d46fSCarlos Alberto Enciso return; 444f06d46fSCarlos Alberto Enciso handleAllErrors(std::move(EC), [&](const ErrorInfoBase &EI) { 454f06d46fSCarlos Alberto Enciso errs() << "\n"; 464f06d46fSCarlos Alberto Enciso WithColor::error(errs(), ToolName) << EI.message() << ".\n"; 474f06d46fSCarlos Alberto Enciso exit(1); 484f06d46fSCarlos Alberto Enciso }); 494f06d46fSCarlos Alberto Enciso } 504f06d46fSCarlos Alberto Enciso 51c28a977bSCarlos Alberto Enciso /// If the input path is a .dSYM bundle (as created by the dsymutil tool), 52c28a977bSCarlos Alberto Enciso /// replace it with individual entries for each of the object files inside the 53c28a977bSCarlos Alberto Enciso /// bundle otherwise return the input path. 54c28a977bSCarlos Alberto Enciso static std::vector<std::string> expandBundle(const std::string &InputPath) { 55c28a977bSCarlos Alberto Enciso std::vector<std::string> BundlePaths; 56c28a977bSCarlos Alberto Enciso SmallString<256> BundlePath(InputPath); 57c28a977bSCarlos Alberto Enciso // Normalize input path. This is necessary to accept `bundle.dSYM/`. 58c28a977bSCarlos Alberto Enciso sys::path::remove_dots(BundlePath); 59c28a977bSCarlos Alberto Enciso // Manually open up the bundle to avoid introducing additional dependencies. 60c28a977bSCarlos Alberto Enciso if (sys::fs::is_directory(BundlePath) && 61c28a977bSCarlos Alberto Enciso sys::path::extension(BundlePath) == ".dSYM") { 62c28a977bSCarlos Alberto Enciso std::error_code EC; 63c28a977bSCarlos Alberto Enciso sys::path::append(BundlePath, "Contents", "Resources", "DWARF"); 64c28a977bSCarlos Alberto Enciso for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd; 65c28a977bSCarlos Alberto Enciso Dir != DirEnd && !EC; Dir.increment(EC)) { 66c28a977bSCarlos Alberto Enciso const std::string &Path = Dir->path(); 67c28a977bSCarlos Alberto Enciso sys::fs::file_status Status; 68c28a977bSCarlos Alberto Enciso EC = sys::fs::status(Path, Status); 69c28a977bSCarlos Alberto Enciso error(EC, "%s", Path.c_str()); 70c28a977bSCarlos Alberto Enciso switch (Status.type()) { 71c28a977bSCarlos Alberto Enciso case sys::fs::file_type::regular_file: 72c28a977bSCarlos Alberto Enciso case sys::fs::file_type::symlink_file: 73c28a977bSCarlos Alberto Enciso case sys::fs::file_type::type_unknown: 74c28a977bSCarlos Alberto Enciso BundlePaths.push_back(Path); 75c28a977bSCarlos Alberto Enciso break; 76c28a977bSCarlos Alberto Enciso default: /*ignore*/; 77c28a977bSCarlos Alberto Enciso } 78c28a977bSCarlos Alberto Enciso } 79c28a977bSCarlos Alberto Enciso } 80c28a977bSCarlos Alberto Enciso if (BundlePaths.empty()) 81c28a977bSCarlos Alberto Enciso BundlePaths.push_back(InputPath); 82c28a977bSCarlos Alberto Enciso return BundlePaths; 83c28a977bSCarlos Alberto Enciso } 84c28a977bSCarlos Alberto Enciso 85c28a977bSCarlos Alberto Enciso int main(int argc, char **argv) { 86c28a977bSCarlos Alberto Enciso InitLLVM X(argc, argv); 87c28a977bSCarlos Alberto Enciso 88c28a977bSCarlos Alberto Enciso // Initialize targets and assembly printers/parsers. 89c28a977bSCarlos Alberto Enciso llvm::InitializeAllTargetInfos(); 90c28a977bSCarlos Alberto Enciso llvm::InitializeAllTargetMCs(); 91c28a977bSCarlos Alberto Enciso InitializeAllDisassemblers(); 92c28a977bSCarlos Alberto Enciso 93c28a977bSCarlos Alberto Enciso llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded); 94c28a977bSCarlos Alberto Enciso 95c28a977bSCarlos Alberto Enciso cl::extrahelp HelpResponse( 96c28a977bSCarlos Alberto Enciso "\nPass @FILE as argument to read options from FILE.\n"); 97c28a977bSCarlos Alberto Enciso 98c28a977bSCarlos Alberto Enciso cl::HideUnrelatedOptions( 99c28a977bSCarlos Alberto Enciso {&AttributeCategory, &CompareCategory, &InternalCategory, &OutputCategory, 100c28a977bSCarlos Alberto Enciso &PrintCategory, &ReportCategory, &SelectCategory, &WarningCategory}); 101c28a977bSCarlos Alberto Enciso cl::ParseCommandLineOptions(argc, argv, 102c28a977bSCarlos Alberto Enciso "Printing a logical representation of low-level " 103c28a977bSCarlos Alberto Enciso "debug information.\n"); 104c28a977bSCarlos Alberto Enciso cl::PrintOptionValues(); 105c28a977bSCarlos Alberto Enciso 106c28a977bSCarlos Alberto Enciso std::error_code EC; 107c28a977bSCarlos Alberto Enciso ToolOutputFile OutputFile(OutputFilename, EC, sys::fs::OF_None); 108c28a977bSCarlos Alberto Enciso error(EC, "Unable to open output file %s", OutputFilename.c_str()); 109c28a977bSCarlos Alberto Enciso // Don't remove output file if we exit with an error. 110c28a977bSCarlos Alberto Enciso OutputFile.keep(); 111c28a977bSCarlos Alberto Enciso 112c28a977bSCarlos Alberto Enciso // Defaults to a.out if no filenames specified. 113c28a977bSCarlos Alberto Enciso if (InputFilenames.empty()) 114c28a977bSCarlos Alberto Enciso InputFilenames.push_back("a.out"); 115c28a977bSCarlos Alberto Enciso 116c28a977bSCarlos Alberto Enciso // Expand any .dSYM bundles to the individual object files contained therein. 117c28a977bSCarlos Alberto Enciso std::vector<std::string> Objects; 118c28a977bSCarlos Alberto Enciso for (const std::string &Filename : InputFilenames) { 119c28a977bSCarlos Alberto Enciso std::vector<std::string> Objs = expandBundle(Filename); 120c28a977bSCarlos Alberto Enciso Objects.insert(Objects.end(), Objs.begin(), Objs.end()); 121c28a977bSCarlos Alberto Enciso } 122c28a977bSCarlos Alberto Enciso 123c28a977bSCarlos Alberto Enciso propagateOptions(); 124c28a977bSCarlos Alberto Enciso ScopedPrinter W(OutputFile.os()); 1254f06d46fSCarlos Alberto Enciso LVReaderHandler ReaderHandler(Objects, W, ReaderOptions); 126c28a977bSCarlos Alberto Enciso 127c28a977bSCarlos Alberto Enciso // Print the command line. 128c28a977bSCarlos Alberto Enciso if (options().getInternalCmdline()) { 129c28a977bSCarlos Alberto Enciso raw_ostream &Stream = W.getOStream(); 130c28a977bSCarlos Alberto Enciso Stream << "\nCommand line:\n"; 131c28a977bSCarlos Alberto Enciso for (int Index = 0; Index < argc; ++Index) 132c28a977bSCarlos Alberto Enciso Stream << " " << argv[Index] << "\n"; 133c28a977bSCarlos Alberto Enciso Stream << "\n"; 134c28a977bSCarlos Alberto Enciso } 135c28a977bSCarlos Alberto Enciso 1364f06d46fSCarlos Alberto Enciso // Create readers and perform requested tasks on them. 1374f06d46fSCarlos Alberto Enciso if (Error Err = ReaderHandler.process()) 1384f06d46fSCarlos Alberto Enciso error(std::move(Err)); 1394f06d46fSCarlos Alberto Enciso 140c28a977bSCarlos Alberto Enciso return EXIT_SUCCESS; 141c28a977bSCarlos Alberto Enciso } 142