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