1//===- bolt/tools/binary-analysis/binary-analysis.cpp ---------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This is a generic binary analysis tool, where multiple different specific
10// binary analyses can be plugged in to. The binary analyses are mostly built
11// on top of BOLT components.
12//
13//===----------------------------------------------------------------------===//
14
15#include "bolt/Rewrite/RewriteInstance.h"
16#include "bolt/Utils/CommandLineOpts.h"
17#include "llvm/MC/TargetRegistry.h"
18#include "llvm/Object/Binary.h"
19#include "llvm/Object/ELFObjectFile.h"
20#include "llvm/Support/CommandLine.h"
21#include "llvm/Support/Errc.h"
22#include "llvm/Support/ManagedStatic.h"
23#include "llvm/Support/PrettyStackTrace.h"
24#include "llvm/Support/Program.h"
25#include "llvm/Support/Signals.h"
26#include "llvm/Support/TargetSelect.h"
27#include "llvm/Support/VirtualFileSystem.h"
28
29#define DEBUG_TYPE "bolt"
30
31using namespace llvm;
32using namespace object;
33using namespace bolt;
34
35namespace opts {
36
37static cl::OptionCategory *BinaryAnalysisCategories[] = {
38 &BinaryAnalysisCategory};
39
40static cl::opt<std::string> InputFilename(cl::Positional,
41 cl::desc("<executable>"),
42 cl::Required,
43 cl::cat(BinaryAnalysisCategory),
44 cl::sub(cl::SubCommand::getAll()));
45
46} // namespace opts
47
48static StringRef ToolName = "llvm-bolt-binary-analysis";
49
50static void report_error(StringRef Message, std::error_code EC) {
51 assert(EC);
52 errs() << ToolName << ": '" << Message << "': " << EC.message() << ".\n";
53 exit(status: 1);
54}
55
56static void report_error(StringRef Message, Error E) {
57 assert(E);
58 errs() << ToolName << ": '" << Message << "': " << toString(E: std::move(E))
59 << ".\n";
60 exit(status: 1);
61}
62
63void ParseCommandLine(int argc, char **argv) {
64 cl::HideUnrelatedOptions(Categories: ArrayRef(opts::BinaryAnalysisCategories));
65 // Register the target printer for --version.
66 cl::AddExtraVersionPrinter(func: TargetRegistry::printRegisteredTargetsForVersion);
67
68 cl::ParseCommandLineOptions(argc, argv, Overview: "BinaryAnalysis\n");
69}
70
71static std::string GetExecutablePath(const char *Argv0) {
72 SmallString<256> ExecutablePath(Argv0);
73 // Do a PATH lookup if Argv0 isn't a valid path.
74 if (!llvm::sys::fs::exists(Path: ExecutablePath))
75 if (llvm::ErrorOr<std::string> P =
76 llvm::sys::findProgramByName(Name: ExecutablePath))
77 ExecutablePath = *P;
78 return std::string(ExecutablePath.str());
79}
80
81int main(int argc, char **argv) {
82 // Print a stack trace if we signal out.
83 sys::PrintStackTraceOnErrorSignal(Argv0: argv[0]);
84 PrettyStackTraceProgram X(argc, argv);
85
86 std::string ToolPath = GetExecutablePath(Argv0: argv[0]);
87
88 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
89
90 // Initialize targets and assembly printers/parsers.
91#define BOLT_TARGET(target) \
92 LLVMInitialize##target##TargetInfo(); \
93 LLVMInitialize##target##TargetMC(); \
94 LLVMInitialize##target##AsmParser(); \
95 LLVMInitialize##target##Disassembler(); \
96 LLVMInitialize##target##Target(); \
97 LLVMInitialize##target##AsmPrinter();
98
99#include "bolt/Core/TargetConfig.def"
100
101 ParseCommandLine(argc, argv);
102
103 opts::BinaryAnalysisMode = true;
104
105 if (!sys::fs::exists(Path: opts::InputFilename))
106 report_error(Message: opts::InputFilename, EC: errc::no_such_file_or_directory);
107
108 Expected<OwningBinary<Binary>> BinaryOrErr =
109 createBinary(Path: opts::InputFilename);
110 if (Error E = BinaryOrErr.takeError())
111 report_error(Message: opts::InputFilename, E: std::move(E));
112 Binary &Binary = *BinaryOrErr.get().getBinary();
113
114 if (auto *e = dyn_cast<ELFObjectFileBase>(Val: &Binary)) {
115 auto RIOrErr = RewriteInstance::create(File: e, Argc: argc, Argv: argv, ToolPath);
116 if (Error E = RIOrErr.takeError())
117 report_error(Message: opts::InputFilename, E: std::move(E));
118 RewriteInstance &RI = *RIOrErr.get();
119 if (Error E = RI.run())
120 report_error(Message: opts::InputFilename, E: std::move(E));
121 }
122
123 return EXIT_SUCCESS;
124}
125

source code of bolt/tools/binary-analysis/binary-analysis.cpp