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/SBStream.h" 23 #include "LLDB/SBSymbol.h" 24 #include "LLDB/SBTarget.h" 25 #include "LLDB/SBThread.h" 26 #include "LLDB/SBProcess.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 executable_path file_address 48 //---------------------------------------------------------------------- 49 class LLDBSentry 50 { 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 { 64 { "help", no_argument, NULL, 'h' }, 65 { "verbose", no_argument, NULL, 'v' }, 66 { "arch", required_argument, NULL, 'a' }, 67 { "platform", required_argument, NULL, 'p' }, 68 { NULL, 0, NULL, 0 } 69 }; 70 71 #define PROGRAM_NAME "lldb-lookup" 72 void 73 usage () 74 { 75 puts ( 76 "NAME\n" 77 " " PROGRAM_NAME " -- symbolicate addresses using lldb.\n" 78 "\n" 79 "SYNOPSIS\n" 80 " " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] [--verbose] [--help] --] <PATH> <ADDRESS> [<ADDRESS>....]\n" 81 "\n" 82 "DESCRIPTION\n" 83 " Loads the executable pointed to by <PATH> and looks up and <ADDRESS>\n" 84 " arguments\n" 85 "\n" 86 "EXAMPLE\n" 87 " " PROGRAM_NAME " --arch=x86_64 -- /usr/lib/dyld 0x100000000\n" 88 ); 89 exit(0); 90 } 91 int 92 main (int argc, char const *argv[]) 93 { 94 // Use a sentry object to properly initialize/terminate LLDB. 95 LLDBSentry sentry; 96 97 SBDebugger debugger (SBDebugger::Create()); 98 99 // Create a debugger instance so we can create a target 100 if (!debugger.IsValid()) 101 fprintf (stderr, "error: failed to create a debugger object\n"); 102 103 bool show_usage = false; 104 bool verbose = false; 105 const char *arch = NULL; 106 const char *platform = NULL; 107 std::string short_options("h?"); 108 for (const struct option *opt = g_long_options; opt->name; ++opt) 109 { 110 if (isprint(opt->val)) 111 { 112 short_options.append(1, (char)opt->val); 113 switch (opt->has_arg) 114 { 115 case no_argument: 116 break; 117 case required_argument: 118 short_options.append(1, ':'); 119 break; 120 case optional_argument: 121 short_options.append(2, ':'); 122 break; 123 } 124 } 125 } 126 #ifdef __GLIBC__ 127 optind = 0; 128 #else 129 optreset = 1; 130 optind = 1; 131 #endif 132 char ch; 133 while ((ch = getopt_long_only(argc, (char * const *)argv, short_options.c_str(), g_long_options, 0)) != -1) 134 { 135 switch (ch) 136 { 137 case 0: 138 break; 139 140 case 'a': 141 if (arch != NULL) 142 { 143 fprintf (stderr, "error: the --arch option can only be specified once\n"); 144 exit(1); 145 } 146 arch = optarg; 147 break; 148 149 case 'p': 150 platform = optarg; 151 break; 152 153 case 'v': 154 verbose = true; 155 break; 156 157 case 'h': 158 case '?': 159 default: 160 show_usage = true; 161 break; 162 } 163 } 164 argc -= optind; 165 argv += optind; 166 167 if (show_usage || argc < 2) 168 usage(); 169 170 int arg_idx = 0; 171 // The first argument is the file path we want to look something up in 172 const char *exe_file_path = argv[arg_idx]; 173 const char *addr_cstr; 174 const bool add_dependent_libs = false; 175 SBError error; 176 SBStream strm; 177 strm.RedirectToFileHandle (stdout, false); 178 179 while ((addr_cstr = argv[++arg_idx]) != NULL) 180 { 181 // The second argument in the address that we want to lookup 182 lldb::addr_t file_addr = strtoull (addr_cstr, NULL, 0); 183 184 // Create a target using the executable. 185 SBTarget target = debugger.CreateTarget (exe_file_path, 186 arch, 187 platform, 188 add_dependent_libs, 189 error); 190 if (!error.Success()) 191 { 192 fprintf (stderr, "error: %s\n", error.GetCString()); 193 exit(1); 194 } 195 196 printf ("%sLooking up 0x%llx in '%s':\n", (arg_idx > 1) ? "\n" : "", file_addr, exe_file_path); 197 198 if (target.IsValid()) 199 { 200 // Find the executable module so we can do a lookup inside it 201 SBFileSpec exe_file_spec (exe_file_path, true); 202 SBModule module (target.FindModule (exe_file_spec)); 203 204 // Take a file virtual address and resolve it to a section offset 205 // address that can be used to do a symbol lookup by address 206 SBAddress addr = module.ResolveFileAddress (file_addr); 207 bool success = addr.IsValid() && addr.GetSection().IsValid(); 208 if (success) 209 { 210 // We can resolve a section offset address in the module 211 // and only ask for what we need. You can logical or together 212 // bits from the SymbolContextItem enumeration found in 213 // lldb-enumeration.h to request only what you want. Here we 214 // are asking for everything. 215 // 216 // NOTE: the less you ask for, the less LLDB will parse as 217 // LLDB does partial parsing on just about everything. 218 SBSymbolContext sc (module.ResolveSymbolContextForAddress (addr, eSymbolContextEverything)); 219 220 strm.Printf (" Address: %s + 0x%llx\n Summary: ", addr.GetSection().GetName (), addr.GetOffset()); 221 addr.GetDescription (strm); 222 strm.Printf ("\n"); 223 if (verbose) 224 sc.GetDescription (strm); 225 } 226 else 227 { 228 printf ("error: 0x%llx does not resolve to a valid file address in '%s'\n", file_addr, exe_file_path); 229 } 230 } 231 } 232 233 return 0; 234 } 235 236