]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - examples/lookup/main.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / examples / lookup / main.cpp
1 //===-- main.cpp ------------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include <getopt.h>
11 #include <stdint.h>
12 #include <stdlib.h>
13
14 #if defined(__APPLE__)
15 #include <LLDB/LLDB.h>
16 #else
17 #include "LLDB/SBBlock.h"
18 #include "LLDB/SBCompileUnit.h"
19 #include "LLDB/SBDebugger.h"
20 #include "LLDB/SBFunction.h"
21 #include "LLDB/SBModule.h"
22 #include "LLDB/SBProcess.h"
23 #include "LLDB/SBStream.h"
24 #include "LLDB/SBSymbol.h"
25 #include "LLDB/SBTarget.h"
26 #include "LLDB/SBThread.h"
27 #endif
28
29 #include <string>
30
31 using namespace lldb;
32
33 //----------------------------------------------------------------------
34 // This quick sample code shows how to create a debugger instance and
35 // create an "i386" executable target. Then we can lookup the executable
36 // module and resolve a file address into a section offset address,
37 // and find all symbol context objects (if any) for that address:
38 // compile unit, function, deepest block, line table entry and the
39 // symbol.
40 //
41 // To build the program, type (while in this directory):
42 //
43 //    $ make
44 //
45 // then (for example):
46 //
47 //    $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/svn/ToT/build/Debug ./a.out
48 //    executable_path file_address
49 //----------------------------------------------------------------------
50 class LLDBSentry {
51 public:
52   LLDBSentry() {
53     // Initialize LLDB
54     SBDebugger::Initialize();
55   }
56   ~LLDBSentry() {
57     // Terminate LLDB
58     SBDebugger::Terminate();
59   }
60 };
61
62 static struct option g_long_options[] = {
63     {"help", no_argument, NULL, 'h'},
64     {"verbose", no_argument, NULL, 'v'},
65     {"arch", required_argument, NULL, 'a'},
66     {"platform", required_argument, NULL, 'p'},
67     {NULL, 0, NULL, 0}};
68
69 #define PROGRAM_NAME "lldb-lookup"
70 void usage() {
71   puts("NAME\n"
72        "    " PROGRAM_NAME " -- symbolicate addresses using lldb.\n"
73        "\n"
74        "SYNOPSIS\n"
75        "    " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] "
76                            "[--verbose] [--help] --] <PATH> <ADDRESS> "
77                            "[<ADDRESS>....]\n"
78        "\n"
79        "DESCRIPTION\n"
80        "    Loads the executable pointed to by <PATH> and looks up and "
81        "<ADDRESS>\n"
82        "    arguments\n"
83        "\n"
84        "EXAMPLE\n"
85        "   " PROGRAM_NAME " --arch=x86_64 -- /usr/lib/dyld 0x100000000\n");
86   exit(0);
87 }
88 int main(int argc, char const *argv[]) {
89   // Use a sentry object to properly initialize/terminate LLDB.
90   LLDBSentry sentry;
91
92   SBDebugger debugger(SBDebugger::Create());
93
94   // Create a debugger instance so we can create a target
95   if (!debugger.IsValid())
96     fprintf(stderr, "error: failed to create a debugger object\n");
97
98   bool show_usage = false;
99   bool verbose = false;
100   const char *arch = NULL;
101   const char *platform = NULL;
102   std::string short_options("h?");
103   for (const struct option *opt = g_long_options; opt->name; ++opt) {
104     if (isprint(opt->val)) {
105       short_options.append(1, (char)opt->val);
106       switch (opt->has_arg) {
107       case no_argument:
108         break;
109       case required_argument:
110         short_options.append(1, ':');
111         break;
112       case optional_argument:
113         short_options.append(2, ':');
114         break;
115       }
116     }
117   }
118 #ifdef __GLIBC__
119   optind = 0;
120 #else
121   optreset = 1;
122   optind = 1;
123 #endif
124   char ch;
125   while ((ch = getopt_long_only(argc, (char *const *)argv,
126                                 short_options.c_str(), g_long_options, 0)) !=
127          -1) {
128     switch (ch) {
129     case 0:
130       break;
131
132     case 'a':
133       if (arch != NULL) {
134         fprintf(stderr,
135                 "error: the --arch option can only be specified once\n");
136         exit(1);
137       }
138       arch = optarg;
139       break;
140
141     case 'p':
142       platform = optarg;
143       break;
144
145     case 'v':
146       verbose = true;
147       break;
148
149     case 'h':
150     case '?':
151     default:
152       show_usage = true;
153       break;
154     }
155   }
156   argc -= optind;
157   argv += optind;
158
159   if (show_usage || argc < 2)
160     usage();
161
162   int arg_idx = 0;
163   // The first argument is the file path we want to look something up in
164   const char *exe_file_path = argv[arg_idx];
165   const char *addr_cstr;
166   const bool add_dependent_libs = false;
167   SBError error;
168   SBStream strm;
169   strm.RedirectToFileHandle(stdout, false);
170
171   while ((addr_cstr = argv[++arg_idx]) != NULL) {
172     // The second argument in the address that we want to lookup
173     lldb::addr_t file_addr = strtoull(addr_cstr, NULL, 0);
174
175     // Create a target using the executable.
176     SBTarget target = debugger.CreateTarget(exe_file_path, arch, platform,
177                                             add_dependent_libs, error);
178     if (!error.Success()) {
179       fprintf(stderr, "error: %s\n", error.GetCString());
180       exit(1);
181     }
182
183     printf("%sLooking up 0x%llx in '%s':\n", (arg_idx > 1) ? "\n" : "",
184            file_addr, exe_file_path);
185
186     if (target.IsValid()) {
187       // Find the executable module so we can do a lookup inside it
188       SBFileSpec exe_file_spec(exe_file_path, true);
189       SBModule module(target.FindModule(exe_file_spec));
190
191       // Take a file virtual address and resolve it to a section offset
192       // address that can be used to do a symbol lookup by address
193       SBAddress addr = module.ResolveFileAddress(file_addr);
194       bool success = addr.IsValid() && addr.GetSection().IsValid();
195       if (success) {
196         // We can resolve a section offset address in the module
197         // and only ask for what we need. You can logical or together
198         // bits from the SymbolContextItem enumeration found in
199         // lldb-enumeration.h to request only what you want. Here we
200         // are asking for everything.
201         //
202         // NOTE: the less you ask for, the less LLDB will parse as
203         // LLDB does partial parsing on just about everything.
204         SBSymbolContext sc(module.ResolveSymbolContextForAddress(
205             addr, eSymbolContextEverything));
206
207         strm.Printf("    Address: %s + 0x%llx\n    Summary: ",
208                     addr.GetSection().GetName(), addr.GetOffset());
209         addr.GetDescription(strm);
210         strm.Printf("\n");
211         if (verbose)
212           sc.GetDescription(strm);
213       } else {
214         printf(
215             "error: 0x%llx does not resolve to a valid file address in '%s'\n",
216             file_addr, exe_file_path);
217       }
218     }
219   }
220
221   return 0;
222 }