forked from OSchip/llvm-project
236 lines
7.0 KiB
C++
236 lines
7.0 KiB
C++
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include <getopt.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
#if defined(__APPLE__)
|
|
#include <LLDB/LLDB.h>
|
|
#else
|
|
#include "LLDB/SBBlock.h"
|
|
#include "LLDB/SBCompileUnit.h"
|
|
#include "LLDB/SBDebugger.h"
|
|
#include "LLDB/SBFunction.h"
|
|
#include "LLDB/SBModule.h"
|
|
#include "LLDB/SBStream.h"
|
|
#include "LLDB/SBSymbol.h"
|
|
#include "LLDB/SBTarget.h"
|
|
#include "LLDB/SBThread.h"
|
|
#include "LLDB/SBProcess.h"
|
|
#endif
|
|
|
|
#include <string>
|
|
|
|
using namespace lldb;
|
|
|
|
//----------------------------------------------------------------------
|
|
// This quick sample code shows how to create a debugger instance and
|
|
// create an "i386" executable target. Then we can lookup the executable
|
|
// module and resolve a file address into a section offset address,
|
|
// and find all symbol context objects (if any) for that address:
|
|
// compile unit, function, deepest block, line table entry and the
|
|
// symbol.
|
|
//
|
|
// To build the program, type (while in this directory):
|
|
//
|
|
// $ make
|
|
//
|
|
// then (for example):
|
|
//
|
|
// $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/svn/ToT/build/Debug ./a.out executable_path file_address
|
|
//----------------------------------------------------------------------
|
|
class LLDBSentry
|
|
{
|
|
public:
|
|
LLDBSentry() {
|
|
// Initialize LLDB
|
|
SBDebugger::Initialize();
|
|
}
|
|
~LLDBSentry() {
|
|
// Terminate LLDB
|
|
SBDebugger::Terminate();
|
|
}
|
|
};
|
|
|
|
static struct option g_long_options[] =
|
|
{
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ "verbose", no_argument, NULL, 'v' },
|
|
{ "arch", required_argument, NULL, 'a' },
|
|
{ "platform", required_argument, NULL, 'p' },
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
|
|
#define PROGRAM_NAME "lldb-lookup"
|
|
void
|
|
usage ()
|
|
{
|
|
puts (
|
|
"NAME\n"
|
|
" " PROGRAM_NAME " -- symbolicate addresses using lldb.\n"
|
|
"\n"
|
|
"SYNOPSIS\n"
|
|
" " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] [--verbose] [--help] --] <PATH> <ADDRESS> [<ADDRESS>....]\n"
|
|
"\n"
|
|
"DESCRIPTION\n"
|
|
" Loads the executable pointed to by <PATH> and looks up and <ADDRESS>\n"
|
|
" arguments\n"
|
|
"\n"
|
|
"EXAMPLE\n"
|
|
" " PROGRAM_NAME " --arch=x86_64 -- /usr/lib/dyld 0x100000000\n"
|
|
);
|
|
exit(0);
|
|
}
|
|
int
|
|
main (int argc, char const *argv[])
|
|
{
|
|
// Use a sentry object to properly initialize/terminate LLDB.
|
|
LLDBSentry sentry;
|
|
|
|
SBDebugger debugger (SBDebugger::Create());
|
|
|
|
// Create a debugger instance so we can create a target
|
|
if (!debugger.IsValid())
|
|
fprintf (stderr, "error: failed to create a debugger object\n");
|
|
|
|
bool show_usage = false;
|
|
bool verbose = false;
|
|
const char *arch = NULL;
|
|
const char *platform = NULL;
|
|
std::string short_options("h?");
|
|
for (const struct option *opt = g_long_options; opt->name; ++opt)
|
|
{
|
|
if (isprint(opt->val))
|
|
{
|
|
short_options.append(1, (char)opt->val);
|
|
switch (opt->has_arg)
|
|
{
|
|
case no_argument:
|
|
break;
|
|
case required_argument:
|
|
short_options.append(1, ':');
|
|
break;
|
|
case optional_argument:
|
|
short_options.append(2, ':');
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#ifdef __GLIBC__
|
|
optind = 0;
|
|
#else
|
|
optreset = 1;
|
|
optind = 1;
|
|
#endif
|
|
char ch;
|
|
while ((ch = getopt_long_only(argc, (char * const *)argv, short_options.c_str(), g_long_options, 0)) != -1)
|
|
{
|
|
switch (ch)
|
|
{
|
|
case 0:
|
|
break;
|
|
|
|
case 'a':
|
|
if (arch != NULL)
|
|
{
|
|
fprintf (stderr, "error: the --arch option can only be specified once\n");
|
|
exit(1);
|
|
}
|
|
arch = optarg;
|
|
break;
|
|
|
|
case 'p':
|
|
platform = optarg;
|
|
break;
|
|
|
|
case 'v':
|
|
verbose = true;
|
|
break;
|
|
|
|
case 'h':
|
|
case '?':
|
|
default:
|
|
show_usage = true;
|
|
break;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
if (show_usage || argc < 2)
|
|
usage();
|
|
|
|
int arg_idx = 0;
|
|
// The first argument is the file path we want to look something up in
|
|
const char *exe_file_path = argv[arg_idx];
|
|
const char *addr_cstr;
|
|
const bool add_dependent_libs = false;
|
|
SBError error;
|
|
SBStream strm;
|
|
strm.RedirectToFileHandle (stdout, false);
|
|
|
|
while ((addr_cstr = argv[++arg_idx]) != NULL)
|
|
{
|
|
// The second argument in the address that we want to lookup
|
|
lldb::addr_t file_addr = strtoull (addr_cstr, NULL, 0);
|
|
|
|
// Create a target using the executable.
|
|
SBTarget target = debugger.CreateTarget (exe_file_path,
|
|
arch,
|
|
platform,
|
|
add_dependent_libs,
|
|
error);
|
|
if (!error.Success())
|
|
{
|
|
fprintf (stderr, "error: %s\n", error.GetCString());
|
|
exit(1);
|
|
}
|
|
|
|
printf ("%sLooking up 0x%llx in '%s':\n", (arg_idx > 1) ? "\n" : "", file_addr, exe_file_path);
|
|
|
|
if (target.IsValid())
|
|
{
|
|
// Find the executable module so we can do a lookup inside it
|
|
SBFileSpec exe_file_spec (exe_file_path, true);
|
|
SBModule module (target.FindModule (exe_file_spec));
|
|
|
|
// Take a file virtual address and resolve it to a section offset
|
|
// address that can be used to do a symbol lookup by address
|
|
SBAddress addr = module.ResolveFileAddress (file_addr);
|
|
bool success = addr.IsValid() && addr.GetSection().IsValid();
|
|
if (success)
|
|
{
|
|
// We can resolve a section offset address in the module
|
|
// and only ask for what we need. You can logical or together
|
|
// bits from the SymbolContextItem enumeration found in
|
|
// lldb-enumeration.h to request only what you want. Here we
|
|
// are asking for everything.
|
|
//
|
|
// NOTE: the less you ask for, the less LLDB will parse as
|
|
// LLDB does partial parsing on just about everything.
|
|
SBSymbolContext sc (module.ResolveSymbolContextForAddress (addr, eSymbolContextEverything));
|
|
|
|
strm.Printf (" Address: %s + 0x%llx\n Summary: ", addr.GetSection().GetName (), addr.GetOffset());
|
|
addr.GetDescription (strm);
|
|
strm.Printf ("\n");
|
|
if (verbose)
|
|
sc.GetDescription (strm);
|
|
}
|
|
else
|
|
{
|
|
printf ("error: 0x%llx does not resolve to a valid file address in '%s'\n", file_addr, exe_file_path);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|