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

source code of lldb/examples/lookup/main.cpp