xref: /aosp_15_r20/external/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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