1*9880d681SAndroid Build Coastguard Worker //===-- llvm-symbolizer.cpp - Simple addr2line-like symbolizer ------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This utility works much like "addr2line". It is able of transforming
11*9880d681SAndroid Build Coastguard Worker // tuples (module name, module offset) to code locations (function name,
12*9880d681SAndroid Build Coastguard Worker // file, line number, column number). It is targeted for compiler-rt tools
13*9880d681SAndroid Build Coastguard Worker // (especially AddressSanitizer and ThreadSanitizer) that can use it
14*9880d681SAndroid Build Coastguard Worker // to symbolize stack traces in their error reports.
15*9880d681SAndroid Build Coastguard Worker //
16*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
17*9880d681SAndroid Build Coastguard Worker
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringRef.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/Symbolize/DIPrinter.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/Symbolize/Symbolize.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/COM.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileSystem.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ManagedStatic.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Path.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/PrettyStackTrace.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Signals.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
30*9880d681SAndroid Build Coastguard Worker #include <cstdio>
31*9880d681SAndroid Build Coastguard Worker #include <cstring>
32*9880d681SAndroid Build Coastguard Worker #include <string>
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker using namespace llvm;
35*9880d681SAndroid Build Coastguard Worker using namespace symbolize;
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
38*9880d681SAndroid Build Coastguard Worker ClUseSymbolTable("use-symbol-table", cl::init(true),
39*9880d681SAndroid Build Coastguard Worker cl::desc("Prefer names in symbol table to names "
40*9880d681SAndroid Build Coastguard Worker "in debug info"));
41*9880d681SAndroid Build Coastguard Worker
42*9880d681SAndroid Build Coastguard Worker static cl::opt<FunctionNameKind> ClPrintFunctions(
43*9880d681SAndroid Build Coastguard Worker "functions", cl::init(FunctionNameKind::LinkageName),
44*9880d681SAndroid Build Coastguard Worker cl::desc("Print function name for a given address:"),
45*9880d681SAndroid Build Coastguard Worker cl::values(clEnumValN(FunctionNameKind::None, "none", "omit function name"),
46*9880d681SAndroid Build Coastguard Worker clEnumValN(FunctionNameKind::ShortName, "short",
47*9880d681SAndroid Build Coastguard Worker "print short function name"),
48*9880d681SAndroid Build Coastguard Worker clEnumValN(FunctionNameKind::LinkageName, "linkage",
49*9880d681SAndroid Build Coastguard Worker "print function linkage name"),
50*9880d681SAndroid Build Coastguard Worker clEnumValEnd));
51*9880d681SAndroid Build Coastguard Worker
52*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
53*9880d681SAndroid Build Coastguard Worker ClUseRelativeAddress("relative-address", cl::init(false),
54*9880d681SAndroid Build Coastguard Worker cl::desc("Interpret addresses as relative addresses"),
55*9880d681SAndroid Build Coastguard Worker cl::ReallyHidden);
56*9880d681SAndroid Build Coastguard Worker
57*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
58*9880d681SAndroid Build Coastguard Worker ClPrintInlining("inlining", cl::init(true),
59*9880d681SAndroid Build Coastguard Worker cl::desc("Print all inlined frames for a given address"));
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
62*9880d681SAndroid Build Coastguard Worker ClDemangle("demangle", cl::init(true), cl::desc("Demangle function names"));
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string> ClDefaultArch("default-arch", cl::init(""),
65*9880d681SAndroid Build Coastguard Worker cl::desc("Default architecture "
66*9880d681SAndroid Build Coastguard Worker "(for multi-arch objects)"));
67*9880d681SAndroid Build Coastguard Worker
68*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string>
69*9880d681SAndroid Build Coastguard Worker ClBinaryName("obj", cl::init(""),
70*9880d681SAndroid Build Coastguard Worker cl::desc("Path to object file to be symbolized (if not provided, "
71*9880d681SAndroid Build Coastguard Worker "object file should be specified for each input line)"));
72*9880d681SAndroid Build Coastguard Worker
73*9880d681SAndroid Build Coastguard Worker static cl::list<std::string>
74*9880d681SAndroid Build Coastguard Worker ClDsymHint("dsym-hint", cl::ZeroOrMore,
75*9880d681SAndroid Build Coastguard Worker cl::desc("Path to .dSYM bundles to search for debug info for the "
76*9880d681SAndroid Build Coastguard Worker "object files"));
77*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
78*9880d681SAndroid Build Coastguard Worker ClPrintAddress("print-address", cl::init(false),
79*9880d681SAndroid Build Coastguard Worker cl::desc("Show address before line information"));
80*9880d681SAndroid Build Coastguard Worker
81*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
82*9880d681SAndroid Build Coastguard Worker ClPrettyPrint("pretty-print", cl::init(false),
83*9880d681SAndroid Build Coastguard Worker cl::desc("Make the output more human friendly"));
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker static cl::opt<int> ClPrintSourceContextLines(
86*9880d681SAndroid Build Coastguard Worker "print-source-context-lines", cl::init(0),
87*9880d681SAndroid Build Coastguard Worker cl::desc("Print N number of source file context"));
88*9880d681SAndroid Build Coastguard Worker
89*9880d681SAndroid Build Coastguard Worker template<typename T>
error(Expected<T> & ResOrErr)90*9880d681SAndroid Build Coastguard Worker static bool error(Expected<T> &ResOrErr) {
91*9880d681SAndroid Build Coastguard Worker if (ResOrErr)
92*9880d681SAndroid Build Coastguard Worker return false;
93*9880d681SAndroid Build Coastguard Worker logAllUnhandledErrors(ResOrErr.takeError(), errs(),
94*9880d681SAndroid Build Coastguard Worker "LLVMSymbolizer: error reading file: ");
95*9880d681SAndroid Build Coastguard Worker return true;
96*9880d681SAndroid Build Coastguard Worker }
97*9880d681SAndroid Build Coastguard Worker
parseCommand(StringRef InputString,bool & IsData,std::string & ModuleName,uint64_t & ModuleOffset)98*9880d681SAndroid Build Coastguard Worker static bool parseCommand(StringRef InputString, bool &IsData,
99*9880d681SAndroid Build Coastguard Worker std::string &ModuleName, uint64_t &ModuleOffset) {
100*9880d681SAndroid Build Coastguard Worker const char *kDataCmd = "DATA ";
101*9880d681SAndroid Build Coastguard Worker const char *kCodeCmd = "CODE ";
102*9880d681SAndroid Build Coastguard Worker const char kDelimiters[] = " \n\r";
103*9880d681SAndroid Build Coastguard Worker IsData = false;
104*9880d681SAndroid Build Coastguard Worker ModuleName = "";
105*9880d681SAndroid Build Coastguard Worker const char *pos = InputString.data();
106*9880d681SAndroid Build Coastguard Worker if (strncmp(pos, kDataCmd, strlen(kDataCmd)) == 0) {
107*9880d681SAndroid Build Coastguard Worker IsData = true;
108*9880d681SAndroid Build Coastguard Worker pos += strlen(kDataCmd);
109*9880d681SAndroid Build Coastguard Worker } else if (strncmp(pos, kCodeCmd, strlen(kCodeCmd)) == 0) {
110*9880d681SAndroid Build Coastguard Worker IsData = false;
111*9880d681SAndroid Build Coastguard Worker pos += strlen(kCodeCmd);
112*9880d681SAndroid Build Coastguard Worker } else {
113*9880d681SAndroid Build Coastguard Worker // If no cmd, assume it's CODE.
114*9880d681SAndroid Build Coastguard Worker IsData = false;
115*9880d681SAndroid Build Coastguard Worker }
116*9880d681SAndroid Build Coastguard Worker // Skip delimiters and parse input filename (if needed).
117*9880d681SAndroid Build Coastguard Worker if (ClBinaryName == "") {
118*9880d681SAndroid Build Coastguard Worker pos += strspn(pos, kDelimiters);
119*9880d681SAndroid Build Coastguard Worker if (*pos == '"' || *pos == '\'') {
120*9880d681SAndroid Build Coastguard Worker char quote = *pos;
121*9880d681SAndroid Build Coastguard Worker pos++;
122*9880d681SAndroid Build Coastguard Worker const char *end = strchr(pos, quote);
123*9880d681SAndroid Build Coastguard Worker if (!end)
124*9880d681SAndroid Build Coastguard Worker return false;
125*9880d681SAndroid Build Coastguard Worker ModuleName = std::string(pos, end - pos);
126*9880d681SAndroid Build Coastguard Worker pos = end + 1;
127*9880d681SAndroid Build Coastguard Worker } else {
128*9880d681SAndroid Build Coastguard Worker int name_length = strcspn(pos, kDelimiters);
129*9880d681SAndroid Build Coastguard Worker ModuleName = std::string(pos, name_length);
130*9880d681SAndroid Build Coastguard Worker pos += name_length;
131*9880d681SAndroid Build Coastguard Worker }
132*9880d681SAndroid Build Coastguard Worker } else {
133*9880d681SAndroid Build Coastguard Worker ModuleName = ClBinaryName;
134*9880d681SAndroid Build Coastguard Worker }
135*9880d681SAndroid Build Coastguard Worker // Skip delimiters and parse module offset.
136*9880d681SAndroid Build Coastguard Worker pos += strspn(pos, kDelimiters);
137*9880d681SAndroid Build Coastguard Worker int offset_length = strcspn(pos, kDelimiters);
138*9880d681SAndroid Build Coastguard Worker return !StringRef(pos, offset_length).getAsInteger(0, ModuleOffset);
139*9880d681SAndroid Build Coastguard Worker }
140*9880d681SAndroid Build Coastguard Worker
main(int argc,char ** argv)141*9880d681SAndroid Build Coastguard Worker int main(int argc, char **argv) {
142*9880d681SAndroid Build Coastguard Worker // Print stack trace if we signal out.
143*9880d681SAndroid Build Coastguard Worker sys::PrintStackTraceOnErrorSignal(argv[0]);
144*9880d681SAndroid Build Coastguard Worker PrettyStackTraceProgram X(argc, argv);
145*9880d681SAndroid Build Coastguard Worker llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
146*9880d681SAndroid Build Coastguard Worker
147*9880d681SAndroid Build Coastguard Worker llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker cl::ParseCommandLineOptions(argc, argv, "llvm-symbolizer\n");
150*9880d681SAndroid Build Coastguard Worker LLVMSymbolizer::Options Opts(ClPrintFunctions, ClUseSymbolTable, ClDemangle,
151*9880d681SAndroid Build Coastguard Worker ClUseRelativeAddress, ClDefaultArch);
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker for (const auto &hint : ClDsymHint) {
154*9880d681SAndroid Build Coastguard Worker if (sys::path::extension(hint) == ".dSYM") {
155*9880d681SAndroid Build Coastguard Worker Opts.DsymHints.push_back(hint);
156*9880d681SAndroid Build Coastguard Worker } else {
157*9880d681SAndroid Build Coastguard Worker errs() << "Warning: invalid dSYM hint: \"" << hint <<
158*9880d681SAndroid Build Coastguard Worker "\" (must have the '.dSYM' extension).\n";
159*9880d681SAndroid Build Coastguard Worker }
160*9880d681SAndroid Build Coastguard Worker }
161*9880d681SAndroid Build Coastguard Worker LLVMSymbolizer Symbolizer(Opts);
162*9880d681SAndroid Build Coastguard Worker
163*9880d681SAndroid Build Coastguard Worker DIPrinter Printer(outs(), ClPrintFunctions != FunctionNameKind::None,
164*9880d681SAndroid Build Coastguard Worker ClPrettyPrint, ClPrintSourceContextLines);
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Worker const int kMaxInputStringLength = 1024;
167*9880d681SAndroid Build Coastguard Worker char InputString[kMaxInputStringLength];
168*9880d681SAndroid Build Coastguard Worker
169*9880d681SAndroid Build Coastguard Worker while (true) {
170*9880d681SAndroid Build Coastguard Worker if (!fgets(InputString, sizeof(InputString), stdin))
171*9880d681SAndroid Build Coastguard Worker break;
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Worker bool IsData = false;
174*9880d681SAndroid Build Coastguard Worker std::string ModuleName;
175*9880d681SAndroid Build Coastguard Worker uint64_t ModuleOffset = 0;
176*9880d681SAndroid Build Coastguard Worker if (!parseCommand(StringRef(InputString), IsData, ModuleName,
177*9880d681SAndroid Build Coastguard Worker ModuleOffset)) {
178*9880d681SAndroid Build Coastguard Worker outs() << InputString;
179*9880d681SAndroid Build Coastguard Worker continue;
180*9880d681SAndroid Build Coastguard Worker }
181*9880d681SAndroid Build Coastguard Worker
182*9880d681SAndroid Build Coastguard Worker if (ClPrintAddress) {
183*9880d681SAndroid Build Coastguard Worker outs() << "0x";
184*9880d681SAndroid Build Coastguard Worker outs().write_hex(ModuleOffset);
185*9880d681SAndroid Build Coastguard Worker StringRef Delimiter = (ClPrettyPrint == true) ? ": " : "\n";
186*9880d681SAndroid Build Coastguard Worker outs() << Delimiter;
187*9880d681SAndroid Build Coastguard Worker }
188*9880d681SAndroid Build Coastguard Worker if (IsData) {
189*9880d681SAndroid Build Coastguard Worker auto ResOrErr = Symbolizer.symbolizeData(ModuleName, ModuleOffset);
190*9880d681SAndroid Build Coastguard Worker Printer << (error(ResOrErr) ? DIGlobal() : ResOrErr.get());
191*9880d681SAndroid Build Coastguard Worker } else if (ClPrintInlining) {
192*9880d681SAndroid Build Coastguard Worker auto ResOrErr = Symbolizer.symbolizeInlinedCode(ModuleName, ModuleOffset);
193*9880d681SAndroid Build Coastguard Worker Printer << (error(ResOrErr) ? DIInliningInfo()
194*9880d681SAndroid Build Coastguard Worker : ResOrErr.get());
195*9880d681SAndroid Build Coastguard Worker } else {
196*9880d681SAndroid Build Coastguard Worker auto ResOrErr = Symbolizer.symbolizeCode(ModuleName, ModuleOffset);
197*9880d681SAndroid Build Coastguard Worker Printer << (error(ResOrErr) ? DILineInfo() : ResOrErr.get());
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker outs() << "\n";
200*9880d681SAndroid Build Coastguard Worker outs().flush();
201*9880d681SAndroid Build Coastguard Worker }
202*9880d681SAndroid Build Coastguard Worker
203*9880d681SAndroid Build Coastguard Worker return 0;
204*9880d681SAndroid Build Coastguard Worker }
205