forked from OSchip/llvm-project
*** 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:
parent
d5aa733769
commit
b9c1b51e45
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
dirname = os.path.abspath(dirname)
|
||||
if not (check_has_dir_in_path(dirname)):
|
||||
sys.path.append(dirname)
|
||||
|
||||
|
||||
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 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";
|
||||
if not (os.sep in args):
|
||||
modname = args
|
||||
ensure_has_dir_in_path('.')
|
||||
else:
|
||||
endofdir = args.rfind(os.sep)
|
||||
modname = args[endofdir+1:]
|
||||
args = args[0:endofdir]
|
||||
ensure_has_dir_in_path(args)
|
||||
do_import(debugger,modname)
|
||||
return None
|
||||
"""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"
|
||||
if not (os.sep in args):
|
||||
modname = args
|
||||
ensure_has_dir_in_path('.')
|
||||
else:
|
||||
endofdir = args.rfind(os.sep)
|
||||
modname = args[endofdir + 1:]
|
||||
args = args[0:endofdir]
|
||||
ensure_has_dir_in_path(args)
|
||||
do_import(debugger, modname)
|
||||
return None
|
||||
|
|
|
@ -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
|
@ -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,319 +46,301 @@ 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
|
||||
SBDebugger::Initialize();
|
||||
}
|
||||
~LLDBSentry() {
|
||||
// Terminate LLDB
|
||||
SBDebugger::Terminate();
|
||||
}
|
||||
LLDBSentry() {
|
||||
// Initialize LLDB
|
||||
SBDebugger::Initialize();
|
||||
}
|
||||
~LLDBSentry() {
|
||||
// Terminate LLDB
|
||||
SBDebugger::Terminate();
|
||||
}
|
||||
};
|
||||
|
||||
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"
|
||||
"\n"
|
||||
"SYNOPSIS\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"
|
||||
"\n"
|
||||
"EXAMPLE\n"
|
||||
" " PROGRAM_NAME " --arch=x86_64 /usr/lib/dyld\n"
|
||||
);
|
||||
exit(0);
|
||||
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"
|
||||
"\n"
|
||||
"DESCRIPTION\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");
|
||||
exit(0);
|
||||
}
|
||||
int
|
||||
main (int argc, char const *argv[])
|
||||
{
|
||||
// Use a sentry object to properly initialize/terminate LLDB.
|
||||
LLDBSentry sentry;
|
||||
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");
|
||||
// Create a debugger instance so we can create a target
|
||||
if (!debugger.IsValid())
|
||||
fprintf(stderr, "error: failed to create a debugger object\n");
|
||||
|
||||
bool show_usage = false;
|
||||
bool verbose = false;
|
||||
bool canonical = false;
|
||||
bool external_only = false;
|
||||
const char *arch = NULL;
|
||||
const char *platform = NULL;
|
||||
std::string short_options("h?");
|
||||
for (const struct option *opt = g_long_options; opt->name; ++opt)
|
||||
{
|
||||
if (isprint(opt->val))
|
||||
{
|
||||
short_options.append(1, (char)opt->val);
|
||||
switch (opt->has_arg)
|
||||
{
|
||||
case no_argument:
|
||||
break;
|
||||
case required_argument:
|
||||
short_options.append(1, ':');
|
||||
break;
|
||||
case optional_argument:
|
||||
short_options.append(2, ':');
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool show_usage = false;
|
||||
bool verbose = false;
|
||||
bool canonical = false;
|
||||
bool external_only = false;
|
||||
const char *arch = NULL;
|
||||
const char *platform = NULL;
|
||||
std::string short_options("h?");
|
||||
for (const struct option *opt = g_long_options; opt->name; ++opt) {
|
||||
if (isprint(opt->val)) {
|
||||
short_options.append(1, (char)opt->val);
|
||||
switch (opt->has_arg) {
|
||||
case no_argument:
|
||||
break;
|
||||
case required_argument:
|
||||
short_options.append(1, ':');
|
||||
break;
|
||||
case optional_argument:
|
||||
short_options.append(2, ':');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __GLIBC__
|
||||
optind = 0;
|
||||
optind = 0;
|
||||
#else
|
||||
optreset = 1;
|
||||
optind = 1;
|
||||
optreset = 1;
|
||||
optind = 1;
|
||||
#endif
|
||||
char ch;
|
||||
while ((ch = getopt_long_only(argc, (char * const *)argv, short_options.c_str(), g_long_options, 0)) != -1)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
char ch;
|
||||
while ((ch = getopt_long_only(argc, (char *const *)argv,
|
||||
short_options.c_str(), g_long_options, 0)) !=
|
||||
-1) {
|
||||
switch (ch) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
if (arch != NULL)
|
||||
{
|
||||
fprintf (stderr, "error: the --arch option can only be specified once\n");
|
||||
exit(1);
|
||||
}
|
||||
arch = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
if (arch != NULL) {
|
||||
fprintf(stderr,
|
||||
"error: the --arch option can only be specified once\n");
|
||||
exit(1);
|
||||
}
|
||||
arch = optarg;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
canonical = true;
|
||||
break;
|
||||
case 'c':
|
||||
canonical = true;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
external_only = true;
|
||||
break;
|
||||
case 'x':
|
||||
external_only = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
platform = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
platform = optarg;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
show_usage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
const bool add_dependent_libs = false;
|
||||
SBError error;
|
||||
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);
|
||||
|
||||
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())
|
||||
{
|
||||
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);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SBFileSpecList module_list;
|
||||
module_list.Append(exe_file_spec);
|
||||
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)
|
||||
{
|
||||
SBBreakpointLocation bp_loc = bp.GetLocationAtIndex(bp_loc_idx);
|
||||
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())
|
||||
{
|
||||
addr_t lo_pc = function.GetStartAddress().GetFileAddress();
|
||||
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();
|
||||
const char *func_demangled_name = function.GetName();
|
||||
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)
|
||||
{
|
||||
// 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 (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);
|
||||
}
|
||||
SBType function_type = function.GetType();
|
||||
SBType return_type = function_type.GetFunctionReturnType();
|
||||
|
||||
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();
|
||||
const size_t num_function_args = function_args.GetSize();
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
const int selector_len = selector_end - selector_pos;
|
||||
SBType function_arg_type = function_args.GetTypeAtIndex(function_arg_idx);
|
||||
|
||||
if (canonical)
|
||||
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 ("(?)");
|
||||
}
|
||||
selector_pos = selector_end;
|
||||
}
|
||||
printf ("]\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("%s ", return_type.GetName());
|
||||
if (strchr (func_demangled_name, '('))
|
||||
printf ("(*)(");
|
||||
else
|
||||
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);
|
||||
|
||||
if (canonical)
|
||||
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 ? ", " : "");
|
||||
}
|
||||
}
|
||||
printf (")\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "error: %s\n", error.GetCString());
|
||||
exit(1);
|
||||
}
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
show_usage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
return 0;
|
||||
const bool add_dependent_libs = false;
|
||||
SBError error;
|
||||
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);
|
||||
|
||||
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()) {
|
||||
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);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SBFileSpecList module_list;
|
||||
module_list.Append(exe_file_spec);
|
||||
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) {
|
||||
SBBreakpointLocation bp_loc = bp.GetLocationAtIndex(bp_loc_idx);
|
||||
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()) {
|
||||
addr_t lo_pc = function.GetStartAddress().GetFileAddress();
|
||||
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();
|
||||
const char *func_demangled_name = function.GetName();
|
||||
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) {
|
||||
// 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 (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);
|
||||
}
|
||||
SBType function_type = function.GetType();
|
||||
SBType return_type = function_type.GetFunctionReturnType();
|
||||
|
||||
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();
|
||||
const size_t num_function_args = function_args.GetSize();
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
const int selector_len = selector_end - selector_pos;
|
||||
SBType function_arg_type =
|
||||
function_args.GetTypeAtIndex(function_arg_idx);
|
||||
|
||||
if (canonical)
|
||||
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("(?)");
|
||||
}
|
||||
selector_pos = selector_end;
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
} else {
|
||||
printf("%s ", return_type.GetName());
|
||||
if (strchr(func_demangled_name, '('))
|
||||
printf("(*)(");
|
||||
else
|
||||
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);
|
||||
|
||||
if (canonical)
|
||||
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 ? ", " : "");
|
||||
}
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "error: %s\n", error.GetCString());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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,192 +44,179 @@ 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
|
||||
SBDebugger::Initialize();
|
||||
}
|
||||
~LLDBSentry() {
|
||||
// Terminate LLDB
|
||||
SBDebugger::Terminate();
|
||||
}
|
||||
LLDBSentry() {
|
||||
// Initialize LLDB
|
||||
SBDebugger::Initialize();
|
||||
}
|
||||
~LLDBSentry() {
|
||||
// Terminate LLDB
|
||||
SBDebugger::Terminate();
|
||||
}
|
||||
};
|
||||
|
||||
static struct option g_long_options[] =
|
||||
{
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "arch", required_argument, NULL, 'a' },
|
||||
{ "platform", required_argument, NULL, 'p' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
static struct option g_long_options[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
{"arch", required_argument, NULL, 'a'},
|
||||
{"platform", required_argument, NULL, 'p'},
|
||||
{NULL, 0, NULL, 0}};
|
||||
|
||||
#define PROGRAM_NAME "lldb-lookup"
|
||||
void
|
||||
usage ()
|
||||
{
|
||||
puts (
|
||||
"NAME\n"
|
||||
" " PROGRAM_NAME " -- symbolicate addresses using lldb.\n"
|
||||
"\n"
|
||||
"SYNOPSIS\n"
|
||||
" " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] [--verbose] [--help] --] <PATH> <ADDRESS> [<ADDRESS>....]\n"
|
||||
"\n"
|
||||
"DESCRIPTION\n"
|
||||
" Loads the executable pointed to by <PATH> and looks up and <ADDRESS>\n"
|
||||
" arguments\n"
|
||||
"\n"
|
||||
"EXAMPLE\n"
|
||||
" " PROGRAM_NAME " --arch=x86_64 -- /usr/lib/dyld 0x100000000\n"
|
||||
);
|
||||
exit(0);
|
||||
void usage() {
|
||||
puts("NAME\n"
|
||||
" " PROGRAM_NAME " -- symbolicate addresses using lldb.\n"
|
||||
"\n"
|
||||
"SYNOPSIS\n"
|
||||
" " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] "
|
||||
"[--verbose] [--help] --] <PATH> <ADDRESS> "
|
||||
"[<ADDRESS>....]\n"
|
||||
"\n"
|
||||
"DESCRIPTION\n"
|
||||
" Loads the executable pointed to by <PATH> and looks up and "
|
||||
"<ADDRESS>\n"
|
||||
" arguments\n"
|
||||
"\n"
|
||||
"EXAMPLE\n"
|
||||
" " PROGRAM_NAME " --arch=x86_64 -- /usr/lib/dyld 0x100000000\n");
|
||||
exit(0);
|
||||
}
|
||||
int
|
||||
main (int argc, char const *argv[])
|
||||
{
|
||||
// Use a sentry object to properly initialize/terminate LLDB.
|
||||
LLDBSentry sentry;
|
||||
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");
|
||||
// Create a debugger instance so we can create a target
|
||||
if (!debugger.IsValid())
|
||||
fprintf(stderr, "error: failed to create a debugger object\n");
|
||||
|
||||
bool show_usage = false;
|
||||
bool verbose = false;
|
||||
const char *arch = NULL;
|
||||
const char *platform = NULL;
|
||||
std::string short_options("h?");
|
||||
for (const struct option *opt = g_long_options; opt->name; ++opt)
|
||||
{
|
||||
if (isprint(opt->val))
|
||||
{
|
||||
short_options.append(1, (char)opt->val);
|
||||
switch (opt->has_arg)
|
||||
{
|
||||
case no_argument:
|
||||
break;
|
||||
case required_argument:
|
||||
short_options.append(1, ':');
|
||||
break;
|
||||
case optional_argument:
|
||||
short_options.append(2, ':');
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool show_usage = false;
|
||||
bool verbose = false;
|
||||
const char *arch = NULL;
|
||||
const char *platform = NULL;
|
||||
std::string short_options("h?");
|
||||
for (const struct option *opt = g_long_options; opt->name; ++opt) {
|
||||
if (isprint(opt->val)) {
|
||||
short_options.append(1, (char)opt->val);
|
||||
switch (opt->has_arg) {
|
||||
case no_argument:
|
||||
break;
|
||||
case required_argument:
|
||||
short_options.append(1, ':');
|
||||
break;
|
||||
case optional_argument:
|
||||
short_options.append(2, ':');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __GLIBC__
|
||||
optind = 0;
|
||||
optind = 0;
|
||||
#else
|
||||
optreset = 1;
|
||||
optind = 1;
|
||||
optreset = 1;
|
||||
optind = 1;
|
||||
#endif
|
||||
char ch;
|
||||
while ((ch = getopt_long_only(argc, (char * const *)argv, short_options.c_str(), g_long_options, 0)) != -1)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
char ch;
|
||||
while ((ch = getopt_long_only(argc, (char *const *)argv,
|
||||
short_options.c_str(), g_long_options, 0)) !=
|
||||
-1) {
|
||||
switch (ch) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
if (arch != NULL)
|
||||
{
|
||||
fprintf (stderr, "error: the --arch option can only be specified once\n");
|
||||
exit(1);
|
||||
}
|
||||
arch = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
if (arch != NULL) {
|
||||
fprintf(stderr,
|
||||
"error: the --arch option can only be specified once\n");
|
||||
exit(1);
|
||||
}
|
||||
arch = optarg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
platform = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
platform = optarg;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
show_usage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
show_usage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (show_usage || argc < 2)
|
||||
usage();
|
||||
if (show_usage || argc < 2)
|
||||
usage();
|
||||
|
||||
int arg_idx = 0;
|
||||
// The first argument is the file path we want to look something up in
|
||||
const char *exe_file_path = argv[arg_idx];
|
||||
const char *addr_cstr;
|
||||
const bool add_dependent_libs = false;
|
||||
SBError error;
|
||||
SBStream strm;
|
||||
strm.RedirectToFileHandle (stdout, false);
|
||||
int arg_idx = 0;
|
||||
// The first argument is the file path we want to look something up in
|
||||
const char *exe_file_path = argv[arg_idx];
|
||||
const char *addr_cstr;
|
||||
const bool add_dependent_libs = false;
|
||||
SBError error;
|
||||
SBStream strm;
|
||||
strm.RedirectToFileHandle(stdout, false);
|
||||
|
||||
while ((addr_cstr = argv[++arg_idx]) != NULL)
|
||||
{
|
||||
// The second argument in the address that we want to lookup
|
||||
lldb::addr_t file_addr = strtoull (addr_cstr, NULL, 0);
|
||||
while ((addr_cstr = argv[++arg_idx]) != NULL) {
|
||||
// The second argument in the address that we want to lookup
|
||||
lldb::addr_t file_addr = strtoull(addr_cstr, NULL, 0);
|
||||
|
||||
// Create a target using the executable.
|
||||
SBTarget target = debugger.CreateTarget (exe_file_path,
|
||||
arch,
|
||||
platform,
|
||||
add_dependent_libs,
|
||||
error);
|
||||
if (!error.Success())
|
||||
{
|
||||
fprintf (stderr, "error: %s\n", error.GetCString());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf ("%sLooking up 0x%llx in '%s':\n", (arg_idx > 1) ? "\n" : "", file_addr, exe_file_path);
|
||||
|
||||
if (target.IsValid())
|
||||
{
|
||||
// Find the executable module so we can do a lookup inside it
|
||||
SBFileSpec exe_file_spec (exe_file_path, true);
|
||||
SBModule module (target.FindModule (exe_file_spec));
|
||||
|
||||
// Take a file virtual address and resolve it to a section offset
|
||||
// address that can be used to do a symbol lookup by address
|
||||
SBAddress addr = module.ResolveFileAddress (file_addr);
|
||||
bool success = addr.IsValid() && addr.GetSection().IsValid();
|
||||
if (success)
|
||||
{
|
||||
// We can resolve a section offset address in the module
|
||||
// and only ask for what we need. You can logical or together
|
||||
// bits from the SymbolContextItem enumeration found in
|
||||
// lldb-enumeration.h to request only what you want. Here we
|
||||
// are asking for everything.
|
||||
//
|
||||
// NOTE: the less you ask for, the less LLDB will parse as
|
||||
// LLDB does partial parsing on just about everything.
|
||||
SBSymbolContext sc (module.ResolveSymbolContextForAddress (addr, eSymbolContextEverything));
|
||||
|
||||
strm.Printf (" Address: %s + 0x%llx\n Summary: ", addr.GetSection().GetName (), addr.GetOffset());
|
||||
addr.GetDescription (strm);
|
||||
strm.Printf ("\n");
|
||||
if (verbose)
|
||||
sc.GetDescription (strm);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("error: 0x%llx does not resolve to a valid file address in '%s'\n", file_addr, exe_file_path);
|
||||
}
|
||||
}
|
||||
// Create a target using the executable.
|
||||
SBTarget target = debugger.CreateTarget(exe_file_path, arch, platform,
|
||||
add_dependent_libs, error);
|
||||
if (!error.Success()) {
|
||||
fprintf(stderr, "error: %s\n", error.GetCString());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
printf("%sLooking up 0x%llx in '%s':\n", (arg_idx > 1) ? "\n" : "",
|
||||
file_addr, exe_file_path);
|
||||
|
||||
if (target.IsValid()) {
|
||||
// Find the executable module so we can do a lookup inside it
|
||||
SBFileSpec exe_file_spec(exe_file_path, true);
|
||||
SBModule module(target.FindModule(exe_file_spec));
|
||||
|
||||
// Take a file virtual address and resolve it to a section offset
|
||||
// address that can be used to do a symbol lookup by address
|
||||
SBAddress addr = module.ResolveFileAddress(file_addr);
|
||||
bool success = addr.IsValid() && addr.GetSection().IsValid();
|
||||
if (success) {
|
||||
// We can resolve a section offset address in the module
|
||||
// and only ask for what we need. You can logical or together
|
||||
// bits from the SymbolContextItem enumeration found in
|
||||
// lldb-enumeration.h to request only what you want. Here we
|
||||
// are asking for everything.
|
||||
//
|
||||
// NOTE: the less you ask for, the less LLDB will parse as
|
||||
// LLDB does partial parsing on just about everything.
|
||||
SBSymbolContext sc(module.ResolveSymbolContextForAddress(
|
||||
addr, eSymbolContextEverything));
|
||||
|
||||
strm.Printf(" Address: %s + 0x%llx\n Summary: ",
|
||||
addr.GetSection().GetName(), addr.GetOffset());
|
||||
addr.GetDescription(strm);
|
||||
strm.Printf("\n");
|
||||
if (verbose)
|
||||
sc.GetDescription(strm);
|
||||
} else {
|
||||
printf(
|
||||
"error: 0x%llx does not resolve to a valid file address in '%s'\n",
|
||||
file_addr, exe_file_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
arg = *(++command);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
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)
|
||||
{
|
||||
lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
|
||||
lldb::SBCommand foo = interpreter.AddMultiwordCommand("foo",NULL);
|
||||
foo.AddCommand("child",new ChildCommand(),"a child of foo");
|
||||
return true;
|
||||
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");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -34,7 +34,7 @@ import optparse
|
|||
import os
|
||||
import platform
|
||||
import plistlib
|
||||
import pprint # pp = pprint.PrettyPrinter(indent=4); pp.pprint(command_args)
|
||||
import pprint # pp = pprint.PrettyPrinter(indent=4); pp.pprint(command_args)
|
||||
import re
|
||||
import shlex
|
||||
import string
|
||||
|
@ -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(),
|
||||
instructions,
|
||||
frame.pc,
|
||||
options.disassemble_before,
|
||||
options.disassemble_after, frame.index > 0)
|
||||
symbolication.disassemble_instructions(
|
||||
crash_log.get_target(),
|
||||
instructions,
|
||||
frame.pc,
|
||||
options.disassemble_before,
|
||||
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,22 +301,21 @@ 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()
|
||||
self.backtraces = list() # For application specific backtraces
|
||||
self.idents = list() # A list of the required identifiers for doing all stack backtraces
|
||||
self.backtraces = list() # For application specific backtraces
|
||||
self.idents = list() # A list of the required identifiers for doing all stack backtraces
|
||||
self.crashed_thread_idx = -1
|
||||
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_match.group(3).strip(),
|
||||
image_match.group(4).strip(),
|
||||
uuid.UUID(image_match.group(5)),
|
||||
image_match.group(6))
|
||||
self.images.append (image)
|
||||
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)
|
||||
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_match.group(3).strip(),
|
||||
image_match.group(4).strip(),
|
||||
None,
|
||||
image_match.group(5))
|
||||
self.images.append (image)
|
||||
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)
|
||||
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,25 +500,26 @@ 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
|
||||
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
|
||||
return self.target # success
|
||||
print 'crashlog.create_target()...4'
|
||||
print 'error: unable to locate any executables from the crash log'
|
||||
return self.target
|
||||
|
@ -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'
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -1,64 +1,67 @@
|
|||
# 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):
|
||||
data = ""
|
||||
error = lldb.SBError()
|
||||
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 ":"
|
||||
else:
|
||||
try:
|
||||
data = data + "0x%x" % byte
|
||||
if byte == 0:
|
||||
data = data + "(\\0)"
|
||||
elif byte == 0xa:
|
||||
data = data + "(\\a)"
|
||||
elif byte == 0xb:
|
||||
data = data + "(\\b)"
|
||||
elif byte == 0xc:
|
||||
data = data + "(\\c)"
|
||||
elif byte == '\n':
|
||||
data = data + "(\\n)"
|
||||
else:
|
||||
data = data + "(%s)" % chr(byte)
|
||||
if x < size-2:
|
||||
data = data + ":"
|
||||
except Exception as e:
|
||||
print e
|
||||
return data
|
||||
|
||||
def diagnose_nsstring_Command_Impl(debugger,command,result,internal_dict):
|
||||
"""
|
||||
A command to diagnose the LLDB NSString data formatter
|
||||
invoke as
|
||||
(lldb) diagnose-nsstring <expr returning NSString>
|
||||
e.g.
|
||||
(lldb) diagnose-nsstring @"Hello world"
|
||||
"""
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
thread = process.GetSelectedThread()
|
||||
frame = thread.GetSelectedFrame()
|
||||
if not target.IsValid() or not process.IsValid():
|
||||
return "unable to get target/process - cannot proceed"
|
||||
options = lldb.SBExpressionOptions()
|
||||
options.SetFetchDynamicValue()
|
||||
error = lldb.SBError()
|
||||
if frame.IsValid():
|
||||
nsstring = frame.EvaluateExpression(command,options)
|
||||
else:
|
||||
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"
|
||||
expression = "\
|
||||
def read_memory(process, location, size):
|
||||
data = ""
|
||||
error = lldb.SBError()
|
||||
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 ":"
|
||||
else:
|
||||
try:
|
||||
data = data + "0x%x" % byte
|
||||
if byte == 0:
|
||||
data = data + "(\\0)"
|
||||
elif byte == 0xa:
|
||||
data = data + "(\\a)"
|
||||
elif byte == 0xb:
|
||||
data = data + "(\\b)"
|
||||
elif byte == 0xc:
|
||||
data = data + "(\\c)"
|
||||
elif byte == '\n':
|
||||
data = data + "(\\n)"
|
||||
else:
|
||||
data = data + "(%s)" % chr(byte)
|
||||
if x < size - 2:
|
||||
data = data + ":"
|
||||
except Exception as e:
|
||||
print e
|
||||
return data
|
||||
|
||||
|
||||
def diagnose_nsstring_Command_Impl(debugger, command, result, internal_dict):
|
||||
"""
|
||||
A command to diagnose the LLDB NSString data formatter
|
||||
invoke as
|
||||
(lldb) diagnose-nsstring <expr returning NSString>
|
||||
e.g.
|
||||
(lldb) diagnose-nsstring @"Hello world"
|
||||
"""
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
thread = process.GetSelectedThread()
|
||||
frame = thread.GetSelectedFrame()
|
||||
if not target.IsValid() or not process.IsValid():
|
||||
return "unable to get target/process - cannot proceed"
|
||||
options = lldb.SBExpressionOptions()
|
||||
options.SetFetchDynamicValue()
|
||||
error = lldb.SBError()
|
||||
if frame.IsValid():
|
||||
nsstring = frame.EvaluateExpression(command, options)
|
||||
else:
|
||||
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"
|
||||
expression = "\
|
||||
struct $__lldb__notInlineMutable {\
|
||||
char* buffer;\
|
||||
signed long length;\
|
||||
|
@ -97,75 +100,84 @@ struct $__lldb__CFString {\
|
|||
};\
|
||||
"
|
||||
|
||||
expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address
|
||||
# print expression
|
||||
dumped = target.EvaluateExpression(expression,options)
|
||||
print >>result, str(dumped)
|
||||
expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address
|
||||
# print expression
|
||||
dumped = target.EvaluateExpression(expression, options)
|
||||
print >>result, str(dumped)
|
||||
|
||||
little_endian = (target.byte_order == lldb.eByteOrderLittle)
|
||||
ptr_size = target.addr_size
|
||||
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)
|
||||
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")
|
||||
has_null = (info_bits & 8) == 8
|
||||
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")
|
||||
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
|
||||
if is_mutable and not is_inline:
|
||||
explicit_length_offset = explicit_length_offset + ptr_size
|
||||
elif is_inline:
|
||||
pass
|
||||
elif not is_inline and not is_mutable:
|
||||
explicit_length_offset = explicit_length_offset + ptr_size
|
||||
else:
|
||||
explicit_length_offset = 0
|
||||
|
||||
explicit_length_offset = 0
|
||||
if not has_null and has_explicit_length and not is_special:
|
||||
explicit_length_offset = 2*ptr_size
|
||||
if is_mutable and not is_inline:
|
||||
explicit_length_offset = explicit_length_offset + ptr_size
|
||||
elif is_inline:
|
||||
pass
|
||||
elif not is_inline and not is_mutable:
|
||||
explicit_length_offset = explicit_length_offset + ptr_size
|
||||
else:
|
||||
explicit_length_offset = 0
|
||||
if explicit_length_offset == 0:
|
||||
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)
|
||||
|
||||
if explicit_length_offset == 0:
|
||||
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)
|
||||
if is_mutable:
|
||||
location = 2 * ptr_size + nsstring_address
|
||||
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"
|
||||
else:
|
||||
location += ptr_size
|
||||
else:
|
||||
location = process.ReadPointerFromMemory(location, error)
|
||||
elif is_special:
|
||||
location = nsstring_address + ptr_size + 4
|
||||
elif is_inline:
|
||||
location = 2 * ptr_size + nsstring_address
|
||||
if not has_explicit_length:
|
||||
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)
|
||||
|
||||
if is_mutable:
|
||||
location = 2 * ptr_size + nsstring_address
|
||||
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"
|
||||
else:
|
||||
location += ptr_size
|
||||
else:
|
||||
location = process.ReadPointerFromMemory(location,error)
|
||||
elif is_special:
|
||||
location = nsstring_address + ptr_size + 4
|
||||
elif is_inline:
|
||||
location = 2 * ptr_size + nsstring_address
|
||||
if not has_explicit_length:
|
||||
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)
|
||||
|
||||
def __lldb_init_module(debugger, internal_dict):
|
||||
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.'
|
||||
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
|
|
@ -13,258 +13,301 @@ 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):
|
||||
process = target.GetProcess()
|
||||
addr_for_printing = addr
|
||||
addr_width = process.GetAddressByteSize() * 2
|
||||
if frame_num > 0:
|
||||
addr = addr - 1
|
||||
|
||||
sbaddr = lldb.SBAddress()
|
||||
try:
|
||||
sbaddr.SetLoadAddress(addr, target)
|
||||
module_description = ""
|
||||
if sbaddr.GetModule():
|
||||
module_filename = ""
|
||||
module_uuid_str = sbaddr.GetModule().GetUUIDString()
|
||||
if module_uuid_str == None:
|
||||
module_uuid_str = ""
|
||||
if sbaddr.GetModule().GetFileSpec():
|
||||
module_filename = sbaddr.GetModule().GetFileSpec().GetFilename()
|
||||
if module_filename == None:
|
||||
module_filename = ""
|
||||
if module_uuid_str != "" or module_filename != "":
|
||||
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)
|
||||
if sym_ctx.IsValid() and sym_ctx.GetSymbol().IsValid():
|
||||
function_start = sym_ctx.GetSymbol().GetStartAddress().GetLoadAddress(target)
|
||||
offset = addr - function_start
|
||||
print '%2d: pc==0x%-*x fp==0x%-*x %s %s + %d' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description, sym_ctx.GetSymbol().GetName(), offset)
|
||||
else:
|
||||
print '%2d: pc==0x%-*x fp==0x%-*x %s' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description)
|
||||
return sbaddr.GetModule()
|
||||
def backtrace_print_frame(target, frame_num, addr, fp):
|
||||
process = target.GetProcess()
|
||||
addr_for_printing = addr
|
||||
addr_width = process.GetAddressByteSize() * 2
|
||||
if frame_num > 0:
|
||||
addr = addr - 1
|
||||
|
||||
sbaddr = lldb.SBAddress()
|
||||
try:
|
||||
sbaddr.SetLoadAddress(addr, target)
|
||||
module_description = ""
|
||||
if sbaddr.GetModule():
|
||||
module_filename = ""
|
||||
module_uuid_str = sbaddr.GetModule().GetUUIDString()
|
||||
if module_uuid_str is None:
|
||||
module_uuid_str = ""
|
||||
if sbaddr.GetModule().GetFileSpec():
|
||||
module_filename = sbaddr.GetModule().GetFileSpec().GetFilename()
|
||||
if module_filename is None:
|
||||
module_filename = ""
|
||||
if module_uuid_str != "" or module_filename != "":
|
||||
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)
|
||||
if sym_ctx.IsValid() and sym_ctx.GetSymbol().IsValid():
|
||||
function_start = sym_ctx.GetSymbol().GetStartAddress().GetLoadAddress(target)
|
||||
offset = addr - function_start
|
||||
print '%2d: pc==0x%-*x fp==0x%-*x %s %s + %d' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description, sym_ctx.GetSymbol().GetName(), offset)
|
||||
else:
|
||||
print '%2d: pc==0x%-*x fp==0x%-*x %s' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description)
|
||||
return sbaddr.GetModule()
|
||||
|
||||
# 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()
|
||||
cur_thread = process.GetSelectedThread()
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
cur_thread = process.GetSelectedThread()
|
||||
|
||||
initial_fp = cur_thread.GetFrameAtIndex(0).GetFP()
|
||||
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 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)
|
||||
# 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)
|
||||
|
||||
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)
|
||||
print ""
|
||||
if this_module != None:
|
||||
module_list.append (this_module)
|
||||
if cur_thread.GetNumFrames() < 2:
|
||||
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)
|
||||
print ""
|
||||
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())
|
||||
|
||||
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)
|
||||
print ""
|
||||
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":
|
||||
error = lldb.SBError()
|
||||
next_pc = process.ReadPointerFromMemory(
|
||||
cur_fp + process.GetAddressByteSize(), error)
|
||||
if not error.Success():
|
||||
next_pc = 0
|
||||
next_fp = process.ReadPointerFromMemory(cur_fp, error)
|
||||
if not error.Success():
|
||||
next_fp = 0
|
||||
# Clear the 0th bit for arm frames - this indicates it is a thumb frame
|
||||
if target.triple[0:3] == "arm" and (next_pc & 1) == 1:
|
||||
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)
|
||||
print ""
|
||||
if this_module is not None:
|
||||
module_list.append(this_module)
|
||||
return [module_list, address_list]
|
||||
|
||||
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)
|
||||
print ""
|
||||
if this_module != 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":
|
||||
error = lldb.SBError()
|
||||
next_pc = process.ReadPointerFromMemory(cur_fp + process.GetAddressByteSize(), error)
|
||||
if not error.Success():
|
||||
next_pc = 0
|
||||
next_fp = process.ReadPointerFromMemory(cur_fp, error)
|
||||
if not error.Success():
|
||||
next_fp = 0
|
||||
# Clear the 0th bit for arm frames - this indicates it is a thumb frame
|
||||
if target.triple[0:3] == "arm" and (next_pc & 1) == 1:
|
||||
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)
|
||||
print ""
|
||||
if this_module != 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
|
||||
addr_size = process.GetAddressByteSize()
|
||||
addr = fp - (2 * addr_size)
|
||||
i = 0
|
||||
outline = "Stack frame from $fp-%d: " % (2 * addr_size)
|
||||
error = lldb.SBError()
|
||||
try:
|
||||
while i < 5 and error.Success():
|
||||
address = process.ReadPointerFromMemory(addr + (i * addr_size), error)
|
||||
outline += " 0x%x" % address
|
||||
i += 1
|
||||
print outline
|
||||
except Exception:
|
||||
return
|
||||
if fp == 0 or fp == lldb.LLDB_INVALID_ADDRESS or fp == 1:
|
||||
return
|
||||
addr_size = process.GetAddressByteSize()
|
||||
addr = fp - (2 * addr_size)
|
||||
i = 0
|
||||
outline = "Stack frame from $fp-%d: " % (2 * addr_size)
|
||||
error = lldb.SBError()
|
||||
try:
|
||||
while i < 5 and error.Success():
|
||||
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)
|
||||
parser = create_diagnose_unwind_options()
|
||||
try:
|
||||
(options, args) = parser.parse_args(command_args)
|
||||
except:
|
||||
return
|
||||
target = debugger.GetSelectedTarget()
|
||||
if target:
|
||||
process = target.GetProcess()
|
||||
if process:
|
||||
thread = process.GetSelectedThread()
|
||||
if thread:
|
||||
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]:
|
||||
lldb_major = int(lldb_versions_match.groups()[0])
|
||||
if len(lldb_versions_match.groups()) >= 5 and lldb_versions_match.groups()[4]:
|
||||
lldb_minor = int(lldb_versions_match.groups()[4])
|
||||
command_args = shlex.split(command)
|
||||
parser = create_diagnose_unwind_options()
|
||||
try:
|
||||
(options, args) = parser.parse_args(command_args)
|
||||
except:
|
||||
return
|
||||
target = debugger.GetSelectedTarget()
|
||||
if target:
|
||||
process = target.GetProcess()
|
||||
if process:
|
||||
thread = process.GetSelectedThread()
|
||||
if thread:
|
||||
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]:
|
||||
lldb_major = int(lldb_versions_match.groups()[0])
|
||||
if len(lldb_versions_match.groups()
|
||||
) >= 5 and lldb_versions_match.groups()[4]:
|
||||
lldb_minor = int(lldb_versions_match.groups()[4])
|
||||
|
||||
modules_seen = []
|
||||
addresses_seen = []
|
||||
modules_seen = []
|
||||
addresses_seen = []
|
||||
|
||||
print 'LLDB version %s' % debugger.GetVersionString()
|
||||
print 'Unwind diagnostics for thread %d' % thread.GetIndexID()
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "OS plugin setting:"
|
||||
debugger.HandleCommand("settings show target.process.python-os-plugin-path")
|
||||
print ""
|
||||
print "Live register context:"
|
||||
thread.SetSelectedFrame(0)
|
||||
debugger.HandleCommand("register read")
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "lldb's unwind algorithm:"
|
||||
print ""
|
||||
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())
|
||||
print ""
|
||||
if this_module != None:
|
||||
modules_seen.append (this_module)
|
||||
addresses_seen.append (frame.GetPC())
|
||||
frame_num = frame_num + 1
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "Simple stack walk algorithm:"
|
||||
print ""
|
||||
(module_list, address_list) = simple_backtrace(debugger)
|
||||
if module_list and module_list != None:
|
||||
modules_seen += module_list
|
||||
if address_list and address_list != None:
|
||||
addresses_seen = set(addresses_seen)
|
||||
addresses_seen.update(set(address_list))
|
||||
print 'LLDB version %s' % debugger.GetVersionString()
|
||||
print 'Unwind diagnostics for thread %d' % thread.GetIndexID()
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "OS plugin setting:"
|
||||
debugger.HandleCommand(
|
||||
"settings show target.process.python-os-plugin-path")
|
||||
print ""
|
||||
print "Live register context:"
|
||||
thread.SetSelectedFrame(0)
|
||||
debugger.HandleCommand("register read")
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "lldb's unwind algorithm:"
|
||||
print ""
|
||||
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())
|
||||
print ""
|
||||
if this_module is not None:
|
||||
modules_seen.append(this_module)
|
||||
addresses_seen.append(frame.GetPC())
|
||||
frame_num = frame_num + 1
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "Simple stack walk algorithm:"
|
||||
print ""
|
||||
(module_list, address_list) = simple_backtrace(debugger)
|
||||
if module_list and module_list is not None:
|
||||
modules_seen += module_list
|
||||
if address_list and address_list is not None:
|
||||
addresses_seen = set(addresses_seen)
|
||||
addresses_seen.update(set(address_list))
|
||||
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "Modules seen in stack walks:"
|
||||
print ""
|
||||
modules_already_seen = set()
|
||||
for module in modules_seen:
|
||||
if module != None and module.GetFileSpec().GetFilename() != 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())
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "Modules seen in stack walks:"
|
||||
print ""
|
||||
modules_already_seen = set()
|
||||
for module in modules_seen:
|
||||
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())
|
||||
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "Disassembly ofaddresses seen in stack walks:"
|
||||
print ""
|
||||
additional_addresses_to_disassemble = addresses_seen
|
||||
for frame in thread.frames:
|
||||
if not frame.IsInlined():
|
||||
print "--------------------------------------------------------------------------------------"
|
||||
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())
|
||||
else:
|
||||
debugger.HandleCommand('disassemble -a 0x%x' % frame.GetPC())
|
||||
if frame.GetPC() in additional_addresses_to_disassemble:
|
||||
additional_addresses_to_disassemble.remove (frame.GetPC())
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "Disassembly ofaddresses seen in stack walks:"
|
||||
print ""
|
||||
additional_addresses_to_disassemble = addresses_seen
|
||||
for frame in thread.frames:
|
||||
if not frame.IsInlined():
|
||||
print "--------------------------------------------------------------------------------------"
|
||||
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())
|
||||
else:
|
||||
debugger.HandleCommand(
|
||||
'disassemble -a 0x%x' %
|
||||
frame.GetPC())
|
||||
if frame.GetPC() in additional_addresses_to_disassemble:
|
||||
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)
|
||||
else:
|
||||
debugger.HandleCommand('disassemble -a 0x%x' % address)
|
||||
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)
|
||||
else:
|
||||
debugger.HandleCommand('disassemble -a 0x%x' % address)
|
||||
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
additional_addresses_to_show_unwind = addresses_seen
|
||||
for frame in thread.frames:
|
||||
if not frame.IsInlined():
|
||||
print "--------------------------------------------------------------------------------------"
|
||||
print ""
|
||||
print "Unwind instructions for %s, frame %d" % (frame.GetFunctionName(), frame.GetFrameID())
|
||||
print ""
|
||||
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())
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
additional_addresses_to_show_unwind = addresses_seen
|
||||
for frame in thread.frames:
|
||||
if not frame.IsInlined():
|
||||
print "--------------------------------------------------------------------------------------"
|
||||
print ""
|
||||
print "Unwind instructions for %s, frame %d" % (frame.GetFunctionName(), frame.GetFrameID())
|
||||
print ""
|
||||
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())
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
return parser
|
||||
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)
|
||||
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.'
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
@ -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:])
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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'
|
|
@ -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,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : self.frame.GetVariables(True, True, True, True).GetSize() > 0,
|
||||
'tree-item-delegate' : self }
|
||||
return {
|
||||
'#0': name,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children': self.frame.GetVariables(
|
||||
True,
|
||||
True,
|
||||
True,
|
||||
True).GetSize() > 0,
|
||||
'tree-item-delegate': self}
|
||||
|
||||
def get_child_item_dictionaries(self):
|
||||
item_dicts = list()
|
||||
|
@ -64,29 +74,33 @@ class FrameTreeItemDelegate(object):
|
|||
item_dicts.append(item_delegate.get_item_dictionary())
|
||||
return item_dicts
|
||||
|
||||
class ThreadTreeItemDelegate(object):
|
||||
def __init__(self, thread):
|
||||
self.thread = thread
|
||||
|
||||
def get_item_dictionary(self):
|
||||
num_frames = self.thread.GetNumFrames()
|
||||
name = 'thread #%u' % (self.thread.GetIndexID())
|
||||
value = '0x%x' % (self.thread.GetThreadID())
|
||||
summary = '%u frames' % (num_frames)
|
||||
return { '#0' : name,
|
||||
class ThreadTreeItemDelegate(object):
|
||||
|
||||
def __init__(self, thread):
|
||||
self.thread = thread
|
||||
|
||||
def get_item_dictionary(self):
|
||||
num_frames = self.thread.GetNumFrames()
|
||||
name = 'thread #%u' % (self.thread.GetIndexID())
|
||||
value = '0x%x' % (self.thread.GetThreadID())
|
||||
summary = '%u frames' % (num_frames)
|
||||
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()
|
||||
for frame in self.thread:
|
||||
item_delegate = FrameTreeItemDelegate(frame)
|
||||
item_dicts.append(item_delegate.get_item_dictionary())
|
||||
return item_dicts
|
||||
|
||||
def get_child_item_dictionaries(self):
|
||||
item_dicts = list()
|
||||
for frame in self.thread:
|
||||
item_delegate = FrameTreeItemDelegate(frame)
|
||||
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',
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : num_threads > 0,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': 'process',
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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',
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : True,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': 'target',
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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',
|
||||
'value': '',
|
||||
'summary': '%u images' % num_modules,
|
||||
'children' : num_modules > 0,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': 'images',
|
||||
'value': '',
|
||||
'summary': '%u images' % num_modules,
|
||||
'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,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : True,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': name,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : True,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': name,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : self.section.GetNumSubSections() > 0,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': name,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : self.module.GetNumCompileUnits() > 0,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': name,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : num_lines > 0,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': name,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : num_lines > 0,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': name,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : False,
|
||||
'tree-item-delegate' : self }
|
||||
summary = self.line_entry.GetFileSpec().fullpath + ':' + \
|
||||
str(self.line_entry.line)
|
||||
return {'#0': name,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : False,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': name,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : True,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': name,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'children' : False,
|
||||
'tree-item-delegate' : self }
|
||||
return {'#0': name,
|
||||
'value': value,
|
||||
'summary': summary,
|
||||
'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,10 +504,10 @@ 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
|
||||
END,
|
||||
text=name,
|
||||
values=values)
|
||||
item_id = self.tree.insert(parent_id, # root item has an empty name
|
||||
END,
|
||||
text=name,
|
||||
values=values)
|
||||
self.item_id_to_item_dict[item_id] = item_dict
|
||||
if item_dict['children']:
|
||||
self.tree.insert(item_id, END, text='dummy')
|
||||
|
@ -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
|
@ -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'
|
||||
|
|
|
@ -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,9 +15,9 @@ 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
|
||||
self.threads = None # Will be an dictionary containing info for each thread
|
||||
|
||||
def get_target(self):
|
||||
# NOTE: Don't use "lldb.target" when trying to get your target as the "lldb.target"
|
||||
|
@ -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
|
||||
|
||||
|
|
|
@ -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,32 +171,33 @@ 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):
|
||||
continue
|
||||
if state == lldb.eStateInvalid or state == lldb.eStateDetached or state == lldb.eStateCrashed or state == lldb.eStateUnloaded or state == lldb.eStateExited:
|
||||
if state == lldb.eStateInvalid or state == lldb.eStateDetached or state == lldb.eStateCrashed or state == lldb.eStateUnloaded or state == lldb.eStateExited:
|
||||
event = process_event
|
||||
self.done = True
|
||||
elif state == lldb.eStateConnected or state == lldb.eStateAttaching or state == lldb.eStateLaunching or state == lldb.eStateRunning or state == lldb.eStateStepping or state == lldb.eStateSuspended:
|
||||
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
@ -262,7 +401,7 @@ def main(argv):
|
|||
while process_stderr:
|
||||
process_stderr = process.GetSTDERR(1024)
|
||||
print process_stderr
|
||||
process.Kill() # kill the process
|
||||
process.Kill() # kill the process
|
||||
else:
|
||||
if error:
|
||||
print error
|
||||
|
|
|
@ -2,310 +2,342 @@ import sys
|
|||
import inspect
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
class TracebackFancy:
|
||||
def __init__(self,traceback):
|
||||
self.t = traceback
|
||||
|
||||
def getFrame(self):
|
||||
return FrameFancy(self.t.tb_frame)
|
||||
def __init__(self, traceback):
|
||||
self.t = traceback
|
||||
|
||||
def getLineNumber(self):
|
||||
return self.t.tb_lineno if self.t != None else None
|
||||
def getFrame(self):
|
||||
return FrameFancy(self.t.tb_frame)
|
||||
|
||||
def getNext(self):
|
||||
return TracebackFancy(self.t.tb_next)
|
||||
def getLineNumber(self):
|
||||
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 is None:
|
||||
return ""
|
||||
str_self = "%s @ %s" % (
|
||||
self.getFrame().getName(), self.getLineNumber())
|
||||
return str_self + "\n" + self.getNext().__str__()
|
||||
|
||||
def __str__(self):
|
||||
if self.t == None:
|
||||
return ""
|
||||
str_self = "%s @ %s" % (self.getFrame().getName(), self.getLineNumber())
|
||||
return str_self + "\n" + self.getNext().__str__()
|
||||
|
||||
class ExceptionFancy:
|
||||
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):
|
||||
self.etraceback = tb
|
||||
self.etype = ty
|
||||
self.evalue = va
|
||||
def __init__(self, frame):
|
||||
self.etraceback = frame.f_exc_traceback
|
||||
self.etype = frame.exc_type
|
||||
self.evalue = frame.f_exc_value
|
||||
|
||||
def getTraceback(self):
|
||||
return TracebackFancy(self.etraceback)
|
||||
def __init__(self, tb, ty, va):
|
||||
self.etraceback = tb
|
||||
self.etype = ty
|
||||
self.evalue = va
|
||||
|
||||
def __nonzero__(self):
|
||||
return self.etraceback != None or self.etype != None or self.evalue != None
|
||||
def getTraceback(self):
|
||||
return TracebackFancy(self.etraceback)
|
||||
|
||||
def getType(self):
|
||||
return str(self.etype)
|
||||
def __nonzero__(self):
|
||||
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)
|
||||
|
||||
def getValue(self):
|
||||
return self.evalue
|
||||
|
||||
def getValue(self):
|
||||
return self.evalue
|
||||
|
||||
class CodeFancy:
|
||||
def __init__(self,code):
|
||||
self.c = code
|
||||
|
||||
def getArgCount(self):
|
||||
return self.c.co_argcount if self.c != None else 0
|
||||
def __init__(self, code):
|
||||
self.c = code
|
||||
|
||||
def getFilename(self):
|
||||
return self.c.co_filename if self.c != None else ""
|
||||
def getArgCount(self):
|
||||
return self.c.co_argcount if self.c is not None else 0
|
||||
|
||||
def getVariables(self):
|
||||
return self.c.co_varnames if self.c != None else []
|
||||
def getFilename(self):
|
||||
return self.c.co_filename if self.c is not None else ""
|
||||
|
||||
def getName(self):
|
||||
return self.c.co_name if self.c != None else ""
|
||||
def getVariables(self):
|
||||
return self.c.co_varnames if self.c is not None else []
|
||||
|
||||
def getName(self):
|
||||
return self.c.co_name if self.c is not None else ""
|
||||
|
||||
def getFileName(self):
|
||||
return self.c.co_filename if self.c is not None else ""
|
||||
|
||||
def getFileName(self):
|
||||
return self.c.co_filename if self.c != None else ""
|
||||
|
||||
class ArgsFancy:
|
||||
def __init__(self,frame,arginfo):
|
||||
self.f = frame
|
||||
self.a = arginfo
|
||||
|
||||
def __str__(self):
|
||||
args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs()
|
||||
ret = ""
|
||||
count = 0
|
||||
size = len(args)
|
||||
for arg in args:
|
||||
ret = ret + ("%s = %s" % (arg, args[arg]))
|
||||
count = count + 1
|
||||
if count < size:
|
||||
ret = ret + ", "
|
||||
if varargs:
|
||||
if size > 0:
|
||||
ret = ret + " "
|
||||
ret = ret + "varargs are " + str(varargs)
|
||||
if kwargs:
|
||||
if size > 0:
|
||||
ret = ret + " "
|
||||
ret = ret + "kwargs are " + str(kwargs)
|
||||
return ret
|
||||
def __init__(self, frame, arginfo):
|
||||
self.f = frame
|
||||
self.a = arginfo
|
||||
|
||||
def getNumArgs(wantVarargs = False, wantKWArgs=False):
|
||||
args, varargs, keywords, values = self.a
|
||||
size = len(args)
|
||||
if varargs and wantVarargs:
|
||||
size = size+len(self.getVarArgs())
|
||||
if keywords and wantKWArgs:
|
||||
size = size+len(self.getKWArgs())
|
||||
return size
|
||||
def __str__(self):
|
||||
args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs()
|
||||
ret = ""
|
||||
count = 0
|
||||
size = len(args)
|
||||
for arg in args:
|
||||
ret = ret + ("%s = %s" % (arg, args[arg]))
|
||||
count = count + 1
|
||||
if count < size:
|
||||
ret = ret + ", "
|
||||
if varargs:
|
||||
if size > 0:
|
||||
ret = ret + " "
|
||||
ret = ret + "varargs are " + str(varargs)
|
||||
if kwargs:
|
||||
if size > 0:
|
||||
ret = ret + " "
|
||||
ret = ret + "kwargs are " + str(kwargs)
|
||||
return ret
|
||||
|
||||
def getArgs(self):
|
||||
args, _, _, values = self.a
|
||||
argWValues = OrderedDict()
|
||||
for arg in args:
|
||||
argWValues[arg] = values[arg]
|
||||
return argWValues
|
||||
def getNumArgs(wantVarargs=False, wantKWArgs=False):
|
||||
args, varargs, keywords, values = self.a
|
||||
size = len(args)
|
||||
if varargs and wantVarargs:
|
||||
size = size + len(self.getVarArgs())
|
||||
if keywords and wantKWArgs:
|
||||
size = size + len(self.getKWArgs())
|
||||
return size
|
||||
|
||||
def getVarArgs(self):
|
||||
_, vargs, _, _ = self.a
|
||||
if vargs:
|
||||
return self.f.f_locals[vargs]
|
||||
return ()
|
||||
def getArgs(self):
|
||||
args, _, _, values = self.a
|
||||
argWValues = OrderedDict()
|
||||
for arg in args:
|
||||
argWValues[arg] = values[arg]
|
||||
return argWValues
|
||||
|
||||
def getVarArgs(self):
|
||||
_, vargs, _, _ = self.a
|
||||
if vargs:
|
||||
return self.f.f_locals[vargs]
|
||||
return ()
|
||||
|
||||
def getKWArgs(self):
|
||||
_, _, kwargs, _ = self.a
|
||||
if kwargs:
|
||||
return self.f.f_locals[kwargs]
|
||||
return {}
|
||||
|
||||
def getKWArgs(self):
|
||||
_, _, kwargs, _ = self.a
|
||||
if kwargs:
|
||||
return self.f.f_locals[kwargs]
|
||||
return {}
|
||||
|
||||
class FrameFancy:
|
||||
def __init__(self,frame):
|
||||
self.f = frame
|
||||
|
||||
def getCaller(self):
|
||||
return FrameFancy(self.f.f_back)
|
||||
def __init__(self, frame):
|
||||
self.f = frame
|
||||
|
||||
def getLineNumber(self):
|
||||
return self.f.f_lineno if self.f != None else 0
|
||||
def getCaller(self):
|
||||
return FrameFancy(self.f.f_back)
|
||||
|
||||
def getCodeInformation(self):
|
||||
return CodeFancy(self.f.f_code) if self.f != None else None
|
||||
def getLineNumber(self):
|
||||
return self.f.f_lineno if self.f is not None else 0
|
||||
|
||||
def getExceptionInfo(self):
|
||||
return ExceptionFancy(self.f) if self.f != None else None
|
||||
def getCodeInformation(self):
|
||||
return CodeFancy(self.f.f_code) if self.f is not None else None
|
||||
|
||||
def getName(self):
|
||||
return self.getCodeInformation().getName() if self.f != None else ""
|
||||
def getExceptionInfo(self):
|
||||
return ExceptionFancy(self.f) if self.f is not None else None
|
||||
|
||||
def getFileName(self):
|
||||
return self.getCodeInformation().getFileName() if self.f != None else ""
|
||||
def getName(self):
|
||||
return self.getCodeInformation().getName() if self.f is not None else ""
|
||||
|
||||
def getLocals(self):
|
||||
return self.f.f_locals if self.f != None else {}
|
||||
def getFileName(self):
|
||||
return self.getCodeInformation().getFileName() if self.f is not None else ""
|
||||
|
||||
def getLocals(self):
|
||||
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 is not None else None
|
||||
|
||||
def getArgumentInfo(self):
|
||||
return ArgsFancy(self.f,inspect.getargvalues(self.f)) if self.f != None else None
|
||||
|
||||
class TracerClass:
|
||||
def callEvent(self,frame):
|
||||
pass
|
||||
|
||||
def lineEvent(self,frame):
|
||||
pass
|
||||
def callEvent(self, frame):
|
||||
pass
|
||||
|
||||
def returnEvent(self,frame,retval):
|
||||
pass
|
||||
def lineEvent(self, frame):
|
||||
pass
|
||||
|
||||
def exceptionEvent(self,frame,exception,value,traceback):
|
||||
pass
|
||||
def returnEvent(self, frame, retval):
|
||||
pass
|
||||
|
||||
def cCallEvent(self,frame,cfunct):
|
||||
pass
|
||||
def exceptionEvent(self, frame, exception, value, traceback):
|
||||
pass
|
||||
|
||||
def cReturnEvent(self,frame,cfunct):
|
||||
pass
|
||||
def cCallEvent(self, frame, cfunct):
|
||||
pass
|
||||
|
||||
def cExceptionEvent(self,frame,cfunct):
|
||||
pass
|
||||
def cReturnEvent(self, frame, cfunct):
|
||||
pass
|
||||
|
||||
def cExceptionEvent(self, frame, cfunct):
|
||||
pass
|
||||
|
||||
tracer_impl = TracerClass()
|
||||
|
||||
|
||||
def the_tracer_entrypoint(frame,event,args):
|
||||
if tracer_impl == None:
|
||||
return None
|
||||
if event == "call":
|
||||
call_retval = tracer_impl.callEvent(FrameFancy(frame))
|
||||
if call_retval == False:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "line":
|
||||
line_retval = tracer_impl.lineEvent(FrameFancy(frame))
|
||||
if line_retval == False:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "return":
|
||||
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:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "c_call":
|
||||
tracer_impl.cCallEvent(FrameFancy(frame),args)
|
||||
elif event == "c_return":
|
||||
tracer_impl.cReturnEvent(FrameFancy(frame),args)
|
||||
elif event == "c_exception":
|
||||
tracer_impl.cExceptionEvent(FrameFancy(frame),args)
|
||||
return 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 not call_retval:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "line":
|
||||
line_retval = tracer_impl.lineEvent(FrameFancy(frame))
|
||||
if not line_retval:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "return":
|
||||
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 not exception_retval:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "c_call":
|
||||
tracer_impl.cCallEvent(FrameFancy(frame), args)
|
||||
elif event == "c_return":
|
||||
tracer_impl.cReturnEvent(FrameFancy(frame), args)
|
||||
elif event == "c_exception":
|
||||
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)
|
||||
global tracer_impl
|
||||
if t:
|
||||
tracer_impl = t
|
||||
sys.settrace(the_tracer_entrypoint)
|
||||
|
||||
|
||||
def disable():
|
||||
sys.settrace(None)
|
||||
sys.settrace(None)
|
||||
|
||||
|
||||
class LoggingTracer:
|
||||
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):
|
||||
print "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals()) + " in " + frame.getFileName()
|
||||
def callEvent(self, frame):
|
||||
print "call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
|
||||
|
||||
def returnEvent(self,frame,retval):
|
||||
print "return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals())
|
||||
def lineEvent(self, frame):
|
||||
print "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals()) + " in " + frame.getFileName()
|
||||
|
||||
def returnEvent(self, frame, retval):
|
||||
print "return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals())
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
class LLDBAwareTracer:
|
||||
def callEvent(self,frame):
|
||||
if frame.getName() == "<module>":
|
||||
return
|
||||
if frame.getName() == "run_one_line":
|
||||
print "call run_one_line(%s)" % (frame.getArgumentInfo().getArgs()["input_string"])
|
||||
return
|
||||
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:
|
||||
return False
|
||||
strout = "call " + frame.getName()
|
||||
if (frame.getCaller().getFileName() == ""):
|
||||
strout += " from LLDB - args are "
|
||||
args = frame.getArgumentInfo().getArgs()
|
||||
for arg in args:
|
||||
if arg == "dict" or arg == "internal_dict":
|
||||
continue
|
||||
strout = strout + ("%s = %s " % (arg,args[arg]))
|
||||
else:
|
||||
strout += " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
|
||||
print strout
|
||||
|
||||
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())
|
||||
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 "
|
||||
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]))
|
||||
else:
|
||||
strout = strout + str(frame.getLocals())
|
||||
strout = strout + " in " + frame.getFileName()
|
||||
print strout
|
||||
def callEvent(self, frame):
|
||||
if frame.getName() == "<module>":
|
||||
return
|
||||
if frame.getName() == "run_one_line":
|
||||
print "call run_one_line(%s)" % (frame.getArgumentInfo().getArgs()["input_string"])
|
||||
return
|
||||
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:
|
||||
return False
|
||||
strout = "call " + frame.getName()
|
||||
if (frame.getCaller().getFileName() == ""):
|
||||
strout += " from LLDB - args are "
|
||||
args = frame.getArgumentInfo().getArgs()
|
||||
for arg in args:
|
||||
if arg == "dict" or arg == "internal_dict":
|
||||
continue
|
||||
strout = strout + ("%s = %s " % (arg, args[arg]))
|
||||
else:
|
||||
strout += " from " + frame.getCaller().getName() + " @ " + \
|
||||
str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
|
||||
print strout
|
||||
|
||||
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)
|
||||
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 "
|
||||
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]))
|
||||
else:
|
||||
strout = strout + str(frame.getLocals())
|
||||
strout = strout + " in " + frame.getFileName()
|
||||
print strout
|
||||
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())
|
||||
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 "
|
||||
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]))
|
||||
else:
|
||||
strout = strout + str(frame.getLocals())
|
||||
strout = strout + " in " + frame.getFileName()
|
||||
print strout
|
||||
|
||||
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 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)
|
||||
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 "
|
||||
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]))
|
||||
else:
|
||||
strout = strout + str(frame.getLocals())
|
||||
strout = strout + " in " + frame.getFileName()
|
||||
print strout
|
||||
|
||||
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):
|
||||
if x > 0:
|
||||
return 2 + f(x - 2)
|
||||
return 35
|
||||
|
||||
def f(x,y=None):
|
||||
if x > 0:
|
||||
return 2 + f(x-2)
|
||||
return 35
|
||||
|
||||
def g(x):
|
||||
return 1.134 / 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)
|
||||
# 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
|
||||
|
@ -316,13 +348,13 @@ def total(initial=5, *numbers, **keywords):
|
|||
return count
|
||||
|
||||
if __name__ == "__main__":
|
||||
enable(LoggingTracer())
|
||||
f(5)
|
||||
f(5,1)
|
||||
print_keyword_args(first_name="John", last_name="Doe")
|
||||
total(10, 1, 2, 3, vegetables=50, fruits=100)
|
||||
try:
|
||||
g(0)
|
||||
except:
|
||||
pass
|
||||
disable()
|
||||
enable(LoggingTracer())
|
||||
f(5)
|
||||
f(5, 1)
|
||||
print_keyword_args(first_name="John", last_name="Doe")
|
||||
total(10, 1, 2, 3, vegetables=50, fruits=100)
|
||||
try:
|
||||
g(0)
|
||||
except:
|
||||
pass
|
||||
disable()
|
||||
|
|
|
@ -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))
|
||||
result = self.__floordiv__(self, other)
|
||||
self.sbvalue.SetValueFromCString(str(result))
|
||||
return result
|
||||
|
||||
def __imod__(self, other):
|
||||
result = self.__and__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
result = self.__and__(self, other)
|
||||
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))
|
||||
result = self.__rshift__(self, other)
|
||||
self.sbvalue.SetValueFromCString(str(result))
|
||||
return result
|
||||
|
||||
def __iand__(self, other):
|
||||
result = self.__and__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
result = self.__and__(self, other)
|
||||
self.sbvalue.SetValueFromCString(str(result))
|
||||
return result
|
||||
|
||||
def __ixor__(self, other):
|
||||
result = self.__xor__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
result = self.__xor__(self, other)
|
||||
self.sbvalue.SetValueFromCString(str(result))
|
||||
return result
|
||||
|
||||
def __ior__(self, other):
|
||||
result = self.__ior__(self, other)
|
||||
self.sbvalue.SetValueFromCString (str(result))
|
||||
result = self.__ior__(self, other)
|
||||
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()
|
||||
|
|
@ -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):
|
||||
if self.step_out_thread_plan.IsPlanComplete():
|
||||
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():
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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."
|
|
@ -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
|
||||
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
|
||||
self.symbolication = None # The cached symbolicated string that describes this address
|
||||
self.load_addr = load_addr # The load address that this object represents
|
||||
# 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
|
||||
# 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,11 +323,11 @@ 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:
|
||||
return None # We already warned that we couldn't find this module, so don't return an error string
|
||||
return None # We already warned that we couldn't find this module, so don't return an error string
|
||||
# Load this module into "target" using the section infos to
|
||||
# set the section load addresses
|
||||
if self.has_section_load_info():
|
||||
|
@ -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,26 +369,29 @@ 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:
|
||||
return None # No sections, the module was added to the target, so success
|
||||
return None # No sections, the module was added to the target, so success
|
||||
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,19 +436,20 @@ class Image:
|
|||
print 'error: unable to locate main executable (%s) "%s"' % (self.arch, self.path)
|
||||
return None
|
||||
|
||||
|
||||
class Symbolicator:
|
||||
|
||||
def __init__(self):
|
||||
"""A class the represents the information needed to symbolicate addresses in a program"""
|
||||
self.target = None
|
||||
self.images = list() # a list of images to be used when symbolicating
|
||||
self.images = list() # a list of images to be used when symbolicating
|
||||
self.addr_mask = 0xffffffffffffffff
|
||||
|
||||
@classmethod
|
||||
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:])
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
@ -246,20 +335,22 @@ if __name__ == '__main__':
|
|||
os.kill(os.getpid(), signal.SIGSTOP)
|
||||
|
||||
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
|
||||
# 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
|
||||
error = lldb.SBError()
|
||||
target = debugger.CreateTarget (path,
|
||||
options.arch,
|
||||
options.platform,
|
||||
True,
|
||||
error)
|
||||
target = debugger.CreateTarget(path,
|
||||
options.arch,
|
||||
options.platform,
|
||||
True,
|
||||
error)
|
||||
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'
|
|
@ -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,
|
||||
'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
|
||||
};
|
||||
'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
|
||||
}
|
||||
|
||||
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()
|
|
@ -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,
|
||||
'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
|
||||
};
|
||||
'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
|
||||
}
|
||||
|
||||
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()
|
||||
|
|
|
@ -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,
|
||||
'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
|
||||
};
|
||||
'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
|
||||
}
|
||||
|
||||
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()
|
|
@ -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,116 +45,95 @@ 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 (root->left != NULL)
|
||||
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;
|
||||
}
|
||||
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);
|
||||
new_node->left = NULL;
|
||||
new_node->right = NULL;
|
||||
root->left = new_node;
|
||||
}
|
||||
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);
|
||||
new_node->left = NULL;
|
||||
new_node->right = NULL;
|
||||
root->right = new_node;
|
||||
}
|
||||
} 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);
|
||||
new_node->left = NULL;
|
||||
new_node->right = NULL;
|
||||
root->right = new_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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));
|
||||
new_node->word = new_word;
|
||||
new_node->left = NULL;
|
||||
new_node->right = NULL;
|
||||
*dictionary = new_node;
|
||||
}
|
||||
else
|
||||
insert (*dictionary, new_word);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
char *word = buffer;
|
||||
int len = strlen (word);
|
||||
int i;
|
||||
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 i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
word[i] = tolower (word[i]);
|
||||
for (i = 0; i < len; ++i)
|
||||
word[i] = tolower(word[i]);
|
||||
|
||||
if ((len > 0) && (word[len-1] == '\n'))
|
||||
{
|
||||
word[len-1] = '\0';
|
||||
len = len - 1;
|
||||
}
|
||||
|
||||
if (find_word (dictionary, word))
|
||||
fprintf (stdout, "Yes!\n");
|
||||
else
|
||||
fprintf (stdout, "No!\n");
|
||||
|
||||
fprintf (stdout, "Enter search word: ");
|
||||
if ((len > 0) && (word[len - 1] == '\n')) {
|
||||
word[len - 1] = '\0';
|
||||
len = len - 1;
|
||||
}
|
||||
|
||||
fprintf (stdout, "\n");
|
||||
if (find_word(dictionary, word))
|
||||
fprintf(stdout, "Yes!\n");
|
||||
else
|
||||
fprintf(stdout, "No!\n");
|
||||
|
||||
fprintf(stdout, "Enter search word: ");
|
||||
}
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -22,183 +22,212 @@ 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):
|
||||
pass
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, dict, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.update()
|
||||
def __init__(self, valobj, dict, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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]");
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return "<variable is not NSArray>"
|
||||
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]")
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return "<variable is not NSArray>"
|
||||
|
||||
# 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):
|
||||
pass
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, dict, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.update()
|
||||
def __init__(self, valobj, dict, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.update()
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
|
||||
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)
|
||||
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.sys_params = params
|
||||
if not(self.sys_params.types_cache.long):
|
||||
self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
|
||||
self.update()
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, dict, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.update()
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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",
|
||||
self.sys_params.pointer_size,
|
||||
self.sys_params.types_cache.long)
|
||||
return count.GetValueAsUnsigned(0)
|
||||
|
||||
# skip the isa pointer and get at the size
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
count = self.valobj.CreateChildAtOffset("count",
|
||||
self.sys_params.pointer_size,
|
||||
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.sys_params = params
|
||||
if not(self.sys_params.types_cache.long):
|
||||
self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
|
||||
self.update()
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, dict, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.update()
|
||||
|
||||
# skip the isa pointer and get at the size
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
count = self.valobj.CreateChildAtOffset("count",
|
||||
self.sys_params.pointer_size,
|
||||
self.sys_params.types_cache.long);
|
||||
return count.GetValueAsUnsigned(0)
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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",
|
||||
self.sys_params.pointer_size,
|
||||
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.adjust_for_architecture()
|
||||
self.error = False
|
||||
self.wrapper = self.make_wrapper()
|
||||
self.invalid = (self.wrapper == None)
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.wrapper == None:
|
||||
return 0;
|
||||
return self.wrapper.num_children()
|
||||
def __init__(self, valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.adjust_for_architecture()
|
||||
self.error = False
|
||||
self.wrapper = self.make_wrapper()
|
||||
self.invalid = (self.wrapper is None)
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.wrapper == None:
|
||||
return
|
||||
self.wrapper.update()
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.wrapper is None:
|
||||
return 0
|
||||
return self.wrapper.num_children()
|
||||
|
||||
# this code acts as our defense against NULL and uninitialized
|
||||
# NSArray pointers, which makes it much longer than it would be otherwise
|
||||
def make_wrapper(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.valobj.GetValueAsUnsigned() == 0:
|
||||
self.error = 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)
|
||||
if wrapper:
|
||||
self.error = True
|
||||
return wrapper
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.wrapper is None:
|
||||
return
|
||||
self.wrapper.update()
|
||||
|
||||
name_string = class_data.class_name()
|
||||
# this code acts as our defense against NULL and uninitialized
|
||||
# NSArray pointers, which makes it much longer than it would be otherwise
|
||||
def make_wrapper(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.valobj.GetValueAsUnsigned() == 0:
|
||||
self.error = 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)
|
||||
if wrapper:
|
||||
self.error = True
|
||||
return wrapper
|
||||
|
||||
logger >> "Class name is " + str(name_string)
|
||||
name_string = class_data.class_name()
|
||||
|
||||
if name_string == '__NSArrayI':
|
||||
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())
|
||||
elif name_string == '__NSCFArray':
|
||||
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;
|
||||
logger >> "Class name is " + str(name_string)
|
||||
|
||||
def CFArray_SummaryProvider (valobj,dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = NSArray_SynthProvider(valobj,dict);
|
||||
if provider.invalid == False:
|
||||
if provider.error == True:
|
||||
return provider.wrapper.message()
|
||||
try:
|
||||
summary = int(provider.num_children());
|
||||
except:
|
||||
summary = None
|
||||
logger >> "provider gave me " + str(summary)
|
||||
if summary == None:
|
||||
summary = '<variable is not NSArray>'
|
||||
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") + '"'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
if name_string == '__NSArrayI':
|
||||
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())
|
||||
elif name_string == '__NSCFArray':
|
||||
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
|
||||
|
||||
def __lldb_init_module(debugger,dict):
|
||||
debugger.HandleCommand("type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")
|
||||
|
||||
def CFArray_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = NSArray_SynthProvider(valobj, dict)
|
||||
if not provider.invalid:
|
||||
if provider.error:
|
||||
return provider.wrapper.message()
|
||||
try:
|
||||
summary = int(provider.num_children())
|
||||
except:
|
||||
summary = None
|
||||
logger >> "provider gave me " + str(summary)
|
||||
if summary is None:
|
||||
summary = '<variable is not NSArray>'
|
||||
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") + '"'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
|
||||
|
||||
def __lldb_init_module(debugger, dict):
|
||||
debugger.HandleCommand(
|
||||
"type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")
|
||||
|
|
|
@ -22,125 +22,142 @@ 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.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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update()
|
||||
|
||||
# 12 bytes on i386
|
||||
# 20 bytes on x64
|
||||
# most probably 2 pointers and 4 bytes of data
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.sys_params.is_64_bit:
|
||||
return 20
|
||||
else:
|
||||
return 12
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def length(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
size = self.valobj.CreateChildAtOffset("count",
|
||||
self.offset(),
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
return size.GetValueAsUnsigned(0)
|
||||
# 12 bytes on i386
|
||||
# 20 bytes on x64
|
||||
# most probably 2 pointers and 4 bytes of data
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.sys_params.is_64_bit:
|
||||
return 20
|
||||
else:
|
||||
return 12
|
||||
|
||||
def length(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.sys_params = params
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
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() + " )")
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return "<variable is not CFBag>"
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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() + " )")
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return "<variable is not CFBag>"
|
||||
|
||||
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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
|
||||
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
|
||||
# an NSCFType and then check we are a pointer-to __CFBag
|
||||
valobj_type = valobj.GetType()
|
||||
if valobj_type.IsValid() and valobj_type.IsPointerType():
|
||||
valobj_type = valobj_type.GetPointeeType()
|
||||
if valobj_type.IsValid():
|
||||
actual_name = valobj_type.GetName()
|
||||
if actual_name == '__CFBag' or \
|
||||
actual_name == 'const struct __CFBag':
|
||||
wrapper = CFBagRef_SummaryProvider(valobj, class_data.sys_params)
|
||||
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;
|
||||
if class_data.is_cftype():
|
||||
# CFBag does not expose an actual NSWrapper type, so we have to check that this is
|
||||
# an NSCFType and then check we are a pointer-to __CFBag
|
||||
valobj_type = valobj.GetType()
|
||||
if valobj_type.IsValid() and valobj_type.IsPointerType():
|
||||
valobj_type = valobj_type.GetPointeeType()
|
||||
if valobj_type.IsValid():
|
||||
actual_name = valobj_type.GetName()
|
||||
if actual_name == '__CFBag' or \
|
||||
actual_name == 'const struct __CFBag':
|
||||
wrapper = CFBagRef_SummaryProvider(valobj, class_data.sys_params)
|
||||
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
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.length();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "summary got from provider: " + str(summary)
|
||||
# for some reason, one needs to clear some bits for the count
|
||||
# to be correct when using CF(Mutable)BagRef on x64
|
||||
# the bit mask was derived through experimentation
|
||||
# (if counts start looking weird, then most probably
|
||||
# the mask needs to be changed)
|
||||
if summary == None:
|
||||
summary = '<variable is not CFBag>'
|
||||
elif isinstance(summary,basestring):
|
||||
pass
|
||||
else:
|
||||
if provider.sys_params.is_64_bit:
|
||||
summary = summary & ~0x1fff000000000000
|
||||
if summary == 1:
|
||||
summary = '@"1 value"'
|
||||
else:
|
||||
summary = '@"' + str(summary) + ' values"'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
|
||||
def __lldb_init_module(debugger,dict):
|
||||
debugger.HandleCommand("type summary add -F CFBag.CFBag_SummaryProvider CFBagRef CFMutableBagRef")
|
||||
def CFBag_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "summary got from provider: " + str(summary)
|
||||
# for some reason, one needs to clear some bits for the count
|
||||
# to be correct when using CF(Mutable)BagRef on x64
|
||||
# the bit mask was derived through experimentation
|
||||
# (if counts start looking weird, then most probably
|
||||
# the mask needs to be changed)
|
||||
if summary is None:
|
||||
summary = '<variable is not CFBag>'
|
||||
elif isinstance(summary, basestring):
|
||||
pass
|
||||
else:
|
||||
if provider.sys_params.is_64_bit:
|
||||
summary = summary & ~0x1fff000000000000
|
||||
if summary == 1:
|
||||
summary = '@"1 value"'
|
||||
else:
|
||||
summary = '@"' + str(summary) + ' values"'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
|
||||
|
||||
def __lldb_init_module(debugger, dict):
|
||||
debugger.HandleCommand(
|
||||
"type summary add -F CFBag.CFBag_SummaryProvider CFBagRef CFMutableBagRef")
|
||||
|
|
|
@ -22,121 +22,140 @@ 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.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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update()
|
||||
|
||||
# 8 bytes on i386
|
||||
# 16 bytes on x64
|
||||
# most probably 2 pointers
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return 2 * self.sys_params.pointer_size
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def length(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
size = self.valobj.CreateChildAtOffset("count",
|
||||
self.offset(),
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
return size.GetValueAsUnsigned(0)
|
||||
# 8 bytes on i386
|
||||
# 16 bytes on x64
|
||||
# most probably 2 pointers
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return 2 * self.sys_params.pointer_size
|
||||
|
||||
def length(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.sys_params = params
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
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() + " )");
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return '<variable is not CFBinaryHeap>'
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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() + " )")
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return '<variable is not CFBinaryHeap>'
|
||||
|
||||
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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()
|
||||
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
|
||||
# an NSCFType and then check we are a pointer-to CFBinaryHeap
|
||||
valobj_type = valobj.GetType()
|
||||
if valobj_type.IsValid() and valobj_type.IsPointerType():
|
||||
valobj_type = valobj_type.GetPointeeType()
|
||||
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)
|
||||
return wrapper
|
||||
wrapper = CFBinaryHeapUnknown_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
|
||||
return wrapper;
|
||||
if class_data.is_cftype():
|
||||
# CFBinaryHeap does not expose an actual NSWrapper type, so we have to check that this is
|
||||
# an NSCFType and then check we are a pointer-to CFBinaryHeap
|
||||
valobj_type = valobj.GetType()
|
||||
if valobj_type.IsValid() and valobj_type.IsPointerType():
|
||||
valobj_type = valobj_type.GetPointeeType()
|
||||
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)
|
||||
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):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = GetSummary_Impl(valobj);
|
||||
if provider != None:
|
||||
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.length();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "summary got from provider: " + str(summary)
|
||||
# for some reason, one needs to clear some bits for the count
|
||||
# to be correct when using CF(Mutable)BagRef on x64
|
||||
# the bit mask was derived through experimentation
|
||||
# (if counts start looking weird, then most probably
|
||||
# the mask needs to be changed)
|
||||
if summary == None:
|
||||
summary = '<variable is not CFBinaryHeap>'
|
||||
elif isinstance(summary,basestring):
|
||||
pass
|
||||
else:
|
||||
if provider.sys_params.is_64_bit:
|
||||
summary = summary & ~0x1fff000000000000
|
||||
if summary == 1:
|
||||
return '@"1 item"'
|
||||
else:
|
||||
summary = '@"' + str(summary) + ' items"'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
|
||||
def __lldb_init_module(debugger,dict):
|
||||
debugger.HandleCommand("type summary add -F CFBinaryHeap.CFBinaryHeap_SummaryProvider CFBinaryHeapRef")
|
||||
def CFBinaryHeap_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "summary got from provider: " + str(summary)
|
||||
# for some reason, one needs to clear some bits for the count
|
||||
# to be correct when using CF(Mutable)BagRef on x64
|
||||
# the bit mask was derived through experimentation
|
||||
# (if counts start looking weird, then most probably
|
||||
# the mask needs to be changed)
|
||||
if summary is None:
|
||||
summary = '<variable is not CFBinaryHeap>'
|
||||
elif isinstance(summary, basestring):
|
||||
pass
|
||||
else:
|
||||
if provider.sys_params.is_64_bit:
|
||||
summary = summary & ~0x1fff000000000000
|
||||
if summary == 1:
|
||||
return '@"1 item"'
|
||||
else:
|
||||
summary = '@"' + str(summary) + ' items"'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
|
||||
|
||||
def __lldb_init_module(debugger, dict):
|
||||
debugger.HandleCommand(
|
||||
"type summary add -F CFBinaryHeap.CFBinaryHeap_SummaryProvider CFBinaryHeapRef")
|
||||
|
|
|
@ -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
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return abs_pos / 8
|
||||
|
||||
|
||||
def bit_index(abs_pos):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return abs_pos & 7
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return abs_pos & 7
|
||||
|
||||
def get_bit(byte,index):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if index < 0 or index > 7:
|
||||
return None
|
||||
return (byte >> (7-index)) & 1
|
||||
|
||||
def grab_array_item_data(pointer,index):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return pointer.GetPointeeData(index,1)
|
||||
def get_bit(byte, index):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if index < 0 or index > 7:
|
||||
return None
|
||||
return (byte >> (7 - index)) & 1
|
||||
|
||||
|
||||
def grab_array_item_data(pointer, index):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return pointer.GetPointeeData(index, 1)
|
||||
|
||||
statistics = lldb.formatters.metrics.Metrics()
|
||||
statistics.add_metric('invalid_isa')
|
||||
|
@ -40,136 +45,162 @@ 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()
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
else:
|
||||
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();
|
||||
def adjust_for_architecture(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.uiint_size = self.sys_params.types_cache.NSUInteger.GetByteSize()
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
else:
|
||||
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()
|
||||
|
||||
# we skip the CFRuntimeBase
|
||||
# then the next CFIndex is the count
|
||||
# then we skip another CFIndex and then we get at a byte array
|
||||
# that wraps the individual bits
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def contents(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)'
|
||||
# we skip the CFRuntimeBase
|
||||
# then the next CFIndex is the count
|
||||
# then we skip another CFIndex and then we get at a byte array
|
||||
# that wraps the individual bits
|
||||
|
||||
array_vo = self.valobj.CreateChildAtOffset("data",
|
||||
self.sys_params.cfruntime_size+2*self.uiint_size,
|
||||
self.sys_params.types_cache.charptr)
|
||||
def contents(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)'
|
||||
|
||||
data_list = []
|
||||
cur_byte_pos = None
|
||||
for i in range(0,count):
|
||||
if cur_byte_pos == None:
|
||||
cur_byte_pos = byte_index(i)
|
||||
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_val = cur_byte.uint8[0]
|
||||
bit = get_bit(cur_byte_val,bit_index(i))
|
||||
if (i % 4) == 0:
|
||||
data_list.append(' ')
|
||||
if bit == 1:
|
||||
data_list.append('1')
|
||||
else:
|
||||
data_list.append('0')
|
||||
return ''.join(data_list)
|
||||
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 is None:
|
||||
cur_byte_pos = byte_index(i)
|
||||
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_val = cur_byte.uint8[0]
|
||||
bit = get_bit(cur_byte_val, bit_index(i))
|
||||
if (i % 4) == 0:
|
||||
data_list.append(' ')
|
||||
if bit == 1:
|
||||
data_list.append('1')
|
||||
else:
|
||||
data_list.append('0')
|
||||
return ''.join(data_list)
|
||||
|
||||
|
||||
class CFBitVectorUnknown_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
def contents(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return '<unable to summarize this CFBitVector>'
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def contents(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return '<unable to summarize this CFBitVector>'
|
||||
|
||||
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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
|
||||
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
|
||||
# an NSCFType and then check we are a pointer-to CFBitVectorRef
|
||||
valobj_type = valobj.GetType()
|
||||
if valobj_type.IsValid() and valobj_type.IsPointerType():
|
||||
valobj_type = valobj_type.GetPointeeType()
|
||||
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)
|
||||
else:
|
||||
wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)
|
||||
print actual_name
|
||||
else:
|
||||
wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)
|
||||
print name_string
|
||||
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
|
||||
return wrapper;
|
||||
if class_data.is_cftype():
|
||||
# CFBitVectorRef does not expose an actual NSWrapper type, so we have to check that this is
|
||||
# an NSCFType and then check we are a pointer-to CFBitVectorRef
|
||||
valobj_type = valobj.GetType()
|
||||
if valobj_type.IsValid() and valobj_type.IsPointerType():
|
||||
valobj_type = valobj_type.GetPointeeType()
|
||||
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)
|
||||
else:
|
||||
wrapper = CFBitVectorUnknown_SummaryProvider(
|
||||
valobj, class_data.sys_params)
|
||||
print actual_name
|
||||
else:
|
||||
wrapper = CFBitVectorUnknown_SummaryProvider(
|
||||
valobj, class_data.sys_params)
|
||||
print name_string
|
||||
statistics.metric_hit(
|
||||
'unknown_class',
|
||||
valobj.GetName() +
|
||||
" seen as " +
|
||||
name_string)
|
||||
return wrapper
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.contents();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "summary got from provider: " + str(summary)
|
||||
if summary == 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 CFBitVector_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "summary got from provider: " + str(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")
|
||||
|
|
|
@ -22,213 +22,242 @@ 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.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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update()
|
||||
|
||||
# empirically determined on both 32 and 64bit desktop Mac OS X
|
||||
# probably boils down to 2 pointers and 4 bytes of data, but
|
||||
# the description of __CFDictionary is not readily available so most
|
||||
# of this is guesswork, plain and simple
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.sys_params.is_64_bit:
|
||||
return 20
|
||||
else:
|
||||
return 12
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
num_children_vo = self.valobj.CreateChildAtOffset("count",
|
||||
self.offset(),
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
# empirically determined on both 32 and 64bit desktop Mac OS X
|
||||
# probably boils down to 2 pointers and 4 bytes of data, but
|
||||
# the description of __CFDictionary is not readily available so most
|
||||
# of this is guesswork, plain and simple
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.sys_params.is_64_bit:
|
||||
return 20
|
||||
else:
|
||||
return 12
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update()
|
||||
|
||||
# we just need to skip the ISA and the count immediately follows
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.sys_params.pointer_size
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
# we just need to skip the ISA and the count immediately follows
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.sys_params.pointer_size
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
num_children_vo = self.valobj.CreateChildAtOffset(
|
||||
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
|
||||
value = num_children_vo.GetValueAsUnsigned(0)
|
||||
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
|
||||
if self.sys_params.is_64_bit:
|
||||
value = value & ~0xFC00000000000000
|
||||
else:
|
||||
value = value & ~0xFC000000
|
||||
return value
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
num_children_vo = self.valobj.CreateChildAtOffset("count",
|
||||
self.offset(),
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
value = num_children_vo.GetValueAsUnsigned(0)
|
||||
if value != 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
|
||||
if self.sys_params.is_64_bit:
|
||||
value = value & ~0xFC00000000000000
|
||||
else:
|
||||
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.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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update()
|
||||
|
||||
# we just need to skip the ISA and the count immediately follows
|
||||
def offset(self):
|
||||
return self.sys_params.pointer_size
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
# we just need to skip the ISA and the count immediately follows
|
||||
def offset(self):
|
||||
return self.sys_params.pointer_size
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
num_children_vo = self.valobj.CreateChildAtOffset(
|
||||
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
|
||||
value = num_children_vo.GetValueAsUnsigned(0)
|
||||
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
|
||||
if self.sys_params.is_64_bit:
|
||||
value = value & ~0xFC00000000000000
|
||||
else:
|
||||
value = value & ~0xFC000000
|
||||
return value
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
num_children_vo = self.valobj.CreateChildAtOffset("count",
|
||||
self.offset(),
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
value = num_children_vo.GetValueAsUnsigned(0)
|
||||
if value != 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
|
||||
if self.sys_params.is_64_bit:
|
||||
value = value & ~0xFC00000000000000
|
||||
else:
|
||||
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.sys_params = params
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
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]");
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return '<variable is not NSDictionary>'
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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]")
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return '<variable is not NSDictionary>'
|
||||
|
||||
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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()
|
||||
name_string = class_data.class_name()
|
||||
|
||||
logger >> "class name is: " + str(name_string)
|
||||
logger >> "class name is: " + str(name_string)
|
||||
|
||||
if name_string == '__NSCFDictionary':
|
||||
wrapper = NSCFDictionary_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun',valobj)
|
||||
elif name_string == '__NSDictionaryI':
|
||||
wrapper = NSDictionaryI_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun',valobj)
|
||||
elif name_string == '__NSDictionaryM':
|
||||
wrapper = NSDictionaryM_SummaryProvider(valobj, class_data.sys_params)
|
||||
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;
|
||||
if name_string == '__NSCFDictionary':
|
||||
wrapper = NSCFDictionary_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun', valobj)
|
||||
elif name_string == '__NSDictionaryI':
|
||||
wrapper = NSDictionaryI_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun', valobj)
|
||||
elif name_string == '__NSDictionaryM':
|
||||
wrapper = NSDictionaryM_SummaryProvider(valobj, class_data.sys_params)
|
||||
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
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.num_children();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary == None:
|
||||
return '<variable is not NSDictionary>'
|
||||
if isinstance(summary,basestring):
|
||||
return summary
|
||||
return str(summary) + (" key/value pairs" if summary != 1 else " key/value pair")
|
||||
return 'Summary Unavailable'
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.num_children();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary == None:
|
||||
summary = '<variable is not CFDictionary>'
|
||||
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"')
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
def CFDictionary_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary is None:
|
||||
return '<variable is not NSDictionary>'
|
||||
if isinstance(summary, basestring):
|
||||
return summary
|
||||
return str(summary) + (" key/value pairs" if summary !=
|
||||
1 else " key/value pair")
|
||||
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 CFDictionary_SummaryProvider2(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary is None:
|
||||
summary = '<variable is not CFDictionary>'
|
||||
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"')
|
||||
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")
|
||||
|
|
|
@ -11,315 +11,341 @@ import lldb
|
|||
import lldb.runtime.objc.objc_runtime
|
||||
import lldb.formatters.Logger
|
||||
|
||||
def CFString_SummaryProvider (valobj,dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = CFStringSynthProvider(valobj,dict);
|
||||
if provider.invalid == False:
|
||||
try:
|
||||
summary = provider.get_child_at_index(provider.get_child_index("content"))
|
||||
if type(summary) == lldb.SBValue:
|
||||
summary = summary.GetSummary()
|
||||
else:
|
||||
summary = '"' + summary + '"'
|
||||
except:
|
||||
summary = None
|
||||
if summary == None:
|
||||
summary = '<variable is not NSString>'
|
||||
return '@'+summary
|
||||
return ''
|
||||
|
||||
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:
|
||||
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:
|
||||
try:
|
||||
summary = provider.get_child_at_index(provider.get_child_index("content")).GetSummary();
|
||||
except:
|
||||
summary = '<variable is not NSAttributedString>'
|
||||
if summary == None:
|
||||
summary = '<variable is not NSAttributedString>'
|
||||
return '@'+summary
|
||||
def CFString_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = CFStringSynthProvider(valobj, dict)
|
||||
if not provider.invalid:
|
||||
try:
|
||||
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 is None:
|
||||
summary = '<variable is not NSString>'
|
||||
return '@' + summary
|
||||
return ''
|
||||
|
||||
|
||||
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 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 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 not provider.invalid:
|
||||
try:
|
||||
summary = provider.get_child_at_index(
|
||||
provider.get_child_index("content")).GetSummary()
|
||||
except:
|
||||
summary = '<variable is not NSAttributedString>'
|
||||
if summary is None:
|
||||
summary = '<variable is not NSAttributedString>'
|
||||
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")
|
||||
|
||||
|
||||
class CFStringSynthProvider:
|
||||
def __init__(self,valobj,dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.update()
|
||||
|
||||
# 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;
|
||||
def __init__(self, valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.update()
|
||||
|
||||
def read_unicode(self, pointer,max_len=2048):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
process = self.valobj.GetTarget().GetProcess()
|
||||
error = lldb.SBError()
|
||||
pystr = u''
|
||||
# cannot do the read at once because the length value has
|
||||
# a weird encoding. better play it safe here
|
||||
while max_len > 0:
|
||||
content = process.ReadMemory(pointer, 2, error)
|
||||
new_bytes = bytearray(content)
|
||||
b0 = new_bytes[0]
|
||||
b1 = new_bytes[1]
|
||||
pointer = pointer + 2
|
||||
if b0 == 0 and b1 == 0:
|
||||
break
|
||||
# rearrange bytes depending on endianness
|
||||
# (do we really need this or is Cocoa going to
|
||||
# use Windows-compatible little-endian even
|
||||
# if the target is big endian?)
|
||||
if self.is_little:
|
||||
value = b1 * 256 + b0
|
||||
else:
|
||||
value = b0 * 256 + b1
|
||||
pystr = pystr + unichr(value)
|
||||
# read max_len unicode values, not max_len bytes
|
||||
max_len = max_len - 1
|
||||
return pystr
|
||||
# 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
|
||||
|
||||
# handle the special case strings
|
||||
# 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:
|
||||
# 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') + "\"")
|
||||
def read_unicode(self, pointer, max_len=2048):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
process = self.valobj.GetTarget().GetProcess()
|
||||
error = lldb.SBError()
|
||||
pystr = u''
|
||||
# cannot do the read at once because the length value has
|
||||
# a weird encoding. better play it safe here
|
||||
while max_len > 0:
|
||||
content = process.ReadMemory(pointer, 2, error)
|
||||
new_bytes = bytearray(content)
|
||||
b0 = new_bytes[0]
|
||||
b1 = new_bytes[1]
|
||||
pointer = pointer + 2
|
||||
if b0 == 0 and b1 == 0:
|
||||
break
|
||||
# rearrange bytes depending on endianness
|
||||
# (do we really need this or is Cocoa going to
|
||||
# use Windows-compatible little-endian even
|
||||
# if the target is big endian?)
|
||||
if self.is_little:
|
||||
value = b1 * 256 + b0
|
||||
else:
|
||||
value = b0 * 256 + b1
|
||||
pystr = pystr + unichr(value)
|
||||
# read max_len unicode values, not max_len bytes
|
||||
max_len = max_len - 1
|
||||
return pystr
|
||||
|
||||
# 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() + "\"");
|
||||
# handle the special case strings
|
||||
# only use the custom code for the tested LP64 case
|
||||
def handle_special(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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') + "\"")
|
||||
|
||||
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:
|
||||
# untested, use the safe code path
|
||||
return self.handle_unicode_string_safe();
|
||||
else:
|
||||
# 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()
|
||||
# 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);
|
||||
pointer = vopointer.GetValueAsUnsigned(0)
|
||||
except:
|
||||
return self.valobj.CreateValueFromExpression("content",
|
||||
'(char*)"@\"invalid NSString\""')
|
||||
# step 2: read Unicode data at pointer
|
||||
pystr = self.read_unicode(pointer)
|
||||
# step 3: return it
|
||||
return 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() + "\"")
|
||||
|
||||
def handle_inline_explicit(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
offset = 3*self.pointer_size
|
||||
offset = offset + self.valobj.GetValueAsUnsigned(0)
|
||||
return self.valobj.CreateValueFromExpression("content",
|
||||
"(char*)(" + str(offset) + ")")
|
||||
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 not self.explicit:
|
||||
# untested, use the safe code path
|
||||
return self.handle_unicode_string_safe()
|
||||
else:
|
||||
# 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()
|
||||
# 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)
|
||||
pointer = vopointer.GetValueAsUnsigned(0)
|
||||
except:
|
||||
return self.valobj.CreateValueFromExpression(
|
||||
"content", '(char*)"@\"invalid NSString\""')
|
||||
# step 2: read Unicode data at pointer
|
||||
pystr = self.read_unicode(pointer)
|
||||
# step 3: return it
|
||||
return pystr.encode('utf-8')
|
||||
|
||||
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_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) + ")")
|
||||
def handle_inline_explicit(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
offset = 3 * self.pointer_size
|
||||
offset = offset + self.valobj.GetValueAsUnsigned(0)
|
||||
return self.valobj.CreateValueFromExpression(
|
||||
"content", "(char*)(" + str(offset) + ")")
|
||||
|
||||
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();
|
||||
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_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) + ")")
|
||||
|
||||
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());
|
||||
def handle_UTF8_inline(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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 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)));
|
||||
if index == 1:
|
||||
return self.valobj.CreateValueFromExpression("inline",
|
||||
str(int(self.inline)));
|
||||
if index == 2:
|
||||
return self.valobj.CreateValueFromExpression("explicit",
|
||||
str(int(self.explicit)));
|
||||
if index == 3:
|
||||
return self.valobj.CreateValueFromExpression("unicode",
|
||||
str(int(self.unicode)));
|
||||
if index == 4:
|
||||
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
|
||||
# go fetch the data from memory instead of running code. if a string is not
|
||||
# correctly displayed, one should start by finding a combination of flags that
|
||||
# makes it different from these known cases, and provide a new reader function
|
||||
# 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:
|
||||
return self.handle_mutable_string()
|
||||
elif self.inline == True and self.explicit == True 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();
|
||||
else:
|
||||
return self.handle_UTF8_not_inline();
|
||||
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())
|
||||
|
||||
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;
|
||||
if name == "mutable":
|
||||
return 0;
|
||||
if name == "inline":
|
||||
return 1;
|
||||
if name == "explicit":
|
||||
return 2;
|
||||
if name == "unicode":
|
||||
return 3;
|
||||
if name == "special":
|
||||
return 4;
|
||||
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)))
|
||||
if index == 1:
|
||||
return self.valobj.CreateValueFromExpression("inline",
|
||||
str(int(self.inline)))
|
||||
if index == 2:
|
||||
return self.valobj.CreateValueFromExpression(
|
||||
"explicit", str(int(self.explicit)))
|
||||
if index == 3:
|
||||
return self.valobj.CreateValueFromExpression(
|
||||
"unicode", str(int(self.unicode)))
|
||||
if index == 4:
|
||||
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
|
||||
# go fetch the data from memory instead of running code. if a string is not
|
||||
# correctly displayed, one should start by finding a combination of flags that
|
||||
# makes it different from these known cases, and provide a new reader function
|
||||
# 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:
|
||||
return self.handle_mutable_string()
|
||||
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:
|
||||
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()
|
||||
|
||||
# CFRuntimeBase is defined as having an additional
|
||||
# 4 bytes (padding?) on LP64 architectures
|
||||
# to get its size we add up sizeof(pointer)+4
|
||||
# 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)
|
||||
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
|
||||
if name == "mutable":
|
||||
return 0
|
||||
if name == "inline":
|
||||
return 1
|
||||
if name == "explicit":
|
||||
return 2
|
||||
if name == "unicode":
|
||||
return 3
|
||||
if name == "special":
|
||||
return 4
|
||||
|
||||
# the info bits are part of the CFRuntimeBase structure
|
||||
# to get at them we have to skip a uintptr_t and then get
|
||||
# at the least-significant byte of a 4 byte array. If we are
|
||||
# on big-endian this means going to byte 3, if we are on
|
||||
# little endian (OSX & iOS), this means reading byte 0
|
||||
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;
|
||||
# CFRuntimeBase is defined as having an additional
|
||||
# 4 bytes (padding?) on LP64 architectures
|
||||
# to get its size we add up sizeof(pointer)+4
|
||||
# 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)
|
||||
|
||||
def read_info_bits(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
cfinfo = self.valobj.CreateChildAtOffset("cfinfo",
|
||||
self.offset_of_info_bits(),
|
||||
self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar));
|
||||
cfinfo.SetFormat(11)
|
||||
info = cfinfo.GetValue();
|
||||
if info != None:
|
||||
self.invalid = False;
|
||||
return int(info,0);
|
||||
else:
|
||||
self.invalid = True;
|
||||
return None;
|
||||
# the info bits are part of the CFRuntimeBase structure
|
||||
# to get at them we have to skip a uintptr_t and then get
|
||||
# at the least-significant byte of a 4 byte array. If we are
|
||||
# on big-endian this means going to byte 3, if we are on
|
||||
# little endian (OSX & iOS), this means reading byte 0
|
||||
def offset_of_info_bits(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
offset = self.pointer_size
|
||||
if not self.is_little:
|
||||
offset = offset + 3
|
||||
return offset
|
||||
|
||||
# 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;
|
||||
def read_info_bits(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
cfinfo = self.valobj.CreateChildAtOffset(
|
||||
"cfinfo",
|
||||
self.offset_of_info_bits(),
|
||||
self.valobj.GetType().GetBasicType(
|
||||
lldb.eBasicTypeChar))
|
||||
cfinfo.SetFormat(11)
|
||||
info = cfinfo.GetValue()
|
||||
if info is not None:
|
||||
self.invalid = False
|
||||
return int(info, 0)
|
||||
else:
|
||||
self.invalid = True
|
||||
return None
|
||||
|
||||
def is_inline(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return (self.info_bits & 0x60) == 0;
|
||||
# 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
|
||||
|
||||
# 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;
|
||||
def is_inline(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return (self.info_bits & 0x60) == 0
|
||||
|
||||
# probably a subclass of NSString. obtained this from [str pathExtension]
|
||||
# here info_bits = 0 and Unicode data at the start of the padding word
|
||||
# in the long run using the isa value might be safer as a way to identify this
|
||||
# instead of reading the info_bits
|
||||
def is_special_case(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.info_bits == 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
|
||||
|
||||
def is_unicode(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return (self.info_bits & 0x10) == 0x10;
|
||||
# probably a subclass of NSString. obtained this from [str pathExtension]
|
||||
# here info_bits = 0 and Unicode data at the start of the padding word
|
||||
# in the long run using the isa value might be safer as a way to identify this
|
||||
# instead of reading the info_bits
|
||||
def is_special_case(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.info_bits == 0
|
||||
|
||||
# preparing ourselves to read into memory
|
||||
# by adjusting architecture-specific info
|
||||
def adjust_for_architecture(self):
|
||||
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
|
||||
def is_unicode(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return (self.info_bits & 0x10) == 0x10
|
||||
|
||||
# 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();
|
||||
# preparing ourselves to read into memory
|
||||
# by adjusting architecture-specific info
|
||||
def adjust_for_architecture(self):
|
||||
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
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
self.compute_flags();
|
||||
# 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 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()
|
||||
|
|
|
@ -9,13 +9,14 @@ import lldb
|
|||
import lldb.runtime.objc.objc_runtime
|
||||
import lldb.formatters.Logger
|
||||
|
||||
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():
|
||||
return '<error: unknown Class>'
|
||||
class_data = runtime.read_class_data()
|
||||
if class_data == None or not class_data.is_valid():
|
||||
return '<error: unknown Class>'
|
||||
return class_data.class_name()
|
||||
|
||||
def Class_Summary(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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 is None or not class_data.is_valid():
|
||||
return '<error: unknown Class>'
|
||||
return class_data.class_name()
|
||||
|
|
|
@ -3,120 +3,131 @@ import sys
|
|||
import os.path
|
||||
import inspect
|
||||
|
||||
|
||||
class NopLogger:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def write(self,data):
|
||||
pass
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
def write(self, data):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
|
||||
class StdoutLogger:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def write(self,data):
|
||||
print(data)
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
def write(self, data):
|
||||
print(data)
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
class FileLogger:
|
||||
def __init__(self, name):
|
||||
self.file = None
|
||||
try:
|
||||
name = os.path.abspath(name)
|
||||
self.file = open(name,'a')
|
||||
except:
|
||||
try:
|
||||
self.file = open('formatters.log','a')
|
||||
except:
|
||||
pass
|
||||
|
||||
def write(self,data):
|
||||
if self.file != None:
|
||||
print(data,file=self.file)
|
||||
else:
|
||||
print(data)
|
||||
def __init__(self, name):
|
||||
self.file = None
|
||||
try:
|
||||
name = os.path.abspath(name)
|
||||
self.file = open(name, 'a')
|
||||
except:
|
||||
try:
|
||||
self.file = open('formatters.log', 'a')
|
||||
except:
|
||||
pass
|
||||
|
||||
def flush(self):
|
||||
if self.file != None:
|
||||
self.file.flush()
|
||||
def write(self, data):
|
||||
if self.file is not None:
|
||||
print(data, file=self.file)
|
||||
else:
|
||||
print(data)
|
||||
|
||||
def close(self):
|
||||
if self.file != None:
|
||||
self.file.close()
|
||||
self.file = None
|
||||
def flush(self):
|
||||
if self.file is not None:
|
||||
self.file.flush()
|
||||
|
||||
def close(self):
|
||||
if self.file is not None:
|
||||
self.file.close()
|
||||
self.file = None
|
||||
|
||||
# to enable logging:
|
||||
# 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):
|
||||
global _lldb_formatters_debug_level
|
||||
global _lldb_formatters_debug_filename
|
||||
self.autoflush = autoflush
|
||||
want_log = False
|
||||
try:
|
||||
want_log = (_lldb_formatters_debug_level > 0)
|
||||
except:
|
||||
pass
|
||||
if not (want_log):
|
||||
self.impl = NopLogger()
|
||||
return
|
||||
want_file = False
|
||||
try:
|
||||
want_file = (_lldb_formatters_debug_filename != None and _lldb_formatters_debug_filename != '' and _lldb_formatters_debug_filename != 0)
|
||||
except:
|
||||
pass
|
||||
if want_file:
|
||||
self.impl = FileLogger(_lldb_formatters_debug_filename)
|
||||
else:
|
||||
self.impl = StdoutLogger()
|
||||
try:
|
||||
self.autoflush = (_lldb_formatters_debug_level > 1)
|
||||
except:
|
||||
self.autoflush = autoflush
|
||||
want_caller_info = False
|
||||
try:
|
||||
want_caller_info = (_lldb_formatters_debug_level > 2)
|
||||
except:
|
||||
pass
|
||||
if want_caller_info:
|
||||
self._log_caller()
|
||||
|
||||
def _log_caller(self):
|
||||
caller = inspect.stack()[2]
|
||||
try:
|
||||
if caller != None and len(caller) > 3:
|
||||
self.write('Logging from function ' + str(caller))
|
||||
else:
|
||||
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 __init__(self, autoflush=False, logcaller=False):
|
||||
global _lldb_formatters_debug_level
|
||||
global _lldb_formatters_debug_filename
|
||||
self.autoflush = autoflush
|
||||
want_log = False
|
||||
try:
|
||||
want_log = (_lldb_formatters_debug_level > 0)
|
||||
except:
|
||||
pass
|
||||
if not (want_log):
|
||||
self.impl = NopLogger()
|
||||
return
|
||||
want_file = False
|
||||
try:
|
||||
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:
|
||||
self.impl = FileLogger(_lldb_formatters_debug_filename)
|
||||
else:
|
||||
self.impl = StdoutLogger()
|
||||
try:
|
||||
self.autoflush = (_lldb_formatters_debug_level > 1)
|
||||
except:
|
||||
self.autoflush = autoflush
|
||||
want_caller_info = False
|
||||
try:
|
||||
want_caller_info = (_lldb_formatters_debug_level > 2)
|
||||
except:
|
||||
pass
|
||||
if want_caller_info:
|
||||
self._log_caller()
|
||||
|
||||
def write(self,data):
|
||||
self.impl.write(data)
|
||||
if self.autoflush:
|
||||
self.flush()
|
||||
def _log_caller(self):
|
||||
caller = inspect.stack()[2]
|
||||
try:
|
||||
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')
|
||||
finally:
|
||||
del caller # needed per Python docs to avoid keeping objects alive longer than we care
|
||||
|
||||
def __rshift__(self,data):
|
||||
self.write(data)
|
||||
def write(self, data):
|
||||
self.impl.write(data)
|
||||
if self.autoflush:
|
||||
self.flush()
|
||||
|
||||
def flush(self):
|
||||
self.impl.flush()
|
||||
def __rshift__(self, data):
|
||||
self.write(data)
|
||||
|
||||
def close(self):
|
||||
self.impl.close()
|
||||
def flush(self):
|
||||
self.impl.flush()
|
||||
|
||||
def close(self):
|
||||
self.impl.close()
|
||||
|
|
|
@ -23,105 +23,123 @@ 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.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();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
|
||||
# we need to skip the ISA, plus four other values
|
||||
# that are luckily each a pointer in size
|
||||
# which makes our computation trivial :-)
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return 5 * self.sys_params.pointer_size
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def url_text(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global statistics
|
||||
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()
|
||||
else:
|
||||
statistics.metric_hit('code_notrun',self.valobj)
|
||||
return my_string
|
||||
# we need to skip the ISA, plus four other values
|
||||
# that are luckily each a pointer in size
|
||||
# which makes our computation trivial :-)
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return 5 * self.sys_params.pointer_size
|
||||
|
||||
def url_text(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global statistics
|
||||
text = self.valobj.CreateChildAtOffset(
|
||||
"text", self.offset(), self.sys_params.types_cache.NSString)
|
||||
my_string = text.GetSummary()
|
||||
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)
|
||||
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.sys_params = params
|
||||
self.update()
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
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);
|
||||
if url_text_vo.IsValid():
|
||||
return url_text_vo.GetSummary()
|
||||
return '<variable is not NSBundle>'
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
if url_text_vo.IsValid():
|
||||
return url_text_vo.GetSummary()
|
||||
return '<variable is not NSBundle>'
|
||||
|
||||
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
name_string = class_data.class_name()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
|
||||
if name_string == 'NSBundle':
|
||||
wrapper = NSBundleKnown_SummaryProvider(valobj, class_data.sys_params)
|
||||
# [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)
|
||||
else:
|
||||
wrapper = NSBundleUnknown_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
|
||||
return wrapper;
|
||||
if name_string == 'NSBundle':
|
||||
wrapper = NSBundleKnown_SummaryProvider(valobj, class_data.sys_params)
|
||||
# [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)
|
||||
else:
|
||||
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):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = GetSummary_Impl(valobj);
|
||||
if provider != None:
|
||||
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.url_text();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary == 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 NSBundle_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(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")
|
||||
|
|
|
@ -22,142 +22,161 @@ 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.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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
logger >> "NSConcreteData_SummaryProvider __init__"
|
||||
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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update()
|
||||
|
||||
# one pointer is the ISA
|
||||
# then there are 32 bit worth of flags and other data
|
||||
# however, on 64bit systems these are padded to be a full
|
||||
# machine word long, which means we actually have two pointers
|
||||
# worth of data to skip
|
||||
def offset(self):
|
||||
return 2 * self.sys_params.pointer_size
|
||||
def update(self):
|
||||
self.adjust_for_architecture()
|
||||
|
||||
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)
|
||||
logger >> str(size)
|
||||
logger >> str(size.GetValueAsUnsigned(0))
|
||||
return size.GetValueAsUnsigned(0)
|
||||
# one pointer is the ISA
|
||||
# then there are 32 bit worth of flags and other data
|
||||
# however, on 64bit systems these are padded to be a full
|
||||
# machine word long, which means we actually have two pointers
|
||||
# worth of data to skip
|
||||
def offset(self):
|
||||
return 2 * self.sys_params.pointer_size
|
||||
|
||||
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)
|
||||
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.sys_params = params
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
logger >> "NSDataUnknown_SummaryProvider __init__"
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
def length(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
logger >> "NSDataUnknown_SummaryProvider length"
|
||||
stream = lldb.SBStream()
|
||||
self.valobj.GetExpressionPath(stream)
|
||||
logger >> stream.GetData()
|
||||
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())
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
logger >> "invalid expr output - too bad"
|
||||
return '<variable is not NSData>'
|
||||
def update(self):
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def length(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
logger >> "NSDataUnknown_SummaryProvider length"
|
||||
stream = lldb.SBStream()
|
||||
self.valobj.GetExpressionPath(stream)
|
||||
logger >> stream.GetData()
|
||||
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())
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
logger >> "invalid expr output - too bad"
|
||||
return '<variable is not NSData>'
|
||||
|
||||
|
||||
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)
|
||||
if wrapper:
|
||||
logger >> "got a wrapper summary - using it"
|
||||
return wrapper
|
||||
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)
|
||||
if wrapper:
|
||||
logger >> "got a wrapper summary - using it"
|
||||
return wrapper
|
||||
|
||||
name_string = class_data.class_name()
|
||||
logger >> "class name: " + name_string
|
||||
if name_string == 'NSConcreteData' or \
|
||||
name_string == 'NSConcreteMutableData' or \
|
||||
name_string == '__NSCFData':
|
||||
wrapper = NSConcreteData_SummaryProvider(valobj, class_data.sys_params)
|
||||
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;
|
||||
name_string = class_data.class_name()
|
||||
logger >> "class name: " + name_string
|
||||
if name_string == 'NSConcreteData' or \
|
||||
name_string == 'NSConcreteMutableData' or \
|
||||
name_string == '__NSCFData':
|
||||
wrapper = NSConcreteData_SummaryProvider(valobj, class_data.sys_params)
|
||||
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
|
||||
|
||||
def NSData_SummaryProvider (valobj,dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
logger >> "NSData_SummaryProvider"
|
||||
provider = GetSummary_Impl(valobj);
|
||||
logger >> "found a summary provider, it is: " + str(provider)
|
||||
if provider != None:
|
||||
try:
|
||||
summary = provider.length();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got a summary: it is " + str(summary)
|
||||
if summary == None:
|
||||
summary = '<variable is not NSData>'
|
||||
elif isinstance(summary,basestring):
|
||||
pass
|
||||
else:
|
||||
if summary == 1:
|
||||
summary = '1 byte'
|
||||
else:
|
||||
summary = str(summary) + ' bytes'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
|
||||
def NSData_SummaryProvider2 (valobj,dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
logger >> "NSData_SummaryProvider2"
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.length();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got a summary: it is " + str(summary)
|
||||
if summary == None:
|
||||
summary = '<variable is not CFData>'
|
||||
elif isinstance(summary,basestring):
|
||||
pass
|
||||
else:
|
||||
if summary == 1:
|
||||
summary = '@"1 byte"'
|
||||
else:
|
||||
summary = '@"' + str(summary) + ' bytes"'
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
def NSData_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
logger >> "NSData_SummaryProvider"
|
||||
provider = GetSummary_Impl(valobj)
|
||||
logger >> "found a summary provider, it is: " + str(provider)
|
||||
if provider is not None:
|
||||
try:
|
||||
summary = provider.length()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got a summary: it is " + str(summary)
|
||||
if summary is None:
|
||||
summary = '<variable is not NSData>'
|
||||
elif isinstance(summary, basestring):
|
||||
pass
|
||||
else:
|
||||
if summary == 1:
|
||||
summary = '1 byte'
|
||||
else:
|
||||
summary = str(summary) + ' bytes'
|
||||
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 NSData_SummaryProvider2(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
logger >> "NSData_SummaryProvider2"
|
||||
provider = GetSummary_Impl(valobj)
|
||||
logger >> "found a summary provider, it is: " + str(provider)
|
||||
if provider is not None:
|
||||
if isinstance(
|
||||
provider,
|
||||
lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.length()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got a summary: it is " + str(summary)
|
||||
if summary is None:
|
||||
summary = '<variable is not CFData>'
|
||||
elif isinstance(summary, basestring):
|
||||
pass
|
||||
else:
|
||||
if summary == 1:
|
||||
summary = '@"1 byte"'
|
||||
else:
|
||||
summary = '@"' + str(summary) + ' bytes"'
|
||||
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")
|
||||
|
|
|
@ -27,243 +27,281 @@ 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
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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:
|
||||
return osx + osx_epoch
|
||||
else:
|
||||
return osx - osx_epoch
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if python_epoch <= 2001:
|
||||
return osx + osx_epoch
|
||||
else:
|
||||
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)
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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))
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return xcode_format_time(time.localtime(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.sys_params = params
|
||||
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 adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, info_bits, data, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
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 value(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
# the value of the date-time object is wrapped into the pointer value
|
||||
# unfortunately, it is made as a time-delta after Jan 1 2001 midnight GMT
|
||||
# while all Python knows about is the "epoch", which is a platform-dependent
|
||||
# year (1970 of *nix) whose Jan 1 at midnight is taken as reference
|
||||
value_double = struct.unpack('d', struct.pack('Q', self.data))[0]
|
||||
if value_double == -63114076800.0:
|
||||
return '0001-12-30 00:00:00 +0000'
|
||||
return xcode_format_count(osx_to_python_time(value_double))
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def value(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
# the value of the date-time object is wrapped into the pointer value
|
||||
# unfortunately, it is made as a time-delta after Jan 1 2001 midnight GMT
|
||||
# while all Python knows about is the "epoch", which is a platform-dependent
|
||||
# year (1970 of *nix) whose Jan 1 at midnight is taken as reference
|
||||
value_double = struct.unpack('d', struct.pack('Q', self.data))[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 NSUntaggedDate_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.update()
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.update()
|
||||
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.sys_params.pointer_size
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return 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]
|
||||
if value_double == -63114076800.0:
|
||||
return '0001-12-30 00:00:00 +0000'
|
||||
return xcode_format_count(osx_to_python_time(value_double))
|
||||
|
||||
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]
|
||||
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.sys_params = params
|
||||
if not (self.sys_params.types_cache.double):
|
||||
self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
|
||||
self.update()
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.update()
|
||||
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return 2*self.sys_params.pointer_size
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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]
|
||||
return xcode_format_count(osx_to_python_time(value_double))
|
||||
|
||||
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]
|
||||
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.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()
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.sys_params.pointer_size
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.sys_params.pointer_size
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
class NSUnknownDate_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.update()
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetSummary()
|
||||
return '<variable is not NSDate>'
|
||||
|
||||
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);
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
name_string = class_data.class_name()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
|
||||
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)
|
||||
else:
|
||||
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)
|
||||
elif name_string == '__NSTimeZone':
|
||||
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;
|
||||
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)
|
||||
else:
|
||||
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)
|
||||
elif name_string == '__NSTimeZone':
|
||||
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
|
||||
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.value();
|
||||
except:
|
||||
summary = None
|
||||
if summary == None:
|
||||
summary = '<variable is not NSDate>'
|
||||
return str(summary)
|
||||
return 'Summary Unavailable'
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.timezone();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary == None:
|
||||
summary = '<variable is not NSTimeZone>'
|
||||
return str(summary)
|
||||
return 'Summary Unavailable'
|
||||
def NSDate_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
if summary is None:
|
||||
summary = '<variable is not NSDate>'
|
||||
return str(summary)
|
||||
return 'Summary Unavailable'
|
||||
|
||||
|
||||
def CFAbsoluteTime_SummaryProvider (valobj,dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
try:
|
||||
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 NSTimeZone_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary is None:
|
||||
summary = '<variable is not NSTimeZone>'
|
||||
return str(summary)
|
||||
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 CFAbsoluteTime_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
try:
|
||||
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")
|
||||
|
|
|
@ -18,97 +18,117 @@ 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.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();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
|
||||
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
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
class NSUnknownException_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
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]");
|
||||
if name_vo.IsValid() and reason_vo.IsValid():
|
||||
return CFString.CFString_SummaryProvider(name_vo,None) + ' ' + CFString.CFString_SummaryProvider(reason_vo,None)
|
||||
return '<variable is not NSException>'
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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]")
|
||||
if name_vo.IsValid() and reason_vo.IsValid():
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
name_string = class_data.class_name()
|
||||
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)
|
||||
else:
|
||||
wrapper = NSUnknownException_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
|
||||
return wrapper;
|
||||
if name_string == 'NSException':
|
||||
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
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.description();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary == 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 NSException_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
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")
|
||||
|
|
|
@ -22,129 +22,155 @@ 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.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)
|
||||
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)
|
||||
if not(self.sys_params.types_cache.uint32):
|
||||
self.sys_params.types_cache.uint32 = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
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)
|
||||
if not(self.sys_params.types_cache.uint32):
|
||||
self.sys_params.types_cache.uint32 = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update()
|
||||
|
||||
# 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
|
||||
def count(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
if self.sys_params.is_64_bit:
|
||||
mode_chooser = mode_chooser & 0x00000000FFFFFFFF
|
||||
# empty set
|
||||
if mode_chooser & 0x01 == 1:
|
||||
return 0
|
||||
# single range
|
||||
if mode_chooser & 0x02 == 2:
|
||||
mode = 1
|
||||
# multi range
|
||||
else:
|
||||
mode = 2
|
||||
if mode == 1:
|
||||
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,
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
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)
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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
|
||||
def count(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
if self.sys_params.is_64_bit:
|
||||
mode_chooser = mode_chooser & 0x00000000FFFFFFFF
|
||||
# empty set
|
||||
if mode_chooser & 0x01 == 1:
|
||||
return 0
|
||||
# single range
|
||||
if mode_chooser & 0x02 == 2:
|
||||
mode = 1
|
||||
# multi range
|
||||
else:
|
||||
mode = 2
|
||||
if mode == 1:
|
||||
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,
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
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.sys_params = params
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
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)
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return '<variable is not NSIndexSet>'
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return '<variable is not NSIndexSet>'
|
||||
|
||||
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
name_string = class_data.class_name()
|
||||
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)
|
||||
else:
|
||||
wrapper = NSIndexSetUnknown_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
|
||||
return wrapper;
|
||||
if name_string == 'NSIndexSet' or name_string == 'NSMutableIndexSet':
|
||||
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
|
||||
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.count();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary == None:
|
||||
summary = '<variable is not NSIndexSet>'
|
||||
if isinstance(summary, basestring):
|
||||
return summary
|
||||
else:
|
||||
summary = str(summary) + (' indexes' if summary != 1 else ' index')
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
def NSIndexSet_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary is None:
|
||||
summary = '<variable is not NSIndexSet>'
|
||||
if isinstance(summary, basestring):
|
||||
return summary
|
||||
else:
|
||||
summary = str(summary) + (' indexes' if summary != 1 else ' index')
|
||||
return summary
|
||||
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")
|
||||
|
|
|
@ -22,102 +22,120 @@ 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.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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update()
|
||||
|
||||
# one pointer is the ISA
|
||||
# then we have one other internal pointer, plus
|
||||
# 4 bytes worth of flags. hence, these values
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.sys_params.is_64_bit:
|
||||
return 20
|
||||
else:
|
||||
return 12
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def port(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
vport = self.valobj.CreateChildAtOffset("port",
|
||||
self.offset(),
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
return vport.GetValueAsUnsigned(0)
|
||||
# one pointer is the ISA
|
||||
# then we have one other internal pointer, plus
|
||||
# 4 bytes worth of flags. hence, these values
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.sys_params.is_64_bit:
|
||||
return 20
|
||||
else:
|
||||
return 12
|
||||
|
||||
def port(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.sys_params = params
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
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]")
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return '<variable is not NSMachPort>'
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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]")
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return '<variable is not NSMachPort>'
|
||||
|
||||
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
name_string = class_data.class_name()
|
||||
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)
|
||||
else:
|
||||
wrapper = NSMachPortUnknown_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
|
||||
return wrapper;
|
||||
if name_string == 'NSMachPort':
|
||||
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
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.port();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary == 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 NSMachPort_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
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")
|
||||
|
|
|
@ -19,92 +19,108 @@ 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.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();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
|
||||
# skip the ISA and go to the name pointer
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.sys_params.pointer_size
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
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)
|
||||
# skip the ISA and go to the name pointer
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.sys_params.pointer_size
|
||||
|
||||
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)
|
||||
|
||||
|
||||
class NSNotificationUnknown_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
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]")
|
||||
if name_vo.IsValid():
|
||||
return CFString.CFString_SummaryProvider(name_vo,None)
|
||||
return '<variable is not NSNotification>'
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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]")
|
||||
if name_vo.IsValid():
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
name_string = class_data.class_name()
|
||||
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)
|
||||
else:
|
||||
wrapper = NSNotificationUnknown_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
|
||||
return wrapper;
|
||||
if name_string == 'NSConcreteNotification':
|
||||
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
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.name();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary == 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 NSNotification_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
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")
|
||||
|
|
|
@ -23,213 +23,247 @@ 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.sys_params = params
|
||||
self.info_bits = info_bits
|
||||
self.data = data
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, info_bits, data, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.info_bits = info_bits
|
||||
self.data = data
|
||||
self.update()
|
||||
|
||||
def value(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
# in spite of the plenty of types made available by the public NSNumber API
|
||||
# only a bunch of these are actually used in the internal implementation
|
||||
# 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))
|
||||
if self.info_bits == 4:
|
||||
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)
|
||||
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) + ')'
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def value(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
# in spite of the plenty of types made available by the public NSNumber API
|
||||
# only a bunch of these are actually used in the internal implementation
|
||||
# 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))
|
||||
if self.info_bits == 4:
|
||||
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)
|
||||
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) + ')'
|
||||
|
||||
|
||||
class NSUntaggedNumber_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
if not(self.sys_params.types_cache.short):
|
||||
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)
|
||||
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)
|
||||
if not(self.sys_params.types_cache.ulong):
|
||||
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)
|
||||
if not(self.sys_params.types_cache.ulonglong):
|
||||
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)
|
||||
if not(self.sys_params.types_cache.double):
|
||||
self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
if not(self.sys_params.types_cache.short):
|
||||
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)
|
||||
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)
|
||||
if not(self.sys_params.types_cache.ulong):
|
||||
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)
|
||||
if not(self.sys_params.types_cache.ulonglong):
|
||||
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)
|
||||
if not(self.sys_params.types_cache.double):
|
||||
self.sys_params.types_cache.double = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeDouble)
|
||||
self.update()
|
||||
|
||||
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)
|
||||
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))
|
||||
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)
|
||||
# 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)
|
||||
# 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)
|
||||
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)
|
||||
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))
|
||||
packed = struct.pack('I', data_plain)
|
||||
data_float = struct.unpack('f', packed)[0]
|
||||
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_plain = data_vo.GetValueAsUnsigned(0)
|
||||
data_double = struct.unpack('d', struct.pack('Q', data_plain))[0]
|
||||
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))
|
||||
return 'unexpected: dt = ' + str(data_type)
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
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))
|
||||
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)
|
||||
# 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)
|
||||
# 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)
|
||||
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)
|
||||
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))
|
||||
packed = struct.pack('I', data_plain)
|
||||
data_float = struct.unpack('f', packed)[0]
|
||||
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_plain = data_vo.GetValueAsUnsigned(0)
|
||||
data_double = struct.unpack('d', struct.pack('Q', data_plain))[0]
|
||||
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))
|
||||
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.sys_params = params
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetSummary()
|
||||
return '<variable is not NSNumber>'
|
||||
|
||||
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)
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
name_string = class_data.class_name()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
|
||||
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)
|
||||
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)
|
||||
else:
|
||||
wrapper = NSUnknownNumber_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
|
||||
return wrapper;
|
||||
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)
|
||||
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)
|
||||
else:
|
||||
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):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = GetSummary_Impl(valobj);
|
||||
if provider != None:
|
||||
if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.value();
|
||||
except Exception as foo:
|
||||
print foo
|
||||
def NSNumber_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except Exception as foo:
|
||||
print foo
|
||||
# except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary == None:
|
||||
summary = '<variable is not NSNumber>'
|
||||
return str(summary)
|
||||
return 'Summary Unavailable'
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
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")
|
||||
|
|
|
@ -22,242 +22,268 @@ 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.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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update()
|
||||
|
||||
# one pointer is the ISA
|
||||
# then we have one other internal pointer, plus
|
||||
# 4 bytes worth of flags. hence, these values
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.sys_params.is_64_bit:
|
||||
return 20
|
||||
else:
|
||||
return 12
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def count(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
vcount = self.valobj.CreateChildAtOffset("count",
|
||||
self.offset(),
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
return vcount.GetValueAsUnsigned(0)
|
||||
# one pointer is the ISA
|
||||
# then we have one other internal pointer, plus
|
||||
# 4 bytes worth of flags. hence, these values
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.sys_params.is_64_bit:
|
||||
return 20
|
||||
else:
|
||||
return 12
|
||||
|
||||
def count(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.sys_params = params
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
if num_children_vo.IsValid():
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
return '<variable is not NSSet>'
|
||||
|
||||
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)
|
||||
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.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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update()
|
||||
|
||||
# we just need to skip the ISA and the count immediately follows
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.sys_params.pointer_size
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
# we just need to skip the ISA and the count immediately follows
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.sys_params.pointer_size
|
||||
|
||||
def count(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
num_children_vo = self.valobj.CreateChildAtOffset(
|
||||
"count", self.offset(), self.sys_params.types_cache.NSUInteger)
|
||||
value = num_children_vo.GetValueAsUnsigned(0)
|
||||
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
|
||||
# too large - but I have not tested this)
|
||||
if self.sys_params.is_64_bit:
|
||||
value = value & ~0xFF00000000000000
|
||||
else:
|
||||
value = value & ~0xFF000000
|
||||
return value
|
||||
|
||||
def count(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
num_children_vo = self.valobj.CreateChildAtOffset("count",
|
||||
self.offset(),
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
value = num_children_vo.GetValueAsUnsigned(0)
|
||||
if value != 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
|
||||
# too large - but I have not tested this)
|
||||
if self.sys_params.is_64_bit:
|
||||
value = value & ~0xFF00000000000000
|
||||
else:
|
||||
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.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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
else:
|
||||
self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
|
||||
).GetBasicType(lldb.eBasicTypeUnsignedInt)
|
||||
self.update()
|
||||
|
||||
# we just need to skip the ISA and the count immediately follows
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.sys_params.pointer_size
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
def count(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
num_children_vo = self.valobj.CreateChildAtOffset("count",
|
||||
self.offset(),
|
||||
self.sys_params.types_cache.NSUInteger)
|
||||
return num_children_vo.GetValueAsUnsigned(0)
|
||||
# we just need to skip the ISA and the count immediately follows
|
||||
def offset(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return self.sys_params.pointer_size
|
||||
|
||||
def count(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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.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();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
|
||||
# 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 update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
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()
|
||||
# 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()
|
||||
|
||||
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
name_string = class_data.class_name()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
|
||||
if name_string == '__NSCFSet':
|
||||
wrapper = NSCFSet_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun',valobj)
|
||||
elif name_string == '__NSSetI':
|
||||
wrapper = NSSetI_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun',valobj)
|
||||
elif name_string == '__NSSetM':
|
||||
wrapper = NSSetM_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun',valobj)
|
||||
elif name_string == 'NSCountedSet':
|
||||
wrapper = NSCountedSet_SummaryProvider(valobj, class_data.sys_params)
|
||||
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;
|
||||
if name_string == '__NSCFSet':
|
||||
wrapper = NSCFSet_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun', valobj)
|
||||
elif name_string == '__NSSetI':
|
||||
wrapper = NSSetI_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun', valobj)
|
||||
elif name_string == '__NSSetM':
|
||||
wrapper = NSSetM_SummaryProvider(valobj, class_data.sys_params)
|
||||
statistics.metric_hit('code_notrun', valobj)
|
||||
elif name_string == 'NSCountedSet':
|
||||
wrapper = NSCountedSet_SummaryProvider(valobj, class_data.sys_params)
|
||||
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
|
||||
|
||||
|
||||
def NSSet_SummaryProvider (valobj,dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = GetSummary_Impl(valobj);
|
||||
if provider != None:
|
||||
try:
|
||||
summary = provider.count();
|
||||
except:
|
||||
summary = None
|
||||
if summary == None:
|
||||
summary = '<variable is not NSSet>'
|
||||
if isinstance(summary, basestring):
|
||||
return summary
|
||||
else:
|
||||
summary = str(summary) + (' objects' if summary != 1 else ' object')
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.count();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
# for some reason, one needs to clear some bits for the count returned
|
||||
# to be correct when using directly CF*SetRef as compared to NS*Set
|
||||
# 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:
|
||||
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"')
|
||||
return summary
|
||||
return 'Summary Unavailable'
|
||||
def NSSet_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
provider = GetSummary_Impl(valobj)
|
||||
if provider is not None:
|
||||
try:
|
||||
summary = provider.count()
|
||||
except:
|
||||
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')
|
||||
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 NSSet_SummaryProvider2(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
# for some reason, one needs to clear some bits for the count returned
|
||||
# to be correct when using directly CF*SetRef as compared to NS*Set
|
||||
# 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 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"')
|
||||
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")
|
||||
|
|
|
@ -22,116 +22,132 @@ 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.sys_params = params
|
||||
if not(self.sys_params.types_cache.NSString):
|
||||
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();
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
if not(self.sys_params.types_cache.NSURL):
|
||||
self.sys_params.types_cache.NSURL = self.valobj.GetTarget(
|
||||
).FindFirstType('NSURL').GetPointerType()
|
||||
self.update()
|
||||
|
||||
# one pointer is the ISA
|
||||
# then there is one more pointer and 8 bytes of plain data
|
||||
# (which are also present on a 32-bit system)
|
||||
# then there is a pointer to an NSString which is the url text
|
||||
# optionally, the next pointer is another NSURL which is the "base"
|
||||
# of this one when doing NSURLs composition (incidentally, NSURLs can
|
||||
# recurse the base+text mechanism to any desired depth)
|
||||
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
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture()
|
||||
|
||||
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)
|
||||
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 + ' -- '
|
||||
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:]
|
||||
my_string = my_string + my_base_string
|
||||
return my_string
|
||||
# one pointer is the ISA
|
||||
# then there is one more pointer and 8 bytes of plain data
|
||||
# (which are also present on a 32-bit system)
|
||||
# then there is a pointer to an NSString which is the url text
|
||||
# optionally, the next pointer is another NSURL which is the "base"
|
||||
# of this one when doing NSURLs composition (incidentally, NSURLs can
|
||||
# recurse the base+text mechanism to any desired depth)
|
||||
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
|
||||
|
||||
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)
|
||||
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 + ' -- '
|
||||
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:]
|
||||
my_string = my_string + my_base_string
|
||||
return my_string
|
||||
|
||||
|
||||
class NSURLUnknown_SummaryProvider:
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
def adjust_for_architecture(self):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.adjust_for_architecture();
|
||||
def __init__(self, valobj, params):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.sys_params = params
|
||||
self.update()
|
||||
|
||||
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]")
|
||||
if url_text_vo.IsValid():
|
||||
return CFString.CFString_SummaryProvider(url_text_vo,None)
|
||||
return '<variable is not NSURL>'
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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]")
|
||||
if url_text_vo.IsValid():
|
||||
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)
|
||||
if wrapper:
|
||||
return wrapper
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
global 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()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
name_string = class_data.class_name()
|
||||
logger >> "class name is: " + str(name_string)
|
||||
|
||||
if name_string == 'NSURL':
|
||||
wrapper = NSURLKnown_SummaryProvider(valobj, class_data.sys_params)
|
||||
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;
|
||||
if name_string == 'NSURL':
|
||||
wrapper = NSURLKnown_SummaryProvider(valobj, class_data.sys_params)
|
||||
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
|
||||
|
||||
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):
|
||||
return provider.message()
|
||||
try:
|
||||
summary = provider.url_text();
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(summary)
|
||||
if summary == 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 NSURL_SummaryProvider(valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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()
|
||||
except:
|
||||
summary = None
|
||||
logger >> "got summary " + str(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")
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -5,34 +5,38 @@ 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
|
||||
self.__dict__['_allow_reset'] = allow_reset
|
||||
|
||||
def __getattr__(self,name):
|
||||
if not self._check_exists(name):
|
||||
return None
|
||||
value = self._dictionary[name]
|
||||
return value
|
||||
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 _set_impl(self,name,value):
|
||||
self._dictionary[name] = value
|
||||
def __getattr__(self, name):
|
||||
if not self._check_exists(name):
|
||||
return None
|
||||
value = self._dictionary[name]
|
||||
return value
|
||||
|
||||
def _check_exists(self,name):
|
||||
return name in self._dictionary
|
||||
def _set_impl(self, name, value):
|
||||
self._dictionary[name] = value
|
||||
|
||||
def __setattr__(self,name,value):
|
||||
if self._allow_reset:
|
||||
self._set_impl(name,value)
|
||||
else:
|
||||
self.set_if_necessary(name,value)
|
||||
def _check_exists(self, name):
|
||||
return name in self._dictionary
|
||||
|
||||
def set_if_necessary(self,name,value):
|
||||
if not self._check_exists(name):
|
||||
self._set_impl(name,value)
|
||||
return True
|
||||
return False
|
||||
def __setattr__(self, name, value):
|
||||
if self._allow_reset:
|
||||
self._set_impl(name, value)
|
||||
else:
|
||||
self.set_if_necessary(name, value)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._dictionary)
|
||||
def set_if_necessary(self, name, value):
|
||||
if not self._check_exists(name):
|
||||
self._set_impl(name, value)
|
||||
return True
|
||||
return False
|
||||
|
||||
def __len__(self):
|
||||
return len(self._dictionary)
|
||||
|
|
|
@ -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):
|
||||
if key in self.data:
|
||||
return True
|
||||
return False
|
||||
def __init__(self):
|
||||
self.data = {}
|
||||
self.statistics = lldb.formatters.metrics.Metrics()
|
||||
self.statistics.add_metric('hit')
|
||||
self.statistics.add_metric('miss')
|
||||
|
||||
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 look_for_key(self, key):
|
||||
if key in self.data:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_value(self,key,default=None):
|
||||
if self.look_for_key(key):
|
||||
self.statistics.metric_hit('hit',key)
|
||||
return self.data[key]
|
||||
else:
|
||||
self.statistics.metric_hit('miss',key)
|
||||
return default
|
||||
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):
|
||||
if self.look_for_key(key):
|
||||
self.statistics.metric_hit('hit', key)
|
||||
return self.data[key]
|
||||
else:
|
||||
self.statistics.metric_hit('miss', key)
|
||||
return default
|
||||
|
|
|
@ -6,89 +6,107 @@ 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):
|
||||
self.label = "" if lbl is None else lbl
|
||||
pass
|
||||
@staticmethod
|
||||
def generate(label=None):
|
||||
return TimeMetrics(label)
|
||||
|
||||
def __enter__(self):
|
||||
caller = inspect.stack()[1]
|
||||
self.function = str(caller)
|
||||
self.enter_time = time.clock()
|
||||
def __init__(self, lbl=None):
|
||||
self.label = "" if lbl is None else lbl
|
||||
pass
|
||||
|
||||
def __enter__(self):
|
||||
caller = inspect.stack()[1]
|
||||
self.function = str(caller)
|
||||
self.enter_time = time.clock()
|
||||
|
||||
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)
|
||||
return False
|
||||
|
||||
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)
|
||||
return False
|
||||
|
||||
class Counter:
|
||||
def __init__(self):
|
||||
self.count = 0
|
||||
self.list = []
|
||||
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):
|
||||
self.list.append(name.GetName())
|
||||
else:
|
||||
self.list.append(str(name))
|
||||
def __str__(self):
|
||||
return str(self.count) + " times, for items [" + str(self.list) + "]"
|
||||
|
||||
def __init__(self):
|
||||
self.count = 0
|
||||
self.list = []
|
||||
|
||||
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):
|
||||
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):
|
||||
self.metrics = metrics
|
||||
def __str__(self):
|
||||
string = ""
|
||||
for key,value in self.metrics.metrics.items():
|
||||
string = string + "metric " + str(key) + ": " + str(value) + "\n"
|
||||
return string
|
||||
|
||||
def __init__(self, metrics):
|
||||
self.metrics = metrics
|
||||
|
||||
def __str__(self):
|
||||
string = ""
|
||||
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):
|
||||
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"
|
||||
return string
|
||||
|
||||
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"
|
||||
return string
|
||||
|
||||
|
||||
class Metrics:
|
||||
def __init__(self):
|
||||
self.metrics = {}
|
||||
|
||||
def add_metric(self,name):
|
||||
self.metrics[name] = Counter()
|
||||
def __init__(self):
|
||||
self.metrics = {}
|
||||
|
||||
def metric_hit(self,metric,trigger):
|
||||
self.metrics[metric].update(trigger)
|
||||
def add_metric(self, name):
|
||||
self.metrics[name] = Counter()
|
||||
|
||||
def __getitem__(self,key):
|
||||
return self.metrics[key]
|
||||
def metric_hit(self, metric, trigger):
|
||||
self.metrics[metric].update(trigger)
|
||||
|
||||
def __getattr__(self,name):
|
||||
if name == 'compact':
|
||||
return MetricsPrinter_Compact(self)
|
||||
if name == 'verbose':
|
||||
return MetricsPrinter_Verbose(self)
|
||||
raise AttributeError("%r object has no attribute %r" %
|
||||
(type(self).__name__, name))
|
||||
def __getitem__(self, key):
|
||||
return self.metrics[key]
|
||||
|
||||
def __str__(self):
|
||||
return str(self.verbose)
|
||||
def __getattr__(self, name):
|
||||
if name == 'compact':
|
||||
return MetricsPrinter_Compact(self)
|
||||
if name == 'verbose':
|
||||
return MetricsPrinter_Verbose(self)
|
||||
raise AttributeError("%r object has no attribute %r" %
|
||||
(type(self).__name__, name))
|
||||
|
||||
def metric_success(self,metric):
|
||||
total_count = 0
|
||||
metric_count = self[metric].count
|
||||
for key,value in self.metrics.items():
|
||||
total_count = total_count + value.count
|
||||
if total_count > 0:
|
||||
return metric_count / float(total_count)
|
||||
return 0
|
||||
def __str__(self):
|
||||
return str(self.verbose)
|
||||
|
||||
def metric_success(self, metric):
|
||||
total_count = 0
|
||||
metric_count = self[metric].count
|
||||
for key, value in self.metrics.items():
|
||||
total_count = total_count + value.count
|
||||
if total_count > 0:
|
||||
return metric_count / float(total_count)
|
||||
return 0
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,16 +1,19 @@
|
|||
# Summaries for common ObjC types that require Python scripting
|
||||
# to be generated fit into this file
|
||||
|
||||
def BOOL_SummaryProvider (valobj,dict):
|
||||
if not (valobj.IsValid()):
|
||||
return "<invalid>"
|
||||
if valobj.GetValueAsUnsigned() == 0:
|
||||
return "NO"
|
||||
else:
|
||||
return "YES"
|
||||
|
||||
def BOOLRef_SummaryProvider (valobj, dict):
|
||||
return BOOL_SummaryProvider (valobj.GetChildAtIndex(0),dict)
|
||||
def BOOL_SummaryProvider(valobj, dict):
|
||||
if not (valobj.IsValid()):
|
||||
return "<invalid>"
|
||||
if valobj.GetValueAsUnsigned() == 0:
|
||||
return "NO"
|
||||
else:
|
||||
return "YES"
|
||||
|
||||
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)
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
import lldb
|
||||
|
||||
def pyobj_summary (value,unused):
|
||||
if value == 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()
|
||||
refcnt_value = "rc = %d" % (refcnt.GetValueAsUnsigned(0))
|
||||
return "%s (%s)" % (expr_summary,refcnt_value)
|
||||
|
||||
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()
|
||||
refcnt_value = "rc = %d" % (refcnt.GetValueAsUnsigned(0))
|
||||
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}")
|
||||
|
|
|
@ -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):
|
||||
self.valobj = valobj
|
||||
self.update()
|
||||
def update(self):
|
||||
pass
|
||||
def num_children(self):
|
||||
return 1
|
||||
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):
|
||||
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 None
|
||||
|
||||
def SharedPtr_SummaryProvider (valobj,dict):
|
||||
return 'use = ' + str(valobj.GetChildMemberWithName("count").GetValueAsUnsigned())
|
||||
class SharedPtr_SyntheticChildrenProvider:
|
||||
|
||||
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):
|
||||
if name == "ptr":
|
||||
return 0
|
||||
if name == "count":
|
||||
return 1
|
||||
return None
|
||||
|
||||
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 None
|
||||
|
||||
|
||||
def SharedPtr_SummaryProvider(valobj, dict):
|
||||
return 'use = ' + \
|
||||
str(valobj.GetChildMemberWithName("count").GetValueAsUnsigned())
|
||||
|
||||
|
||||
class ValueObjectSP_SyntheticChildrenProvider:
|
||||
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):
|
||||
if name == "ptr":
|
||||
return 0
|
||||
if name == "count":
|
||||
return 1
|
||||
return None
|
||||
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 None
|
||||
|
||||
def ValueObjectSP_SummaryProvider (valobj,dict):
|
||||
return 'use = ' + str(1 + valobj.GetChildMemberWithName("count").GetValueAsUnsigned())
|
||||
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):
|
||||
if name == "ptr":
|
||||
return 0
|
||||
if name == "count":
|
||||
return 1
|
||||
return None
|
||||
|
||||
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 None
|
||||
|
||||
|
||||
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')
|
||||
|
|
|
@ -1,57 +1,66 @@
|
|||
import lldb
|
||||
|
||||
|
||||
class PythonObjectSyntheticChildProvider(object):
|
||||
def __init__(self, value, internal_dict):
|
||||
self.value = value
|
||||
self.values = self.make_children()
|
||||
self.built_values = {}
|
||||
self.bo = self.value.target.byte_order
|
||||
self.ps = self.value.target.addr_size
|
||||
|
||||
def make_children(self):
|
||||
pass
|
||||
def __init__(self, value, internal_dict):
|
||||
self.value = value
|
||||
self.values = self.make_children()
|
||||
self.built_values = {}
|
||||
self.bo = self.value.target.byte_order
|
||||
self.ps = self.value.target.addr_size
|
||||
|
||||
def num_children(self):
|
||||
return len(self.values)
|
||||
def make_children(self):
|
||||
pass
|
||||
|
||||
def get_child_index(self, name):
|
||||
i = 0
|
||||
for N, value in self.values:
|
||||
if N == name: return i
|
||||
i += 1
|
||||
return None
|
||||
def num_children(self):
|
||||
return len(self.values)
|
||||
|
||||
def update(self):
|
||||
pass
|
||||
def get_child_index(self, name):
|
||||
i = 0
|
||||
for N, value in self.values:
|
||||
if N == name:
|
||||
return i
|
||||
i += 1
|
||||
return None
|
||||
|
||||
def has_children(self):
|
||||
return len(self.values) > 0
|
||||
def update(self):
|
||||
pass
|
||||
|
||||
def gen_child(self, name, value):
|
||||
data = None; type = None
|
||||
if isinstance(value, int):
|
||||
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])
|
||||
type = self.value.target.GetBasicType(lldb.eBasicTypeLong)
|
||||
elif isinstance(value, float):
|
||||
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))
|
||||
if (data is not None) and (type is not None):
|
||||
return self.value.CreateValueFromData(name, data, type)
|
||||
return None
|
||||
def has_children(self):
|
||||
return len(self.values) > 0
|
||||
|
||||
def get_child_at_index(self, index):
|
||||
if index in self.built_values:
|
||||
return self.built_values[index]
|
||||
def gen_child(self, name, value):
|
||||
data = None
|
||||
type = None
|
||||
if isinstance(value, int):
|
||||
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])
|
||||
type = self.value.target.GetBasicType(lldb.eBasicTypeLong)
|
||||
elif isinstance(value, float):
|
||||
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))
|
||||
if (data is not None) and (type is not None):
|
||||
return self.value.CreateValueFromData(name, data, type)
|
||||
return None
|
||||
|
||||
bv = None
|
||||
def get_child_at_index(self, index):
|
||||
if index in self.built_values:
|
||||
return self.built_values[index]
|
||||
|
||||
name, value = self.values[index]
|
||||
bv = self.gen_child(name, value)
|
||||
self.built_values[index] = bv
|
||||
return bv
|
||||
bv = None
|
||||
|
||||
name, value = self.values[index]
|
||||
bv = self.gen_child(name, value)
|
||||
self.built_values[index] = bv
|
||||
return bv
|
||||
|
|
|
@ -11,38 +11,43 @@ License. See LICENSE.TXT for details.
|
|||
"""
|
||||
|
||||
import lldb
|
||||
def utf8_summary(value,unused):
|
||||
pointer = value.GetChildMemberWithName("first").GetValueAsUnsigned(0)
|
||||
length = value.GetChildMemberWithName("second").GetValueAsUnsigned(0)
|
||||
if pointer == 0:
|
||||
return False
|
||||
if length == 0:
|
||||
return '""'
|
||||
error = lldb.SBError()
|
||||
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):
|
||||
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
|
||||
if pointer == 0:
|
||||
return False
|
||||
if length == 0:
|
||||
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
|
||||
|
||||
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
|
||||
if pointer == 0:
|
||||
return False
|
||||
if length == 0:
|
||||
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
|
||||
def utf8_summary(value, unused):
|
||||
pointer = value.GetChildMemberWithName("first").GetValueAsUnsigned(0)
|
||||
length = value.GetChildMemberWithName("second").GetValueAsUnsigned(0)
|
||||
if pointer == 0:
|
||||
return False
|
||||
if length == 0:
|
||||
return '""'
|
||||
error = lldb.SBError()
|
||||
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):
|
||||
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
|
||||
if pointer == 0:
|
||||
return False
|
||||
if length == 0:
|
||||
return '""'
|
||||
error = lldb.SBError()
|
||||
string_data = value.process.ReadMemory(pointer, length, error)
|
||||
# utf8 is safe to emit as-is on OSX
|
||||
return '"%s"' % (string_data.decode('utf-16').encode('utf-8'))
|
||||
|
||||
|
||||
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
|
||||
if pointer == 0:
|
||||
return False
|
||||
if length == 0:
|
||||
return '""'
|
||||
error = lldb.SBError()
|
||||
string_data = value.process.ReadMemory(pointer, length, error)
|
||||
# utf8 is safe to emit as-is on OSX
|
||||
return '"%s"' % (string_data.decode('utf-32').encode('utf-8'))
|
||||
|
|
|
@ -1,100 +1,123 @@
|
|||
# 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 :-)
|
||||
|
||||
def num_children(self):
|
||||
# you could perform calculations involving the SBValue and/or its children to determine this value
|
||||
# here, we have an hardcoded value - but since you have stored the SBValue you could use it to
|
||||
# help figure out the correct thing to return here. if you return a number N, you should be prepared to
|
||||
# answer questions about N children
|
||||
return 4
|
||||
def __init__(self, valobj, dict):
|
||||
# remember the SBValue since you will not have another chance to get it
|
||||
# :-)
|
||||
self.valobj = valobj
|
||||
|
||||
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)
|
||||
return True
|
||||
def num_children(self):
|
||||
# you could perform calculations involving the SBValue and/or its children to determine this value
|
||||
# here, we have an hardcoded value - but since you have stored the SBValue you could use it to
|
||||
# help figure out the correct thing to return here. if you return a number N, you should be prepared to
|
||||
# answer questions about N children
|
||||
return 4
|
||||
|
||||
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":
|
||||
return 0
|
||||
# here, we are using a reserved C++ keyword as a child name - we could not do that in the source code
|
||||
# but we are free to use the names we like best in the synthetic children provider class
|
||||
# we are also not respecting the order of declaration in the C++ class itself - as long as
|
||||
# we are consistent, we can do that freely
|
||||
if name == "operator":
|
||||
return 1
|
||||
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
|
||||
if name == "apply()":
|
||||
return 3
|
||||
return None # no clue, just say none
|
||||
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)
|
||||
return True
|
||||
|
||||
def get_child_at_index(self,index):
|
||||
# precautionary measures
|
||||
if index < 0:
|
||||
return None
|
||||
if index > self.num_children():
|
||||
return None
|
||||
if self.valobj.IsValid() == False:
|
||||
return None
|
||||
if index == 0:
|
||||
return self.valobj.GetChildMemberWithName("value")
|
||||
if index == 1:
|
||||
# fetch the value of the operator
|
||||
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
|
||||
if op_chosen == 0:
|
||||
return self.valobj.CreateValueFromExpression("operator",'(const char*)"none"')
|
||||
elif op_chosen == 1:
|
||||
return self.valobj.CreateValueFromExpression("operator",'(const char*)"AND"')
|
||||
elif op_chosen == 2:
|
||||
return self.valobj.CreateValueFromExpression("operator",'(const char*)"OR"')
|
||||
elif op_chosen == 3:
|
||||
return self.valobj.CreateValueFromExpression("operator",'(const char*)"XOR"')
|
||||
elif op_chosen == 4:
|
||||
return self.valobj.CreateValueFromExpression("operator",'(const char*)"NAND"')
|
||||
elif op_chosen == 5:
|
||||
return self.valobj.CreateValueFromExpression("operator",'(const char*)"NOR"')
|
||||
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()
|
||||
# compute the masked value according to the operator
|
||||
if operator == 1:
|
||||
value = value & mask
|
||||
elif operator == 2:
|
||||
value = value | mask
|
||||
elif operator == 3:
|
||||
value = value ^ mask
|
||||
elif operator == 4:
|
||||
value = ~(value & mask)
|
||||
elif operator == 5:
|
||||
value = ~(value | mask)
|
||||
else:
|
||||
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) + ')')
|
||||
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":
|
||||
return 0
|
||||
# here, we are using a reserved C++ keyword as a child name - we could not do that in the source code
|
||||
# but we are free to use the names we like best in the synthetic children provider class
|
||||
# we are also not respecting the order of declaration in the C++ class itself - as long as
|
||||
# we are consistent, we can do that freely
|
||||
if name == "operator":
|
||||
return 1
|
||||
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
|
||||
if name == "apply()":
|
||||
return 3
|
||||
return None # no clue, just say none
|
||||
|
||||
def update(self):
|
||||
# we do not do anything special in update - but this would be the right place to lookup
|
||||
# the data we use in get_child_at_index and cache it
|
||||
pass
|
||||
def get_child_at_index(self, index):
|
||||
# precautionary measures
|
||||
if index < 0:
|
||||
return None
|
||||
if index > self.num_children():
|
||||
return None
|
||||
if self.valobj.IsValid() == False:
|
||||
return None
|
||||
if index == 0:
|
||||
return self.valobj.GetChildMemberWithName("value")
|
||||
if index == 1:
|
||||
# fetch the value of the operator
|
||||
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
|
||||
if op_chosen == 0:
|
||||
return self.valobj.CreateValueFromExpression(
|
||||
"operator", '(const char*)"none"')
|
||||
elif op_chosen == 1:
|
||||
return self.valobj.CreateValueFromExpression(
|
||||
"operator", '(const char*)"AND"')
|
||||
elif op_chosen == 2:
|
||||
return self.valobj.CreateValueFromExpression(
|
||||
"operator", '(const char*)"OR"')
|
||||
elif op_chosen == 3:
|
||||
return self.valobj.CreateValueFromExpression(
|
||||
"operator", '(const char*)"XOR"')
|
||||
elif op_chosen == 4:
|
||||
return self.valobj.CreateValueFromExpression(
|
||||
"operator", '(const char*)"NAND"')
|
||||
elif op_chosen == 5:
|
||||
return self.valobj.CreateValueFromExpression(
|
||||
"operator", '(const char*)"NOR"')
|
||||
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()
|
||||
# compute the masked value according to the operator
|
||||
if operator == 1:
|
||||
value = value & mask
|
||||
elif operator == 2:
|
||||
value = value | mask
|
||||
elif operator == 3:
|
||||
value = value ^ mask
|
||||
elif operator == 4:
|
||||
value = ~(value & mask)
|
||||
elif operator == 5:
|
||||
value = ~(value | mask)
|
||||
else:
|
||||
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) + ')')
|
||||
|
||||
def update(self):
|
||||
# we do not do anything special in update - but this would be the right place to lookup
|
||||
# the data we use in get_child_at_index and cache it
|
||||
pass
|
||||
|
|
|
@ -1,74 +1,56 @@
|
|||
typedef unsigned int uint32_t;
|
||||
|
||||
enum MaskingOperator
|
||||
{
|
||||
eMaskingOperatorDefault = 0,
|
||||
eMaskingOperatorAnd = 1,
|
||||
eMaskingOperatorOr = 2,
|
||||
eMaskingOperatorXor = 3,
|
||||
eMaskingOperatorNand = 4,
|
||||
eMaskingOperatorNor = 5
|
||||
enum MaskingOperator {
|
||||
eMaskingOperatorDefault = 0,
|
||||
eMaskingOperatorAnd = 1,
|
||||
eMaskingOperatorOr = 2,
|
||||
eMaskingOperatorXor = 3,
|
||||
eMaskingOperatorNand = 4,
|
||||
eMaskingOperatorNor = 5
|
||||
};
|
||||
|
||||
class MaskedData
|
||||
{
|
||||
class MaskedData {
|
||||
private:
|
||||
uint32_t value;
|
||||
uint32_t mask;
|
||||
MaskingOperator oper;
|
||||
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)
|
||||
{
|
||||
}
|
||||
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:
|
||||
return value | mask;
|
||||
case eMaskingOperatorXor:
|
||||
return value ^ mask;
|
||||
case eMaskingOperatorNand:
|
||||
return ~(value & mask);
|
||||
case eMaskingOperatorNor:
|
||||
return ~(value | mask);
|
||||
case eMaskingOperatorDefault: // fall through
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
uint32_t apply() {
|
||||
switch (oper) {
|
||||
case eMaskingOperatorAnd:
|
||||
return value & mask;
|
||||
case eMaskingOperatorOr:
|
||||
return value | mask;
|
||||
case eMaskingOperatorXor:
|
||||
return value ^ mask;
|
||||
case eMaskingOperatorNand:
|
||||
return ~(value & mask);
|
||||
case eMaskingOperatorNor:
|
||||
return ~(value | mask);
|
||||
case eMaskingOperatorDefault: // fall through
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
return data_6.apply(); // <-- what comes out of here?
|
||||
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?
|
||||
}
|
|
@ -7,446 +7,474 @@ 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())
|
||||
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())
|
||||
|
||||
def next_node(self,node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return node.GetChildMemberWithName('_M_next')
|
||||
def next_node(self, node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return node.GetChildMemberWithName('_M_next')
|
||||
|
||||
def is_valid(self,node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
valid = self.value(self.next_node(node)) != self.node_address
|
||||
if valid:
|
||||
logger >> "%s is valid" % str(self.valobj.GetName())
|
||||
else:
|
||||
logger >> "synthetic value is not valid"
|
||||
return valid
|
||||
def is_valid(self, node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
valid = self.value(self.next_node(node)) != self.node_address
|
||||
if valid:
|
||||
logger >> "%s is valid" % str(self.valobj.GetName())
|
||||
else:
|
||||
logger >> "synthetic value is not valid"
|
||||
return valid
|
||||
|
||||
def value(self,node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
value = node.GetValueAsUnsigned()
|
||||
logger >> "synthetic value for {}: {}".format(str(self.valobj.GetName()), value)
|
||||
return value
|
||||
def value(self, node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
value = node.GetValueAsUnsigned()
|
||||
logger >> "synthetic value for {}: {}".format(
|
||||
str(self.valobj.GetName()), value)
|
||||
return value
|
||||
|
||||
# Floyd's cycle-finding algorithm
|
||||
# try to detect if this list has a loop
|
||||
def has_loop(self):
|
||||
global _list_uses_loop_detector
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if _list_uses_loop_detector == False:
|
||||
logger >> "Asked not to use loop detection"
|
||||
return False
|
||||
slow = self.next
|
||||
fast1 = self.next
|
||||
fast2 = self.next
|
||||
while self.is_valid(slow):
|
||||
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:
|
||||
return True
|
||||
slow = self.next_node(slow)
|
||||
return False
|
||||
# Floyd's cycle-finding algorithm
|
||||
# try to detect if this list has a loop
|
||||
def has_loop(self):
|
||||
global _list_uses_loop_detector
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if not _list_uses_loop_detector:
|
||||
logger >> "Asked not to use loop detection"
|
||||
return False
|
||||
slow = self.next
|
||||
fast1 = self.next
|
||||
fast2 = self.next
|
||||
while self.is_valid(slow):
|
||||
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:
|
||||
return True
|
||||
slow = self.next_node(slow)
|
||||
return False
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.count is None:
|
||||
# libstdc++ 6.0.21 added dedicated count field.
|
||||
count_child = self.node.GetChildMemberWithName('_M_data')
|
||||
if count_child and count_child.IsValid():
|
||||
self.count = count_child.GetValueAsUnsigned(0)
|
||||
if self.count is None:
|
||||
self.count = self.num_children_impl()
|
||||
return self.count
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.count is None:
|
||||
# libstdc++ 6.0.21 added dedicated count field.
|
||||
count_child = self.node.GetChildMemberWithName('_M_data')
|
||||
if count_child and count_child.IsValid():
|
||||
self.count = count_child.GetValueAsUnsigned(0)
|
||||
if self.count is None:
|
||||
self.count = self.num_children_impl()
|
||||
return self.count
|
||||
|
||||
def num_children_impl(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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
|
||||
if next_val == 0 or prev_val == 0:
|
||||
return 0
|
||||
if next_val == self.node_address:
|
||||
return 0
|
||||
if next_val == prev_val:
|
||||
return 1
|
||||
if self.has_loop():
|
||||
return 0
|
||||
size = 2
|
||||
current = self.next
|
||||
while current.GetChildMemberWithName('_M_next').GetValueAsUnsigned(0) != self.node_address:
|
||||
size = size + 1
|
||||
current = current.GetChildMemberWithName('_M_next')
|
||||
return (size - 1)
|
||||
except:
|
||||
return 0;
|
||||
def num_children_impl(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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
|
||||
if next_val == 0 or prev_val == 0:
|
||||
return 0
|
||||
if next_val == self.node_address:
|
||||
return 0
|
||||
if next_val == prev_val:
|
||||
return 1
|
||||
if self.has_loop():
|
||||
return 0
|
||||
size = 2
|
||||
current = self.next
|
||||
while current.GetChildMemberWithName(
|
||||
'_M_next').GetValueAsUnsigned(0) != self.node_address:
|
||||
size = size + 1
|
||||
current = current.GetChildMemberWithName('_M_next')
|
||||
return (size - 1)
|
||||
except:
|
||||
return 0
|
||||
|
||||
def get_child_index(self,name):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
try:
|
||||
return int(name.lstrip('[').rstrip(']'))
|
||||
except:
|
||||
return -1
|
||||
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):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
logger >> "Fetching child " + str(index)
|
||||
if index < 0:
|
||||
return None;
|
||||
if index >= self.num_children():
|
||||
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)
|
||||
except:
|
||||
return None
|
||||
def get_child_at_index(self, index):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
logger >> "Fetching child " + str(index)
|
||||
if index < 0:
|
||||
return None
|
||||
if index >= self.num_children():
|
||||
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)
|
||||
except:
|
||||
return None
|
||||
|
||||
def extract_type(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
list_type = self.valobj.GetType().GetUnqualifiedType()
|
||||
if list_type.IsReferenceType():
|
||||
list_type = list_type.GetDereferencedType()
|
||||
if list_type.GetNumberOfTemplateArguments() > 0:
|
||||
data_type = list_type.GetTemplateArgumentType(0)
|
||||
else:
|
||||
data_type = None
|
||||
return data_type
|
||||
def extract_type(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
list_type = self.valobj.GetType().GetUnqualifiedType()
|
||||
if list_type.IsReferenceType():
|
||||
list_type = list_type.GetDereferencedType()
|
||||
if list_type.GetNumberOfTemplateArguments() > 0:
|
||||
data_type = list_type.GetTemplateArgumentType(0)
|
||||
else:
|
||||
data_type = None
|
||||
return data_type
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
# preemptively setting this to None - we might end up changing our mind later
|
||||
self.count = None
|
||||
try:
|
||||
impl = self.valobj.GetChildMemberWithName('_M_impl')
|
||||
self.node = impl.GetChildMemberWithName('_M_node')
|
||||
self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
|
||||
self.next = self.node.GetChildMemberWithName('_M_next')
|
||||
self.prev = self.node.GetChildMemberWithName('_M_prev')
|
||||
self.data_type = self.extract_type()
|
||||
self.data_size = self.data_type.GetByteSize()
|
||||
except:
|
||||
pass
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
# preemptively setting this to None - we might end up changing our mind
|
||||
# later
|
||||
self.count = None
|
||||
try:
|
||||
impl = self.valobj.GetChildMemberWithName('_M_impl')
|
||||
self.node = impl.GetChildMemberWithName('_M_node')
|
||||
self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
|
||||
self.next = self.node.GetChildMemberWithName('_M_next')
|
||||
self.prev = self.node.GetChildMemberWithName('_M_prev')
|
||||
self.data_type = self.extract_type()
|
||||
self.data_size = self.data_type.GetByteSize()
|
||||
except:
|
||||
pass
|
||||
|
||||
def has_children(self):
|
||||
return True
|
||||
|
||||
def has_children(self):
|
||||
return True
|
||||
|
||||
class StdVectorSynthProvider:
|
||||
|
||||
class StdVectorImplementation(object):
|
||||
def __init__(self, valobj):
|
||||
self.valobj = valobj
|
||||
self.count = None
|
||||
class StdVectorImplementation(object):
|
||||
|
||||
def num_children(self):
|
||||
if self.count == None:
|
||||
self.count = self.num_children_impl()
|
||||
return self.count
|
||||
def __init__(self, valobj):
|
||||
self.valobj = valobj
|
||||
self.count = None
|
||||
|
||||
def num_children_impl(self):
|
||||
try:
|
||||
start_val = self.start.GetValueAsUnsigned(0)
|
||||
finish_val = self.finish.GetValueAsUnsigned(0)
|
||||
end_val = self.end.GetValueAsUnsigned(0)
|
||||
# Before a vector has been constructed, it will contain bad values
|
||||
# so we really need to be careful about the length we return since
|
||||
# uninitialized data can cause us to return a huge number. We need
|
||||
# to also check for any of the start, finish or end of storage values
|
||||
# being zero (NULL). If any are, then this vector has not been
|
||||
# initialized yet and we should return zero
|
||||
def num_children(self):
|
||||
if self.count is None:
|
||||
self.count = self.num_children_impl()
|
||||
return self.count
|
||||
|
||||
# Make sure nothing is NULL
|
||||
if start_val == 0 or finish_val == 0 or end_val == 0:
|
||||
return 0
|
||||
# Make sure start is less than finish
|
||||
if start_val >= finish_val:
|
||||
return 0
|
||||
# Make sure finish is less than or equal to end of storage
|
||||
if finish_val > end_val:
|
||||
return 0
|
||||
def num_children_impl(self):
|
||||
try:
|
||||
start_val = self.start.GetValueAsUnsigned(0)
|
||||
finish_val = self.finish.GetValueAsUnsigned(0)
|
||||
end_val = self.end.GetValueAsUnsigned(0)
|
||||
# Before a vector has been constructed, it will contain bad values
|
||||
# so we really need to be careful about the length we return since
|
||||
# uninitialized data can cause us to return a huge number. We need
|
||||
# to also check for any of the start, finish or end of storage values
|
||||
# being zero (NULL). If any are, then this vector has not been
|
||||
# initialized yet and we should return zero
|
||||
|
||||
# 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)
|
||||
if (num_children % self.data_size) != 0:
|
||||
return 0
|
||||
else:
|
||||
num_children = num_children/self.data_size
|
||||
return num_children
|
||||
except:
|
||||
return 0;
|
||||
# Make sure nothing is NULL
|
||||
if start_val == 0 or finish_val == 0 or end_val == 0:
|
||||
return 0
|
||||
# Make sure start is less than finish
|
||||
if start_val >= finish_val:
|
||||
return 0
|
||||
# Make sure finish is less than or equal to end of storage
|
||||
if finish_val > end_val:
|
||||
return 0
|
||||
|
||||
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;
|
||||
try:
|
||||
offset = index * self.data_size
|
||||
return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type)
|
||||
except:
|
||||
return None
|
||||
# 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)
|
||||
if (num_children % self.data_size) != 0:
|
||||
return 0
|
||||
else:
|
||||
num_children = num_children / self.data_size
|
||||
return num_children
|
||||
except:
|
||||
return 0
|
||||
|
||||
def update(self):
|
||||
# preemptively setting this to None - we might end up changing our mind later
|
||||
self.count = None
|
||||
try:
|
||||
impl = self.valobj.GetChildMemberWithName('_M_impl')
|
||||
self.start = impl.GetChildMemberWithName('_M_start')
|
||||
self.finish = impl.GetChildMemberWithName('_M_finish')
|
||||
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():
|
||||
self.count = None
|
||||
else:
|
||||
self.count = 0
|
||||
except:
|
||||
pass
|
||||
return True
|
||||
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
|
||||
try:
|
||||
offset = index * self.data_size
|
||||
return self.start.CreateChildAtOffset(
|
||||
'[' + str(index) + ']', offset, self.data_type)
|
||||
except:
|
||||
return None
|
||||
|
||||
class StdVBoolImplementation(object):
|
||||
def __init__(self, valobj, bool_type):
|
||||
self.valobj = valobj
|
||||
self.bool_type = bool_type
|
||||
self.valid = False
|
||||
def update(self):
|
||||
# preemptively setting this to None - we might end up changing our
|
||||
# mind later
|
||||
self.count = None
|
||||
try:
|
||||
impl = self.valobj.GetChildMemberWithName('_M_impl')
|
||||
self.start = impl.GetChildMemberWithName('_M_start')
|
||||
self.finish = impl.GetChildMemberWithName('_M_finish')
|
||||
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():
|
||||
self.count = None
|
||||
else:
|
||||
self.count = 0
|
||||
except:
|
||||
pass
|
||||
return True
|
||||
|
||||
def num_children(self):
|
||||
if self.valid:
|
||||
start = self.start_p.GetValueAsUnsigned(0)
|
||||
finish = self.finish_p.GetValueAsUnsigned(0)
|
||||
offset = self.offset.GetValueAsUnsigned(0)
|
||||
if finish >= start:
|
||||
return (finish - start) * 8 + offset
|
||||
return 0
|
||||
class StdVBoolImplementation(object):
|
||||
|
||||
def get_child_at_index(self, index):
|
||||
if index >= self.num_children():
|
||||
return None
|
||||
element_type = self.start_p.GetType().GetPointeeType()
|
||||
element_bits = 8 * 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)
|
||||
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)
|
||||
def __init__(self, valobj, bool_type):
|
||||
self.valobj = valobj
|
||||
self.bool_type = bool_type
|
||||
self.valid = False
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
m_impl = self.valobj.GetChildMemberWithName('_M_impl')
|
||||
self.m_start = m_impl.GetChildMemberWithName('_M_start')
|
||||
self.m_finish = m_impl.GetChildMemberWithName('_M_finish')
|
||||
self.start_p = self.m_start.GetChildMemberWithName('_M_p')
|
||||
self.finish_p = self.m_finish.GetChildMemberWithName('_M_p')
|
||||
self.offset = self.m_finish.GetChildMemberWithName('_M_offset')
|
||||
self.valid = True
|
||||
except:
|
||||
self.valid = False
|
||||
return True
|
||||
def num_children(self):
|
||||
if self.valid:
|
||||
start = self.start_p.GetValueAsUnsigned(0)
|
||||
finish = self.finish_p.GetValueAsUnsigned(0)
|
||||
offset = self.offset.GetValueAsUnsigned(0)
|
||||
if finish >= start:
|
||||
return (finish - start) * 8 + offset
|
||||
return 0
|
||||
|
||||
def __init__(self, valobj, dict):
|
||||
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)
|
||||
else:
|
||||
self.impl = self.StdVectorImplementation(valobj)
|
||||
logger >> "Providing synthetic children for a vector named " + str(valobj.GetName())
|
||||
def get_child_at_index(self, index):
|
||||
if index >= self.num_children():
|
||||
return None
|
||||
element_type = self.start_p.GetType().GetPointeeType()
|
||||
element_bits = 8 * 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)
|
||||
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)
|
||||
|
||||
def num_children(self):
|
||||
return self.impl.num_children()
|
||||
def update(self):
|
||||
try:
|
||||
m_impl = self.valobj.GetChildMemberWithName('_M_impl')
|
||||
self.m_start = m_impl.GetChildMemberWithName('_M_start')
|
||||
self.m_finish = m_impl.GetChildMemberWithName('_M_finish')
|
||||
self.start_p = self.m_start.GetChildMemberWithName('_M_p')
|
||||
self.finish_p = self.m_finish.GetChildMemberWithName('_M_p')
|
||||
self.offset = self.m_finish.GetChildMemberWithName('_M_offset')
|
||||
self.valid = True
|
||||
except:
|
||||
self.valid = False
|
||||
return True
|
||||
|
||||
def get_child_index(self,name):
|
||||
try:
|
||||
return int(name.lstrip('[').rstrip(']'))
|
||||
except:
|
||||
return -1
|
||||
def __init__(self, valobj, dict):
|
||||
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)
|
||||
else:
|
||||
self.impl = self.StdVectorImplementation(valobj)
|
||||
logger >> "Providing synthetic children for a vector named " + \
|
||||
str(valobj.GetName())
|
||||
|
||||
def get_child_at_index(self, index):
|
||||
return self.impl.get_child_at_index(index)
|
||||
def num_children(self):
|
||||
return self.impl.num_children()
|
||||
|
||||
def update(self):
|
||||
return self.impl.update()
|
||||
def get_child_index(self, name):
|
||||
try:
|
||||
return int(name.lstrip('[').rstrip(']'))
|
||||
except:
|
||||
return -1
|
||||
|
||||
def has_children(self):
|
||||
return True
|
||||
def get_child_at_index(self, index):
|
||||
return self.impl.get_child_at_index(index)
|
||||
|
||||
def update(self):
|
||||
return self.impl.update()
|
||||
|
||||
def has_children(self):
|
||||
return True
|
||||
|
||||
|
||||
class StdMapSynthProvider:
|
||||
|
||||
def __init__(self, valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj;
|
||||
self.count = None
|
||||
logger >> "Providing synthetic children for a map named " + str(valobj.GetName())
|
||||
def __init__(self, valobj, dict):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.valobj = valobj
|
||||
self.count = None
|
||||
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
|
||||
# arguments for _Rep_Type _M_t in the map itself - because we have to make up the
|
||||
# typename and then find it, we may hit the situation were std::string has multiple
|
||||
# names but only one is actually referenced in the debug information. hence, we need
|
||||
# to replace the longer versions of std::string with the shorter one in order to be able
|
||||
# to find the type name
|
||||
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
|
||||
if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
|
||||
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
|
||||
if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
|
||||
return 'std::basic_string<char>',True
|
||||
return class_name,False
|
||||
# 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
|
||||
# arguments for _Rep_Type _M_t in the map itself - because we have to make up the
|
||||
# typename and then find it, we may hit the situation were std::string has multiple
|
||||
# names but only one is actually referenced in the debug information. hence, we need
|
||||
# to replace the longer versions of std::string with the shorter one in order to be able
|
||||
# to find the type name
|
||||
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
|
||||
if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
|
||||
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
|
||||
if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
|
||||
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
|
||||
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
|
||||
self.garbage = False
|
||||
self.Mt = self.valobj.GetChildMemberWithName('_M_t')
|
||||
self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl')
|
||||
self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header')
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
# 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
|
||||
self.garbage = False
|
||||
self.Mt = self.valobj.GetChildMemberWithName('_M_t')
|
||||
self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl')
|
||||
self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header')
|
||||
|
||||
map_type = self.valobj.GetType()
|
||||
if map_type.IsReferenceType():
|
||||
logger >> "Dereferencing type"
|
||||
map_type = map_type.GetDereferencedType()
|
||||
map_type = self.valobj.GetType()
|
||||
if map_type.IsReferenceType():
|
||||
logger >> "Dereferencing type"
|
||||
map_type = map_type.GetDereferencedType()
|
||||
|
||||
# Get the type of std::pair<key, value>. It is the first template
|
||||
# argument type of the 4th template argument to std::map.
|
||||
allocator_type = map_type.GetTemplateArgumentType(3)
|
||||
self.data_type = allocator_type.GetTemplateArgumentType(0)
|
||||
if not self.data_type:
|
||||
# GCC does not emit DW_TAG_template_type_parameter for
|
||||
# std::allocator<...>. For such a case, get the type of
|
||||
# std::pair from a member of std::map.
|
||||
rep_type = self.valobj.GetChildMemberWithName('_M_t').GetType()
|
||||
self.data_type = rep_type.GetTypedefedType().GetTemplateArgumentType(1)
|
||||
# Get the type of std::pair<key, value>. It is the first template
|
||||
# argument type of the 4th template argument to std::map.
|
||||
allocator_type = map_type.GetTemplateArgumentType(3)
|
||||
self.data_type = allocator_type.GetTemplateArgumentType(0)
|
||||
if not self.data_type:
|
||||
# GCC does not emit DW_TAG_template_type_parameter for
|
||||
# std::allocator<...>. For such a case, get the type of
|
||||
# std::pair from a member of std::map.
|
||||
rep_type = self.valobj.GetChildMemberWithName('_M_t').GetType()
|
||||
self.data_type = rep_type.GetTypedefedType().GetTemplateArgumentType(1)
|
||||
|
||||
# from libstdc++ implementation of _M_root for rbtree
|
||||
self.Mroot = self.Mheader.GetChildMemberWithName('_M_parent')
|
||||
self.data_size = self.data_type.GetByteSize()
|
||||
self.skip_size = self.Mheader.GetType().GetByteSize()
|
||||
except:
|
||||
pass
|
||||
# from libstdc++ implementation of _M_root for rbtree
|
||||
self.Mroot = self.Mheader.GetChildMemberWithName('_M_parent')
|
||||
self.data_size = self.data_type.GetByteSize()
|
||||
self.skip_size = self.Mheader.GetType().GetByteSize()
|
||||
except:
|
||||
pass
|
||||
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.count == None:
|
||||
self.count = self.num_children_impl()
|
||||
return self.count
|
||||
def num_children(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
if self.count is None:
|
||||
self.count = self.num_children_impl()
|
||||
return self.count
|
||||
|
||||
def num_children_impl(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
logger >> "I have " + str(count) + " children available"
|
||||
return count
|
||||
except:
|
||||
return 0;
|
||||
def num_children_impl(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
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)
|
||||
logger >> "I have " + str(count) + " children available"
|
||||
return count
|
||||
except:
|
||||
return 0
|
||||
|
||||
def get_child_index(self,name):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
try:
|
||||
return int(name.lstrip('[').rstrip(']'))
|
||||
except:
|
||||
return -1
|
||||
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):
|
||||
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;
|
||||
if self.garbage:
|
||||
logger >> "Returning None since we are a garbage tree"
|
||||
return None
|
||||
try:
|
||||
offset = index
|
||||
current = self.left(self.Mheader);
|
||||
while offset > 0:
|
||||
current = self.increment_node(current)
|
||||
offset = offset - 1;
|
||||
# skip all the base stuff and get at the data
|
||||
return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type)
|
||||
except:
|
||||
return None
|
||||
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
|
||||
if self.garbage:
|
||||
logger >> "Returning None since we are a garbage tree"
|
||||
return None
|
||||
try:
|
||||
offset = index
|
||||
current = self.left(self.Mheader)
|
||||
while offset > 0:
|
||||
current = self.increment_node(current)
|
||||
offset = offset - 1
|
||||
# skip all the base stuff and get at the data
|
||||
return current.CreateChildAtOffset(
|
||||
'[' + str(index) + ']', self.skip_size, self.data_type)
|
||||
except:
|
||||
return None
|
||||
|
||||
# utility functions
|
||||
def node_ptr_value(self,node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return node.GetValueAsUnsigned(0)
|
||||
# utility functions
|
||||
def node_ptr_value(self, node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return node.GetValueAsUnsigned(0)
|
||||
|
||||
def right(self,node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return node.GetChildMemberWithName("_M_right");
|
||||
def right(self, node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return node.GetChildMemberWithName("_M_right")
|
||||
|
||||
def left(self,node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return node.GetChildMemberWithName("_M_left");
|
||||
def left(self, node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return node.GetChildMemberWithName("_M_left")
|
||||
|
||||
def parent(self,node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return node.GetChildMemberWithName("_M_parent");
|
||||
def parent(self, node):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
return node.GetChildMemberWithName("_M_parent")
|
||||
|
||||
# from libstdc++ implementation of iterator for rbtree
|
||||
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);
|
||||
max_steps -= 1
|
||||
while self.node_ptr_value(self.left(x)) != 0:
|
||||
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;
|
||||
else:
|
||||
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);
|
||||
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;
|
||||
# from libstdc++ implementation of iterator for rbtree
|
||||
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)
|
||||
max_steps -= 1
|
||||
while self.node_ptr_value(self.left(x)) != 0:
|
||||
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
|
||||
else:
|
||||
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)
|
||||
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
|
||||
|
||||
def has_children(self):
|
||||
return True
|
||||
def has_children(self):
|
||||
return True
|
||||
|
||||
_list_uses_loop_detector = True
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,109 +2,123 @@ import lldb
|
|||
|
||||
_map_capping_size = 255
|
||||
|
||||
|
||||
class libcxx_hash_table_SynthProvider:
|
||||
def __init__(self, valobj, dict):
|
||||
self.valobj = valobj
|
||||
self.num_elements = None
|
||||
self.next_element = None
|
||||
self.bucket_count = None
|
||||
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.num_elements = None
|
||||
self.next_element = None
|
||||
self.bucket_count = None
|
||||
try:
|
||||
# unordered_map is made up of a hash_map, which has 4 pieces in it:
|
||||
# bucket list :
|
||||
# array of buckets
|
||||
# p1 (pair):
|
||||
# first - pointer to first loaded element
|
||||
# p2 (pair):
|
||||
# first - number of elements
|
||||
# second - hash function
|
||||
# p3 (pair):
|
||||
# first - max_load_factor
|
||||
# second - equality operator function
|
||||
#
|
||||
# For display, we actually don't need to go inside the buckets, since 'p1' has a way to iterate over all
|
||||
# the elements directly.
|
||||
#
|
||||
# We will calculate other values about the map because they will be useful for the summary.
|
||||
#
|
||||
table = self.valobj.GetChildMemberWithName('__table_')
|
||||
def __init__(self, valobj, dict):
|
||||
self.valobj = valobj
|
||||
self.num_elements = None
|
||||
self.next_element = None
|
||||
self.bucket_count = None
|
||||
|
||||
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
|
||||
def update(self):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
self.num_elements = None
|
||||
self.next_element = None
|
||||
self.bucket_count = None
|
||||
try:
|
||||
# unordered_map is made up of a hash_map, which has 4 pieces in it:
|
||||
# bucket list :
|
||||
# array of buckets
|
||||
# p1 (pair):
|
||||
# first - pointer to first loaded element
|
||||
# p2 (pair):
|
||||
# first - number of elements
|
||||
# second - hash function
|
||||
# p3 (pair):
|
||||
# first - max_load_factor
|
||||
# second - equality operator function
|
||||
#
|
||||
# For display, we actually don't need to go inside the buckets, since 'p1' has a way to iterate over all
|
||||
# the elements directly.
|
||||
#
|
||||
# We will calculate other values about the map because they will be useful for the summary.
|
||||
#
|
||||
table = self.valobj.GetChildMemberWithName('__table_')
|
||||
|
||||
self.begin_ptr = table.GetChildMemberWithName('__p1_').GetChildMemberWithName('__first_').GetChildMemberWithName('__next_')
|
||||
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.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
|
||||
self.begin_ptr = table.GetChildMemberWithName('__p1_').GetChildMemberWithName(
|
||||
'__first_').GetChildMemberWithName('__next_')
|
||||
|
||||
# save the pointers as we get them
|
||||
# -- don't access this first element if num_element==0!
|
||||
self.elements_cache = []
|
||||
if self.num_elements:
|
||||
self.next_element = self.begin_ptr
|
||||
else:
|
||||
self.next_element = None
|
||||
except Exception as e:
|
||||
logger >> "Caught exception: %r" % e
|
||||
pass
|
||||
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
|
||||
|
||||
def num_children(self):
|
||||
global _map_capping_size
|
||||
num_elements = self.num_elements
|
||||
if num_elements is not None:
|
||||
if num_elements > _map_capping_size:
|
||||
num_elements = _map_capping_size
|
||||
return num_elements
|
||||
# save the pointers as we get them
|
||||
# -- don't access this first element if num_element==0!
|
||||
self.elements_cache = []
|
||||
if self.num_elements:
|
||||
self.next_element = self.begin_ptr
|
||||
else:
|
||||
self.next_element = None
|
||||
except Exception as e:
|
||||
logger >> "Caught exception: %r" % e
|
||||
pass
|
||||
|
||||
def has_children(self):
|
||||
return True
|
||||
def num_children(self):
|
||||
global _map_capping_size
|
||||
num_elements = self.num_elements
|
||||
if num_elements is not None:
|
||||
if num_elements > _map_capping_size:
|
||||
num_elements = _map_capping_size
|
||||
return num_elements
|
||||
|
||||
def get_child_index(self,name):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
try:
|
||||
return int(name.lstrip('[').rstrip(']'))
|
||||
except:
|
||||
return -1
|
||||
def has_children(self):
|
||||
return True
|
||||
|
||||
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
|
||||
def get_child_index(self, name):
|
||||
logger = lldb.formatters.Logger.Logger()
|
||||
try:
|
||||
return int(name.lstrip('[').rstrip(']'))
|
||||
except:
|
||||
return -1
|
||||
|
||||
# extend
|
||||
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:
|
||||
logger >> " : hit end of list"
|
||||
return None
|
||||
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
|
||||
|
||||
node = self.next_element.Dereference()
|
||||
# extend
|
||||
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:
|
||||
logger >> " : hit end of list"
|
||||
return None
|
||||
|
||||
value = node.GetChildMemberWithName('__value_')
|
||||
hash_value = node.GetChildMemberWithName('__hash_').GetValueAsUnsigned()
|
||||
self.elements_cache.append((value, hash_value))
|
||||
node = self.next_element.Dereference()
|
||||
|
||||
self.next_element = node.GetChildMemberWithName('__next_')
|
||||
if not self.next_element.GetValueAsUnsigned(0):
|
||||
self.next_element = None
|
||||
value = node.GetChildMemberWithName('__value_')
|
||||
hash_value = node.GetChildMemberWithName(
|
||||
'__hash_').GetValueAsUnsigned()
|
||||
self.elements_cache.append((value, hash_value))
|
||||
|
||||
# hit the index! so we have the value
|
||||
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())
|
||||
self.next_element = node.GetChildMemberWithName('__next_')
|
||||
if not self.next_element.GetValueAsUnsigned(0):
|
||||
self.next_element = None
|
||||
|
||||
# hit the index! so we have the value
|
||||
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())
|
||||
|
||||
|
||||
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')
|
||||
|
|
|
@ -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"
|
||||
|
@ -77,4 +77,4 @@
|
|||
#include "lldb/API/SBVariablesOptions.h"
|
||||
#include "lldb/API/SBWatchpoint.h"
|
||||
|
||||
#endif // LLDB_LLDB_h_
|
||||
#endif // LLDB_LLDB_h_
|
||||
|
|
|
@ -15,138 +15,108 @@
|
|||
|
||||
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);
|
||||
|
||||
// Create an address by resolving a load address using the supplied 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
|
||||
// might refer to something on the stack or heap. The following functions
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
// might refer to something on the stack or heap. The following functions
|
||||
// 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);
|
||||
// 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);
|
||||
// One or more bits from the SymbolContextItem enumerations can be logically
|
||||
// OR'ed together to more efficiently retrieve multiple symbol objects.
|
||||
|
||||
lldb::SBSection GetSection();
|
||||
|
||||
// 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);
|
||||
// One or more bits from the SymbolContextItem enumerations can be logically
|
||||
// OR'ed together to more efficiently retrieve multiple symbol objects.
|
||||
lldb::addr_t GetOffset();
|
||||
|
||||
lldb::SBSection
|
||||
GetSection ();
|
||||
lldb::SBModule GetModule();
|
||||
|
||||
lldb::addr_t
|
||||
GetOffset ();
|
||||
lldb::SBCompileUnit GetCompileUnit();
|
||||
|
||||
lldb::SBModule
|
||||
GetModule ();
|
||||
lldb::SBFunction GetFunction();
|
||||
|
||||
lldb::SBCompileUnit
|
||||
GetCompileUnit ();
|
||||
lldb::SBBlock GetBlock();
|
||||
|
||||
lldb::SBFunction
|
||||
GetFunction ();
|
||||
lldb::SBSymbol GetSymbol();
|
||||
|
||||
lldb::SBBlock
|
||||
GetBlock ();
|
||||
lldb::SBLineEntry GetLineEntry();
|
||||
|
||||
lldb::SBSymbol
|
||||
GetSymbol ();
|
||||
|
||||
lldb::SBLineEntry
|
||||
GetLineEntry ();
|
||||
|
||||
lldb::AddressClass
|
||||
GetAddressClass ();
|
||||
lldb::AddressClass GetAddressClass();
|
||||
|
||||
protected:
|
||||
friend class SBBlock;
|
||||
friend class SBBreakpointLocation;
|
||||
friend class SBFrame;
|
||||
friend class SBFunction;
|
||||
friend class SBLineEntry;
|
||||
friend class SBInstruction;
|
||||
friend class SBModule;
|
||||
friend class SBSection;
|
||||
friend class SBSymbol;
|
||||
friend class SBSymbolContext;
|
||||
friend class SBTarget;
|
||||
friend class SBThread;
|
||||
friend class SBThreadPlan;
|
||||
friend class SBValue;
|
||||
friend class SBQueueItem;
|
||||
|
||||
friend class SBBlock;
|
||||
friend class SBBreakpointLocation;
|
||||
friend class SBFrame;
|
||||
friend class SBFunction;
|
||||
friend class SBLineEntry;
|
||||
friend class SBInstruction;
|
||||
friend class SBModule;
|
||||
friend class SBSection;
|
||||
friend class SBSymbol;
|
||||
friend class SBSymbolContext;
|
||||
friend class SBTarget;
|
||||
friend class SBThread;
|
||||
friend class SBThreadPlan;
|
||||
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;
|
||||
std::unique_ptr<lldb_private::Address> m_opaque_ap;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBAddress_h_
|
||||
|
|
|
@ -16,209 +16,175 @@ 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.
|
||||
///
|
||||
/// This function implies that a future call to SBTarget::Attach(...)
|
||||
/// will be synchronous.
|
||||
///
|
||||
/// @param[in] path
|
||||
/// A full or partial name for the process to attach to.
|
||||
///
|
||||
/// @param[in] wait_for
|
||||
/// 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);
|
||||
//------------------------------------------------------------------
|
||||
/// Attach to a process by name.
|
||||
///
|
||||
/// This function implies that a future call to SBTarget::Attach(...)
|
||||
/// will be synchronous.
|
||||
///
|
||||
/// @param[in] path
|
||||
/// A full or partial name for the process to attach to.
|
||||
///
|
||||
/// @param[in] wait_for
|
||||
/// 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);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Attach to a process by name.
|
||||
///
|
||||
/// Future calls to SBTarget::Attach(...) will be synchronous or
|
||||
/// asynchronous depending on the \a async argument.
|
||||
///
|
||||
/// @param[in] path
|
||||
/// A full or partial name for the process to attach to.
|
||||
///
|
||||
/// @param[in] wait_for
|
||||
/// If \b false, attach to an existing process whose name matches.
|
||||
/// If \b true, then wait for the next process whose name matches.
|
||||
///
|
||||
/// @param[in] async
|
||||
/// If \b false, then the SBTarget::Attach(...) call will be a
|
||||
/// synchronous call with no way to cancel the attach in
|
||||
/// progress.
|
||||
/// If \b true, then the SBTarget::Attach(...) function will
|
||||
/// return immediately and clients are expected to wait for a
|
||||
/// process eStateStopped event if a suitable process is
|
||||
/// eventually found. If the client wants to cancel the event,
|
||||
/// SBProcess::Stop() can be called and an eStateExited process
|
||||
/// event will be delivered.
|
||||
//------------------------------------------------------------------
|
||||
SBAttachInfo (const char *path, bool wait_for, bool async);
|
||||
//------------------------------------------------------------------
|
||||
/// Attach to a process by name.
|
||||
///
|
||||
/// Future calls to SBTarget::Attach(...) will be synchronous or
|
||||
/// asynchronous depending on the \a async argument.
|
||||
///
|
||||
/// @param[in] path
|
||||
/// A full or partial name for the process to attach to.
|
||||
///
|
||||
/// @param[in] wait_for
|
||||
/// If \b false, attach to an existing process whose name matches.
|
||||
/// If \b true, then wait for the next process whose name matches.
|
||||
///
|
||||
/// @param[in] async
|
||||
/// If \b false, then the SBTarget::Attach(...) call will be a
|
||||
/// synchronous call with no way to cancel the attach in
|
||||
/// progress.
|
||||
/// If \b true, then the SBTarget::Attach(...) function will
|
||||
/// return immediately and clients are expected to wait for a
|
||||
/// process eStateStopped event if a suitable process is
|
||||
/// eventually found. If the client wants to cancel the event,
|
||||
/// SBProcess::Stop() can be called and an eStateExited process
|
||||
/// event will be delivered.
|
||||
//------------------------------------------------------------------
|
||||
SBAttachInfo(const char *path, bool wait_for, bool async);
|
||||
|
||||
SBAttachInfo (const SBAttachInfo &rhs);
|
||||
SBAttachInfo(const SBAttachInfo &rhs);
|
||||
|
||||
~SBAttachInfo();
|
||||
~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.
|
||||
///
|
||||
/// Designed to be used after a call to SBAttachInfo::SetExecutable().
|
||||
/// This function implies that a call to SBTarget::Attach(...) will
|
||||
/// be synchronous.
|
||||
///
|
||||
/// @param[in] wait_for
|
||||
/// 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);
|
||||
//------------------------------------------------------------------
|
||||
/// Set attach by process name settings.
|
||||
///
|
||||
/// Designed to be used after a call to SBAttachInfo::SetExecutable().
|
||||
/// This function implies that a call to SBTarget::Attach(...) will
|
||||
/// be synchronous.
|
||||
///
|
||||
/// @param[in] wait_for
|
||||
/// 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);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Set attach by process name settings.
|
||||
///
|
||||
/// Designed to be used after a call to SBAttachInfo::SetExecutable().
|
||||
/// Future calls to SBTarget::Attach(...) will be synchronous or
|
||||
/// asynchronous depending on the \a async argument.
|
||||
///
|
||||
/// @param[in] wait_for
|
||||
/// If \b false, attach to an existing process whose name matches.
|
||||
/// If \b true, then wait for the next process whose name matches.
|
||||
///
|
||||
/// @param[in] async
|
||||
/// If \b false, then the SBTarget::Attach(...) call will be a
|
||||
/// synchronous call with no way to cancel the attach in
|
||||
/// progress.
|
||||
/// If \b true, then the SBTarget::Attach(...) function will
|
||||
/// return immediately and clients are expected to wait for a
|
||||
/// process eStateStopped event if a suitable process is
|
||||
/// eventually found. If the client wants to cancel the event,
|
||||
/// SBProcess::Stop() can be called and an eStateExited process
|
||||
/// event will be delivered.
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
SetWaitForLaunch (bool b, bool async);
|
||||
//------------------------------------------------------------------
|
||||
/// Set attach by process name settings.
|
||||
///
|
||||
/// Designed to be used after a call to SBAttachInfo::SetExecutable().
|
||||
/// Future calls to SBTarget::Attach(...) will be synchronous or
|
||||
/// asynchronous depending on the \a async argument.
|
||||
///
|
||||
/// @param[in] wait_for
|
||||
/// If \b false, attach to an existing process whose name matches.
|
||||
/// If \b true, then wait for the next process whose name matches.
|
||||
///
|
||||
/// @param[in] async
|
||||
/// If \b false, then the SBTarget::Attach(...) call will be a
|
||||
/// synchronous call with no way to cancel the attach in
|
||||
/// progress.
|
||||
/// If \b true, then the SBTarget::Attach(...) function will
|
||||
/// return immediately and clients are expected to wait for a
|
||||
/// process eStateStopped event if a suitable process is
|
||||
/// eventually found. If the client wants to cancel the event,
|
||||
/// SBProcess::Stop() can be called and an eStateExited process
|
||||
/// event will be delivered.
|
||||
//------------------------------------------------------------------
|
||||
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.
|
||||
///
|
||||
/// If no listener has been set via a call to
|
||||
/// SBLaunchInfo::SetListener(), then an invalid SBListener will be
|
||||
/// returned (SBListener::IsValid() will return false). If a listener
|
||||
/// has been set, then the valid listener object will be returned.
|
||||
//----------------------------------------------------------------------
|
||||
SBListener
|
||||
GetListener ();
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// Set the listener that will be used to receive process events.
|
||||
///
|
||||
/// By default the SBDebugger, which has a listener, that the SBTarget
|
||||
/// 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);
|
||||
//----------------------------------------------------------------------
|
||||
/// Get the listener that will be used to receive process events.
|
||||
///
|
||||
/// If no listener has been set via a call to
|
||||
/// SBLaunchInfo::SetListener(), then an invalid SBListener will be
|
||||
/// returned (SBListener::IsValid() will return false). If a listener
|
||||
/// has been set, then the valid listener object will be returned.
|
||||
//----------------------------------------------------------------------
|
||||
SBListener GetListener();
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// Set the listener that will be used to receive process events.
|
||||
///
|
||||
/// By default the SBDebugger, which has a listener, that the SBTarget
|
||||
/// 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);
|
||||
|
||||
protected:
|
||||
friend class SBTarget;
|
||||
friend class SBTarget;
|
||||
|
||||
lldb_private::ProcessAttachInfo &
|
||||
ref ();
|
||||
lldb_private::ProcessAttachInfo &ref();
|
||||
|
||||
ProcessAttachInfoSP m_opaque_sp;
|
||||
ProcessAttachInfoSP m_opaque_sp;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBAttachInfo_h_
|
||||
#endif // LLDB_SBAttachInfo_h_
|
||||
|
|
|
@ -17,107 +17,80 @@
|
|||
|
||||
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::DynamicValueType use_dynamic);
|
||||
|
||||
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);
|
||||
//------------------------------------------------------------------
|
||||
/// Get the inlined block that contains this block.
|
||||
///
|
||||
/// @return
|
||||
/// If this block is inlined, it will return this block, else
|
||||
/// parent blocks will be searched to see if any contain this
|
||||
/// block and are themselves inlined. An invalid SBBlock will
|
||||
/// be returned if this block nor any parent blocks are inlined
|
||||
/// function blocks.
|
||||
//------------------------------------------------------------------
|
||||
lldb::SBBlock GetContainingInlinedBlock();
|
||||
|
||||
lldb::SBValueList
|
||||
GetVariables (lldb::SBTarget& target,
|
||||
bool arguments,
|
||||
bool locals,
|
||||
bool statics);
|
||||
//------------------------------------------------------------------
|
||||
/// Get the inlined block that contains this block.
|
||||
///
|
||||
/// @return
|
||||
/// If this block is inlined, it will return this block, else
|
||||
/// parent blocks will be searched to see if any contain this
|
||||
/// block and are themselves inlined. An invalid SBBlock will
|
||||
/// be returned if this block nor any parent blocks are inlined
|
||||
/// function blocks.
|
||||
//------------------------------------------------------------------
|
||||
lldb::SBBlock
|
||||
GetContainingInlinedBlock ();
|
||||
|
||||
bool
|
||||
GetDescription (lldb::SBStream &description);
|
||||
bool GetDescription(lldb::SBStream &description);
|
||||
|
||||
private:
|
||||
friend class SBAddress;
|
||||
friend class SBFrame;
|
||||
friend class SBFunction;
|
||||
friend class SBSymbolContext;
|
||||
friend class SBAddress;
|
||||
friend class SBFrame;
|
||||
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;
|
||||
lldb_private::Block *m_opaque_ptr;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBBlock_h_
|
||||
|
|
|
@ -14,180 +14,131 @@
|
|||
|
||||
namespace lldb {
|
||||
|
||||
class LLDB_API SBBreakpoint
|
||||
{
|
||||
class LLDB_API SBBreakpoint {
|
||||
public:
|
||||
typedef bool (*BreakpointHitCallback)(void *baton, SBProcess &process,
|
||||
SBThread &thread,
|
||||
lldb::SBBreakpointLocation &location);
|
||||
|
||||
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();
|
||||
|
||||
~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);
|
||||
|
||||
// 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);
|
||||
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);
|
||||
|
||||
static lldb::BreakpointEventType
|
||||
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);
|
||||
|
||||
static uint32_t
|
||||
GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event_sp);
|
||||
static lldb::SBBreakpointLocation
|
||||
GetBreakpointLocationAtIndexFromEvent(const lldb::SBEvent &event,
|
||||
uint32_t loc_idx);
|
||||
|
||||
static uint32_t
|
||||
GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event_sp);
|
||||
|
||||
private:
|
||||
friend class SBBreakpointLocation;
|
||||
friend class SBTarget;
|
||||
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;
|
||||
lldb::BreakpointSP m_opaque_sp;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBBreakpoint_h_
|
||||
#endif // LLDB_SBBreakpoint_h_
|
||||
|
|
|
@ -10,105 +10,78 @@
|
|||
#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);
|
||||
|
||||
const lldb::SBBreakpointLocation &
|
||||
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;
|
||||
friend class SBBreakpoint;
|
||||
|
||||
void
|
||||
SetLocation (const lldb::BreakpointLocationSP &break_loc_sp);
|
||||
|
||||
lldb::BreakpointLocationSP m_opaque_sp;
|
||||
void SetLocation(const lldb::BreakpointLocationSP &break_loc_sp);
|
||||
|
||||
lldb::BreakpointLocationSP m_opaque_sp;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBBreakpointLocation_h_
|
||||
#endif // LLDB_SBBreakpointLocation_h_
|
||||
|
|
|
@ -14,84 +14,70 @@
|
|||
|
||||
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();
|
||||
~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;
|
||||
// This comparison is checking if the internal opaque pointer value
|
||||
// is equal to that in "rhs".
|
||||
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;
|
||||
// This comparison is checking if the internal opaque pointer value
|
||||
// is not equal to that in "rhs".
|
||||
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;
|
||||
// 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;
|
||||
|
||||
protected:
|
||||
friend class SBCommandInterpreter;
|
||||
friend class SBCommunication;
|
||||
friend class SBEvent;
|
||||
friend class SBListener;
|
||||
friend class SBProcess;
|
||||
friend class SBTarget;
|
||||
friend class SBCommandInterpreter;
|
||||
friend class SBCommunication;
|
||||
friend class SBEvent;
|
||||
friend class SBListener;
|
||||
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;
|
||||
lldb_private::Broadcaster *m_opaque_ptr;
|
||||
lldb::BroadcasterSP m_opaque_sp;
|
||||
lldb_private::Broadcaster *m_opaque_ptr;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBBroadcaster_h_
|
||||
#endif // LLDB_SBBroadcaster_h_
|
||||
|
|
|
@ -16,311 +16,267 @@
|
|||
|
||||
// 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();
|
||||
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;
|
||||
// This is set in the constructor and will always be valid.
|
||||
mutable std::unique_ptr<lldb_private::CommandInterpreterRunOptions>
|
||||
m_opaque_up;
|
||||
};
|
||||
|
||||
class SBCommandInterpreter
|
||||
{
|
||||
class SBCommandInterpreter {
|
||||
public:
|
||||
enum
|
||||
{
|
||||
eBroadcastBitThreadShouldExit = (1 << 0),
|
||||
eBroadcastBitResetPrompt = (1 << 1),
|
||||
eBroadcastBitQuitCommandReceived = (1 << 2), // User entered quit
|
||||
eBroadcastBitAsynchronousOutputData = (1 << 3),
|
||||
eBroadcastBitAsynchronousErrorData = (1 << 4)
|
||||
};
|
||||
enum {
|
||||
eBroadcastBitThreadShouldExit = (1 << 0),
|
||||
eBroadcastBitResetPrompt = (1 << 1),
|
||||
eBroadcastBitQuitCommandReceived = (1 << 2), // User entered quit
|
||||
eBroadcastBitAsynchronousOutputData = (1 << 3),
|
||||
eBroadcastBitAsynchronousErrorData = (1 << 4)
|
||||
};
|
||||
|
||||
SBCommandInterpreter (const lldb::SBCommandInterpreter &rhs);
|
||||
SBCommandInterpreter(const lldb::SBCommandInterpreter &rhs);
|
||||
|
||||
~SBCommandInterpreter ();
|
||||
~SBCommandInterpreter();
|
||||
|
||||
const lldb::SBCommandInterpreter &
|
||||
operator = (const lldb::SBCommandInterpreter &rhs);
|
||||
const lldb::SBCommandInterpreter &
|
||||
operator=(const lldb::SBCommandInterpreter &rhs);
|
||||
|
||||
static const char *
|
||||
GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type);
|
||||
static const char *
|
||||
GetArgumentTypeAsCString(const lldb::CommandArgumentType arg_type);
|
||||
|
||||
static const char *
|
||||
GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type);
|
||||
static const char *
|
||||
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);
|
||||
|
||||
void
|
||||
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,
|
||||
lldb::SBExecutionContext &override_context,
|
||||
lldb::SBCommandInterpreterRunOptions &options,
|
||||
lldb::SBCommandReturnObject result);
|
||||
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
|
||||
// and you can't do that in a scripting language interface in general...
|
||||
// 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
|
||||
// type further to disambiguate.
|
||||
// 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,
|
||||
lldb::SBStringList &matches);
|
||||
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,
|
||||
lldb::CommandOverrideCallback callback,
|
||||
void *baton);
|
||||
// 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,
|
||||
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.
|
||||
///
|
||||
/// This indicates that any input coming into the debugger handles will
|
||||
/// go to the command interpreter and will result in LLDB command line
|
||||
/// commands being executed.
|
||||
//----------------------------------------------------------------------
|
||||
bool
|
||||
IsActive ();
|
||||
//----------------------------------------------------------------------
|
||||
/// Return true if the command interpreter is the active IO handler.
|
||||
///
|
||||
/// This indicates that any input coming into the debugger handles will
|
||||
/// go to the command interpreter and will result in LLDB command line
|
||||
/// commands being executed.
|
||||
//----------------------------------------------------------------------
|
||||
bool IsActive();
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// Get the string that needs to be written to the debugger stdin file
|
||||
/// handle when a control character is typed.
|
||||
///
|
||||
/// Some GUI programs will intercept "control + char" sequences and want
|
||||
/// to have them do what normally would happen when using a real
|
||||
/// terminal, so this function allows GUI programs to emulate this
|
||||
/// functionality.
|
||||
///
|
||||
/// @param[in] ch
|
||||
/// The character that was typed along with the control key
|
||||
///
|
||||
/// @return
|
||||
/// The string that should be written into the file handle that is
|
||||
/// feeding the input stream for the debugger, or nullptr if there is
|
||||
/// no string for this control key.
|
||||
//----------------------------------------------------------------------
|
||||
const char *
|
||||
GetIOHandlerControlSequence(char ch);
|
||||
//----------------------------------------------------------------------
|
||||
/// Get the string that needs to be written to the debugger stdin file
|
||||
/// handle when a control character is typed.
|
||||
///
|
||||
/// Some GUI programs will intercept "control + char" sequences and want
|
||||
/// to have them do what normally would happen when using a real
|
||||
/// terminal, so this function allows GUI programs to emulate this
|
||||
/// functionality.
|
||||
///
|
||||
/// @param[in] ch
|
||||
/// The character that was typed along with the control key
|
||||
///
|
||||
/// @return
|
||||
/// The string that should be written into the file handle that is
|
||||
/// feeding the input stream for the debugger, or nullptr if there is
|
||||
/// no string for this control key.
|
||||
//----------------------------------------------------------------------
|
||||
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);
|
||||
//----------------------------------------------------------------------
|
||||
/// 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);
|
||||
|
||||
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;
|
||||
friend class SBDebugger;
|
||||
|
||||
static void
|
||||
InitializeSWIG ();
|
||||
static void InitializeSWIG();
|
||||
|
||||
lldb_private::CommandInterpreter *m_opaque_ptr;
|
||||
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*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
friend class SBDebugger;
|
||||
friend class SBCommandInterpreter;
|
||||
|
||||
SBCommand (lldb::CommandObjectSP cmd_sp);
|
||||
SBCommand(lldb::CommandObjectSP cmd_sp);
|
||||
|
||||
lldb::CommandObjectSP m_opaque_sp;
|
||||
lldb::CommandObjectSP m_opaque_sp;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
|
|
@ -22,122 +22,90 @@
|
|||
|
||||
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);
|
||||
const lldb::SBCommandReturnObject &
|
||||
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);
|
||||
// deprecated, these two functions do not take
|
||||
// ownership of file handle
|
||||
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,
|
||||
const char *fallback_error_cstr = nullptr);
|
||||
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;
|
||||
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;
|
||||
std::unique_ptr<lldb_private::CommandReturnObject> m_opaque_ap;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
|
|
@ -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();
|
||||
|
||||
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,
|
||||
lldb::ConnectionStatus &status);
|
||||
|
||||
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
|
||||
SetReadThreadBytesReceivedCallback (ReadThreadBytesReceived callback,
|
||||
void *callback_baton);
|
||||
bool ReadThreadIsRunning();
|
||||
|
||||
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;
|
||||
lldb_private::Communication *m_opaque;
|
||||
bool m_opaque_owned;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBCommunication_h_
|
||||
|
|
|
@ -15,105 +15,82 @@
|
|||
|
||||
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,
|
||||
lldb::SBFileSpec *inline_file_spec) const;
|
||||
|
||||
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,
|
||||
lldb::SBFileSpec *inline_file_spec,
|
||||
bool exact) const;
|
||||
|
||||
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
|
||||
/// compile unit.
|
||||
///
|
||||
/// @param[in] type_mask
|
||||
/// A bitfield that consists of one or more bits logically OR'ed
|
||||
/// together from the lldb::TypeClass enumeration. This allows
|
||||
/// you to request only structure types, or only class, struct
|
||||
/// and union types. Passing in lldb::eTypeClassAny will return
|
||||
/// all types found in the debug information for this compile
|
||||
/// unit.
|
||||
///
|
||||
/// @return
|
||||
/// A list of types in this compile unit that match \a type_mask
|
||||
//------------------------------------------------------------------
|
||||
lldb::SBTypeList GetTypes(uint32_t type_mask = lldb::eTypeClassAny);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get all types matching \a type_mask from debug info in this
|
||||
/// compile unit.
|
||||
///
|
||||
/// @param[in] type_mask
|
||||
/// A bitfield that consists of one or more bits logically OR'ed
|
||||
/// together from the lldb::TypeClass enumeration. This allows
|
||||
/// you to request only structure types, or only class, struct
|
||||
/// and union types. Passing in lldb::eTypeClassAny will return
|
||||
/// all types found in the debug information for this compile
|
||||
/// unit.
|
||||
///
|
||||
/// @return
|
||||
/// A list of types in this compile unit that match \a type_mask
|
||||
//------------------------------------------------------------------
|
||||
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;
|
||||
friend class SBFrame;
|
||||
friend class SBSymbolContext;
|
||||
friend class SBModule;
|
||||
friend class SBAddress;
|
||||
friend class SBFrame;
|
||||
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;
|
||||
lldb_private::CompileUnit *m_opaque_ptr;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBCompileUnit_h_
|
||||
|
|
|
@ -14,168 +14,143 @@
|
|||
|
||||
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 size);
|
||||
|
||||
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);
|
||||
|
||||
// see SetData() for why we don't have Append(const void* buf, size_t size)
|
||||
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;
|
||||
|
||||
// Mimic shared pointer...
|
||||
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;
|
||||
friend class SBProcess;
|
||||
friend class SBSection;
|
||||
friend class SBTarget;
|
||||
friend class SBValue;
|
||||
friend class SBInstruction;
|
||||
friend class SBProcess;
|
||||
friend class SBSection;
|
||||
friend class SBTarget;
|
||||
friend class SBValue;
|
||||
|
||||
lldb::DataExtractorSP m_opaque_sp;
|
||||
lldb::DataExtractorSP m_opaque_sp;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBData_h_
|
||||
|
|
|
@ -17,348 +17,254 @@
|
|||
|
||||
namespace lldb {
|
||||
|
||||
class LLDB_API SBInputReader
|
||||
{
|
||||
class LLDB_API SBInputReader {
|
||||
public:
|
||||
SBInputReader() = default;
|
||||
~SBInputReader() = default;
|
||||
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);
|
||||
void SetIsDone(bool);
|
||||
bool IsActive() const;
|
||||
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();
|
||||
SBDebugger();
|
||||
|
||||
SBDebugger(const lldb::SBDebugger &rhs);
|
||||
SBDebugger(const lldb::SBDebugger &rhs);
|
||||
|
||||
SBDebugger(const lldb::DebuggerSP &debugger_sp);
|
||||
SBDebugger(const lldb::DebuggerSP &debugger_sp);
|
||||
|
||||
~SBDebugger();
|
||||
~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();
|
||||
// Deprecated, use the one that takes a source_init_files bool.
|
||||
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,
|
||||
const char *platform_name,
|
||||
bool add_dependent_modules,
|
||||
lldb::SBError& error);
|
||||
lldb::SBTarget CreateTarget(const char *filename, const char *target_triple,
|
||||
const char *platform_name,
|
||||
bool add_dependent_modules, lldb::SBError &error);
|
||||
|
||||
lldb::SBTarget
|
||||
CreateTargetWithFileAndTargetTriple (const char *filename,
|
||||
const char *target_triple);
|
||||
lldb::SBTarget CreateTargetWithFileAndTargetTriple(const char *filename,
|
||||
const char *target_triple);
|
||||
|
||||
lldb::SBTarget
|
||||
CreateTargetWithFileAndArch (const char *filename,
|
||||
const char *archname);
|
||||
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);
|
||||
// Return true if target is deleted from the target list of the debugger.
|
||||
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,
|
||||
const char *arch);
|
||||
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);
|
||||
// REMOVE: just for a quick fix, need to expose platforms through
|
||||
// SBPlatform from this class.
|
||||
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);
|
||||
// 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
|
||||
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);
|
||||
// DEPRECATED
|
||||
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);
|
||||
static lldb::SBStringList
|
||||
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,
|
||||
SBCommandInterpreterRunOptions &options,
|
||||
int &num_errors,
|
||||
bool &quit_requested,
|
||||
bool &stopped_for_crash);
|
||||
void RunCommandInterpreter(bool auto_handle_events, bool spawn_thread,
|
||||
SBCommandInterpreterRunOptions &options,
|
||||
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;
|
||||
friend class SBInputReader;
|
||||
friend class SBListener;
|
||||
friend class SBProcess;
|
||||
friend class SBSourceManager;
|
||||
friend class SBTarget;
|
||||
friend class SBCommandInterpreter;
|
||||
friend class SBInputReader;
|
||||
friend class SBListener;
|
||||
friend class SBProcess;
|
||||
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;
|
||||
lldb::DebuggerSP m_opaque_sp;
|
||||
|
||||
}; // class SBDebugger
|
||||
|
||||
|
|
|
@ -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:
|
||||
private:
|
||||
friend class SBValue;
|
||||
|
||||
lldb_private::Declaration *
|
||||
get ();
|
||||
const lldb_private::Declaration *operator->() const;
|
||||
|
||||
private:
|
||||
friend class SBValue;
|
||||
lldb_private::Declaration &ref();
|
||||
|
||||
const lldb_private::Declaration *
|
||||
operator->() const;
|
||||
const lldb_private::Declaration &ref() const;
|
||||
|
||||
lldb_private::Declaration &
|
||||
ref();
|
||||
SBDeclaration(const lldb_private::Declaration *lldb_object_ptr);
|
||||
|
||||
const lldb_private::Declaration &
|
||||
ref() const;
|
||||
|
||||
SBDeclaration (const lldb_private::Declaration *lldb_object_ptr);
|
||||
|
||||
void
|
||||
SetDeclaration (const lldb_private::Declaration &lldb_object_ref);
|
||||
|
||||
std::unique_ptr<lldb_private::Declaration> m_opaque_ap;
|
||||
};
|
||||
void SetDeclaration(const lldb_private::Declaration &lldb_object_ref);
|
||||
|
||||
std::unique_ptr<lldb_private::Declaration> m_opaque_ap;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
|
|
|
@ -96,7 +96,6 @@ class LLDB_API SBValueList;
|
|||
class LLDB_API SBVariablesOptions;
|
||||
class LLDB_API SBWatchpoint;
|
||||
class LLDB_API SBUnixSignals;
|
||||
|
||||
}
|
||||
|
||||
#endif // LLDB_SBDefines_h_
|
||||
#endif // LLDB_SBDefines_h_
|
||||
|
|
|
@ -16,94 +16,73 @@ namespace lldb {
|
|||
|
||||
class LLDB_API SBError {
|
||||
public:
|
||||
SBError ();
|
||||
SBError();
|
||||
|
||||
SBError (const lldb::SBError &rhs);
|
||||
SBError(const lldb::SBError &rhs);
|
||||
|
||||
~SBError();
|
||||
~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;
|
||||
friend class SBCommunication;
|
||||
friend class SBHostOS;
|
||||
friend class SBPlatform;
|
||||
friend class SBProcess;
|
||||
friend class SBStructuredData;
|
||||
friend class SBThread;
|
||||
friend class SBTarget;
|
||||
friend class SBValue;
|
||||
friend class SBWatchpoint;
|
||||
friend class SBBreakpoint;
|
||||
friend class SBBreakpointLocation;
|
||||
|
||||
friend class SBCommandReturnObject;
|
||||
friend class SBData;
|
||||
friend class SBDebugger;
|
||||
friend class SBCommunication;
|
||||
friend class SBHostOS;
|
||||
friend class SBPlatform;
|
||||
friend class SBProcess;
|
||||
friend class SBStructuredData;
|
||||
friend class SBThread;
|
||||
friend class SBTarget;
|
||||
friend class SBValue;
|
||||
friend class SBWatchpoint;
|
||||
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;
|
||||
std::unique_ptr<lldb_private::Error> m_opaque_ap;
|
||||
|
||||
void
|
||||
CreateIfNeeded ();
|
||||
void CreateIfNeeded();
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBError_h_
|
||||
|
|
|
@ -15,91 +15,72 @@
|
|||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace lldb {
|
||||
|
||||
class SBBroadcaster;
|
||||
|
||||
class LLDB_API SBEvent
|
||||
{
|
||||
class LLDB_API SBEvent {
|
||||
public:
|
||||
SBEvent();
|
||||
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);
|
||||
// Make an event that contains a C string.
|
||||
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();
|
||||
~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;
|
||||
friend class SBBroadcaster;
|
||||
friend class SBBreakpoint;
|
||||
friend class SBDebugger;
|
||||
friend class SBProcess;
|
||||
friend class SBTarget;
|
||||
friend class SBThread;
|
||||
friend class SBWatchpoint;
|
||||
friend class SBListener;
|
||||
friend class SBBroadcaster;
|
||||
friend class SBBreakpoint;
|
||||
friend class SBDebugger;
|
||||
friend class SBProcess;
|
||||
friend class SBTarget;
|
||||
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;
|
||||
mutable lldb::EventSP m_event_sp;
|
||||
mutable lldb_private::Event *m_opaque_ptr;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBEvent_h_
|
||||
#endif // LLDB_SBEvent_h_
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//===-- SBExecutionContext.h -----------------------------------------*- C++ -*-===//
|
||||
//===-- SBExecutionContext.h -----------------------------------------*- C++
|
||||
//-*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
@ -15,60 +16,51 @@
|
|||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace lldb {
|
||||
|
||||
class LLDB_API SBExecutionContext
|
||||
{
|
||||
friend class SBCommandInterpreter;
|
||||
class LLDB_API SBExecutionContext {
|
||||
friend class SBCommandInterpreter;
|
||||
|
||||
public:
|
||||
SBExecutionContext();
|
||||
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();
|
||||
~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;
|
||||
mutable lldb::ExecutionContextRefSP m_exe_ctx_sp;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBExecutionContext_h_
|
||||
#endif // LLDB_SBExecutionContext_h_
|
||||
|
|
|
@ -16,133 +16,100 @@
|
|||
|
||||
namespace lldb {
|
||||
|
||||
|
||||
class LLDB_API SBExpressionOptions
|
||||
{
|
||||
class LLDB_API SBExpressionOptions {
|
||||
public:
|
||||
SBExpressionOptions();
|
||||
SBExpressionOptions();
|
||||
|
||||
SBExpressionOptions (const lldb::SBExpressionOptions &rhs);
|
||||
SBExpressionOptions(const lldb::SBExpressionOptions &rhs);
|
||||
|
||||
~SBExpressionOptions();
|
||||
~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);
|
||||
// Set the timeout for the expression, 0 means wait forever.
|
||||
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
|
||||
// try to run the expression.
|
||||
void
|
||||
SetOneThreadTimeoutInMicroSeconds (uint32_t timeout = 0);
|
||||
// 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);
|
||||
|
||||
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;
|
||||
friend class SBTarget;
|
||||
friend class SBFrame;
|
||||
friend class SBValue;
|
||||
friend class SBTarget;
|
||||
|
||||
private:
|
||||
// This auto_pointer is made in the constructor and is always valid.
|
||||
mutable std::unique_ptr<lldb_private::EvaluateExpressionOptions> m_opaque_ap;
|
||||
// This auto_pointer is made in the constructor and is always valid.
|
||||
mutable std::unique_ptr<lldb_private::EvaluateExpressionOptions> m_opaque_ap;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBExpressionOptions_h_
|
||||
#endif // LLDB_SBExpressionOptions_h_
|
||||
|
|
|
@ -14,94 +14,76 @@
|
|||
|
||||
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;
|
||||
friend class SBBlock;
|
||||
friend class SBCommandInterpreter;
|
||||
friend class SBCompileUnit;
|
||||
friend class SBDeclaration;
|
||||
friend class SBFileSpecList;
|
||||
friend class SBHostOS;
|
||||
friend class SBLaunchInfo;
|
||||
friend class SBLineEntry;
|
||||
friend class SBModule;
|
||||
friend class SBModuleSpec;
|
||||
friend class SBPlatform;
|
||||
friend class SBProcess;
|
||||
friend class SBSourceManager;
|
||||
friend class SBThread;
|
||||
friend class SBTarget;
|
||||
friend class SBAttachInfo;
|
||||
friend class SBBlock;
|
||||
friend class SBCommandInterpreter;
|
||||
friend class SBCompileUnit;
|
||||
friend class SBDeclaration;
|
||||
friend class SBFileSpecList;
|
||||
friend class SBHostOS;
|
||||
friend class SBLaunchInfo;
|
||||
friend class SBLineEntry;
|
||||
friend class SBModule;
|
||||
friend class SBModuleSpec;
|
||||
friend class SBPlatform;
|
||||
friend class SBProcess;
|
||||
friend class SBSourceManager;
|
||||
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;
|
||||
std::unique_ptr<lldb_private::FileSpec> m_opaque_ap;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBFileSpec_h_
|
||||
|
|
|
@ -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;
|
||||
std::unique_ptr<lldb_private::FileSpecList> m_opaque_ap;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBFileSpecList_h_
|
||||
|
|
|
@ -15,227 +15,182 @@
|
|||
|
||||
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();
|
||||
~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;
|
||||
/// Gets the deepest block that contains the frame PC.
|
||||
///
|
||||
/// See also GetFrameBlock().
|
||||
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
|
||||
/// just looking at the SBFunction or SBSymbol for a frame isn't enough.
|
||||
/// This function will return the appropriate function, symbol or inlined
|
||||
/// function name for the frame.
|
||||
///
|
||||
/// This function returns:
|
||||
/// - the name of the inlined function (if there is one)
|
||||
/// - the name of the concrete function (if there is one)
|
||||
/// - the name of the symbol (if there is one)
|
||||
/// - NULL
|
||||
///
|
||||
/// See also IsInlined().
|
||||
const char *
|
||||
GetFunctionName();
|
||||
/// Get the appropriate function name for this frame. Inlined functions in
|
||||
/// LLDB are represented by Blocks that have inlined function information, so
|
||||
/// just looking at the SBFunction or SBSymbol for a frame isn't enough.
|
||||
/// This function will return the appropriate function, symbol or inlined
|
||||
/// function name for the frame.
|
||||
///
|
||||
/// This function returns:
|
||||
/// - the name of the inlined function (if there is one)
|
||||
/// - the name of the concrete function (if there is one)
|
||||
/// - the name of the symbol (if there is one)
|
||||
/// - NULL
|
||||
///
|
||||
/// See also IsInlined().
|
||||
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();
|
||||
/// Return true if this frame represents an inlined function.
|
||||
///
|
||||
/// See also GetFunctionName().
|
||||
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);
|
||||
/// 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::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
|
||||
/// for a stack frame. Inlined functions are represented as SBBlock objects
|
||||
/// that have inlined function information: the name of the inlined function,
|
||||
/// where it was called from. The block that is returned will be the first
|
||||
/// block at or above the block for the PC (SBFrame::GetBlock()) that defines
|
||||
/// the scope of the frame. When a function contains no inlined functions,
|
||||
/// this will be the top most lexical block that defines the function.
|
||||
/// When a function has inlined functions and the PC is currently
|
||||
/// 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;
|
||||
/// 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
|
||||
/// for a stack frame. Inlined functions are represented as SBBlock objects
|
||||
/// that have inlined function information: the name of the inlined function,
|
||||
/// where it was called from. The block that is returned will be the first
|
||||
/// block at or above the block for the PC (SBFrame::GetBlock()) that defines
|
||||
/// the scope of the frame. When a function contains no inlined functions,
|
||||
/// this will be the top most lexical block that defines the function.
|
||||
/// When a function has inlined functions and the PC is currently
|
||||
/// 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::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,
|
||||
bool in_scope_only);
|
||||
/// 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,
|
||||
bool in_scope_only);
|
||||
|
||||
lldb::SBValueList
|
||||
GetVariables (bool arguments,
|
||||
bool locals,
|
||||
bool statics,
|
||||
bool in_scope_only,
|
||||
lldb::DynamicValueType use_dynamic);
|
||||
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);
|
||||
/// 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::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,
|
||||
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,
|
||||
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);
|
||||
/// The version that doesn't supply a 'use_dynamic' value will use the
|
||||
/// target's default.
|
||||
lldb::SBValue GetValueForVariablePath(const char *var_path);
|
||||
|
||||
/// Find variables, register sets, registers, or persistent variables using
|
||||
/// the frame as the scope.
|
||||
///
|
||||
/// NB. This function does not look up ivars in the function object pointer.
|
||||
/// To do that use GetValueForVariablePath.
|
||||
///
|
||||
/// 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);
|
||||
/// Find variables, register sets, registers, or persistent variables using
|
||||
/// the frame as the scope.
|
||||
///
|
||||
/// NB. This function does not look up ivars in the function object pointer.
|
||||
/// To do that use GetValueForVariablePath.
|
||||
///
|
||||
/// 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::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;
|
||||
|
||||
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;
|
||||
lldb::ExecutionContextRefSP m_opaque_sp;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBFrame_h_
|
||||
#endif // LLDB_SBFrame_h_
|
||||
|
|
|
@ -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;
|
||||
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;
|
||||
lldb_private::Function *m_opaque_ptr;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBFunction_h_
|
||||
|
|
|
@ -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,
|
||||
lldb::thread_func_t thread_function,
|
||||
void *thread_arg, lldb::SBError *err);
|
||||
|
||||
static lldb::thread_t
|
||||
ThreadCreate (const char *name,
|
||||
lldb::thread_func_t thread_function,
|
||||
void *thread_arg,
|
||||
lldb::SBError *err);
|
||||
|
||||
static bool
|
||||
ThreadCancel (lldb::thread_t thread,
|
||||
lldb::SBError *err);
|
||||
|
||||
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 ThreadCancel(lldb::thread_t thread, lldb::SBError *err);
|
||||
|
||||
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);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBHostOS_h_
|
||||
|
|
|
@ -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;
|
||||
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;
|
||||
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
Loading…
Reference in New Issue