*** This commit represents a complete reformatting of the LLDB source code

*** to conform to clang-format’s LLVM style.  This kind of mass change has
*** two obvious implications:

Firstly, merging this particular commit into a downstream fork may be a huge
effort.  Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit.  The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):

    find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
    find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;

The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.

Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit.  There are alternatives available that will attempt
to look through this change and find the appropriate prior commit.  YMMV.

llvm-svn: 280751
This commit is contained in:
Kate Stone 2016-09-06 20:57:50 +00:00
parent d5aa733769
commit b9c1b51e45
2780 changed files with 556690 additions and 597060 deletions

View File

@ -2,6 +2,7 @@
import StringIO
def binary(n, width=None):
"""
Return a list of (0|1)'s for the binary representation of n where n >= 0.
@ -12,7 +13,7 @@ def binary(n, width=None):
if width and width <= 0:
width = None
while n > 0:
l.append(1 if n&1 else 0)
l.append(1 if n & 1 else 0)
n = n >> 1
if width:
@ -22,14 +23,15 @@ def binary(n, width=None):
l.reverse()
return l
def twos_complement(n, width):
"""
Return a list of (0|1)'s for the binary representation of a width-bit two's
complement numeral system of an integer n which may be negative.
"""
val = 2**(width-1)
val = 2**(width - 1)
if n >= 0:
if n > (val-1):
if n > (val - 1):
return None
# It is safe to represent n with width-bits.
return binary(n, width)
@ -38,7 +40,7 @@ def twos_complement(n, width):
if abs(n) > val:
return None
# It is safe to represent n (a negative int) with width-bits.
return binary(val*2 - abs(n))
return binary(val * 2 - abs(n))
# print binary(0xABCD)
# [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1]
@ -53,6 +55,7 @@ def twos_complement(n, width):
# print twos_complement(-5, 64)
# [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1]
def positions(width):
"""Helper function returning a list describing the bit positions.
Bit positions greater than 99 are truncated to 2 digits, for example,
@ -88,9 +91,10 @@ def utob(debugger, command_line, result, dict):
return
if verbose and width > 0:
pos = positions(width)
print ' '+' '.join(pos)
print ' ' + ' '.join(pos)
print ' %s' % str(bits)
def itob(debugger, command_line, result, dict):
"""Convert the integer to print its two's complement representation.
args[0] (mandatory) is the integer to be converted
@ -117,6 +121,5 @@ def itob(debugger, command_line, result, dict):
return
if verbose and width > 0:
pos = positions(width)
print ' '+' '.join(pos)
print ' ' + ' '.join(pos)
print ' %s' % str(bits)

View File

@ -1,31 +1,38 @@
import sys,os,lldb
import sys
import os
import lldb
def check_has_dir_in_path(dirname):
return sys.path.__contains__(dirname);
return sys.path.__contains__(dirname)
def ensure_has_dir_in_path(dirname):
dirname = os.path.abspath(dirname)
if not (check_has_dir_in_path(dirname)):
sys.path.append(dirname);
sys.path.append(dirname)
def do_import(debugger,modname):
def do_import(debugger, modname):
if (len(modname) > 4 and modname[-4:] == '.pyc'):
modname = modname[:-4]
if (len(modname) > 3 and modname[-3:] == '.py'):
modname = modname[:-3]
debugger.HandleCommand("script import " + modname)
def pyimport_cmd(debugger, args, result, dict):
"""Import a Python module given its full path"""
print 'WARNING: obsolete feature - use native command "command script import"'
if args == "":
return "no module path given";
return "no module path given"
if not (os.sep in args):
modname = args
ensure_has_dir_in_path('.')
else:
endofdir = args.rfind(os.sep)
modname = args[endofdir+1:]
modname = args[endofdir + 1:]
args = args[0:endofdir]
ensure_has_dir_in_path(args)
do_import(debugger,modname)
do_import(debugger, modname)
return None

View File

@ -1,8 +1,12 @@
"""Utility for changing directories and execution of commands in a subshell."""
import os, shlex, subprocess
import os
import shlex
import subprocess
# Store the previous working directory for the 'cd -' command.
class Holder:
"""Holds the _prev_dir_ class attribute for chdir() function."""
_prev_dir_ = None
@ -15,6 +19,7 @@ class Holder:
def swap(cls, dir):
cls._prev_dir_ = dir
def chdir(debugger, args, result, dict):
"""Change the working directory, or cd to ${HOME}.
You can also issue 'cd -' to change to the previous working directory."""
@ -33,10 +38,14 @@ def chdir(debugger, args, result, dict):
os.chdir(new_dir)
print "Current working directory: %s" % os.getcwd()
def system(debugger, command_line, result, dict):
"""Execute the command (a string) in a subshell."""
args = shlex.split(command_line)
process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process = subprocess.Popen(
args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output, error = process.communicate()
retcode = process.poll()
if output and error:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -19,11 +19,11 @@
#include "LLDB/SBDebugger.h"
#include "LLDB/SBFunction.h"
#include "LLDB/SBModule.h"
#include "LLDB/SBProcess.h"
#include "LLDB/SBStream.h"
#include "LLDB/SBSymbol.h"
#include "LLDB/SBTarget.h"
#include "LLDB/SBThread.h"
#include "LLDB/SBProcess.h"
#endif
#include <string>
@ -46,10 +46,10 @@ using namespace lldb;
// then to run this on MacOSX, specify the path to your LLDB.framework
// library using the DYLD_FRAMEWORK_PATH option and run the executable
//
// $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/tot/build/Debug ./a.out executable_path1 [executable_path2 ...]
// $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/tot/build/Debug ./a.out
// executable_path1 [executable_path2 ...]
//----------------------------------------------------------------------
class LLDBSentry
{
class LLDBSentry {
public:
LLDBSentry() {
// Initialize LLDB
@ -61,47 +61,43 @@ public:
}
};
static struct option g_long_options[] =
{
{ "arch", required_argument, NULL, 'a' },
{ "canonical", no_argument, NULL, 'c' },
{ "extern", no_argument, NULL, 'x' },
{ "help", no_argument, NULL, 'h' },
{ "platform", required_argument, NULL, 'p' },
{ "verbose", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
};
static struct option g_long_options[] = {
{"arch", required_argument, NULL, 'a'},
{"canonical", no_argument, NULL, 'c'},
{"extern", no_argument, NULL, 'x'},
{"help", no_argument, NULL, 'h'},
{"platform", required_argument, NULL, 'p'},
{"verbose", no_argument, NULL, 'v'},
{NULL, 0, NULL, 0}};
#define PROGRAM_NAME "lldb-functions"
void
usage ()
{
puts (
"NAME\n"
" " PROGRAM_NAME " -- extract all function signatures from one or more binaries.\n"
void usage() {
puts("NAME\n"
" " PROGRAM_NAME
" -- extract all function signatures from one or more binaries.\n"
"\n"
"SYNOPSIS\n"
" " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] [--verbose] [--help] [--canonical] --] <PATH> [<PATH>....]\n"
" " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] "
"[--verbose] [--help] [--canonical] --] <PATH> "
"[<PATH>....]\n"
"\n"
"DESCRIPTION\n"
" Loads the executable pointed to by <PATH> and dumps complete signatures for all functions that have debug information.\n"
" Loads the executable pointed to by <PATH> and dumps complete "
"signatures for all functions that have debug information.\n"
"\n"
"EXAMPLE\n"
" " PROGRAM_NAME " --arch=x86_64 /usr/lib/dyld\n"
);
" " PROGRAM_NAME " --arch=x86_64 /usr/lib/dyld\n");
exit(0);
}
int
main (int argc, char const *argv[])
{
int main(int argc, char const *argv[]) {
// Use a sentry object to properly initialize/terminate LLDB.
LLDBSentry sentry;
SBDebugger debugger (SBDebugger::Create());
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");
fprintf(stderr, "error: failed to create a debugger object\n");
bool show_usage = false;
bool verbose = false;
@ -110,13 +106,10 @@ main (int argc, char const *argv[])
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))
{
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)
{
switch (opt->has_arg) {
case no_argument:
break;
case required_argument:
@ -135,17 +128,17 @@ main (int argc, char const *argv[])
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)
{
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");
if (arch != NULL) {
fprintf(stderr,
"error: the --arch option can only be specified once\n");
exit(1);
}
arch = optarg;
@ -179,61 +172,55 @@ main (int argc, char const *argv[])
const bool add_dependent_libs = false;
SBError error;
for (int arg_idx = 0; arg_idx < argc; ++arg_idx)
{
for (int arg_idx = 0; arg_idx < argc; ++arg_idx) {
// The first argument is the file path we want to look something up in
const char *exe_file_path = argv[arg_idx];
// Create a target using the executable.
SBTarget target = debugger.CreateTarget (exe_file_path,
arch,
platform,
add_dependent_libs,
error);
SBTarget target = debugger.CreateTarget(exe_file_path, arch, platform,
add_dependent_libs, error);
if (error.Success())
{
if (target.IsValid())
{
SBFileSpec exe_file_spec (exe_file_path, true);
SBModule module (target.FindModule (exe_file_spec));
if (error.Success()) {
if (target.IsValid()) {
SBFileSpec exe_file_spec(exe_file_path, true);
SBModule module(target.FindModule(exe_file_spec));
SBFileSpecList comp_unit_list;
if (module.IsValid())
{
if (module.IsValid()) {
char command[1024];
lldb::SBCommandReturnObject command_result;
snprintf (command, sizeof(command), "add-dsym --uuid %s", module.GetUUIDString());
debugger.GetCommandInterpreter().HandleCommand (command, command_result);
if (!command_result.Succeeded())
{
fprintf (stderr, "error: couldn't locate debug symbols for '%s'\n", exe_file_path);
snprintf(command, sizeof(command), "add-dsym --uuid %s",
module.GetUUIDString());
debugger.GetCommandInterpreter().HandleCommand(command,
command_result);
if (!command_result.Succeeded()) {
fprintf(stderr, "error: couldn't locate debug symbols for '%s'\n",
exe_file_path);
exit(1);
}
SBFileSpecList module_list;
module_list.Append(exe_file_spec);
SBBreakpoint bp = target.BreakpointCreateByRegex (".", module_list, comp_unit_list);
SBBreakpoint bp =
target.BreakpointCreateByRegex(".", module_list, comp_unit_list);
const size_t num_locations = bp.GetNumLocations();
for (uint32_t bp_loc_idx=0; bp_loc_idx<num_locations; ++bp_loc_idx)
{
for (uint32_t bp_loc_idx = 0; bp_loc_idx < num_locations;
++bp_loc_idx) {
SBBreakpointLocation bp_loc = bp.GetLocationAtIndex(bp_loc_idx);
SBSymbolContext sc (bp_loc.GetAddress().GetSymbolContext(eSymbolContextEverything));
if (sc.IsValid())
{
if (sc.GetBlock().GetContainingInlinedBlock().IsValid())
{
SBSymbolContext sc(
bp_loc.GetAddress().GetSymbolContext(eSymbolContextEverything));
if (sc.IsValid()) {
if (sc.GetBlock().GetContainingInlinedBlock().IsValid()) {
// Skip inlined functions
continue;
}
SBFunction function (sc.GetFunction());
if (function.IsValid())
{
SBFunction function(sc.GetFunction());
if (function.IsValid()) {
addr_t lo_pc = function.GetStartAddress().GetFileAddress();
if (lo_pc == LLDB_INVALID_ADDRESS)
{
// Skip functions that don't have concrete instances in the binary
if (lo_pc == LLDB_INVALID_ADDRESS) {
// Skip functions that don't have concrete instances in the
// binary
continue;
}
addr_t hi_pc = function.GetEndAddress().GetFileAddress();
@ -241,27 +228,25 @@ main (int argc, char const *argv[])
const char *func_mangled_name = function.GetMangledName();
bool dump = true;
const bool is_objc_method = ((func_demangled_name[0] == '-') || (func_demangled_name[0] == '+')) && (func_demangled_name[1] == '[');
if (external_only)
{
const bool is_objc_method = ((func_demangled_name[0] == '-') ||
(func_demangled_name[0] == '+')) &&
(func_demangled_name[1] == '[');
if (external_only) {
// Dump all objective C methods, or external symbols
dump = is_objc_method;
if (!dump)
dump = sc.GetSymbol().IsExternal();
}
if (dump)
{
if (verbose)
{
printf ("\n name: %s\n", func_demangled_name);
if (dump) {
if (verbose) {
printf("\n name: %s\n", func_demangled_name);
if (func_mangled_name)
printf ("mangled: %s\n", func_mangled_name);
printf (" range: [0x%16.16llx - 0x%16.16llx)\n type: ", lo_pc, hi_pc);
}
else
{
printf ("[0x%16.16llx - 0x%16.16llx) ", lo_pc, hi_pc);
printf("mangled: %s\n", func_mangled_name);
printf(" range: [0x%16.16llx - 0x%16.16llx)\n type: ",
lo_pc, hi_pc);
} else {
printf("[0x%16.16llx - 0x%16.16llx) ", lo_pc, hi_pc);
}
SBType function_type = function.GetType();
SBType return_type = function_type.GetFunctionReturnType();
@ -269,80 +254,80 @@ main (int argc, char const *argv[])
if (canonical)
return_type = return_type.GetCanonicalType();
if (func_mangled_name &&
func_mangled_name[0] == '_' &&
func_mangled_name[1] == 'Z')
{
printf ("%s %s\n", return_type.GetName(), func_demangled_name);
}
else
{
SBTypeList function_args = function_type.GetFunctionArgumentTypes();
if (func_mangled_name && func_mangled_name[0] == '_' &&
func_mangled_name[1] == 'Z') {
printf("%s %s\n", return_type.GetName(),
func_demangled_name);
} else {
SBTypeList function_args =
function_type.GetFunctionArgumentTypes();
const size_t num_function_args = function_args.GetSize();
if (is_objc_method)
{
if (is_objc_method) {
const char *class_name_start = func_demangled_name + 2;
if (num_function_args == 0)
{
printf("%c(%s)[%s\n", func_demangled_name[0], return_type.GetName(), class_name_start);
}
else
{
const char *class_name_end = strchr(class_name_start,' ');
const int class_name_len = class_name_end - class_name_start;
printf ("%c(%s)[%*.*s", func_demangled_name[0], return_type.GetName(), class_name_len, class_name_len, class_name_start);
if (num_function_args == 0) {
printf("%c(%s)[%s\n", func_demangled_name[0],
return_type.GetName(), class_name_start);
} else {
const char *class_name_end =
strchr(class_name_start, ' ');
const int class_name_len =
class_name_end - class_name_start;
printf("%c(%s)[%*.*s", func_demangled_name[0],
return_type.GetName(), class_name_len,
class_name_len, class_name_start);
const char *selector_pos = class_name_end + 1;
for (uint32_t function_arg_idx = 0; function_arg_idx < num_function_args; ++function_arg_idx)
{
const char *selector_end = strchr(selector_pos, ':') + 1;
for (uint32_t function_arg_idx = 0;
function_arg_idx < num_function_args;
++function_arg_idx) {
const char *selector_end =
strchr(selector_pos, ':') + 1;
const int selector_len = selector_end - selector_pos;
SBType function_arg_type = function_args.GetTypeAtIndex(function_arg_idx);
SBType function_arg_type =
function_args.GetTypeAtIndex(function_arg_idx);
if (canonical)
function_arg_type = function_arg_type.GetCanonicalType();
function_arg_type =
function_arg_type.GetCanonicalType();
printf (" %*.*s", selector_len, selector_len, selector_pos);
if (function_arg_type.IsValid())
{
printf ("(%s)", function_arg_type.GetName());
}
else
{
printf ("(?)");
printf(" %*.*s", selector_len, selector_len,
selector_pos);
if (function_arg_type.IsValid()) {
printf("(%s)", function_arg_type.GetName());
} else {
printf("(?)");
}
selector_pos = selector_end;
}
printf ("]\n");
}
printf("]\n");
}
} else {
printf("%s ", return_type.GetName());
if (strchr(func_demangled_name, '('))
printf("(*)(");
else
{
printf ("%s ", return_type.GetName());
if (strchr (func_demangled_name, '('))
printf ("(*)(");
else
printf ("%s(", func_demangled_name);
printf("%s(", func_demangled_name);
for (uint32_t function_arg_idx = 0; function_arg_idx < num_function_args; ++function_arg_idx)
{
SBType function_arg_type = function_args.GetTypeAtIndex(function_arg_idx);
for (uint32_t function_arg_idx = 0;
function_arg_idx < num_function_args;
++function_arg_idx) {
SBType function_arg_type =
function_args.GetTypeAtIndex(function_arg_idx);
if (canonical)
function_arg_type = function_arg_type.GetCanonicalType();
function_arg_type =
function_arg_type.GetCanonicalType();
if (function_arg_type.IsValid())
{
printf ("%s%s", function_arg_idx > 0 ? ", " : "", function_arg_type.GetName());
}
else
{
printf ("%s???", function_arg_idx > 0 ? ", " : "");
if (function_arg_type.IsValid()) {
printf("%s%s", function_arg_idx > 0 ? ", " : "",
function_arg_type.GetName());
} else {
printf("%s???", function_arg_idx > 0 ? ", " : "");
}
}
printf (")\n");
printf(")\n");
}
}
}
@ -351,14 +336,11 @@ main (int argc, char const *argv[])
}
}
}
}
else
{
fprintf (stderr, "error: %s\n", error.GetCString());
} else {
fprintf(stderr, "error: %s\n", error.GetCString());
exit(1);
}
}
return 0;
}

View File

@ -19,11 +19,11 @@
#include "LLDB/SBDebugger.h"
#include "LLDB/SBFunction.h"
#include "LLDB/SBModule.h"
#include "LLDB/SBProcess.h"
#include "LLDB/SBStream.h"
#include "LLDB/SBSymbol.h"
#include "LLDB/SBTarget.h"
#include "LLDB/SBThread.h"
#include "LLDB/SBProcess.h"
#endif
#include <string>
@ -44,10 +44,10 @@ using namespace lldb;
//
// then (for example):
//
// $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/svn/ToT/build/Debug ./a.out executable_path file_address
// $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/svn/ToT/build/Debug ./a.out
// executable_path file_address
//----------------------------------------------------------------------
class LLDBSentry
{
class LLDBSentry {
public:
LLDBSentry() {
// Initialize LLDB
@ -59,59 +59,51 @@ public:
}
};
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 }
};
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"
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"
" " 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"
" 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"
);
" " PROGRAM_NAME " --arch=x86_64 -- /usr/lib/dyld 0x100000000\n");
exit(0);
}
int
main (int argc, char const *argv[])
{
int main(int argc, char const *argv[]) {
// Use a sentry object to properly initialize/terminate LLDB.
LLDBSentry sentry;
SBDebugger debugger (SBDebugger::Create());
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");
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))
{
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)
{
switch (opt->has_arg) {
case no_argument:
break;
case required_argument:
@ -130,17 +122,17 @@ main (int argc, char const *argv[])
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)
{
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");
if (arch != NULL) {
fprintf(stderr,
"error: the --arch option can only be specified once\n");
exit(1);
}
arch = optarg;
@ -174,39 +166,33 @@ main (int argc, char const *argv[])
const bool add_dependent_libs = false;
SBError error;
SBStream strm;
strm.RedirectToFileHandle (stdout, false);
strm.RedirectToFileHandle(stdout, false);
while ((addr_cstr = argv[++arg_idx]) != NULL)
{
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);
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());
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);
printf("%sLooking up 0x%llx in '%s':\n", (arg_idx > 1) ? "\n" : "",
file_addr, exe_file_path);
if (target.IsValid())
{
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));
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);
SBAddress addr = module.ResolveFileAddress(file_addr);
bool success = addr.IsValid() && addr.GetSection().IsValid();
if (success)
{
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
@ -215,21 +201,22 @@ main (int argc, char const *argv[])
//
// 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));
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");
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);
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;
}

View File

@ -8,8 +8,10 @@
//===----------------------------------------------------------------------===//
/*
An example plugin for LLDB that provides a new foo command with a child subcommand
Compile this into a dylib foo.dylib and load by placing in appropriate locations on disk or
An example plugin for LLDB that provides a new foo command with a child
subcommand
Compile this into a dylib foo.dylib and load by placing in appropriate locations
on disk or
by typing plugin load foo.dylib at the LLDB command line
*/
@ -18,39 +20,28 @@ by typing plugin load foo.dylib at the LLDB command line
#include <LLDB/SBDebugger.h>
namespace lldb {
bool
PluginInitialize (lldb::SBDebugger debugger);
bool PluginInitialize(lldb::SBDebugger debugger);
}
class ChildCommand : public lldb::SBCommandPluginInterface
{
class ChildCommand : public lldb::SBCommandPluginInterface {
public:
virtual bool
DoExecute (lldb::SBDebugger debugger,
char** command,
lldb::SBCommandReturnObject &result)
{
if (command)
{
const char* arg = *command;
while (arg)
{
result.Printf("%s\n",arg);
virtual bool DoExecute(lldb::SBDebugger debugger, char **command,
lldb::SBCommandReturnObject &result) {
if (command) {
const char *arg = *command;
while (arg) {
result.Printf("%s\n", arg);
arg = *(++command);
}
return true;
}
return false;
}
};
bool
lldb::PluginInitialize (lldb::SBDebugger debugger)
{
bool lldb::PluginInitialize(lldb::SBDebugger debugger) {
lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
lldb::SBCommand foo = interpreter.AddMultiwordCommand("foo",NULL);
foo.AddCommand("child",new ChildCommand(),"a child of foo");
lldb::SBCommand foo = interpreter.AddMultiwordCommand("foo", NULL);
foo.AddCommand("child", new ChildCommand(), "a child of foo");
return true;
}

View File

@ -14,20 +14,49 @@ import commands
import optparse
import shlex
def create_framestats_options():
usage = "usage: %prog [options]"
description='''This command is meant to be an example of how to make an LLDB command that
description = '''This command is meant to be an example of how to make an LLDB command that
does something useful, follows best practices, and exploits the SB API.
Specifically, this command computes the aggregate and average size of the variables in the current frame
and allows you to tweak exactly which variables are to be accounted in the computation.
'''
parser = optparse.OptionParser(description=description, prog='framestats',usage=usage)
parser.add_option('-i', '--in-scope', action='store_true', dest='inscope', help='in_scope_only = True', default=False)
parser.add_option('-a', '--arguments', action='store_true', dest='arguments', help='arguments = True', default=False)
parser.add_option('-l', '--locals', action='store_true', dest='locals', help='locals = True', default=False)
parser.add_option('-s', '--statics', action='store_true', dest='statics', help='statics = True', default=False)
parser = optparse.OptionParser(
description=description,
prog='framestats',
usage=usage)
parser.add_option(
'-i',
'--in-scope',
action='store_true',
dest='inscope',
help='in_scope_only = True',
default=False)
parser.add_option(
'-a',
'--arguments',
action='store_true',
dest='arguments',
help='arguments = True',
default=False)
parser.add_option(
'-l',
'--locals',
action='store_true',
dest='locals',
help='locals = True',
default=False)
parser.add_option(
'-s',
'--statics',
action='store_true',
dest='statics',
help='statics = True',
default=False)
return parser
def the_framestats_command(debugger, command, result, dict):
# Use the Shell Lexer to properly parse up command options just like a
# shell would
@ -38,7 +67,7 @@ def the_framestats_command(debugger, command, result, dict):
except:
# if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
# (courtesy of OptParse dealing with argument errors by throwing SystemExit)
result.SetError ("option parsing failed")
result.SetError("option parsing failed")
return
# in a command - the lldb.* convenience variables are not to be used
@ -51,26 +80,33 @@ def the_framestats_command(debugger, command, result, dict):
if not frame.IsValid():
return "no frame here"
# from now on, replace lldb.<thing>.whatever with <thing>.whatever
variables_list = frame.GetVariables(options.arguments, options.locals, options.statics, options.inscope)
variables_list = frame.GetVariables(
options.arguments,
options.locals,
options.statics,
options.inscope)
variables_count = variables_list.GetSize()
if variables_count == 0:
print >> result, "no variables here"
return
total_size = 0
for i in range(0,variables_count):
for i in range(0, variables_count):
variable = variables_list.GetValueAtIndex(i)
variable_type = variable.GetType()
total_size = total_size + variable_type.GetByteSize()
average_size = float(total_size) / variables_count
print >>result, "Your frame has %d variables. Their total size is %d bytes. The average size is %f bytes" % (variables_count,total_size,average_size)
print >>result, "Your frame has %d variables. Their total size is %d bytes. The average size is %f bytes" % (
variables_count, total_size, average_size)
# not returning anything is akin to returning success
def __lldb_init_module (debugger, dict):
def __lldb_init_module(debugger, dict):
# This initializer is being run from LLDB in the embedded command interpreter
# Make the options so we can generate the help text for the new LLDB
# command line command prior to registering it with LLDB below
parser = create_framestats_options()
the_framestats_command.__doc__ = parser.format_help()
# Add any commands contained in this module to LLDB
debugger.HandleCommand('command script add -f cmdtemplate.the_framestats_command framestats')
debugger.HandleCommand(
'command script add -f cmdtemplate.the_framestats_command framestats')
print 'The "framestats" command has been installed, type "help framestats" or "framestats --help" for detailed help.'

View File

@ -53,9 +53,14 @@ except ImportError:
# On Darwin, try the currently selected Xcode directory
xcode_dir = commands.getoutput("xcode-select --print-path")
if xcode_dir:
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
os.path.realpath(
xcode_dir +
'/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(
xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
'/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
success = False
for lldb_python_dir in lldb_python_dirs:
if os.path.exists(lldb_python_dir):
@ -81,19 +86,24 @@ PARSE_MODE_IMAGES = 2
PARSE_MODE_THREGS = 3
PARSE_MODE_SYSTEM = 4
class CrashLog(symbolication.Symbolicator):
"""Class that does parses darwin crash logs"""
parent_process_regex = re.compile('^Parent Process:\s*(.*)\[(\d+)\]');
parent_process_regex = re.compile('^Parent Process:\s*(.*)\[(\d+)\]')
thread_state_regex = re.compile('^Thread ([0-9]+) crashed with')
thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)')
app_backtrace_regex = re.compile('^Application Specific Backtrace ([0-9]+)([^:]*):(.*)')
app_backtrace_regex = re.compile(
'^Application Specific Backtrace ([0-9]+)([^:]*):(.*)')
frame_regex = re.compile('^([0-9]+)\s+([^ ]+)\s+(0x[0-9a-fA-F]+) +(.*)')
image_regex_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^<]+)<([-0-9a-fA-F]+)> (.*)');
image_regex_no_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^/]+)/(.*)');
image_regex_uuid = re.compile(
'(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^<]+)<([-0-9a-fA-F]+)> (.*)')
image_regex_no_uuid = re.compile(
'(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^/]+)/(.*)')
empty_line_regex = re.compile('^$')
class Thread:
"""Class that represents a thread in a darwin crash log"""
def __init__(self, index, app_specific_backtrace):
self.index = index
self.frames = list()
@ -117,7 +127,7 @@ class CrashLog(symbolication.Symbolicator):
for reg in self.registers.keys():
print "%s %-5s = %#16.16x" % (prefix, reg, self.registers[reg])
def dump_symbolicated (self, crash_log, options):
def dump_symbolicated(self, crash_log, options):
this_thread_crashed = self.app_specific_backtrace
if not this_thread_crashed:
this_thread_crashed = self.did_crash()
@ -128,25 +138,31 @@ class CrashLog(symbolication.Symbolicator):
#prev_frame_index = -1
display_frame_idx = -1
for frame_idx, frame in enumerate(self.frames):
disassemble = (this_thread_crashed or options.disassemble_all_threads) and frame_idx < options.disassemble_depth;
disassemble = (
this_thread_crashed or options.disassemble_all_threads) and frame_idx < options.disassemble_depth
if frame_idx == 0:
symbolicated_frame_addresses = crash_log.symbolicate (frame.pc & crash_log.addr_mask, options.verbose)
symbolicated_frame_addresses = crash_log.symbolicate(
frame.pc & crash_log.addr_mask, options.verbose)
else:
# Any frame above frame zero and we have to subtract one to get the previous line entry
symbolicated_frame_addresses = crash_log.symbolicate ((frame.pc & crash_log.addr_mask) - 1, options.verbose)
# Any frame above frame zero and we have to subtract one to
# get the previous line entry
symbolicated_frame_addresses = crash_log.symbolicate(
(frame.pc & crash_log.addr_mask) - 1, options.verbose)
if symbolicated_frame_addresses:
symbolicated_frame_address_idx = 0
for symbolicated_frame_address in symbolicated_frame_addresses:
display_frame_idx += 1
print '[%3u] %s' % (frame_idx, symbolicated_frame_address)
if (options.source_all or self.did_crash()) and display_frame_idx < options.source_frames and options.source_context:
if (options.source_all or self.did_crash(
)) and display_frame_idx < options.source_frames and options.source_context:
source_context = options.source_context
line_entry = symbolicated_frame_address.get_symbol_context().line_entry
if line_entry.IsValid():
strm = lldb.SBStream()
if line_entry:
lldb.debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers(line_entry.file, line_entry.line, source_context, source_context, "->", strm)
lldb.debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers(
line_entry.file, line_entry.line, source_context, source_context, "->", strm)
source_text = strm.GetData()
if source_text:
# Indent the source a bit
@ -158,22 +174,24 @@ class CrashLog(symbolication.Symbolicator):
instructions = symbolicated_frame_address.get_instructions()
if instructions:
print
symbolication.disassemble_instructions (crash_log.get_target(),
symbolication.disassemble_instructions(
crash_log.get_target(),
instructions,
frame.pc,
options.disassemble_before,
options.disassemble_after, frame.index > 0)
options.disassemble_after,
frame.index > 0)
print
symbolicated_frame_address_idx += 1
else:
print frame
def add_ident(self, ident):
if not ident in self.idents:
if ident not in self.idents:
self.idents.append(ident)
def did_crash(self):
return self.reason != None
return self.reason is not None
def __str__(self):
if self.app_specific_backtrace:
@ -184,9 +202,9 @@ class CrashLog(symbolication.Symbolicator):
s += ' %s' % self.reason
return s
class Frame:
"""Class that represents a stack frame in a thread in a darwin crash log"""
def __init__(self, index, pc, description):
self.pc = pc
self.description = description
@ -194,7 +212,8 @@ class CrashLog(symbolication.Symbolicator):
def __str__(self):
if self.description:
return "[%3u] 0x%16.16x %s" % (self.index, self.pc, self.description)
return "[%3u] 0x%16.16x %s" % (
self.index, self.pc, self.description)
else:
return "[%3u] 0x%16.16x" % (self.index, self.pc)
@ -207,11 +226,23 @@ class CrashLog(symbolication.Symbolicator):
if not os.path.exists(dsymForUUIDBinary):
dsymForUUIDBinary = commands.getoutput('which dsymForUUID')
dwarfdump_uuid_regex = re.compile('UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*')
dwarfdump_uuid_regex = re.compile(
'UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*')
def __init__(self, text_addr_lo, text_addr_hi, identifier, version, uuid, path):
symbolication.Image.__init__(self, path, uuid);
self.add_section (symbolication.Section(text_addr_lo, text_addr_hi, "__TEXT"))
def __init__(
self,
text_addr_lo,
text_addr_hi,
identifier,
version,
uuid,
path):
symbolication.Image.__init__(self, path, uuid)
self.add_section(
symbolication.Section(
text_addr_lo,
text_addr_hi,
"__TEXT"))
self.identifier = identifier
self.version = version
@ -224,37 +255,42 @@ class CrashLog(symbolication.Symbolicator):
uuid_str = self.get_normalized_uuid_string()
print 'Getting symbols for %s %s...' % (uuid_str, self.path),
if os.path.exists(self.dsymForUUIDBinary):
dsym_for_uuid_command = '%s %s' % (self.dsymForUUIDBinary, uuid_str)
dsym_for_uuid_command = '%s %s' % (
self.dsymForUUIDBinary, uuid_str)
s = commands.getoutput(dsym_for_uuid_command)
if s:
plist_root = plistlib.readPlistFromString (s)
plist_root = plistlib.readPlistFromString(s)
if plist_root:
plist = plist_root[uuid_str]
if plist:
if 'DBGArchitecture' in plist:
self.arch = plist['DBGArchitecture']
if 'DBGDSYMPath' in plist:
self.symfile = os.path.realpath(plist['DBGDSYMPath'])
self.symfile = os.path.realpath(
plist['DBGDSYMPath'])
if 'DBGSymbolRichExecutable' in plist:
self.path = os.path.expanduser (plist['DBGSymbolRichExecutable'])
self.path = os.path.expanduser(
plist['DBGSymbolRichExecutable'])
self.resolved_path = self.path
if not self.resolved_path and os.path.exists(self.path):
dwarfdump_cmd_output = commands.getoutput('dwarfdump --uuid "%s"' % self.path)
dwarfdump_cmd_output = commands.getoutput(
'dwarfdump --uuid "%s"' % self.path)
self_uuid = self.get_uuid()
for line in dwarfdump_cmd_output.splitlines():
match = self.dwarfdump_uuid_regex.search (line)
match = self.dwarfdump_uuid_regex.search(line)
if match:
dwarf_uuid_str = match.group(1)
dwarf_uuid = uuid.UUID(dwarf_uuid_str)
if self_uuid == dwarf_uuid:
self.resolved_path = self.path
self.arch = match.group(2)
break;
break
if not self.resolved_path:
self.unavailable = True
print "error\n error: unable to locate '%s' with UUID %s" % (self.path, uuid_str)
return False
if (self.resolved_path and os.path.exists(self.resolved_path)) or (self.path and os.path.exists(self.path)):
if (self.resolved_path and os.path.exists(self.resolved_path)) or (
self.path and os.path.exists(self.path)):
print 'ok'
# if self.resolved_path:
# print ' exe = "%s"' % self.resolved_path
@ -265,12 +301,10 @@ class CrashLog(symbolication.Symbolicator):
self.unavailable = True
return False
def __init__(self, path):
"""CrashLog constructor that take a path to a darwin crash log file"""
symbolication.Symbolicator.__init__(self);
self.path = os.path.expanduser(path);
symbolication.Symbolicator.__init__(self)
self.path = os.path.expanduser(path)
self.info_lines = list()
self.system_profile = list()
self.threads = list()
@ -280,7 +314,8 @@ class CrashLog(symbolication.Symbolicator):
self.version = -1
self.error = None
self.target = None
# With possible initial component of ~ or ~user replaced by that user's home directory.
# With possible initial component of ~ or ~user replaced by that user's
# home directory.
try:
f = open(self.path)
except IOError:
@ -316,70 +351,73 @@ class CrashLog(symbolication.Symbolicator):
parse_mode = PARSE_MODE_NORMAL
# print 'PARSE_MODE_NORMAL'
elif parse_mode == PARSE_MODE_NORMAL:
if line.startswith ('Process:'):
(self.process_name, pid_with_brackets) = line[8:].strip().split(' [')
if line.startswith('Process:'):
(self.process_name, pid_with_brackets) = line[
8:].strip().split(' [')
self.process_id = pid_with_brackets.strip('[]')
elif line.startswith ('Path:'):
elif line.startswith('Path:'):
self.process_path = line[5:].strip()
elif line.startswith ('Identifier:'):
elif line.startswith('Identifier:'):
self.process_identifier = line[11:].strip()
elif line.startswith ('Version:'):
elif line.startswith('Version:'):
version_string = line[8:].strip()
matched_pair = re.search("(.+)\((.+)\)", version_string)
if matched_pair:
self.process_version = matched_pair.group(1)
self.process_compatability_version = matched_pair.group(2)
self.process_compatability_version = matched_pair.group(
2)
else:
self.process = version_string
self.process_compatability_version = version_string
elif self.parent_process_regex.search(line):
parent_process_match = self.parent_process_regex.search(line)
parent_process_match = self.parent_process_regex.search(
line)
self.parent_process_name = parent_process_match.group(1)
self.parent_process_id = parent_process_match.group(2)
elif line.startswith ('Exception Type:'):
elif line.startswith('Exception Type:'):
self.thread_exception = line[15:].strip()
continue
elif line.startswith ('Exception Codes:'):
elif line.startswith('Exception Codes:'):
self.thread_exception_data = line[16:].strip()
continue
elif line.startswith ('Crashed Thread:'):
elif line.startswith('Crashed Thread:'):
self.crashed_thread_idx = int(line[15:].strip().split()[0])
continue
elif line.startswith ('Report Version:'):
elif line.startswith('Report Version:'):
self.version = int(line[15:].strip())
continue
elif line.startswith ('System Profile:'):
elif line.startswith('System Profile:'):
parse_mode = PARSE_MODE_SYSTEM
continue
elif (line.startswith ('Interval Since Last Report:') or
line.startswith ('Crashes Since Last Report:') or
line.startswith ('Per-App Interval Since Last Report:') or
line.startswith ('Per-App Crashes Since Last Report:') or
line.startswith ('Sleep/Wake UUID:') or
line.startswith ('Anonymous UUID:')):
elif (line.startswith('Interval Since Last Report:') or
line.startswith('Crashes Since Last Report:') or
line.startswith('Per-App Interval Since Last Report:') or
line.startswith('Per-App Crashes Since Last Report:') or
line.startswith('Sleep/Wake UUID:') or
line.startswith('Anonymous UUID:')):
# ignore these
continue
elif line.startswith ('Thread'):
thread_state_match = self.thread_state_regex.search (line)
elif line.startswith('Thread'):
thread_state_match = self.thread_state_regex.search(line)
if thread_state_match:
app_specific_backtrace = False
thread_state_match = self.thread_regex.search (line)
thread_state_match = self.thread_regex.search(line)
thread_idx = int(thread_state_match.group(1))
parse_mode = PARSE_MODE_THREGS
thread = self.threads[thread_idx]
else:
thread_match = self.thread_regex.search (line)
thread_match = self.thread_regex.search(line)
if thread_match:
app_specific_backtrace = False
parse_mode = PARSE_MODE_THREAD
thread_idx = int(thread_match.group(1))
thread = CrashLog.Thread(thread_idx, False)
continue
elif line.startswith ('Binary Images:'):
elif line.startswith('Binary Images:'):
parse_mode = PARSE_MODE_IMAGES
continue
elif line.startswith ('Application Specific Backtrace'):
app_backtrace_match = self.app_backtrace_regex.search (line)
elif line.startswith('Application Specific Backtrace'):
app_backtrace_match = self.app_backtrace_regex.search(line)
if app_backtrace_match:
parse_mode = PARSE_MODE_THREAD
app_specific_backtrace = True
@ -387,49 +425,51 @@ class CrashLog(symbolication.Symbolicator):
thread = CrashLog.Thread(idx, True)
self.info_lines.append(line.strip())
elif parse_mode == PARSE_MODE_THREAD:
if line.startswith ('Thread'):
if line.startswith('Thread'):
continue
frame_match = self.frame_regex.search(line)
if frame_match:
ident = frame_match.group(2)
thread.add_ident(ident)
if not ident in self.idents:
if ident not in self.idents:
self.idents.append(ident)
thread.frames.append (CrashLog.Frame(int(frame_match.group(1)), int(frame_match.group(3), 0), frame_match.group(4)))
thread.frames.append(CrashLog.Frame(int(frame_match.group(1)), int(
frame_match.group(3), 0), frame_match.group(4)))
else:
print 'error: frame regex failed for line: "%s"' % line
elif parse_mode == PARSE_MODE_IMAGES:
image_match = self.image_regex_uuid.search (line)
image_match = self.image_regex_uuid.search(line)
if image_match:
image = CrashLog.DarwinImage (int(image_match.group(1),0),
int(image_match.group(2),0),
image = CrashLog.DarwinImage(int(image_match.group(1), 0),
int(image_match.group(2), 0),
image_match.group(3).strip(),
image_match.group(4).strip(),
uuid.UUID(image_match.group(5)),
image_match.group(6))
self.images.append (image)
self.images.append(image)
else:
image_match = self.image_regex_no_uuid.search (line)
image_match = self.image_regex_no_uuid.search(line)
if image_match:
image = CrashLog.DarwinImage (int(image_match.group(1),0),
int(image_match.group(2),0),
image = CrashLog.DarwinImage(int(image_match.group(1), 0),
int(image_match.group(2), 0),
image_match.group(3).strip(),
image_match.group(4).strip(),
None,
image_match.group(5))
self.images.append (image)
self.images.append(image)
else:
print "error: image regex failed for: %s" % line
elif parse_mode == PARSE_MODE_THREGS:
stripped_line = line.strip()
# "r12: 0x00007fff6b5939c8 r13: 0x0000000007000006 r14: 0x0000000000002a03 r15: 0x0000000000000c00"
reg_values = re.findall ('([a-zA-Z0-9]+: 0[Xx][0-9a-fA-F]+) *', stripped_line);
reg_values = re.findall(
'([a-zA-Z0-9]+: 0[Xx][0-9a-fA-F]+) *', stripped_line)
for reg_value in reg_values:
#print 'reg_value = "%s"' % reg_value
# print 'reg_value = "%s"' % reg_value
(reg, value) = reg_value.split(': ')
#print 'reg = "%s"' % reg
#print 'value = "%s"' % value
# print 'reg = "%s"' % reg
# print 'value = "%s"' % value
thread.registers[reg.strip()] = int(value, 0)
elif parse_mode == PARSE_MODE_SYSTEM:
self.system_profile.append(line)
@ -460,23 +500,24 @@ class CrashLog(symbolication.Symbolicator):
return None
def create_target(self):
#print 'crashlog.create_target()...'
# print 'crashlog.create_target()...'
if self.target is None:
self.target = symbolication.Symbolicator.create_target(self)
if self.target:
return self.target
# We weren't able to open the main executable as, but we can still symbolicate
# We weren't able to open the main executable as, but we can still
# symbolicate
print 'crashlog.create_target()...2'
if self.idents:
for ident in self.idents:
image = self.find_image_with_identifier (ident)
image = self.find_image_with_identifier(ident)
if image:
self.target = image.create_target ()
self.target = image.create_target()
if self.target:
return self.target # success
print 'crashlog.create_target()...3'
for image in self.images:
self.target = image.create_target ()
self.target = image.create_target()
if self.target:
return self.target # success
print 'crashlog.create_target()...4'
@ -486,10 +527,12 @@ class CrashLog(symbolication.Symbolicator):
def get_target(self):
return self.target
def usage():
print "Usage: lldb-symbolicate.py [-n name] executable-image"
sys.exit(0)
class Interactive(cmd.Cmd):
'''Interactive prompt for analyzing one or more Darwin crash logs, type "help" to see a list of supported commands.'''
image_option_parser = None
@ -515,10 +558,11 @@ class Interactive(cmd.Cmd):
return True
def do_symbolicate(self, line):
description='''Symbolicate one or more darwin crash log files by index to provide source file and line information,
description = '''Symbolicate one or more darwin crash log files by index to provide source file and line information,
inlined stack frames back to the concrete functions, and disassemble the location of the crash
for the first frame of the crashed thread.'''
option_parser = CreateSymbolicateCrashLogOptions ('symbolicate', description, False)
option_parser = CreateSymbolicateCrashLogOptions(
'symbolicate', description, False)
command_args = shlex.split(line)
try:
(options, args) = option_parser.parse_args(command_args)
@ -530,13 +574,14 @@ class Interactive(cmd.Cmd):
for idx_str in args:
idx = int(idx_str)
if idx < len(self.crash_logs):
SymbolicateCrashLog (self.crash_logs[idx], options)
SymbolicateCrashLog(self.crash_logs[idx], options)
else:
print 'error: crash log index %u is out of range' % (idx)
else:
# No arguments, symbolicate all crash logs using the options provided
# No arguments, symbolicate all crash logs using the options
# provided
for idx in range(len(self.crash_logs)):
SymbolicateCrashLog (self.crash_logs[idx], options)
SymbolicateCrashLog(self.crash_logs[idx], options)
def do_list(self, line=None):
'''Dump a list of all crash logs that are currently loaded.
@ -549,11 +594,17 @@ class Interactive(cmd.Cmd):
def do_image(self, line):
'''Dump information about one or more binary images in the crash log given an image basename, or all images if no arguments are provided.'''
usage = "usage: %prog [options] <PATH> [PATH ...]"
description='''Dump information about one or more images in all crash logs. The <PATH> can be a full path, image basename, or partial path. Searches are done in this order.'''
description = '''Dump information about one or more images in all crash logs. The <PATH> can be a full path, image basename, or partial path. Searches are done in this order.'''
command_args = shlex.split(line)
if not self.image_option_parser:
self.image_option_parser = optparse.OptionParser(description=description, prog='image',usage=usage)
self.image_option_parser.add_option('-a', '--all', action='store_true', help='show all images', default=False)
self.image_option_parser = optparse.OptionParser(
description=description, prog='image', usage=usage)
self.image_option_parser.add_option(
'-a',
'--all',
action='store_true',
help='show all images',
default=False)
try:
(options, args) = self.image_option_parser.parse_args(command_args)
except:
@ -577,7 +628,8 @@ class Interactive(cmd.Cmd):
if matches_found == 0:
for (image_idx, image) in enumerate(crash_log.images):
resolved_image_path = image.get_resolved_path()
if resolved_image_path and string.find(image.get_resolved_path(), image_path) >= 0:
if resolved_image_path and string.find(
image.get_resolved_path(), image_path) >= 0:
print '[%u] ' % (crash_log_idx), image
else:
for crash_log in self.crash_logs:
@ -592,9 +644,9 @@ def interactive_crashlogs(options, args):
for resolved_path in glob.glob(arg):
crash_log_files.append(resolved_path)
crash_logs = list();
crash_logs = list()
for crash_log_file in crash_log_files:
#print 'crash_log_file = "%s"' % crash_log_file
# print 'crash_log_file = "%s"' % crash_log_file
crash_log = CrashLog(crash_log_file)
if crash_log.error:
print crash_log.error
@ -615,20 +667,32 @@ def interactive_crashlogs(options, args):
def save_crashlog(debugger, command, result, dict):
usage = "usage: %prog [options] <output-path>"
description='''Export the state of current target into a crashlog file'''
parser = optparse.OptionParser(description=description, prog='save_crashlog',usage=usage)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
description = '''Export the state of current target into a crashlog file'''
parser = optparse.OptionParser(
description=description,
prog='save_crashlog',
usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
try:
(options, args) = parser.parse_args(shlex.split(command))
except:
result.PutCString ("error: invalid options");
result.PutCString("error: invalid options")
return
if len(args) != 1:
result.PutCString ("error: invalid arguments, a single output file is the only valid argument")
result.PutCString(
"error: invalid arguments, a single output file is the only valid argument")
return
out_file = open(args[0], 'w')
if not out_file:
result.PutCString ("error: failed to open file '%s' for writing...", args[0]);
result.PutCString(
"error: failed to open file '%s' for writing...",
args[0])
return
target = debugger.GetSelectedTarget()
if target:
@ -636,11 +700,16 @@ def save_crashlog(debugger, command, result, dict):
if lldb.process:
pid = lldb.process.id
if pid != lldb.LLDB_INVALID_PROCESS_ID:
out_file.write('Process: %s [%u]\n' % (identifier, pid))
out_file.write(
'Process: %s [%u]\n' %
(identifier, pid))
out_file.write('Path: %s\n' % (target.executable.fullpath))
out_file.write('Identifier: %s\n' % (identifier))
out_file.write('\nDate/Time: %s\n' % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
out_file.write('OS Version: Mac OS X %s (%s)\n' % (platform.mac_ver()[0], commands.getoutput('sysctl -n kern.osversion')));
out_file.write('\nDate/Time: %s\n' %
(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
out_file.write(
'OS Version: Mac OS X %s (%s)\n' %
(platform.mac_ver()[0], commands.getoutput('sysctl -n kern.osversion')))
out_file.write('Report Version: 9\n')
for thread_idx in range(lldb.process.num_threads):
thread = lldb.process.thread[thread_idx]
@ -658,7 +727,9 @@ def save_crashlog(debugger, command, result, dict):
frame_offset = frame_pc - frame.function.addr.load_addr
elif frame.symbol:
frame_offset = frame_pc - frame.symbol.addr.load_addr
out_file.write('%-3u %-32s 0x%16.16x %s' % (frame_idx, frame.module.file.basename, frame_pc, frame.name))
out_file.write(
'%-3u %-32s 0x%16.16x %s' %
(frame_idx, frame.module.file.basename, frame_pc, frame.name))
if frame_offset > 0:
out_file.write(' + %u' % (frame_offset))
line_entry = frame.line_entry
@ -667,7 +738,9 @@ def save_crashlog(debugger, command, result, dict):
# This will output the fullpath + line + column
out_file.write(' %s' % (line_entry))
else:
out_file.write(' %s:%u' % (line_entry.file.basename, line_entry.line))
out_file.write(
' %s:%u' %
(line_entry.file.basename, line_entry.line))
column = line_entry.column
if column:
out_file.write(':%u' % (column))
@ -684,18 +757,27 @@ def save_crashlog(debugger, command, result, dict):
module_version = '???'
module_version_array = module.GetVersion()
if module_version_array:
module_version = '.'.join(map(str,module_version_array))
out_file.write (' 0x%16.16x - 0x%16.16x %s (%s - ???) <%s> %s\n' % (text_segment_load_addr, text_segment_end_load_addr, identifier, module_version, module.GetUUIDString(), module.file.fullpath))
module_version = '.'.join(
map(str, module_version_array))
out_file.write(
' 0x%16.16x - 0x%16.16x %s (%s - ???) <%s> %s\n' %
(text_segment_load_addr,
text_segment_end_load_addr,
identifier,
module_version,
module.GetUUIDString(),
module.file.fullpath))
out_file.close()
else:
result.PutCString ("error: invalid target");
result.PutCString("error: invalid target")
def Symbolicate(debugger, command, result, dict):
try:
SymbolicateCrashLogs (shlex.split(command))
SymbolicateCrashLogs(shlex.split(command))
except:
result.PutCString ("error: python exception %s" % sys.exc_info()[0])
result.PutCString("error: python exception %s" % sys.exc_info()[0])
def SymbolicateCrashLog(crash_log, options):
if crash_log.error:
@ -715,7 +797,7 @@ def SymbolicateCrashLog(crash_log, options):
else:
print image
target = crash_log.create_target ()
target = crash_log.create_target()
if not target:
return
exe_module = target.GetModuleAtIndex(0)
@ -731,7 +813,7 @@ def SymbolicateCrashLog(crash_log, options):
for thread in crash_log.threads:
if thread.did_crash():
for ident in thread.idents:
images = crash_log.find_images_with_identifier (ident)
images = crash_log.find_images_with_identifier(ident)
if images:
for image in images:
images_to_load.append(image)
@ -739,7 +821,7 @@ def SymbolicateCrashLog(crash_log, options):
print 'error: can\'t find image for identifier "%s"' % ident
else:
for ident in crash_log.idents:
images = crash_log.find_images_with_identifier (ident)
images = crash_log.find_images_with_identifier(ident)
if images:
for image in images:
images_to_load.append(image)
@ -747,46 +829,133 @@ def SymbolicateCrashLog(crash_log, options):
print 'error: can\'t find image for identifier "%s"' % ident
for image in images_to_load:
if not image in loaded_images:
err = image.add_module (target)
if image not in loaded_images:
err = image.add_module(target)
if err:
print err
else:
#print 'loaded %s' % image
# print 'loaded %s' % image
loaded_images.append(image)
if crash_log.backtraces:
for thread in crash_log.backtraces:
thread.dump_symbolicated (crash_log, options)
thread.dump_symbolicated(crash_log, options)
print
for thread in crash_log.threads:
thread.dump_symbolicated (crash_log, options)
thread.dump_symbolicated(crash_log, options)
print
def CreateSymbolicateCrashLogOptions(command_name, description, add_interactive_options):
def CreateSymbolicateCrashLogOptions(
command_name,
description,
add_interactive_options):
usage = "usage: %prog [options] <FILE> [FILE ...]"
option_parser = optparse.OptionParser(description=description, prog='crashlog',usage=usage)
option_parser.add_option('--verbose' , '-v', action='store_true', dest='verbose', help='display verbose debug info', default=False)
option_parser.add_option('--debug' , '-g', action='store_true', dest='debug', help='display verbose debug logging', default=False)
option_parser.add_option('--load-all' , '-a', action='store_true', dest='load_all_images', help='load all executable images, not just the images found in the crashed stack frames', default=False)
option_parser.add_option('--images' , action='store_true', dest='dump_image_list', help='show image list', default=False)
option_parser.add_option('--debug-delay' , type='int', dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for debugger', default=0)
option_parser.add_option('--crashed-only' , '-c', action='store_true', dest='crashed_only', help='only symbolicate the crashed thread', default=False)
option_parser.add_option('--disasm-depth' , '-d', type='int', dest='disassemble_depth', help='set the depth in stack frames that should be disassembled (default is 1)', default=1)
option_parser.add_option('--disasm-all' , '-D', action='store_true', dest='disassemble_all_threads', help='enabled disassembly of frames on all threads (not just the crashed thread)', default=False)
option_parser.add_option('--disasm-before' , '-B', type='int', dest='disassemble_before', help='the number of instructions to disassemble before the frame PC', default=4)
option_parser.add_option('--disasm-after' , '-A', type='int', dest='disassemble_after', help='the number of instructions to disassemble after the frame PC', default=4)
option_parser.add_option('--source-context', '-C', type='int', metavar='NLINES', dest='source_context', help='show NLINES source lines of source context (default = 4)', default=4)
option_parser.add_option('--source-frames' , type='int', metavar='NFRAMES', dest='source_frames', help='show source for NFRAMES (default = 4)', default=4)
option_parser.add_option('--source-all' , action='store_true', dest='source_all', help='show source for all threads, not just the crashed thread', default=False)
option_parser = optparse.OptionParser(
description=description, prog='crashlog', usage=usage)
option_parser.add_option(
'--verbose',
'-v',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
option_parser.add_option(
'--debug',
'-g',
action='store_true',
dest='debug',
help='display verbose debug logging',
default=False)
option_parser.add_option(
'--load-all',
'-a',
action='store_true',
dest='load_all_images',
help='load all executable images, not just the images found in the crashed stack frames',
default=False)
option_parser.add_option(
'--images',
action='store_true',
dest='dump_image_list',
help='show image list',
default=False)
option_parser.add_option(
'--debug-delay',
type='int',
dest='debug_delay',
metavar='NSEC',
help='pause for NSEC seconds for debugger',
default=0)
option_parser.add_option(
'--crashed-only',
'-c',
action='store_true',
dest='crashed_only',
help='only symbolicate the crashed thread',
default=False)
option_parser.add_option(
'--disasm-depth',
'-d',
type='int',
dest='disassemble_depth',
help='set the depth in stack frames that should be disassembled (default is 1)',
default=1)
option_parser.add_option(
'--disasm-all',
'-D',
action='store_true',
dest='disassemble_all_threads',
help='enabled disassembly of frames on all threads (not just the crashed thread)',
default=False)
option_parser.add_option(
'--disasm-before',
'-B',
type='int',
dest='disassemble_before',
help='the number of instructions to disassemble before the frame PC',
default=4)
option_parser.add_option(
'--disasm-after',
'-A',
type='int',
dest='disassemble_after',
help='the number of instructions to disassemble after the frame PC',
default=4)
option_parser.add_option(
'--source-context',
'-C',
type='int',
metavar='NLINES',
dest='source_context',
help='show NLINES source lines of source context (default = 4)',
default=4)
option_parser.add_option(
'--source-frames',
type='int',
metavar='NFRAMES',
dest='source_frames',
help='show source for NFRAMES (default = 4)',
default=4)
option_parser.add_option(
'--source-all',
action='store_true',
dest='source_all',
help='show source for all threads, not just the crashed thread',
default=False)
if add_interactive_options:
option_parser.add_option('-i', '--interactive', action='store_true', help='parse all crash logs and enter interactive mode', default=False)
option_parser.add_option(
'-i',
'--interactive',
action='store_true',
help='parse all crash logs and enter interactive mode',
default=False)
return option_parser
def SymbolicateCrashLogs(command_args):
description='''Symbolicate one or more darwin crash log files to provide source file and line information,
description = '''Symbolicate one or more darwin crash log files to provide source file and line information,
inlined stack frames back to the concrete functions, and disassemble the location of the crash
for the first frame of the crashed thread.
If this script is imported into the LLDB command interpreter, a "crashlog" command will be added to the interpreter
@ -794,7 +963,8 @@ for use at the LLDB command line. After a crash log has been parsed and symbolic
created that has all of the shared libraries loaded at the load addresses found in the crash log file. This allows
you to explore the program as if it were stopped at the locations described in the crash log and functions can
be disassembled and lookups can be performed using the addresses found in the crash log.'''
option_parser = CreateSymbolicateCrashLogOptions ('crashlog', description, True)
option_parser = CreateSymbolicateCrashLogOptions(
'crashlog', description, True)
try:
(options, args) = option_parser.parse_args(command_args)
except:
@ -816,14 +986,15 @@ be disassembled and lookups can be performed using the addresses found in the cr
else:
for crash_log_file in args:
crash_log = CrashLog(crash_log_file)
SymbolicateCrashLog (crash_log, options)
SymbolicateCrashLog(crash_log, options)
if __name__ == '__main__':
# Create a new debugger instance
lldb.debugger = lldb.SBDebugger.Create()
SymbolicateCrashLogs (sys.argv[1:])
lldb.SBDebugger.Destroy (lldb.debugger)
SymbolicateCrashLogs(sys.argv[1:])
lldb.SBDebugger.Destroy(lldb.debugger)
elif getattr(lldb, 'debugger', None):
lldb.debugger.HandleCommand('command script add -f lldb.macosx.crashlog.Symbolicate crashlog')
lldb.debugger.HandleCommand('command script add -f lldb.macosx.crashlog.save_crashlog save_crashlog')
lldb.debugger.HandleCommand(
'command script add -f lldb.macosx.crashlog.Symbolicate crashlog')
lldb.debugger.HandleCommand(
'command script add -f lldb.macosx.crashlog.save_crashlog save_crashlog')
print '"crashlog" and "save_crashlog" command installed, use the "--help" option for detailed help'

View File

@ -23,13 +23,16 @@ import shlex
import re
import tempfile
def start_gdb_log(debugger, command, result, dict):
'''Start logging GDB remote packets by enabling logging with timestamps and
thread safe logging. Follow a call to this function with a call to "stop_gdb_log"
in order to dump out the commands.'''
global log_file
if log_file:
result.PutCString ('error: logging is already in progress with file "%s"', log_file)
result.PutCString(
'error: logging is already in progress with file "%s"',
log_file)
else:
args_len = len(args)
if args_len == 0:
@ -38,30 +41,46 @@ def start_gdb_log(debugger, command, result, dict):
log_file = args[0]
if log_file:
debugger.HandleCommand('log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % log_file);
result.PutCString ("GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." % log_file)
debugger.HandleCommand(
'log enable --threadsafe --timestamp --file "%s" gdb-remote packets' %
log_file)
result.PutCString(
"GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." %
log_file)
return
result.PutCString ('error: invalid log file path')
result.PutCString (usage)
result.PutCString('error: invalid log file path')
result.PutCString(usage)
def parse_time_log(debugger, command, result, dict):
# Any commands whose names might be followed by more valid C identifier
# characters must be listed here
command_args = shlex.split(command)
parse_time_log_args (command_args)
parse_time_log_args(command_args)
def parse_time_log_args(command_args):
usage = "usage: parse_time_log [options] [<LOGFILEPATH>]"
description='''Parse a log file that contains timestamps and convert the timestamps to delta times between log lines.'''
parser = optparse.OptionParser(description=description, prog='parse_time_log',usage=usage)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
description = '''Parse a log file that contains timestamps and convert the timestamps to delta times between log lines.'''
parser = optparse.OptionParser(
description=description,
prog='parse_time_log',
usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
try:
(options, args) = parser.parse_args(command_args)
except:
return
for log_file in args:
parse_log_file (log_file, options)
parse_log_file(log_file, options)
def parse_log_file(file, options):
'''Parse a log file that was contains timestamps. These logs are typically
@ -86,9 +105,9 @@ def parse_log_file(file, options):
file = open(file)
lines = file.read().splitlines()
for line in lines:
match = timestamp_regex.match (line)
match = timestamp_regex.match(line)
if match:
curr_time = float (match.group(2))
curr_time = float(match.group(2))
delta = 0.0
if base_time:
delta = curr_time - last_time
@ -101,15 +120,15 @@ def parse_log_file(file, options):
print line
if __name__ == '__main__':
import sys
parse_time_log_args (sys.argv[1:])
parse_time_log_args(sys.argv[1:])
else:
import lldb
if lldb.debugger:
# This initializer is being run from LLDB in the embedded command interpreter
# Add any commands contained in this module to LLDB
lldb.debugger.HandleCommand('command script add -f delta.parse_time_log parse_time_log')
lldb.debugger.HandleCommand(
'command script add -f delta.parse_time_log parse_time_log')
print 'The "parse_time_log" command is now installed and ready for use, type "parse_time_log --help" for more information'

View File

@ -1,17 +1,19 @@
# This implements the "diagnose-nsstring" command, usually installed in the debug session like
# command script import lldb.diagnose
# it is used when NSString summary formatter fails to replicate the logic that went into LLDB making the
# decisions it did and providing some useful context information that can be used for improving the formatter
# decisions it did and providing some useful context information that can
# be used for improving the formatter
import lldb
def read_memory(process,location,size):
def read_memory(process, location, size):
data = ""
error = lldb.SBError()
for x in range(0,size-1):
byte = process.ReadUnsignedFromMemory(x+location,1,error)
for x in range(0, size - 1):
byte = process.ReadUnsignedFromMemory(x + location, 1, error)
if error.fail:
data = data + "err%s" % "" if x == size-2 else ":"
data = data + "err%s" % "" if x == size - 2 else ":"
else:
try:
data = data + "0x%x" % byte
@ -27,13 +29,14 @@ def read_memory(process,location,size):
data = data + "(\\n)"
else:
data = data + "(%s)" % chr(byte)
if x < size-2:
if x < size - 2:
data = data + ":"
except Exception as e:
print e
return data
def diagnose_nsstring_Command_Impl(debugger,command,result,internal_dict):
def diagnose_nsstring_Command_Impl(debugger, command, result, internal_dict):
"""
A command to diagnose the LLDB NSString data formatter
invoke as
@ -51,10 +54,10 @@ def diagnose_nsstring_Command_Impl(debugger,command,result,internal_dict):
options.SetFetchDynamicValue()
error = lldb.SBError()
if frame.IsValid():
nsstring = frame.EvaluateExpression(command,options)
nsstring = frame.EvaluateExpression(command, options)
else:
nsstring = target.EvaluateExpression(command,options)
print >>result,str(nsstring)
nsstring = target.EvaluateExpression(command, options)
print >>result, str(nsstring)
nsstring_address = nsstring.GetValueAsUnsigned(0)
if nsstring_address == 0:
return "unable to obtain the string - cannot proceed"
@ -99,27 +102,29 @@ struct $__lldb__CFString {\
expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address
# print expression
dumped = target.EvaluateExpression(expression,options)
dumped = target.EvaluateExpression(expression, options)
print >>result, str(dumped)
little_endian = (target.byte_order == lldb.eByteOrderLittle)
ptr_size = target.addr_size
info_bits = dumped.GetChildMemberWithName("_cfinfo").GetChildAtIndex(0 if little_endian else 3).GetValueAsUnsigned(0)
info_bits = dumped.GetChildMemberWithName("_cfinfo").GetChildAtIndex(
0 if little_endian else 3).GetValueAsUnsigned(0)
is_mutable = (info_bits & 1) == 1
is_inline = (info_bits & 0x60) == 0
has_explicit_length = (info_bits & (1 | 4)) != 4
is_unicode = (info_bits & 0x10) == 0x10
is_special = (nsstring.GetDynamicValue(lldb.eDynamicCanRunTarget).GetTypeName() == "NSPathStore2")
is_special = (
nsstring.GetDynamicValue(
lldb.eDynamicCanRunTarget).GetTypeName() == "NSPathStore2")
has_null = (info_bits & 8) == 8
print >>result,"\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n" % \
(info_bits, "yes" if is_mutable else "no","yes" if is_inline else "no","yes" if has_explicit_length else "no","yes" if is_unicode else "no","yes" if is_special else "no","yes" if has_null else "no")
print >>result, "\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n" % \
(info_bits, "yes" if is_mutable else "no", "yes" if is_inline else "no", "yes" if has_explicit_length else "no", "yes" if is_unicode else "no", "yes" if is_special else "no", "yes" if has_null else "no")
explicit_length_offset = 0
if not has_null and has_explicit_length and not is_special:
explicit_length_offset = 2*ptr_size
explicit_length_offset = 2 * ptr_size
if is_mutable and not is_inline:
explicit_length_offset = explicit_length_offset + ptr_size
elif is_inline:
@ -130,26 +135,28 @@ struct $__lldb__CFString {\
explicit_length_offset = 0
if explicit_length_offset == 0:
print >>result,"There is no explicit length marker - skipping this step\n"
print >>result, "There is no explicit length marker - skipping this step\n"
else:
explicit_length_offset = nsstring_address + explicit_length_offset
explicit_length = process.ReadUnsignedFromMemory(explicit_length_offset, 4, error)
print >>result,"Explicit length location is at 0x%x - read value is %d\n" % (explicit_length_offset,explicit_length)
explicit_length = process.ReadUnsignedFromMemory(
explicit_length_offset, 4, error)
print >>result, "Explicit length location is at 0x%x - read value is %d\n" % (
explicit_length_offset, explicit_length)
if is_mutable:
location = 2 * ptr_size + nsstring_address
location = process.ReadPointerFromMemory(location,error)
location = process.ReadPointerFromMemory(location, error)
elif is_inline and has_explicit_length and not is_unicode and not is_special and not is_mutable:
location = 3 * ptr_size + nsstring_address
elif is_unicode:
location = 2 * ptr_size + nsstring_address
if is_inline:
if not has_explicit_length:
print >>result,"Unicode & Inline & !Explicit is a new combo - no formula for it"
print >>result, "Unicode & Inline & !Explicit is a new combo - no formula for it"
else:
location += ptr_size
else:
location = process.ReadPointerFromMemory(location,error)
location = process.ReadPointerFromMemory(location, error)
elif is_special:
location = nsstring_address + ptr_size + 4
elif is_inline:
@ -158,14 +165,19 @@ struct $__lldb__CFString {\
location += 1
else:
location = 2 * ptr_size + nsstring_address
location = process.ReadPointerFromMemory(location,error)
print >>result,"Expected data location: 0x%x\n" % (location)
print >>result,"1K of data around location: %s\n" % read_memory(process,location,1024)
print >>result,"5K of data around string pointer: %s\n" % read_memory(process,nsstring_address,1024*5)
location = process.ReadPointerFromMemory(location, error)
print >>result, "Expected data location: 0x%x\n" % (location)
print >>result, "1K of data around location: %s\n" % read_memory(
process, location, 1024)
print >>result, "5K of data around string pointer: %s\n" % read_memory(
process, nsstring_address, 1024 * 5)
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand("command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" % __name__)
debugger.HandleCommand(
"command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" %
__name__)
print 'The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.'
__lldb_init_module(lldb.debugger,None)
__lldb_init_module(lldb.debugger, None)
__lldb_init_module = None

View File

@ -13,7 +13,9 @@ import shlex
# Print the frame number, pc, frame pointer, module UUID and function name
# Returns the SBModule that contains the PC, if it could be found
def backtrace_print_frame (target, frame_num, addr, fp):
def backtrace_print_frame(target, frame_num, addr, fp):
process = target.GetProcess()
addr_for_printing = addr
addr_width = process.GetAddressByteSize() * 2
@ -27,19 +29,21 @@ def backtrace_print_frame (target, frame_num, addr, fp):
if sbaddr.GetModule():
module_filename = ""
module_uuid_str = sbaddr.GetModule().GetUUIDString()
if module_uuid_str == None:
if module_uuid_str is None:
module_uuid_str = ""
if sbaddr.GetModule().GetFileSpec():
module_filename = sbaddr.GetModule().GetFileSpec().GetFilename()
if module_filename == None:
if module_filename is None:
module_filename = ""
if module_uuid_str != "" or module_filename != "":
module_description = '%s %s' % (module_filename, module_uuid_str)
module_description = '%s %s' % (
module_filename, module_uuid_str)
except Exception:
print '%2d: pc==0x%-*x fp==0x%-*x' % (frame_num, addr_width, addr_for_printing, addr_width, fp)
return
sym_ctx = target.ResolveSymbolContextForAddress(sbaddr, lldb.eSymbolContextEverything)
sym_ctx = target.ResolveSymbolContextForAddress(
sbaddr, lldb.eSymbolContextEverything)
if sym_ctx.IsValid() and sym_ctx.GetSymbol().IsValid():
function_start = sym_ctx.GetSymbol().GetStartAddress().GetLoadAddress(target)
offset = addr - function_start
@ -51,6 +55,8 @@ def backtrace_print_frame (target, frame_num, addr, fp):
# A simple stack walk algorithm that follows the frame chain.
# Returns a two-element list; the first element is a list of modules
# seen and the second element is a list of addresses seen during the backtrace.
def simple_backtrace(debugger):
target = debugger.GetSelectedTarget()
process = target.GetProcess()
@ -58,42 +64,49 @@ def simple_backtrace(debugger):
initial_fp = cur_thread.GetFrameAtIndex(0).GetFP()
# If the pseudoreg "fp" isn't recognized, on arm hardcode to r7 which is correct for Darwin programs.
# If the pseudoreg "fp" isn't recognized, on arm hardcode to r7 which is
# correct for Darwin programs.
if initial_fp == lldb.LLDB_INVALID_ADDRESS and target.triple[0:3] == "arm":
for reggroup in cur_thread.GetFrameAtIndex(1).registers:
if reggroup.GetName() == "General Purpose Registers":
for reg in reggroup:
if reg.GetName() == "r7":
initial_fp = int (reg.GetValue(), 16)
initial_fp = int(reg.GetValue(), 16)
module_list = []
address_list = [cur_thread.GetFrameAtIndex(0).GetPC()]
this_module = backtrace_print_frame (target, 0, cur_thread.GetFrameAtIndex(0).GetPC(), initial_fp)
print_stack_frame (process, initial_fp)
this_module = backtrace_print_frame(
target, 0, cur_thread.GetFrameAtIndex(0).GetPC(), initial_fp)
print_stack_frame(process, initial_fp)
print ""
if this_module != None:
module_list.append (this_module)
if this_module is not None:
module_list.append(this_module)
if cur_thread.GetNumFrames() < 2:
return [module_list, address_list]
cur_fp = process.ReadPointerFromMemory (initial_fp, lldb.SBError())
cur_pc = process.ReadPointerFromMemory (initial_fp + process.GetAddressByteSize(), lldb.SBError())
cur_fp = process.ReadPointerFromMemory(initial_fp, lldb.SBError())
cur_pc = process.ReadPointerFromMemory(
initial_fp + process.GetAddressByteSize(), lldb.SBError())
frame_num = 1
while cur_pc != 0 and cur_fp != 0 and cur_pc != lldb.LLDB_INVALID_ADDRESS and cur_fp != lldb.LLDB_INVALID_ADDRESS:
address_list.append (cur_pc)
this_module = backtrace_print_frame (target, frame_num, cur_pc, cur_fp)
print_stack_frame (process, cur_fp)
address_list.append(cur_pc)
this_module = backtrace_print_frame(target, frame_num, cur_pc, cur_fp)
print_stack_frame(process, cur_fp)
print ""
if this_module != None:
module_list.append (this_module)
if this_module is not None:
module_list.append(this_module)
frame_num = frame_num + 1
next_pc = 0
next_fp = 0
if target.triple[0:6] == "x86_64" or target.triple[0:4] == "i386" or target.triple[0:3] == "arm":
if target.triple[
0:6] == "x86_64" or target.triple[
0:4] == "i386" or target.triple[
0:3] == "arm":
error = lldb.SBError()
next_pc = process.ReadPointerFromMemory(cur_fp + process.GetAddressByteSize(), error)
next_pc = process.ReadPointerFromMemory(
cur_fp + process.GetAddressByteSize(), error)
if not error.Success():
next_pc = 0
next_fp = process.ReadPointerFromMemory(cur_fp, error)
@ -104,13 +117,14 @@ def simple_backtrace(debugger):
next_pc = next_pc & ~1
cur_pc = next_pc
cur_fp = next_fp
this_module = backtrace_print_frame (target, frame_num, cur_pc, cur_fp)
print_stack_frame (process, cur_fp)
this_module = backtrace_print_frame(target, frame_num, cur_pc, cur_fp)
print_stack_frame(process, cur_fp)
print ""
if this_module != None:
module_list.append (this_module)
if this_module is not None:
module_list.append(this_module)
return [module_list, address_list]
def print_stack_frame(process, fp):
if fp == 0 or fp == lldb.LLDB_INVALID_ADDRESS or fp == 1:
return
@ -121,20 +135,22 @@ def print_stack_frame(process, fp):
error = lldb.SBError()
try:
while i < 5 and error.Success():
address = process.ReadPointerFromMemory(addr + (i * addr_size), error)
address = process.ReadPointerFromMemory(
addr + (i * addr_size), error)
outline += " 0x%x" % address
i += 1
print outline
except Exception:
return
def diagnose_unwind(debugger, command, result, dict):
"""
Gather diagnostic information to help debug incorrect unwind (backtrace)
behavior in lldb. When there is a backtrace that doesn't look
correct, run this command with the correct thread selected and a
large amount of diagnostic information will be printed, it is likely
to be helpful when reporting the problem.
Gather diagnostic information to help debug incorrect unwind (backtrace)
behavior in lldb. When there is a backtrace that doesn't look
correct, run this command with the correct thread selected and a
large amount of diagnostic information will be printed, it is likely
to be helpful when reporting the problem.
"""
command_args = shlex.split(command)
@ -149,12 +165,16 @@ to be helpful when reporting the problem.
if process:
thread = process.GetSelectedThread()
if thread:
lldb_versions_match = re.search(r'[lL][lL][dD][bB]-(\d+)([.](\d+))?([.](\d+))?', debugger.GetVersionString())
lldb_versions_match = re.search(
r'[lL][lL][dD][bB]-(\d+)([.](\d+))?([.](\d+))?',
debugger.GetVersionString())
lldb_version = 0
lldb_minor = 0
if len(lldb_versions_match.groups()) >= 1 and lldb_versions_match.groups()[0]:
if len(lldb_versions_match.groups()
) >= 1 and lldb_versions_match.groups()[0]:
lldb_major = int(lldb_versions_match.groups()[0])
if len(lldb_versions_match.groups()) >= 5 and lldb_versions_match.groups()[4]:
if len(lldb_versions_match.groups()
) >= 5 and lldb_versions_match.groups()[4]:
lldb_minor = int(lldb_versions_match.groups()[4])
modules_seen = []
@ -166,7 +186,8 @@ to be helpful when reporting the problem.
print "============================================================================================="
print ""
print "OS plugin setting:"
debugger.HandleCommand("settings show target.process.python-os-plugin-path")
debugger.HandleCommand(
"settings show target.process.python-os-plugin-path")
print ""
print "Live register context:"
thread.SetSelectedFrame(0)
@ -179,12 +200,13 @@ to be helpful when reporting the problem.
frame_num = 0
for frame in thread.frames:
if not frame.IsInlined():
this_module = backtrace_print_frame (target, frame_num, frame.GetPC(), frame.GetFP())
print_stack_frame (process, frame.GetFP())
this_module = backtrace_print_frame(
target, frame_num, frame.GetPC(), frame.GetFP())
print_stack_frame(process, frame.GetFP())
print ""
if this_module != None:
modules_seen.append (this_module)
addresses_seen.append (frame.GetPC())
if this_module is not None:
modules_seen.append(this_module)
addresses_seen.append(frame.GetPC())
frame_num = frame_num + 1
print ""
print "============================================================================================="
@ -192,9 +214,9 @@ to be helpful when reporting the problem.
print "Simple stack walk algorithm:"
print ""
(module_list, address_list) = simple_backtrace(debugger)
if module_list and module_list != None:
if module_list and module_list is not None:
modules_seen += module_list
if address_list and address_list != None:
if address_list and address_list is not None:
addresses_seen = set(addresses_seen)
addresses_seen.update(set(address_list))
@ -205,10 +227,13 @@ to be helpful when reporting the problem.
print ""
modules_already_seen = set()
for module in modules_seen:
if module != None and module.GetFileSpec().GetFilename() != None:
if module is not None and module.GetFileSpec().GetFilename() is not None:
if not module.GetFileSpec().GetFilename() in modules_already_seen:
debugger.HandleCommand('image list %s' % module.GetFileSpec().GetFilename())
modules_already_seen.add(module.GetFileSpec().GetFilename())
debugger.HandleCommand(
'image list %s' %
module.GetFileSpec().GetFilename())
modules_already_seen.add(
module.GetFileSpec().GetFilename())
print ""
print "============================================================================================="
@ -222,20 +247,29 @@ to be helpful when reporting the problem.
print ""
print "Disassembly of %s, frame %d, address 0x%x" % (frame.GetFunctionName(), frame.GetFrameID(), frame.GetPC())
print ""
if target.triple[0:6] == "x86_64" or target.triple[0:4] == "i386":
debugger.HandleCommand('disassemble -F att -a 0x%x' % frame.GetPC())
if target.triple[
0:6] == "x86_64" or target.triple[
0:4] == "i386":
debugger.HandleCommand(
'disassemble -F att -a 0x%x' % frame.GetPC())
else:
debugger.HandleCommand('disassemble -a 0x%x' % frame.GetPC())
debugger.HandleCommand(
'disassemble -a 0x%x' %
frame.GetPC())
if frame.GetPC() in additional_addresses_to_disassemble:
additional_addresses_to_disassemble.remove (frame.GetPC())
additional_addresses_to_disassemble.remove(
frame.GetPC())
for address in list(additional_addresses_to_disassemble):
print "--------------------------------------------------------------------------------------"
print ""
print "Disassembly of 0x%x" % address
print ""
if target.triple[0:6] == "x86_64" or target.triple[0:4] == "i386":
debugger.HandleCommand('disassemble -F att -a 0x%x' % address)
if target.triple[
0:6] == "x86_64" or target.triple[
0:4] == "i386":
debugger.HandleCommand(
'disassemble -F att -a 0x%x' % address)
else:
debugger.HandleCommand('disassemble -a 0x%x' % address)
@ -249,22 +283,31 @@ to be helpful when reporting the problem.
print ""
print "Unwind instructions for %s, frame %d" % (frame.GetFunctionName(), frame.GetFrameID())
print ""
debugger.HandleCommand('image show-unwind -a "0x%x"' % frame.GetPC())
debugger.HandleCommand(
'image show-unwind -a "0x%x"' % frame.GetPC())
if frame.GetPC() in additional_addresses_to_show_unwind:
additional_addresses_to_show_unwind.remove (frame.GetPC())
additional_addresses_to_show_unwind.remove(
frame.GetPC())
for address in list(additional_addresses_to_show_unwind):
print "--------------------------------------------------------------------------------------"
print ""
print "Unwind instructions for 0x%x" % address
print ""
debugger.HandleCommand('image show-unwind -a "0x%x"' % address)
debugger.HandleCommand(
'image show-unwind -a "0x%x"' % address)
def create_diagnose_unwind_options():
usage = "usage: %prog"
description='''Print diagnostic information about a thread backtrace which will help to debug unwind problems'''
parser = optparse.OptionParser(description=description, prog='diagnose_unwind',usage=usage)
description = '''Print diagnostic information about a thread backtrace which will help to debug unwind problems'''
parser = optparse.OptionParser(
description=description,
prog='diagnose_unwind',
usage=usage)
return parser
lldb.debugger.HandleCommand('command script add -f %s.diagnose_unwind diagnose-unwind' % __name__)
lldb.debugger.HandleCommand(
'command script add -f %s.diagnose_unwind diagnose-unwind' %
__name__)
print 'The "diagnose-unwind" command has been installed, type "help diagnose-unwind" for detailed help.'

View File

@ -3,25 +3,26 @@ class LookupDictionary(dict):
"""
a dictionary which can lookup value by key, or keys by value
"""
def __init__(self, items=[]):
"""items can be a list of pair_lists or a dictionary"""
dict.__init__(self, items)
def get_keys_for_value(self, value, fail_value = None):
def get_keys_for_value(self, value, fail_value=None):
"""find the key(s) as a list given a value"""
list_result = [item[0] for item in self.items() if item[1] == value]
if len(list_result) > 0:
return list_result
return fail_value
def get_first_key_for_value(self, value, fail_value = None):
def get_first_key_for_value(self, value, fail_value=None):
"""return the first key of this dictionary given the value"""
list_result = [item[0] for item in self.items() if item[1] == value]
if len(list_result) > 0:
return list_result[0]
return fail_value
def get_value(self, key, fail_value = None):
def get_value(self, key, fail_value=None):
"""find the value given a key"""
if key in self:
return self[key]
@ -52,8 +53,8 @@ class Enum(LookupDictionary):
return self.__str__()
def __str__(self):
s = self.get_first_key_for_value (self.value, None)
if s == None:
s = self.get_first_key_for_value(self.value, None)
if s is None:
s = "%#8.8x" % self.value
return s

View File

@ -1,40 +1,82 @@
#!/usr/bin/python
import argparse, datetime, re, subprocess, sys, time
import argparse
import datetime
import re
import subprocess
import sys
import time
parser = argparse.ArgumentParser(description="Run an exhaustive test of the LLDB disassembler for a specific architecture.")
parser = argparse.ArgumentParser(
description="Run an exhaustive test of the LLDB disassembler for a specific architecture.")
parser.add_argument('--arch', required=True, action='store', help='The architecture whose disassembler is to be tested')
parser.add_argument('--bytes', required=True, action='store', type=int, help='The byte width of instructions for that architecture')
parser.add_argument('--random', required=False, action='store_true', help='Enables non-sequential testing')
parser.add_argument('--start', required=False, action='store', type=int, help='The first instruction value to test')
parser.add_argument('--skip', required=False, action='store', type=int, help='The interval between instructions to test')
parser.add_argument('--log', required=False, action='store', help='A log file to write the most recent instruction being tested')
parser.add_argument('--time', required=False, action='store_true', help='Every 100,000 instructions, print an ETA to standard out')
parser.add_argument('--lldb', required=False, action='store', help='The path to LLDB.framework, if LLDB should be overridden')
parser.add_argument(
'--arch',
required=True,
action='store',
help='The architecture whose disassembler is to be tested')
parser.add_argument(
'--bytes',
required=True,
action='store',
type=int,
help='The byte width of instructions for that architecture')
parser.add_argument(
'--random',
required=False,
action='store_true',
help='Enables non-sequential testing')
parser.add_argument(
'--start',
required=False,
action='store',
type=int,
help='The first instruction value to test')
parser.add_argument(
'--skip',
required=False,
action='store',
type=int,
help='The interval between instructions to test')
parser.add_argument(
'--log',
required=False,
action='store',
help='A log file to write the most recent instruction being tested')
parser.add_argument(
'--time',
required=False,
action='store_true',
help='Every 100,000 instructions, print an ETA to standard out')
parser.add_argument(
'--lldb',
required=False,
action='store',
help='The path to LLDB.framework, if LLDB should be overridden')
arguments = sys.argv[1:]
arg_ns = parser.parse_args(arguments)
def AddLLDBToSysPathOnMacOSX():
def GetLLDBFrameworkPath():
lldb_path = subprocess.check_output(["xcrun", "-find", "lldb"])
re_result = re.match("(.*)/Developer/usr/bin/lldb", lldb_path)
if re_result == None:
if re_result is None:
return None
xcode_contents_path = re_result.group(1)
return xcode_contents_path + "/SharedFrameworks/LLDB.framework"
lldb_framework_path = GetLLDBFrameworkPath()
if lldb_framework_path == None:
if lldb_framework_path is None:
print "Couldn't find LLDB.framework"
sys.exit(-1)
sys.path.append(lldb_framework_path + "/Resources/Python")
if arg_ns.lldb == None:
if arg_ns.lldb is None:
AddLLDBToSysPathOnMacOSX()
else:
sys.path.append(arg_ns.lldb + "/Resources/Python")
@ -53,16 +95,20 @@ if target.IsValid() == False:
print "Couldn't create an SBTarget for architecture " + arg_ns.arch
sys.exit(-1)
def ResetLogFile(log_file):
if log_file != sys.stdout:
log_file.seek(0)
def PrintByteArray(log_file, byte_array):
for byte in byte_array:
print >>log_file, hex(byte) + " ",
print >>log_file
class SequentialInstructionProvider:
def __init__(self, byte_width, log_file, start=0, skip=1):
self.m_byte_width = byte_width
self.m_log_file = log_file
@ -70,10 +116,12 @@ class SequentialInstructionProvider:
self.m_skip = skip
self.m_value = start
self.m_last = (1 << (byte_width * 8)) - 1
def PrintCurrentState(self, ret):
ResetLogFile(self.m_log_file)
print >>self.m_log_file, self.m_value
PrintByteArray(self.m_log_file, ret)
def GetNextInstruction(self):
if self.m_value > self.m_last:
return None
@ -83,57 +131,68 @@ class SequentialInstructionProvider:
self.PrintCurrentState(ret)
self.m_value += self.m_skip
return ret
def GetNumInstructions(self):
return (self.m_last - self.m_start) / self.m_skip
def __iter__(self):
return self
def next(self):
ret = self.GetNextInstruction()
if ret == None:
if ret is None:
raise StopIteration
return ret
class RandomInstructionProvider:
def __init__(self, byte_width, log_file):
self.m_byte_width = byte_width
self.m_log_file = log_file
self.m_random_file = open("/dev/random", 'r')
def PrintCurrentState(self, ret):
ResetLogFile(self.m_log_file)
PrintByteArray(self.m_log_file, ret)
def GetNextInstruction(self):
ret = bytearray(self.m_byte_width)
for i in range(self.m_byte_width):
ret[i] = self.m_random_file.read(1)
self.PrintCurrentState(ret)
return ret
def __iter__(self):
return self
def next(self):
ret = self.GetNextInstruction()
if ret == None:
if ret is None:
raise StopIteration
return ret
log_file = None
def GetProviderWithArguments(args):
global log_file
if args.log != None:
if args.log is not None:
log_file = open(args.log, 'w')
else:
log_file = sys.stdout
instruction_provider = None
if args.random == True:
if args.random:
instruction_provider = RandomInstructionProvider(args.bytes, log_file)
else:
start = 0
skip = 1
if args.start != None:
if args.start is not None:
start = args.start
if args.skip != None:
if args.skip is not None:
skip = args.skip
instruction_provider = SequentialInstructionProvider(args.bytes, log_file, start, skip)
instruction_provider = SequentialInstructionProvider(
args.bytes, log_file, start, skip)
return instruction_provider
instruction_provider = GetProviderWithArguments(arg_ns)
@ -149,10 +208,13 @@ if actually_time:
for inst_bytes in instruction_provider:
if actually_time:
if (num_instructions_logged != 0) and (num_instructions_logged % 100000 == 0):
if (num_instructions_logged != 0) and (
num_instructions_logged % 100000 == 0):
curr_time = time.time()
elapsed_time = curr_time - start_time
remaining_time = float(total_num_instructions - num_instructions_logged) * (float(elapsed_time) / float(num_instructions_logged))
remaining_time = float(
total_num_instructions - num_instructions_logged) * (
float(elapsed_time) / float(num_instructions_logged))
print str(datetime.timedelta(seconds=remaining_time))
num_instructions_logged = num_instructions_logged + 1
inst_list = target.GetInstructions(fake_address, inst_bytes)

View File

@ -12,10 +12,12 @@ import lldb
import os
import sys
def disassemble_instructions (insts):
def disassemble_instructions(insts):
for i in insts:
print i
def usage():
print "Usage: disasm.py [-n name] executable-image"
print " By default, it breaks at and disassembles the 'main' function."
@ -38,61 +40,67 @@ debugger = lldb.SBDebugger.Create()
# When we step or continue, don't return from the function until the process
# stops. We do this by setting the async mode to false.
debugger.SetAsync (False)
debugger.SetAsync(False)
# Create a target from a file and arch
print "Creating a target for '%s'" % exe
target = debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
target = debugger.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT)
if target:
# If the target is valid set a breakpoint at main
main_bp = target.BreakpointCreateByName (fname, target.GetExecutable().GetFilename());
main_bp = target.BreakpointCreateByName(
fname, target.GetExecutable().GetFilename())
print main_bp
# Launch the process. Since we specified synchronous mode, we won't return
# from this function until we hit the breakpoint at main
process = target.LaunchSimple (None, None, os.getcwd())
process = target.LaunchSimple(None, None, os.getcwd())
# Make sure the launch went ok
if process:
# Print some simple process info
state = process.GetState ()
state = process.GetState()
print process
if state == lldb.eStateStopped:
# Get the first thread
thread = process.GetThreadAtIndex (0)
thread = process.GetThreadAtIndex(0)
if thread:
# Print some simple thread info
print thread
# Get the first frame
frame = thread.GetFrameAtIndex (0)
frame = thread.GetFrameAtIndex(0)
if frame:
# Print some simple frame info
print frame
function = frame.GetFunction()
# See if we have debug info (a function)
if function:
# We do have a function, print some info for the function
# We do have a function, print some info for the
# function
print function
# Now get all instructions for this function and print them
# Now get all instructions for this function and print
# them
insts = function.GetInstructions(target)
disassemble_instructions (insts)
disassemble_instructions(insts)
else:
# See if we have a symbol in the symbol table for where we stopped
symbol = frame.GetSymbol();
# See if we have a symbol in the symbol table for where
# we stopped
symbol = frame.GetSymbol()
if symbol:
# We do have a symbol, print some info for the symbol
# We do have a symbol, print some info for the
# symbol
print symbol
# Now get all instructions for this symbol and print them
# Now get all instructions for this symbol and
# print them
insts = symbol.GetInstructions(target)
disassemble_instructions (insts)
disassemble_instructions(insts)
registerList = frame.GetRegisters()
print "Frame registers (size of register set = %d):" % registerList.GetSize()
for value in registerList:
#print value
# print value
print "%s (number of children = %d):" % (value.GetName(), value.GetNumChildren())
for child in value:
print "Name: ", child.GetName(), " Value: ", child.GetValue()
@ -111,9 +119,8 @@ if target:
elif state == lldb.eStateExited:
print "Didn't hit the breakpoint at main, program has exited..."
else:
print "Unexpected process state: %s, killing process..." % debugger.StateAsCString (state)
print "Unexpected process state: %s, killing process..." % debugger.StateAsCString(state)
process.Kill()
lldb.SBDebugger.Terminate()

View File

@ -4,10 +4,11 @@ import string
import struct
import sys
class FileExtract:
'''Decode binary data from a file'''
def __init__(self, f, b = '='):
def __init__(self, f, b='='):
'''Initialize with an open binary file and optional byte order'''
self.file = f
@ -33,7 +34,7 @@ class FileExtract:
def is_in_memory(self):
return False
def seek(self, offset, whence = 0):
def seek(self, offset, whence=0):
if self.file:
return self.file.seek(offset, whence)
raise ValueError
@ -43,7 +44,7 @@ class FileExtract:
return self.file.tell()
raise ValueError
def read_size (self, byte_size):
def read_size(self, byte_size):
s = self.file.read(byte_size)
if len(s) != byte_size:
return None
@ -131,7 +132,11 @@ class FileExtract:
else:
return fail_value
def get_fixed_length_c_string(self, n, fail_value='', isprint_only_with_space_padding=False):
def get_fixed_length_c_string(
self,
n,
fail_value='',
isprint_only_with_space_padding=False):
'''Extract a single fixed length C string from the binary file at the current file position, returns a single C string'''
s = self.read_size(n)
if s:
@ -174,7 +179,7 @@ class FileExtract:
def get_n_sint16(self, n, fail_value=0):
'''Extract "n" int16_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(2*n)
s = self.read_size(2 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'h', s)
else:
@ -182,7 +187,7 @@ class FileExtract:
def get_n_uint16(self, n, fail_value=0):
'''Extract "n" uint16_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(2*n)
s = self.read_size(2 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'H', s)
else:
@ -190,7 +195,7 @@ class FileExtract:
def get_n_sint32(self, n, fail_value=0):
'''Extract "n" int32_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(4*n)
s = self.read_size(4 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'i', s)
else:
@ -198,7 +203,7 @@ class FileExtract:
def get_n_uint32(self, n, fail_value=0):
'''Extract "n" uint32_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(4*n)
s = self.read_size(4 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'I', s)
else:
@ -206,7 +211,7 @@ class FileExtract:
def get_n_sint64(self, n, fail_value=0):
'''Extract "n" int64_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(8*n)
s = self.read_size(8 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'q', s)
else:
@ -214,7 +219,7 @@ class FileExtract:
def get_n_uint64(self, n, fail_value=0):
'''Extract "n" uint64_t integers from the binary file at the current file position, returns a list of integers'''
s = self.read_size(8*n)
s = self.read_size(8 * n)
if s:
return struct.unpack(self.byte_order + ("%u" % n) + 'Q', s)
else:

View File

@ -1,5 +1,6 @@
import lldb
def disassemble(debugger, command, result, dict):
if lldb.frame.function:
instructions = lldb.frame.function.instructions
@ -20,5 +21,6 @@ def disassemble(debugger, command, result, dict):
print "<%s + %-4u> 0x%x %8s %s" % (name, inst_offset, inst_addr, inst.mnemonic, inst.operands)
# Install the command when the module gets imported
lldb.debugger.HandleCommand('command script add -f gdb_disassemble.disassemble gdb-disassemble')
lldb.debugger.HandleCommand(
'command script add -f gdb_disassemble.disassemble gdb-disassemble')
print 'Installed "gdb-disassemble" command for disassembly'

File diff suppressed because it is too large Load Diff

View File

@ -15,19 +15,22 @@ import os
import shlex
import sys
def get_globals(raw_path, options):
error = lldb.SBError()
# Resolve the path if needed
path = os.path.expanduser(raw_path)
# Create a target using path + options
target = lldb.debugger.CreateTarget(path, options.arch, options.platform, False, error)
target = lldb.debugger.CreateTarget(
path, options.arch, options.platform, False, error)
if target:
# Get the executable module
module = target.module[target.executable.basename]
if module:
# Keep track of which variables we have already looked up
global_names = list()
# Iterate through all symbols in the symbol table and watch for any DATA symbols
# Iterate through all symbols in the symbol table and watch for any
# DATA symbols
for symbol in module.symbols:
if symbol.type == lldb.eSymbolTypeData:
# The symbol is a DATA symbol, lets try and find all global variables
@ -37,36 +40,67 @@ def get_globals(raw_path, options):
if global_name not in global_names:
global_names.append(global_name)
# Find all global variables by name
global_variable_list = module.FindGlobalVariables (target, global_name, lldb.UINT32_MAX)
global_variable_list = module.FindGlobalVariables(
target, global_name, lldb.UINT32_MAX)
if global_variable_list:
# Print results for anything that matched
for global_variable in global_variable_list:
print 'name = %s' % global_variable.name # returns the global variable name as a string
print 'value = %s' % global_variable.value # Returns the variable value as a string
# returns the global variable name as a string
print 'name = %s' % global_variable.name
# Returns the variable value as a string
print 'value = %s' % global_variable.value
print 'type = %s' % global_variable.type # Returns an lldb.SBType object
print 'addr = %s' % global_variable.addr # Returns an lldb.SBAddress (section offset address) for this global
print 'file_addr = 0x%x' % global_variable.addr.file_addr # Returns the file virtual address for this global
print 'location = %s' % global_variable.location # returns the global variable value as a string
print 'size = %s' % global_variable.size # Returns the size in bytes of this global variable
# Returns an lldb.SBAddress (section offset
# address) for this global
print 'addr = %s' % global_variable.addr
# Returns the file virtual address for this
# global
print 'file_addr = 0x%x' % global_variable.addr.file_addr
# returns the global variable value as a string
print 'location = %s' % global_variable.location
# Returns the size in bytes of this global
# variable
print 'size = %s' % global_variable.size
print
def globals(command_args):
'''Extract all globals from any arguments which must be paths to object files.'''
usage = "usage: %prog [options] <PATH> [PATH ...]"
description='''This command will find all globals in the specified object file and return an list() of lldb.SBValue objects (which might be empty).'''
parser = optparse.OptionParser(description=description, prog='globals',usage=usage)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
parser.add_option('-a', '--arch', type='string', metavar='arch', dest='arch', help='Specify an architecture (or triple) to use when extracting from a file.')
parser.add_option('-p', '--platform', type='string', metavar='platform', dest='platform', help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
description = '''This command will find all globals in the specified object file and return an list() of lldb.SBValue objects (which might be empty).'''
parser = optparse.OptionParser(
description=description,
prog='globals',
usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
parser.add_option(
'-a',
'--arch',
type='string',
metavar='arch',
dest='arch',
help='Specify an architecture (or triple) to use when extracting from a file.')
parser.add_option(
'-p',
'--platform',
type='string',
metavar='platform',
dest='platform',
help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
try:
(options, args) = parser.parse_args(command_args)
except:
return
for path in args:
get_globals (path, options)
get_globals(path, options)
if __name__ == '__main__':
lldb.debugger = lldb.SBDebugger.Create()
globals (sys.argv[1:])
globals(sys.argv[1:])

View File

@ -1,6 +1,8 @@
import lldb, re
import lldb
import re
def parse_linespec (linespec, frame, result):
def parse_linespec(linespec, frame, result):
"""Handles a subset of GDB-style linespecs. Specifically:
number - A line in the current file
@ -21,65 +23,73 @@ def parse_linespec (linespec, frame, result):
if (not matched):
mo = re.match("^([0-9]+)$", linespec)
if (mo != None):
if (mo is not None):
matched = True
#print "Matched <linenum>"
# print "Matched <linenum>"
line_number = int(mo.group(1))
line_entry = frame.GetLineEntry()
if not line_entry.IsValid():
result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.")
result.AppendMessage(
"Specified a line in the current file, but the current frame doesn't have line table information.")
return
breakpoint = target.BreakpointCreateByLocation (line_entry.GetFileSpec(), line_number)
breakpoint = target.BreakpointCreateByLocation(
line_entry.GetFileSpec(), line_number)
if (not matched):
mo = re.match("^\+([0-9]+)$", linespec)
if (mo != None):
if (mo is not None):
matched = True
#print "Matched +<count>"
# print "Matched +<count>"
line_number = int(mo.group(1))
line_entry = frame.GetLineEntry()
if not line_entry.IsValid():
result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.")
result.AppendMessage(
"Specified a line in the current file, but the current frame doesn't have line table information.")
return
breakpoint = target.BreakpointCreateByLocation(line_entry.GetFileSpec(), (line_entry.GetLine() + line_number))
breakpoint = target.BreakpointCreateByLocation(
line_entry.GetFileSpec(), (line_entry.GetLine() + line_number))
if (not matched):
mo = re.match("^\-([0-9]+)$", linespec)
if (mo != None):
if (mo is not None):
matched = True
#print "Matched -<count>"
# print "Matched -<count>"
line_number = int(mo.group(1))
line_entry = frame.GetLineEntry()
if not line_entry.IsValid():
result.AppendMessage("Specified a line in the current file, but the current frame doesn't have line table information.")
result.AppendMessage(
"Specified a line in the current file, but the current frame doesn't have line table information.")
return
breakpoint = target.BreakpointCreateByLocation(line_entry.GetFileSpec(), (line_entry.GetLine() - line_number))
breakpoint = target.BreakpointCreateByLocation(
line_entry.GetFileSpec(), (line_entry.GetLine() - line_number))
if (not matched):
mo = re.match("^(.*):([0-9]+)$", linespec)
if (mo != None):
if (mo is not None):
matched = True
#print "Matched <filename>:<linenum>"
# print "Matched <filename>:<linenum>"
file_name = mo.group(1)
line_number = int(mo.group(2))
breakpoint = target.BreakpointCreateByLocation(file_name, line_number)
breakpoint = target.BreakpointCreateByLocation(
file_name, line_number)
if (not matched):
mo = re.match("\*((0x)?([0-9a-f]+))$", linespec)
if (mo != None):
if (mo is not None):
matched = True
#print "Matched <address-expression>"
# print "Matched <address-expression>"
address = long(mo.group(1), base=0)
breakpoint = target.BreakpointCreateByAddress(address)
if (not matched):
#print "Trying <function-name>"
# print "Trying <function-name>"
breakpoint = target.BreakpointCreateByName(linespec)
num_locations = breakpoint.GetNumLocations()
if (num_locations == 0):
result.AppendMessage("The line specification provided doesn't resolve to any addresses.")
result.AppendMessage(
"The line specification provided doesn't resolve to any addresses.")
addr_list = []
@ -91,6 +101,7 @@ def parse_linespec (linespec, frame, result):
return addr_list
def usage_string():
return """ Sets the program counter to a specific address.
@ -106,7 +117,8 @@ Command Options Usage:
<location-id> serves to disambiguate when multiple locations could be meant."""
def jump (debugger, command, result, internal_dict):
def jump(debugger, command, result, internal_dict):
if (command == ""):
result.AppendMessage(usage_string())
@ -151,17 +163,28 @@ def jump (debugger, command, result, internal_dict):
if (desired_index >= 0) and (desired_index < len(addresses)):
desired_address = addresses[desired_index]
else:
result.AppendMessage("Desired index " + args[1] + " is not one of the options.")
result.AppendMessage(
"Desired index " +
args[1] +
" is not one of the options.")
return
else:
index = 0
result.AppendMessage("The specified location resolves to multiple targets.");
result.AppendMessage(
"The specified location resolves to multiple targets.")
for address in addresses:
stream.Clear()
address.GetDescription(stream)
result.AppendMessage(" Location ID " + str(index) + ": " + stream.GetData())
result.AppendMessage(
" Location ID " +
str(index) +
": " +
stream.GetData())
index = index + 1
result.AppendMessage("Please type 'jump " + command + " <location-id>' to choose one.")
result.AppendMessage(
"Please type 'jump " +
command +
" <location-id>' to choose one.")
return
frame.SetPC(desired_address.GetLoadAddress(target))

View File

@ -6,18 +6,29 @@ import shlex
import string
import sys
def create_dump_module_line_tables_options ():
def create_dump_module_line_tables_options():
usage = "usage: dump_module_line_tables [options] MODULE1 [MODULE2 ...]"
description='''Dumps all line tables from all compile units for any modules specified as arguments. Specifying the --verbose flag will output address ranges for each line entry.'''
parser = optparse.OptionParser(description=description, prog='start_gdb_log',usage=usage)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='Display verbose output.', default=False)
description = '''Dumps all line tables from all compile units for any modules specified as arguments. Specifying the --verbose flag will output address ranges for each line entry.'''
parser = optparse.OptionParser(
description=description,
prog='start_gdb_log',
usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='Display verbose output.',
default=False)
return parser
def dump_module_line_tables(debugger, command, result, dict):
'''Dumps all line tables from all compile units for any modules specified as arguments.'''
command_args = shlex.split(command)
parser = create_dump_module_line_tables_options ()
parser = create_dump_module_line_tables_options()
try:
(options, args) = parser.parse_args(command_args)
except:
@ -27,33 +38,41 @@ def dump_module_line_tables(debugger, command, result, dict):
lldb.target = target
for module_name in command_args:
result.PutCString('Searching for module "%s"' % (module_name,))
module_fspec = lldb.SBFileSpec (module_name, False)
module = target.FindModule (module_fspec);
module_fspec = lldb.SBFileSpec(module_name, False)
module = target.FindModule(module_fspec)
if module:
for cu_idx in range (module.GetNumCompileUnits()):
for cu_idx in range(module.GetNumCompileUnits()):
cu = module.GetCompileUnitAtIndex(cu_idx)
result.PutCString("\n%s:" % (cu.file))
for line_idx in range(cu.GetNumLineEntries()):
line_entry = cu.GetLineEntryAtIndex(line_idx)
start_file_addr = line_entry.addr.file_addr
end_file_addr = line_entry.end_addr.file_addr
# If the two addresses are equal, this line table entry is a termination entry
# If the two addresses are equal, this line table entry
# is a termination entry
if options.verbose:
if start_file_addr != end_file_addr:
result.PutCString('[%#x - %#x): %s' % (start_file_addr, end_file_addr, line_entry))
result.PutCString(
'[%#x - %#x): %s' %
(start_file_addr, end_file_addr, line_entry))
else:
if start_file_addr == end_file_addr:
result.PutCString('%#x: END' % (start_file_addr))
result.PutCString('%#x: END' %
(start_file_addr))
else:
result.PutCString('%#x: %s' % (start_file_addr, line_entry))
result.PutCString(
'%#x: %s' %
(start_file_addr, line_entry))
if start_file_addr == end_file_addr:
result.Printf("\n")
else:
result.PutCString ("no module for '%s'" % module)
result.PutCString("no module for '%s'" % module)
else:
result.PutCString ("error: invalid target")
result.PutCString("error: invalid target")
parser = create_dump_module_line_tables_options ()
parser = create_dump_module_line_tables_options()
dump_module_line_tables.__doc__ = parser.format_help()
lldb.debugger.HandleCommand('command script add -f %s.dump_module_line_tables dump_module_line_tables' % __name__)
lldb.debugger.HandleCommand(
'command script add -f %s.dump_module_line_tables dump_module_line_tables' %
__name__)
print 'Installed "dump_module_line_tables" command'

View File

@ -6,7 +6,9 @@ import sys
from Tkinter import *
import ttk
class ValueTreeItemDelegate(object):
def __init__(self, value):
self.value = value
@ -24,36 +26,44 @@ class ValueTreeItemDelegate(object):
if summary is None:
summary = ''
has_children = self.value.MightHaveChildren()
return { '#0' : name,
'typename' : typename,
'value' : value,
'summary' : summary,
'children' : has_children,
'tree-item-delegate' : self }
return {'#0': name,
'typename': typename,
'value': value,
'summary': summary,
'children': has_children,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
for i in range(self.value.num_children):
item_delegate = ValueTreeItemDelegate(self.value.GetChildAtIndex(i))
item_delegate = ValueTreeItemDelegate(
self.value.GetChildAtIndex(i))
item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts
class FrameTreeItemDelegate(object):
def __init__(self, frame):
self.frame = frame
def get_item_dictionary(self):
id = self.frame.GetFrameID()
name = 'frame #%u' % (id);
name = 'frame #%u' % (id)
value = '0x%16.16x' % (self.frame.GetPC())
stream = lldb.SBStream()
self.frame.GetDescription(stream)
summary = stream.GetData().split("`")[1]
return { '#0' : name,
return {
'#0': name,
'value': value,
'summary': summary,
'children' : self.frame.GetVariables(True, True, True, True).GetSize() > 0,
'tree-item-delegate' : self }
'children': self.frame.GetVariables(
True,
True,
True,
True).GetSize() > 0,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
@ -64,7 +74,9 @@ class FrameTreeItemDelegate(object):
item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts
class ThreadTreeItemDelegate(object):
def __init__(self, thread):
self.thread = thread
@ -73,11 +85,11 @@ class ThreadTreeItemDelegate(object):
name = 'thread #%u' % (self.thread.GetIndexID())
value = '0x%x' % (self.thread.GetThreadID())
summary = '%u frames' % (num_frames)
return { '#0' : name,
return {'#0': name,
'value': value,
'summary': summary,
'children' : num_frames > 0,
'tree-item-delegate' : self }
'children': num_frames > 0,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
@ -86,7 +98,9 @@ class ThreadTreeItemDelegate(object):
item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts
class ProcessTreeItemDelegate(object):
def __init__(self, process):
self.process = process
@ -95,11 +109,11 @@ class ProcessTreeItemDelegate(object):
num_threads = self.process.GetNumThreads()
value = str(self.process.GetProcessID())
summary = self.process.target.executable.fullpath
return { '#0' : 'process',
return {'#0': 'process',
'value': value,
'summary': summary,
'children' : num_threads > 0,
'tree-item-delegate' : self }
'children': num_threads > 0,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
@ -108,18 +122,20 @@ class ProcessTreeItemDelegate(object):
item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts
class TargetTreeItemDelegate(object):
def __init__(self, target):
self.target = target
def get_item_dictionary(self):
value = str(self.target.triple)
summary = self.target.executable.fullpath
return { '#0' : 'target',
return {'#0': 'target',
'value': value,
'summary': summary,
'children' : True,
'tree-item-delegate' : self }
'children': True,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
@ -127,7 +143,9 @@ class TargetTreeItemDelegate(object):
item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts
class TargetImagesTreeItemDelegate(object):
def __init__(self, target):
self.target = target
@ -135,21 +153,24 @@ class TargetImagesTreeItemDelegate(object):
value = str(self.target.triple)
summary = self.target.executable.fullpath
num_modules = self.target.GetNumModules()
return { '#0' : 'images',
return {'#0': 'images',
'value': '',
'summary': '%u images' % num_modules,
'children' : num_modules > 0,
'tree-item-delegate' : self }
'children': num_modules > 0,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
for i in range(self.target.GetNumModules()):
module = self.target.GetModuleAtIndex(i)
image_item_delegate = ModuleTreeItemDelegate(self.target, module, i)
image_item_delegate = ModuleTreeItemDelegate(
self.target, module, i)
item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts
class ModuleTreeItemDelegate(object):
def __init__(self, target, module, index):
self.target = target
self.module = module
@ -159,25 +180,30 @@ class ModuleTreeItemDelegate(object):
name = 'module %u' % (self.index)
value = self.module.file.basename
summary = self.module.file.dirname
return { '#0' : name,
return {'#0': name,
'value': value,
'summary': summary,
'children' : True,
'tree-item-delegate' : self }
'children': True,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
sections_item_delegate = ModuleSectionsTreeItemDelegate(self.target, self.module)
sections_item_delegate = ModuleSectionsTreeItemDelegate(
self.target, self.module)
item_dicts.append(sections_item_delegate.get_item_dictionary())
symbols_item_delegate = ModuleSymbolsTreeItemDelegate(self.target, self.module)
symbols_item_delegate = ModuleSymbolsTreeItemDelegate(
self.target, self.module)
item_dicts.append(symbols_item_delegate.get_item_dictionary())
comp_units_item_delegate = ModuleCompileUnitsTreeItemDelegate(self.target, self.module)
comp_units_item_delegate = ModuleCompileUnitsTreeItemDelegate(
self.target, self.module)
item_dicts.append(comp_units_item_delegate.get_item_dictionary())
return item_dicts
class ModuleSectionsTreeItemDelegate(object):
def __init__(self, target, module):
self.target = target
self.module = module
@ -186,11 +212,11 @@ class ModuleSectionsTreeItemDelegate(object):
name = 'sections'
value = ''
summary = '%u sections' % (self.module.GetNumSections())
return { '#0' : name,
return {'#0': name,
'value': value,
'summary': summary,
'children' : True,
'tree-item-delegate' : self }
'children': True,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
@ -201,7 +227,9 @@ class ModuleSectionsTreeItemDelegate(object):
item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts
class SectionTreeItemDelegate(object):
def __init__(self, target, section):
self.target = target
self.section = section
@ -214,11 +242,11 @@ class SectionTreeItemDelegate(object):
else:
value = '0x%16.16x *' % (self.section.file_addr)
summary = ''
return { '#0' : name,
return {'#0': name,
'value': value,
'summary': summary,
'children' : self.section.GetNumSubSections() > 0,
'tree-item-delegate' : self }
'children': self.section.GetNumSubSections() > 0,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
@ -229,7 +257,9 @@ class SectionTreeItemDelegate(object):
item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts
class ModuleCompileUnitsTreeItemDelegate(object):
def __init__(self, target, module):
self.target = target
self.module = module
@ -238,11 +268,11 @@ class ModuleCompileUnitsTreeItemDelegate(object):
name = 'compile units'
value = ''
summary = '%u compile units' % (self.module.GetNumSections())
return { '#0' : name,
return {'#0': name,
'value': value,
'summary': summary,
'children' : self.module.GetNumCompileUnits() > 0,
'tree-item-delegate' : self }
'children': self.module.GetNumCompileUnits() > 0,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
@ -253,7 +283,9 @@ class ModuleCompileUnitsTreeItemDelegate(object):
item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts
class CompileUnitTreeItemDelegate(object):
def __init__(self, target, cu):
self.target = target
self.cu = cu
@ -263,11 +295,11 @@ class CompileUnitTreeItemDelegate(object):
value = ''
num_lines = self.cu.GetNumLineEntries()
summary = ''
return { '#0' : name,
return {'#0': name,
'value': value,
'summary': summary,
'children' : num_lines > 0,
'tree-item-delegate' : self }
'children': num_lines > 0,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
@ -275,7 +307,9 @@ class CompileUnitTreeItemDelegate(object):
item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts
class LineTableTreeItemDelegate(object):
def __init__(self, target, cu):
self.target = target
self.cu = cu
@ -285,22 +319,25 @@ class LineTableTreeItemDelegate(object):
value = ''
num_lines = self.cu.GetNumLineEntries()
summary = '%u line entries' % (num_lines)
return { '#0' : name,
return {'#0': name,
'value': value,
'summary': summary,
'children' : num_lines > 0,
'tree-item-delegate' : self }
'children': num_lines > 0,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
num_lines = self.cu.GetNumLineEntries()
for i in range(num_lines):
line_entry = self.cu.GetLineEntryAtIndex(i)
item_delegate = LineEntryTreeItemDelegate(self.target, line_entry, i)
item_delegate = LineEntryTreeItemDelegate(
self.target, line_entry, i)
item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts
class LineEntryTreeItemDelegate(object):
def __init__(self, target, line_entry, index):
self.target = target
self.line_entry = line_entry
@ -314,18 +351,21 @@ class LineEntryTreeItemDelegate(object):
value = '0x%16.16x' % (load_addr)
else:
value = '0x%16.16x *' % (address.file_addr)
summary = self.line_entry.GetFileSpec().fullpath + ':' + str(self.line_entry.line)
return { '#0' : name,
summary = self.line_entry.GetFileSpec().fullpath + ':' + \
str(self.line_entry.line)
return {'#0': name,
'value': value,
'summary': summary,
'children' : False,
'tree-item-delegate' : self }
'children': False,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
return item_dicts
class InstructionTreeItemDelegate(object):
def __init__(self, target, instr):
self.target = target
self.instr = instr
@ -337,15 +377,18 @@ class InstructionTreeItemDelegate(object):
name = '0x%16.16x' % (load_addr)
else:
name = '0x%16.16x *' % (address.file_addr)
value = self.instr.GetMnemonic(self.target) + ' ' + self.instr.GetOperands(self.target)
value = self.instr.GetMnemonic(
self.target) + ' ' + self.instr.GetOperands(self.target)
summary = self.instr.GetComment(self.target)
return { '#0' : name,
return {'#0': name,
'value': value,
'summary': summary,
'children' : False,
'tree-item-delegate' : self }
'children': False,
'tree-item-delegate': self}
class ModuleSymbolsTreeItemDelegate(object):
def __init__(self, target, module):
self.target = target
self.module = module
@ -354,22 +397,25 @@ class ModuleSymbolsTreeItemDelegate(object):
name = 'symbols'
value = ''
summary = '%u symbols' % (self.module.GetNumSymbols())
return { '#0' : name,
return {'#0': name,
'value': value,
'summary': summary,
'children' : True,
'tree-item-delegate' : self }
'children': True,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
num_symbols = self.module.GetNumSymbols()
for i in range(num_symbols):
symbol = self.module.GetSymbolAtIndex(i)
image_item_delegate = SymbolTreeItemDelegate(self.target, symbol, i)
image_item_delegate = SymbolTreeItemDelegate(
self.target, symbol, i)
item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts
class SymbolTreeItemDelegate(object):
def __init__(self, target, symbol, index):
self.target = target
self.symbol = symbol
@ -384,18 +430,17 @@ class SymbolTreeItemDelegate(object):
else:
value = '0x%16.16x *' % (address.file_addr)
summary = self.symbol.name
return { '#0' : name,
return {'#0': name,
'value': value,
'summary': summary,
'children' : False,
'tree-item-delegate' : self }
'children': False,
'tree-item-delegate': self}
def get_child_item_dictionaries(self):
item_dicts = list()
return item_dicts
class DelegateTree(ttk.Frame):
def __init__(self, column_dicts, delegate, title, name):
@ -415,20 +460,26 @@ class DelegateTree(ttk.Frame):
frame.pack(side=TOP, fill=BOTH, expand=Y)
column_ids = list()
for i in range(1,len(self.columns_dicts)):
for i in range(1, len(self.columns_dicts)):
column_ids.append(self.columns_dicts[i]['id'])
# create the tree and scrollbars
self.tree = ttk.Treeview(columns=column_ids)
scroll_bar_v = ttk.Scrollbar(orient=VERTICAL, command= self.tree.yview)
scroll_bar_h = ttk.Scrollbar(orient=HORIZONTAL, command= self.tree.xview)
scroll_bar_v = ttk.Scrollbar(orient=VERTICAL, command=self.tree.yview)
scroll_bar_h = ttk.Scrollbar(
orient=HORIZONTAL, command=self.tree.xview)
self.tree['yscroll'] = scroll_bar_v.set
self.tree['xscroll'] = scroll_bar_h.set
# setup column headings and columns properties
for columns_dict in self.columns_dicts:
self.tree.heading(columns_dict['id'], text=columns_dict['text'], anchor=columns_dict['anchor'])
self.tree.column(columns_dict['id'], stretch=columns_dict['stretch'])
self.tree.heading(
columns_dict['id'],
text=columns_dict['text'],
anchor=columns_dict['anchor'])
self.tree.column(
columns_dict['id'],
stretch=columns_dict['stretch'])
# add tree and scrollbars to frame
self.tree.grid(in_=frame, row=0, column=0, sticky=NSEW)
@ -453,7 +504,7 @@ class DelegateTree(ttk.Frame):
first = False
else:
values.append(item_dict[columns_dict['id']])
item_id = self.tree.insert (parent_id, # root item has an empty name
item_id = self.tree.insert(parent_id, # root item has an empty name
END,
text=name,
values=values)
@ -468,7 +519,7 @@ class DelegateTree(ttk.Frame):
def _update_tree(self, event):
# user expanded a node - build the related directory
item_id = self.tree.focus() # the id of the expanded node
children = self.tree.get_children (item_id)
children = self.tree.get_children(item_id)
if len(children):
first_child = children[0]
# if the node only has a 'dummy' child, remove it and
@ -477,12 +528,15 @@ class DelegateTree(ttk.Frame):
if self.tree.item(first_child, option='text') == 'dummy':
self.tree.delete(first_child)
item_dict = self.item_id_to_item_dict[item_id]
item_dicts = item_dict['tree-item-delegate'].get_child_item_dictionaries()
item_dicts = item_dict[
'tree-item-delegate'].get_child_item_dictionaries()
self.insert_items(item_id, item_dicts)
@lldb.command("tk-variables")
def tk_variable_display(debugger, command, result, dict):
sys.argv = ['tk-variables'] # needed for tree creation in TK library as it uses sys.argv...
# needed for tree creation in TK library as it uses sys.argv...
sys.argv = ['tk-variables']
target = debugger.GetSelectedTarget()
if not target:
print >>result, "invalid target"
@ -501,16 +555,22 @@ def tk_variable_display(debugger, command, result, dict):
return
# Parse command line args
command_args = shlex.split(command)
column_dicts = [{ 'id' : '#0' , 'text' : 'Name' , 'anchor' : W , 'stretch' : 0 },
{ 'id' : 'typename', 'text' : 'Type' , 'anchor' : W , 'stretch' : 0 },
{ 'id' : 'value' , 'text' : 'Value' , 'anchor' : W , 'stretch' : 0 },
{ 'id' : 'summary' , 'text' : 'Summary', 'anchor' : W , 'stretch' : 1 }]
tree = DelegateTree(column_dicts, FrameTreeItemDelegate(frame), 'Variables', 'lldb-tk-variables')
column_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0},
{'id': 'typename', 'text': 'Type', 'anchor': W, 'stretch': 0},
{'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0},
{'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}]
tree = DelegateTree(
column_dicts,
FrameTreeItemDelegate(frame),
'Variables',
'lldb-tk-variables')
tree.mainloop()
@lldb.command("tk-process")
def tk_process_display(debugger, command, result, dict):
sys.argv = ['tk-process'] # needed for tree creation in TK library as it uses sys.argv...
# needed for tree creation in TK library as it uses sys.argv...
sys.argv = ['tk-process']
target = debugger.GetSelectedTarget()
if not target:
print >>result, "invalid target"
@ -520,25 +580,34 @@ def tk_process_display(debugger, command, result, dict):
print >>result, "invalid process"
return
# Parse command line args
columnd_dicts = [{ 'id' : '#0' , 'text' : 'Name' , 'anchor' : W , 'stretch' : 0 },
{ 'id' : 'value' , 'text' : 'Value' , 'anchor' : W , 'stretch' : 0 },
{ 'id' : 'summary', 'text' : 'Summary', 'anchor' : W , 'stretch' : 1 }];
columnd_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0},
{'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0},
{'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}]
command_args = shlex.split(command)
tree = DelegateTree(columnd_dicts, ProcessTreeItemDelegate(process), 'Process', 'lldb-tk-process')
tree = DelegateTree(
columnd_dicts,
ProcessTreeItemDelegate(process),
'Process',
'lldb-tk-process')
tree.mainloop()
@lldb.command("tk-target")
def tk_target_display(debugger, command, result, dict):
sys.argv = ['tk-target'] # needed for tree creation in TK library as it uses sys.argv...
# needed for tree creation in TK library as it uses sys.argv...
sys.argv = ['tk-target']
target = debugger.GetSelectedTarget()
if not target:
print >>result, "invalid target"
return
# Parse command line args
columnd_dicts = [{ 'id' : '#0' , 'text' : 'Name' , 'anchor' : W , 'stretch' : 0 },
{ 'id' : 'value' , 'text' : 'Value' , 'anchor' : W , 'stretch' : 0 },
{ 'id' : 'summary', 'text' : 'Summary', 'anchor' : W , 'stretch' : 1 }];
columnd_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0},
{'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0},
{'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}]
command_args = shlex.split(command)
tree = DelegateTree(columnd_dicts, TargetTreeItemDelegate(target), 'Target', 'lldb-tk-target')
tree = DelegateTree(
columnd_dicts,
TargetTreeItemDelegate(target),
'Target',
'lldb-tk-target')
tree.mainloop()

File diff suppressed because it is too large Load Diff

View File

@ -26,9 +26,14 @@ except ImportError:
# On Darwin, try the currently selected Xcode directory
xcode_dir = commands.getoutput("xcode-select --print-path")
if xcode_dir:
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
os.path.realpath(
xcode_dir +
'/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(
xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
'/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
success = False
for lldb_python_dir in lldb_python_dirs:
if os.path.exists(lldb_python_dir):
@ -53,51 +58,128 @@ import string
import struct
import time
def append_data_callback(option, opt_str, value, parser):
if opt_str == "--uint8":
int8 = int(value, 0)
parser.values.data += struct.pack('1B',int8)
parser.values.data += struct.pack('1B', int8)
if opt_str == "--uint16":
int16 = int(value, 0)
parser.values.data += struct.pack('1H',int16)
parser.values.data += struct.pack('1H', int16)
if opt_str == "--uint32":
int32 = int(value, 0)
parser.values.data += struct.pack('1I',int32)
parser.values.data += struct.pack('1I', int32)
if opt_str == "--uint64":
int64 = int(value, 0)
parser.values.data += struct.pack('1Q',int64)
parser.values.data += struct.pack('1Q', int64)
if opt_str == "--int8":
int8 = int(value, 0)
parser.values.data += struct.pack('1b',int8)
parser.values.data += struct.pack('1b', int8)
if opt_str == "--int16":
int16 = int(value, 0)
parser.values.data += struct.pack('1h',int16)
parser.values.data += struct.pack('1h', int16)
if opt_str == "--int32":
int32 = int(value, 0)
parser.values.data += struct.pack('1i',int32)
parser.values.data += struct.pack('1i', int32)
if opt_str == "--int64":
int64 = int(value, 0)
parser.values.data += struct.pack('1q',int64)
parser.values.data += struct.pack('1q', int64)
def create_memfind_options():
usage = "usage: %prog [options] STARTADDR [ENDADDR]"
description='''This command can find data in a specified address range.
description = '''This command can find data in a specified address range.
Options are used to specify the data that is to be looked for and the options
can be specified multiple times to look for longer streams of data.
'''
parser = optparse.OptionParser(description=description, prog='memfind',usage=usage)
parser.add_option('-s', '--size', type='int', metavar='BYTESIZE', dest='size', help='Specify the byte size to search.', default=0)
parser.add_option('--int8', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 8 bit signed integer value to search for in memory.', default='')
parser.add_option('--int16', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 16 bit signed integer value to search for in memory.', default='')
parser.add_option('--int32', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 32 bit signed integer value to search for in memory.', default='')
parser.add_option('--int64', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 64 bit signed integer value to search for in memory.', default='')
parser.add_option('--uint8', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 8 bit unsigned integer value to search for in memory.', default='')
parser.add_option('--uint16', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 16 bit unsigned integer value to search for in memory.', default='')
parser.add_option('--uint32', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 32 bit unsigned integer value to search for in memory.', default='')
parser.add_option('--uint64', action="callback", callback=append_data_callback, type='string', metavar='INT', dest='data', help='Specify a 64 bit unsigned integer value to search for in memory.', default='')
parser = optparse.OptionParser(
description=description,
prog='memfind',
usage=usage)
parser.add_option(
'-s',
'--size',
type='int',
metavar='BYTESIZE',
dest='size',
help='Specify the byte size to search.',
default=0)
parser.add_option(
'--int8',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 8 bit signed integer value to search for in memory.',
default='')
parser.add_option(
'--int16',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 16 bit signed integer value to search for in memory.',
default='')
parser.add_option(
'--int32',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 32 bit signed integer value to search for in memory.',
default='')
parser.add_option(
'--int64',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 64 bit signed integer value to search for in memory.',
default='')
parser.add_option(
'--uint8',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 8 bit unsigned integer value to search for in memory.',
default='')
parser.add_option(
'--uint16',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 16 bit unsigned integer value to search for in memory.',
default='')
parser.add_option(
'--uint32',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 32 bit unsigned integer value to search for in memory.',
default='')
parser.add_option(
'--uint64',
action="callback",
callback=append_data_callback,
type='string',
metavar='INT',
dest='data',
help='Specify a 64 bit unsigned integer value to search for in memory.',
default='')
return parser
def memfind_command (debugger, command, result, dict):
def memfind_command(debugger, command, result, dict):
# Use the Shell Lexer to properly parse up command options just like a
# shell would
command_args = shlex.split(command)
@ -111,33 +193,43 @@ def memfind_command (debugger, command, result, dict):
# result.SetStatus (lldb.eReturnStatusFailed)
# print >>result, "error: option parsing failed" # returning a string is the same as returning an error whose description is the string
# return
memfind (debugger.GetSelectedTarget(), options, args, result)
memfind(debugger.GetSelectedTarget(), options, args, result)
def print_error(str, show_usage, result):
print >>result, str
if show_usage:
print >>result, create_memfind_options().format_help()
def memfind (target, options, args, result):
def memfind(target, options, args, result):
num_args = len(args)
start_addr = 0
if num_args == 1:
if options.size > 0:
print_error ("error: --size must be specified if there is no ENDADDR argument", True, result)
print_error(
"error: --size must be specified if there is no ENDADDR argument",
True,
result)
return
start_addr = int(args[0], 0)
elif num_args == 2:
if options.size != 0:
print_error ("error: --size can't be specified with an ENDADDR argument", True, result)
print_error(
"error: --size can't be specified with an ENDADDR argument",
True,
result)
return
start_addr = int(args[0], 0)
end_addr = int(args[1], 0)
if start_addr >= end_addr:
print_error ("error: inavlid memory range [%#x - %#x)" % (start_addr, end_addr), True, result)
print_error(
"error: inavlid memory range [%#x - %#x)" %
(start_addr, end_addr), True, result)
return
options.size = end_addr - start_addr
else:
print_error ("error: memfind takes 1 or 2 arguments", True, result)
print_error("error: memfind takes 1 or 2 arguments", True, result)
return
if not options.data:
@ -153,10 +245,11 @@ def memfind (target, options, args, result):
return
error = lldb.SBError()
bytes = process.ReadMemory (start_addr, options.size, error)
bytes = process.ReadMemory(start_addr, options.size, error)
if error.Success():
num_matches = 0
print >>result, "Searching memory range [%#x - %#x) for" % (start_addr, end_addr),
print >>result, "Searching memory range [%#x - %#x) for" % (
start_addr, end_addr),
for byte in options.data:
print >>result, '%2.2x' % ord(byte),
print >>result
@ -164,7 +257,8 @@ def memfind (target, options, args, result):
match_index = string.find(bytes, options.data)
while match_index != -1:
num_matches = num_matches + 1
print >>result, '%#x: %#x + %u' % (start_addr + match_index, start_addr, match_index)
print >>result, '%#x: %#x + %u' % (start_addr +
match_index, start_addr, match_index)
match_index = string.find(bytes, options.data, match_index + 1)
if num_matches == 0:
@ -177,5 +271,6 @@ if __name__ == '__main__':
print 'error: this script is designed to be used within the embedded script interpreter in LLDB'
elif getattr(lldb, 'debugger', None):
memfind_command.__doc__ = create_memfind_options().format_help()
lldb.debugger.HandleCommand('command script add -f memory.memfind_command memfind')
lldb.debugger.HandleCommand(
'command script add -f memory.memfind_command memfind')
print '"memfind" command installed, use the "--help" option for detailed help'

View File

@ -3,6 +3,7 @@
import lldb
import struct
class OperatingSystemPlugIn(object):
"""Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class"""
@ -14,7 +15,7 @@ class OperatingSystemPlugIn(object):
self.process = None
self.registers = None
self.threads = None
if type(process) is lldb.SBProcess and process.IsValid():
if isinstance(process, lldb.SBProcess) and process.IsValid():
self.process = process
self.threads = None # Will be an dictionary containing info for each thread
@ -26,7 +27,12 @@ class OperatingSystemPlugIn(object):
def create_thread(self, tid, context):
if tid == 0x444444444:
thread_info = { 'tid' : tid, 'name' : 'four' , 'queue' : 'queue4', 'state' : 'stopped', 'stop_reason' : 'none' }
thread_info = {
'tid': tid,
'name': 'four',
'queue': 'queue4',
'state': 'stopped',
'stop_reason': 'none'}
self.threads.append(thread_info)
return thread_info
return None
@ -48,16 +54,28 @@ class OperatingSystemPlugIn(object):
# Specifying this key/value pair for a thread will avoid a call to get_register_data()
# and can be used when your registers are in a thread context structure that is contiguous
# in memory. Don't specify this if your register layout in memory doesn't match the layout
# described by the dictionary returned from a call to the get_register_info() method.
self.threads = [
{ 'tid' : 0x111111111, 'name' : 'one' , 'queue' : 'queue1', 'state' : 'stopped', 'stop_reason' : 'breakpoint'},
{ 'tid' : 0x222222222, 'name' : 'two' , 'queue' : 'queue2', 'state' : 'stopped', 'stop_reason' : 'none' },
{ 'tid' : 0x333333333, 'name' : 'three', 'queue' : 'queue3', 'state' : 'stopped', 'stop_reason' : 'trace' , 'register_data_addr' : 0x100000000 }
]
# described by the dictionary returned from a call to the
# get_register_info() method.
self.threads = [{'tid': 0x111111111,
'name': 'one',
'queue': 'queue1',
'state': 'stopped',
'stop_reason': 'breakpoint'},
{'tid': 0x222222222,
'name': 'two',
'queue': 'queue2',
'state': 'stopped',
'stop_reason': 'none'},
{'tid': 0x333333333,
'name': 'three',
'queue': 'queue3',
'state': 'stopped',
'stop_reason': 'trace',
'register_data_addr': 0x100000000}]
return self.threads
def get_register_info(self):
if self.registers == None:
if self.registers is None:
self.registers = dict()
triple = self.process.target.triple
if triple:
@ -65,40 +83,149 @@ class OperatingSystemPlugIn(object):
if arch == 'x86_64':
self.registers['sets'] = ['GPR', 'FPU', 'EXC']
self.registers['registers'] = [
{ 'name':'rax' , 'bitsize' : 64, 'offset' : 0, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 0, 'dwarf' : 0},
{ 'name':'rbx' , 'bitsize' : 64, 'offset' : 8, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 3, 'dwarf' : 3},
{ 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
{ 'name':'rdx' , 'bitsize' : 64, 'offset' : 24, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 1, 'dwarf' : 1, 'generic':'arg3', 'alt-name':'arg3', },
{ 'name':'rdi' , 'bitsize' : 64, 'offset' : 32, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 5, 'dwarf' : 5, 'generic':'arg1', 'alt-name':'arg1', },
{ 'name':'rsi' , 'bitsize' : 64, 'offset' : 40, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 4, 'dwarf' : 4, 'generic':'arg2', 'alt-name':'arg2', },
{ 'name':'rbp' , 'bitsize' : 64, 'offset' : 48, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 6, 'dwarf' : 6, 'generic':'fp' , 'alt-name':'fp', },
{ 'name':'rsp' , 'bitsize' : 64, 'offset' : 56, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 7, 'dwarf' : 7, 'generic':'sp' , 'alt-name':'sp', },
{ 'name':'r8' , 'bitsize' : 64, 'offset' : 64, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 8, 'dwarf' : 8, 'generic':'arg5', 'alt-name':'arg5', },
{ 'name':'r9' , 'bitsize' : 64, 'offset' : 72, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 9, 'dwarf' : 9, 'generic':'arg6', 'alt-name':'arg6', },
{ 'name':'r10' , 'bitsize' : 64, 'offset' : 80, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 10, 'dwarf' : 10},
{ 'name':'r11' , 'bitsize' : 64, 'offset' : 88, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 11, 'dwarf' : 11},
{ 'name':'r12' , 'bitsize' : 64, 'offset' : 96, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 12, 'dwarf' : 12},
{ 'name':'r13' , 'bitsize' : 64, 'offset' : 104, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 13, 'dwarf' : 13},
{ 'name':'r14' , 'bitsize' : 64, 'offset' : 112, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 14, 'dwarf' : 14},
{ 'name':'r15' , 'bitsize' : 64, 'offset' : 120, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 15, 'dwarf' : 15},
{ 'name':'rip' , 'bitsize' : 64, 'offset' : 128, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 16, 'dwarf' : 16, 'generic':'pc', 'alt-name':'pc' },
{ 'name':'rflags' , 'bitsize' : 64, 'offset' : 136, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'generic':'flags', 'alt-name':'flags' },
{ 'name':'cs' , 'bitsize' : 64, 'offset' : 144, 'encoding':'uint' , 'format':'hex' , 'set': 0 },
{ 'name':'fs' , 'bitsize' : 64, 'offset' : 152, 'encoding':'uint' , 'format':'hex' , 'set': 0 },
{ 'name':'gs' , 'bitsize' : 64, 'offset' : 160, 'encoding':'uint' , 'format':'hex' , 'set': 0 },
{'name': 'rax', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0},
{'name': 'rbx', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3},
{'name': 'rcx', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg4', 'alt-name': 'arg4', },
{'name': 'rdx', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg3', 'alt-name': 'arg3', },
{'name': 'rdi', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg1', 'alt-name': 'arg1', },
{'name': 'rsi', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg2', 'alt-name': 'arg2', },
{'name': 'rbp', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'fp', 'alt-name': 'fp', },
{'name': 'rsp', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'sp', 'alt-name': 'sp', },
{'name': 'r8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8, 'generic': 'arg5', 'alt-name': 'arg5', },
{'name': 'r9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9, 'generic': 'arg6', 'alt-name': 'arg6', },
{'name': 'r10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10},
{'name': 'r11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11},
{'name': 'r12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12},
{'name': 'r13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13},
{'name': 'r14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14},
{'name': 'r15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15},
{'name': 'rip', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16, 'generic': 'pc', 'alt-name': 'pc'},
{'name': 'rflags', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'generic': 'flags', 'alt-name': 'flags'},
{'name': 'cs', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0},
{'name': 'fs', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0},
{'name': 'gs', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0},
]
return self.registers
def get_register_data(self, tid):
if tid == 0x111111111:
return struct.pack('21Q',1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21);
return struct.pack(
'21Q',
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21)
elif tid == 0x222222222:
return struct.pack('21Q',11,12,13,14,15,16,17,18,19,110,111,112,113,114,115,116,117,118,119,120,121);
return struct.pack(
'21Q',
11,
12,
13,
14,
15,
16,
17,
18,
19,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121)
elif tid == 0x333333333:
return struct.pack('21Q',21,22,23,24,25,26,27,28,29,210,211,212,213,214,215,216,217,218,219,220,221);
return struct.pack(
'21Q',
21,
22,
23,
24,
25,
26,
27,
28,
29,
210,
211,
212,
213,
214,
215,
216,
217,
218,
219,
220,
221)
elif tid == 0x444444444:
return struct.pack('21Q',31,32,33,34,35,36,37,38,39,310,311,312,313,314,315,316,317,318,319,320,321);
return struct.pack(
'21Q',
31,
32,
33,
34,
35,
36,
37,
38,
39,
310,
311,
312,
313,
314,
315,
316,
317,
318,
319,
320,
321)
else:
return struct.pack('21Q',41,42,43,44,45,46,47,48,49,410,411,412,413,414,415,416,417,418,419,420,421);
return struct.pack(
'21Q',
41,
42,
43,
44,
45,
46,
47,
48,
49,
410,
411,
412,
413,
414,
415,
416,
417,
418,
419,
420,
421)
return None

View File

@ -32,9 +32,14 @@ except ImportError:
# On Darwin, try the currently selected Xcode directory
xcode_dir = commands.getoutput("xcode-select --print-path")
if xcode_dir:
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
os.path.realpath(
xcode_dir +
'/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(
xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
'/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
success = False
for lldb_python_dir in lldb_python_dirs:
if os.path.exists(lldb_python_dir):
@ -54,6 +59,7 @@ except ImportError:
class Timer:
def __enter__(self):
self.start = time.clock()
return self
@ -62,30 +68,45 @@ class Timer:
self.end = time.clock()
self.interval = self.end - self.start
class Action(object):
"""Class that encapsulates actions to take when a thread stops for a reason."""
def __init__(self, callback = None, callback_owner = None):
def __init__(self, callback=None, callback_owner=None):
self.callback = callback
self.callback_owner = callback_owner
def ThreadStopped (self, thread):
def ThreadStopped(self, thread):
assert False, "performance.Action.ThreadStopped(self, thread) must be overridden in a subclass"
class PlanCompleteAction (Action):
def __init__(self, callback = None, callback_owner = None):
def __init__(self, callback=None, callback_owner=None):
Action.__init__(self, callback, callback_owner)
def ThreadStopped (self, thread):
def ThreadStopped(self, thread):
if thread.GetStopReason() == lldb.eStopReasonPlanComplete:
if self.callback:
if self.callback_owner:
self.callback (self.callback_owner, thread)
self.callback(self.callback_owner, thread)
else:
self.callback (thread)
self.callback(thread)
return True
return False
class BreakpointAction (Action):
def __init__(self, callback = None, callback_owner = None, name = None, module = None, file = None, line = None, breakpoint = None):
def __init__(
self,
callback=None,
callback_owner=None,
name=None,
module=None,
file=None,
line=None,
breakpoint=None):
Action.__init__(self, callback, callback_owner)
self.modules = lldb.SBFileSpecList()
self.files = lldb.SBFileSpecList()
@ -97,7 +118,8 @@ class BreakpointAction (Action):
if module:
if isinstance(module, types.ListType):
for module_path in module:
self.modules.Append(lldb.SBFileSpec(module_path, False))
self.modules.Append(
lldb.SBFileSpec(module_path, False))
elif isinstance(module, types.StringTypes):
self.modules.Append(lldb.SBFileSpec(module, False))
if name:
@ -109,22 +131,30 @@ class BreakpointAction (Action):
self.files.Append(lldb.SBFileSpec(f, False))
elif isinstance(file, types.StringTypes):
self.files.Append(lldb.SBFileSpec(file, False))
self.breakpoints.append (self.target.BreakpointCreateByName(name, self.modules, self.files))
self.breakpoints.append(
self.target.BreakpointCreateByName(
name, self.modules, self.files))
elif file and line:
self.breakpoints.append (self.target.BreakpointCreateByLocation(file, line))
def ThreadStopped (self, thread):
self.breakpoints.append(
self.target.BreakpointCreateByLocation(
file, line))
def ThreadStopped(self, thread):
if thread.GetStopReason() == lldb.eStopReasonBreakpoint:
for bp in self.breakpoints:
if bp.GetID() == thread.GetStopReasonDataAtIndex(0):
if self.callback:
if self.callback_owner:
self.callback (self.callback_owner, thread)
self.callback(self.callback_owner, thread)
else:
self.callback (thread)
self.callback(thread)
return True
return False
class TestCase:
"""Class that aids in running performance tests."""
def __init__(self):
self.verbose = False
self.debugger = lldb.SBDebugger.Create()
@ -141,27 +171,28 @@ class TestCase:
def Setup(self, args):
self.launch_info = lldb.SBLaunchInfo(args)
def Run (self, args):
def Run(self, args):
assert False, "performance.TestCase.Run(self, args) must be subclassed"
def Launch(self):
if self.target:
error = lldb.SBError()
self.process = self.target.Launch (self.launch_info, error)
self.process = self.target.Launch(self.launch_info, error)
if not error.Success():
print "error: %s" % error.GetCString()
if self.process:
self.process.GetBroadcaster().AddListener(self.listener, lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitInterrupt)
self.process.GetBroadcaster().AddListener(self.listener,
lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitInterrupt)
return True
return False
def WaitForNextProcessEvent (self):
def WaitForNextProcessEvent(self):
event = None
if self.process:
while event is None:
process_event = lldb.SBEvent()
if self.listener.WaitForEvent (lldb.UINT32_MAX, process_event):
state = lldb.SBProcess.GetStateFromEvent (process_event)
if self.listener.WaitForEvent(lldb.UINT32_MAX, process_event):
state = lldb.SBProcess.GetStateFromEvent(process_event)
if self.verbose:
print "event = %s" % (lldb.SBDebugger.StateAsCString(state))
if lldb.SBProcess.GetRestartedFromEvent(process_event):
@ -182,7 +213,7 @@ class TestCase:
stop_reason = thread.GetStopReason()
if self.verbose:
print "tid = %#x pc = %#x " % (thread.GetThreadID(),frame.GetPC()),
print "tid = %#x pc = %#x " % (thread.GetThreadID(), frame.GetPC()),
if stop_reason == lldb.eStopReasonNone:
if self.verbose:
print "none"
@ -225,11 +256,11 @@ class TestCase:
if select_thread and not selected_thread:
self.thread = thread
selected_thread = self.process.SetSelectedThread(thread)
selected_thread = self.process.SetSelectedThread(
thread)
for action in self.user_actions:
action.ThreadStopped (thread)
action.ThreadStopped(thread)
if fatal:
# if self.verbose:
@ -237,20 +268,36 @@ class TestCase:
sys.exit(1)
return event
class Measurement:
'''A class that encapsulates a measurement'''
def __init__(self):
object.__init__(self)
def Measure(self):
assert False, "performance.Measurement.Measure() must be subclassed"
class MemoryMeasurement(Measurement):
'''A class that can measure memory statistics for a process.'''
def __init__(self, pid):
Measurement.__init__(self)
self.pid = pid
self.stats = ["rprvt","rshrd","rsize","vsize","vprvt","kprvt","kshrd","faults","cow","pageins"]
self.command = "top -l 1 -pid %u -stats %s" % (self.pid, ",".join(self.stats))
self.stats = [
"rprvt",
"rshrd",
"rsize",
"vsize",
"vprvt",
"kprvt",
"kshrd",
"faults",
"cow",
"pageins"]
self.command = "top -l 1 -pid %u -stats %s" % (
self.pid, ",".join(self.stats))
self.value = dict()
def Measure(self):
@ -263,14 +310,14 @@ class MemoryMeasurement(Measurement):
multiplier = 1024
stat = stat[:-1]
elif stat[-1] == 'M':
multiplier = 1024*1024
multiplier = 1024 * 1024
stat = stat[:-1]
elif stat[-1] == 'G':
multiplier = 1024*1024*1024
multiplier = 1024 * 1024 * 1024
elif stat[-1] == 'T':
multiplier = 1024*1024*1024*1024
multiplier = 1024 * 1024 * 1024 * 1024
stat = stat[:-1]
self.value[self.stats[idx]] = int (stat) * multiplier
self.value[self.stats[idx]] = int(stat) * multiplier
def __str__(self):
'''Dump the MemoryMeasurement current value'''
@ -283,35 +330,45 @@ class MemoryMeasurement(Measurement):
class TesterTestCase(TestCase):
def __init__(self):
TestCase.__init__(self)
self.verbose = True
self.num_steps = 5
def BreakpointHit (self, thread):
def BreakpointHit(self, thread):
bp_id = thread.GetStopReasonDataAtIndex(0)
loc_id = thread.GetStopReasonDataAtIndex(1)
print "Breakpoint %i.%i hit: %s" % (bp_id, loc_id, thread.process.target.FindBreakpointByID(bp_id))
thread.StepOver()
def PlanComplete (self, thread):
def PlanComplete(self, thread):
if self.num_steps > 0:
thread.StepOver()
self.num_steps = self.num_steps - 1
else:
thread.process.Kill()
def Run (self, args):
def Run(self, args):
self.Setup(args)
with Timer() as total_time:
self.target = self.debugger.CreateTarget(args[0])
if self.target:
with Timer() as breakpoint_timer:
bp = self.target.BreakpointCreateByName("main")
print('Breakpoint time = %.03f sec.' % breakpoint_timer.interval)
print(
'Breakpoint time = %.03f sec.' %
breakpoint_timer.interval)
self.user_actions.append (BreakpointAction(breakpoint=bp, callback=TesterTestCase.BreakpointHit, callback_owner=self))
self.user_actions.append (PlanCompleteAction(callback=TesterTestCase.PlanComplete, callback_owner=self))
self.user_actions.append(
BreakpointAction(
breakpoint=bp,
callback=TesterTestCase.BreakpointHit,
callback_owner=self))
self.user_actions.append(
PlanCompleteAction(
callback=TesterTestCase.PlanComplete,
callback_owner=self))
if self.Launch():
while not self.done:
@ -326,7 +383,7 @@ class TesterTestCase(TestCase):
if __name__ == '__main__':
lldb.SBDebugger.Initialize()
test = TesterTestCase()
test.Run (sys.argv[1:])
test.Run(sys.argv[1:])
mem = MemoryMeasurement(os.getpid())
mem.Measure()
print str(mem)

View File

@ -28,9 +28,14 @@ except ImportError:
# On Darwin, try the currently selected Xcode directory
xcode_dir = commands.getoutput("xcode-select --print-path")
if xcode_dir:
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
os.path.realpath(
xcode_dir +
'/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(
xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
'/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
success = False
for lldb_python_dir in lldb_python_dirs:
if os.path.exists(lldb_python_dir):
@ -48,15 +53,17 @@ except ImportError:
print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
sys.exit(1)
def print_threads(process, options):
if options.show_threads:
for thread in process:
print '%s %s' % (thread, thread.GetFrameAtIndex(0))
def run_commands(command_interpreter, commands):
return_obj = lldb.SBCommandReturnObject()
for command in commands:
command_interpreter.HandleCommand( command, return_obj )
command_interpreter.HandleCommand(command, return_obj)
if return_obj.Succeeded():
print return_obj.GetOutput()
else:
@ -64,9 +71,10 @@ def run_commands(command_interpreter, commands):
if options.stop_on_error:
break
def main(argv):
description='''Debugs a program using the LLDB python API and uses asynchronous broadcast events to watch for process state changes.'''
epilog='''Examples:
description = '''Debugs a program using the LLDB python API and uses asynchronous broadcast events to watch for process state changes.'''
epilog = '''Examples:
#----------------------------------------------------------------------
# Run "/bin/ls" with the arguments "-lAF /tmp/", and set a breakpoint
@ -76,24 +84,144 @@ def main(argv):
'''
optparse.OptionParser.format_epilog = lambda self, formatter: self.epilog
parser = optparse.OptionParser(description=description, prog='process_events',usage='usage: process_events [options] program [arg1 arg2]', epilog=epilog)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help="Enable verbose logging.", default=False)
parser.add_option('-b', '--breakpoint', action='append', type='string', metavar='BPEXPR', dest='breakpoints', help='Breakpoint commands to create after the target has been created, the values will be sent to the "_regexp-break" command which supports breakpoints by name, file:line, and address.')
parser.add_option('-a', '--arch', type='string', dest='arch', help='The architecture to use when creating the debug target.', default=None)
parser.add_option('--platform', type='string', metavar='platform', dest='platform', help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".', default=None)
parser.add_option('-l', '--launch-command', action='append', type='string', metavar='CMD', dest='launch_commands', help='LLDB command interpreter commands to run once after the process has launched. This option can be specified more than once.', default=[])
parser.add_option('-s', '--stop-command', action='append', type='string', metavar='CMD', dest='stop_commands', help='LLDB command interpreter commands to run each time the process stops. This option can be specified more than once.', default=[])
parser.add_option('-c', '--crash-command', action='append', type='string', metavar='CMD', dest='crash_commands', help='LLDB command interpreter commands to run in case the process crashes. This option can be specified more than once.', default=[])
parser.add_option('-x', '--exit-command', action='append', type='string', metavar='CMD', dest='exit_commands', help='LLDB command interpreter commands to run once after the process has exited. This option can be specified more than once.', default=[])
parser.add_option('-T', '--no-threads', action='store_false', dest='show_threads', help="Don't show threads when process stops.", default=True)
parser.add_option('--ignore-errors', action='store_false', dest='stop_on_error', help="Don't stop executing LLDB commands if the command returns an error. This applies to all of the LLDB command interpreter commands that get run for launch, stop, crash and exit.", default=True)
parser.add_option('-n', '--run-count', type='int', dest='run_count', metavar='N', help='How many times to run the process in case the process exits.', default=1)
parser.add_option('-t', '--event-timeout', type='int', dest='event_timeout', metavar='SEC', help='Specify the timeout in seconds to wait for process state change events.', default=lldb.UINT32_MAX)
parser.add_option('-e', '--environment', action='append', type='string', metavar='ENV', dest='env_vars', help='Environment variables to set in the inferior process when launching a process.')
parser.add_option('-d', '--working-dir', type='string', metavar='DIR', dest='working_dir', help='The the current working directory when launching a process.', default=None)
parser.add_option('-p', '--attach-pid', type='int', dest='attach_pid', metavar='PID', help='Specify a process to attach to by process ID.', default=-1)
parser.add_option('-P', '--attach-name', type='string', dest='attach_name', metavar='PROCESSNAME', help='Specify a process to attach to by name.', default=None)
parser.add_option('-w', '--attach-wait', action='store_true', dest='attach_wait', help='Wait for the next process to launch when attaching to a process by name.', default=False)
parser = optparse.OptionParser(
description=description,
prog='process_events',
usage='usage: process_events [options] program [arg1 arg2]',
epilog=epilog)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help="Enable verbose logging.",
default=False)
parser.add_option(
'-b',
'--breakpoint',
action='append',
type='string',
metavar='BPEXPR',
dest='breakpoints',
help='Breakpoint commands to create after the target has been created, the values will be sent to the "_regexp-break" command which supports breakpoints by name, file:line, and address.')
parser.add_option(
'-a',
'--arch',
type='string',
dest='arch',
help='The architecture to use when creating the debug target.',
default=None)
parser.add_option(
'--platform',
type='string',
metavar='platform',
dest='platform',
help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".',
default=None)
parser.add_option(
'-l',
'--launch-command',
action='append',
type='string',
metavar='CMD',
dest='launch_commands',
help='LLDB command interpreter commands to run once after the process has launched. This option can be specified more than once.',
default=[])
parser.add_option(
'-s',
'--stop-command',
action='append',
type='string',
metavar='CMD',
dest='stop_commands',
help='LLDB command interpreter commands to run each time the process stops. This option can be specified more than once.',
default=[])
parser.add_option(
'-c',
'--crash-command',
action='append',
type='string',
metavar='CMD',
dest='crash_commands',
help='LLDB command interpreter commands to run in case the process crashes. This option can be specified more than once.',
default=[])
parser.add_option(
'-x',
'--exit-command',
action='append',
type='string',
metavar='CMD',
dest='exit_commands',
help='LLDB command interpreter commands to run once after the process has exited. This option can be specified more than once.',
default=[])
parser.add_option(
'-T',
'--no-threads',
action='store_false',
dest='show_threads',
help="Don't show threads when process stops.",
default=True)
parser.add_option(
'--ignore-errors',
action='store_false',
dest='stop_on_error',
help="Don't stop executing LLDB commands if the command returns an error. This applies to all of the LLDB command interpreter commands that get run for launch, stop, crash and exit.",
default=True)
parser.add_option(
'-n',
'--run-count',
type='int',
dest='run_count',
metavar='N',
help='How many times to run the process in case the process exits.',
default=1)
parser.add_option(
'-t',
'--event-timeout',
type='int',
dest='event_timeout',
metavar='SEC',
help='Specify the timeout in seconds to wait for process state change events.',
default=lldb.UINT32_MAX)
parser.add_option(
'-e',
'--environment',
action='append',
type='string',
metavar='ENV',
dest='env_vars',
help='Environment variables to set in the inferior process when launching a process.')
parser.add_option(
'-d',
'--working-dir',
type='string',
metavar='DIR',
dest='working_dir',
help='The the current working directory when launching a process.',
default=None)
parser.add_option(
'-p',
'--attach-pid',
type='int',
dest='attach_pid',
metavar='PID',
help='Specify a process to attach to by process ID.',
default=-1)
parser.add_option(
'-P',
'--attach-name',
type='string',
dest='attach_name',
metavar='PROCESSNAME',
help='Specify a process to attach to by name.',
default=None)
parser.add_option(
'-w',
'--attach-wait',
action='store_true',
dest='attach_wait',
help='Wait for the next process to launch when attaching to a process by name.',
default=False)
try:
(options, args) = parser.parse_args(argv)
except:
@ -104,20 +232,21 @@ def main(argv):
exe = None
if args:
exe = args.pop(0)
launch_info = lldb.SBLaunchInfo (args)
launch_info = lldb.SBLaunchInfo(args)
if options.env_vars:
launch_info.SetEnvironmentEntries(options.env_vars, True)
if options.working_dir:
launch_info.SetWorkingDirectory(options.working_dir)
elif options.attach_pid != -1:
if options.run_count == 1:
attach_info = lldb.SBAttachInfo (options.attach_pid)
attach_info = lldb.SBAttachInfo(options.attach_pid)
else:
print "error: --run-count can't be used with the --attach-pid option"
sys.exit(1)
elif not options.attach_name is None:
if options.run_count == 1:
attach_info = lldb.SBAttachInfo (options.attach_name, options.attach_wait)
attach_info = lldb.SBAttachInfo(
options.attach_name, options.attach_wait)
else:
print "error: --run-count can't be used with the --attach-name option"
sys.exit(1)
@ -125,26 +254,26 @@ def main(argv):
print 'error: a program path for a program to debug and its arguments are required'
sys.exit(1)
# Create a new debugger instance
debugger = lldb.SBDebugger.Create()
debugger.SetAsync (True)
debugger.SetAsync(True)
command_interpreter = debugger.GetCommandInterpreter()
# Create a target from a file and arch
if exe:
print "Creating a target for '%s'" % exe
error = lldb.SBError()
target = debugger.CreateTarget (exe, options.arch, options.platform, True, error)
target = debugger.CreateTarget(
exe, options.arch, options.platform, True, error)
if target:
# Set any breakpoints that were specified in the args if we are launching. We use the
# command line command to take advantage of the shorthand breakpoint creation
# command line command to take advantage of the shorthand breakpoint
# creation
if launch_info and options.breakpoints:
for bp in options.breakpoints:
debugger.HandleCommand( "_regexp-break %s" % (bp))
debugger.HandleCommand("_regexp-break %s" % (bp))
run_commands(command_interpreter, ['breakpoint list'])
for run_idx in range(options.run_count):
@ -158,7 +287,7 @@ def main(argv):
else:
print 'Launching "%s"... (launch %u of %u)' % (exe, run_idx + 1, options.run_count)
process = target.Launch (launch_info, error)
process = target.Launch(launch_info, error)
else:
if options.attach_pid != -1:
print 'Attaching to process %i...' % (options.attach_pid)
@ -167,7 +296,7 @@ def main(argv):
print 'Waiting for next to process named "%s" to launch...' % (options.attach_name)
else:
print 'Attaching to existing process named "%s"...' % (options.attach_name)
process = target.Attach (attach_info, error)
process = target.Attach(attach_info, error)
# Make sure the launch went ok
if process and process.GetProcessID() != lldb.LLDB_INVALID_PROCESS_ID:
@ -175,7 +304,8 @@ def main(argv):
pid = process.GetProcessID()
print 'Process is %i' % (pid)
if attach_info:
# continue process if we attached as we won't get an initial event
# continue process if we attached as we won't get an
# initial event
process.Continue()
listener = debugger.GetListener()
@ -184,9 +314,9 @@ def main(argv):
done = False
while not done:
event = lldb.SBEvent()
if listener.WaitForEvent (options.event_timeout, event):
if listener.WaitForEvent(options.event_timeout, event):
if lldb.SBProcess.EventIsProcessEvent(event):
state = lldb.SBProcess.GetStateFromEvent (event)
state = lldb.SBProcess.GetStateFromEvent(event)
if state == lldb.eStateInvalid:
# Not a state event
print 'process event = %s' % (event)
@ -196,42 +326,51 @@ def main(argv):
if stop_idx == 0:
if launch_info:
print "process %u launched" % (pid)
run_commands(command_interpreter, ['breakpoint list'])
run_commands(
command_interpreter, ['breakpoint list'])
else:
print "attached to process %u" % (pid)
for m in target.modules:
print m
if options.breakpoints:
for bp in options.breakpoints:
debugger.HandleCommand( "_regexp-break %s" % (bp))
run_commands(command_interpreter, ['breakpoint list'])
run_commands (command_interpreter, options.launch_commands)
debugger.HandleCommand(
"_regexp-break %s" % (bp))
run_commands(
command_interpreter, ['breakpoint list'])
run_commands(
command_interpreter, options.launch_commands)
else:
if options.verbose:
print "process %u stopped" % (pid)
run_commands (command_interpreter, options.stop_commands)
run_commands(
command_interpreter, options.stop_commands)
stop_idx += 1
print_threads (process, options)
print_threads(process, options)
print "continuing process %u" % (pid)
process.Continue()
elif state == lldb.eStateExited:
exit_desc = process.GetExitDescription()
if exit_desc:
print "process %u exited with status %u: %s" % (pid, process.GetExitStatus (), exit_desc)
print "process %u exited with status %u: %s" % (pid, process.GetExitStatus(), exit_desc)
else:
print "process %u exited with status %u" % (pid, process.GetExitStatus ())
run_commands (command_interpreter, options.exit_commands)
print "process %u exited with status %u" % (pid, process.GetExitStatus())
run_commands(
command_interpreter, options.exit_commands)
done = True
elif state == lldb.eStateCrashed:
print "process %u crashed" % (pid)
print_threads (process, options)
run_commands (command_interpreter, options.crash_commands)
print_threads(process, options)
run_commands(
command_interpreter, options.crash_commands)
done = True
elif state == lldb.eStateDetached:
print "process %u detached" % (pid)
done = True
elif state == lldb.eStateRunning:
# process is running, don't say anything, we will always get one of these after resuming
# process is running, don't say anything,
# we will always get one of these after
# resuming
if options.verbose:
print "process %u resumed" % (pid)
elif state == lldb.eStateUnloaded:

View File

@ -2,32 +2,37 @@ import sys
import inspect
from collections import OrderedDict
class TracebackFancy:
def __init__(self,traceback):
def __init__(self, traceback):
self.t = traceback
def getFrame(self):
return FrameFancy(self.t.tb_frame)
def getLineNumber(self):
return self.t.tb_lineno if self.t != None else None
return self.t.tb_lineno if self.t is not None else None
def getNext(self):
return TracebackFancy(self.t.tb_next)
def __str__(self):
if self.t == None:
if self.t is None:
return ""
str_self = "%s @ %s" % (self.getFrame().getName(), self.getLineNumber())
str_self = "%s @ %s" % (
self.getFrame().getName(), self.getLineNumber())
return str_self + "\n" + self.getNext().__str__()
class ExceptionFancy:
def __init__(self,frame):
def __init__(self, frame):
self.etraceback = frame.f_exc_traceback
self.etype = frame.exc_type
self.evalue = frame.f_exc_value
def __init__(self,tb,ty,va):
def __init__(self, tb, ty, va):
self.etraceback = tb
self.etype = ty
self.evalue = va
@ -36,7 +41,7 @@ class ExceptionFancy:
return TracebackFancy(self.etraceback)
def __nonzero__(self):
return self.etraceback != None or self.etype != None or self.evalue != None
return self.etraceback is not None or self.etype is not None or self.evalue is not None
def getType(self):
return str(self.etype)
@ -44,27 +49,31 @@ class ExceptionFancy:
def getValue(self):
return self.evalue
class CodeFancy:
def __init__(self,code):
def __init__(self, code):
self.c = code
def getArgCount(self):
return self.c.co_argcount if self.c != None else 0
return self.c.co_argcount if self.c is not None else 0
def getFilename(self):
return self.c.co_filename if self.c != None else ""
return self.c.co_filename if self.c is not None else ""
def getVariables(self):
return self.c.co_varnames if self.c != None else []
return self.c.co_varnames if self.c is not None else []
def getName(self):
return self.c.co_name if self.c != None else ""
return self.c.co_name if self.c is not None else ""
def getFileName(self):
return self.c.co_filename if self.c != None else ""
return self.c.co_filename if self.c is not None else ""
class ArgsFancy:
def __init__(self,frame,arginfo):
def __init__(self, frame, arginfo):
self.f = frame
self.a = arginfo
@ -88,13 +97,13 @@ class ArgsFancy:
ret = ret + "kwargs are " + str(kwargs)
return ret
def getNumArgs(wantVarargs = False, wantKWArgs=False):
def getNumArgs(wantVarargs=False, wantKWArgs=False):
args, varargs, keywords, values = self.a
size = len(args)
if varargs and wantVarargs:
size = size+len(self.getVarArgs())
size = size + len(self.getVarArgs())
if keywords and wantKWArgs:
size = size+len(self.getKWArgs())
size = size + len(self.getKWArgs())
return size
def getArgs(self):
@ -116,114 +125,129 @@ class ArgsFancy:
return self.f.f_locals[kwargs]
return {}
class FrameFancy:
def __init__(self,frame):
def __init__(self, frame):
self.f = frame
def getCaller(self):
return FrameFancy(self.f.f_back)
def getLineNumber(self):
return self.f.f_lineno if self.f != None else 0
return self.f.f_lineno if self.f is not None else 0
def getCodeInformation(self):
return CodeFancy(self.f.f_code) if self.f != None else None
return CodeFancy(self.f.f_code) if self.f is not None else None
def getExceptionInfo(self):
return ExceptionFancy(self.f) if self.f != None else None
return ExceptionFancy(self.f) if self.f is not None else None
def getName(self):
return self.getCodeInformation().getName() if self.f != None else ""
return self.getCodeInformation().getName() if self.f is not None else ""
def getFileName(self):
return self.getCodeInformation().getFileName() if self.f != None else ""
return self.getCodeInformation().getFileName() if self.f is not None else ""
def getLocals(self):
return self.f.f_locals if self.f != None else {}
return self.f.f_locals if self.f is not None else {}
def getArgumentInfo(self):
return ArgsFancy(self.f,inspect.getargvalues(self.f)) if self.f != None else None
return ArgsFancy(
self.f, inspect.getargvalues(
self.f)) if self.f is not None else None
class TracerClass:
def callEvent(self,frame):
def callEvent(self, frame):
pass
def lineEvent(self,frame):
def lineEvent(self, frame):
pass
def returnEvent(self,frame,retval):
def returnEvent(self, frame, retval):
pass
def exceptionEvent(self,frame,exception,value,traceback):
def exceptionEvent(self, frame, exception, value, traceback):
pass
def cCallEvent(self,frame,cfunct):
def cCallEvent(self, frame, cfunct):
pass
def cReturnEvent(self,frame,cfunct):
def cReturnEvent(self, frame, cfunct):
pass
def cExceptionEvent(self,frame,cfunct):
def cExceptionEvent(self, frame, cfunct):
pass
tracer_impl = TracerClass()
def the_tracer_entrypoint(frame,event,args):
if tracer_impl == None:
def the_tracer_entrypoint(frame, event, args):
if tracer_impl is None:
return None
if event == "call":
call_retval = tracer_impl.callEvent(FrameFancy(frame))
if call_retval == False:
if not call_retval:
return None
return the_tracer_entrypoint
elif event == "line":
line_retval = tracer_impl.lineEvent(FrameFancy(frame))
if line_retval == False:
if not line_retval:
return None
return the_tracer_entrypoint
elif event == "return":
tracer_impl.returnEvent(FrameFancy(frame),args)
tracer_impl.returnEvent(FrameFancy(frame), args)
elif event == "exception":
exty,exva,extb = args
exception_retval = tracer_impl.exceptionEvent(FrameFancy(frame),ExceptionFancy(extb,exty,exva))
if exception_retval == False:
exty, exva, extb = args
exception_retval = tracer_impl.exceptionEvent(
FrameFancy(frame), ExceptionFancy(extb, exty, exva))
if not exception_retval:
return None
return the_tracer_entrypoint
elif event == "c_call":
tracer_impl.cCallEvent(FrameFancy(frame),args)
tracer_impl.cCallEvent(FrameFancy(frame), args)
elif event == "c_return":
tracer_impl.cReturnEvent(FrameFancy(frame),args)
tracer_impl.cReturnEvent(FrameFancy(frame), args)
elif event == "c_exception":
tracer_impl.cExceptionEvent(FrameFancy(frame),args)
tracer_impl.cExceptionEvent(FrameFancy(frame), args)
return None
def enable(t=None):
global tracer_impl
if t:
tracer_impl = t
sys.settrace(the_tracer_entrypoint)
def disable():
sys.settrace(None)
class LoggingTracer:
def callEvent(self,frame):
def callEvent(self, frame):
print "call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
def lineEvent(self,frame):
def lineEvent(self, frame):
print "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals()) + " in " + frame.getFileName()
def returnEvent(self,frame,retval):
def returnEvent(self, frame, retval):
print "return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals())
def exceptionEvent(self,frame,exception):
def exceptionEvent(self, frame, exception):
print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
print "tb: " + str(exception.getTraceback())
# the same functionality as LoggingTracer, but with a little more lldb-specific smarts
# the same functionality as LoggingTracer, but with a little more
# lldb-specific smarts
class LLDBAwareTracer:
def callEvent(self,frame):
def callEvent(self, frame):
if frame.getName() == "<module>":
return
if frame.getName() == "run_one_line":
@ -232,7 +256,8 @@ class LLDBAwareTracer:
if "Python.framework" in frame.getFileName():
print "call into Python at " + frame.getName()
return
if frame.getName() == "__init__" and frame.getCaller().getName() == "run_one_line" and frame.getCaller().getLineNumber() == 101:
if frame.getName() == "__init__" and frame.getCaller().getName(
) == "run_one_line" and frame.getCaller().getLineNumber() == 101:
return False
strout = "call " + frame.getName()
if (frame.getCaller().getFileName() == ""):
@ -241,72 +266,79 @@ class LLDBAwareTracer:
for arg in args:
if arg == "dict" or arg == "internal_dict":
continue
strout = strout + ("%s = %s " % (arg,args[arg]))
strout = strout + ("%s = %s " % (arg, args[arg]))
else:
strout += " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
strout += " from " + frame.getCaller().getName() + " @ " + \
str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
print strout
def lineEvent(self,frame):
def lineEvent(self, frame):
if frame.getName() == "<module>":
return
if frame.getName() == "run_one_line":
print "running run_one_line(%s) @ %s" % (frame.getArgumentInfo().getArgs()["input_string"],frame.getLineNumber())
print "running run_one_line(%s) @ %s" % (frame.getArgumentInfo().getArgs()["input_string"], frame.getLineNumber())
return
if "Python.framework" in frame.getFileName():
print "running into Python at " + frame.getName() + " @ " + str(frame.getLineNumber())
return
strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are "
strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + \
" locals are "
if (frame.getCaller().getFileName() == ""):
locals = frame.getLocals()
for local in locals:
if local == "dict" or local == "internal_dict":
continue
strout = strout + ("%s = %s " % (local,locals[local]))
strout = strout + ("%s = %s " % (local, locals[local]))
else:
strout = strout + str(frame.getLocals())
strout = strout + " in " + frame.getFileName()
print strout
def returnEvent(self,frame,retval):
def returnEvent(self, frame, retval):
if frame.getName() == "<module>":
return
if frame.getName() == "run_one_line":
print "return from run_one_line(%s) return value is %s" % (frame.getArgumentInfo().getArgs()["input_string"],retval)
print "return from run_one_line(%s) return value is %s" % (frame.getArgumentInfo().getArgs()["input_string"], retval)
return
if "Python.framework" in frame.getFileName():
print "return from Python at " + frame.getName() + " return value is " + str(retval)
return
strout = "return from " + frame.getName() + " return value is " + str(retval) + " locals are "
strout = "return from " + frame.getName() + " return value is " + \
str(retval) + " locals are "
if (frame.getCaller().getFileName() == ""):
locals = frame.getLocals()
for local in locals:
if local == "dict" or local == "internal_dict":
continue
strout = strout + ("%s = %s " % (local,locals[local]))
strout = strout + ("%s = %s " % (local, locals[local]))
else:
strout = strout + str(frame.getLocals())
strout = strout + " in " + frame.getFileName()
print strout
def exceptionEvent(self,frame,exception):
def exceptionEvent(self, frame, exception):
if frame.getName() == "<module>":
return
print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
print "tb: " + str(exception.getTraceback())
def f(x,y=None):
def f(x, y=None):
if x > 0:
return 2 + f(x-2)
return 2 + f(x - 2)
return 35
def g(x):
return 1.134 / x
def print_keyword_args(**kwargs):
# kwargs is a dict of the keyword args passed to the function
for key, value in kwargs.iteritems():
print "%s = %s" % (key, value)
def total(initial=5, *numbers, **keywords):
count = initial
for number in numbers:
@ -318,7 +350,7 @@ def total(initial=5, *numbers, **keywords):
if __name__ == "__main__":
enable(LoggingTracer())
f(5)
f(5,1)
f(5, 1)
print_keyword_args(first_name="John", last_name="Doe")
total(10, 1, 2, 3, vegetables=50, fruits=100)
try:

View File

@ -2,6 +2,7 @@
import lldb
class value(object):
'''A class that wraps an lldb.SBValue object and returns an object that
can be used as an object with attribytes:\n
@ -24,6 +25,7 @@ class value(object):
argv.num_children - return the number of children this value has
argv.children - return a list of sbvalue objects that represents all of the children of this value
'''
def __init__(self, sbvalue):
self.sbvalue = sbvalue
@ -37,8 +39,10 @@ class value(object):
return self.sbvalue.__str__()
def __getitem__(self, key):
if type(key) is int:
return value(self.sbvalue.GetChildAtIndex(key, lldb.eNoDynamicValues, True))
if isinstance(key, int):
return value(
self.sbvalue.GetChildAtIndex(
key, lldb.eNoDynamicValues, True))
raise TypeError
def __getattr__(self, name):
@ -55,15 +59,15 @@ class value(object):
if name == 'is_pointer':
return self.sbvalue.TypeIsPointerType()
if name == 'format':
return self.sbvalue.GetFormat ()
return self.sbvalue.GetFormat()
if name == 'value':
return self.sbvalue.GetValue ()
return self.sbvalue.GetValue()
if name == 'summary':
return self.sbvalue.GetSummary ()
return self.sbvalue.GetSummary()
if name == 'description':
return self.sbvalue.GetObjectDescription ()
return self.sbvalue.GetObjectDescription()
if name == 'location':
return self.sbvalue.GetLocation ()
return self.sbvalue.GetLocation()
if name == 'target':
return self.sbvalue.GetTarget()
if name == 'process':
@ -78,15 +82,22 @@ class value(object):
# Returns an array of sbvalue objects, one for each child of
# the value for the lldb.SBValue
children = []
for i in range (self.sbvalue.GetNumChildren()):
children.append(value(self.sbvalue.GetChildAtIndex(i, lldb.eNoDynamicValues, True)))
for i in range(self.sbvalue.GetNumChildren()):
children.append(
value(
self.sbvalue.GetChildAtIndex(
i,
lldb.eNoDynamicValues,
True)))
return children
raise AttributeError
class variable(object):
'''A class that treats a lldb.SBValue and allows it to be used just as
a variable would be in code. So if you have a Point structure variable
in your code, you would be able to do: "pt.x + pt.y"'''
def __init__(self, sbvalue):
self.sbvalue = sbvalue
@ -101,12 +112,15 @@ class variable(object):
def __getitem__(self, key):
# Allow array access if this value has children...
if type(key) is int:
return variable(self.sbvalue.GetValueForExpressionPath("[%i]" % key))
if isinstance(key, int):
return variable(
self.sbvalue.GetValueForExpressionPath(
"[%i]" %
key))
raise TypeError
def __getattr__(self, name):
child_sbvalue = self.sbvalue.GetChildMemberWithName (name)
child_sbvalue = self.sbvalue.GetChildMemberWithName(name)
if child_sbvalue:
return variable(child_sbvalue)
raise AttributeError
@ -155,72 +169,72 @@ class variable(object):
def __iadd__(self, other):
result = self.__add__(other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __isub__(self, other):
result = self.__sub__(other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __imul__(self, other):
result = self.__mul__(other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __idiv__(self, other):
result = self.__div__(other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __itruediv__(self, other):
result = self.__truediv__(other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __ifloordiv__(self, other):
result = self.__floordiv__(self, other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __imod__(self, other):
result = self.__and__(self, other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __ipow__(self, other):
result = self.__pow__(self, other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __ipow__(self, other, modulo):
result = self.__pow__(self, other, modulo)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __ilshift__(self, other):
result = self.__lshift__(self, other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __irshift__(self, other):
result = self.__rshift__(self, other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __iand__(self, other):
result = self.__and__(self, other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __ixor__(self, other):
result = self.__xor__(self, other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __ior__(self, other):
result = self.__ior__(self, other)
self.sbvalue.SetValueFromCString (str(result))
self.sbvalue.SetValueFromCString(str(result))
return result
def __neg__(self):
@ -236,7 +250,7 @@ class variable(object):
return ~int(self)
def __complex__(self):
return complex (int(self))
return complex(int(self))
def __int__(self):
return self.sbvalue.GetValueAsSigned()
@ -245,11 +259,10 @@ class variable(object):
return self.sbvalue.GetValueAsSigned()
def __float__(self):
return float (self.sbvalue.GetValueAsSigned())
return float(self.sbvalue.GetValueAsSigned())
def __oct__(self):
return '0%o' % self.sbvalue.GetValueAsSigned()
def __hex__(self):
return '0x%x' % self.sbvalue.GetValueAsSigned()

View File

@ -95,20 +95,22 @@
import lldb
class SimpleStep:
def __init__ (self, thread_plan, dict):
def __init__(self, thread_plan, dict):
self.thread_plan = thread_plan
self.start_address = thread_plan.GetThread().GetFrameAtIndex(0).GetPC()
def explains_stop (self, event):
def explains_stop(self, event):
# We are stepping, so if we stop for any other reason, it isn't
# because of us.
if self.thread_plan.GetThread().GetStopReason()== lldb.eStopReasonTrace:
if self.thread_plan.GetThread().GetStopReason() == lldb.eStopReasonTrace:
return True
else:
return False
def should_stop (self, event):
def should_stop(self, event):
cur_pc = self.thread_plan.GetThread().GetFrameAtIndex(0).GetPC()
if cur_pc < self.start_address or cur_pc >= self.start_address + 20:
@ -117,54 +119,60 @@ class SimpleStep:
else:
return False
def should_step (self):
def should_step(self):
return True
class StepWithPlan:
def __init__ (self, thread_plan, dict):
def __init__(self, thread_plan, dict):
self.thread_plan = thread_plan
self.start_address = thread_plan.GetThread().GetFrameAtIndex(0).GetPCAddress()
self.step_thread_plan =thread_plan.QueueThreadPlanForStepOverRange(self.start_address, 20);
self.step_thread_plan = thread_plan.QueueThreadPlanForStepOverRange(
self.start_address, 20)
def explains_stop (self, event):
def explains_stop(self, event):
# Since all I'm doing is running a plan, I will only ever get askedthis
# if myplan doesn't explain the stop, and in that caseI don'teither.
return False
def should_stop (self, event):
def should_stop(self, event):
if self.step_thread_plan.IsPlanComplete():
self.thread_plan.SetPlanComplete(True)
return True
else:
return False
def should_step (self):
def should_step(self):
return False
# Here's another example which does "step over" through the current function,
# and when it stops at each line, it checks some condition (in this example the
# value of a variable) and stops if that condition is true.
class StepCheckingCondition:
def __init__ (self, thread_plan, dict):
def __init__(self, thread_plan, dict):
self.thread_plan = thread_plan
self.start_frame = thread_plan.GetThread().GetFrameAtIndex(0)
self.queue_next_plan()
def queue_next_plan (self):
def queue_next_plan(self):
cur_frame = self.thread_plan.GetThread().GetFrameAtIndex(0)
cur_line_entry = cur_frame.GetLineEntry()
start_address = cur_line_entry.GetStartAddress()
end_address = cur_line_entry.GetEndAddress()
line_range = end_address.GetFileAddress() - start_address.GetFileAddress()
self.step_thread_plan = self.thread_plan.QueueThreadPlanForStepOverRange(start_address, line_range)
self.step_thread_plan = self.thread_plan.QueueThreadPlanForStepOverRange(
start_address, line_range)
def explains_stop (self, event):
def explains_stop(self, event):
# We are stepping, so if we stop for any other reason, it isn't
# because of us.
return False
def should_stop (self, event):
def should_stop(self, event):
if not self.step_thread_plan.IsPlanComplete():
return False
@ -182,7 +190,7 @@ class StepCheckingCondition:
return True
error = lldb.SBError()
a_value = a_var.GetValueAsSigned (error)
a_value = a_var.GetValueAsSigned(error)
if not error.Success():
print "A value was not good."
return True
@ -194,7 +202,7 @@ class StepCheckingCondition:
self.queue_next_plan()
return False
def should_step (self):
def should_step(self):
return True
# Here's an example that steps out of the current frame, gathers some information
@ -202,29 +210,32 @@ class StepCheckingCondition:
# plans are not a safe place to call lldb command-line commands, so the information
# is gathered through SB API calls.
class FinishPrintAndContinue:
def __init__ (self, thread_plan, dict):
def __init__(self, thread_plan, dict):
self.thread_plan = thread_plan
self.step_out_thread_plan = thread_plan.QueueThreadPlanForStepOut(0, True)
self.step_out_thread_plan = thread_plan.QueueThreadPlanForStepOut(
0, True)
self.thread = self.thread_plan.GetThread()
def is_stale (self):
def is_stale(self):
if self.step_out_thread_plan.IsPlanStale():
self.do_print()
return True
else:
return False
def explains_stop (self, event):
def explains_stop(self, event):
return False
def should_stop (self, event):
def should_stop(self, event):
if self.step_out_thread_plan.IsPlanComplete():
self.do_print()
self.thread_plan.SetPlanComplete(True)
return False
def do_print (self):
def do_print(self):
frame_0 = self.thread.frames[0]
rax_value = frame_0.FindRegister("rax")
if rax_value.GetError().Success():

View File

@ -3,13 +3,15 @@
import lldb
import shlex
@lldb.command("shadow")
def check_shadow_command(debugger, command, exe_ctx, result, dict):
'''Check the currently selected stack frame for shadowed variables'''
process = exe_ctx.GetProcess()
state = process.GetState()
if state != lldb.eStateStopped:
print >>result, "process must be stopped, state is %s" % lldb.SBDebugger.StateAsCString(state)
print >>result, "process must be stopped, state is %s" % lldb.SBDebugger.StateAsCString(
state)
return
frame = exe_ctx.GetFrame()
if not frame:
@ -54,4 +56,3 @@ def check_shadow_command(debugger, command, exe_ctx, result, dict):
print >>result, str(shadow_var.GetDeclaration())
if num_shadowed_variables == 0:
print >>result, 'no variables are shadowed'

View File

@ -3,6 +3,7 @@
import lldb
import shlex
def dump_module_sources(module, result):
if module:
print >> result, "Module: %s" % (module.file)
@ -10,8 +11,9 @@ def dump_module_sources(module, result):
if compile_unit.file:
print >> result, " %s" % (compile_unit.file)
def info_sources(debugger, command, result, dict):
description='''This command will dump all compile units in any modules that are listed as arguments, or for all modules if no arguments are supplied.'''
description = '''This command will dump all compile units in any modules that are listed as arguments, or for all modules if no arguments are supplied.'''
module_names = shlex.split(command)
target = debugger.GetSelectedTarget()
if module_names:
@ -22,7 +24,8 @@ def info_sources(debugger, command, result, dict):
dump_module_sources(module, result)
def __lldb_init_module (debugger, dict):
def __lldb_init_module(debugger, dict):
# Add any commands contained in this module to LLDB
debugger.HandleCommand('command script add -f sources.info_sources info_sources')
debugger.HandleCommand(
'command script add -f sources.info_sources info_sources')
print 'The "info_sources" command has been installed, type "help info_sources" or "info_sources --help" for detailed help.'

View File

@ -5,12 +5,20 @@ import commands
import optparse
import shlex
def stack_frames(debugger, command, result, dict):
command_args = shlex.split(command)
usage = "usage: %prog [options] <PATH> [PATH ...]"
description='''This command will enumerate all stack frames, print the stack size for each, and print an aggregation of which functions have the largest stack frame sizes at the end.'''
parser = optparse.OptionParser(description=description, prog='ls',usage=usage)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
description = '''This command will enumerate all stack frames, print the stack size for each, and print an aggregation of which functions have the largest stack frame sizes at the end.'''
parser = optparse.OptionParser(
description=description, prog='ls', usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
try:
(options, args) = parser.parse_args(command_args)
except:
@ -28,7 +36,8 @@ def stack_frames(debugger, command, result, dict):
frame_size = 0
if frame.idx == 1:
if frame.fp == last_frame.fp:
# No frame one the first frame (might be right at the entry point)
# No frame one the first frame (might be right at the
# entry point)
first_frame_size = 0
frame_size = frame.fp - frame.sp
else:
@ -55,5 +64,6 @@ def stack_frames(debugger, command, result, dict):
print frame_info
lldb.debugger.HandleCommand("command script add -f stacks.stack_frames stack_frames")
lldb.debugger.HandleCommand(
"command script add -f stacks.stack_frames stack_frames")
print "A new command called 'stack_frames' was added, type 'stack_frames --help' for more information."

View File

@ -37,16 +37,23 @@ import sys
import time
import uuid
class Address:
"""Class that represents an address that will be symbolicated"""
def __init__(self, target, load_addr):
self.target = target
self.load_addr = load_addr # The load address that this object represents
self.so_addr = None # the resolved lldb.SBAddress (if any), named so_addr for section/offset address
# the resolved lldb.SBAddress (if any), named so_addr for
# section/offset address
self.so_addr = None
self.sym_ctx = None # The cached symbol context for this address
self.description = None # Any original textual description of this address to be used as a backup in case symbolication fails
# Any original textual description of this address to be used as a
# backup in case symbolication fails
self.description = None
self.symbolication = None # The cached symbolicated string that describes this address
self.inlined = False
def __str__(self):
s = "%#16.16x" % (self.load_addr)
if self.symbolication:
@ -58,18 +65,19 @@ class Address:
return s
def resolve_addr(self):
if self.so_addr == None:
self.so_addr = self.target.ResolveLoadAddress (self.load_addr)
if self.so_addr is None:
self.so_addr = self.target.ResolveLoadAddress(self.load_addr)
return self.so_addr
def is_inlined(self):
return self.inlined
def get_symbol_context(self):
if self.sym_ctx == None:
if self.sym_ctx is None:
sb_addr = self.resolve_addr()
if sb_addr:
self.sym_ctx = self.target.ResolveSymbolContextForAddress (sb_addr, lldb.eSymbolContextEverything)
self.sym_ctx = self.target.ResolveSymbolContextForAddress(
sb_addr, lldb.eSymbolContextEverything)
else:
self.sym_ctx = lldb.SBSymbolContext()
return self.sym_ctx
@ -83,8 +91,8 @@ class Address:
return sym_ctx.GetSymbol().GetInstructions(self.target)
return None
def symbolicate(self, verbose = False):
if self.symbolication == None:
def symbolicate(self, verbose=False):
if self.symbolication is None:
self.symbolication = ''
self.inlined = False
sym_ctx = self.get_symbol_context()
@ -101,27 +109,32 @@ class Address:
block = sym_ctx.GetBlock()
line_entry = sym_ctx.GetLineEntry()
symbol = sym_ctx.GetSymbol()
inlined_block = block.GetContainingInlinedBlock();
inlined_block = block.GetContainingInlinedBlock()
if function:
self.symbolication += function.GetName()
if inlined_block:
self.inlined = True
self.symbolication += ' [inlined] ' + inlined_block.GetInlinedName();
block_range_idx = inlined_block.GetRangeIndexForBlockAddress (self.so_addr)
self.symbolication += ' [inlined] ' + \
inlined_block.GetInlinedName()
block_range_idx = inlined_block.GetRangeIndexForBlockAddress(
self.so_addr)
if block_range_idx < lldb.UINT32_MAX:
block_range_start_addr = inlined_block.GetRangeStartAddress (block_range_idx)
function_start_load_addr = block_range_start_addr.GetLoadAddress (self.target)
block_range_start_addr = inlined_block.GetRangeStartAddress(
block_range_idx)
function_start_load_addr = block_range_start_addr.GetLoadAddress(
self.target)
if function_start_load_addr == -1:
function_start_load_addr = function.GetStartAddress().GetLoadAddress (self.target)
function_start_load_addr = function.GetStartAddress().GetLoadAddress(self.target)
elif symbol:
self.symbolication += symbol.GetName()
function_start_load_addr = symbol.GetStartAddress().GetLoadAddress (self.target)
function_start_load_addr = symbol.GetStartAddress().GetLoadAddress(self.target)
else:
self.symbolication = ''
return False
# Dump the offset from the current function or symbol if it is non zero
# Dump the offset from the current function or symbol if it
# is non zero
function_offset = self.load_addr - function_start_load_addr
if function_offset > 0:
self.symbolication += " + %u" % (function_offset)
@ -135,20 +148,22 @@ class Address:
self.symbolication += ' at %s' % line_entry.GetFileSpec()
else:
self.symbolication += ' at %s' % line_entry.GetFileSpec().GetFilename()
self.symbolication += ':%u' % line_entry.GetLine ()
self.symbolication += ':%u' % line_entry.GetLine()
column = line_entry.GetColumn()
if column > 0:
self.symbolication += ':%u' % column
return True
return False
class Section:
"""Class that represents an load address range"""
sect_info_regex = re.compile('(?P<name>[^=]+)=(?P<range>.*)')
addr_regex = re.compile('^\s*(?P<start>0x[0-9A-Fa-f]+)\s*$')
range_regex = re.compile('^\s*(?P<start>0x[0-9A-Fa-f]+)\s*(?P<op>[-+])\s*(?P<end>0x[0-9A-Fa-f]+)\s*$')
range_regex = re.compile(
'^\s*(?P<start>0x[0-9A-Fa-f]+)\s*(?P<op>[-+])\s*(?P<end>0x[0-9A-Fa-f]+)\s*$')
def __init__(self, start_addr = None, end_addr = None, name = None):
def __init__(self, start_addr=None, end_addr=None, name=None):
self.start_addr = start_addr
self.end_addr = end_addr
self.name = name
@ -157,16 +172,20 @@ class Section:
def InitWithSBTargetAndSBSection(cls, target, section):
sect_load_addr = section.GetLoadAddress(target)
if sect_load_addr != lldb.LLDB_INVALID_ADDRESS:
obj = cls(sect_load_addr, sect_load_addr + section.size, section.name)
obj = cls(
sect_load_addr,
sect_load_addr +
section.size,
section.name)
return obj
else:
return None
def contains(self, addr):
return self.start_addr <= addr and addr < self.end_addr;
return self.start_addr <= addr and addr < self.end_addr
def set_from_string(self, s):
match = self.sect_info_regex.match (s)
match = self.sect_info_regex.match(s)
if match:
self.name = match.group('name')
range_str = match.group('range')
@ -195,19 +214,21 @@ class Section:
def __str__(self):
if self.name:
if self.end_addr != None:
if self.start_addr != None:
return "%s=[0x%16.16x - 0x%16.16x)" % (self.name, self.start_addr, self.end_addr)
if self.end_addr is not None:
if self.start_addr is not None:
return "%s=[0x%16.16x - 0x%16.16x)" % (
self.name, self.start_addr, self.end_addr)
else:
if self.start_addr != None:
if self.start_addr is not None:
return "%s=0x%16.16x" % (self.name, self.start_addr)
return self.name
return "<invalid>"
class Image:
"""A class that represents an executable image and any associated data"""
def __init__(self, path, uuid = None):
def __init__(self, path, uuid=None):
self.path = path
self.resolved_path = None
self.resolved = False
@ -229,9 +250,10 @@ class Image:
obj.resolved = True
obj.arch = module.triple
for section in module.sections:
symb_section = Section.InitWithSBTargetAndSBSection(target, section)
symb_section = Section.InitWithSBTargetAndSBSection(
target, section)
if symb_section:
obj.section_infos.append (symb_section)
obj.section_infos.append(symb_section)
obj.arch = module.triple
obj.module = module
obj.symfile = None
@ -268,15 +290,15 @@ class Image:
s += "%s " % (resolved_path)
for section_info in self.section_infos:
s += ", %s" % (section_info)
if self.slide != None:
if self.slide is not None:
s += ', slide = 0x%16.16x' % self.slide
return s
def add_section(self, section):
#print "added '%s' to '%s'" % (section, self.path)
self.section_infos.append (section)
# print "added '%s' to '%s'" % (section, self.path)
self.section_infos.append(section)
def get_section_containing_load_addr (self, load_addr):
def get_section_containing_load_addr(self, load_addr):
for section_info in self.section_infos:
if section_info.contains(load_addr):
return section_info
@ -301,7 +323,7 @@ class Image:
return None
def has_section_load_info(self):
return self.section_infos or self.slide != None
return self.section_infos or self.slide is not None
def load_module(self, target):
if self.unavailable:
@ -315,9 +337,11 @@ class Image:
num_sections_loaded = 0
for section_info in self.section_infos:
if section_info.name:
section = self.module.FindSection (section_info.name)
section = self.module.FindSection(
section_info.name)
if section:
error = target.SetSectionLoadAddress (section, section_info.start_addr)
error = target.SetSectionLoadAddress(
section, section_info.start_addr)
if error.Success():
num_sections_loaded += 1
else:
@ -325,11 +349,13 @@ class Image:
else:
return 'error: unable to find the section named "%s"' % section_info.name
else:
return 'error: unable to find "%s" section in "%s"' % (range.name, self.get_resolved_path())
return 'error: unable to find "%s" section in "%s"' % (
range.name, self.get_resolved_path())
if num_sections_loaded == 0:
return 'error: no sections were successfully loaded'
else:
err = target.SetModuleLoadAddress(self.module, self.slide)
err = target.SetModuleLoadAddress(
self.module, self.slide)
if err.Fail():
return err.GetCString()
return None
@ -343,18 +369,21 @@ class Image:
def add_module(self, target):
'''Add the Image described in this object to "target" and load the sections if "load" is True.'''
if target:
# Try and find using UUID only first so that paths need not match up
# Try and find using UUID only first so that paths need not match
# up
uuid_str = self.get_normalized_uuid_string()
if uuid_str:
self.module = target.AddModule (None, None, uuid_str)
self.module = target.AddModule(None, None, uuid_str)
if not self.module:
self.locate_module_and_debug_symbols ()
self.locate_module_and_debug_symbols()
if self.unavailable:
return None
resolved_path = self.get_resolved_path()
self.module = target.AddModule (resolved_path, self.arch, uuid_str, self.symfile)
self.module = target.AddModule(
resolved_path, self.arch, uuid_str, self.symfile)
if not self.module:
return 'error: unable to get module for (%s) "%s"' % (self.arch, self.get_resolved_path())
return 'error: unable to get module for (%s) "%s"' % (
self.arch, self.get_resolved_path())
if self.has_section_load_info():
return self.load_module(target)
else:
@ -362,7 +391,7 @@ class Image:
else:
return 'error: invalid target'
def locate_module_and_debug_symbols (self):
def locate_module_and_debug_symbols(self):
# By default, just use the paths that were supplied in:
# self.path
# self.resolved_path
@ -387,12 +416,13 @@ class Image:
if self.unavailable:
return None
if self.locate_module_and_debug_symbols ():
resolved_path = self.get_resolved_path();
path_spec = lldb.SBFileSpec (resolved_path)
if self.locate_module_and_debug_symbols():
resolved_path = self.get_resolved_path()
path_spec = lldb.SBFileSpec(resolved_path)
#result.PutCString ('plist[%s] = %s' % (uuid, self.plist))
error = lldb.SBError()
target = lldb.debugger.CreateTarget (resolved_path, self.arch, None, False, error);
target = lldb.debugger.CreateTarget(
resolved_path, self.arch, None, False, error)
if target:
self.module = target.FindModule(path_spec)
if self.has_section_load_info():
@ -406,6 +436,7 @@ class Image:
print 'error: unable to locate main executable (%s) "%s"' % (self.arch, self.path)
return None
class Symbolicator:
def __init__(self):
@ -418,7 +449,7 @@ class Symbolicator:
def InitWithSBTarget(cls, target):
obj = cls()
obj.target = target
obj.images = list();
obj.images = list()
triple = target.triple
if triple:
arch = triple.split('-')[0]
@ -457,7 +488,7 @@ class Symbolicator:
def find_image_containing_load_addr(self, load_addr):
for image in self.images:
if image.get_section_containing_load_addr (load_addr):
if image.get_section_containing_load_addr(load_addr):
return image
return None
@ -467,7 +498,7 @@ class Symbolicator:
if self.images:
for image in self.images:
self.target = image.create_target ()
self.target = image.create_target()
if self.target:
if self.target.GetAddressByteSize() == 4:
triple = self.target.triple
@ -478,8 +509,7 @@ class Symbolicator:
return self.target
return None
def symbolicate(self, load_addr, verbose = False):
def symbolicate(self, load_addr, verbose=False):
if not self.target:
self.create_target()
if self.target:
@ -493,30 +523,33 @@ class Symbolicator:
# that a load address belongs to and lazily load its module in the
# target, but we shouldn't do any of this if we have a live process
if not live_process:
image = self.find_image_containing_load_addr (load_addr)
image = self.find_image_containing_load_addr(load_addr)
if image:
image.add_module (self.target)
image.add_module(self.target)
symbolicated_address = Address(self.target, load_addr)
if symbolicated_address.symbolicate (verbose):
if symbolicated_address.symbolicate(verbose):
if symbolicated_address.so_addr:
symbolicated_addresses = list()
symbolicated_addresses.append(symbolicated_address)
# See if we were able to reconstruct anything?
while 1:
while True:
inlined_parent_so_addr = lldb.SBAddress()
inlined_parent_sym_ctx = symbolicated_address.sym_ctx.GetParentOfInlinedScope (symbolicated_address.so_addr, inlined_parent_so_addr)
inlined_parent_sym_ctx = symbolicated_address.sym_ctx.GetParentOfInlinedScope(
symbolicated_address.so_addr, inlined_parent_so_addr)
if not inlined_parent_sym_ctx:
break
if not inlined_parent_so_addr:
break
symbolicated_address = Address(self.target, inlined_parent_so_addr.GetLoadAddress(self.target))
symbolicated_address = Address(
self.target, inlined_parent_so_addr.GetLoadAddress(
self.target))
symbolicated_address.sym_ctx = inlined_parent_sym_ctx
symbolicated_address.so_addr = inlined_parent_so_addr
symbolicated_address.symbolicate (verbose)
symbolicated_address.symbolicate(verbose)
# push the new frame onto the new frame stack
symbolicated_addresses.append (symbolicated_address)
symbolicated_addresses.append(symbolicated_address)
if symbolicated_addresses:
return symbolicated_addresses
@ -525,19 +558,25 @@ class Symbolicator:
return None
def disassemble_instructions (target, instructions, pc, insts_before_pc, insts_after_pc, non_zeroeth_frame):
def disassemble_instructions(
target,
instructions,
pc,
insts_before_pc,
insts_after_pc,
non_zeroeth_frame):
lines = list()
pc_index = -1
comment_column = 50
for inst_idx, inst in enumerate(instructions):
inst_pc = inst.GetAddress().GetLoadAddress(target);
inst_pc = inst.GetAddress().GetLoadAddress(target)
if pc == inst_pc:
pc_index = inst_idx
mnemonic = inst.GetMnemonic (target)
operands = inst.GetOperands (target)
comment = inst.GetComment (target)
mnemonic = inst.GetMnemonic(target)
operands = inst.GetOperands(target)
comment = inst.GetComment(target)
#data = inst.GetData (target)
lines.append ("%#16.16x: %8s %s" % (inst_pc, mnemonic, operands))
lines.append("%#16.16x: %8s %s" % (inst_pc, mnemonic, operands))
if comment:
line_len = len(lines[-1])
if line_len < comment_column:
@ -545,7 +584,8 @@ def disassemble_instructions (target, instructions, pc, insts_before_pc, insts_a
lines[-1] += "; %s" % comment
if pc_index >= 0:
# If we are disassembling the non-zeroeth frame, we need to backup the PC by 1
# If we are disassembling the non-zeroeth frame, we need to backup the
# PC by 1
if non_zeroeth_frame and pc_index > 0:
pc_index = pc_index - 1
if insts_before_pc == -1:
@ -560,64 +600,110 @@ def disassemble_instructions (target, instructions, pc, insts_before_pc, insts_a
end_idx = pc_index + insts_after_pc
if end_idx > inst_idx:
end_idx = inst_idx
for i in range(start_idx, end_idx+1):
for i in range(start_idx, end_idx + 1):
if i == pc_index:
print ' -> ', lines[i]
else:
print ' ', lines[i]
def print_module_section_data (section):
def print_module_section_data(section):
print section
section_data = section.GetSectionData()
if section_data:
ostream = lldb.SBStream()
section_data.GetDescription (ostream, section.GetFileAddress())
section_data.GetDescription(ostream, section.GetFileAddress())
print ostream.GetData()
def print_module_section (section, depth):
def print_module_section(section, depth):
print section
if depth > 0:
num_sub_sections = section.GetNumSubSections()
for sect_idx in range(num_sub_sections):
print_module_section (section.GetSubSectionAtIndex(sect_idx), depth - 1)
print_module_section(
section.GetSubSectionAtIndex(sect_idx), depth - 1)
def print_module_sections (module, depth):
def print_module_sections(module, depth):
for sect in module.section_iter():
print_module_section (sect, depth)
print_module_section(sect, depth)
def print_module_symbols (module):
def print_module_symbols(module):
for sym in module:
print sym
def Symbolicate(command_args):
usage = "usage: %prog [options] <addr1> [addr2 ...]"
description='''Symbolicate one or more addresses using LLDB's python scripting API..'''
parser = optparse.OptionParser(description=description, prog='crashlog.py',usage=usage)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
parser.add_option('-p', '--platform', type='string', metavar='platform', dest='platform', help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
parser.add_option('-f', '--file', type='string', metavar='file', dest='file', help='Specify a file to use when symbolicating')
parser.add_option('-a', '--arch', type='string', metavar='arch', dest='arch', help='Specify a architecture to use when symbolicating')
parser.add_option('-s', '--slide', type='int', metavar='slide', dest='slide', help='Specify the slide to use on the file specified with the --file option', default=None)
parser.add_option('--section', type='string', action='append', dest='section_strings', help='specify <sect-name>=<start-addr> or <sect-name>=<start-addr>-<end-addr>')
description = '''Symbolicate one or more addresses using LLDB's python scripting API..'''
parser = optparse.OptionParser(
description=description,
prog='crashlog.py',
usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
parser.add_option(
'-p',
'--platform',
type='string',
metavar='platform',
dest='platform',
help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
parser.add_option(
'-f',
'--file',
type='string',
metavar='file',
dest='file',
help='Specify a file to use when symbolicating')
parser.add_option(
'-a',
'--arch',
type='string',
metavar='arch',
dest='arch',
help='Specify a architecture to use when symbolicating')
parser.add_option(
'-s',
'--slide',
type='int',
metavar='slide',
dest='slide',
help='Specify the slide to use on the file specified with the --file option',
default=None)
parser.add_option(
'--section',
type='string',
action='append',
dest='section_strings',
help='specify <sect-name>=<start-addr> or <sect-name>=<start-addr>-<end-addr>')
try:
(options, args) = parser.parse_args(command_args)
except:
return
symbolicator = Symbolicator()
images = list();
images = list()
if options.file:
image = Image(options.file);
image = Image(options.file)
image.arch = options.arch
# Add any sections that were specified with one or more --section options
# Add any sections that were specified with one or more --section
# options
if options.section_strings:
for section_str in options.section_strings:
section = Section()
if section.set_from_string (section_str):
image.add_section (section)
if section.set_from_string(section_str):
image.add_section(section)
else:
sys.exit(1)
if options.slide != None:
if options.slide is not None:
image.slide = options.slide
symbolicator.images.append(image)
@ -627,7 +713,8 @@ def Symbolicate(command_args):
if target:
for addr_str in args:
addr = int(addr_str, 0)
symbolicated_addrs = symbolicator.symbolicate(addr, options.verbose)
symbolicated_addrs = symbolicator.symbolicate(
addr, options.verbose)
for symbolicated_addr in symbolicated_addrs:
print symbolicated_addr
print
@ -637,4 +724,4 @@ def Symbolicate(command_args):
if __name__ == '__main__':
# Create a new debugger instance
lldb.debugger = lldb.SBDebugger.Create()
Symbolicate (sys.argv[1:])
Symbolicate(sys.argv[1:])

View File

@ -27,9 +27,14 @@ except ImportError:
# On Darwin, try the currently selected Xcode directory
xcode_dir = commands.getoutput("xcode-select --print-path")
if xcode_dir:
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
os.path.realpath(
xcode_dir +
'/../SharedFrameworks/LLDB.framework/Resources/Python'))
lldb_python_dirs.append(
xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
lldb_python_dirs.append(
'/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
success = False
for lldb_python_dir in lldb_python_dirs:
if os.path.exists(lldb_python_dir):
@ -52,16 +57,18 @@ import optparse
import shlex
import time
def regex_option_callback(option, opt_str, value, parser):
if opt_str == "--std":
value = '^std::'
regex = re.compile(value)
parser.values.skip_type_regexes.append (regex)
parser.values.skip_type_regexes.append(regex)
def create_types_options(for_lldb_command):
if for_lldb_command:
usage = "usage: %prog [options]"
description='''This command will help check for padding in between
description = '''This command will help check for padding in between
base classes and members in structs and classes. It will summarize the types
and how much padding was found. If no types are specified with the --types TYPENAME
option, all structure and class types will be verified. If no modules are
@ -70,30 +77,91 @@ searched.
'''
else:
usage = "usage: %prog [options] EXEPATH [EXEPATH ...]"
description='''This command will help check for padding in between
description = '''This command will help check for padding in between
base classes and members in structures and classes. It will summarize the types
and how much padding was found. One or more paths to executable files must be
specified and targets will be created with these modules. If no types are
specified with the --types TYPENAME option, all structure and class types will
be verified in all specified modules.
'''
parser = optparse.OptionParser(description=description, prog='framestats',usage=usage)
parser = optparse.OptionParser(
description=description,
prog='framestats',
usage=usage)
if not for_lldb_command:
parser.add_option('-a', '--arch', type='string', dest='arch', help='The architecture to use when creating the debug target.', default=None)
parser.add_option('-p', '--platform', type='string', metavar='platform', dest='platform', help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
parser.add_option('-m', '--module', action='append', type='string', metavar='MODULE', dest='modules', help='Specify one or more modules which will be used to verify the types.', default=[])
parser.add_option('-d', '--debug', action='store_true', dest='debug', help='Pause 10 seconds to wait for a debugger to attach.', default=False)
parser.add_option('-t', '--type', action='append', type='string', metavar='TYPENAME', dest='typenames', help='Specify one or more type names which should be verified. If no type names are specified, all class and struct types will be verified.', default=[])
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='Enable verbose logging and information.', default=False)
parser.add_option('-s', '--skip-type-regex', action="callback", callback=regex_option_callback, type='string', metavar='REGEX', dest='skip_type_regexes', help='Regular expressions that, if they match the current member typename, will cause the type to no be recursively displayed.', default=[])
parser.add_option('--std', action="callback", callback=regex_option_callback, metavar='REGEX', dest='skip_type_regexes', help="Don't' recurse into types in the std namespace.", default=[])
parser.add_option(
'-a',
'--arch',
type='string',
dest='arch',
help='The architecture to use when creating the debug target.',
default=None)
parser.add_option(
'-p',
'--platform',
type='string',
metavar='platform',
dest='platform',
help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
parser.add_option(
'-m',
'--module',
action='append',
type='string',
metavar='MODULE',
dest='modules',
help='Specify one or more modules which will be used to verify the types.',
default=[])
parser.add_option(
'-d',
'--debug',
action='store_true',
dest='debug',
help='Pause 10 seconds to wait for a debugger to attach.',
default=False)
parser.add_option(
'-t',
'--type',
action='append',
type='string',
metavar='TYPENAME',
dest='typenames',
help='Specify one or more type names which should be verified. If no type names are specified, all class and struct types will be verified.',
default=[])
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='Enable verbose logging and information.',
default=False)
parser.add_option(
'-s',
'--skip-type-regex',
action="callback",
callback=regex_option_callback,
type='string',
metavar='REGEX',
dest='skip_type_regexes',
help='Regular expressions that, if they match the current member typename, will cause the type to no be recursively displayed.',
default=[])
parser.add_option(
'--std',
action="callback",
callback=regex_option_callback,
metavar='REGEX',
dest='skip_type_regexes',
help="Don't' recurse into types in the std namespace.",
default=[])
return parser
def verify_type (target, options, type):
def verify_type(target, options, type):
print type
typename = type.GetName()
# print 'type: %s' % (typename)
(end_offset, padding) = verify_type_recursive (target, options, type, None, 0, 0, 0)
(end_offset, padding) = verify_type_recursive(
target, options, type, None, 0, 0, 0)
byte_size = type.GetByteSize()
# if end_offset < byte_size:
# last_member_padding = byte_size - end_offset
@ -105,7 +173,15 @@ def verify_type (target, options, type):
print 'Padding percentage: %2.2f %%' % ((float(padding) / float(byte_size)) * 100.0)
print
def verify_type_recursive (target, options, type, member_name, depth, base_offset, padding):
def verify_type_recursive(
target,
options,
type,
member_name,
depth,
base_offset,
padding):
prev_end_offset = base_offset
typename = type.GetName()
byte_size = type.GetByteSize()
@ -115,7 +191,7 @@ def verify_type_recursive (target, options, type, member_name, depth, base_offse
print '%+4u {%3u} %s%s' % (base_offset, byte_size, ' ' * depth, typename)
for type_regex in options.skip_type_regexes:
match = type_regex.match (typename)
match = type_regex.match(typename)
if match:
return (base_offset + byte_size, padding)
@ -132,7 +208,8 @@ def verify_type_recursive (target, options, type, member_name, depth, base_offse
member_is_class_or_struct = False
if member_type_class == lldb.eTypeClassStruct or member_type_class == lldb.eTypeClassClass:
member_is_class_or_struct = True
if member_idx == 0 and member_offset == target.GetAddressByteSize() and type.IsPolymorphicClass():
if member_idx == 0 and member_offset == target.GetAddressByteSize(
) and type.IsPolymorphicClass():
ptr_size = target.GetAddressByteSize()
print '%+4u <%3u> %s__vtbl_ptr_type * _vptr;' % (prev_end_offset, ptr_size, ' ' * (depth + 1))
prev_end_offset = ptr_size
@ -143,7 +220,14 @@ def verify_type_recursive (target, options, type, member_name, depth, base_offse
print '%+4u <%3u> %s<PADDING>' % (prev_end_offset, member_padding, ' ' * (depth + 1))
if member_is_class_or_struct:
(prev_end_offset, padding) = verify_type_recursive (target, options, member_canonical_type, member_name, depth + 1, member_total_offset, padding)
(prev_end_offset,
padding) = verify_type_recursive(target,
options,
member_canonical_type,
member_name,
depth + 1,
member_total_offset,
padding)
else:
prev_end_offset = member_total_offset + member_byte_size
member_typename = member_type.GetName()
@ -165,7 +249,8 @@ def verify_type_recursive (target, options, type, member_name, depth, base_offse
return (prev_end_offset, padding)
def check_padding_command (debugger, command, result, dict):
def check_padding_command(debugger, command, result, dict):
# Use the Shell Lexer to properly parse up command options just like a
# shell would
command_args = shlex.split(command)
@ -175,16 +260,19 @@ def check_padding_command (debugger, command, result, dict):
except:
# if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
# (courtesy of OptParse dealing with argument errors by throwing SystemExit)
result.SetStatus (lldb.eReturnStatusFailed)
return "option parsing failed" # returning a string is the same as returning an error whose description is the string
result.SetStatus(lldb.eReturnStatusFailed)
# returning a string is the same as returning an error whose
# description is the string
return "option parsing failed"
verify_types(debugger.GetSelectedTarget(), options)
@lldb.command("parse_all_struct_class_types")
def parse_all_struct_class_types (debugger, command, result, dict):
def parse_all_struct_class_types(debugger, command, result, dict):
command_args = shlex.split(command)
for f in command_args:
error = lldb.SBError()
target = debugger.CreateTarget (f, None, None, False, error)
target = debugger.CreateTarget(f, None, None, False, error)
module = target.GetModuleAtIndex(0)
print "Parsing all types in '%s'" % (module)
types = module.GetTypes(lldb.eTypeClassClass | lldb.eTypeClassStruct)
@ -193,7 +281,7 @@ def parse_all_struct_class_types (debugger, command, result, dict):
print ""
def verify_types (target, options):
def verify_types(target, options):
if not target:
print 'error: invalid target'
@ -220,14 +308,15 @@ def verify_types (target, options):
if types.GetSize():
print 'Found %u types matching "%s" in "%s"' % (len(types), typename, module.file)
for type in types:
verify_type (target, options, type)
verify_type(target, options, type)
else:
print 'error: no type matches "%s" in "%s"' % (typename, module.file)
else:
types = module.GetTypes(lldb.eTypeClassClass | lldb.eTypeClassStruct)
types = module.GetTypes(
lldb.eTypeClassClass | lldb.eTypeClassStruct)
print 'Found %u types in "%s"' % (len(types), module.file)
for type in types:
verify_type (target, options, type)
verify_type(target, options, type)
else:
print 'error: no modules'
@ -248,9 +337,10 @@ if __name__ == '__main__':
for path in args:
# in a command - the lldb.* convenience variables are not to be used
# and their values (if any) are undefined
# this is the best practice to access those objects from within a command
# this is the best practice to access those objects from within a
# command
error = lldb.SBError()
target = debugger.CreateTarget (path,
target = debugger.CreateTarget(path,
options.arch,
options.platform,
True,
@ -258,8 +348,9 @@ if __name__ == '__main__':
if error.Fail():
print error.GetCString()
continue
verify_types (target, options)
verify_types(target, options)
elif getattr(lldb, 'debugger', None):
lldb.debugger.HandleCommand('command script add -f types.check_padding_command check_padding')
lldb.debugger.HandleCommand(
'command script add -f types.check_padding_command check_padding')
print '"check_padding" command installed, use the "--help" option for detailed help'

View File

@ -41,289 +41,707 @@ from lldb import *
# Compiler and DWARF register numbers
name_to_gcc_dwarf_regnum = {
'rax' : 0 ,
'rdx' : 1 ,
'rcx' : 2 ,
'rbx' : 3 ,
'rsi' : 4 ,
'rdi' : 5 ,
'rbp' : 6 ,
'rsp' : 7 ,
'r8' : 8 ,
'r9' : 9 ,
'r10' : 10,
'r11' : 11,
'r12' : 12,
'r13' : 13,
'r14' : 14,
'r15' : 15,
'rip' : 16,
'xmm0' : 17,
'xmm1' : 18,
'xmm2' : 19,
'xmm3' : 20,
'xmm4' : 21,
'xmm5' : 22,
'xmm6' : 23,
'xmm7' : 24,
'xmm8' : 25,
'xmm9' : 26,
'xmm10' : 27,
'xmm11' : 28,
'xmm12' : 29,
'xmm13' : 30,
'xmm14' : 31,
'xmm15' : 32,
'stmm0' : 33,
'stmm1' : 34,
'stmm2' : 35,
'stmm3' : 36,
'stmm4' : 37,
'stmm5' : 38,
'stmm6' : 39,
'stmm7' : 30,
'ymm0' : 41,
'ymm1' : 42,
'ymm2' : 43,
'ymm3' : 44,
'ymm4' : 45,
'ymm5' : 46,
'ymm6' : 47,
'ymm7' : 48,
'ymm8' : 49,
'ymm9' : 40,
'ymm10' : 41,
'ymm11' : 42,
'ymm12' : 43,
'ymm13' : 44,
'ymm14' : 45,
'ymm15' : 46
};
'rax': 0,
'rdx': 1,
'rcx': 2,
'rbx': 3,
'rsi': 4,
'rdi': 5,
'rbp': 6,
'rsp': 7,
'r8': 8,
'r9': 9,
'r10': 10,
'r11': 11,
'r12': 12,
'r13': 13,
'r14': 14,
'r15': 15,
'rip': 16,
'xmm0': 17,
'xmm1': 18,
'xmm2': 19,
'xmm3': 20,
'xmm4': 21,
'xmm5': 22,
'xmm6': 23,
'xmm7': 24,
'xmm8': 25,
'xmm9': 26,
'xmm10': 27,
'xmm11': 28,
'xmm12': 29,
'xmm13': 30,
'xmm14': 31,
'xmm15': 32,
'stmm0': 33,
'stmm1': 34,
'stmm2': 35,
'stmm3': 36,
'stmm4': 37,
'stmm5': 38,
'stmm6': 39,
'stmm7': 30,
'ymm0': 41,
'ymm1': 42,
'ymm2': 43,
'ymm3': 44,
'ymm4': 45,
'ymm5': 46,
'ymm6': 47,
'ymm7': 48,
'ymm8': 49,
'ymm9': 40,
'ymm10': 41,
'ymm11': 42,
'ymm12': 43,
'ymm13': 44,
'ymm14': 45,
'ymm15': 46
}
name_to_gdb_regnum = {
'rax' : 0,
'rbx' : 1,
'rcx' : 2,
'rdx' : 3,
'rsi' : 4,
'rdi' : 5,
'rbp' : 6,
'rsp' : 7,
'r8' : 8,
'r9' : 9,
'r10' : 10,
'r11' : 11,
'r12' : 12,
'r13' : 13,
'r14' : 14,
'r15' : 15,
'rip' : 16,
'rax': 0,
'rbx': 1,
'rcx': 2,
'rdx': 3,
'rsi': 4,
'rdi': 5,
'rbp': 6,
'rsp': 7,
'r8': 8,
'r9': 9,
'r10': 10,
'r11': 11,
'r12': 12,
'r13': 13,
'r14': 14,
'r15': 15,
'rip': 16,
'rflags': 17,
'cs' : 18,
'ss' : 19,
'ds' : 20,
'es' : 21,
'fs' : 22,
'gs' : 23,
'stmm0' : 24,
'stmm1' : 25,
'stmm2' : 26,
'stmm3' : 27,
'stmm4' : 28,
'stmm5' : 29,
'stmm6' : 30,
'stmm7' : 31,
'fctrl' : 32,
'fstat' : 33,
'ftag' : 34,
'fiseg' : 35,
'fioff' : 36,
'foseg' : 37,
'fooff' : 38,
'fop' : 39,
'xmm0' : 40,
'xmm1' : 41,
'xmm2' : 42,
'xmm3' : 43,
'xmm4' : 44,
'xmm5' : 45,
'xmm6' : 46,
'xmm7' : 47,
'xmm8' : 48,
'xmm9' : 49,
'xmm10' : 50,
'xmm11' : 51,
'xmm12' : 52,
'xmm13' : 53,
'xmm14' : 54,
'xmm15' : 55,
'mxcsr' : 56,
'ymm0' : 57,
'ymm1' : 58,
'ymm2' : 59,
'ymm3' : 60,
'ymm4' : 61,
'ymm5' : 62,
'ymm6' : 63,
'ymm7' : 64,
'ymm8' : 65,
'ymm9' : 66,
'ymm10' : 67,
'ymm11' : 68,
'ymm12' : 69,
'ymm13' : 70,
'ymm14' : 71,
'ymm15' : 72
};
'cs': 18,
'ss': 19,
'ds': 20,
'es': 21,
'fs': 22,
'gs': 23,
'stmm0': 24,
'stmm1': 25,
'stmm2': 26,
'stmm3': 27,
'stmm4': 28,
'stmm5': 29,
'stmm6': 30,
'stmm7': 31,
'fctrl': 32,
'fstat': 33,
'ftag': 34,
'fiseg': 35,
'fioff': 36,
'foseg': 37,
'fooff': 38,
'fop': 39,
'xmm0': 40,
'xmm1': 41,
'xmm2': 42,
'xmm3': 43,
'xmm4': 44,
'xmm5': 45,
'xmm6': 46,
'xmm7': 47,
'xmm8': 48,
'xmm9': 49,
'xmm10': 50,
'xmm11': 51,
'xmm12': 52,
'xmm13': 53,
'xmm14': 54,
'xmm15': 55,
'mxcsr': 56,
'ymm0': 57,
'ymm1': 58,
'ymm2': 59,
'ymm3': 60,
'ymm4': 61,
'ymm5': 62,
'ymm6': 63,
'ymm7': 64,
'ymm8': 65,
'ymm9': 66,
'ymm10': 67,
'ymm11': 68,
'ymm12': 69,
'ymm13': 70,
'ymm14': 71,
'ymm15': 72
}
name_to_generic_regnum = {
'rip' : LLDB_REGNUM_GENERIC_PC,
'rsp' : LLDB_REGNUM_GENERIC_SP,
'rbp' : LLDB_REGNUM_GENERIC_FP,
'rdi' : LLDB_REGNUM_GENERIC_ARG1,
'rsi' : LLDB_REGNUM_GENERIC_ARG2,
'rdx' : LLDB_REGNUM_GENERIC_ARG3,
'rcx' : LLDB_REGNUM_GENERIC_ARG4,
'r8' : LLDB_REGNUM_GENERIC_ARG5,
'r9' : LLDB_REGNUM_GENERIC_ARG6
};
'rip': LLDB_REGNUM_GENERIC_PC,
'rsp': LLDB_REGNUM_GENERIC_SP,
'rbp': LLDB_REGNUM_GENERIC_FP,
'rdi': LLDB_REGNUM_GENERIC_ARG1,
'rsi': LLDB_REGNUM_GENERIC_ARG2,
'rdx': LLDB_REGNUM_GENERIC_ARG3,
'rcx': LLDB_REGNUM_GENERIC_ARG4,
'r8': LLDB_REGNUM_GENERIC_ARG5,
'r9': LLDB_REGNUM_GENERIC_ARG6
}
def get_reg_num (reg_num_dict, reg_name):
def get_reg_num(reg_num_dict, reg_name):
if reg_name in reg_num_dict:
return reg_num_dict[reg_name]
return LLDB_INVALID_REGNUM
x86_64_register_infos = [
{ 'name':'rax' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'rbx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'rcx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg4' },
{ 'name':'rdx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg3' },
{ 'name':'rsi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg2' },
{ 'name':'rdi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg1' },
{ 'name':'rbp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'fp' },
{ 'name':'rsp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'sp' },
{ 'name':'r8' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg5' },
{ 'name':'r9' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg6' },
{ 'name':'r10' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r11' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r12' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r13' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r14' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r15' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'rip' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'pc' },
{ 'name':'rflags', 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'cs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'ss' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'ds' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'es' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'gs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'stmm0' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm1' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm2' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm3' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm4' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm5' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm6' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm7' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'fctrl' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fstat' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'ftag' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fiseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fioff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'foseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fooff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fop' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'xmm0' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm1' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm2' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm3' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm4' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm5' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm6' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm7' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm8' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm9' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm10' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm11' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm12' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm13' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm14' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm15' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'mxcsr' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'orig_rax' , 'set':1, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatHex },
# Registers that are contained in or composed of one of more other registers
{ 'name':'eax' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[31:0]' },
{ 'name':'ebx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[31:0]' },
{ 'name':'ecx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[31:0]' },
{ 'name':'edx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[31:0]' },
{ 'name':'edi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[31:0]' },
{ 'name':'esi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[31:0]' },
{ 'name':'ebp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[31:0]' },
{ 'name':'esp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[31:0]' },
{ 'name':'r8d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[31:0]' },
{ 'name':'r9d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[31:0]' },
{ 'name':'r10d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[31:0]' },
{ 'name':'r11d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[31:0]' },
{ 'name':'r12d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[31:0]' },
{ 'name':'r13d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[31:0]' },
{ 'name':'r14d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[31:0]' },
{ 'name':'r15d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[31:0]' },
{'name': 'rax',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'rbx',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'rcx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg4'},
{'name': 'rdx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg3'},
{'name': 'rsi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg2'},
{'name': 'rdi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg1'},
{'name': 'rbp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'fp'},
{'name': 'rsp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'sp'},
{'name': 'r8', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg5'},
{'name': 'r9', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg6'},
{'name': 'r10',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r11',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r12',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r13',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r14',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r15',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'rip', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'pc'},
{'name': 'rflags', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'cs', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'ss', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'ds', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'es', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fs', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'gs', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'stmm0',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm1',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm2',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm3',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm4',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm5',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm6',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm7',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'fctrl', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fstat', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'ftag', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fiseg', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fioff', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'foseg', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fooff', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fop', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'xmm0',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm1',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm2',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm3',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm4',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm5',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm6',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm7',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm8',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm9',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm10',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm11',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm12',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm13',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm14',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm15',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'mxcsr', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'orig_rax', 'set': 1, 'bitsize': 64,
'encoding': eEncodingUint, 'format': eFormatHex},
# Registers that are contained in or composed of one of more other
# registers
{'name': 'eax',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[31:0]'},
{'name': 'ebx',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[31:0]'},
{'name': 'ecx',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[31:0]'},
{'name': 'edx',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[31:0]'},
{'name': 'edi',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdi[31:0]'},
{'name': 'esi',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsi[31:0]'},
{'name': 'ebp',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbp[31:0]'},
{'name': 'esp',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsp[31:0]'},
{'name': 'r8d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r8[31:0]'},
{'name': 'r9d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r9[31:0]'},
{'name': 'r10d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r10[31:0]'},
{'name': 'r11d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r11[31:0]'},
{'name': 'r12d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r12[31:0]'},
{'name': 'r13d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r13[31:0]'},
{'name': 'r14d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r14[31:0]'},
{'name': 'r15d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r15[31:0]'},
{ 'name':'ax' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[15:0]' },
{ 'name':'bx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:0]' },
{ 'name':'cx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:0]' },
{ 'name':'dx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:0]' },
{ 'name':'di' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[15:0]' },
{ 'name':'si' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[15:0]' },
{ 'name':'bp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[15:0]' },
{ 'name':'sp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[15:0]' },
{ 'name':'r8w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[15:0]' },
{ 'name':'r9w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[15:0]' },
{ 'name':'r10w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[15:0]' },
{ 'name':'r11w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[15:0]' },
{ 'name':'r12w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[15:0]' },
{ 'name':'r13w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[15:0]' },
{ 'name':'r14w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[15:0]' },
{ 'name':'r15w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[15:0]' },
{'name': 'ax',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[15:0]'},
{'name': 'bx',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[15:0]'},
{'name': 'cx',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[15:0]'},
{'name': 'dx',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[15:0]'},
{'name': 'di',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdi[15:0]'},
{'name': 'si',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsi[15:0]'},
{'name': 'bp',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbp[15:0]'},
{'name': 'sp',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsp[15:0]'},
{'name': 'r8w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r8[15:0]'},
{'name': 'r9w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r9[15:0]'},
{'name': 'r10w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r10[15:0]'},
{'name': 'r11w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r11[15:0]'},
{'name': 'r12w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r12[15:0]'},
{'name': 'r13w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r13[15:0]'},
{'name': 'r14w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r14[15:0]'},
{'name': 'r15w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r15[15:0]'},
{ 'name':'ah' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[15:8]' },
{ 'name':'bh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:8]' },
{ 'name':'ch' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:8]' },
{ 'name':'dh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:8]' },
{'name': 'ah',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[15:8]'},
{'name': 'bh',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[15:8]'},
{'name': 'ch',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[15:8]'},
{'name': 'dh',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[15:8]'},
{ 'name':'al' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[7:0]' },
{ 'name':'bl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[7:0]' },
{ 'name':'cl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[7:0]' },
{ 'name':'dl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[7:0]' },
{ 'name':'dil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[7:0]' },
{ 'name':'sil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[7:0]' },
{ 'name':'bpl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[7:0]' },
{ 'name':'spl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[7:0]' },
{ 'name':'r8l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[7:0]' },
{ 'name':'r9l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[7:0]' },
{ 'name':'r10l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[7:0]' },
{ 'name':'r11l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[7:0]' },
{ 'name':'r12l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[7:0]' },
{ 'name':'r13l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[7:0]' },
{ 'name':'r14l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[7:0]' },
{ 'name':'r15l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[7:0]' },
];
{'name': 'al',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[7:0]'},
{'name': 'bl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[7:0]'},
{'name': 'cl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[7:0]'},
{'name': 'dl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[7:0]'},
{'name': 'dil',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdi[7:0]'},
{'name': 'sil',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsi[7:0]'},
{'name': 'bpl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbp[7:0]'},
{'name': 'spl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsp[7:0]'},
{'name': 'r8l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r8[7:0]'},
{'name': 'r9l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r9[7:0]'},
{'name': 'r10l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r10[7:0]'},
{'name': 'r11l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r11[7:0]'},
{'name': 'r12l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r12[7:0]'},
{'name': 'r13l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r13[7:0]'},
{'name': 'r14l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r14[7:0]'},
{'name': 'r15l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r15[7:0]'},
]
g_target_definition = None
def get_target_definition ():
def get_target_definition():
global g_target_definition
if g_target_definition == None:
if g_target_definition is None:
g_target_definition = {}
offset = 0
for reg_info in x86_64_register_infos:
reg_name = reg_info['name']
# Only fill in the offset if there is no 'slice' in the register info
# Only fill in the offset if there is no 'slice' in the register
# info
if 'slice' not in reg_info and 'composite' not in reg_info:
reg_info['offset'] = offset
offset += reg_info['bitsize']/8
offset += reg_info['bitsize'] / 8
# Set the GCC/DWARF register number for this register if it has one
reg_num = get_reg_num(name_to_gcc_dwarf_regnum, reg_name)
@ -341,13 +759,17 @@ def get_target_definition ():
if reg_num != LLDB_INVALID_REGNUM:
reg_info['gdb'] = reg_num
g_target_definition['sets'] = ['General Purpose Registers', 'Floating Point Registers']
g_target_definition['sets'] = [
'General Purpose Registers',
'Floating Point Registers']
g_target_definition['registers'] = x86_64_register_infos
g_target_definition['host-info'] = { 'triple' : 'x86_64-*-linux', 'endian': eByteOrderLittle }
g_target_definition[
'host-info'] = {'triple': 'x86_64-*-linux', 'endian': eByteOrderLittle}
g_target_definition['g-packet-size'] = offset
g_target_definition['breakpoint-pc-offset'] = -1
return g_target_definition
def get_dynamic_setting(target, setting_name):
if setting_name == 'gdb-server-target-definition':
return get_target_definition()

View File

@ -41,288 +41,705 @@ from lldb import *
# Compiler and DWARF register numbers
name_to_gcc_dwarf_regnum = {
'rax' : 0 ,
'rdx' : 1 ,
'rcx' : 2 ,
'rbx' : 3 ,
'rsi' : 4 ,
'rdi' : 5 ,
'rbp' : 6 ,
'rsp' : 7 ,
'r8' : 8 ,
'r9' : 9 ,
'r10' : 10,
'r11' : 11,
'r12' : 12,
'r13' : 13,
'r14' : 14,
'r15' : 15,
'rip' : 16,
'xmm0' : 17,
'xmm1' : 18,
'xmm2' : 19,
'xmm3' : 20,
'xmm4' : 21,
'xmm5' : 22,
'xmm6' : 23,
'xmm7' : 24,
'xmm8' : 25,
'xmm9' : 26,
'xmm10' : 27,
'xmm11' : 28,
'xmm12' : 29,
'xmm13' : 30,
'xmm14' : 31,
'xmm15' : 32,
'stmm0' : 33,
'stmm1' : 34,
'stmm2' : 35,
'stmm3' : 36,
'stmm4' : 37,
'stmm5' : 38,
'stmm6' : 39,
'stmm7' : 30,
'ymm0' : 41,
'ymm1' : 42,
'ymm2' : 43,
'ymm3' : 44,
'ymm4' : 45,
'ymm5' : 46,
'ymm6' : 47,
'ymm7' : 48,
'ymm8' : 49,
'ymm9' : 40,
'ymm10' : 41,
'ymm11' : 42,
'ymm12' : 43,
'ymm13' : 44,
'ymm14' : 45,
'ymm15' : 46
};
'rax': 0,
'rdx': 1,
'rcx': 2,
'rbx': 3,
'rsi': 4,
'rdi': 5,
'rbp': 6,
'rsp': 7,
'r8': 8,
'r9': 9,
'r10': 10,
'r11': 11,
'r12': 12,
'r13': 13,
'r14': 14,
'r15': 15,
'rip': 16,
'xmm0': 17,
'xmm1': 18,
'xmm2': 19,
'xmm3': 20,
'xmm4': 21,
'xmm5': 22,
'xmm6': 23,
'xmm7': 24,
'xmm8': 25,
'xmm9': 26,
'xmm10': 27,
'xmm11': 28,
'xmm12': 29,
'xmm13': 30,
'xmm14': 31,
'xmm15': 32,
'stmm0': 33,
'stmm1': 34,
'stmm2': 35,
'stmm3': 36,
'stmm4': 37,
'stmm5': 38,
'stmm6': 39,
'stmm7': 30,
'ymm0': 41,
'ymm1': 42,
'ymm2': 43,
'ymm3': 44,
'ymm4': 45,
'ymm5': 46,
'ymm6': 47,
'ymm7': 48,
'ymm8': 49,
'ymm9': 40,
'ymm10': 41,
'ymm11': 42,
'ymm12': 43,
'ymm13': 44,
'ymm14': 45,
'ymm15': 46
}
name_to_gdb_regnum = {
'rax' : 0,
'rbx' : 1,
'rcx' : 2,
'rdx' : 3,
'rsi' : 4,
'rdi' : 5,
'rbp' : 6,
'rsp' : 7,
'r8' : 8,
'r9' : 9,
'r10' : 10,
'r11' : 11,
'r12' : 12,
'r13' : 13,
'r14' : 14,
'r15' : 15,
'rip' : 16,
'rax': 0,
'rbx': 1,
'rcx': 2,
'rdx': 3,
'rsi': 4,
'rdi': 5,
'rbp': 6,
'rsp': 7,
'r8': 8,
'r9': 9,
'r10': 10,
'r11': 11,
'r12': 12,
'r13': 13,
'r14': 14,
'r15': 15,
'rip': 16,
'rflags': 17,
'cs' : 18,
'ss' : 19,
'ds' : 20,
'es' : 21,
'fs' : 22,
'gs' : 23,
'stmm0' : 24,
'stmm1' : 25,
'stmm2' : 26,
'stmm3' : 27,
'stmm4' : 28,
'stmm5' : 29,
'stmm6' : 30,
'stmm7' : 31,
'fctrl' : 32,
'fstat' : 33,
'ftag' : 34,
'fiseg' : 35,
'fioff' : 36,
'foseg' : 37,
'fooff' : 38,
'fop' : 39,
'xmm0' : 40,
'xmm1' : 41,
'xmm2' : 42,
'xmm3' : 43,
'xmm4' : 44,
'xmm5' : 45,
'xmm6' : 46,
'xmm7' : 47,
'xmm8' : 48,
'xmm9' : 49,
'xmm10' : 50,
'xmm11' : 51,
'xmm12' : 52,
'xmm13' : 53,
'xmm14' : 54,
'xmm15' : 55,
'mxcsr' : 56,
'ymm0' : 57,
'ymm1' : 58,
'ymm2' : 59,
'ymm3' : 60,
'ymm4' : 61,
'ymm5' : 62,
'ymm6' : 63,
'ymm7' : 64,
'ymm8' : 65,
'ymm9' : 66,
'ymm10' : 67,
'ymm11' : 68,
'ymm12' : 69,
'ymm13' : 70,
'ymm14' : 71,
'ymm15' : 72
};
'cs': 18,
'ss': 19,
'ds': 20,
'es': 21,
'fs': 22,
'gs': 23,
'stmm0': 24,
'stmm1': 25,
'stmm2': 26,
'stmm3': 27,
'stmm4': 28,
'stmm5': 29,
'stmm6': 30,
'stmm7': 31,
'fctrl': 32,
'fstat': 33,
'ftag': 34,
'fiseg': 35,
'fioff': 36,
'foseg': 37,
'fooff': 38,
'fop': 39,
'xmm0': 40,
'xmm1': 41,
'xmm2': 42,
'xmm3': 43,
'xmm4': 44,
'xmm5': 45,
'xmm6': 46,
'xmm7': 47,
'xmm8': 48,
'xmm9': 49,
'xmm10': 50,
'xmm11': 51,
'xmm12': 52,
'xmm13': 53,
'xmm14': 54,
'xmm15': 55,
'mxcsr': 56,
'ymm0': 57,
'ymm1': 58,
'ymm2': 59,
'ymm3': 60,
'ymm4': 61,
'ymm5': 62,
'ymm6': 63,
'ymm7': 64,
'ymm8': 65,
'ymm9': 66,
'ymm10': 67,
'ymm11': 68,
'ymm12': 69,
'ymm13': 70,
'ymm14': 71,
'ymm15': 72
}
name_to_generic_regnum = {
'rip' : LLDB_REGNUM_GENERIC_PC,
'rsp' : LLDB_REGNUM_GENERIC_SP,
'rbp' : LLDB_REGNUM_GENERIC_FP,
'rdi' : LLDB_REGNUM_GENERIC_ARG1,
'rsi' : LLDB_REGNUM_GENERIC_ARG2,
'rdx' : LLDB_REGNUM_GENERIC_ARG3,
'rcx' : LLDB_REGNUM_GENERIC_ARG4,
'r8' : LLDB_REGNUM_GENERIC_ARG5,
'r9' : LLDB_REGNUM_GENERIC_ARG6
};
'rip': LLDB_REGNUM_GENERIC_PC,
'rsp': LLDB_REGNUM_GENERIC_SP,
'rbp': LLDB_REGNUM_GENERIC_FP,
'rdi': LLDB_REGNUM_GENERIC_ARG1,
'rsi': LLDB_REGNUM_GENERIC_ARG2,
'rdx': LLDB_REGNUM_GENERIC_ARG3,
'rcx': LLDB_REGNUM_GENERIC_ARG4,
'r8': LLDB_REGNUM_GENERIC_ARG5,
'r9': LLDB_REGNUM_GENERIC_ARG6
}
def get_reg_num (reg_num_dict, reg_name):
def get_reg_num(reg_num_dict, reg_name):
if reg_name in reg_num_dict:
return reg_num_dict[reg_name]
return LLDB_INVALID_REGNUM
x86_64_register_infos = [
{ 'name':'rax' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'rbx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'rcx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg4' },
{ 'name':'rdx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg3' },
{ 'name':'rsi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg2' },
{ 'name':'rdi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg1' },
{ 'name':'rbp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'fp' },
{ 'name':'rsp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'sp' },
{ 'name':'r8' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg5' },
{ 'name':'r9' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg6' },
{ 'name':'r10' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r11' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r12' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r13' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r14' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r15' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'rip' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'pc' },
{ 'name':'rflags', 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'cs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'ss' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'ds' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'es' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'gs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'stmm0' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm1' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm2' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm3' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm4' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm5' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm6' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm7' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'fctrl' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fstat' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'ftag' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fiseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fioff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'foseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fooff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fop' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'xmm0' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm1' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm2' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm3' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm4' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm5' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm6' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm7' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm8' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm9' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm10' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm11' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm12' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm13' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm14' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm15' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'mxcsr' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
# Registers that are contained in or composed of one of more other registers
{ 'name':'eax' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[31:0]' },
{ 'name':'ebx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[31:0]' },
{ 'name':'ecx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[31:0]' },
{ 'name':'edx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[31:0]' },
{ 'name':'edi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[31:0]' },
{ 'name':'esi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[31:0]' },
{ 'name':'ebp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[31:0]' },
{ 'name':'esp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[31:0]' },
{ 'name':'r8d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[31:0]' },
{ 'name':'r9d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[31:0]' },
{ 'name':'r10d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[31:0]' },
{ 'name':'r11d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[31:0]' },
{ 'name':'r12d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[31:0]' },
{ 'name':'r13d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[31:0]' },
{ 'name':'r14d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[31:0]' },
{ 'name':'r15d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[31:0]' },
{'name': 'rax',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'rbx',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'rcx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg4'},
{'name': 'rdx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg3'},
{'name': 'rsi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg2'},
{'name': 'rdi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg1'},
{'name': 'rbp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'fp'},
{'name': 'rsp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'sp'},
{'name': 'r8', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg5'},
{'name': 'r9', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg6'},
{'name': 'r10',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r11',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r12',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r13',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r14',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r15',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'rip', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'pc'},
{'name': 'rflags', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'cs', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'ss', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'ds', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'es', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fs', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'gs', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'stmm0',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm1',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm2',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm3',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm4',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm5',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm6',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm7',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'fctrl', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fstat', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'ftag', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fiseg', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fioff', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'foseg', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fooff', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fop', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'xmm0',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm1',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm2',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm3',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm4',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm5',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm6',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm7',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm8',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm9',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm10',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm11',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm12',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm13',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm14',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm15',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'mxcsr', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
# Registers that are contained in or composed of one of more other
# registers
{'name': 'eax',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[31:0]'},
{'name': 'ebx',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[31:0]'},
{'name': 'ecx',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[31:0]'},
{'name': 'edx',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[31:0]'},
{'name': 'edi',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdi[31:0]'},
{'name': 'esi',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsi[31:0]'},
{'name': 'ebp',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbp[31:0]'},
{'name': 'esp',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsp[31:0]'},
{'name': 'r8d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r8[31:0]'},
{'name': 'r9d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r9[31:0]'},
{'name': 'r10d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r10[31:0]'},
{'name': 'r11d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r11[31:0]'},
{'name': 'r12d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r12[31:0]'},
{'name': 'r13d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r13[31:0]'},
{'name': 'r14d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r14[31:0]'},
{'name': 'r15d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r15[31:0]'},
{ 'name':'ax' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[15:0]' },
{ 'name':'bx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:0]' },
{ 'name':'cx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:0]' },
{ 'name':'dx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:0]' },
{ 'name':'di' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[15:0]' },
{ 'name':'si' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[15:0]' },
{ 'name':'bp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[15:0]' },
{ 'name':'sp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[15:0]' },
{ 'name':'r8w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[15:0]' },
{ 'name':'r9w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[15:0]' },
{ 'name':'r10w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[15:0]' },
{ 'name':'r11w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[15:0]' },
{ 'name':'r12w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[15:0]' },
{ 'name':'r13w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[15:0]' },
{ 'name':'r14w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[15:0]' },
{ 'name':'r15w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[15:0]' },
{'name': 'ax',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[15:0]'},
{'name': 'bx',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[15:0]'},
{'name': 'cx',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[15:0]'},
{'name': 'dx',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[15:0]'},
{'name': 'di',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdi[15:0]'},
{'name': 'si',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsi[15:0]'},
{'name': 'bp',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbp[15:0]'},
{'name': 'sp',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsp[15:0]'},
{'name': 'r8w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r8[15:0]'},
{'name': 'r9w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r9[15:0]'},
{'name': 'r10w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r10[15:0]'},
{'name': 'r11w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r11[15:0]'},
{'name': 'r12w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r12[15:0]'},
{'name': 'r13w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r13[15:0]'},
{'name': 'r14w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r14[15:0]'},
{'name': 'r15w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r15[15:0]'},
{ 'name':'ah' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[15:8]' },
{ 'name':'bh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:8]' },
{ 'name':'ch' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:8]' },
{ 'name':'dh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:8]' },
{'name': 'ah',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[15:8]'},
{'name': 'bh',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[15:8]'},
{'name': 'ch',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[15:8]'},
{'name': 'dh',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[15:8]'},
{ 'name':'al' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[7:0]' },
{ 'name':'bl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[7:0]' },
{ 'name':'cl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[7:0]' },
{ 'name':'dl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[7:0]' },
{ 'name':'dil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[7:0]' },
{ 'name':'sil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[7:0]' },
{ 'name':'bpl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[7:0]' },
{ 'name':'spl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[7:0]' },
{ 'name':'r8l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[7:0]' },
{ 'name':'r9l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[7:0]' },
{ 'name':'r10l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[7:0]' },
{ 'name':'r11l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[7:0]' },
{ 'name':'r12l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[7:0]' },
{ 'name':'r13l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[7:0]' },
{ 'name':'r14l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[7:0]' },
{ 'name':'r15l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[7:0]' },
];
{'name': 'al',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[7:0]'},
{'name': 'bl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[7:0]'},
{'name': 'cl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[7:0]'},
{'name': 'dl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[7:0]'},
{'name': 'dil',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdi[7:0]'},
{'name': 'sil',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsi[7:0]'},
{'name': 'bpl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbp[7:0]'},
{'name': 'spl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsp[7:0]'},
{'name': 'r8l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r8[7:0]'},
{'name': 'r9l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r9[7:0]'},
{'name': 'r10l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r10[7:0]'},
{'name': 'r11l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r11[7:0]'},
{'name': 'r12l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r12[7:0]'},
{'name': 'r13l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r13[7:0]'},
{'name': 'r14l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r14[7:0]'},
{'name': 'r15l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r15[7:0]'},
]
g_target_definition = None
def get_target_definition ():
def get_target_definition():
global g_target_definition
if g_target_definition == None:
if g_target_definition is None:
g_target_definition = {}
offset = 0
for reg_info in x86_64_register_infos:
reg_name = reg_info['name']
# Only fill in the offset if there is no 'slice' in the register info
# Only fill in the offset if there is no 'slice' in the register
# info
if 'slice' not in reg_info and 'composite' not in reg_info:
reg_info['offset'] = offset
offset += reg_info['bitsize']/8
offset += reg_info['bitsize'] / 8
# Set the GCC/DWARF register number for this register if it has one
reg_num = get_reg_num(name_to_gcc_dwarf_regnum, reg_name)
@ -340,13 +757,17 @@ def get_target_definition ():
if reg_num != LLDB_INVALID_REGNUM:
reg_info['gdb'] = reg_num
g_target_definition['sets'] = ['General Purpose Registers', 'Floating Point Registers']
g_target_definition['sets'] = [
'General Purpose Registers',
'Floating Point Registers']
g_target_definition['registers'] = x86_64_register_infos
g_target_definition['host-info'] = { 'triple' : 'x86_64-*-linux', 'endian': eByteOrderLittle }
g_target_definition[
'host-info'] = {'triple': 'x86_64-*-linux', 'endian': eByteOrderLittle}
g_target_definition['g-packet-size'] = offset
g_target_definition['breakpoint-pc-offset'] = -1
return g_target_definition
def get_dynamic_setting(target, setting_name):
if setting_name == 'gdb-server-target-definition':
return get_target_definition()

View File

@ -41,294 +41,711 @@ from lldb import *
# Compiler and DWARF register numbers
name_to_gcc_dwarf_regnum = {
'rax' : 0 ,
'rdx' : 1 ,
'rcx' : 2 ,
'rbx' : 3 ,
'rsi' : 4 ,
'rdi' : 5 ,
'rbp' : 6 ,
'rsp' : 7 ,
'r8' : 8 ,
'r9' : 9 ,
'r10' : 10,
'r11' : 11,
'r12' : 12,
'r13' : 13,
'r14' : 14,
'r15' : 15,
'rip' : 16,
'xmm0' : 17,
'xmm1' : 18,
'xmm2' : 19,
'xmm3' : 20,
'xmm4' : 21,
'xmm5' : 22,
'xmm6' : 23,
'xmm7' : 24,
'xmm8' : 25,
'xmm9' : 26,
'xmm10' : 27,
'xmm11' : 28,
'xmm12' : 29,
'xmm13' : 30,
'xmm14' : 31,
'xmm15' : 32,
'stmm0' : 33,
'stmm1' : 34,
'stmm2' : 35,
'stmm3' : 36,
'stmm4' : 37,
'stmm5' : 38,
'stmm6' : 39,
'stmm7' : 30,
'ymm0' : 41,
'ymm1' : 42,
'ymm2' : 43,
'ymm3' : 44,
'ymm4' : 45,
'ymm5' : 46,
'ymm6' : 47,
'ymm7' : 48,
'ymm8' : 49,
'ymm9' : 40,
'ymm10' : 41,
'ymm11' : 42,
'ymm12' : 43,
'ymm13' : 44,
'ymm14' : 45,
'ymm15' : 46
};
'rax': 0,
'rdx': 1,
'rcx': 2,
'rbx': 3,
'rsi': 4,
'rdi': 5,
'rbp': 6,
'rsp': 7,
'r8': 8,
'r9': 9,
'r10': 10,
'r11': 11,
'r12': 12,
'r13': 13,
'r14': 14,
'r15': 15,
'rip': 16,
'xmm0': 17,
'xmm1': 18,
'xmm2': 19,
'xmm3': 20,
'xmm4': 21,
'xmm5': 22,
'xmm6': 23,
'xmm7': 24,
'xmm8': 25,
'xmm9': 26,
'xmm10': 27,
'xmm11': 28,
'xmm12': 29,
'xmm13': 30,
'xmm14': 31,
'xmm15': 32,
'stmm0': 33,
'stmm1': 34,
'stmm2': 35,
'stmm3': 36,
'stmm4': 37,
'stmm5': 38,
'stmm6': 39,
'stmm7': 30,
'ymm0': 41,
'ymm1': 42,
'ymm2': 43,
'ymm3': 44,
'ymm4': 45,
'ymm5': 46,
'ymm6': 47,
'ymm7': 48,
'ymm8': 49,
'ymm9': 40,
'ymm10': 41,
'ymm11': 42,
'ymm12': 43,
'ymm13': 44,
'ymm14': 45,
'ymm15': 46
}
name_to_gdb_regnum = {
'rax' : 0,
'rbx' : 1,
'rcx' : 2,
'rdx' : 3,
'rsi' : 4,
'rdi' : 5,
'rbp' : 6,
'rsp' : 7,
'r8' : 8,
'r9' : 9,
'r10' : 10,
'r11' : 11,
'r12' : 12,
'r13' : 13,
'r14' : 14,
'r15' : 15,
'rip' : 16,
'rax': 0,
'rbx': 1,
'rcx': 2,
'rdx': 3,
'rsi': 4,
'rdi': 5,
'rbp': 6,
'rsp': 7,
'r8': 8,
'r9': 9,
'r10': 10,
'r11': 11,
'r12': 12,
'r13': 13,
'r14': 14,
'r15': 15,
'rip': 16,
'rflags': 17,
'cs' : 18,
'ss' : 19,
'ds' : 20,
'es' : 21,
'fs' : 22,
'gs' : 23,
'stmm0' : 24,
'stmm1' : 25,
'stmm2' : 26,
'stmm3' : 27,
'stmm4' : 28,
'stmm5' : 29,
'stmm6' : 30,
'stmm7' : 31,
'fctrl' : 32,
'fstat' : 33,
'ftag' : 34,
'fiseg' : 35,
'fioff' : 36,
'foseg' : 37,
'fooff' : 38,
'fop' : 39,
'xmm0' : 40,
'xmm1' : 41,
'xmm2' : 42,
'xmm3' : 43,
'xmm4' : 44,
'xmm5' : 45,
'xmm6' : 46,
'xmm7' : 47,
'xmm8' : 48,
'xmm9' : 49,
'xmm10' : 50,
'xmm11' : 51,
'xmm12' : 52,
'xmm13' : 53,
'xmm14' : 54,
'xmm15' : 55,
'mxcsr' : 56,
'ymm0' : 57,
'ymm1' : 58,
'ymm2' : 59,
'ymm3' : 60,
'ymm4' : 61,
'ymm5' : 62,
'ymm6' : 63,
'ymm7' : 64,
'ymm8' : 65,
'ymm9' : 66,
'ymm10' : 67,
'ymm11' : 68,
'ymm12' : 69,
'ymm13' : 70,
'ymm14' : 71,
'ymm15' : 72
};
'cs': 18,
'ss': 19,
'ds': 20,
'es': 21,
'fs': 22,
'gs': 23,
'stmm0': 24,
'stmm1': 25,
'stmm2': 26,
'stmm3': 27,
'stmm4': 28,
'stmm5': 29,
'stmm6': 30,
'stmm7': 31,
'fctrl': 32,
'fstat': 33,
'ftag': 34,
'fiseg': 35,
'fioff': 36,
'foseg': 37,
'fooff': 38,
'fop': 39,
'xmm0': 40,
'xmm1': 41,
'xmm2': 42,
'xmm3': 43,
'xmm4': 44,
'xmm5': 45,
'xmm6': 46,
'xmm7': 47,
'xmm8': 48,
'xmm9': 49,
'xmm10': 50,
'xmm11': 51,
'xmm12': 52,
'xmm13': 53,
'xmm14': 54,
'xmm15': 55,
'mxcsr': 56,
'ymm0': 57,
'ymm1': 58,
'ymm2': 59,
'ymm3': 60,
'ymm4': 61,
'ymm5': 62,
'ymm6': 63,
'ymm7': 64,
'ymm8': 65,
'ymm9': 66,
'ymm10': 67,
'ymm11': 68,
'ymm12': 69,
'ymm13': 70,
'ymm14': 71,
'ymm15': 72
}
name_to_generic_regnum = {
'rip' : LLDB_REGNUM_GENERIC_PC,
'rsp' : LLDB_REGNUM_GENERIC_SP,
'rbp' : LLDB_REGNUM_GENERIC_FP,
'rdi' : LLDB_REGNUM_GENERIC_ARG1,
'rsi' : LLDB_REGNUM_GENERIC_ARG2,
'rdx' : LLDB_REGNUM_GENERIC_ARG3,
'rcx' : LLDB_REGNUM_GENERIC_ARG4,
'r8' : LLDB_REGNUM_GENERIC_ARG5,
'r9' : LLDB_REGNUM_GENERIC_ARG6
};
'rip': LLDB_REGNUM_GENERIC_PC,
'rsp': LLDB_REGNUM_GENERIC_SP,
'rbp': LLDB_REGNUM_GENERIC_FP,
'rdi': LLDB_REGNUM_GENERIC_ARG1,
'rsi': LLDB_REGNUM_GENERIC_ARG2,
'rdx': LLDB_REGNUM_GENERIC_ARG3,
'rcx': LLDB_REGNUM_GENERIC_ARG4,
'r8': LLDB_REGNUM_GENERIC_ARG5,
'r9': LLDB_REGNUM_GENERIC_ARG6
}
def get_reg_num (reg_num_dict, reg_name):
def get_reg_num(reg_num_dict, reg_name):
if reg_name in reg_num_dict:
return reg_num_dict[reg_name]
return LLDB_INVALID_REGNUM
def get_reg_num (reg_num_dict, reg_name):
def get_reg_num(reg_num_dict, reg_name):
if reg_name in reg_num_dict:
return reg_num_dict[reg_name]
return LLDB_INVALID_REGNUM
x86_64_register_infos = [
{ 'name':'rax' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'rbx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'rcx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg4' },
{ 'name':'rdx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg3' },
{ 'name':'rsi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg2' },
{ 'name':'rdi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg1' },
{ 'name':'rbp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'fp' },
{ 'name':'rsp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'sp' },
{ 'name':'r8' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg5' },
{ 'name':'r9' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg6' },
{ 'name':'r10' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r11' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r12' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r13' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r14' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'r15' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo },
{ 'name':'rip' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'pc' },
{ 'name':'rflags', 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'cs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'ss' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'ds' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'es' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'gs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'stmm0' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm1' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm2' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm3' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm4' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm5' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm6' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'stmm7' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'fctrl' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fstat' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'ftag' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fiseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fioff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'foseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fooff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'fop' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
{ 'name':'xmm0' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm1' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm2' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm3' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm4' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm5' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm6' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm7' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm8' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm9' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm10' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm11' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm12' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm13' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm14' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'xmm15' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 },
{ 'name':'mxcsr' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex },
# Registers that are contained in or composed of one of more other registers
{ 'name':'eax' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[31:0]' },
{ 'name':'ebx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[31:0]' },
{ 'name':'ecx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[31:0]' },
{ 'name':'edx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[31:0]' },
{ 'name':'edi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[31:0]' },
{ 'name':'esi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[31:0]' },
{ 'name':'ebp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[31:0]' },
{ 'name':'esp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[31:0]' },
{ 'name':'r8d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[31:0]' },
{ 'name':'r9d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[31:0]' },
{ 'name':'r10d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[31:0]' },
{ 'name':'r11d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[31:0]' },
{ 'name':'r12d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[31:0]' },
{ 'name':'r13d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[31:0]' },
{ 'name':'r14d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[31:0]' },
{ 'name':'r15d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[31:0]' },
{'name': 'rax',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'rbx',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'rcx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg4'},
{'name': 'rdx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg3'},
{'name': 'rsi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg2'},
{'name': 'rdi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg1'},
{'name': 'rbp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'fp'},
{'name': 'rsp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'sp'},
{'name': 'r8', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg5'},
{'name': 'r9', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'arg6'},
{'name': 'r10',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r11',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r12',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r13',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r14',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'r15',
'set': 0,
'bitsize': 64,
'encoding': eEncodingUint,
'format': eFormatAddressInfo},
{'name': 'rip', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
'format': eFormatAddressInfo, 'alt-name': 'pc'},
{'name': 'rflags', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'cs', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'ss', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'ds', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'es', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fs', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'gs', 'set': 0, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'stmm0',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm1',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm2',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm3',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm4',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm5',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm6',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'stmm7',
'set': 1,
'bitsize': 80,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'fctrl', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fstat', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'ftag', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fiseg', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fioff', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'foseg', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fooff', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'fop', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
{'name': 'xmm0',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm1',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm2',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm3',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm4',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm5',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm6',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm7',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm8',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm9',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm10',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm11',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm12',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm13',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm14',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'xmm15',
'set': 1,
'bitsize': 128,
'encoding': eEncodingVector,
'format': eFormatVectorOfUInt8},
{'name': 'mxcsr', 'set': 1, 'bitsize': 32,
'encoding': eEncodingUint, 'format': eFormatHex},
# Registers that are contained in or composed of one of more other
# registers
{'name': 'eax',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[31:0]'},
{'name': 'ebx',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[31:0]'},
{'name': 'ecx',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[31:0]'},
{'name': 'edx',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[31:0]'},
{'name': 'edi',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdi[31:0]'},
{'name': 'esi',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsi[31:0]'},
{'name': 'ebp',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbp[31:0]'},
{'name': 'esp',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsp[31:0]'},
{'name': 'r8d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r8[31:0]'},
{'name': 'r9d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r9[31:0]'},
{'name': 'r10d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r10[31:0]'},
{'name': 'r11d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r11[31:0]'},
{'name': 'r12d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r12[31:0]'},
{'name': 'r13d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r13[31:0]'},
{'name': 'r14d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r14[31:0]'},
{'name': 'r15d',
'set': 0,
'bitsize': 32,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r15[31:0]'},
{ 'name':'ax' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[15:0]' },
{ 'name':'bx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:0]' },
{ 'name':'cx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:0]' },
{ 'name':'dx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:0]' },
{ 'name':'di' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[15:0]' },
{ 'name':'si' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[15:0]' },
{ 'name':'bp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[15:0]' },
{ 'name':'sp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[15:0]' },
{ 'name':'r8w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[15:0]' },
{ 'name':'r9w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[15:0]' },
{ 'name':'r10w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[15:0]' },
{ 'name':'r11w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[15:0]' },
{ 'name':'r12w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[15:0]' },
{ 'name':'r13w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[15:0]' },
{ 'name':'r14w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[15:0]' },
{ 'name':'r15w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[15:0]' },
{'name': 'ax',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[15:0]'},
{'name': 'bx',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[15:0]'},
{'name': 'cx',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[15:0]'},
{'name': 'dx',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[15:0]'},
{'name': 'di',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdi[15:0]'},
{'name': 'si',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsi[15:0]'},
{'name': 'bp',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbp[15:0]'},
{'name': 'sp',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsp[15:0]'},
{'name': 'r8w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r8[15:0]'},
{'name': 'r9w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r9[15:0]'},
{'name': 'r10w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r10[15:0]'},
{'name': 'r11w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r11[15:0]'},
{'name': 'r12w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r12[15:0]'},
{'name': 'r13w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r13[15:0]'},
{'name': 'r14w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r14[15:0]'},
{'name': 'r15w',
'set': 0,
'bitsize': 16,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r15[15:0]'},
{ 'name':'ah' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[15:8]' },
{ 'name':'bh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:8]' },
{ 'name':'ch' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:8]' },
{ 'name':'dh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:8]' },
{'name': 'ah',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[15:8]'},
{'name': 'bh',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[15:8]'},
{'name': 'ch',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[15:8]'},
{'name': 'dh',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[15:8]'},
{ 'name':'al' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[7:0]' },
{ 'name':'bl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[7:0]' },
{ 'name':'cl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[7:0]' },
{ 'name':'dl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[7:0]' },
{ 'name':'dil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[7:0]' },
{ 'name':'sil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[7:0]' },
{ 'name':'bpl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[7:0]' },
{ 'name':'spl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[7:0]' },
{ 'name':'r8l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[7:0]' },
{ 'name':'r9l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[7:0]' },
{ 'name':'r10l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[7:0]' },
{ 'name':'r11l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[7:0]' },
{ 'name':'r12l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[7:0]' },
{ 'name':'r13l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[7:0]' },
{ 'name':'r14l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[7:0]' },
{ 'name':'r15l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[7:0]' },
];
{'name': 'al',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rax[7:0]'},
{'name': 'bl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbx[7:0]'},
{'name': 'cl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rcx[7:0]'},
{'name': 'dl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdx[7:0]'},
{'name': 'dil',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rdi[7:0]'},
{'name': 'sil',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsi[7:0]'},
{'name': 'bpl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rbp[7:0]'},
{'name': 'spl',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'rsp[7:0]'},
{'name': 'r8l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r8[7:0]'},
{'name': 'r9l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r9[7:0]'},
{'name': 'r10l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r10[7:0]'},
{'name': 'r11l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r11[7:0]'},
{'name': 'r12l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r12[7:0]'},
{'name': 'r13l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r13[7:0]'},
{'name': 'r14l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r14[7:0]'},
{'name': 'r15l',
'set': 0,
'bitsize': 8,
'encoding': eEncodingUint,
'format': eFormatHex,
'slice': 'r15[7:0]'},
]
g_target_definition = None
def get_target_definition ():
def get_target_definition():
global g_target_definition
if g_target_definition == None:
if g_target_definition is None:
g_target_definition = {}
offset = 0
for reg_info in x86_64_register_infos:
reg_name = reg_info['name']
# Only fill in the offset if there is no 'slice' in the register info
# Only fill in the offset if there is no 'slice' in the register
# info
if 'slice' not in reg_info and 'composite' not in reg_info:
reg_info['offset'] = offset
offset += reg_info['bitsize']/8
offset += reg_info['bitsize'] / 8
# Set the GCC/DWARF register number for this register if it has one
reg_num = get_reg_num(name_to_gcc_dwarf_regnum, reg_name)
@ -346,12 +763,16 @@ def get_target_definition ():
if reg_num != LLDB_INVALID_REGNUM:
reg_info['gdb'] = reg_num
g_target_definition['sets'] = ['General Purpose Registers', 'Floating Point Registers']
g_target_definition['sets'] = [
'General Purpose Registers',
'Floating Point Registers']
g_target_definition['registers'] = x86_64_register_infos
g_target_definition['host-info'] = { 'triple' : 'x86_64-apple-macosx', 'endian': eByteOrderLittle }
g_target_definition[
'host-info'] = {'triple': 'x86_64-apple-macosx', 'endian': eByteOrderLittle}
g_target_definition['g-packet-size'] = offset
return g_target_definition
def get_dynamic_setting(target, setting_name):
if setting_name == 'gdb-server-target-definition':
return get_target_definition()

View File

@ -6,13 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tree_node
{
typedef struct tree_node {
const char *word;
struct tree_node *left;
struct tree_node *right;
@ -22,17 +21,15 @@ typedef struct tree_node
alphabet character and ends at the last alphabet character, i.e. it
strips off beginning or ending quotes, punctuation, etc. */
char *
strip (char **word)
{
char *strip(char **word) {
char *start = *word;
int len = strlen (start);
int len = strlen(start);
char *end = start + len - 1;
while ((start < end) && (!isalpha (start[0])))
while ((start < end) && (!isalpha(start[0])))
start++;
while ((end > start) && (!isalpha (end[0])))
while ((end > start) && (!isalpha(end[0])))
end--;
if (start > end)
@ -48,38 +45,31 @@ strip (char **word)
each node), and a new word, inserts the word at the appropriate
place in the tree. */
void
insert (tree_node *root, char *word)
{
void insert(tree_node *root, char *word) {
if (root == NULL)
return;
int compare_value = strcmp (word, root->word);
int compare_value = strcmp(word, root->word);
if (compare_value == 0)
return;
if (compare_value < 0)
{
if (compare_value < 0) {
if (root->left != NULL)
insert (root->left, word);
else
{
tree_node *new_node = (tree_node *) malloc (sizeof (tree_node));
new_node->word = strdup (word);
insert(root->left, word);
else {
tree_node *new_node = (tree_node *)malloc(sizeof(tree_node));
new_node->word = strdup(word);
new_node->left = NULL;
new_node->right = NULL;
root->left = new_node;
}
}
else
{
} else {
if (root->right != NULL)
insert (root->right, word);
else
{
tree_node *new_node = (tree_node *) malloc (sizeof (tree_node));
new_node->word = strdup (word);
insert(root->right, word);
else {
tree_node *new_node = (tree_node *)malloc(sizeof(tree_node));
new_node->word = strdup(word);
new_node->left = NULL;
new_node->right = NULL;
root->right = new_node;
@ -90,29 +80,23 @@ insert (tree_node *root, char *word)
/* Read in a text file and storea all the words from the file in a
binary search tree. */
void
populate_dictionary (tree_node **dictionary, char *filename)
{
void populate_dictionary(tree_node **dictionary, char *filename) {
FILE *in_file;
char word[1024];
in_file = fopen (filename, "r");
if (in_file)
{
while (fscanf (in_file, "%s", word) == 1)
{
char *new_word = (strdup (word));
new_word = strip (&new_word);
if (*dictionary == NULL)
{
tree_node *new_node = (tree_node *) malloc (sizeof (tree_node));
in_file = fopen(filename, "r");
if (in_file) {
while (fscanf(in_file, "%s", word) == 1) {
char *new_word = (strdup(word));
new_word = strip(&new_word);
if (*dictionary == NULL) {
tree_node *new_node = (tree_node *)malloc(sizeof(tree_node));
new_node->word = new_word;
new_node->left = NULL;
new_node->right = NULL;
*dictionary = new_node;
}
else
insert (*dictionary, new_word);
} else
insert(*dictionary, new_word);
}
}
}
@ -120,44 +104,36 @@ populate_dictionary (tree_node **dictionary, char *filename)
/* Given a binary search tree and a word, search for the word
in the binary search tree. */
int
find_word (tree_node *dictionary, char *word)
{
int find_word(tree_node *dictionary, char *word) {
if (!word || !dictionary)
return 0;
int compare_value = strcmp (word, dictionary->word);
int compare_value = strcmp(word, dictionary->word);
if (compare_value == 0)
return 1;
else if (compare_value < 0)
return find_word (dictionary->left, word);
return find_word(dictionary->left, word);
else
return find_word (dictionary->right, word);
return find_word(dictionary->right, word);
}
/* Print out the words in the binary search tree, in sorted order. */
void
print_tree (tree_node *dictionary)
{
void print_tree(tree_node *dictionary) {
if (!dictionary)
return;
if (dictionary->left)
print_tree (dictionary->left);
printf ("%s\n", dictionary->word);
print_tree(dictionary->left);
printf("%s\n", dictionary->word);
if (dictionary->right)
print_tree (dictionary->right);
print_tree(dictionary->right);
}
int
main (int argc, char **argv)
{
int main(int argc, char **argv) {
tree_node *dictionary = NULL;
char buffer[1024];
char *filename;
@ -169,32 +145,29 @@ main (int argc, char **argv)
if (!filename)
return -1;
populate_dictionary (&dictionary, filename);
fprintf (stdout, "Dictionary loaded.\nEnter search word: ");
while (!done && fgets (buffer, sizeof(buffer), stdin))
{
populate_dictionary(&dictionary, filename);
fprintf(stdout, "Dictionary loaded.\nEnter search word: ");
while (!done && fgets(buffer, sizeof(buffer), stdin)) {
char *word = buffer;
int len = strlen (word);
int len = strlen(word);
int i;
for (i = 0; i < len; ++i)
word[i] = tolower (word[i]);
word[i] = tolower(word[i]);
if ((len > 0) && (word[len-1] == '\n'))
{
word[len-1] = '\0';
if ((len > 0) && (word[len - 1] == '\n')) {
word[len - 1] = '\0';
len = len - 1;
}
if (find_word (dictionary, word))
fprintf (stdout, "Yes!\n");
if (find_word(dictionary, word))
fprintf(stdout, "Yes!\n");
else
fprintf (stdout, "No!\n");
fprintf(stdout, "No!\n");
fprintf (stdout, "Enter search word: ");
fprintf(stdout, "Enter search word: ");
}
fprintf (stdout, "\n");
fprintf(stdout, "\n");
return 0;
}

View File

@ -20,7 +20,7 @@ http://lldb.llvm.org/scripting.html
"""
def DFS (root, word, cur_path):
def DFS(root, word, cur_path):
"""
Recursively traverse a binary search tree containing
words sorted alphabetically, searching for a particular
@ -36,18 +36,18 @@ def DFS (root, word, cur_path):
# Get pointer field values out of node 'root'
root_word_ptr = root.GetChildMemberWithName ("word")
left_child_ptr = root.GetChildMemberWithName ("left")
right_child_ptr = root.GetChildMemberWithName ("right")
root_word_ptr = root.GetChildMemberWithName("word")
left_child_ptr = root.GetChildMemberWithName("left")
right_child_ptr = root.GetChildMemberWithName("right")
# Get the word out of the word pointer and strip off
# surrounding quotes (added by call to GetSummary).
root_word = root_word_ptr.GetSummary()
end = len (root_word) - 1
end = len(root_word) - 1
if root_word[0] == '"' and root_word[end] == '"':
root_word = root_word[1:end]
end = len (root_word) - 1
end = len(root_word) - 1
if root_word[0] == '\'' and root_word[end] == '\'':
root_word = root_word[1:end]
@ -59,23 +59,23 @@ def DFS (root, word, cur_path):
# Check to see if left child is NULL
if left_child_ptr.GetValue() == None:
if left_child_ptr.GetValue() is None:
return ""
else:
cur_path = cur_path + "L"
return DFS (left_child_ptr, word, cur_path)
return DFS(left_child_ptr, word, cur_path)
else:
# Check to see if right child is NULL
if right_child_ptr.GetValue() == None:
if right_child_ptr.GetValue() is None:
return ""
else:
cur_path = cur_path + "R"
return DFS (right_child_ptr, word, cur_path)
return DFS(right_child_ptr, word, cur_path)
def tree_size (root):
def tree_size(root):
"""
Recursively traverse a binary search tree, counting
the nodes in the tree. Returns the final count.
@ -84,20 +84,20 @@ def tree_size (root):
the one defined in dictionary.c It uses LLDB API
functions to examine and traverse the tree nodes.
"""
if (root.GetValue == None):
if (root.GetValue is None):
return 0
if (int (root.GetValue(), 16) == 0):
if (int(root.GetValue(), 16) == 0):
return 0
left_size = tree_size (root.GetChildAtIndex(1));
right_size = tree_size (root.GetChildAtIndex(2));
left_size = tree_size(root.GetChildAtIndex(1))
right_size = tree_size(root.GetChildAtIndex(2))
total_size = left_size + right_size + 1
return total_size
def print_tree (root):
def print_tree(root):
"""
Recursively traverse a binary search tree, printing out
the words at the nodes in alphabetical order (the
@ -107,12 +107,12 @@ def print_tree (root):
the one defined in dictionary.c It uses LLDB API
functions to examine and traverse the tree nodes.
"""
if (root.GetChildAtIndex(1).GetValue() != None) and (int (root.GetChildAtIndex(1).GetValue(), 16) != 0):
print_tree (root.GetChildAtIndex(1))
if (root.GetChildAtIndex(1).GetValue() is not None) and (
int(root.GetChildAtIndex(1).GetValue(), 16) != 0):
print_tree(root.GetChildAtIndex(1))
print root.GetChildAtIndex(0).GetSummary()
if (root.GetChildAtIndex(2).GetValue() != None) and (int (root.GetChildAtIndex(2).GetValue(), 16) != 0):
print_tree (root.GetChildAtIndex(2))
if (root.GetChildAtIndex(2).GetValue() is not None) and (
int(root.GetChildAtIndex(2).GetValue(), 16) != 0):
print_tree(root.GetChildAtIndex(2))

View File

@ -22,6 +22,8 @@ statistics.add_metric('code_notrun')
# much less functional than the other two cases below
# just runs code to get to the count and then returns
# no children
class NSArrayKVC_SynthProvider:
def adjust_for_architecture(self):
@ -29,18 +31,19 @@ class NSArrayKVC_SynthProvider:
def __init__(self, valobj, dict, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def num_children(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
num_children_vo = self.valobj.CreateValueFromExpression(
"count", "(int)[" + stream.GetData() + " count]")
if num_children_vo.IsValid():
return num_children_vo.GetValueAsUnsigned(0)
return "<variable is not NSArray>"
@ -48,6 +51,8 @@ class NSArrayKVC_SynthProvider:
# much less functional than the other two cases below
# just runs code to get to the count and then returns
# no children
class NSArrayCF_SynthProvider:
def adjust_for_architecture(self):
@ -55,95 +60,106 @@ class NSArrayCF_SynthProvider:
def __init__(self, valobj, dict, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not (self.sys_params.types_cache.ulong):
self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.ulong = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def num_children(self):
logger = lldb.formatters.Logger.Logger()
num_children_vo = self.valobj.CreateChildAtOffset("count",
self.sys_params.cfruntime_size,
self.sys_params.types_cache.ulong)
num_children_vo = self.valobj.CreateChildAtOffset(
"count", self.sys_params.cfruntime_size, self.sys_params.types_cache.ulong)
return num_children_vo.GetValueAsUnsigned(0)
class NSArrayI_SynthProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, dict, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.long):
self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
self.sys_params.types_cache.long = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeLong)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# skip the isa pointer and get at the size
def num_children(self):
logger = lldb.formatters.Logger.Logger()
count = self.valobj.CreateChildAtOffset("count",
count = self.valobj.CreateChildAtOffset(
"count",
self.sys_params.pointer_size,
self.sys_params.types_cache.long);
self.sys_params.types_cache.long)
return count.GetValueAsUnsigned(0)
class NSArrayM_SynthProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, dict, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.long):
self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
self.sys_params.types_cache.long = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeLong)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# skip the isa pointer and get at the size
def num_children(self):
logger = lldb.formatters.Logger.Logger()
count = self.valobj.CreateChildAtOffset("count",
count = self.valobj.CreateChildAtOffset(
"count",
self.sys_params.pointer_size,
self.sys_params.types_cache.long);
self.sys_params.types_cache.long)
return count.GetValueAsUnsigned(0)
# this is the actual synth provider, but is just a wrapper that checks
# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an
# appropriate backend layer to do the computations
class NSArray_SynthProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, dict):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.adjust_for_architecture()
self.error = False
self.wrapper = self.make_wrapper()
self.invalid = (self.wrapper == None)
self.invalid = (self.wrapper is None)
def num_children(self):
logger = lldb.formatters.Logger.Logger()
if self.wrapper == None:
return 0;
if self.wrapper is None:
return 0
return self.wrapper.num_children()
def update(self):
logger = lldb.formatters.Logger.Logger()
if self.wrapper == None:
if self.wrapper is None:
return
self.wrapper.update()
@ -153,10 +169,12 @@ class NSArray_SynthProvider:
logger = lldb.formatters.Logger.Logger()
if self.valobj.GetValueAsUnsigned() == 0:
self.error = True
return lldb.runtime.objc.objc_runtime.InvalidPointer_Description(True)
return lldb.runtime.objc.objc_runtime.InvalidPointer_Description(
True)
else:
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(self.valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
self.valobj, statistics)
if wrapper:
self.error = True
return wrapper
@ -166,39 +184,50 @@ class NSArray_SynthProvider:
logger >> "Class name is " + str(name_string)
if name_string == '__NSArrayI':
wrapper = NSArrayI_SynthProvider(self.valobj, dict, class_data.sys_params)
statistics.metric_hit('code_notrun',self.valobj.GetName())
wrapper = NSArrayI_SynthProvider(
self.valobj, dict, class_data.sys_params)
statistics.metric_hit('code_notrun', self.valobj.GetName())
elif name_string == '__NSArrayM':
wrapper = NSArrayM_SynthProvider(self.valobj, dict, class_data.sys_params)
statistics.metric_hit('code_notrun',self.valobj.GetName())
wrapper = NSArrayM_SynthProvider(
self.valobj, dict, class_data.sys_params)
statistics.metric_hit('code_notrun', self.valobj.GetName())
elif name_string == '__NSCFArray':
wrapper = NSArrayCF_SynthProvider(self.valobj, dict, class_data.sys_params)
statistics.metric_hit('code_notrun',self.valobj.GetName())
wrapper = NSArrayCF_SynthProvider(
self.valobj, dict, class_data.sys_params)
statistics.metric_hit('code_notrun', self.valobj.GetName())
else:
wrapper = NSArrayKVC_SynthProvider(self.valobj, dict, class_data.sys_params)
statistics.metric_hit('unknown_class',str(self.valobj.GetName()) + " seen as " + name_string)
return wrapper;
wrapper = NSArrayKVC_SynthProvider(
self.valobj, dict, class_data.sys_params)
statistics.metric_hit(
'unknown_class', str(
self.valobj.GetName()) + " seen as " + name_string)
return wrapper
def CFArray_SummaryProvider (valobj,dict):
def CFArray_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = NSArray_SynthProvider(valobj,dict);
if provider.invalid == False:
if provider.error == True:
provider = NSArray_SynthProvider(valobj, dict)
if not provider.invalid:
if provider.error:
return provider.wrapper.message()
try:
summary = int(provider.num_children());
summary = int(provider.num_children())
except:
summary = None
logger >> "provider gave me " + str(summary)
if summary == None:
if summary is None:
summary = '<variable is not NSArray>'
elif isinstance(summary,basestring):
elif isinstance(summary, basestring):
pass
else:
# we format it like it were a CFString to make it look the same as the summary from Xcode
summary = '@"' + str(summary) + (" objects" if summary != 1 else " object") + '"'
# we format it like it were a CFString to make it look the same as
# the summary from Xcode
summary = '@"' + str(summary) + \
(" objects" if summary != 1 else " object") + '"'
return summary
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")

View File

@ -22,24 +22,29 @@ statistics.add_metric('code_notrun')
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but the length for an CFBag, so they need not
# obey the interface specification for synthetic children providers
class CFBagRef_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# 12 bytes on i386
# 20 bytes on x64
@ -53,31 +58,32 @@ class CFBagRef_SummaryProvider:
def length(self):
logger = lldb.formatters.Logger.Logger()
size = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
size = self.valobj.CreateChildAtOffset(
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
return size.GetValueAsUnsigned(0)
class CFBagUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update();
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def length(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)CFBagGetCount(" + stream.GetData() + " )")
num_children_vo = self.valobj.CreateValueFromExpression(
"count", "(int)CFBagGetCount(" + stream.GetData() + " )")
if num_children_vo.IsValid():
return num_children_vo.GetValueAsUnsigned(0)
return "<variable is not CFBag>"
@ -86,14 +92,16 @@ class CFBagUnknown_SummaryProvider:
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
name_string = class_data.class_name()
actual_name = name_string
logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
logger >> "name string got was " + \
str(name_string) + " but actual name is " + str(actual_name)
if class_data.is_cftype():
# CFBag does not expose an actual NSWrapper type, so we have to check that this is
@ -106,20 +114,27 @@ def GetSummary_Impl(valobj):
if actual_name == '__CFBag' or \
actual_name == 'const struct __CFBag':
wrapper = CFBagRef_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
statistics.metric_hit('code_notrun', valobj)
return wrapper
wrapper = CFBagUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + actual_name)
return wrapper;
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
actual_name)
return wrapper
def CFBag_SummaryProvider (valobj,dict):
def CFBag_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.length();
summary = provider.length()
except:
summary = None
logger >> "summary got from provider: " + str(summary)
@ -128,9 +143,9 @@ def CFBag_SummaryProvider (valobj,dict):
# the bit mask was derived through experimentation
# (if counts start looking weird, then most probably
# the mask needs to be changed)
if summary == None:
if summary is None:
summary = '<variable is not CFBag>'
elif isinstance(summary,basestring):
elif isinstance(summary, basestring):
pass
else:
if provider.sys_params.is_64_bit:
@ -142,5 +157,7 @@ def CFBag_SummaryProvider (valobj,dict):
return summary
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F CFBag.CFBag_SummaryProvider CFBagRef CFMutableBagRef")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F CFBag.CFBag_SummaryProvider CFBagRef CFMutableBagRef")

View File

@ -22,24 +22,29 @@ statistics.add_metric('code_notrun')
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but the length for an CFBinaryHeap, so they need not
# obey the interface specification for synthetic children providers
class CFBinaryHeapRef_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# 8 bytes on i386
# 16 bytes on x64
@ -50,31 +55,32 @@ class CFBinaryHeapRef_SummaryProvider:
def length(self):
logger = lldb.formatters.Logger.Logger()
size = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
size = self.valobj.CreateChildAtOffset(
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
return size.GetValueAsUnsigned(0)
class CFBinaryHeapUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update();
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def length(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)CFBinaryHeapGetCount(" + stream.GetData() + " )");
num_children_vo = self.valobj.CreateValueFromExpression(
"count", "(int)CFBinaryHeapGetCount(" + stream.GetData() + " )")
if num_children_vo.IsValid():
return num_children_vo.GetValueAsUnsigned(0)
return '<variable is not CFBinaryHeap>'
@ -83,14 +89,16 @@ class CFBinaryHeapUnknown_SummaryProvider:
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
name_string = class_data.class_name()
actual_name = class_data.class_name()
logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
logger >> "name string got was " + \
str(name_string) + " but actual name is " + str(actual_name)
if class_data.is_cftype():
# CFBinaryHeap does not expose an actual NSWrapper type, so we have to check that this is
@ -101,21 +109,30 @@ def GetSummary_Impl(valobj):
if valobj_type.IsValid():
actual_name = valobj_type.GetName()
if actual_name == '__CFBinaryHeap':
wrapper = CFBinaryHeapRef_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
wrapper = CFBinaryHeapRef_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit('code_notrun', valobj)
return wrapper
wrapper = CFBinaryHeapUnknown_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
wrapper = CFBinaryHeapUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
def CFBinaryHeap_SummaryProvider (valobj,dict):
def CFBinaryHeap_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.length();
summary = provider.length()
except:
summary = None
logger >> "summary got from provider: " + str(summary)
@ -124,9 +141,9 @@ def CFBinaryHeap_SummaryProvider (valobj,dict):
# the bit mask was derived through experimentation
# (if counts start looking weird, then most probably
# the mask needs to be changed)
if summary == None:
if summary is None:
summary = '<variable is not CFBinaryHeap>'
elif isinstance(summary,basestring):
elif isinstance(summary, basestring):
pass
else:
if provider.sys_params.is_64_bit:
@ -138,5 +155,7 @@ def CFBinaryHeap_SummaryProvider (valobj,dict):
return summary
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F CFBinaryHeap.CFBinaryHeap_SummaryProvider CFBinaryHeapRef")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F CFBinaryHeap.CFBinaryHeap_SummaryProvider CFBinaryHeapRef")

View File

@ -13,23 +13,28 @@ import lldb.formatters.metrics
import lldb.formatters.Logger
# first define some utility functions
def byte_index(abs_pos):
logger = lldb.formatters.Logger.Logger()
return abs_pos/8
return abs_pos / 8
def bit_index(abs_pos):
logger = lldb.formatters.Logger.Logger()
return abs_pos & 7
def get_bit(byte,index):
def get_bit(byte, index):
logger = lldb.formatters.Logger.Logger()
if index < 0 or index > 7:
return None
return (byte >> (7-index)) & 1
return (byte >> (7 - index)) & 1
def grab_array_item_data(pointer,index):
def grab_array_item_data(pointer, index):
logger = lldb.formatters.Logger.Logger()
return pointer.GetPointeeData(index,1)
return pointer.GetPointeeData(index, 1)
statistics = lldb.formatters.metrics.Metrics()
statistics.add_metric('invalid_isa')
@ -40,7 +45,10 @@ statistics.add_metric('code_notrun')
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but a summary for a CF*BitVector, so they need not
# obey the interface specification for synthetic children providers
class CFBitVectorKnown_SummaryProvider:
def adjust_for_architecture(self):
logger = lldb.formatters.Logger.Logger()
self.uiint_size = self.sys_params.types_cache.NSUInteger.GetByteSize()
@ -48,20 +56,23 @@ class CFBitVectorKnown_SummaryProvider:
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
if not(self.sys_params.types_cache.charptr):
self.sys_params.types_cache.charptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()
self.update();
self.sys_params.types_cache.charptr = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeChar).GetPointerType()
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# we skip the CFRuntimeBase
# then the next CFIndex is the count
@ -70,31 +81,36 @@ class CFBitVectorKnown_SummaryProvider:
def contents(self):
logger = lldb.formatters.Logger.Logger()
count_vo = self.valobj.CreateChildAtOffset("count",self.sys_params.cfruntime_size,
count_vo = self.valobj.CreateChildAtOffset(
"count",
self.sys_params.cfruntime_size,
self.sys_params.types_cache.NSUInteger)
count = count_vo.GetValueAsUnsigned(0)
if count == 0:
return '(empty)'
array_vo = self.valobj.CreateChildAtOffset("data",
self.sys_params.cfruntime_size+2*self.uiint_size,
array_vo = self.valobj.CreateChildAtOffset(
"data",
self.sys_params.cfruntime_size +
2 *
self.uiint_size,
self.sys_params.types_cache.charptr)
data_list = []
cur_byte_pos = None
for i in range(0,count):
if cur_byte_pos == None:
for i in range(0, count):
if cur_byte_pos is None:
cur_byte_pos = byte_index(i)
cur_byte = grab_array_item_data(array_vo,cur_byte_pos)
cur_byte = grab_array_item_data(array_vo, cur_byte_pos)
cur_byte_val = cur_byte.uint8[0]
else:
byte_pos = byte_index(i)
# do not fetch the pointee data every single time through
if byte_pos != cur_byte_pos:
cur_byte_pos = byte_pos
cur_byte = grab_array_item_data(array_vo,cur_byte_pos)
cur_byte = grab_array_item_data(array_vo, cur_byte_pos)
cur_byte_val = cur_byte.uint8[0]
bit = get_bit(cur_byte_val,bit_index(i))
bit = get_bit(cur_byte_val, bit_index(i))
if (i % 4) == 0:
data_list.append(' ')
if bit == 1:
@ -105,18 +121,19 @@ class CFBitVectorKnown_SummaryProvider:
class CFBitVectorUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update();
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def contents(self):
logger = lldb.formatters.Logger.Logger()
@ -126,14 +143,16 @@ class CFBitVectorUnknown_SummaryProvider:
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
name_string = class_data.class_name()
actual_name = name_string
logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
logger >> "name string got was " + \
str(name_string) + " but actual name is " + str(actual_name)
if class_data.is_cftype():
# CFBitVectorRef does not expose an actual NSWrapper type, so we have to check that this is
@ -144,32 +163,44 @@ def GetSummary_Impl(valobj):
if valobj_type.IsValid():
actual_name = valobj_type.GetName()
if actual_name == '__CFBitVector' or actual_name == '__CFMutableBitVector':
wrapper = CFBitVectorKnown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
wrapper = CFBitVectorKnown_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit('code_notrun', valobj)
else:
wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)
wrapper = CFBitVectorUnknown_SummaryProvider(
valobj, class_data.sys_params)
print actual_name
else:
wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)
wrapper = CFBitVectorUnknown_SummaryProvider(
valobj, class_data.sys_params)
print name_string
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def CFBitVector_SummaryProvider (valobj,dict):
def CFBitVector_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.contents();
summary = provider.contents()
except:
summary = None
logger >> "summary got from provider: " + str(summary)
if summary == None or summary == '':
if summary is None or summary == '':
summary = '<variable is not CFBitVector>'
return summary
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F CFBitVector.CFBitVector_SummaryProvider CFBitVectorRef CFMutableBitVectorRef")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F CFBitVector.CFBitVector_SummaryProvider CFBitVectorRef CFMutableBitVectorRef")

View File

@ -22,24 +22,29 @@ statistics.add_metric('code_notrun')
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but the count for an NSDictionary, so they need not
# obey the interface specification for synthetic children providers
class NSCFDictionary_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# empirically determined on both 32 and 64bit desktop Mac OS X
# probably boils down to 2 pointers and 4 bytes of data, but
@ -54,30 +59,32 @@ class NSCFDictionary_SummaryProvider:
def num_children(self):
logger = lldb.formatters.Logger.Logger()
num_children_vo = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
num_children_vo = self.valobj.CreateChildAtOffset(
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
return num_children_vo.GetValueAsUnsigned(0)
class NSDictionaryI_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# we just need to skip the ISA and the count immediately follows
def offset(self):
@ -86,11 +93,10 @@ class NSDictionaryI_SummaryProvider:
def num_children(self):
logger = lldb.formatters.Logger.Logger()
num_children_vo = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
num_children_vo = self.valobj.CreateChildAtOffset(
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
value = num_children_vo.GetValueAsUnsigned(0)
if value != None:
if value is not None:
# the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
# not sure if it is a bug or some weird sort of feature, but masking that out
# gets the count right
@ -100,24 +106,28 @@ class NSDictionaryI_SummaryProvider:
value = value & ~0xFC000000
return value
class NSDictionaryM_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# we just need to skip the ISA and the count immediately follows
def offset(self):
@ -125,11 +135,10 @@ class NSDictionaryM_SummaryProvider:
def num_children(self):
logger = lldb.formatters.Logger.Logger()
num_children_vo = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
num_children_vo = self.valobj.CreateChildAtOffset(
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
value = num_children_vo.GetValueAsUnsigned(0)
if value != None:
if value is not None:
# the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
# not sure if it is a bug or some weird sort of feature, but masking that out
# gets the count right
@ -139,25 +148,28 @@ class NSDictionaryM_SummaryProvider:
value = value & ~0xFC000000
return value
class NSDictionaryUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update();
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def num_children(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
num_children_vo = self.valobj.CreateValueFromExpression(
"count", "(int)[" + stream.GetData() + " count]")
if num_children_vo.IsValid():
return num_children_vo.GetValueAsUnsigned(0)
return '<variable is not NSDictionary>'
@ -166,7 +178,8 @@ class NSDictionaryUnknown_SummaryProvider:
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
@ -176,59 +189,75 @@ def GetSummary_Impl(valobj):
if name_string == '__NSCFDictionary':
wrapper = NSCFDictionary_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
statistics.metric_hit('code_notrun', valobj)
elif name_string == '__NSDictionaryI':
wrapper = NSDictionaryI_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
statistics.metric_hit('code_notrun', valobj)
elif name_string == '__NSDictionaryM':
wrapper = NSDictionaryM_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
statistics.metric_hit('code_notrun', valobj)
else:
wrapper = NSDictionaryUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
wrapper = NSDictionaryUnknown_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def CFDictionary_SummaryProvider (valobj,dict):
def CFDictionary_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.num_children();
summary = provider.num_children()
except:
summary = None
logger >> "got summary " + str(summary)
if summary == None:
if summary is None:
return '<variable is not NSDictionary>'
if isinstance(summary,basestring):
if isinstance(summary, basestring):
return summary
return str(summary) + (" key/value pairs" if summary != 1 else " key/value pair")
return str(summary) + (" key/value pairs" if summary !=
1 else " key/value pair")
return 'Summary Unavailable'
def CFDictionary_SummaryProvider2 (valobj,dict):
def CFDictionary_SummaryProvider2(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.num_children();
summary = provider.num_children()
except:
summary = None
logger >> "got summary " + str(summary)
if summary == None:
if summary is None:
summary = '<variable is not CFDictionary>'
if isinstance(summary,basestring):
if isinstance(summary, basestring):
return summary
else:
# needed on OSX Mountain Lion
if provider.sys_params.is_64_bit:
summary = summary & ~0x0f1f000000000000
summary = '@"' + str(summary) + (' entries"' if summary != 1 else ' entry"')
summary = '@"' + str(summary) + \
(' entries"' if summary != 1 else ' entry"')
return summary
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider NSDictionary")
debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider2 CFDictionaryRef CFMutableDictionaryRef")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F CFDictionary.CFDictionary_SummaryProvider NSDictionary")
debugger.HandleCommand(
"type summary add -F CFDictionary.CFDictionary_SummaryProvider2 CFDictionaryRef CFMutableDictionaryRef")

View File

@ -11,61 +11,74 @@ import lldb
import lldb.runtime.objc.objc_runtime
import lldb.formatters.Logger
def CFString_SummaryProvider (valobj,dict):
def CFString_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = CFStringSynthProvider(valobj,dict);
if provider.invalid == False:
provider = CFStringSynthProvider(valobj, dict)
if not provider.invalid:
try:
summary = provider.get_child_at_index(provider.get_child_index("content"))
if type(summary) == lldb.SBValue:
summary = provider.get_child_at_index(
provider.get_child_index("content"))
if isinstance(summary, lldb.SBValue):
summary = summary.GetSummary()
else:
summary = '"' + summary + '"'
except:
summary = None
if summary == None:
if summary is None:
summary = '<variable is not NSString>'
return '@'+summary
return '@' + summary
return ''
def CFAttributedString_SummaryProvider (valobj,dict):
def CFAttributedString_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
offset = valobj.GetTarget().GetProcess().GetAddressByteSize()
pointee = valobj.GetValueAsUnsigned(0)
summary = '<variable is not NSAttributedString>'
if pointee != None and pointee != 0:
if pointee is not None and pointee != 0:
pointee = pointee + offset
child_ptr = valobj.CreateValueFromAddress("string_ptr",pointee,valobj.GetType())
child = child_ptr.CreateValueFromAddress("string_data",child_ptr.GetValueAsUnsigned(),valobj.GetType()).AddressOf()
provider = CFStringSynthProvider(child,dict);
if provider.invalid == False:
child_ptr = valobj.CreateValueFromAddress(
"string_ptr", pointee, valobj.GetType())
child = child_ptr.CreateValueFromAddress(
"string_data",
child_ptr.GetValueAsUnsigned(),
valobj.GetType()).AddressOf()
provider = CFStringSynthProvider(child, dict)
if not provider.invalid:
try:
summary = provider.get_child_at_index(provider.get_child_index("content")).GetSummary();
summary = provider.get_child_at_index(
provider.get_child_index("content")).GetSummary()
except:
summary = '<variable is not NSAttributedString>'
if summary == None:
if summary is None:
summary = '<variable is not NSAttributedString>'
return '@'+summary
return '@' + summary
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F CFString.CFString_SummaryProvider NSString CFStringRef CFMutableStringRef")
debugger.HandleCommand("type summary add -F CFString.CFAttributedString_SummaryProvider NSAttributedString")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F CFString.CFString_SummaryProvider NSString CFStringRef CFMutableStringRef")
debugger.HandleCommand(
"type summary add -F CFString.CFAttributedString_SummaryProvider NSAttributedString")
class CFStringSynthProvider:
def __init__(self,valobj,dict):
def __init__(self, valobj, dict):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.update()
# children other than "content" are for debugging only and must not be used in production code
# children other than "content" are for debugging only and must not be
# used in production code
def num_children(self):
logger = lldb.formatters.Logger.Logger()
if self.invalid:
return 0;
return 6;
return 0
return 6
def read_unicode(self, pointer,max_len=2048):
def read_unicode(self, pointer, max_len=2048):
logger = lldb.formatters.Logger.Logger()
process = self.valobj.GetTarget().GetProcess()
error = lldb.SBError()
@ -97,43 +110,48 @@ class CFStringSynthProvider:
# only use the custom code for the tested LP64 case
def handle_special(self):
logger = lldb.formatters.Logger.Logger()
if self.is_64_bit == False:
if not self.is_64_bit:
# for 32bit targets, use safe ObjC code
return self.handle_unicode_string_safe()
offset = 12
pointer = self.valobj.GetValueAsUnsigned(0) + offset
pystr = self.read_unicode(pointer)
return self.valobj.CreateValueFromExpression("content",
"(char*)\"" + pystr.encode('utf-8') + "\"")
return self.valobj.CreateValueFromExpression(
"content", "(char*)\"" + pystr.encode('utf-8') + "\"")
# last resort call, use ObjC code to read; the final aim is to
# be able to strip this call away entirely and only do the read
# ourselves
def handle_unicode_string_safe(self):
return self.valobj.CreateValueFromExpression("content",
"(char*)\"" + self.valobj.GetObjectDescription() + "\"");
return self.valobj.CreateValueFromExpression(
"content", "(char*)\"" + self.valobj.GetObjectDescription() + "\"")
def handle_unicode_string(self):
logger = lldb.formatters.Logger.Logger()
# step 1: find offset
if self.inline:
pointer = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base();
if self.explicit == False:
pointer = self.valobj.GetValueAsUnsigned(
0) + self.size_of_cfruntime_base()
if not self.explicit:
# untested, use the safe code path
return self.handle_unicode_string_safe();
return self.handle_unicode_string_safe()
else:
# a full pointer is skipped here before getting to the live data
# a full pointer is skipped here before getting to the live
# data
pointer = pointer + self.pointer_size
else:
pointer = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base()
pointer = self.valobj.GetValueAsUnsigned(
0) + self.size_of_cfruntime_base()
# read 8 bytes here and make an address out of them
try:
char_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()
vopointer = self.valobj.CreateValueFromAddress("dummy",pointer,char_type);
char_type = self.valobj.GetType().GetBasicType(
lldb.eBasicTypeChar).GetPointerType()
vopointer = self.valobj.CreateValueFromAddress(
"dummy", pointer, char_type)
pointer = vopointer.GetValueAsUnsigned(0)
except:
return self.valobj.CreateValueFromExpression("content",
'(char*)"@\"invalid NSString\""')
return self.valobj.CreateValueFromExpression(
"content", '(char*)"@\"invalid NSString\""')
# step 2: read Unicode data at pointer
pystr = self.read_unicode(pointer)
# step 3: return it
@ -141,55 +159,60 @@ class CFStringSynthProvider:
def handle_inline_explicit(self):
logger = lldb.formatters.Logger.Logger()
offset = 3*self.pointer_size
offset = 3 * self.pointer_size
offset = offset + self.valobj.GetValueAsUnsigned(0)
return self.valobj.CreateValueFromExpression("content",
"(char*)(" + str(offset) + ")")
return self.valobj.CreateValueFromExpression(
"content", "(char*)(" + str(offset) + ")")
def handle_mutable_string(self):
logger = lldb.formatters.Logger.Logger()
offset = 2 * self.pointer_size
data = self.valobj.CreateChildAtOffset("content",
offset, self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
data = self.valobj.CreateChildAtOffset(
"content", offset, self.valobj.GetType().GetBasicType(
lldb.eBasicTypeChar).GetPointerType())
data_value = data.GetValueAsUnsigned(0)
if self.explicit and self.unicode:
return self.read_unicode(data_value).encode('utf-8')
else:
data_value = data_value + 1
return self.valobj.CreateValueFromExpression("content", "(char*)(" + str(data_value) + ")")
return self.valobj.CreateValueFromExpression(
"content", "(char*)(" + str(data_value) + ")")
def handle_UTF8_inline(self):
logger = lldb.formatters.Logger.Logger()
offset = self.valobj.GetValueAsUnsigned(0) + self.size_of_cfruntime_base();
if self.explicit == False:
offset = offset + 1;
return self.valobj.CreateValueFromAddress("content",
offset, self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar)).AddressOf();
offset = self.valobj.GetValueAsUnsigned(
0) + self.size_of_cfruntime_base()
if not self.explicit:
offset = offset + 1
return self.valobj.CreateValueFromAddress(
"content", offset, self.valobj.GetType().GetBasicType(
lldb.eBasicTypeChar)).AddressOf()
def handle_UTF8_not_inline(self):
logger = lldb.formatters.Logger.Logger()
offset = self.size_of_cfruntime_base();
return self.valobj.CreateChildAtOffset("content",
offset,self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType());
offset = self.size_of_cfruntime_base()
return self.valobj.CreateChildAtOffset(
"content", offset, self.valobj.GetType().GetBasicType(
lldb.eBasicTypeChar).GetPointerType())
def get_child_at_index(self,index):
def get_child_at_index(self, index):
logger = lldb.formatters.Logger.Logger()
logger >> "Querying for child [" + str(index) + "]"
if index == 0:
return self.valobj.CreateValueFromExpression("mutable",
str(int(self.mutable)));
return self.valobj.CreateValueFromExpression(
"mutable", str(int(self.mutable)))
if index == 1:
return self.valobj.CreateValueFromExpression("inline",
str(int(self.inline)));
str(int(self.inline)))
if index == 2:
return self.valobj.CreateValueFromExpression("explicit",
str(int(self.explicit)));
return self.valobj.CreateValueFromExpression(
"explicit", str(int(self.explicit)))
if index == 3:
return self.valobj.CreateValueFromExpression("unicode",
str(int(self.unicode)));
return self.valobj.CreateValueFromExpression(
"unicode", str(int(self.unicode)))
if index == 4:
return self.valobj.CreateValueFromExpression("special",
str(int(self.special)));
return self.valobj.CreateValueFromExpression(
"special", str(int(self.special)))
if index == 5:
# we are handling the several possible combinations of flags.
# for each known combination we have a function that knows how to
@ -199,41 +222,41 @@ class CFStringSynthProvider:
# if this is not possible, a new flag might have to be made up (like the "special" flag
# below, which is not a real flag in CFString), or alternatively one might need to use
# the ObjC runtime helper to detect the new class and deal with it accordingly
#print 'mutable = ' + str(self.mutable)
#print 'inline = ' + str(self.inline)
#print 'explicit = ' + str(self.explicit)
#print 'unicode = ' + str(self.unicode)
#print 'special = ' + str(self.special)
if self.mutable == True:
# print 'mutable = ' + str(self.mutable)
# print 'inline = ' + str(self.inline)
# print 'explicit = ' + str(self.explicit)
# print 'unicode = ' + str(self.unicode)
# print 'special = ' + str(self.special)
if self.mutable:
return self.handle_mutable_string()
elif self.inline == True and self.explicit == True and \
elif self.inline and self.explicit and \
self.unicode == False and self.special == False and \
self.mutable == False:
return self.handle_inline_explicit()
elif self.unicode == True:
return self.handle_unicode_string();
elif self.special == True:
return self.handle_special();
elif self.inline == True:
return self.handle_UTF8_inline();
elif self.unicode:
return self.handle_unicode_string()
elif self.special:
return self.handle_special()
elif self.inline:
return self.handle_UTF8_inline()
else:
return self.handle_UTF8_not_inline();
return self.handle_UTF8_not_inline()
def get_child_index(self,name):
def get_child_index(self, name):
logger = lldb.formatters.Logger.Logger()
logger >> "Querying for child ['" + str(name) + "']"
if name == "content":
return self.num_children() - 1;
return self.num_children() - 1
if name == "mutable":
return 0;
return 0
if name == "inline":
return 1;
return 1
if name == "explicit":
return 2;
return 2
if name == "unicode":
return 3;
return 3
if name == "special":
return 4;
return 4
# CFRuntimeBase is defined as having an additional
# 4 bytes (padding?) on LP64 architectures
@ -241,7 +264,7 @@ class CFStringSynthProvider:
# and then add 4 more bytes if we are on a 64bit system
def size_of_cfruntime_base(self):
logger = lldb.formatters.Logger.Logger()
return self.pointer_size+4+(4 if self.is_64_bit else 0)
return self.pointer_size + 4 + (4 if self.is_64_bit else 0)
# the info bits are part of the CFRuntimeBase structure
# to get at them we have to skip a uintptr_t and then get
@ -251,40 +274,42 @@ class CFStringSynthProvider:
def offset_of_info_bits(self):
logger = lldb.formatters.Logger.Logger()
offset = self.pointer_size
if self.is_little == False:
offset = offset + 3;
return offset;
if not self.is_little:
offset = offset + 3
return offset
def read_info_bits(self):
logger = lldb.formatters.Logger.Logger()
cfinfo = self.valobj.CreateChildAtOffset("cfinfo",
cfinfo = self.valobj.CreateChildAtOffset(
"cfinfo",
self.offset_of_info_bits(),
self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
self.valobj.GetType().GetBasicType(
lldb.eBasicTypeChar))
cfinfo.SetFormat(11)
info = cfinfo.GetValue();
if info != None:
self.invalid = False;
return int(info,0);
info = cfinfo.GetValue()
if info is not None:
self.invalid = False
return int(info, 0)
else:
self.invalid = True;
return None;
self.invalid = True
return None
# calculating internal flag bits of the CFString object
# this stuff is defined and discussed in CFString.c
def is_mutable(self):
logger = lldb.formatters.Logger.Logger()
return (self.info_bits & 1) == 1;
return (self.info_bits & 1) == 1
def is_inline(self):
logger = lldb.formatters.Logger.Logger()
return (self.info_bits & 0x60) == 0;
return (self.info_bits & 0x60) == 0
# this flag's name is ambiguous, it turns out
# we must skip a length byte to get at the data
# when this flag is False
def has_explicit_length(self):
logger = lldb.formatters.Logger.Logger()
return (self.info_bits & (1 | 4)) != 4;
return (self.info_bits & (1 | 4)) != 4
# probably a subclass of NSString. obtained this from [str pathExtension]
# here info_bits = 0 and Unicode data at the start of the padding word
@ -292,11 +317,11 @@ class CFStringSynthProvider:
# instead of reading the info_bits
def is_special_case(self):
logger = lldb.formatters.Logger.Logger()
return self.info_bits == 0;
return self.info_bits == 0
def is_unicode(self):
logger = lldb.formatters.Logger.Logger()
return (self.info_bits & 0x10) == 0x10;
return (self.info_bits & 0x10) == 0x10
# preparing ourselves to read into memory
# by adjusting architecture-specific info
@ -304,22 +329,23 @@ class CFStringSynthProvider:
logger = lldb.formatters.Logger.Logger()
self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize()
self.is_64_bit = self.pointer_size == 8
self.is_little = self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle
self.is_little = self.valobj.GetTarget().GetProcess(
).GetByteOrder() == lldb.eByteOrderLittle
# reading info bits out of the CFString and computing
# useful values to get at the real data
def compute_flags(self):
logger = lldb.formatters.Logger.Logger()
self.info_bits = self.read_info_bits();
if self.info_bits == None:
return;
self.mutable = self.is_mutable();
self.inline = self.is_inline();
self.explicit = self.has_explicit_length();
self.unicode = self.is_unicode();
self.special = self.is_special_case();
self.info_bits = self.read_info_bits()
if self.info_bits is None:
return
self.mutable = self.is_mutable()
self.inline = self.is_inline()
self.explicit = self.has_explicit_length()
self.unicode = self.is_unicode()
self.special = self.is_special_case()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.compute_flags();
self.adjust_for_architecture()
self.compute_flags()

View File

@ -9,13 +9,14 @@ import lldb
import lldb.runtime.objc.objc_runtime
import lldb.formatters.Logger
def Class_Summary(valobj,dict):
def Class_Summary(valobj, dict):
logger = lldb.formatters.Logger.Logger()
runtime =lldb.runtime.objc.objc_runtime.ObjCRuntime.runtime_from_isa(valobj)
if runtime == None or not runtime.is_valid():
runtime = lldb.runtime.objc.objc_runtime.ObjCRuntime.runtime_from_isa(
valobj)
if runtime is None or not runtime.is_valid():
return '<error: unknown Class>'
class_data = runtime.read_class_data()
if class_data == None or not class_data.is_valid():
if class_data is None or not class_data.is_valid():
return '<error: unknown Class>'
return class_data.class_name()

View File

@ -3,11 +3,13 @@ import sys
import os.path
import inspect
class NopLogger:
def __init__(self):
pass
def write(self,data):
def write(self, data):
pass
def flush(self):
@ -18,10 +20,11 @@ class NopLogger:
class StdoutLogger:
def __init__(self):
pass
def write(self,data):
def write(self, data):
print(data)
def flush(self):
@ -30,30 +33,32 @@ class StdoutLogger:
def close(self):
pass
class FileLogger:
def __init__(self, name):
self.file = None
try:
name = os.path.abspath(name)
self.file = open(name,'a')
self.file = open(name, 'a')
except:
try:
self.file = open('formatters.log','a')
self.file = open('formatters.log', 'a')
except:
pass
def write(self,data):
if self.file != None:
print(data,file=self.file)
def write(self, data):
if self.file is not None:
print(data, file=self.file)
else:
print(data)
def flush(self):
if self.file != None:
if self.file is not None:
self.file.flush()
def close(self):
if self.file != None:
if self.file is not None:
self.file.close()
self.file = None
@ -61,9 +66,14 @@ class FileLogger:
# define lldb.formatters.Logger._lldb_formatters_debug_level to any number greater than 0
# if you define it to any value greater than 1, the log will be automatically flushed after each write (slower but should make sure most of the stuff makes it to the log even if we crash)
# if you define it to any value greater than 2, the calling function's details will automatically be logged (even slower, but provides additional details)
# if you need the log to go to a file instead of on screen, define lldb.formatters.Logger._lldb_formatters_debug_filename to a valid filename
# if you need the log to go to a file instead of on screen, define
# lldb.formatters.Logger._lldb_formatters_debug_filename to a valid
# filename
class Logger:
def __init__(self,autoflush=False,logcaller=False):
def __init__(self, autoflush=False, logcaller=False):
global _lldb_formatters_debug_level
global _lldb_formatters_debug_filename
self.autoflush = autoflush
@ -77,7 +87,8 @@ class Logger:
return
want_file = False
try:
want_file = (_lldb_formatters_debug_filename != None and _lldb_formatters_debug_filename != '' and _lldb_formatters_debug_filename != 0)
want_file = (_lldb_formatters_debug_filename is not None and _lldb_formatters_debug_filename !=
'' and _lldb_formatters_debug_filename != 0)
except:
pass
if want_file:
@ -99,19 +110,20 @@ class Logger:
def _log_caller(self):
caller = inspect.stack()[2]
try:
if caller != None and len(caller) > 3:
if caller is not None and len(caller) > 3:
self.write('Logging from function ' + str(caller))
else:
self.write('Caller info not available - Required caller logging not possible')
self.write(
'Caller info not available - Required caller logging not possible')
finally:
del caller # needed per Python docs to avoid keeping objects alive longer than we care
def write(self,data):
def write(self, data):
self.impl.write(data)
if self.autoflush:
self.flush()
def __rshift__(self,data):
def __rshift__(self, data):
self.write(data)
def flush(self):
@ -119,4 +131,3 @@ class Logger:
def close(self):
self.impl.close()

View File

@ -23,21 +23,25 @@ statistics.add_metric('code_notrun')
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but a summary for an NSURL, so they need not
# obey the interface specification for synthetic children providers
class NSBundleKnown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSString):
self.sys_params.types_cache.NSString = self.valobj.GetTarget().FindFirstType('NSString').GetPointerType()
self.update();
self.sys_params.types_cache.NSString = self.valobj.GetTarget(
).FindFirstType('NSString').GetPointerType()
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# we need to skip the ISA, plus four other values
# that are luckily each a pointer in size
@ -49,38 +53,41 @@ class NSBundleKnown_SummaryProvider:
def url_text(self):
logger = lldb.formatters.Logger.Logger()
global statistics
text = self.valobj.CreateChildAtOffset("text",
self.offset(),
self.sys_params.types_cache.NSString)
text = self.valobj.CreateChildAtOffset(
"text", self.offset(), self.sys_params.types_cache.NSString)
my_string = text.GetSummary()
if (my_string == None) or (my_string == ''):
statistics.metric_hit('unknown_class',str(self.valobj.GetName()) + " triggered unknown pointer location")
return NSBundleUnknown_SummaryProvider(self.valobj, self.sys_params).url_text()
if (my_string is None) or (my_string == ''):
statistics.metric_hit(
'unknown_class', str(
self.valobj.GetName()) + " triggered unknown pointer location")
return NSBundleUnknown_SummaryProvider(
self.valobj, self.sys_params).url_text()
else:
statistics.metric_hit('code_notrun',self.valobj)
statistics.metric_hit('code_notrun', self.valobj)
return my_string
class NSBundleUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def url_text(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
expr = "(NSString*)[" + stream.GetData() + " bundlePath]"
url_text_vo = self.valobj.CreateValueFromExpression("path",expr);
url_text_vo = self.valobj.CreateValueFromExpression("path", expr)
if url_text_vo.IsValid():
return url_text_vo.GetSummary()
return '<variable is not NSBundle>'
@ -89,7 +96,8 @@ class NSBundleUnknown_SummaryProvider:
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
@ -101,27 +109,37 @@ def GetSummary_Impl(valobj):
# [NSBundle mainBundle] does return an object that is
# not correctly filled out for our purposes, so we still
# end up having to run code in that case
#statistics.metric_hit('code_notrun',valobj)
# statistics.metric_hit('code_notrun',valobj)
else:
wrapper = NSBundleUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
wrapper = NSBundleUnknown_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def NSBundle_SummaryProvider (valobj,dict):
def NSBundle_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.url_text();
summary = provider.url_text()
except:
summary = None
logger >> "got summary " + str(summary)
if summary == None or summary == '':
if summary is None or summary == '':
summary = '<variable is not NSBundle>'
return summary
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F NSBundle.NSBundle_SummaryProvider NSBundle")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F NSBundle.NSBundle_SummaryProvider NSBundle")

View File

@ -22,24 +22,29 @@ statistics.add_metric('code_notrun')
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but the length for an NSData, so they need not
# obey the interface specification for synthetic children providers
class NSConcreteData_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
logger >> "NSConcreteData_SummaryProvider __init__"
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update()
def update(self):
self.adjust_for_architecture();
self.adjust_for_architecture()
# one pointer is the ISA
# then there are 32 bit worth of flags and other data
@ -52,27 +57,27 @@ class NSConcreteData_SummaryProvider:
def length(self):
logger = lldb.formatters.Logger.Logger()
logger >> "NSConcreteData_SummaryProvider length"
size = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
size = self.valobj.CreateChildAtOffset(
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
logger >> str(size)
logger >> str(size.GetValueAsUnsigned(0))
return size.GetValueAsUnsigned(0)
class NSDataUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
logger >> "NSDataUnknown_SummaryProvider __init__"
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update();
self.update()
def update(self):
self.adjust_for_architecture();
self.adjust_for_architecture()
def length(self):
logger = lldb.formatters.Logger.Logger()
@ -80,10 +85,12 @@ class NSDataUnknown_SummaryProvider:
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
logger >> stream.GetData()
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " length]");
num_children_vo = self.valobj.CreateValueFromExpression(
"count", "(int)[" + stream.GetData() + " length]")
logger >> "still in after expression: " + str(num_children_vo)
if num_children_vo.IsValid():
logger >> "wow - expr output is valid: " + str(num_children_vo.GetValueAsUnsigned())
logger >> "wow - expr output is valid: " + \
str(num_children_vo.GetValueAsUnsigned())
return num_children_vo.GetValueAsUnsigned(0)
logger >> "invalid expr output - too bad"
return '<variable is not NSData>'
@ -93,7 +100,8 @@ def GetSummary_Impl(valobj):
global statistics
logger = lldb.formatters.Logger.Logger()
logger >> "NSData GetSummary_Impl"
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
logger >> "got a wrapper summary - using it"
return wrapper
@ -104,26 +112,31 @@ def GetSummary_Impl(valobj):
name_string == 'NSConcreteMutableData' or \
name_string == '__NSCFData':
wrapper = NSConcreteData_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
statistics.metric_hit('code_notrun', valobj)
else:
wrapper = NSDataUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def NSData_SummaryProvider (valobj,dict):
def NSData_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
logger >> "NSData_SummaryProvider"
provider = GetSummary_Impl(valobj);
provider = GetSummary_Impl(valobj)
logger >> "found a summary provider, it is: " + str(provider)
if provider != None:
if provider is not None:
try:
summary = provider.length();
summary = provider.length()
except:
summary = None
logger >> "got a summary: it is " + str(summary)
if summary == None:
if summary is None:
summary = '<variable is not NSData>'
elif isinstance(summary,basestring):
elif isinstance(summary, basestring):
pass
else:
if summary == 1:
@ -133,22 +146,25 @@ def NSData_SummaryProvider (valobj,dict):
return summary
return 'Summary Unavailable'
def NSData_SummaryProvider2 (valobj,dict):
def NSData_SummaryProvider2(valobj, dict):
logger = lldb.formatters.Logger.Logger()
logger >> "NSData_SummaryProvider2"
provider = GetSummary_Impl(valobj);
provider = GetSummary_Impl(valobj)
logger >> "found a summary provider, it is: " + str(provider)
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.length();
summary = provider.length()
except:
summary = None
logger >> "got a summary: it is " + str(summary)
if summary == None:
if summary is None:
summary = '<variable is not CFData>'
elif isinstance(summary,basestring):
elif isinstance(summary, basestring):
pass
else:
if summary == 1:
@ -158,6 +174,9 @@ def NSData_SummaryProvider2 (valobj,dict):
return summary
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F NSData.NSData_SummaryProvider NSData")
debugger.HandleCommand("type summary add -F NSData.NSData_SummaryProvider2 CFDataRef CFMutableDataRef")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F NSData.NSData_SummaryProvider NSData")
debugger.HandleCommand(
"type summary add -F NSData.NSData_SummaryProvider2 CFDataRef CFMutableDataRef")

View File

@ -27,14 +27,16 @@ statistics.add_metric('code_notrun')
# hence, all we need to know is the epoch year
python_epoch = time.gmtime(0).tm_year
osx_epoch = datetime.date(2001,1,1).timetuple()
osx_epoch = datetime.date(2001, 1, 1).timetuple()
def mkgmtime(t):
logger = lldb.formatters.Logger.Logger()
return time.mktime(t)-time.timezone
return time.mktime(t) - time.timezone
osx_epoch = mkgmtime(osx_epoch)
def osx_to_python_time(osx):
logger = lldb.formatters.Logger.Logger()
if python_epoch <= 2001:
@ -43,11 +45,15 @@ def osx_to_python_time(osx):
return osx - osx_epoch
# represent a struct_time as a string in the format used by Xcode
def xcode_format_time(X):
logger = lldb.formatters.Logger.Logger()
return time.strftime('%Y-%m-%d %H:%M:%S %Z',X)
return time.strftime('%Y-%m-%d %H:%M:%S %Z', X)
# represent a count-since-epoch as a string in the format used by Xcode
def xcode_format_count(X):
logger = lldb.formatters.Logger.Logger()
return xcode_format_time(time.localtime(X))
@ -55,22 +61,25 @@ def xcode_format_count(X):
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but the summary for NSDate, so they need not
# obey the interface specification for synthetic children providers
class NSTaggedDate_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, info_bits, data, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update();
self.update()
# NSDate is not using its info_bits for info like NSNumber is
# so we need to regroup info_bits and data
self.data = ((data << 8) | (info_bits << 4))
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def value(self):
logger = lldb.formatters.Logger.Logger()
@ -85,20 +94,22 @@ class NSTaggedDate_SummaryProvider:
class NSUntaggedDate_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not (self.sys_params.types_cache.double):
self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
self.sys_params.types_cache.double = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeDouble)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def offset(self):
logger = lldb.formatters.Logger.Logger()
@ -106,57 +117,65 @@ class NSUntaggedDate_SummaryProvider:
def value(self):
logger = lldb.formatters.Logger.Logger()
value = self.valobj.CreateChildAtOffset("value",
self.offset(),
self.sys_params.types_cache.double)
value_double = struct.unpack('d', struct.pack('Q', value.GetData().uint64[0]))[0]
value = self.valobj.CreateChildAtOffset(
"value", self.offset(), self.sys_params.types_cache.double)
value_double = struct.unpack(
'd', struct.pack(
'Q', value.GetData().uint64[0]))[0]
if value_double == -63114076800.0:
return '0001-12-30 00:00:00 +0000'
return xcode_format_count(osx_to_python_time(value_double))
class NSCalendarDate_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not (self.sys_params.types_cache.double):
self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
self.sys_params.types_cache.double = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeDouble)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def offset(self):
logger = lldb.formatters.Logger.Logger()
return 2*self.sys_params.pointer_size
return 2 * self.sys_params.pointer_size
def value(self):
logger = lldb.formatters.Logger.Logger()
value = self.valobj.CreateChildAtOffset("value",
self.offset(),
self.sys_params.types_cache.double)
value_double = struct.unpack('d', struct.pack('Q', value.GetData().uint64[0]))[0]
value = self.valobj.CreateChildAtOffset(
"value", self.offset(), self.sys_params.types_cache.double)
value_double = struct.unpack(
'd', struct.pack(
'Q', value.GetData().uint64[0]))[0]
return xcode_format_count(osx_to_python_time(value_double))
class NSTimeZoneClass_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not (self.sys_params.types_cache.voidptr):
self.sys_params.types_cache.voidptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType()
self.sys_params.types_cache.voidptr = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeVoid).GetPointerType()
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def offset(self):
logger = lldb.formatters.Logger.Logger()
@ -164,38 +183,41 @@ class NSTimeZoneClass_SummaryProvider:
def timezone(self):
logger = lldb.formatters.Logger.Logger()
tz_string = self.valobj.CreateChildAtOffset("tz_name",
self.offset(),
self.sys_params.types_cache.voidptr)
return CFString.CFString_SummaryProvider(tz_string,None)
tz_string = self.valobj.CreateChildAtOffset(
"tz_name", self.offset(), self.sys_params.types_cache.voidptr)
return CFString.CFString_SummaryProvider(tz_string, None)
class NSUnknownDate_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def value(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
expr = "(NSString*)[" + stream.GetData() + " description]"
num_children_vo = self.valobj.CreateValueFromExpression("str",expr);
num_children_vo = self.valobj.CreateValueFromExpression("str", expr)
if num_children_vo.IsValid():
return num_children_vo.GetSummary()
return '<variable is not NSDate>'
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
@ -204,66 +226,82 @@ def GetSummary_Impl(valobj):
if name_string == 'NSDate' or name_string == '__NSDate' or name_string == '__NSTaggedDate':
if class_data.is_tagged():
wrapper = NSTaggedDate_SummaryProvider(valobj,class_data.info_bits(),class_data.value(), class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
wrapper = NSTaggedDate_SummaryProvider(
valobj, class_data.info_bits(), class_data.value(), class_data.sys_params)
statistics.metric_hit('code_notrun', valobj)
else:
wrapper = NSUntaggedDate_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
wrapper = NSUntaggedDate_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit('code_notrun', valobj)
elif name_string == 'NSCalendarDate':
wrapper = NSCalendarDate_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
statistics.metric_hit('code_notrun', valobj)
elif name_string == '__NSTimeZone':
wrapper = NSTimeZoneClass_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
wrapper = NSTimeZoneClass_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit('code_notrun', valobj)
else:
wrapper = NSUnknownDate_SummaryProvider(valobj)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def NSDate_SummaryProvider (valobj,dict):
def NSDate_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.value();
summary = provider.value()
except:
summary = None
if summary == None:
if summary is None:
summary = '<variable is not NSDate>'
return str(summary)
return 'Summary Unavailable'
def NSTimeZone_SummaryProvider (valobj,dict):
def NSTimeZone_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.timezone();
summary = provider.timezone()
except:
summary = None
logger >> "got summary " + str(summary)
if summary == None:
if summary is None:
summary = '<variable is not NSTimeZone>'
return str(summary)
return 'Summary Unavailable'
def CFAbsoluteTime_SummaryProvider (valobj,dict):
def CFAbsoluteTime_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
try:
value_double = struct.unpack('d', struct.pack('Q', valobj.GetData().uint64[0]))[0]
value_double = struct.unpack(
'd', struct.pack(
'Q', valobj.GetData().uint64[0]))[0]
return xcode_format_count(osx_to_python_time(value_double))
except:
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F NSDate.NSDate_SummaryProvider NSDate")
debugger.HandleCommand("type summary add -F NSDate.CFAbsoluteTime_SummaryProvider CFAbsoluteTime")
debugger.HandleCommand("type summary add -F NSDate.NSTimeZone_SummaryProvider NSTimeZone CFTimeZoneRef")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F NSDate.NSDate_SummaryProvider NSDate")
debugger.HandleCommand(
"type summary add -F NSDate.CFAbsoluteTime_SummaryProvider CFAbsoluteTime")
debugger.HandleCommand(
"type summary add -F NSDate.NSTimeZone_SummaryProvider NSTimeZone CFTimeZoneRef")

View File

@ -18,68 +18,77 @@ statistics.add_metric('invalid_pointer')
statistics.add_metric('unknown_class')
statistics.add_metric('code_notrun')
class NSKnownException_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not (self.sys_params.types_cache.id):
self.sys_params.types_cache.id = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
self.update();
self.sys_params.types_cache.id = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeObjCID)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def offset_name(self):
logger = lldb.formatters.Logger.Logger()
return self.sys_params.pointer_size
def offset_reason(self):
logger = lldb.formatters.Logger.Logger()
return 2*self.sys_params.pointer_size
return 2 * self.sys_params.pointer_size
def description(self):
logger = lldb.formatters.Logger.Logger()
name_ptr = self.valobj.CreateChildAtOffset("name",
self.offset_name(),
self.sys_params.types_cache.id)
reason_ptr = self.valobj.CreateChildAtOffset("reason",
self.offset_reason(),
self.sys_params.types_cache.id)
return 'name:' + CFString.CFString_SummaryProvider(name_ptr,None) + ' reason:' + CFString.CFString_SummaryProvider(reason_ptr,None)
name_ptr = self.valobj.CreateChildAtOffset(
"name", self.offset_name(), self.sys_params.types_cache.id)
reason_ptr = self.valobj.CreateChildAtOffset(
"reason", self.offset_reason(), self.sys_params.types_cache.id)
return 'name:' + CFString.CFString_SummaryProvider(
name_ptr, None) + ' reason:' + CFString.CFString_SummaryProvider(reason_ptr, None)
class NSUnknownException_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update();
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def description(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
name_vo = self.valobj.CreateValueFromExpression("name","(NSString*)[" + stream.GetData() + " name]");
reason_vo = self.valobj.CreateValueFromExpression("reason","(NSString*)[" + stream.GetData() + " reason]");
name_vo = self.valobj.CreateValueFromExpression(
"name", "(NSString*)[" + stream.GetData() + " name]")
reason_vo = self.valobj.CreateValueFromExpression(
"reason", "(NSString*)[" + stream.GetData() + " reason]")
if name_vo.IsValid() and reason_vo.IsValid():
return CFString.CFString_SummaryProvider(name_vo,None) + ' ' + CFString.CFString_SummaryProvider(reason_vo,None)
return CFString.CFString_SummaryProvider(
name_vo, None) + ' ' + CFString.CFString_SummaryProvider(reason_vo, None)
return '<variable is not NSException>'
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
@ -87,28 +96,39 @@ def GetSummary_Impl(valobj):
logger >> "class name is: " + str(name_string)
if name_string == 'NSException':
wrapper = NSKnownException_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
wrapper = NSKnownException_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit('code_notrun', valobj)
else:
wrapper = NSUnknownException_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
wrapper = NSUnknownException_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def NSException_SummaryProvider (valobj,dict):
def NSException_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.description();
summary = provider.description()
except:
summary = None
logger >> "got summary " + str(summary)
if summary == None:
if summary is None:
summary = '<variable is not NSException>'
return str(summary)
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F NSException.NSException_SummaryProvider NSException")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F NSException.NSException_SummaryProvider NSException")

View File

@ -22,37 +22,47 @@ statistics.add_metric('code_notrun')
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but the count of values for an NSIndexSet, so they need not
# obey the interface specification for synthetic children providers
class NSIndexSetClass_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.uint32 = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.uint32 = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.sys_params.types_cache.uint32 = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.sys_params.types_cache.uint32 = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
if not(self.sys_params.types_cache.uint32):
self.sys_params.types_cache.uint32 = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
self.sys_params.types_cache.uint32 = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# NS(Mutable)IndexSet works in one of two modes: when having a compact block of data (e.g. a Range)
# the count is stored in the set itself, 3 pointers into it
# otherwise, it will store a pointer to an additional data structure (2 pointers into itself) and this
# additional structure will contain the count two pointers deep
# a bunch of flags allow us to detect an empty set, vs. a one-range set, vs. a multi-range set
# a bunch of flags allow us to detect an empty set, vs. a one-range set,
# vs. a multi-range set
def count(self):
logger = lldb.formatters.Logger.Logger()
mode_chooser_vo = self.valobj.CreateChildAtOffset("mode_chooser",
mode_chooser_vo = self.valobj.CreateChildAtOffset(
"mode_chooser",
self.sys_params.pointer_size,
self.sys_params.types_cache.uint32)
mode_chooser = mode_chooser_vo.GetValueAsUnsigned(0)
@ -68,39 +78,45 @@ class NSIndexSetClass_SummaryProvider:
else:
mode = 2
if mode == 1:
count_vo = self.valobj.CreateChildAtOffset("count",
3*self.sys_params.pointer_size,
count_vo = self.valobj.CreateChildAtOffset(
"count",
3 * self.sys_params.pointer_size,
self.sys_params.types_cache.NSUInteger)
else:
count_ptr = self.valobj.CreateChildAtOffset("count_ptr",
2*self.sys_params.pointer_size,
count_ptr = self.valobj.CreateChildAtOffset(
"count_ptr",
2 * self.sys_params.pointer_size,
self.sys_params.types_cache.NSUInteger)
count_vo = self.valobj.CreateValueFromAddress("count",
count_ptr.GetValueAsUnsigned()+2*self.sys_params.pointer_size,
count_vo = self.valobj.CreateValueFromAddress(
"count",
count_ptr.GetValueAsUnsigned() +
2 *
self.sys_params.pointer_size,
self.sys_params.types_cache.NSUInteger)
return count_vo.GetValueAsUnsigned(0)
class NSIndexSetUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update();
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def count(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
expr = "(int)[" + stream.GetData() + " count]"
num_children_vo = self.valobj.CreateValueFromExpression("count",expr)
num_children_vo = self.valobj.CreateValueFromExpression("count", expr)
if num_children_vo.IsValid():
return num_children_vo.GetValueAsUnsigned(0)
return '<variable is not NSIndexSet>'
@ -109,7 +125,8 @@ class NSIndexSetUnknown_SummaryProvider:
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
@ -117,26 +134,34 @@ def GetSummary_Impl(valobj):
logger >> "class name is: " + str(name_string)
if name_string == 'NSIndexSet' or name_string == 'NSMutableIndexSet':
wrapper = NSIndexSetClass_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
wrapper = NSIndexSetClass_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit('code_notrun', valobj)
else:
wrapper = NSIndexSetUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
wrapper = NSIndexSetUnknown_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def NSIndexSet_SummaryProvider (valobj,dict):
def NSIndexSet_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.count();
summary = provider.count()
except:
summary = None
logger >> "got summary " + str(summary)
if summary == None:
if summary is None:
summary = '<variable is not NSIndexSet>'
if isinstance(summary, basestring):
return summary
@ -146,5 +171,6 @@ def NSIndexSet_SummaryProvider (valobj,dict):
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F NSIndexSet.NSIndexSet_SummaryProvider NSIndexSet NSMutableIndexSet")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F NSIndexSet.NSIndexSet_SummaryProvider NSIndexSet NSMutableIndexSet")

View File

@ -22,24 +22,29 @@ statistics.add_metric('code_notrun')
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but the port number of an NSMachPort, so they need not
# obey the interface specification for synthetic children providers
class NSMachPortKnown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# one pointer is the ISA
# then we have one other internal pointer, plus
@ -53,31 +58,32 @@ class NSMachPortKnown_SummaryProvider:
def port(self):
logger = lldb.formatters.Logger.Logger()
vport = self.valobj.CreateChildAtOffset("port",
self.offset(),
self.sys_params.types_cache.NSUInteger)
vport = self.valobj.CreateChildAtOffset(
"port", self.offset(), self.sys_params.types_cache.NSUInteger)
return vport.GetValueAsUnsigned(0)
class NSMachPortUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update();
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def port(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
num_children_vo = self.valobj.CreateValueFromExpression("port","(int)[" + stream.GetData() + " machPort]")
num_children_vo = self.valobj.CreateValueFromExpression(
"port", "(int)[" + stream.GetData() + " machPort]")
if num_children_vo.IsValid():
return num_children_vo.GetValueAsUnsigned(0)
return '<variable is not NSMachPort>'
@ -86,7 +92,8 @@ class NSMachPortUnknown_SummaryProvider:
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
@ -94,30 +101,41 @@ def GetSummary_Impl(valobj):
logger >> "class name is: " + str(name_string)
if name_string == 'NSMachPort':
wrapper = NSMachPortKnown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
wrapper = NSMachPortKnown_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit('code_notrun', valobj)
else:
wrapper = NSMachPortUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
wrapper = NSMachPortUnknown_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def NSMachPort_SummaryProvider (valobj,dict):
def NSMachPort_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.port();
summary = provider.port()
except:
summary = None
logger >> "got summary " + str(summary)
if summary == None:
if summary is None:
summary = '<variable is not NSMachPort>'
if isinstance(summary, basestring):
return summay
return 'mach port: ' + str(summary)
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F NSMachPort.NSMachPort_SummaryProvider NSMachPort")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F NSMachPort.NSMachPort_SummaryProvider NSMachPort")

View File

@ -19,21 +19,24 @@ statistics.add_metric('invalid_pointer')
statistics.add_metric('unknown_class')
statistics.add_metric('code_notrun')
class NSConcreteNotification_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not (self.sys_params.types_cache.id):
self.sys_params.types_cache.id = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
self.update();
self.sys_params.types_cache.id = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeObjCID)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# skip the ISA and go to the name pointer
def offset(self):
@ -42,40 +45,42 @@ class NSConcreteNotification_SummaryProvider:
def name(self):
logger = lldb.formatters.Logger.Logger()
string_ptr = self.valobj.CreateChildAtOffset("name",
self.offset(),
self.sys_params.types_cache.id)
return CFString.CFString_SummaryProvider(string_ptr,None)
string_ptr = self.valobj.CreateChildAtOffset(
"name", self.offset(), self.sys_params.types_cache.id)
return CFString.CFString_SummaryProvider(string_ptr, None)
class NSNotificationUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def name(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
name_vo = self.valobj.CreateValueFromExpression("name","(NSString*)[" + stream.GetData() + " name]")
name_vo = self.valobj.CreateValueFromExpression(
"name", "(NSString*)[" + stream.GetData() + " name]")
if name_vo.IsValid():
return CFString.CFString_SummaryProvider(name_vo,None)
return CFString.CFString_SummaryProvider(name_vo, None)
return '<variable is not NSNotification>'
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
@ -83,28 +88,39 @@ def GetSummary_Impl(valobj):
logger >> "class name is: " + str(name_string)
if name_string == 'NSConcreteNotification':
wrapper = NSConcreteNotification_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
wrapper = NSConcreteNotification_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit('code_notrun', valobj)
else:
wrapper = NSNotificationUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
wrapper = NSNotificationUnknown_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def NSNotification_SummaryProvider (valobj,dict):
def NSNotification_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.name();
summary = provider.name()
except:
summary = None
logger >> "got summary " + str(summary)
if summary == None:
if summary is None:
summary = '<variable is not NSNotification>'
return str(summary)
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F NSNotification.NSNotification_SummaryProvider NSNotification")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F NSNotification.NSNotification_SummaryProvider NSNotification")

View File

@ -23,21 +23,24 @@ statistics.add_metric('code_notrun')
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but the port number of an NSNumber, so they need not
# obey the interface specification for synthetic children providers
class NSTaggedNumber_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, info_bits, data, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.info_bits = info_bits
self.data = data
self.update();
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def value(self):
logger = lldb.formatters.Logger.Logger()
@ -46,149 +49,169 @@ class NSTaggedNumber_SummaryProvider:
# unfortunately, the original type information appears to be lost
# so we try to at least recover the proper magnitude of the data
if self.info_bits == 0:
return '(char)' + str(ord(ctypes.c_char(chr(self.data % 256)).value))
return '(char)' + \
str(ord(ctypes.c_char(chr(self.data % 256)).value))
if self.info_bits == 4:
return '(short)' + str(ctypes.c_short(self.data % (256*256)).value)
return '(short)' + \
str(ctypes.c_short(self.data % (256 * 256)).value)
if self.info_bits == 8:
return '(int)' + str(ctypes.c_int(self.data % (256*256*256*256)).value)
return '(int)' + str(ctypes.c_int(self.data %
(256 * 256 * 256 * 256)).value)
if self.info_bits == 12:
return '(long)' + str(ctypes.c_long(self.data).value)
else:
return 'unexpected value:(info=' + str(self.info_bits) + ", value = " + str(self.data) + ')'
return 'unexpected value:(info=' + str(self.info_bits) + \
", value = " + str(self.data) + ')'
class NSUntaggedNumber_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.char):
self.sys_params.types_cache.char = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar)
self.sys_params.types_cache.char = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeChar)
if not(self.sys_params.types_cache.short):
self.sys_params.types_cache.short = self.valobj.GetType().GetBasicType(lldb.eBasicTypeShort)
self.sys_params.types_cache.short = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeShort)
if not(self.sys_params.types_cache.ushort):
self.sys_params.types_cache.ushort = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedShort)
self.sys_params.types_cache.ushort = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedShort)
if not(self.sys_params.types_cache.int):
self.sys_params.types_cache.int = self.valobj.GetType().GetBasicType(lldb.eBasicTypeInt)
if not(self.sys_params.types_cache.long):
self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
self.sys_params.types_cache.long = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeLong)
if not(self.sys_params.types_cache.ulong):
self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.ulong = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
if not(self.sys_params.types_cache.longlong):
self.sys_params.types_cache.longlong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLongLong)
self.sys_params.types_cache.longlong = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeLongLong)
if not(self.sys_params.types_cache.ulonglong):
self.sys_params.types_cache.ulonglong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLongLong)
self.sys_params.types_cache.ulonglong = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLongLong)
if not(self.sys_params.types_cache.float):
self.sys_params.types_cache.float = self.valobj.GetType().GetBasicType(lldb.eBasicTypeFloat)
self.sys_params.types_cache.float = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeFloat)
if not(self.sys_params.types_cache.double):
self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
self.update();
self.sys_params.types_cache.double = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeDouble)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def value(self):
logger = lldb.formatters.Logger.Logger()
global statistics
# we need to skip the ISA, then the next byte tells us what to read
# we then skip one other full pointer worth of data and then fetch the contents
# if we are fetching an int64 value, one more pointer must be skipped to get at our data
data_type_vo = self.valobj.CreateChildAtOffset("dt",
self.sys_params.pointer_size,
self.sys_params.types_cache.char)
# if we are fetching an int64 value, one more pointer must be skipped
# to get at our data
data_type_vo = self.valobj.CreateChildAtOffset(
"dt", self.sys_params.pointer_size, self.sys_params.types_cache.char)
data_type = ((data_type_vo.GetValueAsUnsigned(0) % 256) & 0x1F)
data_offset = 2 * self.sys_params.pointer_size
if data_type == 0B00001:
data_vo = self.valobj.CreateChildAtOffset("data",
data_offset,
self.sys_params.types_cache.char)
statistics.metric_hit('code_notrun',self.valobj)
return '(char)' + str(ord(ctypes.c_char(chr(data_vo.GetValueAsUnsigned(0))).value))
data_vo = self.valobj.CreateChildAtOffset(
"data", data_offset, self.sys_params.types_cache.char)
statistics.metric_hit('code_notrun', self.valobj)
return '(char)' + \
str(ord(ctypes.c_char(chr(data_vo.GetValueAsUnsigned(0))).value))
elif data_type == 0B0010:
data_vo = self.valobj.CreateChildAtOffset("data",
data_offset,
self.sys_params.types_cache.short)
statistics.metric_hit('code_notrun',self.valobj)
return '(short)' + str(ctypes.c_short(data_vo.GetValueAsUnsigned(0) % (256*256)).value)
data_vo = self.valobj.CreateChildAtOffset(
"data", data_offset, self.sys_params.types_cache.short)
statistics.metric_hit('code_notrun', self.valobj)
return '(short)' + str(
ctypes.c_short(
data_vo.GetValueAsUnsigned(0) %
(256 * 256)).value)
# IF tagged pointers are possible on 32bit+v2 runtime
# (of which the only existing instance should be iOS)
# then values of this type might be tagged
elif data_type == 0B0011:
data_vo = self.valobj.CreateChildAtOffset("data",
data_offset,
self.sys_params.types_cache.int)
statistics.metric_hit('code_notrun',self.valobj)
return '(int)' + str(ctypes.c_int(data_vo.GetValueAsUnsigned(0)% (256*256*256*256)).value)
data_vo = self.valobj.CreateChildAtOffset(
"data", data_offset, self.sys_params.types_cache.int)
statistics.metric_hit('code_notrun', self.valobj)
return '(int)' + str(ctypes.c_int(data_vo.GetValueAsUnsigned(0) %
(256 * 256 * 256 * 256)).value)
# apparently, on is_64_bit architectures, these are the only values that will ever
# be represented by a non tagged pointers
elif data_type == 0B10001:
data_offset = data_offset + 8 # 8 is needed even if we are on 32bit
data_vo = self.valobj.CreateChildAtOffset("data",
data_offset,
self.sys_params.types_cache.longlong)
statistics.metric_hit('code_notrun',self.valobj)
return '(long)' + str(ctypes.c_long(data_vo.GetValueAsUnsigned(0)).value)
data_vo = self.valobj.CreateChildAtOffset(
"data", data_offset, self.sys_params.types_cache.longlong)
statistics.metric_hit('code_notrun', self.valobj)
return '(long)' + \
str(ctypes.c_long(data_vo.GetValueAsUnsigned(0)).value)
elif data_type == 0B0100:
if self.sys_params.is_64_bit:
data_offset = data_offset + self.sys_params.pointer_size
data_vo = self.valobj.CreateChildAtOffset("data",
data_offset,
self.sys_params.types_cache.longlong)
statistics.metric_hit('code_notrun',self.valobj)
return '(long)' + str(ctypes.c_long(data_vo.GetValueAsUnsigned(0)).value)
data_vo = self.valobj.CreateChildAtOffset(
"data", data_offset, self.sys_params.types_cache.longlong)
statistics.metric_hit('code_notrun', self.valobj)
return '(long)' + \
str(ctypes.c_long(data_vo.GetValueAsUnsigned(0)).value)
elif data_type == 0B0101:
data_vo = self.valobj.CreateChildAtOffset("data",
data_offset,
self.sys_params.types_cache.longlong)
data_plain = int(str(data_vo.GetValueAsUnsigned(0) & 0x00000000FFFFFFFF))
data_vo = self.valobj.CreateChildAtOffset(
"data", data_offset, self.sys_params.types_cache.longlong)
data_plain = int(
str(data_vo.GetValueAsUnsigned(0) & 0x00000000FFFFFFFF))
packed = struct.pack('I', data_plain)
data_float = struct.unpack('f', packed)[0]
statistics.metric_hit('code_notrun',self.valobj)
statistics.metric_hit('code_notrun', self.valobj)
return '(float)' + str(data_float)
elif data_type == 0B0110:
data_vo = self.valobj.CreateChildAtOffset("data",
data_offset,
self.sys_params.types_cache.longlong)
data_vo = self.valobj.CreateChildAtOffset(
"data", data_offset, self.sys_params.types_cache.longlong)
data_plain = data_vo.GetValueAsUnsigned(0)
data_double = struct.unpack('d', struct.pack('Q', data_plain))[0]
statistics.metric_hit('code_notrun',self.valobj)
statistics.metric_hit('code_notrun', self.valobj)
return '(double)' + str(data_double)
statistics.metric_hit('unknown_class',str(valobj.GetName()) + " had unknown data_type " + str(data_type))
statistics.metric_hit(
'unknown_class', str(
valobj.GetName()) + " had unknown data_type " + str(data_type))
return 'unexpected: dt = ' + str(data_type)
class NSUnknownNumber_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update();
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def value(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
expr = "(NSString*)[" + stream.GetData() + " stringValue]"
num_children_vo = self.valobj.CreateValueFromExpression("str",expr)
num_children_vo = self.valobj.CreateValueFromExpression("str", expr)
if num_children_vo.IsValid():
return num_children_vo.GetSummary()
return '<variable is not NSNumber>'
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
@ -197,39 +220,50 @@ def GetSummary_Impl(valobj):
if name_string == 'NSNumber' or name_string == '__NSCFNumber':
if class_data.is_tagged():
wrapper = NSTaggedNumber_SummaryProvider(valobj,class_data.info_bits(),class_data.value(), class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
wrapper = NSTaggedNumber_SummaryProvider(
valobj, class_data.info_bits(), class_data.value(), class_data.sys_params)
statistics.metric_hit('code_notrun', valobj)
else:
# the wrapper might be unable to decipher what is into the NSNumber
# and then have to run code on it
wrapper = NSUntaggedNumber_SummaryProvider(valobj, class_data.sys_params)
wrapper = NSUntaggedNumber_SummaryProvider(
valobj, class_data.sys_params)
else:
wrapper = NSUnknownNumber_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
wrapper = NSUnknownNumber_SummaryProvider(
valobj, class_data.sys_params)
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def NSNumber_SummaryProvider (valobj,dict):
def NSNumber_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.value();
summary = provider.value()
except Exception as foo:
print foo
# except:
summary = None
logger >> "got summary " + str(summary)
if summary == None:
if summary is None:
summary = '<variable is not NSNumber>'
return str(summary)
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F NSNumber.NSNumber_SummaryProvider NSNumber")
debugger.HandleCommand("type summary add -F NSNumber.NSNumber_SummaryProvider __NSCFBoolean")
debugger.HandleCommand("type summary add -F NSNumber.NSNumber_SummaryProvider __NSCFNumber")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F NSNumber.NSNumber_SummaryProvider NSNumber")
debugger.HandleCommand(
"type summary add -F NSNumber.NSNumber_SummaryProvider __NSCFBoolean")
debugger.HandleCommand(
"type summary add -F NSNumber.NSNumber_SummaryProvider __NSCFNumber")

View File

@ -22,24 +22,29 @@ statistics.add_metric('code_notrun')
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but the port number of an NSMachPort, so they need not
# obey the interface specification for synthetic children providers
class NSCFSet_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# one pointer is the ISA
# then we have one other internal pointer, plus
@ -53,54 +58,58 @@ class NSCFSet_SummaryProvider:
def count(self):
logger = lldb.formatters.Logger.Logger()
vcount = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
vcount = self.valobj.CreateChildAtOffset(
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
return vcount.GetValueAsUnsigned(0)
class NSSetUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update();
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def count(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
expr = "(int)[" + stream.GetData() + " count]"
num_children_vo = self.valobj.CreateValueFromExpression("count",expr)
num_children_vo = self.valobj.CreateValueFromExpression("count", expr)
if num_children_vo.IsValid():
return num_children_vo.GetValueAsUnsigned(0)
return '<variable is not NSSet>'
class NSSetI_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# we just need to skip the ISA and the count immediately follows
def offset(self):
@ -109,11 +118,10 @@ class NSSetI_SummaryProvider:
def count(self):
logger = lldb.formatters.Logger.Logger()
num_children_vo = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
num_children_vo = self.valobj.CreateChildAtOffset(
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
value = num_children_vo.GetValueAsUnsigned(0)
if value != None:
if value is not None:
# the MSB on immutable sets seems to be taken by some other data
# not sure if it is a bug or some weird sort of feature, but masking it out
# gets the count right (unless, of course, someone's dictionaries grow
@ -124,24 +132,28 @@ class NSSetI_SummaryProvider:
value = value & ~0xFF000000
return value
class NSSetM_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSUInteger):
if self.sys_params.is_64_bit:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
else:
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update();
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# we just need to skip the ISA and the count immediately follows
def offset(self):
@ -150,45 +162,48 @@ class NSSetM_SummaryProvider:
def count(self):
logger = lldb.formatters.Logger.Logger()
num_children_vo = self.valobj.CreateChildAtOffset("count",
self.offset(),
self.sys_params.types_cache.NSUInteger)
num_children_vo = self.valobj.CreateChildAtOffset(
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
return num_children_vo.GetValueAsUnsigned(0)
class NSCountedSet_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not (self.sys_params.types_cache.voidptr):
self.sys_params.types_cache.voidptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType()
self.update();
self.sys_params.types_cache.voidptr = self.valobj.GetType(
).GetBasicType(lldb.eBasicTypeVoid).GetPointerType()
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# an NSCountedSet is implemented using a CFBag whose pointer just follows the ISA
# an NSCountedSet is implemented using a CFBag whose pointer just follows
# the ISA
def offset(self):
logger = lldb.formatters.Logger.Logger()
return self.sys_params.pointer_size
def count(self):
logger = lldb.formatters.Logger.Logger()
cfbag_vo = self.valobj.CreateChildAtOffset("bag_impl",
self.offset(),
self.sys_params.types_cache.voidptr)
return CFBag.CFBagRef_SummaryProvider(cfbag_vo,self.sys_params).length()
cfbag_vo = self.valobj.CreateChildAtOffset(
"bag_impl", self.offset(), self.sys_params.types_cache.voidptr)
return CFBag.CFBagRef_SummaryProvider(
cfbag_vo, self.sys_params).length()
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
@ -197,47 +212,55 @@ def GetSummary_Impl(valobj):
if name_string == '__NSCFSet':
wrapper = NSCFSet_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
statistics.metric_hit('code_notrun', valobj)
elif name_string == '__NSSetI':
wrapper = NSSetI_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
statistics.metric_hit('code_notrun', valobj)
elif name_string == '__NSSetM':
wrapper = NSSetM_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
statistics.metric_hit('code_notrun', valobj)
elif name_string == 'NSCountedSet':
wrapper = NSCountedSet_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
statistics.metric_hit('code_notrun', valobj)
else:
wrapper = NSSetUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def NSSet_SummaryProvider (valobj,dict):
def NSSet_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
provider = GetSummary_Impl(valobj)
if provider is not None:
try:
summary = provider.count();
summary = provider.count()
except:
summary = None
if summary == None:
if summary is None:
summary = '<variable is not NSSet>'
if isinstance(summary, basestring):
return summary
else:
summary = str(summary) + (' objects' if summary != 1 else ' object')
summary = str(summary) + \
(' objects' if summary != 1 else ' object')
return summary
return 'Summary Unavailable'
def NSSet_SummaryProvider2 (valobj,dict):
def NSSet_SummaryProvider2(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.count();
summary = provider.count()
except:
summary = None
logger >> "got summary " + str(summary)
@ -246,18 +269,21 @@ def NSSet_SummaryProvider2 (valobj,dict):
# this only happens on 64bit, and the bit mask was derived through
# experimentation (if counts start looking weird, then most probably
# the mask needs to be changed)
if summary == None:
if summary is None:
summary = '<variable is not CFSet>'
if isinstance(summary, basestring):
return summary
else:
if provider.sys_params.is_64_bit:
summary = summary & ~0x1fff000000000000
summary = '@"' + str(summary) + (' values"' if summary != 1 else ' value"')
summary = '@"' + str(summary) + \
(' values"' if summary != 1 else ' value"')
return summary
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F NSSet.NSSet_SummaryProvider NSSet")
debugger.HandleCommand("type summary add -F NSSet.NSSet_SummaryProvider2 CFSetRef CFMutableSetRef")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F NSSet.NSSet_SummaryProvider NSSet")
debugger.HandleCommand(
"type summary add -F NSSet.NSSet_SummaryProvider2 CFSetRef CFMutableSetRef")

View File

@ -22,23 +22,28 @@ statistics.add_metric('code_notrun')
# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but a summary for an NSURL, so they need not
# obey the interface specification for synthetic children providers
class NSURLKnown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
if not(self.sys_params.types_cache.NSString):
self.sys_params.types_cache.NSString = self.valobj.GetTarget().FindFirstType('NSString').GetPointerType()
self.sys_params.types_cache.NSString = self.valobj.GetTarget(
).FindFirstType('NSString').GetPointerType()
if not(self.sys_params.types_cache.NSURL):
self.sys_params.types_cache.NSURL = self.valobj.GetTarget().FindFirstType('NSURL').GetPointerType()
self.update();
self.sys_params.types_cache.NSURL = self.valobj.GetTarget(
).FindFirstType('NSURL').GetPointerType()
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
# one pointer is the ISA
# then there is one more pointer and 8 bytes of plain data
@ -50,24 +55,23 @@ class NSURLKnown_SummaryProvider:
def offset_text(self):
logger = lldb.formatters.Logger.Logger()
return 24 if self.sys_params.is_64_bit else 16
def offset_base(self):
logger = lldb.formatters.Logger.Logger()
return self.offset_text()+self.sys_params.pointer_size
return self.offset_text() + self.sys_params.pointer_size
def url_text(self):
logger = lldb.formatters.Logger.Logger()
text = self.valobj.CreateChildAtOffset("text",
self.offset_text(),
self.sys_params.types_cache.NSString)
base = self.valobj.CreateChildAtOffset("base",
self.offset_base(),
self.sys_params.types_cache.NSURL)
my_string = CFString.CFString_SummaryProvider(text,None)
text = self.valobj.CreateChildAtOffset(
"text", self.offset_text(), self.sys_params.types_cache.NSString)
base = self.valobj.CreateChildAtOffset(
"base", self.offset_base(), self.sys_params.types_cache.NSURL)
my_string = CFString.CFString_SummaryProvider(text, None)
if len(my_string) > 0 and base.GetValueAsUnsigned(0) != 0:
# remove final " from myself
my_string = my_string[0:len(my_string)-1]
my_string = my_string[0:len(my_string) - 1]
my_string = my_string + ' -- '
my_base_string = NSURL_SummaryProvider(base,None)
my_base_string = NSURL_SummaryProvider(base, None)
if len(my_base_string) > 2:
# remove @" marker from base URL string
my_base_string = my_base_string[2:]
@ -76,33 +80,36 @@ class NSURLKnown_SummaryProvider:
class NSURLUnknown_SummaryProvider:
def adjust_for_architecture(self):
pass
def __init__(self, valobj, params):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.sys_params = params
self.update()
def update(self):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture();
self.adjust_for_architecture()
def url_text(self):
logger = lldb.formatters.Logger.Logger()
stream = lldb.SBStream()
self.valobj.GetExpressionPath(stream)
url_text_vo = self.valobj.CreateValueFromExpression("url","(NSString*)[" + stream.GetData() + " description]")
url_text_vo = self.valobj.CreateValueFromExpression(
"url", "(NSString*)[" + stream.GetData() + " description]")
if url_text_vo.IsValid():
return CFString.CFString_SummaryProvider(url_text_vo,None)
return CFString.CFString_SummaryProvider(url_text_vo, None)
return '<variable is not NSURL>'
def GetSummary_Impl(valobj):
logger = lldb.formatters.Logger.Logger()
global statistics
class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
valobj, statistics)
if wrapper:
return wrapper
@ -111,27 +118,36 @@ def GetSummary_Impl(valobj):
if name_string == 'NSURL':
wrapper = NSURLKnown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
statistics.metric_hit('code_notrun', valobj)
else:
wrapper = NSURLUnknown_SummaryProvider(valobj, class_data.sys_params)
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
return wrapper;
statistics.metric_hit(
'unknown_class',
valobj.GetName() +
" seen as " +
name_string)
return wrapper
def NSURL_SummaryProvider (valobj,dict):
def NSURL_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
provider = GetSummary_Impl(valobj);
if provider != None:
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
provider = GetSummary_Impl(valobj)
if provider is not None:
if isinstance(
provider,
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
return provider.message()
try:
summary = provider.url_text();
summary = provider.url_text()
except:
summary = None
logger >> "got summary " + str(summary)
if summary == None or summary == '':
if summary is None or summary == '':
summary = '<variable is not NSURL>'
return summary
return 'Summary Unavailable'
def __lldb_init_module(debugger,dict):
debugger.HandleCommand("type summary add -F NSURL.NSURL_SummaryProvider NSURL CFURLRef")
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"type summary add -F NSURL.NSURL_SummaryProvider NSURL CFURLRef")

View File

@ -7,8 +7,13 @@ License. See LICENSE.TXT for details.
"""
import lldb
def SEL_Summary(valobj,dict):
return valobj.Cast(valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()).GetSummary()
def SELPointer_Summary(valobj,dict):
return valobj.CreateValueFromAddress('text',valobj.GetValueAsUnsigned(0),valobj.GetType().GetBasicType(lldb.eBasicTypeChar)).AddressOf().GetSummary()
def SEL_Summary(valobj, dict):
return valobj.Cast(valobj.GetType().GetBasicType(
lldb.eBasicTypeChar).GetPointerType()).GetSummary()
def SELPointer_Summary(valobj, dict):
return valobj.CreateValueFromAddress(
'text', valobj.GetValueAsUnsigned(0), valobj.GetType().GetBasicType(
lldb.eBasicTypeChar)).AddressOf().GetSummary()

View File

@ -5,32 +5,36 @@ part of The LLVM Compiler Infrastructure
This file is distributed under the University of Illinois Open Source
License. See LICENSE.TXT for details.
"""
class AttributesDictionary:
def __init__(self, allow_reset = True):
self.__dict__['_dictionary'] = {} # need to do it this way to prevent endless recursion
def __init__(self, allow_reset=True):
# need to do it this way to prevent endless recursion
self.__dict__['_dictionary'] = {}
self.__dict__['_allow_reset'] = allow_reset
def __getattr__(self,name):
def __getattr__(self, name):
if not self._check_exists(name):
return None
value = self._dictionary[name]
return value
def _set_impl(self,name,value):
def _set_impl(self, name, value):
self._dictionary[name] = value
def _check_exists(self,name):
def _check_exists(self, name):
return name in self._dictionary
def __setattr__(self,name,value):
def __setattr__(self, name, value):
if self._allow_reset:
self._set_impl(name,value)
self._set_impl(name, value)
else:
self.set_if_necessary(name,value)
self.set_if_necessary(name, value)
def set_if_necessary(self,name,value):
def set_if_necessary(self, name, value):
if not self._check_exists(name):
self._set_impl(name,value)
self._set_impl(name, value)
return True
return False

View File

@ -7,29 +7,30 @@ License. See LICENSE.TXT for details.
"""
import lldb.formatters.metrics
class Cache:
def __init__(self):
self.data = {}
self.statistics = lldb.formatters.metrics.Metrics()
self.statistics.add_metric('hit')
self.statistics.add_metric('miss')
def look_for_key(self,key):
def look_for_key(self, key):
if key in self.data:
return True
return False
def add_item(self,key,value,ok_to_replace=True):
def add_item(self, key, value, ok_to_replace=True):
if not(ok_to_replace) and self.look_for_key(key):
return False
self.data[key] = value
return True
def get_value(self,key,default=None):
def get_value(self, key, default=None):
if self.look_for_key(key):
self.statistics.metric_hit('hit',key)
self.statistics.metric_hit('hit', key)
return self.data[key]
else:
self.statistics.metric_hit('miss',key)
self.statistics.metric_hit('miss', key)
return default

View File

@ -6,15 +6,18 @@ This file is distributed under the University of Illinois Open Source
License. See LICENSE.TXT for details.
"""
import lldb
import time, datetime
import time
import datetime
import inspect
class TimeMetrics:
@staticmethod
def generate(label=None):
return TimeMetrics(label)
def __init__(self,lbl=None):
def __init__(self, lbl=None):
self.label = "" if lbl is None else lbl
pass
@ -23,57 +26,72 @@ class TimeMetrics:
self.function = str(caller)
self.enter_time = time.clock()
def __exit__(self, a,b,c):
def __exit__(self, a, b, c):
self.exit_time = time.clock()
print("It took " + str(self.exit_time - self.enter_time) + " time units to run through " + self.function + self.label)
print("It took " + str(self.exit_time - self.enter_time) +
" time units to run through " + self.function + self.label)
return False
class Counter:
def __init__(self):
self.count = 0
self.list = []
def update(self,name):
def update(self, name):
self.count = self.count + 1
# avoid getting the full dump of this ValueObject just to save its metrics
if isinstance(name,lldb.SBValue):
# avoid getting the full dump of this ValueObject just to save its
# metrics
if isinstance(name, lldb.SBValue):
self.list.append(name.GetName())
else:
self.list.append(str(name))
def __str__(self):
return str(self.count) + " times, for items [" + str(self.list) + "]"
class MetricsPrinter_Verbose:
def __init__(self,metrics):
def __init__(self, metrics):
self.metrics = metrics
def __str__(self):
string = ""
for key,value in self.metrics.metrics.items():
for key, value in self.metrics.metrics.items():
string = string + "metric " + str(key) + ": " + str(value) + "\n"
return string
class MetricsPrinter_Compact:
def __init__(self,metrics):
def __init__(self, metrics):
self.metrics = metrics
def __str__(self):
string = ""
for key,value in self.metrics.metrics.items():
string = string + "metric " + str(key) + " was hit " + str(value.count) + " times\n"
for key, value in self.metrics.metrics.items():
string = string + "metric " + \
str(key) + " was hit " + str(value.count) + " times\n"
return string
class Metrics:
def __init__(self):
self.metrics = {}
def add_metric(self,name):
def add_metric(self, name):
self.metrics[name] = Counter()
def metric_hit(self,metric,trigger):
def metric_hit(self, metric, trigger):
self.metrics[metric].update(trigger)
def __getitem__(self,key):
def __getitem__(self, key):
return self.metrics[key]
def __getattr__(self,name):
def __getattr__(self, name):
if name == 'compact':
return MetricsPrinter_Compact(self)
if name == 'verbose':
@ -84,10 +102,10 @@ class Metrics:
def __str__(self):
return str(self.verbose)
def metric_success(self,metric):
def metric_success(self, metric):
total_count = 0
metric_count = self[metric].count
for key,value in self.metrics.items():
for key, value in self.metrics.items():
total_count = total_count + value.count
if total_count > 0:
return metric_count / float(total_count)

View File

@ -11,14 +11,16 @@ import lldb.formatters.attrib_fromdict
import functools
import lldb.formatters.Logger
class Utilities:
@staticmethod
def read_ascii(process, pointer,max_len=128):
def read_ascii(process, pointer, max_len=128):
logger = lldb.formatters.Logger.Logger()
error = lldb.SBError()
content = None
try:
content = process.ReadCStringFromMemory(pointer,max_len,error)
content = process.ReadCStringFromMemory(pointer, max_len, error)
except:
pass
if content is None or len(content) == 0 or error.fail:
@ -37,7 +39,8 @@ class Utilities:
return ((pointer % pointer_size) == 0)
# Objective-C runtime has a rule that pointers in a class_t will only have bits 0 thru 46 set
# so if any pointer has bits 47 thru 63 high we know that this is not a valid isa
# so if any pointer has bits 47 thru 63 high we know that this is not a
# valid isa
@staticmethod
def is_allowed_pointer(pointer):
logger = lldb.formatters.Logger.Logger()
@ -46,13 +49,13 @@ class Utilities:
return ((pointer & 0xFFFF800000000000) == 0)
@staticmethod
def read_child_of(valobj,offset,type):
def read_child_of(valobj, offset, type):
logger = lldb.formatters.Logger.Logger()
if offset == 0 and type.GetByteSize() == valobj.GetByteSize():
return valobj.GetValueAsUnsigned()
child = valobj.CreateChildAtOffset("childUNK",offset,type)
child = valobj.CreateChildAtOffset("childUNK", offset, type)
if child is None or child.IsValid() == 0:
return None;
return None
return child.GetValueAsUnsigned()
@staticmethod
@ -67,7 +70,8 @@ class Utilities:
# symbols: $, %, -, _, .
# WARNING: this means that you cannot use this runtime implementation if you need to deal
# with class names that use anything but what is allowed here
ok_values = dict.fromkeys("$%_.-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890")
ok_values = dict.fromkeys(
"$%_.-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890")
return all(c in ok_values for c in name)
@staticmethod
@ -88,32 +92,36 @@ class Utilities:
# a utility method that factors out code common to almost all the formatters
# takes in an SBValue and a metrics object
# returns a class_data and a wrapper (or None, if the runtime alone can't decide on a wrapper)
# returns a class_data and a wrapper (or None, if the runtime alone can't
# decide on a wrapper)
@staticmethod
def prepare_class_detection(valobj,statistics):
def prepare_class_detection(valobj, statistics):
logger = lldb.formatters.Logger.Logger()
class_data = ObjCRuntime(valobj)
if class_data.is_valid() == 0:
statistics.metric_hit('invalid_pointer',valobj)
wrapper = InvalidPointer_Description(valobj.GetValueAsUnsigned(0) == 0)
return class_data,wrapper
statistics.metric_hit('invalid_pointer', valobj)
wrapper = InvalidPointer_Description(
valobj.GetValueAsUnsigned(0) == 0)
return class_data, wrapper
class_data = class_data.read_class_data()
if class_data.is_valid() == 0:
statistics.metric_hit('invalid_isa',valobj)
statistics.metric_hit('invalid_isa', valobj)
wrapper = InvalidISA_Description()
return class_data,wrapper
return class_data, wrapper
if class_data.is_kvo():
class_data = class_data.get_superclass()
if class_data.class_name() == '_NSZombie_OriginalClass':
wrapper = ThisIsZombie_Description()
return class_data,wrapper
return class_data,None
return class_data, wrapper
return class_data, None
class RoT_Data:
def __init__(self,rot_pointer,params):
def __init__(self, rot_pointer, params):
logger = lldb.formatters.Logger.Logger()
if (Utilities.is_valid_pointer(rot_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
if (Utilities.is_valid_pointer(rot_pointer.GetValueAsUnsigned(),
params.pointer_size, allow_tagged=0)):
self.sys_params = params
self.valobj = rot_pointer
#self.flags = Utilities.read_child_of(self.valobj,0,self.sys_params.uint32_t)
@ -121,13 +129,15 @@ class RoT_Data:
self.instanceSize = None # lazy fetching
offset = 24 if self.sys_params.is_64_bit else 16
#self.ivarLayoutPtr = Utilities.read_child_of(self.valobj,offset,self.sys_params.addr_ptr_type)
self.namePointer = Utilities.read_child_of(self.valobj,offset,self.sys_params.types_cache.addr_ptr_type)
self.namePointer = Utilities.read_child_of(
self.valobj, offset, self.sys_params.types_cache.addr_ptr_type)
self.valid = 1 # self.check_valid()
else:
logger >> "Marking as invalid - rot is invalid"
self.valid = 0
if self.valid:
self.name = Utilities.read_ascii(self.valobj.GetTarget().GetProcess(),self.namePointer)
self.name = Utilities.read_ascii(
self.valobj.GetTarget().GetProcess(), self.namePointer)
if not(Utilities.is_valid_identifier(self.name)):
logger >> "Marking as invalid - name is invalid"
self.valid = 0
@ -136,7 +146,7 @@ class RoT_Data:
def check_valid(self):
self.valid = 1
# misaligned pointers seem to be possible for this field
#if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=0)):
# if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=0)):
# self.valid = 0
# pass
@ -149,12 +159,13 @@ class RoT_Data:
def is_valid(self):
return self.valid
def instance_size(self,align=0):
def instance_size(self, align=0):
logger = lldb.formatters.Logger.Logger()
if self.is_valid() == 0:
return None
if self.instanceSize is None:
self.instanceSize = Utilities.read_child_of(self.valobj,8,self.sys_params.types_cache.uint32_t)
self.instanceSize = Utilities.read_child_of(
self.valobj, 8, self.sys_params.types_cache.uint32_t)
if align:
unalign = self.instance_size(0)
if self.sys_params.is_64_bit:
@ -164,29 +175,40 @@ class RoT_Data:
else:
return self.instanceSize
class RwT_Data:
def __init__(self,rwt_pointer,params):
def __init__(self, rwt_pointer, params):
logger = lldb.formatters.Logger.Logger()
if (Utilities.is_valid_pointer(rwt_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
if (Utilities.is_valid_pointer(rwt_pointer.GetValueAsUnsigned(),
params.pointer_size, allow_tagged=0)):
self.sys_params = params
self.valobj = rwt_pointer
#self.flags = Utilities.read_child_of(self.valobj,0,self.sys_params.uint32_t)
#self.version = Utilities.read_child_of(self.valobj,4,self.sys_params.uint32_t)
self.roPointer = Utilities.read_child_of(self.valobj,8,self.sys_params.types_cache.addr_ptr_type)
self.roPointer = Utilities.read_child_of(
self.valobj, 8, self.sys_params.types_cache.addr_ptr_type)
self.check_valid()
else:
logger >> "Marking as invalid - rwt is invald"
self.valid = 0
if self.valid:
self.rot = self.valobj.CreateValueFromData("rot",lldb.SBData.CreateDataFromUInt64Array(self.sys_params.endianness, self.sys_params.pointer_size, [self.roPointer]),self.sys_params.types_cache.addr_ptr_type)
self.rot = self.valobj.CreateValueFromData(
"rot", lldb.SBData.CreateDataFromUInt64Array(
self.sys_params.endianness, self.sys_params.pointer_size, [
self.roPointer]), self.sys_params.types_cache.addr_ptr_type)
# self.rot = self.valobj.CreateValueFromAddress("rot",self.roPointer,self.sys_params.types_cache.addr_ptr_type).AddressOf()
self.data = RoT_Data(self.rot,self.sys_params)
self.data = RoT_Data(self.rot, self.sys_params)
# perform sanity checks on the contents of this class_rw_t
def check_valid(self):
logger = lldb.formatters.Logger.Logger()
self.valid = 1
if not(Utilities.is_valid_pointer(self.roPointer,self.sys_params.pointer_size,allow_tagged=0)):
if not(
Utilities.is_valid_pointer(
self.roPointer,
self.sys_params.pointer_size,
allow_tagged=0)):
logger >> "Marking as invalid - ropointer is invalid"
self.valid = 0
@ -201,10 +223,13 @@ class RwT_Data:
return self.data.is_valid()
return 0
class Class_Data_V2:
def __init__(self,isa_pointer,params):
def __init__(self, isa_pointer, params):
logger = lldb.formatters.Logger.Logger()
if (isa_pointer != None) and (Utilities.is_valid_pointer(isa_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
if (isa_pointer is not None) and (Utilities.is_valid_pointer(
isa_pointer.GetValueAsUnsigned(), params.pointer_size, allow_tagged=0)):
self.sys_params = params
self.valobj = isa_pointer
self.check_valid()
@ -212,9 +237,12 @@ class Class_Data_V2:
logger >> "Marking as invalid - isa is invalid or None"
self.valid = 0
if self.valid:
self.rwt = self.valobj.CreateValueFromData("rwt",lldb.SBData.CreateDataFromUInt64Array(self.sys_params.endianness, self.sys_params.pointer_size, [self.dataPointer]),self.sys_params.types_cache.addr_ptr_type)
self.rwt = self.valobj.CreateValueFromData(
"rwt", lldb.SBData.CreateDataFromUInt64Array(
self.sys_params.endianness, self.sys_params.pointer_size, [
self.dataPointer]), self.sys_params.types_cache.addr_ptr_type)
# self.rwt = self.valobj.CreateValueFromAddress("rwt",self.dataPointer,self.sys_params.types_cache.addr_ptr_type).AddressOf()
self.data = RwT_Data(self.rwt,self.sys_params)
self.data = RwT_Data(self.rwt, self.sys_params)
# perform sanity checks on the contents of this class_t
# this call tries to minimize the amount of data fetched- as soon as we have "proven"
@ -223,8 +251,13 @@ class Class_Data_V2:
logger = lldb.formatters.Logger.Logger()
self.valid = 1
self.isaPointer = Utilities.read_child_of(self.valobj,0,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.isaPointer,self.sys_params.pointer_size,allow_tagged=0)):
self.isaPointer = Utilities.read_child_of(
self.valobj, 0, self.sys_params.types_cache.addr_ptr_type)
if not(
Utilities.is_valid_pointer(
self.isaPointer,
self.sys_params.pointer_size,
allow_tagged=0)):
logger >> "Marking as invalid - isaPointer is invalid"
self.valid = 0
return
@ -233,8 +266,15 @@ class Class_Data_V2:
self.valid = 0
return
self.cachePointer = Utilities.read_child_of(self.valobj,2*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.cachePointer,self.sys_params.pointer_size,allow_tagged=0)):
self.cachePointer = Utilities.read_child_of(
self.valobj,
2 * self.sys_params.pointer_size,
self.sys_params.types_cache.addr_ptr_type)
if not(
Utilities.is_valid_pointer(
self.cachePointer,
self.sys_params.pointer_size,
allow_tagged=0)):
logger >> "Marking as invalid - cachePointer is invalid"
self.valid = 0
return
@ -242,8 +282,15 @@ class Class_Data_V2:
logger >> "Marking as invalid - cachePointer is not allowed"
self.valid = 0
return
self.dataPointer = Utilities.read_child_of(self.valobj,4*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.dataPointer,self.sys_params.pointer_size,allow_tagged=0)):
self.dataPointer = Utilities.read_child_of(
self.valobj,
4 * self.sys_params.pointer_size,
self.sys_params.types_cache.addr_ptr_type)
if not(
Utilities.is_valid_pointer(
self.dataPointer,
self.sys_params.pointer_size,
allow_tagged=0)):
logger >> "Marking as invalid - dataPointer is invalid"
self.valid = 0
return
@ -252,8 +299,16 @@ class Class_Data_V2:
self.valid = 0
return
self.superclassIsaPointer = Utilities.read_child_of(self.valobj,1*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=0, allow_NULL=1)):
self.superclassIsaPointer = Utilities.read_child_of(
self.valobj,
1 * self.sys_params.pointer_size,
self.sys_params.types_cache.addr_ptr_type)
if not(
Utilities.is_valid_pointer(
self.superclassIsaPointer,
self.sys_params.pointer_size,
allow_tagged=0,
allow_NULL=1)):
logger >> "Marking as invalid - superclassIsa is invalid"
self.valid = 0
return
@ -285,10 +340,9 @@ class Class_Data_V2:
def get_superclass(self):
logger = lldb.formatters.Logger.Logger()
if self.is_valid():
parent_isa_pointer = self.valobj.CreateChildAtOffset("parent_isa",
self.sys_params.pointer_size,
self.sys_params.addr_ptr_type)
return Class_Data_V2(parent_isa_pointer,self.sys_params)
parent_isa_pointer = self.valobj.CreateChildAtOffset(
"parent_isa", self.sys_params.pointer_size, self.sys_params.addr_ptr_type)
return Class_Data_V2(parent_isa_pointer, self.sys_params)
else:
return None
@ -315,17 +369,22 @@ class Class_Data_V2:
def is_tagged(self):
return 0
def instance_size(self,align=0):
def instance_size(self, align=0):
logger = lldb.formatters.Logger.Logger()
if self.is_valid() == 0:
return None
return self.rwt.rot.instance_size(align)
# runtime v1 is much less intricate than v2 and stores relevant information directly in the class_t object
# runtime v1 is much less intricate than v2 and stores relevant
# information directly in the class_t object
class Class_Data_V1:
def __init__(self,isa_pointer,params):
def __init__(self, isa_pointer, params):
logger = lldb.formatters.Logger.Logger()
if (isa_pointer != None) and (Utilities.is_valid_pointer(isa_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
if (isa_pointer is not None) and (Utilities.is_valid_pointer(
isa_pointer.GetValueAsUnsigned(), params.pointer_size, allow_tagged=0)):
self.valid = 1
self.sys_params = params
self.valobj = isa_pointer
@ -334,7 +393,8 @@ class Class_Data_V1:
logger >> "Marking as invalid - isaPointer is invalid or None"
self.valid = 0
if self.valid:
self.name = Utilities.read_ascii(self.valobj.GetTarget().GetProcess(),self.namePointer)
self.name = Utilities.read_ascii(
self.valobj.GetTarget().GetProcess(), self.namePointer)
if not(Utilities.is_valid_identifier(self.name)):
logger >> "Marking as invalid - name is not valid"
self.valid = 0
@ -344,20 +404,36 @@ class Class_Data_V1:
logger = lldb.formatters.Logger.Logger()
self.valid = 1
self.isaPointer = Utilities.read_child_of(self.valobj,0,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.isaPointer,self.sys_params.pointer_size,allow_tagged=0)):
self.isaPointer = Utilities.read_child_of(
self.valobj, 0, self.sys_params.types_cache.addr_ptr_type)
if not(
Utilities.is_valid_pointer(
self.isaPointer,
self.sys_params.pointer_size,
allow_tagged=0)):
logger >> "Marking as invalid - isaPointer is invalid"
self.valid = 0
return
self.superclassIsaPointer = Utilities.read_child_of(self.valobj,1*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=0,allow_NULL=1)):
self.superclassIsaPointer = Utilities.read_child_of(
self.valobj,
1 * self.sys_params.pointer_size,
self.sys_params.types_cache.addr_ptr_type)
if not(
Utilities.is_valid_pointer(
self.superclassIsaPointer,
self.sys_params.pointer_size,
allow_tagged=0,
allow_NULL=1)):
logger >> "Marking as invalid - superclassIsa is invalid"
self.valid = 0
return
self.namePointer = Utilities.read_child_of(self.valobj,2*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
#if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=0,allow_NULL=0)):
self.namePointer = Utilities.read_child_of(
self.valobj,
2 * self.sys_params.pointer_size,
self.sys_params.types_cache.addr_ptr_type)
# if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=0,allow_NULL=0)):
# self.valid = 0
# return
@ -384,10 +460,9 @@ class Class_Data_V1:
def get_superclass(self):
logger = lldb.formatters.Logger.Logger()
if self.is_valid():
parent_isa_pointer = self.valobj.CreateChildAtOffset("parent_isa",
self.sys_params.pointer_size,
self.sys_params.addr_ptr_type)
return Class_Data_V1(parent_isa_pointer,self.sys_params)
parent_isa_pointer = self.valobj.CreateChildAtOffset(
"parent_isa", self.sys_params.pointer_size, self.sys_params.addr_ptr_type)
return Class_Data_V1(parent_isa_pointer, self.sys_params)
else:
return None
@ -411,12 +486,15 @@ class Class_Data_V1:
def is_tagged(self):
return 0
def instance_size(self,align=0):
def instance_size(self, align=0):
logger = lldb.formatters.Logger.Logger()
if self.is_valid() == 0:
return None
if self.instanceSize is None:
self.instanceSize = Utilities.read_child_of(self.valobj,5*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
self.instanceSize = Utilities.read_child_of(
self.valobj,
5 * self.sys_params.pointer_size,
self.sys_params.types_cache.addr_ptr_type)
if align:
unalign = self.instance_size(0)
if self.sys_params.is_64_bit:
@ -430,20 +508,22 @@ class Class_Data_V1:
# of OSX - they might change in future OS releases, and no-one is
# advised to rely on these values, or any of the bitmasking formulas
# in TaggedClass_Data. doing otherwise is at your own risk
TaggedClass_Values_Lion = {1 : 'NSNumber', \
5: 'NSManagedObject', \
6: 'NSDate', \
7: 'NSDateTS' };
TaggedClass_Values_NMOS = {0: 'NSAtom', \
3 : 'NSNumber', \
4: 'NSDateTS', \
5: 'NSManagedObject', \
6: 'NSDate' };
TaggedClass_Values_Lion = {1: 'NSNumber',
5: 'NSManagedObject',
6: 'NSDate',
7: 'NSDateTS'}
TaggedClass_Values_NMOS = {0: 'NSAtom',
3: 'NSNumber',
4: 'NSDateTS',
5: 'NSManagedObject',
6: 'NSDate'}
class TaggedClass_Data:
def __init__(self,pointer,params):
def __init__(self, pointer, params):
logger = lldb.formatters.Logger.Logger()
global TaggedClass_Values_Lion,TaggedClass_Values_NMOS
global TaggedClass_Values_Lion, TaggedClass_Values_NMOS
self.valid = 1
self.name = None
self.sys_params = params
@ -465,7 +545,6 @@ class TaggedClass_Data:
logger >> "Marking as invalid - not a good tagged pointer for NMOS"
self.valid = 0
def is_valid(self):
return self.valid
@ -499,7 +578,7 @@ class TaggedClass_Data:
return 1
# it seems reasonable to say that a tagged pointer is the size of a pointer
def instance_size(self,align=0):
def instance_size(self, align=0):
logger = lldb.formatters.Logger.Logger()
if self.is_valid() == 0:
return None
@ -507,13 +586,16 @@ class TaggedClass_Data:
class InvalidClass_Data:
def __init__(self):
pass
def is_valid(self):
return 0
class Version:
def __init__(self, major, minor, release, build_string):
self._major = major
self._minor = minor
@ -522,19 +604,22 @@ class Version:
def get_major(self):
return self._major
def get_minor(self):
return self._minor
def get_release(self):
return self._release
def get_build_string(self):
return self._build_string
major = property(get_major,None)
minor = property(get_minor,None)
release = property(get_release,None)
build_string = property(get_build_string,None)
major = property(get_major, None)
minor = property(get_minor, None)
release = property(get_release, None)
build_string = property(get_build_string, None)
def __lt__(self,other):
def __lt__(self, other):
if (self.major < other.major):
return 1
if (self.minor < other.minor):
@ -545,7 +630,7 @@ class Version:
# be available
return 0
def __eq__(self,other):
def __eq__(self, other):
return (self.major == other.major) and \
(self.minor == other.minor) and \
(self.release == other.release) and \
@ -568,8 +653,10 @@ os_version = lldb.formatters.cache.Cache()
types_caches = lldb.formatters.cache.Cache()
isa_caches = lldb.formatters.cache.Cache()
class SystemParameters:
def __init__(self,valobj):
def __init__(self, valobj):
logger = lldb.formatters.Logger.Logger()
self.adjust_for_architecture(valobj)
self.adjust_for_process(valobj)
@ -582,36 +669,41 @@ class SystemParameters:
global isa_caches
process = valobj.GetTarget().GetProcess()
self.pid = process.GetUniqueID() # using the unique ID for added guarantees (see svn revision 172628 for further details)
# using the unique ID for added guarantees (see svn revision 172628 for
# further details)
self.pid = process.GetUniqueID()
if runtime_version.look_for_key(self.pid):
self.runtime_version = runtime_version.get_value(self.pid)
else:
self.runtime_version = ObjCRuntime.runtime_version(process)
runtime_version.add_item(self.pid,self.runtime_version)
runtime_version.add_item(self.pid, self.runtime_version)
if os_version.look_for_key(self.pid):
self.is_lion = os_version.get_value(self.pid)
else:
self.is_lion = Utilities.check_is_osx_lion(valobj.GetTarget())
os_version.add_item(self.pid,self.is_lion)
os_version.add_item(self.pid, self.is_lion)
if types_caches.look_for_key(self.pid):
self.types_cache = types_caches.get_value(self.pid)
else:
self.types_cache = lldb.formatters.attrib_fromdict.AttributesDictionary(allow_reset=0)
self.types_cache.addr_type = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.types_cache = lldb.formatters.attrib_fromdict.AttributesDictionary(
allow_reset=0)
self.types_cache.addr_type = valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedLong)
self.types_cache.addr_ptr_type = self.types_cache.addr_type.GetPointerType()
self.types_cache.uint32_t = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
types_caches.add_item(self.pid,self.types_cache)
self.types_cache.uint32_t = valobj.GetType(
).GetBasicType(lldb.eBasicTypeUnsignedInt)
types_caches.add_item(self.pid, self.types_cache)
if isa_caches.look_for_key(self.pid):
self.isa_cache = isa_caches.get_value(self.pid)
else:
self.isa_cache = lldb.formatters.cache.Cache()
isa_caches.add_item(self.pid,self.isa_cache)
isa_caches.add_item(self.pid, self.isa_cache)
def adjust_for_architecture(self,valobj):
def adjust_for_architecture(self, valobj):
process = valobj.GetTarget().GetProcess()
self.pointer_size = process.GetAddressByteSize()
self.is_64_bit = (self.pointer_size == 8)
@ -623,11 +715,18 @@ class SystemParameters:
# an offset that is made up of X pointers and Y bytes of additional data
# taking into account pointer size - if you know there is going to be some padding
# you can pass that in and it will be taken into account (since padding may be different between
# 32 and 64 bit versions, you can pass padding value for both, the right one will be used)
def calculate_offset(self, num_pointers = 0, bytes_count = 0, padding32 = 0, padding64 = 0):
value = bytes_count + num_pointers*self.pointer_size
# 32 and 64 bit versions, you can pass padding value for both, the right
# one will be used)
def calculate_offset(
self,
num_pointers=0,
bytes_count=0,
padding32=0,
padding64=0):
value = bytes_count + num_pointers * self.pointer_size
return value + padding64 if self.is_64_bit else value + padding32
class ObjCRuntime:
# the ObjC runtime has no explicit "version" field that we can use
@ -657,7 +756,7 @@ class ObjCRuntime:
if section.GetName() == '__OBJC':
section_objc = section
break
if section_objc != None and section_objc.IsValid():
if section_objc is not None and section_objc.IsValid():
logger >> "found __OBJC: v1"
return 1
logger >> "no __OBJC: v2"
@ -670,7 +769,7 @@ class ObjCRuntime:
runtime.isa = isa
return runtime
def __init__(self,valobj):
def __init__(self, valobj):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj
self.adjust_for_architecture()
@ -686,8 +785,15 @@ class ObjCRuntime:
logger = lldb.formatters.Logger.Logger()
if self.valobj is None:
return 0
return (Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=1) and \
not(Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=0)))
return (
Utilities.is_valid_pointer(
self.unsigned_value,
self.sys_params.pointer_size,
allow_tagged=1) and not(
Utilities.is_valid_pointer(
self.unsigned_value,
self.sys_params.pointer_size,
allow_tagged=0)))
def is_valid(self):
logger = lldb.formatters.Logger.Logger()
@ -695,26 +801,28 @@ class ObjCRuntime:
return 0
if self.valobj.IsInScope() == 0:
return 0
return Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=1)
return Utilities.is_valid_pointer(
self.unsigned_value,
self.sys_params.pointer_size,
allow_tagged=1)
def is_nil(self):
return self.unsigned_value == 0
def read_isa(self):
logger = lldb.formatters.Logger.Logger()
if self.isa_value != None:
if self.isa_value is not None:
logger >> "using cached isa"
return self.isa_value
self.isa_pointer = self.valobj.CreateChildAtOffset("cfisa",
0,
self.sys_params.types_cache.addr_ptr_type)
self.isa_pointer = self.valobj.CreateChildAtOffset(
"cfisa", 0, self.sys_params.types_cache.addr_ptr_type)
if self.isa_pointer is None or self.isa_pointer.IsValid() == 0:
logger >> "invalid isa - bailing out"
return None;
return None
self.isa_value = self.isa_pointer.GetValueAsUnsigned(1)
if self.isa_value == 1:
logger >> "invalid isa value - bailing out"
return None;
return None
return Ellipsis
def read_class_data(self):
@ -726,8 +834,10 @@ class ObjCRuntime:
logger >> "on v2 and tagged - maybe"
# not every odd-valued pointer is actually tagged. most are just plain wrong
# we could try and predetect this before even creating a TaggedClass_Data object
# but unless performance requires it, this seems a cleaner way to tackle the task
tentative_tagged = TaggedClass_Data(self.unsigned_value,self.sys_params)
# but unless performance requires it, this seems a cleaner way
# to tackle the task
tentative_tagged = TaggedClass_Data(
self.unsigned_value, self.sys_params)
if tentative_tagged.is_valid():
logger >> "truly tagged"
return tentative_tagged
@ -739,27 +849,34 @@ class ObjCRuntime:
return InvalidClass_Data()
if self.is_valid() == 0 or self.read_isa() is None:
return InvalidClass_Data()
data = self.sys_params.isa_cache.get_value(self.isa_value,default=None)
if data != None:
data = self.sys_params.isa_cache.get_value(
self.isa_value, default=None)
if data is not None:
return data
if self.sys_params.runtime_version == 2:
data = Class_Data_V2(self.isa_pointer,self.sys_params)
data = Class_Data_V2(self.isa_pointer, self.sys_params)
else:
data = Class_Data_V1(self.isa_pointer,self.sys_params)
data = Class_Data_V1(self.isa_pointer, self.sys_params)
if data is None:
return InvalidClass_Data()
if data.is_valid():
self.sys_params.isa_cache.add_item(self.isa_value,data,ok_to_replace=1)
self.sys_params.isa_cache.add_item(
self.isa_value, data, ok_to_replace=1)
return data
# these classes below can be used by the data formatters to provide a consistent message that describes a given runtime-generated situation
# these classes below can be used by the data formatters to provide a
# consistent message that describes a given runtime-generated situation
class SpecialSituation_Description:
def message(self):
return ''
class InvalidPointer_Description(SpecialSituation_Description):
def __init__(self,nil):
def __init__(self, nil):
self.is_nil = nil
def message(self):
@ -768,6 +885,7 @@ class InvalidPointer_Description(SpecialSituation_Description):
else:
return '<invalid pointer>'
class InvalidISA_Description(SpecialSituation_Description):
def __init__(self):
@ -776,6 +894,8 @@ class InvalidISA_Description(SpecialSituation_Description):
def message(self):
return '<not an Objective-C object>'
class ThisIsZombie_Description(SpecialSituation_Description):
def message(self):
return '<freed object>'

View File

@ -1,7 +1,8 @@
# Summaries for common ObjC types that require Python scripting
# to be generated fit into this file
def BOOL_SummaryProvider (valobj,dict):
def BOOL_SummaryProvider(valobj, dict):
if not (valobj.IsValid()):
return "<invalid>"
if valobj.GetValueAsUnsigned() == 0:
@ -9,8 +10,10 @@ def BOOL_SummaryProvider (valobj,dict):
else:
return "YES"
def BOOLRef_SummaryProvider (valobj, dict):
return BOOL_SummaryProvider (valobj.GetChildAtIndex(0),dict)
def BOOLPtr_SummaryProvider (valobj,dict):
return BOOL_SummaryProvider (valobj.Dereference(),dict)
def BOOLRef_SummaryProvider(valobj, dict):
return BOOL_SummaryProvider(valobj.GetChildAtIndex(0), dict)
def BOOLPtr_SummaryProvider(valobj, dict):
return BOOL_SummaryProvider(valobj.Dereference(), dict)

View File

@ -1,18 +1,24 @@
import lldb
def pyobj_summary (value,unused):
if value == None or value.IsValid() == False or value.GetValueAsUnsigned(0) == 0:
def pyobj_summary(value, unused):
if value is None or value.IsValid() == False or value.GetValueAsUnsigned(0) == 0:
return "<invalid>"
refcnt = value.GetChildMemberWithName("ob_refcnt")
expr = "(char*)PyString_AsString( (PyObject*)PyObject_Str( (PyObject*)0x%x) )" % (value.GetValueAsUnsigned(0))
expr_summary = value.target.EvaluateExpression(expr,lldb.SBExpressionOptions()).GetSummary()
expr = "(char*)PyString_AsString( (PyObject*)PyObject_Str( (PyObject*)0x%x) )" % (
value.GetValueAsUnsigned(0))
expr_summary = value.target.EvaluateExpression(
expr, lldb.SBExpressionOptions()).GetSummary()
refcnt_value = "rc = %d" % (refcnt.GetValueAsUnsigned(0))
return "%s (%s)" % (expr_summary,refcnt_value)
return "%s (%s)" % (expr_summary, refcnt_value)
def __lldb_init_module(debugger, unused):
debugger.HandleCommand("type summary add PyObject --python-function pysummary.pyobj_summary")
debugger.HandleCommand("type summary add lldb_private::PythonObject -s ${var.m_py_obj%S}")
debugger.HandleCommand("type summary add lldb_private::PythonDictionary -s ${var.m_py_obj%S}")
debugger.HandleCommand("type summary add lldb_private::PythonString -s ${var.m_py_obj%S}")
debugger.HandleCommand(
"type summary add PyObject --python-function pysummary.pyobj_summary")
debugger.HandleCommand(
"type summary add lldb_private::PythonObject -s ${var.m_py_obj%S}")
debugger.HandleCommand(
"type summary add lldb_private::PythonDictionary -s ${var.m_py_obj%S}")
debugger.HandleCommand(
"type summary add lldb_private::PythonString -s ${var.m_py_obj%S}")

View File

@ -6,56 +6,79 @@ This file is distributed under the University of Illinois Open Source
License. See LICENSE.TXT for details.
"""
class SharedPtr_SyntheticChildrenProvider:
def __init__(self,valobj,dict):
def __init__(self, valobj, dict):
self.valobj = valobj
self.update()
def update(self):
pass
def num_children(self):
return 1
def get_child_index(self,name):
def get_child_index(self, name):
if name == "ptr":
return 0
if name == "count":
return 1
return None
def get_child_at_index(self,index):
def get_child_at_index(self, index):
if index == 0:
return self.valobj.GetChildMemberWithName('_M_ptr')
if index == 1:
return self.valobj.GetChildMemberWithName('_M_refcount').GetChildMemberWithName('_M_pi').GetChildMemberWithName('_M_use_count')
return self.valobj.GetChildMemberWithName('_M_refcount').GetChildMemberWithName(
'_M_pi').GetChildMemberWithName('_M_use_count')
return None
def SharedPtr_SummaryProvider (valobj,dict):
return 'use = ' + str(valobj.GetChildMemberWithName("count").GetValueAsUnsigned())
def SharedPtr_SummaryProvider(valobj, dict):
return 'use = ' + \
str(valobj.GetChildMemberWithName("count").GetValueAsUnsigned())
class ValueObjectSP_SyntheticChildrenProvider:
def __init__(self,valobj,dict):
def __init__(self, valobj, dict):
self.valobj = valobj
self.update()
def update(self):
pass
def num_children(self):
return 1
def get_child_index(self,name):
def get_child_index(self, name):
if name == "ptr":
return 0
if name == "count":
return 1
return None
def get_child_at_index(self,index):
def get_child_at_index(self, index):
if index == 0:
return self.valobj.GetChildMemberWithName('ptr_')
if index == 1:
return self.valobj.GetChildMemberWithName('cntrl_').GetChildMemberWithName('shared_owners_')
return self.valobj.GetChildMemberWithName(
'cntrl_').GetChildMemberWithName('shared_owners_')
return None
def ValueObjectSP_SummaryProvider (valobj,dict):
return 'use = ' + str(1 + valobj.GetChildMemberWithName("count").GetValueAsUnsigned())
def ValueObjectSP_SummaryProvider(valobj, dict):
return 'use = ' + \
str(1 + valobj.GetChildMemberWithName("count").GetValueAsUnsigned())
def __lldb_init_module(debugger, dict):
debugger.HandleCommand('type summary add -x ".*ValueObjectSP" --expand -F sp_cp.ValueObjectSP_SummaryProvider')
debugger.HandleCommand('type synthetic add -x ".*ValueObjectSP" -l sp_cp.ValueObjectSP_SyntheticChildrenProvider')
debugger.HandleCommand('type summary add -x ".*SP" --expand -F sp_cp.SharedPtr_SummaryProvider')
debugger.HandleCommand('type synthetic add -x ".*SP" -l sp_cp.SharedPtr_SyntheticChildrenProvider')
debugger.HandleCommand(
'type summary add -x ".*ValueObjectSP" --expand -F sp_cp.ValueObjectSP_SummaryProvider')
debugger.HandleCommand(
'type synthetic add -x ".*ValueObjectSP" -l sp_cp.ValueObjectSP_SyntheticChildrenProvider')
debugger.HandleCommand(
'type summary add -x ".*SP" --expand -F sp_cp.SharedPtr_SummaryProvider')
debugger.HandleCommand(
'type synthetic add -x ".*SP" -l sp_cp.SharedPtr_SyntheticChildrenProvider')

View File

@ -1,6 +1,8 @@
import lldb
class PythonObjectSyntheticChildProvider(object):
def __init__(self, value, internal_dict):
self.value = value
self.values = self.make_children()
@ -17,7 +19,8 @@ class PythonObjectSyntheticChildProvider(object):
def get_child_index(self, name):
i = 0
for N, value in self.values:
if N == name: return i
if N == name:
return i
i += 1
return None
@ -28,19 +31,25 @@ class PythonObjectSyntheticChildProvider(object):
return len(self.values) > 0
def gen_child(self, name, value):
data = None; type = None
data = None
type = None
if isinstance(value, int):
data = lldb.SBData.CreateDataFromUInt32Array(self.bo, self.ps, [value])
data = lldb.SBData.CreateDataFromUInt32Array(
self.bo, self.ps, [value])
type = self.value.target.GetBasicType(lldb.eBasicTypeInt)
elif isinstance(value, long):
data = lldb.SBData.CreateDataFromUInt64Array(self.bo, self.ps, [value])
data = lldb.SBData.CreateDataFromUInt64Array(
self.bo, self.ps, [value])
type = self.value.target.GetBasicType(lldb.eBasicTypeLong)
elif isinstance(value, float):
data = lldb.SBData.CreateDataFromDoubleArray(self.bo, self.ps, [value])
data = lldb.SBData.CreateDataFromDoubleArray(
self.bo, self.ps, [value])
type = self.value.target.GetBasicType(lldb.eBasicTypeDouble)
elif isinstance(value, str):
data = lldb.SBData.CreateDataFromCString(self.bo, self.ps, value)
type = self.value.target.GetBasicType(lldb.eBasicTypeChar).GetArrayType(len(value))
type = self.value.target.GetBasicType(
lldb.eBasicTypeChar).GetArrayType(
len(value))
if (data is not None) and (type is not None):
return self.value.CreateValueFromData(name, data, type)
return None

View File

@ -11,7 +11,9 @@ License. See LICENSE.TXT for details.
"""
import lldb
def utf8_summary(value,unused):
def utf8_summary(value, unused):
pointer = value.GetChildMemberWithName("first").GetValueAsUnsigned(0)
length = value.GetChildMemberWithName("second").GetValueAsUnsigned(0)
if pointer == 0:
@ -22,7 +24,8 @@ def utf8_summary(value,unused):
string_data = value.process.ReadMemory(pointer, length, error)
return '"%s"' % (string_data) # utf8 is safe to emit as-is on OSX
def utf16_summary(value,unused):
def utf16_summary(value, unused):
pointer = value.GetChildMemberWithName("first").GetValueAsUnsigned(0)
length = value.GetChildMemberWithName("second").GetValueAsUnsigned(0)
# assume length is in bytes - if in UTF16 chars, just multiply by 2
@ -32,9 +35,11 @@ def utf16_summary(value,unused):
return '""'
error = lldb.SBError()
string_data = value.process.ReadMemory(pointer, length, error)
return '"%s"' % (string_data.decode('utf-16').encode('utf-8')) # utf8 is safe to emit as-is on OSX
# utf8 is safe to emit as-is on OSX
return '"%s"' % (string_data.decode('utf-16').encode('utf-8'))
def utf32_summary(value,unused):
def utf32_summary(value, unused):
pointer = value.GetChildMemberWithName("first").GetValueAsUnsigned(0)
length = value.GetChildMemberWithName("second").GetValueAsUnsigned(0)
# assume length is in bytes - if in UTF32 chars, just multiply by 4
@ -44,5 +49,5 @@ def utf32_summary(value,unused):
return '""'
error = lldb.SBError()
string_data = value.process.ReadMemory(pointer, length, error)
return '"%s"' % (string_data.decode('utf-32').encode('utf-8')) # utf8 is safe to emit as-is on OSX
# utf8 is safe to emit as-is on OSX
return '"%s"' % (string_data.decode('utf-32').encode('utf-8'))

View File

@ -1,10 +1,16 @@
# Synthetic children provider example for class MaskedData
# to use me:
# command script import ./example.py --allow-reload
# type synthetic add MaskedData --python-class example.MaskedData_SyntheticChildrenProvider
# type synthetic add MaskedData --python-class
# example.MaskedData_SyntheticChildrenProvider
class MaskedData_SyntheticChildrenProvider:
def __init__(self, valobj, dict):
self.valobj = valobj # remember the SBValue since you will not have another chance to get it :-)
# remember the SBValue since you will not have another chance to get it
# :-)
self.valobj = valobj
def num_children(self):
# you could perform calculations involving the SBValue and/or its children to determine this value
@ -16,10 +22,11 @@ class MaskedData_SyntheticChildrenProvider:
def has_children(self):
# we simply say True here because we know we have 4 children
# in general, you want to make this calculation as simple as possible
# and return True if in doubt (you can always return num_children == 0 later)
# and return True if in doubt (you can always return num_children == 0
# later)
return True
def get_child_index(self,name):
def get_child_index(self, name):
# given a name, return its index
# you can return None if you don't know the answer for a given name
if name == "value":
@ -33,12 +40,13 @@ class MaskedData_SyntheticChildrenProvider:
if name == "mask":
return 2
# this member does not exist in the original class - we will compute its value and show it to the user
# when returning synthetic children, there is no need to only stick to what already exists in memory
# when returning synthetic children, there is no need to only stick to
# what already exists in memory
if name == "apply()":
return 3
return None # no clue, just say none
def get_child_at_index(self,index):
def get_child_at_index(self, index):
# precautionary measures
if index < 0:
return None
@ -50,32 +58,45 @@ class MaskedData_SyntheticChildrenProvider:
return self.valobj.GetChildMemberWithName("value")
if index == 1:
# fetch the value of the operator
op_chosen = self.valobj.GetChildMemberWithName("oper").GetValueAsUnsigned()
op_chosen = self.valobj.GetChildMemberWithName(
"oper").GetValueAsUnsigned()
# if it is a known value, return a descriptive string for it
# we are not doing this in the most efficient possible way, but the code is very readable
# and easy to maintain - if you change the values on the C++ side, the same changes must be made here
# and easy to maintain - if you change the values on the C++ side,
# the same changes must be made here
if op_chosen == 0:
return self.valobj.CreateValueFromExpression("operator",'(const char*)"none"')
return self.valobj.CreateValueFromExpression(
"operator", '(const char*)"none"')
elif op_chosen == 1:
return self.valobj.CreateValueFromExpression("operator",'(const char*)"AND"')
return self.valobj.CreateValueFromExpression(
"operator", '(const char*)"AND"')
elif op_chosen == 2:
return self.valobj.CreateValueFromExpression("operator",'(const char*)"OR"')
return self.valobj.CreateValueFromExpression(
"operator", '(const char*)"OR"')
elif op_chosen == 3:
return self.valobj.CreateValueFromExpression("operator",'(const char*)"XOR"')
return self.valobj.CreateValueFromExpression(
"operator", '(const char*)"XOR"')
elif op_chosen == 4:
return self.valobj.CreateValueFromExpression("operator",'(const char*)"NAND"')
return self.valobj.CreateValueFromExpression(
"operator", '(const char*)"NAND"')
elif op_chosen == 5:
return self.valobj.CreateValueFromExpression("operator",'(const char*)"NOR"')
return self.valobj.CreateValueFromExpression(
"operator", '(const char*)"NOR"')
else:
return self.valobj.CreateValueFromExpression("operator",'(const char*)"unknown"') # something else
return self.valobj.CreateValueFromExpression(
"operator", '(const char*)"unknown"') # something else
if index == 2:
return self.valobj.GetChildMemberWithName("mask")
if index == 3:
# for this, we must fetch all the other elements
# in an efficient implementation, we would be caching this data for efficiency
value = self.valobj.GetChildMemberWithName("value").GetValueAsUnsigned()
operator = self.valobj.GetChildMemberWithName("oper").GetValueAsUnsigned()
mask = self.valobj.GetChildMemberWithName("mask").GetValueAsUnsigned()
# in an efficient implementation, we would be caching this data for
# efficiency
value = self.valobj.GetChildMemberWithName(
"value").GetValueAsUnsigned()
operator = self.valobj.GetChildMemberWithName(
"oper").GetValueAsUnsigned()
mask = self.valobj.GetChildMemberWithName(
"mask").GetValueAsUnsigned()
# compute the masked value according to the operator
if operator == 1:
value = value & mask
@ -91,8 +112,10 @@ class MaskedData_SyntheticChildrenProvider:
pass
value &= 0xFFFFFFFF # make sure Python does not extend our values to 64-bits
# return it - again, not the most efficient possible way. we should actually be pushing the computed value
# into an SBData, and using the SBData to create an SBValue - this has the advantage of readability
return self.valobj.CreateValueFromExpression("apply()",'(uint32_t)(' + str(value) + ')')
# into an SBData, and using the SBData to create an SBValue - this
# has the advantage of readability
return self.valobj.CreateValueFromExpression(
"apply()", '(uint32_t)(' + str(value) + ')')
def update(self):
# we do not do anything special in update - but this would be the right place to lookup

View File

@ -1,7 +1,6 @@
typedef unsigned int uint32_t;
enum MaskingOperator
{
enum MaskingOperator {
eMaskingOperatorDefault = 0,
eMaskingOperatorAnd = 1,
eMaskingOperatorOr = 2,
@ -10,26 +9,19 @@ enum MaskingOperator
eMaskingOperatorNor = 5
};
class MaskedData
{
class MaskedData {
private:
uint32_t value;
uint32_t mask;
MaskingOperator oper;
public:
MaskedData( uint32_t V = 0,
uint32_t M = 0,
MaskingOperator P = eMaskingOperatorDefault) :
value(V),
mask(M),
oper(P)
{
}
uint32_t apply()
{
switch(oper)
{
public:
MaskedData(uint32_t V = 0, uint32_t M = 0,
MaskingOperator P = eMaskingOperatorDefault)
: value(V), mask(M), oper(P) {}
uint32_t apply() {
switch (oper) {
case eMaskingOperatorAnd:
return value & mask;
case eMaskingOperatorOr:
@ -46,29 +38,19 @@ public:
}
}
void setValue(uint32_t V)
{
value = V;
}
void setValue(uint32_t V) { value = V; }
void setMask (uint32_t M)
{
mask = M;
}
void setMask(uint32_t M) { mask = M; }
void setOperator(MaskingOperator P)
{
oper = P;
}
void setOperator(MaskingOperator P) { oper = P; }
};
int main()
{
MaskedData data_1(0xFF0F,0xA01F,eMaskingOperatorAnd);
MaskedData data_2(data_1.apply(),0x1AFC,eMaskingOperatorXor);
MaskedData data_3(data_2.apply(),0xFFCF,eMaskingOperatorOr);
MaskedData data_4(data_3.apply(),0xAABC,eMaskingOperatorAnd);
MaskedData data_5(data_4.apply(),0xFFAC,eMaskingOperatorNor);
MaskedData data_6(data_5.apply(),0x0000BEEF,eMaskingOperatorAnd);
int main() {
MaskedData data_1(0xFF0F, 0xA01F, eMaskingOperatorAnd);
MaskedData data_2(data_1.apply(), 0x1AFC, eMaskingOperatorXor);
MaskedData data_3(data_2.apply(), 0xFFCF, eMaskingOperatorOr);
MaskedData data_4(data_3.apply(), 0xAABC, eMaskingOperatorAnd);
MaskedData data_5(data_4.apply(), 0xFFAC, eMaskingOperatorNor);
MaskedData data_6(data_5.apply(), 0x0000BEEF, eMaskingOperatorAnd);
return data_6.apply(); // <-- what comes out of here?
}

View File

@ -7,19 +7,21 @@ import lldb.formatters.Logger
# You are encouraged to look at the STL implementation for your platform
# before relying on these formatters to do the right thing for your setup
class StdListSynthProvider:
def __init__(self, valobj, dict):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj
self.count = None
logger >> "Providing synthetic children for a list named " + str(valobj.GetName())
logger >> "Providing synthetic children for a list named " + \
str(valobj.GetName())
def next_node(self,node):
def next_node(self, node):
logger = lldb.formatters.Logger.Logger()
return node.GetChildMemberWithName('_M_next')
def is_valid(self,node):
def is_valid(self, node):
logger = lldb.formatters.Logger.Logger()
valid = self.value(self.next_node(node)) != self.node_address
if valid:
@ -28,10 +30,11 @@ class StdListSynthProvider:
logger >> "synthetic value is not valid"
return valid
def value(self,node):
def value(self, node):
logger = lldb.formatters.Logger.Logger()
value = node.GetValueAsUnsigned()
logger >> "synthetic value for {}: {}".format(str(self.valobj.GetName()), value)
logger >> "synthetic value for {}: {}".format(
str(self.valobj.GetName()), value)
return value
# Floyd's cycle-finding algorithm
@ -39,7 +42,7 @@ class StdListSynthProvider:
def has_loop(self):
global _list_uses_loop_detector
logger = lldb.formatters.Logger.Logger()
if _list_uses_loop_detector == False:
if not _list_uses_loop_detector:
logger >> "Asked not to use loop detection"
return False
slow = self.next
@ -49,7 +52,8 @@ class StdListSynthProvider:
slow_value = self.value(slow)
fast1 = self.next_node(fast2)
fast2 = self.next_node(fast1)
if self.value(fast1) == slow_value or self.value(fast2) == slow_value:
if self.value(fast1) == slow_value or self.value(
fast2) == slow_value:
return True
slow = self.next_node(slow)
return False
@ -70,7 +74,8 @@ class StdListSynthProvider:
try:
next_val = self.next.GetValueAsUnsigned(0)
prev_val = self.prev.GetValueAsUnsigned(0)
# After a std::list has been initialized, both next and prev will be non-NULL
# After a std::list has been initialized, both next and prev will
# be non-NULL
if next_val == 0 or prev_val == 0:
return 0
if next_val == self.node_address:
@ -81,34 +86,38 @@ class StdListSynthProvider:
return 0
size = 2
current = self.next
while current.GetChildMemberWithName('_M_next').GetValueAsUnsigned(0) != self.node_address:
while current.GetChildMemberWithName(
'_M_next').GetValueAsUnsigned(0) != self.node_address:
size = size + 1
current = current.GetChildMemberWithName('_M_next')
return (size - 1)
except:
return 0;
return 0
def get_child_index(self,name):
def get_child_index(self, name):
logger = lldb.formatters.Logger.Logger()
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1
def get_child_at_index(self,index):
def get_child_at_index(self, index):
logger = lldb.formatters.Logger.Logger()
logger >> "Fetching child " + str(index)
if index < 0:
return None;
return None
if index >= self.num_children():
return None;
return None
try:
offset = index
current = self.next
while offset > 0:
current = current.GetChildMemberWithName('_M_next')
offset = offset - 1
return current.CreateChildAtOffset('['+str(index)+']',2*current.GetType().GetByteSize(),self.data_type)
return current.CreateChildAtOffset(
'[' + str(index) + ']',
2 * current.GetType().GetByteSize(),
self.data_type)
except:
return None
@ -125,7 +134,8 @@ class StdListSynthProvider:
def update(self):
logger = lldb.formatters.Logger.Logger()
# preemptively setting this to None - we might end up changing our mind later
# preemptively setting this to None - we might end up changing our mind
# later
self.count = None
try:
impl = self.valobj.GetChildMemberWithName('_M_impl')
@ -141,15 +151,17 @@ class StdListSynthProvider:
def has_children(self):
return True
class StdVectorSynthProvider:
class StdVectorImplementation(object):
def __init__(self, valobj):
self.valobj = valobj
self.count = None
def num_children(self):
if self.count == None:
if self.count is None:
self.count = self.num_children_impl()
return self.count
@ -177,31 +189,34 @@ class StdVectorSynthProvider:
# if we have a struct (or other data type that the compiler pads to native word size)
# this check might fail, unless the sizeof() we get is itself incremented to take the
# padding bytes into account - on current clang it looks like this is the case
num_children = (finish_val-start_val)
# padding bytes into account - on current clang it looks like
# this is the case
num_children = (finish_val - start_val)
if (num_children % self.data_size) != 0:
return 0
else:
num_children = num_children/self.data_size
num_children = num_children / self.data_size
return num_children
except:
return 0;
return 0
def get_child_at_index(self, index):
logger = lldb.formatters.Logger.Logger()
logger >> "Retrieving child " + str(index)
if index < 0:
return None;
return None
if index >= self.num_children():
return None;
return None
try:
offset = index * self.data_size
return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type)
return self.start.CreateChildAtOffset(
'[' + str(index) + ']', offset, self.data_type)
except:
return None
def update(self):
# preemptively setting this to None - we might end up changing our mind later
# preemptively setting this to None - we might end up changing our
# mind later
self.count = None
try:
impl = self.valobj.GetChildMemberWithName('_M_impl')
@ -210,8 +225,10 @@ class StdVectorSynthProvider:
self.end = impl.GetChildMemberWithName('_M_end_of_storage')
self.data_type = self.start.GetType().GetPointeeType()
self.data_size = self.data_type.GetByteSize()
# if any of these objects is invalid, it means there is no point in trying to fetch anything
if self.start.IsValid() and self.finish.IsValid() and self.end.IsValid() and self.data_type.IsValid():
# if any of these objects is invalid, it means there is no
# point in trying to fetch anything
if self.start.IsValid() and self.finish.IsValid(
) and self.end.IsValid() and self.data_type.IsValid():
self.count = None
else:
self.count = 0
@ -220,6 +237,7 @@ class StdVectorSynthProvider:
return True
class StdVBoolImplementation(object):
def __init__(self, valobj, bool_type):
self.valobj = valobj
self.bool_type = bool_type
@ -239,15 +257,18 @@ class StdVectorSynthProvider:
return None
element_type = self.start_p.GetType().GetPointeeType()
element_bits = 8 * element_type.GetByteSize()
element_offset = (index / element_bits) * element_type.GetByteSize()
element_offset = (index / element_bits) * \
element_type.GetByteSize()
bit_offset = index % element_bits
element = self.start_p.CreateChildAtOffset('['+str(index)+']',element_offset,element_type)
element = self.start_p.CreateChildAtOffset(
'[' + str(index) + ']', element_offset, element_type)
bit = element.GetValueAsUnsigned(0) & (1 << bit_offset)
if bit != 0:
value_expr = "(bool)true"
else:
value_expr = "(bool)false"
return self.valobj.CreateValueFromExpression("[%d]" % index, value_expr)
return self.valobj.CreateValueFromExpression(
"[%d]" % index, value_expr)
def update(self):
try:
@ -266,15 +287,17 @@ class StdVectorSynthProvider:
logger = lldb.formatters.Logger.Logger()
first_template_arg_type = valobj.GetType().GetTemplateArgumentType(0)
if str(first_template_arg_type.GetName()) == "bool":
self.impl = self.StdVBoolImplementation(valobj, first_template_arg_type)
self.impl = self.StdVBoolImplementation(
valobj, first_template_arg_type)
else:
self.impl = self.StdVectorImplementation(valobj)
logger >> "Providing synthetic children for a vector named " + str(valobj.GetName())
logger >> "Providing synthetic children for a vector named " + \
str(valobj.GetName())
def num_children(self):
return self.impl.num_children()
def get_child_index(self,name):
def get_child_index(self, name):
try:
return int(name.lstrip('[').rstrip(']'))
except:
@ -294,9 +317,10 @@ class StdMapSynthProvider:
def __init__(self, valobj, dict):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.count = None
logger >> "Providing synthetic children for a map named " + str(valobj.GetName())
logger >> "Providing synthetic children for a map named " + \
str(valobj.GetName())
# we need this function as a temporary workaround for rdar://problem/10801549
# which prevents us from extracting the std::pair<K,V> SBType out of the template
@ -308,22 +332,24 @@ class StdMapSynthProvider:
def fixup_class_name(self, class_name):
logger = lldb.formatters.Logger.Logger()
if class_name == 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >':
return 'std::basic_string<char>',True
return 'std::basic_string<char>', True
if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
return 'std::basic_string<char>',True
return 'std::basic_string<char>', True
if class_name == 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >':
return 'std::basic_string<char>',True
return 'std::basic_string<char>', True
if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
return 'std::basic_string<char>',True
return class_name,False
return 'std::basic_string<char>', True
return class_name, False
def update(self):
logger = lldb.formatters.Logger.Logger()
# preemptively setting this to None - we might end up changing our mind later
# preemptively setting this to None - we might end up changing our mind
# later
self.count = None
try:
# we will set this to True if we find out that discovering a node in the map takes more steps than the overall size of the RB tree
# if this gets set to True, then we will merrily return None for any child from that moment on
# if this gets set to True, then we will merrily return None for
# any child from that moment on
self.garbage = False
self.Mt = self.valobj.GetChildMemberWithName('_M_t')
self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl')
@ -354,7 +380,7 @@ class StdMapSynthProvider:
def num_children(self):
logger = lldb.formatters.Logger.Logger()
if self.count == None:
if self.count is None:
self.count = self.num_children_impl()
return self.count
@ -363,88 +389,90 @@ class StdMapSynthProvider:
try:
root_ptr_val = self.node_ptr_value(self.Mroot)
if root_ptr_val == 0:
return 0;
count = self.Mimpl.GetChildMemberWithName('_M_node_count').GetValueAsUnsigned(0)
return 0
count = self.Mimpl.GetChildMemberWithName(
'_M_node_count').GetValueAsUnsigned(0)
logger >> "I have " + str(count) + " children available"
return count
except:
return 0;
return 0
def get_child_index(self,name):
def get_child_index(self, name):
logger = lldb.formatters.Logger.Logger()
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1
def get_child_at_index(self,index):
def get_child_at_index(self, index):
logger = lldb.formatters.Logger.Logger()
logger >> "Being asked to fetch child[" + str(index) + "]"
if index < 0:
return None
if index >= self.num_children():
return None;
return None
if self.garbage:
logger >> "Returning None since we are a garbage tree"
return None
try:
offset = index
current = self.left(self.Mheader);
current = self.left(self.Mheader)
while offset > 0:
current = self.increment_node(current)
offset = offset - 1;
offset = offset - 1
# skip all the base stuff and get at the data
return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type)
return current.CreateChildAtOffset(
'[' + str(index) + ']', self.skip_size, self.data_type)
except:
return None
# utility functions
def node_ptr_value(self,node):
def node_ptr_value(self, node):
logger = lldb.formatters.Logger.Logger()
return node.GetValueAsUnsigned(0)
def right(self,node):
def right(self, node):
logger = lldb.formatters.Logger.Logger()
return node.GetChildMemberWithName("_M_right");
return node.GetChildMemberWithName("_M_right")
def left(self,node):
def left(self, node):
logger = lldb.formatters.Logger.Logger()
return node.GetChildMemberWithName("_M_left");
return node.GetChildMemberWithName("_M_left")
def parent(self,node):
def parent(self, node):
logger = lldb.formatters.Logger.Logger()
return node.GetChildMemberWithName("_M_parent");
return node.GetChildMemberWithName("_M_parent")
# from libstdc++ implementation of iterator for rbtree
def increment_node(self,node):
def increment_node(self, node):
logger = lldb.formatters.Logger.Logger()
max_steps = self.num_children()
if self.node_ptr_value(self.right(node)) != 0:
x = self.right(node);
x = self.right(node)
max_steps -= 1
while self.node_ptr_value(self.left(x)) != 0:
x = self.left(x);
x = self.left(x)
max_steps -= 1
logger >> str(max_steps) + " more to go before giving up"
if max_steps <= 0:
self.garbage = True
return None
return x;
return x
else:
x = node;
x = node
y = self.parent(x)
max_steps -= 1
while(self.node_ptr_value(x) == self.node_ptr_value(self.right(y))):
x = y;
y = self.parent(y);
x = y
y = self.parent(y)
max_steps -= 1
logger >> str(max_steps) + " more to go before giving up"
if max_steps <= 0:
self.garbage = True
return None
if self.node_ptr_value(self.right(x)) != self.node_ptr_value(y):
x = y;
return x;
x = y
return x
def has_children(self):
return True

View File

@ -4,14 +4,17 @@ import lldb.formatters.Logger
# libcxx STL formatters for LLDB
# These formatters are based upon the implementation of libc++ that
# ships with current releases of OS X - They will not work for other implementations
# of the standard C++ library - and they are bound to use the libc++-specific namespace
# of the standard C++ library - and they are bound to use the
# libc++-specific namespace
# the std::string summary is just an example for your convenience
# the actual summary that LLDB uses is C++ code inside the debugger's own core
# this could probably be made more efficient but since it only reads a handful of bytes at a time
# we probably don't need to worry too much about this for the time being
def make_string(F,L):
def make_string(F, L):
strval = ''
G = F.GetData().uint8
for X in range(L):
@ -22,15 +25,22 @@ def make_string(F,L):
return '"' + strval + '"'
# if we ever care about big-endian, these two functions might need to change
def is_short_string(value):
return True if (value & 1) == 0 else False
def extract_short_size(value):
return ((value >> 1) % 256)
# some of the members of libc++ std::string are anonymous or have internal names that convey
# no external significance - we access them by index since this saves a name lookup that would add
# no information for readers of the code, but when possible try to use meaningful variable names
def stdstring_SummaryProvider(valobj,dict):
# no information for readers of the code, but when possible try to use
# meaningful variable names
def stdstring_SummaryProvider(valobj, dict):
logger = lldb.formatters.Logger.Logger()
r = valobj.GetChildAtIndex(0)
B = r.GetChildAtIndex(0)
@ -42,29 +52,31 @@ def stdstring_SummaryProvider(valobj,dict):
size_mode = D20.GetChildAtIndex(0).GetValueAsUnsigned(0)
if is_short_string(size_mode):
size = extract_short_size(size_mode)
return make_string(s.GetChildAtIndex(1),size)
return make_string(s.GetChildAtIndex(1), size)
else:
data_ptr = l.GetChildAtIndex(2)
size_vo = l.GetChildAtIndex(1)
size = size_vo.GetValueAsUnsigned(0)+1 # the NULL terminator must be accounted for
if size <= 1 or size == None: # should never be the case
# the NULL terminator must be accounted for
size = size_vo.GetValueAsUnsigned(0) + 1
if size <= 1 or size is None: # should never be the case
return '""'
try:
data = data_ptr.GetPointeeData(0,size)
data = data_ptr.GetPointeeData(0, size)
except:
return '""'
error = lldb.SBError()
strval = data.GetString(error,0)
strval = data.GetString(error, 0)
if error.Fail():
return '<error:' + error.GetCString() + '>'
else:
return '"' + strval + '"'
class stdvector_SynthProvider:
def __init__(self, valobj, dict):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
def num_children(self):
logger = lldb.formatters.Logger.Logger()
@ -85,32 +97,33 @@ class stdvector_SynthProvider:
if start_val >= finish_val:
return 0
num_children = (finish_val-start_val)
num_children = (finish_val - start_val)
if (num_children % self.data_size) != 0:
return 0
else:
num_children = num_children/self.data_size
num_children = num_children / self.data_size
return num_children
except:
return 0;
return 0
def get_child_index(self,name):
def get_child_index(self, name):
logger = lldb.formatters.Logger.Logger()
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1
def get_child_at_index(self,index):
def get_child_at_index(self, index):
logger = lldb.formatters.Logger.Logger()
logger >> "Retrieving child " + str(index)
if index < 0:
return None;
return None
if index >= self.num_children():
return None;
return None
try:
offset = index * self.data_size
return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type)
return self.start.CreateChildAtOffset(
'[' + str(index) + ']', offset, self.data_type)
except:
return None
@ -120,8 +133,10 @@ class stdvector_SynthProvider:
self.start = self.valobj.GetChildMemberWithName('__begin_')
self.finish = self.valobj.GetChildMemberWithName('__end_')
# the purpose of this field is unclear, but it is the only field whose type is clearly T* for a vector<T>
# if this ends up not being correct, we can use the APIs to get at template arguments
data_type_finder = self.valobj.GetChildMemberWithName('__end_cap_').GetChildMemberWithName('__first_')
# if this ends up not being correct, we can use the APIs to get at
# template arguments
data_type_finder = self.valobj.GetChildMemberWithName(
'__end_cap_').GetChildMemberWithName('__first_')
self.data_type = data_type_finder.GetType().GetPointeeType()
self.data_size = self.data_type.GetByteSize()
except:
@ -130,14 +145,18 @@ class stdvector_SynthProvider:
def has_children(self):
return True
# Just an example: the actual summary is produced by a summary string: size=${svar%#}
def stdvector_SummaryProvider(valobj,dict):
prov = stdvector_SynthProvider(valobj,None)
# Just an example: the actual summary is produced by a summary string:
# size=${svar%#}
def stdvector_SummaryProvider(valobj, dict):
prov = stdvector_SynthProvider(valobj, None)
return 'size=' + str(prov.num_children())
class stdlist_entry:
def __init__(self,entry):
def __init__(self, entry):
logger = lldb.formatters.Logger.Logger()
self.entry = entry
@ -161,22 +180,24 @@ class stdlist_entry:
logger = lldb.formatters.Logger.Logger()
return self.entry
next = property(_next_impl,None)
value = property(_value_impl,None)
is_null = property(_isnull_impl,None)
sbvalue = property(_sbvalue_impl,None)
next = property(_next_impl, None)
value = property(_value_impl, None)
is_null = property(_isnull_impl, None)
sbvalue = property(_sbvalue_impl, None)
class stdlist_iterator:
def increment_node(self,node):
def increment_node(self, node):
logger = lldb.formatters.Logger.Logger()
if node.is_null:
return None
return node.next
def __init__(self,node):
def __init__(self, node):
logger = lldb.formatters.Logger.Logger()
self.node = stdlist_entry(node) # we convert the SBValue to an internal node object on entry
# we convert the SBValue to an internal node object on entry
self.node = stdlist_entry(node)
def value(self):
logger = lldb.formatters.Logger.Logger()
@ -185,13 +206,13 @@ class stdlist_iterator:
def next(self):
logger = lldb.formatters.Logger.Logger()
node = self.increment_node(self.node)
if node != None and node.sbvalue.IsValid() and not(node.is_null):
if node is not None and node.sbvalue.IsValid() and not(node.is_null):
self.node = node
return self.value()
else:
return None
def advance(self,N):
def advance(self, N):
logger = lldb.formatters.Logger.Logger()
if N < 0:
return None
@ -206,16 +227,17 @@ class stdlist_iterator:
class stdlist_SynthProvider:
def __init__(self, valobj, dict):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj
self.count = None
def next_node(self,node):
def next_node(self, node):
logger = lldb.formatters.Logger.Logger()
return node.GetChildMemberWithName('__next_')
def value(self,node):
def value(self, node):
logger = lldb.formatters.Logger.Logger()
return node.GetValueAsUnsigned()
@ -224,7 +246,7 @@ class stdlist_SynthProvider:
def has_loop(self):
global _list_uses_loop_detector
logger = lldb.formatters.Logger.Logger()
if _list_uses_loop_detector == False:
if not _list_uses_loop_detector:
logger >> "Asked not to use loop detection"
return False
slow = stdlist_entry(self.head)
@ -242,7 +264,7 @@ class stdlist_SynthProvider:
def num_children(self):
global _list_capping_size
logger = lldb.formatters.Logger.Logger()
if self.count == None:
if self.count is None:
self.count = self.num_children_impl()
if self.count > _list_capping_size:
self.count = _list_capping_size
@ -254,7 +276,8 @@ class stdlist_SynthProvider:
try:
next_val = self.head.GetValueAsUnsigned(0)
prev_val = self.tail.GetValueAsUnsigned(0)
# After a std::list has been initialized, both next and prev will be non-NULL
# After a std::list has been initialized, both next and prev will
# be non-NULL
if next_val == 0 or prev_val == 0:
return 0
if next_val == self.node_address:
@ -272,30 +295,32 @@ class stdlist_SynthProvider:
return _list_capping_size
return (size - 1)
except:
return 0;
return 0
def get_child_index(self,name):
def get_child_index(self, name):
logger = lldb.formatters.Logger.Logger()
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1
def get_child_at_index(self,index):
def get_child_at_index(self, index):
logger = lldb.formatters.Logger.Logger()
logger >> "Fetching child " + str(index)
if index < 0:
return None;
return None
if index >= self.num_children():
return None;
return None
try:
current = stdlist_iterator(self.head)
current = current.advance(index)
# we do not return __value_ because then all our children would be named __value_
# we need to make a copy of __value__ with the right name - unfortunate
# we need to make a copy of __value__ with the right name -
# unfortunate
obj = current.GetChildMemberWithName('__value_')
obj_data = obj.GetData()
return self.valobj.CreateValueFromData('[' + str(index) + ']',obj_data,self.data_type)
return self.valobj.CreateValueFromData(
'[' + str(index) + ']', obj_data, self.data_type)
except:
return None
@ -327,24 +352,32 @@ class stdlist_SynthProvider:
return True
# Just an example: the actual summary is produced by a summary string: size=${svar%#}
def stdlist_SummaryProvider(valobj,dict):
prov = stdlist_SynthProvider(valobj,None)
# Just an example: the actual summary is produced by a summary string:
# size=${svar%#}
def stdlist_SummaryProvider(valobj, dict):
prov = stdlist_SynthProvider(valobj, None)
return 'size=' + str(prov.num_children())
# a tree node - this class makes the syntax in the actual iterator nicer to read and maintain
# a tree node - this class makes the syntax in the actual iterator nicer
# to read and maintain
class stdmap_iterator_node:
def _left_impl(self):
logger = lldb.formatters.Logger.Logger()
return stdmap_iterator_node(self.node.GetChildMemberWithName("__left_"))
return stdmap_iterator_node(
self.node.GetChildMemberWithName("__left_"))
def _right_impl(self):
logger = lldb.formatters.Logger.Logger()
return stdmap_iterator_node(self.node.GetChildMemberWithName("__right_"))
return stdmap_iterator_node(
self.node.GetChildMemberWithName("__right_"))
def _parent_impl(self):
logger = lldb.formatters.Logger.Logger()
return stdmap_iterator_node(self.node.GetChildMemberWithName("__parent_"))
return stdmap_iterator_node(
self.node.GetChildMemberWithName("__parent_"))
def _value_impl(self):
logger = lldb.formatters.Logger.Logger()
@ -358,21 +391,23 @@ class stdmap_iterator_node:
logger = lldb.formatters.Logger.Logger()
return self.value == 0
def __init__(self,node):
def __init__(self, node):
logger = lldb.formatters.Logger.Logger()
self.node = node
left = property(_left_impl,None)
right = property(_right_impl,None)
parent = property(_parent_impl,None)
value = property(_value_impl,None)
is_null = property(_null_impl,None)
sbvalue = property(_sbvalue_impl,None)
left = property(_left_impl, None)
right = property(_right_impl, None)
parent = property(_parent_impl, None)
value = property(_value_impl, None)
is_null = property(_null_impl, None)
sbvalue = property(_sbvalue_impl, None)
# a Python implementation of the tree iterator used by libc++
class stdmap_iterator:
def tree_min(self,x):
def tree_min(self, x):
logger = lldb.formatters.Logger.Logger()
steps = 0
if x.is_null:
@ -385,7 +420,7 @@ class stdmap_iterator:
return None
return x
def tree_max(self,x):
def tree_max(self, x):
logger = lldb.formatters.Logger.Logger()
if x.is_null:
return None
@ -393,13 +428,13 @@ class stdmap_iterator:
x = x.right
return x
def tree_is_left_child(self,x):
def tree_is_left_child(self, x):
logger = lldb.formatters.Logger.Logger()
if x.is_null:
return None
return True if x.value == x.parent.left.value else False
def increment_node(self,node):
def increment_node(self, node):
logger = lldb.formatters.Logger.Logger()
if node.is_null:
return None
@ -414,9 +449,10 @@ class stdmap_iterator:
node = node.parent
return node.parent
def __init__(self,node,max_count=0):
def __init__(self, node, max_count=0):
logger = lldb.formatters.Logger.Logger()
self.node = stdmap_iterator_node(node) # we convert the SBValue to an internal node object on entry
# we convert the SBValue to an internal node object on entry
self.node = stdmap_iterator_node(node)
self.max_count = max_count
def value(self):
@ -426,13 +462,13 @@ class stdmap_iterator:
def next(self):
logger = lldb.formatters.Logger.Logger()
node = self.increment_node(self.node)
if node != None and node.sbvalue.IsValid() and not(node.is_null):
if node is not None and node.sbvalue.IsValid() and not(node.is_null):
self.node = node
return self.value()
else:
return None
def advance(self,N):
def advance(self, N):
logger = lldb.formatters.Logger.Logger()
if N < 0:
return None
@ -441,16 +477,17 @@ class stdmap_iterator:
if N == 1:
return self.next()
while N > 0:
if self.next() == None:
if self.next() is None:
return None
N = N - 1
return self.value()
class stdmap_SynthProvider:
def __init__(self, valobj, dict):
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj;
self.valobj = valobj
self.pointer_size = self.valobj.GetProcess().GetAddressByteSize()
self.count = None
@ -459,7 +496,8 @@ class stdmap_SynthProvider:
self.count = None
try:
# we will set this to True if we find out that discovering a node in the map takes more steps than the overall size of the RB tree
# if this gets set to True, then we will merrily return None for any child from that moment on
# if this gets set to True, then we will merrily return None for
# any child from that moment on
self.garbage = False
self.tree = self.valobj.GetChildMemberWithName('__tree_')
self.root_node = self.tree.GetChildMemberWithName('__begin_node_')
@ -474,7 +512,7 @@ class stdmap_SynthProvider:
def num_children(self):
global _map_capping_size
logger = lldb.formatters.Logger.Logger()
if self.count == None:
if self.count is None:
self.count = self.num_children_impl()
if self.count > _map_capping_size:
self.count = _map_capping_size
@ -483,16 +521,17 @@ class stdmap_SynthProvider:
def num_children_impl(self):
logger = lldb.formatters.Logger.Logger()
try:
return self.valobj.GetChildMemberWithName('__tree_').GetChildMemberWithName('__pair3_').GetChildMemberWithName('__first_').GetValueAsUnsigned()
return self.valobj.GetChildMemberWithName('__tree_').GetChildMemberWithName(
'__pair3_').GetChildMemberWithName('__first_').GetValueAsUnsigned()
except:
return 0;
return 0
def has_children(self):
return True
def get_data_type(self):
logger = lldb.formatters.Logger.Logger()
if self.data_type == None or self.data_size == None:
if self.data_type is None or self.data_size is None:
if self.num_children() == 0:
return False
deref = self.root_node.Dereference()
@ -508,9 +547,9 @@ class stdmap_SynthProvider:
else:
return True
def get_value_offset(self,node):
def get_value_offset(self, node):
logger = lldb.formatters.Logger.Logger()
if self.skip_size == None:
if self.skip_size is None:
node_type = node.GetType()
fields_count = node_type.GetNumberOfFields()
for i in range(fields_count):
@ -518,34 +557,36 @@ class stdmap_SynthProvider:
if field.GetName() == '__value_':
self.skip_size = field.GetOffsetInBytes()
break
return (self.skip_size != None)
return (self.skip_size is not None)
def get_child_index(self,name):
def get_child_index(self, name):
logger = lldb.formatters.Logger.Logger()
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1
def get_child_at_index(self,index):
def get_child_at_index(self, index):
logger = lldb.formatters.Logger.Logger()
logger >> "Retrieving child " + str(index)
if index < 0:
return None
if index >= self.num_children():
return None;
return None
if self.garbage:
logger >> "Returning None since this tree is garbage"
return None
try:
iterator = stdmap_iterator(self.root_node,max_count=self.num_children())
iterator = stdmap_iterator(
self.root_node, max_count=self.num_children())
# the debug info for libc++ std::map is such that __begin_node_ has a very nice and useful type
# out of which we can grab the information we need - every other node has a less informative
# type which omits all value information and only contains housekeeping information for the RB tree
# hence, we need to know if we are at a node != 0, so that we can still get at the data
# hence, we need to know if we are at a node != 0, so that we can
# still get at the data
need_to_skip = (index > 0)
current = iterator.advance(index)
if current == None:
if current is None:
logger >> "Tree is garbage - returning None"
self.garbage = True
return None
@ -554,20 +595,24 @@ class stdmap_SynthProvider:
current = current.Dereference()
obj = current.GetChildMemberWithName('__value_')
obj_data = obj.GetData()
self.get_value_offset(current) # make sure we have a valid offset for the next items
# make sure we have a valid offset for the next items
self.get_value_offset(current)
# we do not return __value_ because then we would end up with a child named
# __value_ instead of [0]
return self.valobj.CreateValueFromData('[' + str(index) + ']',obj_data,self.data_type)
return self.valobj.CreateValueFromData(
'[' + str(index) + ']', obj_data, self.data_type)
else:
# FIXME we need to have accessed item 0 before accessing any other item!
if self.skip_size == None:
# FIXME we need to have accessed item 0 before accessing
# any other item!
if self.skip_size is None:
logger >> "You asked for item > 0 before asking for item == 0, I will fetch 0 now then retry"
if self.get_child_at_index(0):
return self.get_child_at_index(index)
else:
logger >> "item == 0 could not be found. sorry, nothing can be done here."
return None
return current.CreateChildAtOffset('[' + str(index) + ']',self.skip_size,self.data_type)
return current.CreateChildAtOffset(
'[' + str(index) + ']', self.skip_size, self.data_type)
else:
logger >> "Unable to infer data-type - returning None (should mark tree as garbage here?)"
return None
@ -575,12 +620,17 @@ class stdmap_SynthProvider:
logger >> "Hit an exception: " + str(err)
return None
# Just an example: the actual summary is produced by a summary string: size=${svar%#}
def stdmap_SummaryProvider(valobj,dict):
prov = stdmap_SynthProvider(valobj,None)
# Just an example: the actual summary is produced by a summary string:
# size=${svar%#}
def stdmap_SummaryProvider(valobj, dict):
prov = stdmap_SynthProvider(valobj, None)
return 'size=' + str(prov.num_children())
class stddeque_SynthProvider:
def __init__(self, valobj, d):
logger = lldb.formatters.Logger.Logger()
logger.write("init")
@ -592,7 +642,9 @@ class stddeque_SynthProvider:
except:
self.block_size = -1
self.element_size = -1
logger.write("block_size=%d, element_size=%d" % (self.block_size, self.element_size))
logger.write(
"block_size=%d, element_size=%d" %
(self.block_size, self.element_size))
def find_block_size(self):
# in order to use the deque we must have the block size, or else
@ -619,24 +671,25 @@ class stddeque_SynthProvider:
def has_children(self):
return True
def get_child_index(self,name):
def get_child_index(self, name):
logger = lldb.formatters.Logger.Logger()
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1
def get_child_at_index(self,index):
def get_child_at_index(self, index):
logger = lldb.formatters.Logger.Logger()
logger.write("Fetching child " + str(index))
if index < 0 or self.count is None:
return None;
return None
if index >= self.num_children():
return None;
return None
try:
i, j = divmod(self.start+index, self.block_size)
return self.first.CreateValueFromExpression('[' + str(index) + ']',
'*(*(%s + %d) + %d)' % (self.first.get_expr_path(), i, j))
i, j = divmod(self.start + index, self.block_size)
return self.first.CreateValueFromExpression(
'[' + str(index) + ']', '*(*(%s + %d) + %d)' %
(self.first.get_expr_path(), i, j))
except:
return None
@ -656,23 +709,29 @@ class stddeque_SynthProvider:
# variable tells which element in this NxM array is the 0th
# one, and the 'size' element gives the number of elements
# in the deque.
count = self.valobj.GetChildMemberWithName('__size_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
count = self.valobj.GetChildMemberWithName(
'__size_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
# give up now if we cant access memory reliably
if self.block_size < 0:
logger.write("block_size < 0")
return
map_ = self.valobj.GetChildMemberWithName('__map_')
start = self.valobj.GetChildMemberWithName('__start_').GetValueAsUnsigned(0)
start = self.valobj.GetChildMemberWithName(
'__start_').GetValueAsUnsigned(0)
first = map_.GetChildMemberWithName('__first_')
map_first = first.GetValueAsUnsigned(0)
map_begin = map_.GetChildMemberWithName('__begin_').GetValueAsUnsigned(0)
map_end = map_.GetChildMemberWithName('__end_').GetValueAsUnsigned(0)
map_endcap= map_.GetChildMemberWithName('__end_cap_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
map_begin = map_.GetChildMemberWithName(
'__begin_').GetValueAsUnsigned(0)
map_end = map_.GetChildMemberWithName(
'__end_').GetValueAsUnsigned(0)
map_endcap = map_.GetChildMemberWithName(
'__end_cap_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
# check consistency
if not map_first <= map_begin <= map_end <= map_endcap:
logger.write("map pointers are not monotonic")
return
total_rows, junk = divmod(map_endcap - map_first, self.pointer_size)
total_rows, junk = divmod(
map_endcap - map_first, self.pointer_size)
if junk:
logger.write("endcap-first doesnt align correctly")
return
@ -684,7 +743,8 @@ class stddeque_SynthProvider:
if junk:
logger.write("begin-first doesnt align correctly")
return
if not start_row*self.block_size <= start < (start_row+1)*self.block_size:
if not start_row * \
self.block_size <= start < (start_row + 1) * self.block_size:
logger.write("0th element must be in the 'begin' row")
return
end_row = start_row + active_rows
@ -692,10 +752,12 @@ class stddeque_SynthProvider:
if active_rows:
logger.write("empty deque but begin!=end")
return
elif not (end_row-1)*self.block_size <= start+count < end_row*self.block_size:
elif not (end_row - 1) * self.block_size <= start + count < end_row * self.block_size:
logger.write("nth element must be before the 'end' row")
return
logger.write("update success: count=%r, start=%r, first=%r" % (count,start,first))
logger.write(
"update success: count=%r, start=%r, first=%r" %
(count, start, first))
# if consistent, save all we really need:
self.count = count
self.start = start
@ -706,7 +768,9 @@ class stddeque_SynthProvider:
self.map_first = None
self.map_begin = None
class stdsharedptr_SynthProvider:
def __init__(self, valobj, d):
logger = lldb.formatters.Logger.Logger()
logger.write("init")
@ -725,39 +789,42 @@ class stdsharedptr_SynthProvider:
def has_children(self):
return True
def get_child_index(self,name):
if name=="__ptr_":
def get_child_index(self, name):
if name == "__ptr_":
return 0
if name=="count":
if name == "count":
return 1
if name=="weak_count":
if name == "weak_count":
return 2
return -1
def get_child_at_index(self,index):
def get_child_at_index(self, index):
if index == 0:
return self.ptr
if index == 1:
if self.cntrl == None:
if self.cntrl is None:
count = 0
else:
count = 1 + self.cntrl.GetChildMemberWithName('__shared_owners_').GetValueAsSigned()
return self.valobj.CreateValueFromData("count",
lldb.SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [count]),
self.count_type)
count = 1 + \
self.cntrl.GetChildMemberWithName('__shared_owners_').GetValueAsSigned()
return self.valobj.CreateValueFromData(
"count", lldb.SBData.CreateDataFromUInt64Array(
self.endianness, self.pointer_size, [count]), self.count_type)
if index == 2:
if self.cntrl == None:
if self.cntrl is None:
count = 0
else:
count = 1 + self.cntrl.GetChildMemberWithName('__shared_weak_owners_').GetValueAsSigned()
return self.valobj.CreateValueFromData("weak_count",
lldb.SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [count]),
self.count_type)
count = 1 + \
self.cntrl.GetChildMemberWithName('__shared_weak_owners_').GetValueAsSigned()
return self.valobj.CreateValueFromData(
"weak_count", lldb.SBData.CreateDataFromUInt64Array(
self.endianness, self.pointer_size, [count]), self.count_type)
return None
def update(self):
logger = lldb.formatters.Logger.Logger()
self.ptr = self.valobj.GetChildMemberWithName('__ptr_')#.Cast(self.element_ptr_type)
self.ptr = self.valobj.GetChildMemberWithName(
'__ptr_') # .Cast(self.element_ptr_type)
cntrl = self.valobj.GetChildMemberWithName('__cntrl_')
if cntrl.GetValueAsUnsigned(0):
self.cntrl = cntrl.Dereference()
@ -765,21 +832,36 @@ class stdsharedptr_SynthProvider:
self.cntrl = None
# we can use two different categories for old and new formatters - type names are different enough that we should make no confusion
# talking with libc++ developer: "std::__1::class_name is set in stone until we decide to change the ABI. That shouldn't happen within a 5 year time frame"
def __lldb_init_module(debugger,dict):
debugger.HandleCommand('type summary add -F libcxx.stdstring_SummaryProvider "std::__1::string" -w libcxx')
debugger.HandleCommand('type summary add -F libcxx.stdstring_SummaryProvider "std::__1::basic_string<char, class std::__1::char_traits<char>, class std::__1::allocator<char> >" -w libcxx')
debugger.HandleCommand('type synthetic add -l libcxx.stdvector_SynthProvider -x "^(std::__1::)vector<.+>$" -w libcxx')
debugger.HandleCommand('type summary add -F libcxx.stdvector_SummaryProvider -e -x "^(std::__1::)vector<.+>$" -w libcxx')
debugger.HandleCommand('type synthetic add -l libcxx.stdlist_SynthProvider -x "^(std::__1::)list<.+>$" -w libcxx')
debugger.HandleCommand('type summary add -F libcxx.stdlist_SummaryProvider -e -x "^(std::__1::)list<.+>$" -w libcxx')
debugger.HandleCommand('type synthetic add -l libcxx.stdmap_SynthProvider -x "^(std::__1::)map<.+> >$" -w libcxx')
debugger.HandleCommand('type summary add -F libcxx.stdmap_SummaryProvider -e -x "^(std::__1::)map<.+> >$" -w libcxx')
# talking with libc++ developer: "std::__1::class_name is set in stone
# until we decide to change the ABI. That shouldn't happen within a 5 year
# time frame"
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
'type summary add -F libcxx.stdstring_SummaryProvider "std::__1::string" -w libcxx')
debugger.HandleCommand(
'type summary add -F libcxx.stdstring_SummaryProvider "std::__1::basic_string<char, class std::__1::char_traits<char>, class std::__1::allocator<char> >" -w libcxx')
debugger.HandleCommand(
'type synthetic add -l libcxx.stdvector_SynthProvider -x "^(std::__1::)vector<.+>$" -w libcxx')
debugger.HandleCommand(
'type summary add -F libcxx.stdvector_SummaryProvider -e -x "^(std::__1::)vector<.+>$" -w libcxx')
debugger.HandleCommand(
'type synthetic add -l libcxx.stdlist_SynthProvider -x "^(std::__1::)list<.+>$" -w libcxx')
debugger.HandleCommand(
'type summary add -F libcxx.stdlist_SummaryProvider -e -x "^(std::__1::)list<.+>$" -w libcxx')
debugger.HandleCommand(
'type synthetic add -l libcxx.stdmap_SynthProvider -x "^(std::__1::)map<.+> >$" -w libcxx')
debugger.HandleCommand(
'type summary add -F libcxx.stdmap_SummaryProvider -e -x "^(std::__1::)map<.+> >$" -w libcxx')
debugger.HandleCommand("type category enable libcxx")
debugger.HandleCommand('type synthetic add -l libcxx.stddeque_SynthProvider -x "^(std::__1::)deque<.+>$" -w libcxx')
debugger.HandleCommand('type synthetic add -l libcxx.stdsharedptr_SynthProvider -x "^(std::__1::)shared_ptr<.+>$" -w libcxx')
debugger.HandleCommand(
'type synthetic add -l libcxx.stddeque_SynthProvider -x "^(std::__1::)deque<.+>$" -w libcxx')
debugger.HandleCommand(
'type synthetic add -l libcxx.stdsharedptr_SynthProvider -x "^(std::__1::)shared_ptr<.+>$" -w libcxx')
# turns out the structs look the same, so weak_ptr can be handled the same!
debugger.HandleCommand('type synthetic add -l libcxx.stdsharedptr_SynthProvider -x "^(std::__1::)weak_ptr<.+>$" -w libcxx')
debugger.HandleCommand(
'type synthetic add -l libcxx.stdsharedptr_SynthProvider -x "^(std::__1::)weak_ptr<.+>$" -w libcxx')
_map_capping_size = 255
_list_capping_size = 255

View File

@ -2,7 +2,9 @@ import lldb
_map_capping_size = 255
class libcxx_hash_table_SynthProvider:
def __init__(self, valobj, dict):
self.valobj = valobj
self.num_elements = None
@ -34,15 +36,21 @@ class libcxx_hash_table_SynthProvider:
#
table = self.valobj.GetChildMemberWithName('__table_')
bl_ptr = table.GetChildMemberWithName('__bucket_list_').GetChildMemberWithName('__ptr_')
self.bucket_array_ptr = bl_ptr.GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
self.bucket_count = bl_ptr.GetChildMemberWithName('__second_').GetChildMemberWithName('__data_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
bl_ptr = table.GetChildMemberWithName(
'__bucket_list_').GetChildMemberWithName('__ptr_')
self.bucket_array_ptr = bl_ptr.GetChildMemberWithName(
'__first_').GetValueAsUnsigned(0)
self.bucket_count = bl_ptr.GetChildMemberWithName('__second_').GetChildMemberWithName(
'__data_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
logger >> "Bucket count = %r" % self.bucket_count
self.begin_ptr = table.GetChildMemberWithName('__p1_').GetChildMemberWithName('__first_').GetChildMemberWithName('__next_')
self.begin_ptr = table.GetChildMemberWithName('__p1_').GetChildMemberWithName(
'__first_').GetChildMemberWithName('__next_')
self.num_elements = table.GetChildMemberWithName('__p2_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
self.max_load_factor = table.GetChildMemberWithName('__p3_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
self.num_elements = table.GetChildMemberWithName(
'__p2_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
self.max_load_factor = table.GetChildMemberWithName(
'__p3_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
logger >> "Num elements = %r" % self.num_elements
# save the pointers as we get them
@ -67,14 +75,14 @@ class libcxx_hash_table_SynthProvider:
def has_children(self):
return True
def get_child_index(self,name):
def get_child_index(self, name):
logger = lldb.formatters.Logger.Logger()
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1
def get_child_at_index(self,index):
def get_child_at_index(self, index):
logger = lldb.formatters.Logger.Logger()
logger >> "Retrieving child " + str(index)
if index < 0:
@ -83,7 +91,8 @@ class libcxx_hash_table_SynthProvider:
return None
# extend
logger >> " : cache size starts with %d elements" % len(self.elements_cache)
logger >> " : cache size starts with %d elements" % len(
self.elements_cache)
while index >= len(self.elements_cache):
# if we hit the end before we get the index, give up:
if not self.next_element:
@ -93,7 +102,8 @@ class libcxx_hash_table_SynthProvider:
node = self.next_element.Dereference()
value = node.GetChildMemberWithName('__value_')
hash_value = node.GetChildMemberWithName('__hash_').GetValueAsUnsigned()
hash_value = node.GetChildMemberWithName(
'__hash_').GetValueAsUnsigned()
self.elements_cache.append((value, hash_value))
self.next_element = node.GetChildMemberWithName('__next_')
@ -101,10 +111,14 @@ class libcxx_hash_table_SynthProvider:
self.next_element = None
# hit the index! so we have the value
logger >> " : cache size ends with %d elements" % len(self.elements_cache)
logger >> " : cache size ends with %d elements" % len(
self.elements_cache)
value, hash_value = self.elements_cache[index]
return self.valobj.CreateValueFromData('[%d] <hash %d>'%(index,hash_value), value.GetData(), value.GetType())
return self.valobj.CreateValueFromData(
'[%d] <hash %d>' %
(index, hash_value), value.GetData(), value.GetType())
def __lldb_init_module(debugger,dict):
debugger.HandleCommand('type synthetic add -l unordered_multi.libcxx_hash_table_SynthProvider -x "^(std::__1::)unordered_(multi)?(map|set)<.+> >$" -w libcxx')
def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
'type synthetic add -l unordered_multi.libcxx_hash_table_SynthProvider -x "^(std::__1::)unordered_(multi)?(map|set)<.+> >$" -w libcxx')

View File

@ -14,7 +14,6 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBAttachInfo.h"
#include "lldb/API/SBBlock.h"
@ -28,6 +27,7 @@
#include "lldb/API/SBData.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBDeclaration.h"
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBExecutionContext.h"

View File

@ -15,47 +15,35 @@
namespace lldb {
class LLDB_API SBAddress
{
class LLDB_API SBAddress {
public:
SBAddress();
SBAddress ();
SBAddress(const lldb::SBAddress &rhs);
SBAddress (const lldb::SBAddress &rhs);
SBAddress (lldb::SBSection section, lldb::addr_t offset);
SBAddress(lldb::SBSection section, lldb::addr_t offset);
// Create an address by resolving a load address using the supplied target
SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target);
SBAddress(lldb::addr_t load_addr, lldb::SBTarget &target);
~SBAddress ();
~SBAddress();
const lldb::SBAddress &
operator = (const lldb::SBAddress &rhs);
const lldb::SBAddress &operator=(const lldb::SBAddress &rhs);
bool
IsValid () const;
bool IsValid() const;
void
Clear ();
void Clear();
addr_t
GetFileAddress () const;
addr_t GetFileAddress() const;
addr_t
GetLoadAddress (const lldb::SBTarget &target) const;
addr_t GetLoadAddress(const lldb::SBTarget &target) const;
void
SetAddress (lldb::SBSection section, lldb::addr_t offset);
void SetAddress(lldb::SBSection section, lldb::addr_t offset);
void
SetLoadAddress (lldb::addr_t load_addr,
lldb::SBTarget &target);
bool
OffsetAddress (addr_t offset);
void SetLoadAddress(lldb::addr_t load_addr, lldb::SBTarget &target);
bool OffsetAddress(addr_t offset);
bool
GetDescription (lldb::SBStream &description);
bool GetDescription(lldb::SBStream &description);
// The following queries can lookup symbol information for a given address.
// An address might refer to code or data from an existing module, or it
@ -63,48 +51,38 @@ public:
// will only return valid values if the address has been resolved to a code
// or data address using "void SBAddress::SetLoadAddress(...)" or
// "lldb::SBAddress SBTarget::ResolveLoadAddress (...)".
lldb::SBSymbolContext
GetSymbolContext (uint32_t resolve_scope);
lldb::SBSymbolContext GetSymbolContext(uint32_t resolve_scope);
// The following functions grab individual objects for a given address and
// are less efficient if you want more than one symbol related objects.
// Use one of the following when you want multiple debug symbol related
// objects for an address:
// lldb::SBSymbolContext SBAddress::GetSymbolContext (uint32_t resolve_scope);
// lldb::SBSymbolContext SBTarget::ResolveSymbolContextForAddress (const SBAddress &addr, uint32_t resolve_scope);
// lldb::SBSymbolContext SBAddress::GetSymbolContext (uint32_t
// resolve_scope);
// lldb::SBSymbolContext SBTarget::ResolveSymbolContextForAddress (const
// SBAddress &addr, uint32_t resolve_scope);
// One or more bits from the SymbolContextItem enumerations can be logically
// OR'ed together to more efficiently retrieve multiple symbol objects.
lldb::SBSection
GetSection ();
lldb::SBSection GetSection();
lldb::addr_t
GetOffset ();
lldb::addr_t GetOffset();
lldb::SBModule
GetModule ();
lldb::SBModule GetModule();
lldb::SBCompileUnit
GetCompileUnit ();
lldb::SBCompileUnit GetCompileUnit();
lldb::SBFunction
GetFunction ();
lldb::SBFunction GetFunction();
lldb::SBBlock
GetBlock ();
lldb::SBBlock GetBlock();
lldb::SBSymbol
GetSymbol ();
lldb::SBSymbol GetSymbol();
lldb::SBLineEntry
GetLineEntry ();
lldb::SBLineEntry GetLineEntry();
lldb::AddressClass
GetAddressClass ();
lldb::AddressClass GetAddressClass();
protected:
friend class SBBlock;
friend class SBBreakpointLocation;
friend class SBFrame;
@ -121,32 +99,24 @@ protected:
friend class SBValue;
friend class SBQueueItem;
lldb_private::Address *
operator->();
lldb_private::Address *operator->();
const lldb_private::Address *
operator->() const;
const lldb_private::Address *operator->() const;
lldb_private::Address *
get ();
lldb_private::Address *get();
lldb_private::Address &
ref();
lldb_private::Address &ref();
const lldb_private::Address &
ref() const;
const lldb_private::Address &ref() const;
SBAddress (const lldb_private::Address *lldb_object_ptr);
SBAddress(const lldb_private::Address *lldb_object_ptr);
void
SetAddress (const lldb_private::Address *lldb_object_ptr);
void SetAddress(const lldb_private::Address *lldb_object_ptr);
private:
std::unique_ptr<lldb_private::Address> m_opaque_ap;
};
} // namespace lldb
#endif // LLDB_SBAddress_h_

View File

@ -16,12 +16,11 @@ namespace lldb {
class SBTarget;
class LLDB_API SBAttachInfo
{
class LLDB_API SBAttachInfo {
public:
SBAttachInfo ();
SBAttachInfo();
SBAttachInfo (lldb::pid_t pid);
SBAttachInfo(lldb::pid_t pid);
//------------------------------------------------------------------
/// Attach to a process by name.
@ -36,7 +35,7 @@ public:
/// If \b false, attach to an existing process whose name matches.
/// If \b true, then wait for the next process whose name matches.
//------------------------------------------------------------------
SBAttachInfo (const char *path, bool wait_for);
SBAttachInfo(const char *path, bool wait_for);
//------------------------------------------------------------------
/// Attach to a process by name.
@ -62,29 +61,23 @@ public:
/// SBProcess::Stop() can be called and an eStateExited process
/// event will be delivered.
//------------------------------------------------------------------
SBAttachInfo (const char *path, bool wait_for, bool async);
SBAttachInfo(const char *path, bool wait_for, bool async);
SBAttachInfo (const SBAttachInfo &rhs);
SBAttachInfo(const SBAttachInfo &rhs);
~SBAttachInfo();
SBAttachInfo &
operator = (const SBAttachInfo &rhs);
SBAttachInfo &operator=(const SBAttachInfo &rhs);
lldb::pid_t
GetProcessID ();
lldb::pid_t GetProcessID();
void
SetProcessID (lldb::pid_t pid);
void SetProcessID(lldb::pid_t pid);
void
SetExecutable (const char *path);
void SetExecutable(const char *path);
void
SetExecutable (lldb::SBFileSpec exe_file);
void SetExecutable(lldb::SBFileSpec exe_file);
bool
GetWaitForLaunch ();
bool GetWaitForLaunch();
//------------------------------------------------------------------
/// Set attach by process name settings.
@ -97,8 +90,7 @@ public:
/// If \b false, attach to an existing process whose name matches.
/// If \b true, then wait for the next process whose name matches.
//------------------------------------------------------------------
void
SetWaitForLaunch (bool b);
void SetWaitForLaunch(bool b);
//------------------------------------------------------------------
/// Set attach by process name settings.
@ -122,71 +114,49 @@ public:
/// SBProcess::Stop() can be called and an eStateExited process
/// event will be delivered.
//------------------------------------------------------------------
void
SetWaitForLaunch (bool b, bool async);
void SetWaitForLaunch(bool b, bool async);
bool
GetIgnoreExisting ();
bool GetIgnoreExisting();
void
SetIgnoreExisting (bool b);
void SetIgnoreExisting(bool b);
uint32_t
GetResumeCount ();
uint32_t GetResumeCount();
void
SetResumeCount (uint32_t c);
void SetResumeCount(uint32_t c);
const char *
GetProcessPluginName ();
const char *GetProcessPluginName();
void
SetProcessPluginName (const char *plugin_name);
void SetProcessPluginName(const char *plugin_name);
uint32_t
GetUserID();
uint32_t GetUserID();
uint32_t
GetGroupID();
uint32_t GetGroupID();
bool
UserIDIsValid ();
bool UserIDIsValid();
bool
GroupIDIsValid ();
bool GroupIDIsValid();
void
SetUserID (uint32_t uid);
void SetUserID(uint32_t uid);
void
SetGroupID (uint32_t gid);
void SetGroupID(uint32_t gid);
uint32_t
GetEffectiveUserID();
uint32_t GetEffectiveUserID();
uint32_t
GetEffectiveGroupID();
uint32_t GetEffectiveGroupID();
bool
EffectiveUserIDIsValid ();
bool EffectiveUserIDIsValid();
bool
EffectiveGroupIDIsValid ();
bool EffectiveGroupIDIsValid();
void
SetEffectiveUserID (uint32_t uid);
void SetEffectiveUserID(uint32_t uid);
void
SetEffectiveGroupID (uint32_t gid);
void SetEffectiveGroupID(uint32_t gid);
lldb::pid_t
GetParentProcessID ();
lldb::pid_t GetParentProcessID();
void
SetParentProcessID (lldb::pid_t pid);
void SetParentProcessID(lldb::pid_t pid);
bool
ParentProcessIDIsValid();
bool ParentProcessIDIsValid();
//----------------------------------------------------------------------
/// Get the listener that will be used to receive process events.
@ -196,8 +166,7 @@ public:
/// returned (SBListener::IsValid() will return false). If a listener
/// has been set, then the valid listener object will be returned.
//----------------------------------------------------------------------
SBListener
GetListener ();
SBListener GetListener();
//----------------------------------------------------------------------
/// Set the listener that will be used to receive process events.
@ -206,15 +175,12 @@ public:
/// belongs to will listen for the process events. Calling this function
/// allows a different listener to be used to listen for process events.
//----------------------------------------------------------------------
void
SetListener (SBListener &listener);
void SetListener(SBListener &listener);
protected:
friend class SBTarget;
lldb_private::ProcessAttachInfo &
ref ();
lldb_private::ProcessAttachInfo &ref();
ProcessAttachInfoSP m_opaque_sp;
};

View File

@ -17,70 +17,48 @@
namespace lldb {
class LLDB_API SBBlock
{
class LLDB_API SBBlock {
public:
SBBlock();
SBBlock ();
SBBlock(const lldb::SBBlock &rhs);
SBBlock (const lldb::SBBlock &rhs);
~SBBlock();
~SBBlock ();
const lldb::SBBlock &operator=(const lldb::SBBlock &rhs);
const lldb::SBBlock &
operator = (const lldb::SBBlock &rhs);
bool IsInlined() const;
bool
IsInlined () const;
bool IsValid() const;
bool
IsValid () const;
const char *GetInlinedName() const;
const char *
GetInlinedName () const;
lldb::SBFileSpec GetInlinedCallSiteFile() const;
lldb::SBFileSpec
GetInlinedCallSiteFile () const;
uint32_t GetInlinedCallSiteLine() const;
uint32_t
GetInlinedCallSiteLine () const;
uint32_t GetInlinedCallSiteColumn() const;
uint32_t
GetInlinedCallSiteColumn () const;
lldb::SBBlock GetParent();
lldb::SBBlock
GetParent ();
lldb::SBBlock GetSibling();
lldb::SBBlock
GetSibling ();
lldb::SBBlock GetFirstChild();
lldb::SBBlock
GetFirstChild ();
uint32_t GetNumRanges();
uint32_t
GetNumRanges ();
lldb::SBAddress GetRangeStartAddress(uint32_t idx);
lldb::SBAddress
GetRangeStartAddress (uint32_t idx);
lldb::SBAddress GetRangeEndAddress(uint32_t idx);
lldb::SBAddress
GetRangeEndAddress (uint32_t idx);
uint32_t GetRangeIndexForBlockAddress(lldb::SBAddress block_addr);
uint32_t
GetRangeIndexForBlockAddress (lldb::SBAddress block_addr);
lldb::SBValueList
GetVariables (lldb::SBFrame& frame,
bool arguments,
bool locals,
bool statics,
lldb::SBValueList GetVariables(lldb::SBFrame &frame, bool arguments,
bool locals, bool statics,
lldb::DynamicValueType use_dynamic);
lldb::SBValueList
GetVariables (lldb::SBTarget& target,
bool arguments,
bool locals,
bool statics);
lldb::SBValueList GetVariables(lldb::SBTarget &target, bool arguments,
bool locals, bool statics);
//------------------------------------------------------------------
/// Get the inlined block that contains this block.
///
@ -91,11 +69,9 @@ public:
/// be returned if this block nor any parent blocks are inlined
/// function blocks.
//------------------------------------------------------------------
lldb::SBBlock
GetContainingInlinedBlock ();
lldb::SBBlock GetContainingInlinedBlock();
bool
GetDescription (lldb::SBStream &description);
bool GetDescription(lldb::SBStream &description);
private:
friend class SBAddress;
@ -103,21 +79,18 @@ private:
friend class SBFunction;
friend class SBSymbolContext;
lldb_private::Block *
GetPtr ();
lldb_private::Block *GetPtr();
void
SetPtr (lldb_private::Block *lldb_object_ptr);
void SetPtr(lldb_private::Block *lldb_object_ptr);
SBBlock (lldb_private::Block *lldb_object_ptr);
SBBlock(lldb_private::Block *lldb_object_ptr);
void
AppendVariables (bool can_create, bool get_parent_variables, lldb_private::VariableList *var_list);
void AppendVariables(bool can_create, bool get_parent_variables,
lldb_private::VariableList *var_list);
lldb_private::Block *m_opaque_ptr;
};
} // namespace lldb
#endif // LLDB_SBBlock_h_

View File

@ -14,176 +14,127 @@
namespace lldb {
class LLDB_API SBBreakpoint
{
class LLDB_API SBBreakpoint {
public:
typedef bool (*BreakpointHitCallback) (void *baton,
SBProcess &process,
typedef bool (*BreakpointHitCallback)(void *baton, SBProcess &process,
SBThread &thread,
lldb::SBBreakpointLocation &location);
SBBreakpoint ();
SBBreakpoint();
SBBreakpoint (const lldb::SBBreakpoint& rhs);
SBBreakpoint(const lldb::SBBreakpoint &rhs);
~SBBreakpoint();
const lldb::SBBreakpoint &
operator = (const lldb::SBBreakpoint& rhs);
const lldb::SBBreakpoint &operator=(const lldb::SBBreakpoint &rhs);
// Tests to see if the opaque breakpoint object in this object matches the
// opaque breakpoint object in "rhs".
bool
operator == (const lldb::SBBreakpoint& rhs);
bool operator==(const lldb::SBBreakpoint &rhs);
bool
operator != (const lldb::SBBreakpoint& rhs);
bool operator!=(const lldb::SBBreakpoint &rhs);
break_id_t
GetID () const;
break_id_t GetID() const;
bool
IsValid() const;
bool IsValid() const;
void
ClearAllBreakpointSites ();
void ClearAllBreakpointSites();
lldb::SBBreakpointLocation
FindLocationByAddress (lldb::addr_t vm_addr);
lldb::SBBreakpointLocation FindLocationByAddress(lldb::addr_t vm_addr);
lldb::break_id_t
FindLocationIDByAddress (lldb::addr_t vm_addr);
lldb::break_id_t FindLocationIDByAddress(lldb::addr_t vm_addr);
lldb::SBBreakpointLocation
FindLocationByID (lldb::break_id_t bp_loc_id);
lldb::SBBreakpointLocation FindLocationByID(lldb::break_id_t bp_loc_id);
lldb::SBBreakpointLocation
GetLocationAtIndex (uint32_t index);
lldb::SBBreakpointLocation GetLocationAtIndex(uint32_t index);
void
SetEnabled (bool enable);
void SetEnabled(bool enable);
bool
IsEnabled ();
bool IsEnabled();
void
SetOneShot (bool one_shot);
void SetOneShot(bool one_shot);
bool
IsOneShot () const;
bool IsOneShot() const;
bool
IsInternal ();
bool IsInternal();
uint32_t
GetHitCount () const;
uint32_t GetHitCount() const;
void
SetIgnoreCount (uint32_t count);
void SetIgnoreCount(uint32_t count);
uint32_t
GetIgnoreCount () const;
uint32_t GetIgnoreCount() const;
void
SetCondition (const char *condition);
void SetCondition(const char *condition);
const char *
GetCondition ();
const char *GetCondition();
void
SetThreadID (lldb::tid_t sb_thread_id);
void SetThreadID(lldb::tid_t sb_thread_id);
lldb::tid_t
GetThreadID ();
lldb::tid_t GetThreadID();
void
SetThreadIndex (uint32_t index);
void SetThreadIndex(uint32_t index);
uint32_t
GetThreadIndex() const;
uint32_t GetThreadIndex() const;
void
SetThreadName (const char *thread_name);
void SetThreadName(const char *thread_name);
const char *
GetThreadName () const;
const char *GetThreadName() const;
void
SetQueueName (const char *queue_name);
void SetQueueName(const char *queue_name);
const char *
GetQueueName () const;
const char *GetQueueName() const;
void
SetCallback (BreakpointHitCallback callback, void *baton);
void SetCallback(BreakpointHitCallback callback, void *baton);
void
SetScriptCallbackFunction (const char *callback_function_name);
void SetScriptCallbackFunction(const char *callback_function_name);
SBError
SetScriptCallbackBody (const char *script_body_text);
SBError SetScriptCallbackBody(const char *script_body_text);
bool
AddName (const char *new_name);
bool AddName(const char *new_name);
void
RemoveName (const char *name_to_remove);
void RemoveName(const char *name_to_remove);
bool
MatchesName (const char *name);
bool MatchesName(const char *name);
void
GetNames (SBStringList &names);
void GetNames(SBStringList &names);
size_t
GetNumResolvedLocations() const;
size_t GetNumResolvedLocations() const;
size_t
GetNumLocations() const;
size_t GetNumLocations() const;
bool
GetDescription (lldb::SBStream &description);
bool GetDescription(lldb::SBStream &description);
static bool
EventIsBreakpointEvent (const lldb::SBEvent &event);
static bool EventIsBreakpointEvent(const lldb::SBEvent &event);
static lldb::BreakpointEventType
GetBreakpointEventTypeFromEvent (const lldb::SBEvent& event);
GetBreakpointEventTypeFromEvent(const lldb::SBEvent &event);
static lldb::SBBreakpoint
GetBreakpointFromEvent (const lldb::SBEvent& event);
static lldb::SBBreakpoint GetBreakpointFromEvent(const lldb::SBEvent &event);
static lldb::SBBreakpointLocation
GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx);
GetBreakpointLocationAtIndexFromEvent(const lldb::SBEvent &event,
uint32_t loc_idx);
static uint32_t
GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event_sp);
GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event_sp);
private:
friend class SBBreakpointLocation;
friend class SBTarget;
SBBreakpoint (const lldb::BreakpointSP &bp_sp);
SBBreakpoint(const lldb::BreakpointSP &bp_sp);
lldb_private::Breakpoint *
operator->() const;
lldb_private::Breakpoint *operator->() const;
lldb_private::Breakpoint *
get() const;
lldb_private::Breakpoint *get() const;
lldb::BreakpointSP &
operator *();
lldb::BreakpointSP &operator*();
const lldb::BreakpointSP &
operator *() const;
const lldb::BreakpointSP &operator*() const;
static bool
PrivateBreakpointHitCallback (void *baton,
lldb_private::StoppointCallbackContext *context,
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
static bool PrivateBreakpointHitCallback(
void *baton, lldb_private::StoppointCallbackContext *context,
lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
lldb::BreakpointSP m_opaque_sp;
};

View File

@ -10,103 +10,76 @@
#ifndef LLDB_SBBreakpointLocation_h_
#define LLDB_SBBreakpointLocation_h_
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBDefines.h"
namespace lldb {
class LLDB_API SBBreakpointLocation
{
class LLDB_API SBBreakpointLocation {
public:
SBBreakpointLocation();
SBBreakpointLocation ();
SBBreakpointLocation(const lldb::SBBreakpointLocation &rhs);
SBBreakpointLocation (const lldb::SBBreakpointLocation &rhs);
~SBBreakpointLocation ();
~SBBreakpointLocation();
const lldb::SBBreakpointLocation &
operator = (const lldb::SBBreakpointLocation &rhs);
operator=(const lldb::SBBreakpointLocation &rhs);
break_id_t
GetID ();
break_id_t GetID();
bool
IsValid() const;
bool IsValid() const;
lldb::SBAddress
GetAddress ();
lldb::SBAddress GetAddress();
lldb::addr_t
GetLoadAddress ();
lldb::addr_t GetLoadAddress();
void
SetEnabled(bool enabled);
void SetEnabled(bool enabled);
bool
IsEnabled ();
bool IsEnabled();
uint32_t
GetIgnoreCount ();
uint32_t GetIgnoreCount();
void
SetIgnoreCount (uint32_t n);
void SetIgnoreCount(uint32_t n);
void
SetCondition (const char *condition);
void SetCondition(const char *condition);
const char *
GetCondition ();
const char *GetCondition();
void
SetScriptCallbackFunction (const char *callback_function_name);
void SetScriptCallbackFunction(const char *callback_function_name);
SBError
SetScriptCallbackBody (const char *script_body_text);
SBError SetScriptCallbackBody(const char *script_body_text);
void
SetThreadID (lldb::tid_t sb_thread_id);
void SetThreadID(lldb::tid_t sb_thread_id);
lldb::tid_t
GetThreadID ();
lldb::tid_t GetThreadID();
void
SetThreadIndex (uint32_t index);
void SetThreadIndex(uint32_t index);
uint32_t
GetThreadIndex() const;
uint32_t GetThreadIndex() const;
void
SetThreadName (const char *thread_name);
void SetThreadName(const char *thread_name);
const char *
GetThreadName () const;
const char *GetThreadName() const;
void
SetQueueName (const char *queue_name);
void SetQueueName(const char *queue_name);
const char *
GetQueueName () const;
const char *GetQueueName() const;
bool
IsResolved ();
bool IsResolved();
bool
GetDescription (lldb::SBStream &description, DescriptionLevel level);
bool GetDescription(lldb::SBStream &description, DescriptionLevel level);
SBBreakpoint
GetBreakpoint ();
SBBreakpoint GetBreakpoint();
SBBreakpointLocation (const lldb::BreakpointLocationSP &break_loc_sp);
SBBreakpointLocation(const lldb::BreakpointLocationSP &break_loc_sp);
private:
friend class SBBreakpoint;
void
SetLocation (const lldb::BreakpointLocationSP &break_loc_sp);
void SetLocation(const lldb::BreakpointLocationSP &break_loc_sp);
lldb::BreakpointLocationSP m_opaque_sp;
};
} // namespace lldb

View File

@ -14,62 +14,50 @@
namespace lldb {
class LLDB_API SBBroadcaster
{
class LLDB_API SBBroadcaster {
public:
SBBroadcaster ();
SBBroadcaster();
SBBroadcaster (const char *name);
SBBroadcaster(const char *name);
SBBroadcaster (const SBBroadcaster &rhs);
SBBroadcaster(const SBBroadcaster &rhs);
const SBBroadcaster &
operator = (const SBBroadcaster &rhs);
const SBBroadcaster &operator=(const SBBroadcaster &rhs);
~SBBroadcaster();
bool
IsValid () const;
bool IsValid() const;
void
Clear ();
void Clear();
void
BroadcastEventByType (uint32_t event_type, bool unique = false);
void BroadcastEventByType(uint32_t event_type, bool unique = false);
void
BroadcastEvent (const lldb::SBEvent &event, bool unique = false);
void BroadcastEvent(const lldb::SBEvent &event, bool unique = false);
void
AddInitialEventsToListener (const lldb::SBListener &listener, uint32_t requested_events);
void AddInitialEventsToListener(const lldb::SBListener &listener,
uint32_t requested_events);
uint32_t
AddListener (const lldb::SBListener &listener, uint32_t event_mask);
uint32_t AddListener(const lldb::SBListener &listener, uint32_t event_mask);
const char *
GetName () const;
const char *GetName() const;
bool
EventTypeHasListeners (uint32_t event_type);
bool EventTypeHasListeners(uint32_t event_type);
bool
RemoveListener (const lldb::SBListener &listener, uint32_t event_mask = UINT32_MAX);
bool RemoveListener(const lldb::SBListener &listener,
uint32_t event_mask = UINT32_MAX);
// This comparison is checking if the internal opaque pointer value
// is equal to that in "rhs".
bool
operator == (const lldb::SBBroadcaster &rhs) const;
bool operator==(const lldb::SBBroadcaster &rhs) const;
// This comparison is checking if the internal opaque pointer value
// is not equal to that in "rhs".
bool
operator != (const lldb::SBBroadcaster &rhs) const;
bool operator!=(const lldb::SBBroadcaster &rhs) const;
// This comparison is checking if the internal opaque pointer value
// is less than that in "rhs" so SBBroadcaster objects can be contained
// in ordered containers.
bool
operator < (const lldb::SBBroadcaster &rhs) const;
bool operator<(const lldb::SBBroadcaster &rhs) const;
protected:
friend class SBCommandInterpreter;
@ -79,13 +67,11 @@ protected:
friend class SBProcess;
friend class SBTarget;
SBBroadcaster (lldb_private::Broadcaster *broadcaster, bool owns);
SBBroadcaster(lldb_private::Broadcaster *broadcaster, bool owns);
lldb_private::Broadcaster *
get () const;
lldb_private::Broadcaster *get() const;
void
reset (lldb_private::Broadcaster *broadcaster, bool owns);
void reset(lldb_private::Broadcaster *broadcaster, bool owns);
private:
lldb::BroadcasterSP m_opaque_sp;

View File

@ -16,72 +16,56 @@
// Other libraries and framework includes
// Project includes
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBDefines.h"
namespace lldb {
class LLDB_API SBCommandInterpreterRunOptions
{
friend class SBDebugger;
friend class SBCommandInterpreter;
class LLDB_API SBCommandInterpreterRunOptions {
friend class SBDebugger;
friend class SBCommandInterpreter;
public:
SBCommandInterpreterRunOptions();
~SBCommandInterpreterRunOptions();
bool
GetStopOnContinue () const;
bool GetStopOnContinue() const;
void
SetStopOnContinue (bool);
void SetStopOnContinue(bool);
bool
GetStopOnError () const;
bool GetStopOnError() const;
void
SetStopOnError (bool);
void SetStopOnError(bool);
bool
GetStopOnCrash () const;
bool GetStopOnCrash() const;
void
SetStopOnCrash (bool);
void SetStopOnCrash(bool);
bool
GetEchoCommands () const;
bool GetEchoCommands() const;
void
SetEchoCommands (bool);
void SetEchoCommands(bool);
bool
GetPrintResults () const;
bool GetPrintResults() const;
void
SetPrintResults (bool);
void SetPrintResults(bool);
bool
GetAddToHistory () const;
bool GetAddToHistory() const;
void
SetAddToHistory (bool);
void SetAddToHistory(bool);
private:
lldb_private::CommandInterpreterRunOptions *
get () const;
lldb_private::CommandInterpreterRunOptions *get() const;
lldb_private::CommandInterpreterRunOptions &
ref () const;
lldb_private::CommandInterpreterRunOptions &ref() const;
// This is set in the constructor and will always be valid.
mutable std::unique_ptr<lldb_private::CommandInterpreterRunOptions> m_opaque_up;
mutable std::unique_ptr<lldb_private::CommandInterpreterRunOptions>
m_opaque_up;
};
class SBCommandInterpreter
{
class SBCommandInterpreter {
public:
enum
{
enum {
eBroadcastBitThreadShouldExit = (1 << 0),
eBroadcastBitResetPrompt = (1 << 1),
eBroadcastBitQuitCommandReceived = (1 << 2), // User entered quit
@ -89,115 +73,108 @@ public:
eBroadcastBitAsynchronousErrorData = (1 << 4)
};
SBCommandInterpreter (const lldb::SBCommandInterpreter &rhs);
SBCommandInterpreter(const lldb::SBCommandInterpreter &rhs);
~SBCommandInterpreter ();
~SBCommandInterpreter();
const lldb::SBCommandInterpreter &
operator = (const lldb::SBCommandInterpreter &rhs);
operator=(const lldb::SBCommandInterpreter &rhs);
static const char *
GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type);
GetArgumentTypeAsCString(const lldb::CommandArgumentType arg_type);
static const char *
GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type);
GetArgumentDescriptionAsCString(const lldb::CommandArgumentType arg_type);
static bool
EventIsCommandInterpreterEvent (const lldb::SBEvent &event);
static bool EventIsCommandInterpreterEvent(const lldb::SBEvent &event);
bool
IsValid() const;
bool IsValid() const;
bool
CommandExists (const char *cmd);
bool CommandExists(const char *cmd);
bool
AliasExists (const char *cmd);
bool AliasExists(const char *cmd);
lldb::SBBroadcaster
GetBroadcaster ();
lldb::SBBroadcaster GetBroadcaster();
static const char *
GetBroadcasterClass ();
static const char *GetBroadcasterClass();
bool
HasCommands ();
bool HasCommands();
bool
HasAliases ();
bool HasAliases();
bool
HasAliasOptions ();
bool HasAliasOptions();
lldb::SBProcess
GetProcess ();
lldb::SBProcess GetProcess();
lldb::SBDebugger
GetDebugger ();
lldb::SBDebugger GetDebugger();
lldb::SBCommand
AddMultiwordCommand (const char* name, const char* help);
lldb::SBCommand AddMultiwordCommand(const char *name, const char *help);
lldb::SBCommand
AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, const char* help);
lldb::SBCommand AddCommand(const char *name,
lldb::SBCommandPluginInterface *impl,
const char *help);
lldb::SBCommand
AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, const char* help, const char* syntax);
lldb::SBCommand AddCommand(const char *name,
lldb::SBCommandPluginInterface *impl,
const char *help, const char *syntax);
void SourceInitFileInHomeDirectory(lldb::SBCommandReturnObject &result);
void
SourceInitFileInHomeDirectory (lldb::SBCommandReturnObject &result);
SourceInitFileInCurrentWorkingDirectory(lldb::SBCommandReturnObject &result);
void
SourceInitFileInCurrentWorkingDirectory (lldb::SBCommandReturnObject &result);
lldb::ReturnStatus HandleCommand(const char *command_line,
lldb::SBCommandReturnObject &result,
bool add_to_history = false);
lldb::ReturnStatus
HandleCommand (const char *command_line, lldb::SBCommandReturnObject &result, bool add_to_history = false);
lldb::ReturnStatus HandleCommand(const char *command_line,
SBExecutionContext &exe_ctx,
SBCommandReturnObject &result,
bool add_to_history = false);
lldb::ReturnStatus
HandleCommand (const char *command_line, SBExecutionContext &exe_ctx, SBCommandReturnObject &result, bool add_to_history = false);
void
HandleCommandsFromFile (lldb::SBFileSpec &file,
void HandleCommandsFromFile(lldb::SBFileSpec &file,
lldb::SBExecutionContext &override_context,
lldb::SBCommandInterpreterRunOptions &options,
lldb::SBCommandReturnObject result);
// The pointer based interface is not useful in SWIG, since the cursor & last_char arguments are string pointers INTO current_line
// The pointer based interface is not useful in SWIG, since the cursor &
// last_char arguments are string pointers INTO current_line
// and you can't do that in a scripting language interface in general...
// In either case, the way this works is that the you give it a line and cursor position in the line. The function
// will return the number of completions. The matches list will contain number_of_completions + 1 elements. The first
// element is the common substring after the cursor position for all the matches. The rest of the elements are the
// matches. The first element is useful if you are emulating the common shell behavior where the tab completes
// to the string that is common among all the matches, then you should first check if the first element is non-empty,
// and if so just insert it and move the cursor to the end of the insertion. The next tab will return an empty
// common substring, and a list of choices (if any), at which point you should display the choices and let the user
// In either case, the way this works is that the you give it a line and
// cursor position in the line. The function
// will return the number of completions. The matches list will contain
// number_of_completions + 1 elements. The first
// element is the common substring after the cursor position for all the
// matches. The rest of the elements are the
// matches. The first element is useful if you are emulating the common shell
// behavior where the tab completes
// to the string that is common among all the matches, then you should first
// check if the first element is non-empty,
// and if so just insert it and move the cursor to the end of the insertion.
// The next tab will return an empty
// common substring, and a list of choices (if any), at which point you should
// display the choices and let the user
// type further to disambiguate.
int
HandleCompletion (const char *current_line,
const char *cursor,
const char *last_char,
int match_start_point,
int max_return_elements,
lldb::SBStringList &matches);
int HandleCompletion(const char *current_line, const char *cursor,
const char *last_char, int match_start_point,
int max_return_elements, lldb::SBStringList &matches);
int
HandleCompletion (const char *current_line,
uint32_t cursor_pos,
int match_start_point,
int max_return_elements,
int HandleCompletion(const char *current_line, uint32_t cursor_pos,
int match_start_point, int max_return_elements,
lldb::SBStringList &matches);
// Catch commands before they execute by registering a callback that will
// get called when the command gets executed. This allows GUI or command
// line interfaces to intercept a command and stop it from happening
bool
SetCommandOverrideCallback (const char *command_name,
bool SetCommandOverrideCallback(const char *command_name,
lldb::CommandOverrideCallback callback,
void *baton);
SBCommandInterpreter(lldb_private::CommandInterpreter *interpreter_ptr = nullptr); // Access using SBDebugger::GetCommandInterpreter();
SBCommandInterpreter(
lldb_private::CommandInterpreter *interpreter_ptr =
nullptr); // Access using SBDebugger::GetCommandInterpreter();
//----------------------------------------------------------------------
/// Return true if the command interpreter is the active IO handler.
@ -206,8 +183,7 @@ public:
/// go to the command interpreter and will result in LLDB command line
/// commands being executed.
//----------------------------------------------------------------------
bool
IsActive ();
bool IsActive();
//----------------------------------------------------------------------
/// Get the string that needs to be written to the debugger stdin file
@ -226,99 +202,79 @@ public:
/// feeding the input stream for the debugger, or nullptr if there is
/// no string for this control key.
//----------------------------------------------------------------------
const char *
GetIOHandlerControlSequence(char ch);
const char *GetIOHandlerControlSequence(char ch);
bool
GetPromptOnQuit();
bool GetPromptOnQuit();
void
SetPromptOnQuit(bool b);
void SetPromptOnQuit(bool b);
//----------------------------------------------------------------------
/// Resolve the command just as HandleCommand would, expanding abbreviations
/// and aliases. If successful, result->GetOutput has the full expansion.
//----------------------------------------------------------------------
void
ResolveCommand(const char *command_line, SBCommandReturnObject &result);
void ResolveCommand(const char *command_line, SBCommandReturnObject &result);
protected:
lldb_private::CommandInterpreter &
ref ();
lldb_private::CommandInterpreter &ref();
lldb_private::CommandInterpreter *
get ();
lldb_private::CommandInterpreter *get();
void
reset (lldb_private::CommandInterpreter *);
void reset(lldb_private::CommandInterpreter *);
private:
friend class SBDebugger;
static void
InitializeSWIG ();
static void InitializeSWIG();
lldb_private::CommandInterpreter *m_opaque_ptr;
};
class SBCommandPluginInterface
{
class SBCommandPluginInterface {
public:
virtual
~SBCommandPluginInterface() = default;
virtual ~SBCommandPluginInterface() = default;
virtual bool
DoExecute (lldb::SBDebugger /*debugger*/,
char** /*command*/,
lldb::SBCommandReturnObject & /*result*/)
{
virtual bool DoExecute(lldb::SBDebugger /*debugger*/, char ** /*command*/,
lldb::SBCommandReturnObject & /*result*/) {
return false;
}
};
class SBCommand
{
class SBCommand {
public:
SBCommand ();
SBCommand();
bool
IsValid ();
bool IsValid();
const char*
GetName ();
const char *GetName();
const char*
GetHelp ();
const char *GetHelp();
const char*
GetHelpLong ();
const char *GetHelpLong();
void
SetHelp (const char*);
void SetHelp(const char *);
void
SetHelpLong (const char*);
void SetHelpLong(const char *);
uint32_t
GetFlags ();
uint32_t GetFlags();
void
SetFlags (uint32_t flags);
void SetFlags(uint32_t flags);
lldb::SBCommand
AddMultiwordCommand(const char* name, const char* help = nullptr);
lldb::SBCommand AddMultiwordCommand(const char *name,
const char *help = nullptr);
lldb::SBCommand
AddCommand(const char* name, lldb::SBCommandPluginInterface* impl, const char* help = nullptr);
lldb::SBCommand AddCommand(const char *name,
lldb::SBCommandPluginInterface *impl,
const char *help = nullptr);
lldb::SBCommand
AddCommand(const char* name, lldb::SBCommandPluginInterface* impl, const char* help, const char* syntax);
lldb::SBCommand AddCommand(const char *name,
lldb::SBCommandPluginInterface *impl,
const char *help, const char *syntax);
private:
friend class SBDebugger;
friend class SBCommandInterpreter;
SBCommand (lldb::CommandObjectSP cmd_sp);
SBCommand(lldb::CommandObjectSP cmd_sp);
lldb::CommandObjectSP m_opaque_sp;
};

View File

@ -22,119 +22,87 @@
namespace lldb {
class LLDB_API SBCommandReturnObject
{
class LLDB_API SBCommandReturnObject {
public:
SBCommandReturnObject ();
SBCommandReturnObject();
SBCommandReturnObject (const lldb::SBCommandReturnObject &rhs);
SBCommandReturnObject(const lldb::SBCommandReturnObject &rhs);
~SBCommandReturnObject ();
~SBCommandReturnObject();
const lldb::SBCommandReturnObject &
operator = (const lldb::SBCommandReturnObject &rhs);
operator=(const lldb::SBCommandReturnObject &rhs);
SBCommandReturnObject (lldb_private::CommandReturnObject *ptr);
SBCommandReturnObject(lldb_private::CommandReturnObject *ptr);
lldb_private::CommandReturnObject *
Release ();
lldb_private::CommandReturnObject *Release();
bool
IsValid() const;
bool IsValid() const;
const char *
GetOutput ();
const char *GetOutput();
const char *
GetError ();
const char *GetError();
size_t
PutOutput (FILE *fh);
size_t PutOutput(FILE *fh);
size_t
GetOutputSize ();
size_t GetOutputSize();
size_t
GetErrorSize ();
size_t GetErrorSize();
size_t
PutError (FILE *fh);
size_t PutError(FILE *fh);
void
Clear();
void Clear();
lldb::ReturnStatus
GetStatus();
lldb::ReturnStatus GetStatus();
void
SetStatus (lldb::ReturnStatus status);
void SetStatus(lldb::ReturnStatus status);
bool
Succeeded ();
bool Succeeded();
bool
HasResult ();
bool HasResult();
void
AppendMessage (const char *message);
void AppendMessage(const char *message);
void
AppendWarning (const char *message);
void AppendWarning(const char *message);
bool
GetDescription (lldb::SBStream &description);
bool GetDescription(lldb::SBStream &description);
// deprecated, these two functions do not take
// ownership of file handle
void
SetImmediateOutputFile (FILE *fh);
void SetImmediateOutputFile(FILE *fh);
void
SetImmediateErrorFile (FILE *fh);
void SetImmediateErrorFile(FILE *fh);
void
SetImmediateOutputFile (FILE *fh, bool transfer_ownership);
void SetImmediateOutputFile(FILE *fh, bool transfer_ownership);
void
SetImmediateErrorFile (FILE *fh, bool transfer_ownership);
void SetImmediateErrorFile(FILE *fh, bool transfer_ownership);
void
PutCString(const char* string, int len = -1);
void PutCString(const char *string, int len = -1);
size_t
Printf(const char* format, ...) __attribute__ ((format (printf, 2, 3)));
size_t Printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
const char *
GetOutput (bool only_if_no_immediate);
const char *GetOutput(bool only_if_no_immediate);
const char *
GetError (bool only_if_no_immediate);
const char *GetError(bool only_if_no_immediate);
void
SetError(lldb::SBError &error,
void SetError(lldb::SBError &error,
const char *fallback_error_cstr = nullptr);
void
SetError (const char* error_cstr);
void SetError(const char *error_cstr);
protected:
friend class SBCommandInterpreter;
friend class SBOptions;
lldb_private::CommandReturnObject *
operator->() const;
lldb_private::CommandReturnObject *operator->() const;
lldb_private::CommandReturnObject *
get() const;
lldb_private::CommandReturnObject *get() const;
lldb_private::CommandReturnObject &
operator*() const;
lldb_private::CommandReturnObject &operator*() const;
lldb_private::CommandReturnObject &
ref() const;
lldb_private::CommandReturnObject &ref() const;
void
SetLLDBObjectPtr (lldb_private::CommandReturnObject *ptr);
void SetLLDBObjectPtr(lldb_private::CommandReturnObject *ptr);
private:
std::unique_ptr<lldb_private::CommandReturnObject> m_opaque_ap;

View File

@ -15,86 +15,68 @@
namespace lldb {
class LLDB_API SBCommunication
{
class LLDB_API SBCommunication {
public:
FLAGS_ANONYMOUS_ENUM()
{
eBroadcastBitDisconnected = (1 << 0), ///< Sent when the communications connection is lost.
eBroadcastBitReadThreadGotBytes = (1 << 1), ///< Sent by the read thread when bytes become available.
eBroadcastBitReadThreadDidExit = (1 << 2), ///< Sent by the read thread when it exits to inform clients.
eBroadcastBitReadThreadShouldExit = (1 << 3), ///< Sent by clients that need to cancel the read thread.
eBroadcastBitPacketAvailable = (1 << 4), ///< Sent when data received makes a complete packet.
eAllEventBits = 0xffffffff
};
FLAGS_ANONYMOUS_ENUM(){
eBroadcastBitDisconnected =
(1 << 0), ///< Sent when the communications connection is lost.
eBroadcastBitReadThreadGotBytes =
(1 << 1), ///< Sent by the read thread when bytes become available.
eBroadcastBitReadThreadDidExit =
(1
<< 2), ///< Sent by the read thread when it exits to inform clients.
eBroadcastBitReadThreadShouldExit =
(1 << 3), ///< Sent by clients that need to cancel the read thread.
eBroadcastBitPacketAvailable =
(1 << 4), ///< Sent when data received makes a complete packet.
eAllEventBits = 0xffffffff};
typedef void (*ReadThreadBytesReceived) (void *baton, const void *src, size_t src_len);
typedef void (*ReadThreadBytesReceived)(void *baton, const void *src,
size_t src_len);
SBCommunication ();
SBCommunication (const char * broadcaster_name);
~SBCommunication ();
SBCommunication();
SBCommunication(const char *broadcaster_name);
~SBCommunication();
bool IsValid() const;
bool
IsValid () const;
lldb::SBBroadcaster
GetBroadcaster ();
lldb::SBBroadcaster GetBroadcaster();
static const char *GetBroadcasterClass();
lldb::ConnectionStatus
AdoptFileDesriptor (int fd, bool owns_fd);
lldb::ConnectionStatus AdoptFileDesriptor(int fd, bool owns_fd);
lldb::ConnectionStatus
Connect (const char *url);
lldb::ConnectionStatus Connect(const char *url);
lldb::ConnectionStatus
Disconnect ();
lldb::ConnectionStatus Disconnect();
bool
IsConnected () const;
bool IsConnected() const;
bool
GetCloseOnEOF ();
bool GetCloseOnEOF();
void
SetCloseOnEOF (bool b);
void SetCloseOnEOF(bool b);
size_t
Read (void *dst,
size_t dst_len,
uint32_t timeout_usec,
size_t Read(void *dst, size_t dst_len, uint32_t timeout_usec,
lldb::ConnectionStatus &status);
size_t
Write (const void *src,
size_t src_len,
lldb::ConnectionStatus &status);
size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status);
bool
ReadThreadStart ();
bool ReadThreadStart();
bool
ReadThreadStop ();
bool ReadThreadStop();
bool
ReadThreadIsRunning ();
bool ReadThreadIsRunning();
bool
SetReadThreadBytesReceivedCallback (ReadThreadBytesReceived callback,
bool SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback,
void *callback_baton);
private:
DISALLOW_COPY_AND_ASSIGN (SBCommunication);
DISALLOW_COPY_AND_ASSIGN(SBCommunication);
lldb_private::Communication *m_opaque;
bool m_opaque_owned;
};
} // namespace lldb
#endif // LLDB_SBCommunication_h_

View File

@ -15,50 +15,37 @@
namespace lldb {
class LLDB_API SBCompileUnit
{
class LLDB_API SBCompileUnit {
public:
SBCompileUnit();
SBCompileUnit ();
SBCompileUnit(const lldb::SBCompileUnit &rhs);
SBCompileUnit (const lldb::SBCompileUnit &rhs);
~SBCompileUnit();
~SBCompileUnit ();
const lldb::SBCompileUnit &operator=(const lldb::SBCompileUnit &rhs);
const lldb::SBCompileUnit &
operator = (const lldb::SBCompileUnit &rhs);
bool IsValid() const;
bool
IsValid () const;
lldb::SBFileSpec GetFileSpec() const;
lldb::SBFileSpec
GetFileSpec () const;
uint32_t GetNumLineEntries() const;
uint32_t
GetNumLineEntries () const;
lldb::SBLineEntry GetLineEntryAtIndex(uint32_t idx) const;
lldb::SBLineEntry
GetLineEntryAtIndex (uint32_t idx) const;
uint32_t
FindLineEntryIndex (uint32_t start_idx,
uint32_t line,
uint32_t FindLineEntryIndex(uint32_t start_idx, uint32_t line,
lldb::SBFileSpec *inline_file_spec) const;
uint32_t
FindLineEntryIndex (uint32_t start_idx,
uint32_t line,
uint32_t FindLineEntryIndex(uint32_t start_idx, uint32_t line,
lldb::SBFileSpec *inline_file_spec,
bool exact) const;
SBFileSpec
GetSupportFileAtIndex (uint32_t idx) const;
SBFileSpec GetSupportFileAtIndex(uint32_t idx) const;
uint32_t
GetNumSupportFiles () const;
uint32_t GetNumSupportFiles() const;
uint32_t
FindSupportFileIndex (uint32_t start_idx, const SBFileSpec &sb_file, bool full);
uint32_t FindSupportFileIndex(uint32_t start_idx, const SBFileSpec &sb_file,
bool full);
//------------------------------------------------------------------
/// Get all types matching \a type_mask from debug info in this
@ -75,20 +62,15 @@ public:
/// @return
/// A list of types in this compile unit that match \a type_mask
//------------------------------------------------------------------
lldb::SBTypeList
GetTypes (uint32_t type_mask = lldb::eTypeClassAny);
lldb::SBTypeList GetTypes(uint32_t type_mask = lldb::eTypeClassAny);
lldb::LanguageType
GetLanguage ();
lldb::LanguageType GetLanguage();
bool
operator == (const lldb::SBCompileUnit &rhs) const;
bool operator==(const lldb::SBCompileUnit &rhs) const;
bool
operator != (const lldb::SBCompileUnit &rhs) const;
bool operator!=(const lldb::SBCompileUnit &rhs) const;
bool
GetDescription (lldb::SBStream &description);
bool GetDescription(lldb::SBStream &description);
private:
friend class SBAddress;
@ -96,24 +78,19 @@ private:
friend class SBSymbolContext;
friend class SBModule;
SBCompileUnit (lldb_private::CompileUnit *lldb_object_ptr);
SBCompileUnit(lldb_private::CompileUnit *lldb_object_ptr);
const lldb_private::CompileUnit *
operator->() const;
const lldb_private::CompileUnit *operator->() const;
const lldb_private::CompileUnit &
operator*() const;
const lldb_private::CompileUnit &operator*() const;
lldb_private::CompileUnit *
get ();
lldb_private::CompileUnit *get();
void
reset (lldb_private::CompileUnit *lldb_object_ptr);
void reset(lldb_private::CompileUnit *lldb_object_ptr);
lldb_private::CompileUnit *m_opaque_ptr;
};
} // namespace lldb
#endif // LLDB_SBCompileUnit_h_

View File

@ -14,156 +14,132 @@
namespace lldb {
class LLDB_API SBData
{
class LLDB_API SBData {
public:
SBData();
SBData ();
SBData(const SBData &rhs);
SBData (const SBData &rhs);
const SBData &operator=(const SBData &rhs);
const SBData &
operator = (const SBData &rhs);
~SBData();
~SBData ();
uint8_t GetAddressByteSize();
uint8_t
GetAddressByteSize ();
void SetAddressByteSize(uint8_t addr_byte_size);
void
SetAddressByteSize (uint8_t addr_byte_size);
void Clear();
void
Clear ();
bool IsValid();
bool
IsValid();
size_t GetByteSize();
size_t
GetByteSize ();
lldb::ByteOrder GetByteOrder();
lldb::ByteOrder
GetByteOrder();
void SetByteOrder(lldb::ByteOrder endian);
void
SetByteOrder (lldb::ByteOrder endian);
float GetFloat(lldb::SBError &error, lldb::offset_t offset);
float
GetFloat (lldb::SBError& error, lldb::offset_t offset);
double GetDouble(lldb::SBError &error, lldb::offset_t offset);
double
GetDouble (lldb::SBError& error, lldb::offset_t offset);
long double GetLongDouble(lldb::SBError &error, lldb::offset_t offset);
long double
GetLongDouble (lldb::SBError& error, lldb::offset_t offset);
lldb::addr_t GetAddress(lldb::SBError &error, lldb::offset_t offset);
lldb::addr_t
GetAddress (lldb::SBError& error, lldb::offset_t offset);
uint8_t GetUnsignedInt8(lldb::SBError &error, lldb::offset_t offset);
uint8_t
GetUnsignedInt8 (lldb::SBError& error, lldb::offset_t offset);
uint16_t GetUnsignedInt16(lldb::SBError &error, lldb::offset_t offset);
uint16_t
GetUnsignedInt16 (lldb::SBError& error, lldb::offset_t offset);
uint32_t GetUnsignedInt32(lldb::SBError &error, lldb::offset_t offset);
uint32_t
GetUnsignedInt32 (lldb::SBError& error, lldb::offset_t offset);
uint64_t GetUnsignedInt64(lldb::SBError &error, lldb::offset_t offset);
uint64_t
GetUnsignedInt64 (lldb::SBError& error, lldb::offset_t offset);
int8_t GetSignedInt8(lldb::SBError &error, lldb::offset_t offset);
int8_t
GetSignedInt8 (lldb::SBError& error, lldb::offset_t offset);
int16_t GetSignedInt16(lldb::SBError &error, lldb::offset_t offset);
int16_t
GetSignedInt16 (lldb::SBError& error, lldb::offset_t offset);
int32_t GetSignedInt32(lldb::SBError &error, lldb::offset_t offset);
int32_t
GetSignedInt32 (lldb::SBError& error, lldb::offset_t offset);
int64_t GetSignedInt64(lldb::SBError &error, lldb::offset_t offset);
int64_t
GetSignedInt64 (lldb::SBError& error, lldb::offset_t offset);
const char *GetString(lldb::SBError &error, lldb::offset_t offset);
const char*
GetString (lldb::SBError& error, lldb::offset_t offset);
size_t
ReadRawData (lldb::SBError& error,
lldb::offset_t offset,
void *buf,
size_t ReadRawData(lldb::SBError &error, lldb::offset_t offset, void *buf,
size_t size);
bool
GetDescription (lldb::SBStream &description, lldb::addr_t base_addr = LLDB_INVALID_ADDRESS);
bool GetDescription(lldb::SBStream &description,
lldb::addr_t base_addr = LLDB_INVALID_ADDRESS);
// it would be nice to have SetData(SBError, const void*, size_t) when endianness and address size can be
// inferred from the existing DataExtractor, but having two SetData() signatures triggers a SWIG bug where
// the typemap isn't applied before resolving the overload, and thus the right function never gets called
void
SetData (lldb::SBError& error, const void *buf, size_t size, lldb::ByteOrder endian, uint8_t addr_size);
// it would be nice to have SetData(SBError, const void*, size_t) when
// endianness and address size can be
// inferred from the existing DataExtractor, but having two SetData()
// signatures triggers a SWIG bug where
// the typemap isn't applied before resolving the overload, and thus the right
// function never gets called
void SetData(lldb::SBError &error, const void *buf, size_t size,
lldb::ByteOrder endian, uint8_t addr_size);
// see SetData() for why we don't have Append(const void* buf, size_t size)
bool
Append (const SBData& rhs);
bool Append(const SBData &rhs);
static lldb::SBData
CreateDataFromCString (lldb::ByteOrder endian, uint32_t addr_byte_size, const char* data);
static lldb::SBData CreateDataFromCString(lldb::ByteOrder endian,
uint32_t addr_byte_size,
const char *data);
// in the following CreateData*() and SetData*() prototypes, the two parameters array and array_len
// should not be renamed or rearranged, because doing so will break the SWIG typemap
static lldb::SBData
CreateDataFromUInt64Array (lldb::ByteOrder endian, uint32_t addr_byte_size, uint64_t* array, size_t array_len);
// in the following CreateData*() and SetData*() prototypes, the two
// parameters array and array_len
// should not be renamed or rearranged, because doing so will break the SWIG
// typemap
static lldb::SBData CreateDataFromUInt64Array(lldb::ByteOrder endian,
uint32_t addr_byte_size,
uint64_t *array,
size_t array_len);
static lldb::SBData
CreateDataFromUInt32Array (lldb::ByteOrder endian, uint32_t addr_byte_size, uint32_t* array, size_t array_len);
static lldb::SBData CreateDataFromUInt32Array(lldb::ByteOrder endian,
uint32_t addr_byte_size,
uint32_t *array,
size_t array_len);
static lldb::SBData
CreateDataFromSInt64Array (lldb::ByteOrder endian, uint32_t addr_byte_size, int64_t* array, size_t array_len);
static lldb::SBData CreateDataFromSInt64Array(lldb::ByteOrder endian,
uint32_t addr_byte_size,
int64_t *array,
size_t array_len);
static lldb::SBData
CreateDataFromSInt32Array (lldb::ByteOrder endian, uint32_t addr_byte_size, int32_t* array, size_t array_len);
static lldb::SBData CreateDataFromSInt32Array(lldb::ByteOrder endian,
uint32_t addr_byte_size,
int32_t *array,
size_t array_len);
static lldb::SBData
CreateDataFromDoubleArray (lldb::ByteOrder endian, uint32_t addr_byte_size, double* array, size_t array_len);
static lldb::SBData CreateDataFromDoubleArray(lldb::ByteOrder endian,
uint32_t addr_byte_size,
double *array,
size_t array_len);
bool
SetDataFromCString (const char* data);
bool SetDataFromCString(const char *data);
bool
SetDataFromUInt64Array (uint64_t* array, size_t array_len);
bool SetDataFromUInt64Array(uint64_t *array, size_t array_len);
bool
SetDataFromUInt32Array (uint32_t* array, size_t array_len);
bool SetDataFromUInt32Array(uint32_t *array, size_t array_len);
bool
SetDataFromSInt64Array (int64_t* array, size_t array_len);
bool SetDataFromSInt64Array(int64_t *array, size_t array_len);
bool
SetDataFromSInt32Array (int32_t* array, size_t array_len);
bool
SetDataFromDoubleArray (double* array, size_t array_len);
bool SetDataFromSInt32Array(int32_t *array, size_t array_len);
bool SetDataFromDoubleArray(double *array, size_t array_len);
protected:
// Mimic shared pointer...
lldb_private::DataExtractor *
get() const;
lldb_private::DataExtractor *get() const;
lldb_private::DataExtractor *
operator->() const;
lldb_private::DataExtractor *operator->() const;
lldb::DataExtractorSP &
operator*();
lldb::DataExtractorSP &operator*();
const lldb::DataExtractorSP &
operator*() const;
const lldb::DataExtractorSP &operator*() const;
SBData (const lldb::DataExtractorSP &data_sp);
SBData(const lldb::DataExtractorSP &data_sp);
void
SetOpaque (const lldb::DataExtractorSP &data_sp);
void SetOpaque(const lldb::DataExtractorSP &data_sp);
private:
friend class SBInstruction;
@ -175,7 +151,6 @@ private:
lldb::DataExtractorSP m_opaque_sp;
};
} // namespace lldb
#endif // LLDB_SBData_h_

View File

@ -17,19 +17,22 @@
namespace lldb {
class LLDB_API SBInputReader
{
class LLDB_API SBInputReader {
public:
SBInputReader() = default;
~SBInputReader() = default;
SBError Initialize(lldb::SBDebugger&, unsigned long (*)(void*, lldb::SBInputReader*, lldb::InputReaderAction, char const*, unsigned long), void*, lldb::InputReaderGranularity, char const*, char const*, bool);
SBError Initialize(lldb::SBDebugger &,
unsigned long (*)(void *, lldb::SBInputReader *,
lldb::InputReaderAction, char const *,
unsigned long),
void *, lldb::InputReaderGranularity, char const *,
char const *, bool);
void SetIsDone(bool);
bool IsActive() const;
};
class LLDB_API SBDebugger
{
class LLDB_API SBDebugger {
public:
SBDebugger();
@ -39,301 +42,209 @@ public:
~SBDebugger();
lldb::SBDebugger &
operator = (const lldb::SBDebugger &rhs);
lldb::SBDebugger &operator=(const lldb::SBDebugger &rhs);
static void
Initialize();
static void Initialize();
static void
Terminate();
static void Terminate();
// Deprecated, use the one that takes a source_init_files bool.
static lldb::SBDebugger
Create();
static lldb::SBDebugger Create();
static lldb::SBDebugger
Create(bool source_init_files);
static lldb::SBDebugger Create(bool source_init_files);
static lldb::SBDebugger
Create(bool source_init_files, lldb::LogOutputCallback log_callback, void *baton);
static lldb::SBDebugger Create(bool source_init_files,
lldb::LogOutputCallback log_callback,
void *baton);
static void
Destroy (lldb::SBDebugger &debugger);
static void Destroy(lldb::SBDebugger &debugger);
static void
MemoryPressureDetected ();
static void MemoryPressureDetected();
bool
IsValid() const;
bool IsValid() const;
void
Clear ();
void Clear();
void
SetAsync (bool b);
void SetAsync(bool b);
bool
GetAsync ();
bool GetAsync();
void
SkipLLDBInitFiles (bool b);
void SkipLLDBInitFiles(bool b);
void
SkipAppInitFiles (bool b);
void SkipAppInitFiles(bool b);
void
SetInputFileHandle (FILE *f, bool transfer_ownership);
void SetInputFileHandle(FILE *f, bool transfer_ownership);
void
SetOutputFileHandle (FILE *f, bool transfer_ownership);
void SetOutputFileHandle(FILE *f, bool transfer_ownership);
void
SetErrorFileHandle (FILE *f, bool transfer_ownership);
void SetErrorFileHandle(FILE *f, bool transfer_ownership);
FILE *
GetInputFileHandle ();
FILE *GetInputFileHandle();
FILE *
GetOutputFileHandle ();
FILE *GetOutputFileHandle();
FILE *
GetErrorFileHandle ();
FILE *GetErrorFileHandle();
void
SaveInputTerminalState();
void SaveInputTerminalState();
void
RestoreInputTerminalState();
void RestoreInputTerminalState();
lldb::SBCommandInterpreter
GetCommandInterpreter ();
lldb::SBCommandInterpreter GetCommandInterpreter();
void
HandleCommand (const char *command);
void HandleCommand(const char *command);
lldb::SBListener
GetListener ();
lldb::SBListener GetListener();
void
HandleProcessEvent (const lldb::SBProcess &process,
const lldb::SBEvent &event,
FILE *out,
FILE *err);
void HandleProcessEvent(const lldb::SBProcess &process,
const lldb::SBEvent &event, FILE *out, FILE *err);
lldb::SBTarget
CreateTarget (const char *filename,
const char *target_triple,
lldb::SBTarget CreateTarget(const char *filename, const char *target_triple,
const char *platform_name,
bool add_dependent_modules,
lldb::SBError& error);
bool add_dependent_modules, lldb::SBError &error);
lldb::SBTarget
CreateTargetWithFileAndTargetTriple (const char *filename,
lldb::SBTarget CreateTargetWithFileAndTargetTriple(const char *filename,
const char *target_triple);
lldb::SBTarget
CreateTargetWithFileAndArch (const char *filename,
lldb::SBTarget CreateTargetWithFileAndArch(const char *filename,
const char *archname);
lldb::SBTarget
CreateTarget (const char *filename);
lldb::SBTarget CreateTarget(const char *filename);
// Return true if target is deleted from the target list of the debugger.
bool
DeleteTarget (lldb::SBTarget &target);
bool DeleteTarget(lldb::SBTarget &target);
lldb::SBTarget
GetTargetAtIndex (uint32_t idx);
lldb::SBTarget GetTargetAtIndex(uint32_t idx);
uint32_t
GetIndexOfTarget (lldb::SBTarget target);
uint32_t GetIndexOfTarget(lldb::SBTarget target);
lldb::SBTarget
FindTargetWithProcessID (pid_t pid);
lldb::SBTarget FindTargetWithProcessID(pid_t pid);
lldb::SBTarget
FindTargetWithFileAndArch (const char *filename,
lldb::SBTarget FindTargetWithFileAndArch(const char *filename,
const char *arch);
uint32_t
GetNumTargets ();
uint32_t GetNumTargets();
lldb::SBTarget
GetSelectedTarget ();
lldb::SBTarget GetSelectedTarget();
void
SetSelectedTarget (SBTarget& target);
void SetSelectedTarget(SBTarget &target);
lldb::SBPlatform
GetSelectedPlatform();
lldb::SBPlatform GetSelectedPlatform();
void
SetSelectedPlatform(lldb::SBPlatform &platform);
void SetSelectedPlatform(lldb::SBPlatform &platform);
lldb::SBSourceManager
GetSourceManager ();
lldb::SBSourceManager GetSourceManager();
// REMOVE: just for a quick fix, need to expose platforms through
// SBPlatform from this class.
lldb::SBError
SetCurrentPlatform (const char *platform_name);
lldb::SBError SetCurrentPlatform(const char *platform_name);
bool
SetCurrentPlatformSDKRoot (const char *sysroot);
bool SetCurrentPlatformSDKRoot(const char *sysroot);
// FIXME: Once we get the set show stuff in place, the driver won't need
// an interface to the Set/Get UseExternalEditor.
bool
SetUseExternalEditor (bool input);
bool SetUseExternalEditor(bool input);
bool
GetUseExternalEditor ();
bool GetUseExternalEditor();
bool
SetUseColor (bool use_color);
bool SetUseColor(bool use_color);
bool
GetUseColor () const;
bool GetUseColor() const;
static bool
GetDefaultArchitecture (char *arch_name, size_t arch_name_len);
static bool GetDefaultArchitecture(char *arch_name, size_t arch_name_len);
static bool
SetDefaultArchitecture (const char *arch_name);
static bool SetDefaultArchitecture(const char *arch_name);
lldb::ScriptLanguage
GetScriptingLanguage (const char *script_language_name);
lldb::ScriptLanguage GetScriptingLanguage(const char *script_language_name);
static const char *
GetVersionString ();
static const char *GetVersionString();
static const char *
StateAsCString (lldb::StateType state);
static const char *StateAsCString(lldb::StateType state);
static bool
StateIsRunningState (lldb::StateType state);
static bool StateIsRunningState(lldb::StateType state);
static bool
StateIsStoppedState (lldb::StateType state);
static bool StateIsStoppedState(lldb::StateType state);
bool
EnableLog (const char *channel, const char **categories);
bool EnableLog(const char *channel, const char **categories);
void
SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton);
void SetLoggingCallback(lldb::LogOutputCallback log_callback, void *baton);
// DEPRECATED
void
DispatchInput (void* baton,
const void* data,
size_t data_len);
void DispatchInput(void *baton, const void *data, size_t data_len);
void
DispatchInput (const void *data, size_t data_len);
void DispatchInput(const void *data, size_t data_len);
void
DispatchInputInterrupt ();
void DispatchInputInterrupt();
void
DispatchInputEndOfFile ();
void DispatchInputEndOfFile();
void
PushInputReader (lldb::SBInputReader &reader);
void PushInputReader(lldb::SBInputReader &reader);
const char *
GetInstanceName ();
const char *GetInstanceName();
static SBDebugger
FindDebuggerWithID (int id);
static SBDebugger FindDebuggerWithID(int id);
static lldb::SBError
SetInternalVariable (const char *var_name, const char *value, const char *debugger_instance_name);
static lldb::SBError SetInternalVariable(const char *var_name,
const char *value,
const char *debugger_instance_name);
static lldb::SBStringList
GetInternalVariableValue (const char *var_name, const char *debugger_instance_name);
GetInternalVariableValue(const char *var_name,
const char *debugger_instance_name);
bool
GetDescription (lldb::SBStream &description);
bool GetDescription(lldb::SBStream &description);
uint32_t
GetTerminalWidth () const;
uint32_t GetTerminalWidth() const;
void
SetTerminalWidth (uint32_t term_width);
void SetTerminalWidth(uint32_t term_width);
lldb::user_id_t
GetID ();
lldb::user_id_t GetID();
const char *
GetPrompt() const;
const char *GetPrompt() const;
void
SetPrompt (const char *prompt);
void SetPrompt(const char *prompt);
lldb::ScriptLanguage
GetScriptLanguage() const;
lldb::ScriptLanguage GetScriptLanguage() const;
void
SetScriptLanguage (lldb::ScriptLanguage script_lang);
void SetScriptLanguage(lldb::ScriptLanguage script_lang);
bool
GetCloseInputOnEOF () const;
bool GetCloseInputOnEOF() const;
void
SetCloseInputOnEOF (bool b);
void SetCloseInputOnEOF(bool b);
SBTypeCategory
GetCategory (const char* category_name);
SBTypeCategory GetCategory(const char *category_name);
SBTypeCategory
GetCategory (lldb::LanguageType lang_type);
SBTypeCategory GetCategory(lldb::LanguageType lang_type);
SBTypeCategory
CreateCategory (const char* category_name);
SBTypeCategory CreateCategory(const char *category_name);
bool
DeleteCategory (const char* category_name);
bool DeleteCategory(const char *category_name);
uint32_t
GetNumCategories ();
uint32_t GetNumCategories();
SBTypeCategory
GetCategoryAtIndex (uint32_t);
SBTypeCategory GetCategoryAtIndex(uint32_t);
SBTypeCategory
GetDefaultCategory();
SBTypeCategory GetDefaultCategory();
SBTypeFormat
GetFormatForType (SBTypeNameSpecifier);
SBTypeFormat GetFormatForType(SBTypeNameSpecifier);
#ifndef LLDB_DISABLE_PYTHON
SBTypeSummary
GetSummaryForType (SBTypeNameSpecifier);
SBTypeSummary GetSummaryForType(SBTypeNameSpecifier);
#endif
SBTypeFilter
GetFilterForType (SBTypeNameSpecifier);
SBTypeFilter GetFilterForType(SBTypeNameSpecifier);
#ifndef LLDB_DISABLE_PYTHON
SBTypeSynthetic
GetSyntheticForType (SBTypeNameSpecifier);
SBTypeSynthetic GetSyntheticForType(SBTypeNameSpecifier);
#endif
void
RunCommandInterpreter (bool auto_handle_events,
bool spawn_thread);
void RunCommandInterpreter(bool auto_handle_events, bool spawn_thread);
void
RunCommandInterpreter (bool auto_handle_events,
bool spawn_thread,
void RunCommandInterpreter(bool auto_handle_events, bool spawn_thread,
SBCommandInterpreterRunOptions &options,
int &num_errors,
bool &quit_requested,
int &num_errors, bool &quit_requested,
bool &stopped_for_crash);
SBError
RunREPL (lldb::LanguageType language, const char *repl_options);
SBError RunREPL(lldb::LanguageType language, const char *repl_options);
private:
friend class SBCommandInterpreter;
@ -343,20 +254,15 @@ private:
friend class SBSourceManager;
friend class SBTarget;
lldb::SBTarget
FindTargetWithLLDBProcess (const lldb::ProcessSP &processSP);
lldb::SBTarget FindTargetWithLLDBProcess(const lldb::ProcessSP &processSP);
void
reset (const lldb::DebuggerSP &debugger_sp);
void reset(const lldb::DebuggerSP &debugger_sp);
lldb_private::Debugger *
get () const;
lldb_private::Debugger *get() const;
lldb_private::Debugger &
ref () const;
lldb_private::Debugger &ref() const;
const lldb::DebuggerSP &
get_sp () const;
const lldb::DebuggerSP &get_sp() const;
lldb::DebuggerSP m_opaque_sp;

View File

@ -1,4 +1,5 @@
//===-- SBDeclaration.h -------------------------------------------*- C++ -*-===//
//===-- SBDeclaration.h -------------------------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
@ -15,74 +16,54 @@
namespace lldb {
class LLDB_API SBDeclaration
{
public:
class LLDB_API SBDeclaration {
public:
SBDeclaration();
SBDeclaration ();
SBDeclaration(const lldb::SBDeclaration &rhs);
SBDeclaration (const lldb::SBDeclaration &rhs);
~SBDeclaration();
~SBDeclaration ();
const lldb::SBDeclaration &operator=(const lldb::SBDeclaration &rhs);
const lldb::SBDeclaration &
operator = (const lldb::SBDeclaration &rhs);
bool IsValid() const;
bool
IsValid () const;
lldb::SBFileSpec GetFileSpec() const;
lldb::SBFileSpec
GetFileSpec () const;
uint32_t GetLine() const;
uint32_t
GetLine () const;
uint32_t GetColumn() const;
uint32_t
GetColumn () const;
void SetFileSpec(lldb::SBFileSpec filespec);
void
SetFileSpec (lldb::SBFileSpec filespec);
void SetLine(uint32_t line);
void
SetLine (uint32_t line);
void SetColumn(uint32_t column);
void
SetColumn (uint32_t column);
bool operator==(const lldb::SBDeclaration &rhs) const;
bool
operator == (const lldb::SBDeclaration &rhs) const;
bool operator!=(const lldb::SBDeclaration &rhs) const;
bool
operator != (const lldb::SBDeclaration &rhs) const;
bool GetDescription(lldb::SBStream &description);
bool
GetDescription (lldb::SBStream &description);
protected:
lldb_private::Declaration *get();
protected:
lldb_private::Declaration *
get ();
private:
private:
friend class SBValue;
const lldb_private::Declaration *
operator->() const;
const lldb_private::Declaration *operator->() const;
lldb_private::Declaration &
ref();
lldb_private::Declaration &ref();
const lldb_private::Declaration &
ref() const;
const lldb_private::Declaration &ref() const;
SBDeclaration (const lldb_private::Declaration *lldb_object_ptr);
SBDeclaration(const lldb_private::Declaration *lldb_object_ptr);
void
SetDeclaration (const lldb_private::Declaration &lldb_object_ref);
void SetDeclaration(const lldb_private::Declaration &lldb_object_ref);
std::unique_ptr<lldb_private::Declaration> m_opaque_ap;
};
};
} // namespace lldb

View File

@ -96,7 +96,6 @@ class LLDB_API SBValueList;
class LLDB_API SBVariablesOptions;
class LLDB_API SBWatchpoint;
class LLDB_API SBUnixSignals;
}
#endif // LLDB_SBDefines_h_

View File

@ -16,56 +16,42 @@ namespace lldb {
class LLDB_API SBError {
public:
SBError ();
SBError();
SBError (const lldb::SBError &rhs);
SBError(const lldb::SBError &rhs);
~SBError();
const SBError &
operator =(const lldb::SBError &rhs);
const SBError &operator=(const lldb::SBError &rhs);
const char *
GetCString () const;
const char *GetCString() const;
void
Clear ();
void Clear();
bool
Fail () const;
bool Fail() const;
bool
Success () const;
bool Success() const;
uint32_t
GetError () const;
uint32_t GetError() const;
lldb::ErrorType
GetType () const;
lldb::ErrorType GetType() const;
void
SetError (uint32_t err, lldb::ErrorType type);
void SetError(uint32_t err, lldb::ErrorType type);
void
SetErrorToErrno ();
void SetErrorToErrno();
void
SetErrorToGenericError ();
void SetErrorToGenericError();
void
SetErrorString (const char *err_str);
void SetErrorString(const char *err_str);
int
SetErrorStringWithFormat (const char *format, ...) __attribute__ ((format (printf, 2, 3)));
int SetErrorStringWithFormat(const char *format, ...)
__attribute__((format(printf, 2, 3)));
bool
IsValid () const;
bool IsValid() const;
bool
GetDescription (lldb::SBStream &description);
bool GetDescription(lldb::SBStream &description);
protected:
friend class SBCommandReturnObject;
friend class SBData;
friend class SBDebugger;
@ -81,29 +67,22 @@ protected:
friend class SBBreakpoint;
friend class SBBreakpointLocation;
lldb_private::Error *
get();
lldb_private::Error *get();
lldb_private::Error *
operator->();
lldb_private::Error *operator->();
const lldb_private::Error &
operator*() const;
const lldb_private::Error &operator*() const;
lldb_private::Error &
ref();
lldb_private::Error &ref();
void
SetError (const lldb_private::Error &lldb_error);
void SetError(const lldb_private::Error &lldb_error);
private:
std::unique_ptr<lldb_private::Error> m_opaque_ap;
void
CreateIfNeeded ();
void CreateIfNeeded();
};
} // namespace lldb
#endif // LLDB_SBError_h_

View File

@ -15,62 +15,48 @@
#include <stdio.h>
#include <vector>
namespace lldb {
class SBBroadcaster;
class LLDB_API SBEvent
{
class LLDB_API SBEvent {
public:
SBEvent();
SBEvent (const lldb::SBEvent &rhs);
SBEvent(const lldb::SBEvent &rhs);
// Make an event that contains a C string.
SBEvent (uint32_t event, const char *cstr, uint32_t cstr_len);
SBEvent(uint32_t event, const char *cstr, uint32_t cstr_len);
SBEvent (lldb::EventSP &event_sp);
SBEvent(lldb::EventSP &event_sp);
SBEvent (lldb_private::Event *event_sp);
SBEvent(lldb_private::Event *event_sp);
~SBEvent();
const SBEvent &
operator = (const lldb::SBEvent &rhs);
const SBEvent &operator=(const lldb::SBEvent &rhs);
bool
IsValid() const;
bool IsValid() const;
const char *
GetDataFlavor ();
const char *GetDataFlavor();
uint32_t
GetType () const;
uint32_t GetType() const;
lldb::SBBroadcaster
GetBroadcaster () const;
lldb::SBBroadcaster GetBroadcaster() const;
const char *
GetBroadcasterClass () const;
const char *GetBroadcasterClass() const;
bool
BroadcasterMatchesPtr (const lldb::SBBroadcaster *broadcaster);
bool BroadcasterMatchesPtr(const lldb::SBBroadcaster *broadcaster);
bool
BroadcasterMatchesRef (const lldb::SBBroadcaster &broadcaster);
bool BroadcasterMatchesRef(const lldb::SBBroadcaster &broadcaster);
void
Clear();
void Clear();
static const char *
GetCStringFromEvent (const lldb::SBEvent &event);
static const char *GetCStringFromEvent(const lldb::SBEvent &event);
bool
GetDescription (lldb::SBStream &description);
bool GetDescription(lldb::SBStream &description);
bool
GetDescription (lldb::SBStream &description) const;
bool GetDescription(lldb::SBStream &description) const;
protected:
friend class SBListener;
@ -82,20 +68,15 @@ protected:
friend class SBThread;
friend class SBWatchpoint;
lldb::EventSP &
GetSP () const;
lldb::EventSP &GetSP() const;
void
reset (lldb::EventSP &event_sp);
void reset(lldb::EventSP &event_sp);
void
reset (lldb_private::Event* event);
void reset(lldb_private::Event *event);
lldb_private::Event *
get () const;
lldb_private::Event *get() const;
private:
mutable lldb::EventSP m_event_sp;
mutable lldb_private::Event *m_opaque_ptr;
};

View File

@ -1,4 +1,5 @@
//===-- SBExecutionContext.h -----------------------------------------*- C++ -*-===//
//===-- SBExecutionContext.h -----------------------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
@ -15,57 +16,48 @@
#include <stdio.h>
#include <vector>
namespace lldb {
class LLDB_API SBExecutionContext
{
friend class SBCommandInterpreter;
class LLDB_API SBExecutionContext {
friend class SBCommandInterpreter;
public:
SBExecutionContext();
SBExecutionContext (const lldb::SBExecutionContext &rhs);
SBExecutionContext(const lldb::SBExecutionContext &rhs);
SBExecutionContext (lldb::ExecutionContextRefSP exe_ctx_ref_sp);
SBExecutionContext(lldb::ExecutionContextRefSP exe_ctx_ref_sp);
SBExecutionContext (const lldb::SBTarget &target);
SBExecutionContext(const lldb::SBTarget &target);
SBExecutionContext (const lldb::SBProcess &process);
SBExecutionContext(const lldb::SBProcess &process);
SBExecutionContext (lldb::SBThread thread); // can't be a const& because SBThread::get() isn't itself a const function
SBExecutionContext(lldb::SBThread thread); // can't be a const& because
// SBThread::get() isn't itself a
// const function
SBExecutionContext (const lldb::SBFrame &frame);
SBExecutionContext(const lldb::SBFrame &frame);
~SBExecutionContext();
const SBExecutionContext &
operator = (const lldb::SBExecutionContext &rhs);
const SBExecutionContext &operator=(const lldb::SBExecutionContext &rhs);
SBTarget
GetTarget () const;
SBTarget GetTarget() const;
SBProcess
GetProcess () const;
SBProcess GetProcess() const;
SBThread
GetThread () const;
SBThread GetThread() const;
SBFrame
GetFrame () const;
SBFrame GetFrame() const;
protected:
ExecutionContextRefSP &
GetSP () const;
ExecutionContextRefSP &GetSP() const;
void
reset (lldb::ExecutionContextRefSP &event_sp);
void reset(lldb::ExecutionContextRefSP &event_sp);
lldb_private::ExecutionContextRef *
get () const;
lldb_private::ExecutionContextRef *get() const;
private:
mutable lldb::ExecutionContextRefSP m_exe_ctx_sp;
};

View File

@ -16,123 +16,90 @@
namespace lldb {
class LLDB_API SBExpressionOptions
{
class LLDB_API SBExpressionOptions {
public:
SBExpressionOptions();
SBExpressionOptions (const lldb::SBExpressionOptions &rhs);
SBExpressionOptions(const lldb::SBExpressionOptions &rhs);
~SBExpressionOptions();
const SBExpressionOptions &
operator = (const lldb::SBExpressionOptions &rhs);
const SBExpressionOptions &operator=(const lldb::SBExpressionOptions &rhs);
bool
GetCoerceResultToId () const;
bool GetCoerceResultToId() const;
void
SetCoerceResultToId (bool coerce = true);
void SetCoerceResultToId(bool coerce = true);
bool
GetUnwindOnError () const;
bool GetUnwindOnError() const;
void
SetUnwindOnError (bool unwind = true);
void SetUnwindOnError(bool unwind = true);
bool
GetIgnoreBreakpoints () const;
bool GetIgnoreBreakpoints() const;
void
SetIgnoreBreakpoints (bool ignore = true);
void SetIgnoreBreakpoints(bool ignore = true);
lldb::DynamicValueType
GetFetchDynamicValue () const;
lldb::DynamicValueType GetFetchDynamicValue() const;
void
SetFetchDynamicValue (lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget);
void SetFetchDynamicValue(
lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget);
uint32_t
GetTimeoutInMicroSeconds () const;
uint32_t GetTimeoutInMicroSeconds() const;
// Set the timeout for the expression, 0 means wait forever.
void
SetTimeoutInMicroSeconds (uint32_t timeout = 0);
void SetTimeoutInMicroSeconds(uint32_t timeout = 0);
uint32_t
GetOneThreadTimeoutInMicroSeconds () const;
uint32_t GetOneThreadTimeoutInMicroSeconds() const;
// Set the timeout for running on one thread, 0 means use the default behavior.
// If you set this higher than the overall timeout, you'll get an error when you
// Set the timeout for running on one thread, 0 means use the default
// behavior.
// If you set this higher than the overall timeout, you'll get an error when
// you
// try to run the expression.
void
SetOneThreadTimeoutInMicroSeconds (uint32_t timeout = 0);
void SetOneThreadTimeoutInMicroSeconds(uint32_t timeout = 0);
bool
GetTryAllThreads () const;
bool GetTryAllThreads() const;
void
SetTryAllThreads (bool run_others = true);
void SetTryAllThreads(bool run_others = true);
bool
GetStopOthers() const;
bool GetStopOthers() const;
void
SetStopOthers(bool stop_others = true);
void SetStopOthers(bool stop_others = true);
bool
GetTrapExceptions () const;
bool GetTrapExceptions() const;
void
SetTrapExceptions (bool trap_exceptions = true);
void SetTrapExceptions(bool trap_exceptions = true);
void
SetLanguage (lldb::LanguageType language);
void SetLanguage(lldb::LanguageType language);
void
SetCancelCallback (lldb::ExpressionCancelCallback callback, void *baton);
void SetCancelCallback(lldb::ExpressionCancelCallback callback, void *baton);
bool
GetGenerateDebugInfo ();
bool GetGenerateDebugInfo();
void
SetGenerateDebugInfo (bool b = true);
void SetGenerateDebugInfo(bool b = true);
bool
GetSuppressPersistentResult ();
bool GetSuppressPersistentResult();
void
SetSuppressPersistentResult (bool b = false);
void SetSuppressPersistentResult(bool b = false);
const char *
GetPrefix () const;
const char *GetPrefix() const;
void
SetPrefix (const char *prefix);
void SetPrefix(const char *prefix);
void
SetAutoApplyFixIts(bool b = true);
void SetAutoApplyFixIts(bool b = true);
bool
GetAutoApplyFixIts();
bool GetAutoApplyFixIts();
bool
GetTopLevel ();
void
SetTopLevel (bool b = true);
bool GetTopLevel();
void SetTopLevel(bool b = true);
protected:
SBExpressionOptions(
lldb_private::EvaluateExpressionOptions &expression_options);
SBExpressionOptions (lldb_private::EvaluateExpressionOptions &expression_options);
lldb_private::EvaluateExpressionOptions *get() const;
lldb_private::EvaluateExpressionOptions *
get () const;
lldb_private::EvaluateExpressionOptions &
ref () const;
lldb_private::EvaluateExpressionOptions &ref() const;
friend class SBFrame;
friend class SBValue;

View File

@ -14,54 +14,42 @@
namespace lldb {
class LLDB_API SBFileSpec
{
class LLDB_API SBFileSpec {
public:
SBFileSpec ();
SBFileSpec();
SBFileSpec (const lldb::SBFileSpec &rhs);
SBFileSpec(const lldb::SBFileSpec &rhs);
SBFileSpec (const char *path);// Deprecated, use SBFileSpec (const char *path, bool resolve)
SBFileSpec(const char *path); // Deprecated, use SBFileSpec (const char *path,
// bool resolve)
SBFileSpec (const char *path, bool resolve);
SBFileSpec(const char *path, bool resolve);
~SBFileSpec ();
~SBFileSpec();
const SBFileSpec &
operator = (const lldb::SBFileSpec &rhs);
const SBFileSpec &operator=(const lldb::SBFileSpec &rhs);
bool
IsValid() const;
bool IsValid() const;
bool
Exists () const;
bool Exists() const;
bool
ResolveExecutableLocation ();
bool ResolveExecutableLocation();
const char *
GetFilename() const;
const char *GetFilename() const;
const char *
GetDirectory() const;
const char *GetDirectory() const;
void
SetFilename(const char *filename);
void SetFilename(const char *filename);
void
SetDirectory(const char *directory);
void SetDirectory(const char *directory);
uint32_t
GetPath (char *dst_path, size_t dst_len) const;
uint32_t GetPath(char *dst_path, size_t dst_len) const;
static int
ResolvePath (const char *src_path, char *dst_path, size_t dst_len);
static int ResolvePath(const char *src_path, char *dst_path, size_t dst_len);
bool
GetDescription (lldb::SBStream &description) const;
bool GetDescription(lldb::SBStream &description) const;
void
AppendPathComponent (const char *file_or_directory);
void AppendPathComponent(const char *file_or_directory);
private:
friend class SBAttachInfo;
@ -81,27 +69,21 @@ private:
friend class SBThread;
friend class SBTarget;
SBFileSpec (const lldb_private::FileSpec& fspec);
SBFileSpec(const lldb_private::FileSpec &fspec);
void
SetFileSpec (const lldb_private::FileSpec& fspec);
void SetFileSpec(const lldb_private::FileSpec &fspec);
const lldb_private::FileSpec *
operator->() const;
const lldb_private::FileSpec *operator->() const;
const lldb_private::FileSpec *
get() const;
const lldb_private::FileSpec *get() const;
const lldb_private::FileSpec &
operator*() const;
const lldb_private::FileSpec &operator*() const;
const lldb_private::FileSpec &
ref() const;
const lldb_private::FileSpec &ref() const;
std::unique_ptr<lldb_private::FileSpec> m_opaque_ap;
};
} // namespace lldb
#endif // LLDB_SBFileSpec_h_

View File

@ -1,4 +1,5 @@
//===-- SBFileSpecList.h --------------------------------------------*- C++ -*-===//
//===-- SBFileSpecList.h --------------------------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
@ -14,59 +15,44 @@
namespace lldb {
class LLDB_API SBFileSpecList
{
class LLDB_API SBFileSpecList {
public:
SBFileSpecList ();
SBFileSpecList();
SBFileSpecList (const lldb::SBFileSpecList &rhs);
SBFileSpecList(const lldb::SBFileSpecList &rhs);
~SBFileSpecList ();
~SBFileSpecList();
const SBFileSpecList &
operator = (const lldb::SBFileSpecList &rhs);
const SBFileSpecList &operator=(const lldb::SBFileSpecList &rhs);
uint32_t
GetSize () const;
uint32_t GetSize() const;
bool
GetDescription (SBStream &description) const;
bool GetDescription(SBStream &description) const;
void
Append (const SBFileSpec &sb_file);
void Append(const SBFileSpec &sb_file);
bool
AppendIfUnique (const SBFileSpec &sb_file);
bool AppendIfUnique(const SBFileSpec &sb_file);
void
Clear();
void Clear();
uint32_t
FindFileIndex (uint32_t idx, const SBFileSpec &sb_file, bool full);
uint32_t FindFileIndex(uint32_t idx, const SBFileSpec &sb_file, bool full);
const SBFileSpec
GetFileSpecAtIndex (uint32_t idx) const;
const SBFileSpec GetFileSpecAtIndex(uint32_t idx) const;
private:
friend class SBTarget;
friend class SBTarget;
const lldb_private::FileSpecList *operator->() const;
const lldb_private::FileSpecList *
operator->() const;
const lldb_private::FileSpecList *get() const;
const lldb_private::FileSpecList *
get() const;
const lldb_private::FileSpecList &operator*() const;
const lldb_private::FileSpecList &
operator*() const;
const lldb_private::FileSpecList &
ref() const;
const lldb_private::FileSpecList &ref() const;
std::unique_ptr<lldb_private::FileSpecList> m_opaque_ap;
};
} // namespace lldb
#endif // LLDB_SBFileSpecList_h_

View File

@ -15,65 +15,48 @@
namespace lldb {
class LLDB_API SBFrame
{
class LLDB_API SBFrame {
public:
SBFrame ();
SBFrame();
SBFrame (const lldb::SBFrame &rhs);
SBFrame(const lldb::SBFrame &rhs);
const lldb::SBFrame &
operator =(const lldb::SBFrame &rhs);
const lldb::SBFrame &operator=(const lldb::SBFrame &rhs);
~SBFrame();
bool
IsEqual (const lldb::SBFrame &that) const;
bool IsEqual(const lldb::SBFrame &that) const;
bool
IsValid() const;
bool IsValid() const;
uint32_t
GetFrameID () const;
uint32_t GetFrameID() const;
lldb::addr_t
GetCFA () const;
lldb::addr_t GetCFA() const;
lldb::addr_t
GetPC () const;
lldb::addr_t GetPC() const;
bool
SetPC (lldb::addr_t new_pc);
bool SetPC(lldb::addr_t new_pc);
lldb::addr_t
GetSP () const;
lldb::addr_t GetSP() const;
lldb::addr_t
GetFP () const;
lldb::addr_t GetFP() const;
lldb::SBAddress
GetPCAddress () const;
lldb::SBAddress GetPCAddress() const;
lldb::SBSymbolContext
GetSymbolContext (uint32_t resolve_scope) const;
lldb::SBSymbolContext GetSymbolContext(uint32_t resolve_scope) const;
lldb::SBModule
GetModule () const;
lldb::SBModule GetModule() const;
lldb::SBCompileUnit
GetCompileUnit () const;
lldb::SBCompileUnit GetCompileUnit() const;
lldb::SBFunction
GetFunction () const;
lldb::SBFunction GetFunction() const;
lldb::SBSymbol
GetSymbol () const;
lldb::SBSymbol GetSymbol() const;
/// Gets the deepest block that contains the frame PC.
///
/// See also GetFrameBlock().
lldb::SBBlock
GetBlock () const;
lldb::SBBlock GetBlock() const;
/// Get the appropriate function name for this frame. Inlined functions in
/// LLDB are represented by Blocks that have inlined function information, so
@ -88,38 +71,34 @@ public:
/// - NULL
///
/// See also IsInlined().
const char *
GetFunctionName();
const char *GetFunctionName();
// Get an appropriate function name for this frame that is suitable for display to a user
const char *
GetDisplayFunctionName ();
// Get an appropriate function name for this frame that is suitable for
// display to a user
const char *GetDisplayFunctionName();
const char *
GetFunctionName() const;
const char *GetFunctionName() const;
/// Return true if this frame represents an inlined function.
///
/// See also GetFunctionName().
bool
IsInlined();
bool IsInlined();
bool
IsInlined() const;
bool IsInlined() const;
/// The version that doesn't supply a 'use_dynamic' value will use the
/// target's default.
lldb::SBValue
EvaluateExpression (const char *expr);
lldb::SBValue EvaluateExpression(const char *expr);
lldb::SBValue
EvaluateExpression (const char *expr, lldb::DynamicValueType use_dynamic);
lldb::SBValue EvaluateExpression(const char *expr,
lldb::DynamicValueType use_dynamic);
lldb::SBValue
EvaluateExpression (const char *expr, lldb::DynamicValueType use_dynamic, bool unwind_on_error);
lldb::SBValue EvaluateExpression(const char *expr,
lldb::DynamicValueType use_dynamic,
bool unwind_on_error);
lldb::SBValue
EvaluateExpression (const char *expr, const SBExpressionOptions &options);
lldb::SBValue EvaluateExpression(const char *expr,
const SBExpressionOptions &options);
/// Gets the lexical block that defines the stack frame. Another way to think
/// of this is it will return the block that contains all of the variables
@ -133,72 +112,53 @@ public:
/// in one of those inlined functions, this method will return the inlined
/// block that defines this frame. If the PC isn't currently in an inlined
/// function, the lexical block that defines the function is returned.
lldb::SBBlock
GetFrameBlock () const;
lldb::SBBlock GetFrameBlock() const;
lldb::SBLineEntry
GetLineEntry () const;
lldb::SBLineEntry GetLineEntry() const;
lldb::SBThread
GetThread () const;
lldb::SBThread GetThread() const;
const char *
Disassemble () const;
const char *Disassemble() const;
void
Clear();
void Clear();
bool
operator == (const lldb::SBFrame &rhs) const;
bool operator==(const lldb::SBFrame &rhs) const;
bool
operator != (const lldb::SBFrame &rhs) const;
bool operator!=(const lldb::SBFrame &rhs) const;
/// The version that doesn't supply a 'use_dynamic' value will use the
/// target's default.
lldb::SBValueList
GetVariables (bool arguments,
bool locals,
bool statics,
lldb::SBValueList GetVariables(bool arguments, bool locals, bool statics,
bool in_scope_only);
lldb::SBValueList
GetVariables (bool arguments,
bool locals,
bool statics,
lldb::SBValueList GetVariables(bool arguments, bool locals, bool statics,
bool in_scope_only,
lldb::DynamicValueType use_dynamic);
lldb::SBValueList
GetVariables (const lldb::SBVariablesOptions& options);
lldb::SBValueList GetVariables(const lldb::SBVariablesOptions &options);
lldb::SBValueList
GetRegisters ();
lldb::SBValueList GetRegisters();
lldb::SBValue
FindRegister (const char *name);
lldb::SBValue FindRegister(const char *name);
/// The version that doesn't supply a 'use_dynamic' value will use the
/// target's default.
lldb::SBValue
FindVariable (const char *var_name);
lldb::SBValue FindVariable(const char *var_name);
lldb::SBValue
FindVariable (const char *var_name, lldb::DynamicValueType use_dynamic);
lldb::SBValue FindVariable(const char *var_name,
lldb::DynamicValueType use_dynamic);
// Find a value for a variable expression path like "rect.origin.x" or
// "pt_ptr->x", "*self", "*this->obj_ptr". The returned value is _not_
// and expression result and is not a constant object like
// SBFrame::EvaluateExpression(...) returns, but a child object of
// the variable value.
lldb::SBValue
GetValueForVariablePath (const char *var_expr_cstr,
lldb::SBValue GetValueForVariablePath(const char *var_expr_cstr,
DynamicValueType use_dynamic);
/// The version that doesn't supply a 'use_dynamic' value will use the
/// target's default.
lldb::SBValue
GetValueForVariablePath (const char *var_path);
lldb::SBValue GetValueForVariablePath(const char *var_path);
/// Find variables, register sets, registers, or persistent variables using
/// the frame as the scope.
@ -208,30 +168,25 @@ public:
///
/// The version that doesn't supply a 'use_dynamic' value will use the
/// target's default.
lldb::SBValue
FindValue (const char *name, ValueType value_type);
lldb::SBValue FindValue(const char *name, ValueType value_type);
lldb::SBValue
FindValue (const char *name, ValueType value_type, lldb::DynamicValueType use_dynamic);
lldb::SBValue FindValue(const char *name, ValueType value_type,
lldb::DynamicValueType use_dynamic);
bool
GetDescription (lldb::SBStream &description);
bool GetDescription(lldb::SBStream &description);
SBFrame (const lldb::StackFrameSP &lldb_object_sp);
SBFrame(const lldb::StackFrameSP &lldb_object_sp);
protected:
friend class SBBlock;
friend class SBExecutionContext;
friend class SBInstruction;
friend class SBThread;
friend class SBValue;
lldb::StackFrameSP
GetFrameSP() const;
lldb::StackFrameSP GetFrameSP() const;
void
SetFrameSP (const lldb::StackFrameSP &lldb_object_sp);
void SetFrameSP(const lldb::StackFrameSP &lldb_object_sp);
lldb::ExecutionContextRefSP m_opaque_sp;
};

View File

@ -10,96 +10,72 @@
#ifndef LLDB_SBFunction_h_
#define LLDB_SBFunction_h_
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBInstructionList.h"
namespace lldb {
class LLDB_API SBFunction
{
class LLDB_API SBFunction {
public:
SBFunction();
SBFunction ();
SBFunction(const lldb::SBFunction &rhs);
SBFunction (const lldb::SBFunction &rhs);
const lldb::SBFunction &operator=(const lldb::SBFunction &rhs);
const lldb::SBFunction &
operator = (const lldb::SBFunction &rhs);
~SBFunction();
~SBFunction ();
bool IsValid() const;
bool
IsValid () const;
const char *GetName() const;
const char *
GetName() const;
const char *GetDisplayName() const;
const char *
GetDisplayName() const;
const char *GetMangledName() const;
const char *
GetMangledName () const;
lldb::SBInstructionList GetInstructions(lldb::SBTarget target);
lldb::SBInstructionList
GetInstructions (lldb::SBTarget target);
lldb::SBInstructionList GetInstructions(lldb::SBTarget target,
const char *flavor);
lldb::SBInstructionList
GetInstructions (lldb::SBTarget target, const char *flavor);
lldb::SBAddress GetStartAddress();
lldb::SBAddress
GetStartAddress ();
lldb::SBAddress GetEndAddress();
lldb::SBAddress
GetEndAddress ();
const char *GetArgumentName(uint32_t arg_idx);
const char *
GetArgumentName (uint32_t arg_idx);
uint32_t GetPrologueByteSize();
uint32_t
GetPrologueByteSize ();
lldb::SBType GetType();
lldb::SBType
GetType ();
lldb::SBBlock GetBlock();
lldb::SBBlock
GetBlock ();
lldb::LanguageType GetLanguage();
lldb::LanguageType
GetLanguage ();
bool GetIsOptimized();
bool
GetIsOptimized ();
bool operator==(const lldb::SBFunction &rhs) const;
bool
operator == (const lldb::SBFunction &rhs) const;
bool operator!=(const lldb::SBFunction &rhs) const;
bool
operator != (const lldb::SBFunction &rhs) const;
bool
GetDescription (lldb::SBStream &description);
bool GetDescription(lldb::SBStream &description);
protected:
lldb_private::Function *get();
lldb_private::Function *
get ();
void
reset (lldb_private::Function *lldb_object_ptr);
void reset(lldb_private::Function *lldb_object_ptr);
private:
friend class SBAddress;
friend class SBFrame;
friend class SBSymbolContext;
SBFunction (lldb_private::Function *lldb_object_ptr);
SBFunction(lldb_private::Function *lldb_object_ptr);
lldb_private::Function *m_opaque_ptr;
};
} // namespace lldb
#endif // LLDB_SBFunction_h_

View File

@ -15,49 +15,31 @@
namespace lldb {
class LLDB_API SBHostOS
{
class LLDB_API SBHostOS {
public:
static lldb::SBFileSpec GetProgramFileSpec();
static lldb::SBFileSpec
GetProgramFileSpec ();
static lldb::SBFileSpec GetLLDBPythonPath();
static lldb::SBFileSpec
GetLLDBPythonPath ();
static lldb::SBFileSpec GetLLDBPath(lldb::PathType path_type);
static lldb::SBFileSpec
GetLLDBPath (lldb::PathType path_type);
static lldb::SBFileSpec GetUserHomeDirectory();
static lldb::SBFileSpec
GetUserHomeDirectory ();
static void ThreadCreated(const char *name);
static void
ThreadCreated (const char *name);
static lldb::thread_t
ThreadCreate (const char *name,
static lldb::thread_t ThreadCreate(const char *name,
lldb::thread_func_t thread_function,
void *thread_arg,
lldb::SBError *err);
void *thread_arg, lldb::SBError *err);
static bool
ThreadCancel (lldb::thread_t thread,
lldb::SBError *err);
static bool ThreadCancel(lldb::thread_t thread, lldb::SBError *err);
static bool
ThreadDetach (lldb::thread_t thread,
static bool ThreadDetach(lldb::thread_t thread, lldb::SBError *err);
static bool ThreadJoin(lldb::thread_t thread, lldb::thread_result_t *result,
lldb::SBError *err);
static bool
ThreadJoin (lldb::thread_t thread,
lldb::thread_result_t *result,
lldb::SBError *err);
private:
};
} // namespace lldb
#endif // LLDB_SBHostOS_h_

View File

@ -10,93 +10,76 @@
#ifndef LLDB_SBInstruction_h_
#define LLDB_SBInstruction_h_
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBData.h"
#include "lldb/API/SBDefines.h"
#include <stdio.h>
// There's a lot to be fixed here, but need to wait for underlying insn implementation
// There's a lot to be fixed here, but need to wait for underlying insn
// implementation
// to be revised & settle down first.
class InstructionImpl;
namespace lldb {
class LLDB_API SBInstruction
{
class LLDB_API SBInstruction {
public:
SBInstruction();
SBInstruction ();
SBInstruction(const SBInstruction &rhs);
SBInstruction (const SBInstruction &rhs);
const SBInstruction &operator=(const SBInstruction &rhs);
const SBInstruction &
operator = (const SBInstruction &rhs);
~SBInstruction();
~SBInstruction ();
bool IsValid();
bool
IsValid();
SBAddress GetAddress();
SBAddress
GetAddress();
lldb::AddressClass GetAddressClass();
lldb::AddressClass
GetAddressClass ();
const char *GetMnemonic(lldb::SBTarget target);
const char *
GetMnemonic (lldb::SBTarget target);
const char *GetOperands(lldb::SBTarget target);
const char *
GetOperands (lldb::SBTarget target);
const char *GetComment(lldb::SBTarget target);
const char *
GetComment (lldb::SBTarget target);
lldb::SBData GetData(lldb::SBTarget target);
lldb::SBData
GetData (lldb::SBTarget target);
size_t GetByteSize();
size_t
GetByteSize ();
bool DoesBranch();
bool
DoesBranch ();
bool HasDelaySlot();
bool
HasDelaySlot ();
void Print(FILE *out);
void
Print (FILE *out);
bool GetDescription(lldb::SBStream &description);
bool
GetDescription (lldb::SBStream &description);
bool EmulateWithFrame(lldb::SBFrame &frame, uint32_t evaluate_options);
bool
EmulateWithFrame (lldb::SBFrame &frame, uint32_t evaluate_options);
bool DumpEmulation(const char *triple); // triple is to specify the
// architecture, e.g. 'armv6' or
// 'armv7-apple-ios'
bool
DumpEmulation (const char * triple); // triple is to specify the architecture, e.g. 'armv6' or 'armv7-apple-ios'
bool
TestEmulation (lldb::SBStream &output_stream, const char *test_file);
bool TestEmulation(lldb::SBStream &output_stream, const char *test_file);
protected:
friend class SBInstructionList;
SBInstruction(const lldb::DisassemblerSP &disasm_sp, const lldb::InstructionSP &inst_sp);
SBInstruction(const lldb::DisassemblerSP &disasm_sp,
const lldb::InstructionSP &inst_sp);
void
SetOpaque(const lldb::DisassemblerSP &disasm_sp, const lldb::InstructionSP& inst_sp);
void SetOpaque(const lldb::DisassemblerSP &disasm_sp,
const lldb::InstructionSP &inst_sp);
lldb::InstructionSP
GetOpaque();
lldb::InstructionSP GetOpaque();
private:
std::shared_ptr<InstructionImpl> m_opaque_sp;
};
} // namespace lldb
#endif // LLDB_SBInstruction_h_

Some files were not shown because too many files have changed in this diff Show More