brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · 4c6daeb Raw
220 lines · cpp
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-exception6//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#else16#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#endif27 28#include <string>29 30using namespace lldb;31 32// This quick sample code shows how to create a debugger instance and33// create an "i386" executable target. Then we can lookup the executable34// 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 the37// symbol.38//39// To build the program, type (while in this directory):40//41//    $ make42//43// then (for example):44//45//    $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/svn/ToT/build/Debug ./a.out46//    executable_path file_address47class LLDBSentry {48public:49  LLDBSentry() {50    // Initialize LLDB51    SBDebugger::Initialize();52  }53  ~LLDBSentry() {54    // Terminate LLDB55    SBDebugger::Terminate();56  }57};58 59static struct option g_long_options[] = {60    {"help", no_argument, NULL, 'h'},61    {"verbose", no_argument, NULL, 'v'},62    {"arch", required_argument, NULL, 'a'},63    {"platform", required_argument, NULL, 'p'},64    {NULL, 0, NULL, 0}};65 66#define PROGRAM_NAME "lldb-lookup"67void usage() {68  puts("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(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 target92  if (!debugger.IsValid())93    fprintf(stderr, "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(1, (char)opt->val);103      switch (opt->has_arg) {104      case no_argument:105        break;106      case required_argument:107        short_options.append(1, ':');108        break;109      case optional_argument:110        short_options.append(2, ':');111        break;112      }113    }114  }115#ifdef __GLIBC__116  optind = 0;117#else118  optreset = 1;119  optind = 1;120#endif121  char ch;122  while ((ch = getopt_long_only(argc, (char *const *)argv,123                                short_options.c_str(), g_long_options, 0)) !=124         -1) {125    switch (ch) {126    case 0:127      break;128 129    case 'a':130      if (arch != NULL) {131        fprintf(stderr,132                "error: the --arch option can only be specified once\n");133        exit(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 in161  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 lookup170    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(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 it185      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 offset189      // address that can be used to do a symbol lookup by address190      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 module194        // and only ask for what we need. You can logical or together195        // bits from the SymbolContextItem enumeration found in196        // lldb-enumeration.h to request only what you want. Here we197        // are asking for everything.198        //199        // NOTE: the less you ask for, the less LLDB will parse as200        // 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