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

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

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

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

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

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

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

View File

@ -2,6 +2,7 @@
import StringIO import StringIO
def binary(n, width=None): def binary(n, width=None):
""" """
Return a list of (0|1)'s for the binary representation of n where n >= 0. Return a list of (0|1)'s for the binary representation of n where n >= 0.
@ -22,6 +23,7 @@ def binary(n, width=None):
l.reverse() l.reverse()
return l return l
def twos_complement(n, width): def twos_complement(n, width):
""" """
Return a list of (0|1)'s for the binary representation of a width-bit two's Return a list of (0|1)'s for the binary representation of a width-bit two's
@ -53,6 +55,7 @@ def twos_complement(n, width):
# print twos_complement(-5, 64) # 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] # [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): def positions(width):
"""Helper function returning a list describing the bit positions. """Helper function returning a list describing the bit positions.
Bit positions greater than 99 are truncated to 2 digits, for example, Bit positions greater than 99 are truncated to 2 digits, for example,
@ -91,6 +94,7 @@ def utob(debugger, command_line, result, dict):
print ' ' + ' '.join(pos) print ' ' + ' '.join(pos)
print ' %s' % str(bits) print ' %s' % str(bits)
def itob(debugger, command_line, result, dict): def itob(debugger, command_line, result, dict):
"""Convert the integer to print its two's complement representation. """Convert the integer to print its two's complement representation.
args[0] (mandatory) is the integer to be converted args[0] (mandatory) is the integer to be converted
@ -119,4 +123,3 @@ def itob(debugger, command_line, result, dict):
pos = positions(width) pos = positions(width)
print ' ' + ' '.join(pos) print ' ' + ' '.join(pos)
print ' %s' % str(bits) print ' %s' % str(bits)

View File

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

View File

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

View File

@ -23,7 +23,12 @@ import lldb.utils.symbolication
g_libheap_dylib_dir = None g_libheap_dylib_dir = None
g_libheap_dylib_dict = dict() g_libheap_dylib_dict = dict()
def get_iterate_memory_expr(options, process, user_init_code, user_return_code):
def get_iterate_memory_expr(
options,
process,
user_init_code,
user_return_code):
expr = ''' expr = '''
typedef unsigned natural_t; typedef unsigned natural_t;
typedef uintptr_t vm_size_t; typedef uintptr_t vm_size_t;
@ -32,7 +37,7 @@ typedef natural_t task_t;
typedef int kern_return_t; typedef int kern_return_t;
#define KERN_SUCCESS 0 #define KERN_SUCCESS 0
typedef void (*range_callback_t)(task_t task, void *baton, unsigned type, uintptr_t ptr_addr, uintptr_t ptr_size); typedef void (*range_callback_t)(task_t task, void *baton, unsigned type, uintptr_t ptr_addr, uintptr_t ptr_size);
'''; '''
if options.search_vm_regions: if options.search_vm_regions:
expr += ''' expr += '''
typedef int vm_prot_t; typedef int vm_prot_t;
@ -67,9 +72,9 @@ typedef struct vm_region_submap_short_info_data_64_t {
vm32_object_id_t object_id; // obj/map name, not a handle vm32_object_id_t object_id; // obj/map name, not a handle
unsigned short user_wired_count; unsigned short user_wired_count;
} vm_region_submap_short_info_data_64_t; } vm_region_submap_short_info_data_64_t;
#define VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 ((mach_msg_type_number_t)(sizeof(vm_region_submap_short_info_data_64_t)/sizeof(int)))'''; #define VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 ((mach_msg_type_number_t)(sizeof(vm_region_submap_short_info_data_64_t)/sizeof(int)))'''
if user_init_code: if user_init_code:
expr += user_init_code; expr += user_init_code
expr += ''' expr += '''
task_t task = (task_t)mach_task_self(); task_t task = (task_t)mach_task_self();
mach_vm_address_t vm_region_base_addr; mach_vm_address_t vm_region_base_addr;
@ -178,6 +183,7 @@ for (uint32_t i=0; i<NUM_SEGMENTS; ++i)
return expr return expr
def get_member_types_for_offset(value_type, offset, member_list): def get_member_types_for_offset(value_type, offset, member_list):
member = value_type.GetFieldAtIndex(0) member = value_type.GetFieldAtIndex(0)
search_bases = False search_bases = False
@ -189,7 +195,8 @@ def get_member_types_for_offset(value_type, offset, member_list):
member_end_byte_offset = member_byte_offset + member.type.size member_end_byte_offset = member_byte_offset + member.type.size
if member_byte_offset <= offset and offset < member_end_byte_offset: if member_byte_offset <= offset and offset < member_end_byte_offset:
member_list.append(member) member_list.append(member)
get_member_types_for_offset (member.type, offset - member_byte_offset, member_list) get_member_types_for_offset(
member.type, offset - member_byte_offset, member_list)
return return
else: else:
search_bases = True search_bases = True
@ -202,7 +209,8 @@ def get_member_types_for_offset(value_type, offset, member_list):
member_end_byte_offset = member_byte_offset + member.type.size member_end_byte_offset = member_byte_offset + member.type.size
if member_byte_offset <= offset and offset < member_end_byte_offset: if member_byte_offset <= offset and offset < member_end_byte_offset:
member_list.append(member) member_list.append(member)
get_member_types_for_offset (member.type, offset - member_byte_offset, member_list) get_member_types_for_offset(
member.type, offset - member_byte_offset, member_list)
return return
for field_idx in range(value_type.GetNumberOfVirtualBaseClasses()): for field_idx in range(value_type.GetNumberOfVirtualBaseClasses()):
member = value_type.GetVirtualBaseClassAtIndex(field_idx) member = value_type.GetVirtualBaseClassAtIndex(field_idx)
@ -210,9 +218,11 @@ def get_member_types_for_offset(value_type, offset, member_list):
member_end_byte_offset = member_byte_offset + member.type.size member_end_byte_offset = member_byte_offset + member.type.size
if member_byte_offset <= offset and offset < member_end_byte_offset: if member_byte_offset <= offset and offset < member_end_byte_offset:
member_list.append(member) member_list.append(member)
get_member_types_for_offset (member.type, offset - member_byte_offset, member_list) get_member_types_for_offset(
member.type, offset - member_byte_offset, member_list)
return return
def append_regex_callback(option, opt, value, parser): def append_regex_callback(option, opt, value, parser):
try: try:
ivar_regex = re.compile(value) ivar_regex = re.compile(value)
@ -220,25 +230,134 @@ def append_regex_callback(option, opt, value, parser):
except: except:
print 'error: an exception was thrown when compiling the ivar regular expression for "%s"' % value print 'error: an exception was thrown when compiling the ivar regular expression for "%s"' % value
def add_common_options(parser): def add_common_options(parser):
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) parser.add_option(
parser.add_option('-t', '--type', action='store_true', dest='print_type', help='print the full value of the type for each matching malloc block', default=False) '-v',
parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False) '--verbose',
parser.add_option('-z', '--size', action='store_true', dest='show_size', help='print the allocation size in bytes', default=False) action='store_true',
parser.add_option('-r', '--range', action='store_true', dest='show_range', help='print the allocation address range instead of just the allocation base address', default=False) dest='verbose',
parser.add_option('-m', '--memory', action='store_true', dest='memory', help='dump the memory for each matching block', default=False) help='display verbose debug info',
parser.add_option('-f', '--format', type='string', dest='format', help='the format to use when dumping memory if --memory is specified', default=None) default=False)
parser.add_option('-I', '--omit-ivar-regex', type='string', action='callback', callback=append_regex_callback, dest='ivar_regex_blacklist', default=[], help='specify one or more regular expressions used to backlist any matches that are in ivars') parser.add_option(
parser.add_option('-s', '--stack', action='store_true', dest='stack', help='gets the stack that allocated each malloc block if MallocStackLogging is enabled', default=False) '-t',
parser.add_option('-S', '--stack-history', action='store_true', dest='stack_history', help='gets the stack history for all allocations whose start address matches each malloc block if MallocStackLogging is enabled', default=False) '--type',
parser.add_option('-F', '--max-frames', type='int', dest='max_frames', help='the maximum number of stack frames to print when using the --stack or --stack-history options (default=128)', default=128) action='store_true',
parser.add_option('-H', '--max-history', type='int', dest='max_history', help='the maximum number of stack history backtraces to print for each allocation when using the --stack-history option (default=16)', default=16) dest='print_type',
parser.add_option('-M', '--max-matches', type='int', dest='max_matches', help='the maximum number of matches to print', default=32) help='print the full value of the type for each matching malloc block',
parser.add_option('-O', '--offset', type='int', dest='offset', help='the matching data must be at this offset', default=-1) default=False)
parser.add_option('--ignore-stack', action='store_false', dest='search_stack', help="Don't search the stack when enumerating memory", default=True) parser.add_option(
parser.add_option('--ignore-heap', action='store_false', dest='search_heap', help="Don't search the heap allocations when enumerating memory", default=True) '-o',
parser.add_option('--ignore-segments', action='store_false', dest='search_segments', help="Don't search readable executable segments enumerating memory", default=True) '--po',
parser.add_option('-V', '--vm-regions', action='store_true', dest='search_vm_regions', help='Check all VM regions instead of searching the heap, stack and segments', default=False) action='store_true',
dest='print_object_description',
help='print the object descriptions for any matches',
default=False)
parser.add_option(
'-z',
'--size',
action='store_true',
dest='show_size',
help='print the allocation size in bytes',
default=False)
parser.add_option(
'-r',
'--range',
action='store_true',
dest='show_range',
help='print the allocation address range instead of just the allocation base address',
default=False)
parser.add_option(
'-m',
'--memory',
action='store_true',
dest='memory',
help='dump the memory for each matching block',
default=False)
parser.add_option(
'-f',
'--format',
type='string',
dest='format',
help='the format to use when dumping memory if --memory is specified',
default=None)
parser.add_option(
'-I',
'--omit-ivar-regex',
type='string',
action='callback',
callback=append_regex_callback,
dest='ivar_regex_blacklist',
default=[],
help='specify one or more regular expressions used to backlist any matches that are in ivars')
parser.add_option(
'-s',
'--stack',
action='store_true',
dest='stack',
help='gets the stack that allocated each malloc block if MallocStackLogging is enabled',
default=False)
parser.add_option(
'-S',
'--stack-history',
action='store_true',
dest='stack_history',
help='gets the stack history for all allocations whose start address matches each malloc block if MallocStackLogging is enabled',
default=False)
parser.add_option(
'-F',
'--max-frames',
type='int',
dest='max_frames',
help='the maximum number of stack frames to print when using the --stack or --stack-history options (default=128)',
default=128)
parser.add_option(
'-H',
'--max-history',
type='int',
dest='max_history',
help='the maximum number of stack history backtraces to print for each allocation when using the --stack-history option (default=16)',
default=16)
parser.add_option(
'-M',
'--max-matches',
type='int',
dest='max_matches',
help='the maximum number of matches to print',
default=32)
parser.add_option(
'-O',
'--offset',
type='int',
dest='offset',
help='the matching data must be at this offset',
default=-1)
parser.add_option(
'--ignore-stack',
action='store_false',
dest='search_stack',
help="Don't search the stack when enumerating memory",
default=True)
parser.add_option(
'--ignore-heap',
action='store_false',
dest='search_heap',
help="Don't search the heap allocations when enumerating memory",
default=True)
parser.add_option(
'--ignore-segments',
action='store_false',
dest='search_segments',
help="Don't search readable executable segments enumerating memory",
default=True)
parser.add_option(
'-V',
'--vm-regions',
action='store_true',
dest='search_vm_regions',
help='Check all VM regions instead of searching the heap, stack and segments',
default=False)
def type_flags_to_string(type_flags): def type_flags_to_string(type_flags):
if type_flags == 0: if type_flags == 0:
@ -261,6 +380,7 @@ def type_flags_to_string(type_flags):
type_str = hex(type_flags) type_str = hex(type_flags)
return type_str return type_str
def find_variable_containing_address(verbose, frame, match_addr): def find_variable_containing_address(verbose, frame, match_addr):
variables = frame.GetVariables(True, True, True, True) variables = frame.GetVariables(True, True, True, True)
matching_var = None matching_var = None
@ -275,14 +395,16 @@ def find_variable_containing_address(verbose, frame, match_addr):
print 'match' print 'match'
return var return var
else: else:
if byte_size > 0 and var_addr <= match_addr and match_addr < (var_addr + byte_size): if byte_size > 0 and var_addr <= match_addr and match_addr < (
var_addr + byte_size):
if verbose: if verbose:
print 'match' print 'match'
return var return var
return None return None
def find_frame_for_stack_address(process, addr): def find_frame_for_stack_address(process, addr):
closest_delta = sys.maxint closest_delta = sys.maxsize
closest_frame = None closest_frame = None
# print 'find_frame_for_stack_address(%#x)' % (addr) # print 'find_frame_for_stack_address(%#x)' % (addr)
for thread in process: for thread in process:
@ -301,7 +423,14 @@ def find_frame_for_stack_address(process, addr):
# print 'delta >= closest_delta' # print 'delta >= closest_delta'
return closest_frame return closest_frame
def type_flags_to_description(process, type_flags, ptr_addr, ptr_size, offset, match_addr):
def type_flags_to_description(
process,
type_flags,
ptr_addr,
ptr_size,
offset,
match_addr):
show_offset = False show_offset = False
if type_flags == 0 or type_flags & 4: if type_flags == 0 or type_flags & 4:
type_str = 'free(%#x)' % (ptr_addr,) type_str = 'free(%#x)' % (ptr_addr,)
@ -312,31 +441,37 @@ def type_flags_to_description(process, type_flags, ptr_addr, ptr_size, offset, m
type_str = 'stack' type_str = 'stack'
frame = find_frame_for_stack_address(process, match_addr) frame = find_frame_for_stack_address(process, match_addr)
if frame: if frame:
type_str += ' in frame #%u of thread #%u: tid %#x' % (frame.GetFrameID(), frame.GetThread().GetIndexID(), frame.GetThread().GetThreadID()) type_str += ' in frame #%u of thread #%u: tid %#x' % (frame.GetFrameID(
), frame.GetThread().GetIndexID(), frame.GetThread().GetThreadID())
variables = frame.GetVariables(True, True, True, True) variables = frame.GetVariables(True, True, True, True)
matching_var = None matching_var = None
for var in variables: for var in variables:
var_addr = var.GetLoadAddress() var_addr = var.GetLoadAddress()
if var_addr != lldb.LLDB_INVALID_ADDRESS: if var_addr != lldb.LLDB_INVALID_ADDRESS:
#print 'variable "%s" @ %#x (%#x)' % (var.name, var.load_addr, match_addr) # print 'variable "%s" @ %#x (%#x)' % (var.name, var.load_addr,
# match_addr)
if var_addr == match_addr: if var_addr == match_addr:
matching_var = var matching_var = var
break break
else: else:
byte_size = var.GetType().GetByteSize() byte_size = var.GetType().GetByteSize()
if byte_size > 0 and var_addr <= match_addr and match_addr < (var_addr + byte_size): if byte_size > 0 and var_addr <= match_addr and match_addr < (
var_addr + byte_size):
matching_var = var matching_var = var
break break
if matching_var: if matching_var:
type_str += ' in variable at %#x:\n %s' % (matching_var.GetLoadAddress(), matching_var) type_str += ' in variable at %#x:\n %s' % (
matching_var.GetLoadAddress(), matching_var)
elif type_flags & 16: elif type_flags & 16:
type_str = 'stack (red zone)' type_str = 'stack (red zone)'
elif type_flags & 32: elif type_flags & 32:
sb_addr = process.GetTarget().ResolveLoadAddress(ptr_addr + offset) sb_addr = process.GetTarget().ResolveLoadAddress(ptr_addr + offset)
type_str = 'segment [%#x - %#x), %s + %u, %s' % (ptr_addr, ptr_addr + ptr_size, sb_addr.section.name, sb_addr.offset, sb_addr) type_str = 'segment [%#x - %#x), %s + %u, %s' % (
ptr_addr, ptr_addr + ptr_size, sb_addr.section.name, sb_addr.offset, sb_addr)
elif type_flags & 64: elif type_flags & 64:
sb_addr = process.GetTarget().ResolveLoadAddress(ptr_addr + offset) sb_addr = process.GetTarget().ResolveLoadAddress(ptr_addr + offset)
type_str = 'vm_region [%#x - %#x), %s + %u, %s' % (ptr_addr, ptr_addr + ptr_size, sb_addr.section.name, sb_addr.offset, sb_addr) type_str = 'vm_region [%#x - %#x), %s + %u, %s' % (
ptr_addr, ptr_addr + ptr_size, sb_addr.section.name, sb_addr.offset, sb_addr)
else: else:
type_str = '%#x' % (ptr_addr,) type_str = '%#x' % (ptr_addr,)
show_offset = True show_offset = True
@ -344,6 +479,7 @@ def type_flags_to_description(process, type_flags, ptr_addr, ptr_size, offset, m
type_str += ' + %-6u' % (offset,) type_str += ' + %-6u' % (offset,)
return type_str return type_str
def dump_stack_history_entry(options, result, stack_history_entry, idx): def dump_stack_history_entry(options, result, stack_history_entry, idx):
address = int(stack_history_entry.address) address = int(stack_history_entry.address)
if address: if address:
@ -351,7 +487,9 @@ def dump_stack_history_entry(options, result, stack_history_entry, idx):
symbolicator = lldb.utils.symbolication.Symbolicator() symbolicator = lldb.utils.symbolication.Symbolicator()
symbolicator.target = lldb.debugger.GetSelectedTarget() symbolicator.target = lldb.debugger.GetSelectedTarget()
type_str = type_flags_to_string(type_flags) type_str = type_flags_to_string(type_flags)
result.AppendMessage('stack[%u]: addr = 0x%x, type=%s, frames:' % (idx, address, type_str)) result.AppendMessage(
'stack[%u]: addr = 0x%x, type=%s, frames:' %
(idx, address, type_str))
frame_idx = 0 frame_idx = 0
idx = 0 idx = 0
pc = int(stack_history_entry.frames[idx]) pc = int(stack_history_entry.frames[idx])
@ -360,7 +498,9 @@ def dump_stack_history_entry(options, result, stack_history_entry, idx):
frames = symbolicator.symbolicate(pc) frames = symbolicator.symbolicate(pc)
if frames: if frames:
for frame in frames: for frame in frames:
result.AppendMessage(' [%u] %s' % (frame_idx, frame)) result.AppendMessage(
' [%u] %s' %
(frame_idx, frame))
frame_idx += 1 frame_idx += 1
else: else:
result.AppendMessage(' [%u] 0x%x' % (frame_idx, pc)) result.AppendMessage(' [%u] 0x%x' % (frame_idx, pc))
@ -370,10 +510,13 @@ def dump_stack_history_entry(options, result, stack_history_entry, idx):
else: else:
pc = 0 pc = 0
if idx >= options.max_frames: if idx >= options.max_frames:
result.AppendMessage('warning: the max number of stack frames (%u) was reached, use the "--max-frames=<COUNT>" option to see more frames' % (options.max_frames)) result.AppendMessage(
'warning: the max number of stack frames (%u) was reached, use the "--max-frames=<COUNT>" option to see more frames' %
(options.max_frames))
result.AppendMessage('') result.AppendMessage('')
def dump_stack_history_entries(options, result, addr, history): def dump_stack_history_entries(options, result, addr, history):
# malloc_stack_entry *get_stack_history_for_address (const void * addr) # malloc_stack_entry *get_stack_history_for_address (const void * addr)
expr_prefix = ''' expr_prefix = '''
@ -406,7 +549,7 @@ if (stack.num_frames < MAX_FRAMES)
stack.frames[stack.num_frames] = 0; stack.frames[stack.num_frames] = 0;
else else
stack.frames[MAX_FRAMES-1] = 0; stack.frames[MAX_FRAMES-1] = 0;
stack''' % (options.max_frames, addr); stack''' % (options.max_frames, addr)
history_expr = ''' history_expr = '''
typedef int kern_return_t; typedef int kern_return_t;
@ -457,15 +600,16 @@ enumerate_callback_t callback = [] (mach_stack_logging_record_t stack_record, vo
++info->idx; ++info->idx;
}; };
(kern_return_t)__mach_stack_logging_enumerate_records (info.task, (uint64_t)0x%x, callback, &info); (kern_return_t)__mach_stack_logging_enumerate_records (info.task, (uint64_t)0x%x, callback, &info);
info''' % (options.max_frames, options.max_history, addr); info''' % (options.max_frames, options.max_history, addr)
frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() frame = lldb.debugger.GetSelectedTarget().GetProcess(
).GetSelectedThread().GetSelectedFrame()
if history: if history:
expr = history_expr expr = history_expr
else: else:
expr = single_expr expr = single_expr
expr_options = lldb.SBExpressionOptions() expr_options = lldb.SBExpressionOptions()
expr_options.SetIgnoreBreakpoints(True); expr_options.SetIgnoreBreakpoints(True)
expr_options.SetTimeoutInMicroSeconds(5 * 1000 * 1000) # 5 second timeout expr_options.SetTimeoutInMicroSeconds(5 * 1000 * 1000) # 5 second timeout
expr_options.SetTryAllThreads(True) expr_options.SetTryAllThreads(True)
expr_options.SetLanguage(lldb.eLanguageTypeObjC_plus_plus) expr_options.SetLanguage(lldb.eLanguageTypeObjC_plus_plus)
@ -486,26 +630,40 @@ info''' % (options.max_frames, options.max_history, addr);
i_max = options.max_history i_max = options.max_history
for i in range(i_max): for i in range(i_max):
stack_history_entry = malloc_stack_history.entries[i] stack_history_entry = malloc_stack_history.entries[i]
dump_stack_history_entry(options, result, stack_history_entry, i) dump_stack_history_entry(
options, result, stack_history_entry, i)
if num_stacks > options.max_history: if num_stacks > options.max_history:
result.AppendMessage('warning: the max number of stacks (%u) was reached, use the "--max-history=%u" option to see all of the stacks' % (options.max_history, num_stacks)) result.AppendMessage(
'warning: the max number of stacks (%u) was reached, use the "--max-history=%u" option to see all of the stacks' %
(options.max_history, num_stacks))
else: else:
stack_history_entry = lldb.value(expr_sbvalue) stack_history_entry = lldb.value(expr_sbvalue)
dump_stack_history_entry(options, result, stack_history_entry, 0) dump_stack_history_entry(options, result, stack_history_entry, 0)
else: else:
result.AppendMessage('error: expression failed "%s" => %s' % (expr, expr_sbvalue.error)) result.AppendMessage(
'error: expression failed "%s" => %s' %
(expr, expr_sbvalue.error))
def display_match_results (process, result, options, arg_str_description, expr, print_no_matches, expr_prefix = None): def display_match_results(
frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() process,
result,
options,
arg_str_description,
expr,
print_no_matches,
expr_prefix=None):
frame = lldb.debugger.GetSelectedTarget().GetProcess(
).GetSelectedThread().GetSelectedFrame()
if not frame: if not frame:
result.AppendMessage('error: invalid frame') result.AppendMessage('error: invalid frame')
return 0 return 0
expr_options = lldb.SBExpressionOptions() expr_options = lldb.SBExpressionOptions()
expr_options.SetIgnoreBreakpoints(True); expr_options.SetIgnoreBreakpoints(True)
expr_options.SetFetchDynamicValue(lldb.eNoDynamicValues); expr_options.SetFetchDynamicValue(lldb.eNoDynamicValues)
expr_options.SetTimeoutInMicroSeconds (30*1000*1000) # 30 second timeout expr_options.SetTimeoutInMicroSeconds(
30 * 1000 * 1000) # 30 second timeout
expr_options.SetTryAllThreads(False) expr_options.SetTryAllThreads(False)
expr_options.SetLanguage(lldb.eLanguageTypeObjC_plus_plus) expr_options.SetLanguage(lldb.eLanguageTypeObjC_plus_plus)
if expr_prefix: if expr_prefix:
@ -520,11 +678,14 @@ def display_match_results (process, result, options, arg_str_description, expr,
match_value = lldb.value(expr_sbvalue) match_value = lldb.value(expr_sbvalue)
i = 0 i = 0
match_idx = 0 match_idx = 0
while 1: while True:
print_entry = True print_entry = True
match_entry = match_value[i]; i += 1 match_entry = match_value[i]
i += 1
if i > options.max_matches: if i > options.max_matches:
result.AppendMessage('warning: the max number of matches (%u) was reached, use the --max-matches option to get more results' % (options.max_matches)) result.AppendMessage(
'warning: the max number of matches (%u) was reached, use the --max-matches option to get more results' %
(options.max_matches))
break break
malloc_addr = match_entry.addr.sbvalue.unsigned malloc_addr = match_entry.addr.sbvalue.unsigned
if malloc_addr == 0: if malloc_addr == 0:
@ -547,29 +708,36 @@ def display_match_results (process, result, options, arg_str_description, expr,
options.search_segments = True options.search_segments = True
options.search_heap = True options.search_heap = True
options.search_vm_regions = False options.search_vm_regions = False
if malloc_info_impl (lldb.debugger, result, options, [hex(malloc_addr + offset)]): if malloc_info_impl(lldb.debugger, result, options, [
hex(malloc_addr + offset)]):
print_entry = False print_entry = False
options.search_stack = search_stack_old options.search_stack = search_stack_old
options.search_segments = search_segments_old options.search_segments = search_segments_old
options.search_heap = search_heap_old options.search_heap = search_heap_old
options.search_vm_regions = search_vm_regions options.search_vm_regions = search_vm_regions
if print_entry: if print_entry:
description = '%#16.16x: %s' % (match_addr, type_flags_to_description(process, type_flags, malloc_addr, malloc_size, offset, match_addr)) description = '%#16.16x: %s' % (match_addr, type_flags_to_description(
process, type_flags, malloc_addr, malloc_size, offset, match_addr))
if options.show_size: if options.show_size:
description += ' <%5u>' % (malloc_size) description += ' <%5u>' % (malloc_size)
if options.show_range: if options.show_range:
description += ' [%#x - %#x)' % (malloc_addr, malloc_addr + malloc_size) description += ' [%#x - %#x)' % (
malloc_addr, malloc_addr + malloc_size)
derefed_dynamic_value = None derefed_dynamic_value = None
dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget) dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(
lldb.eDynamicCanRunTarget)
if dynamic_value.type.name == 'void *': if dynamic_value.type.name == 'void *':
if options.type == 'pointer' and malloc_size == 4096: if options.type == 'pointer' and malloc_size == 4096:
error = lldb.SBError() error = lldb.SBError()
process = expr_sbvalue.GetProcess() process = expr_sbvalue.GetProcess()
target = expr_sbvalue.GetTarget() target = expr_sbvalue.GetTarget()
data = bytearray(process.ReadMemory(malloc_addr, 16, error)) data = bytearray(
process.ReadMemory(
malloc_addr, 16, error))
if data == '\xa1\xa1\xa1\xa1AUTORELEASE!': if data == '\xa1\xa1\xa1\xa1AUTORELEASE!':
ptr_size = target.addr_size ptr_size = target.addr_size
thread = process.ReadUnsignedFromMemory (malloc_addr + 16 + ptr_size, ptr_size, error) thread = process.ReadUnsignedFromMemory(
malloc_addr + 16 + ptr_size, ptr_size, error)
# 4 bytes 0xa1a1a1a1 # 4 bytes 0xa1a1a1a1
# 12 bytes 'AUTORELEASE!' # 12 bytes 'AUTORELEASE!'
# ptr bytes autorelease insertion point # ptr bytes autorelease insertion point
@ -578,7 +746,8 @@ def display_match_results (process, result, options, arg_str_description, expr,
# ptr bytes next hotter page # ptr bytes next hotter page
# 4 bytes this page's depth in the list # 4 bytes this page's depth in the list
# 4 bytes high-water mark # 4 bytes high-water mark
description += ' AUTORELEASE! for pthread_t %#x' % (thread) description += ' AUTORELEASE! for pthread_t %#x' % (
thread)
# else: # else:
# description += 'malloc(%u)' % (malloc_size) # description += 'malloc(%u)' % (malloc_size)
# else: # else:
@ -592,8 +761,9 @@ def display_match_results (process, result, options, arg_str_description, expr,
description += ' ' description += ' '
description += derefed_dynamic_type_name description += derefed_dynamic_type_name
if offset < derefed_dynamic_type_size: if offset < derefed_dynamic_type_size:
member_list = list(); member_list = list()
get_member_types_for_offset (derefed_dynamic_type, offset, member_list) get_member_types_for_offset(
derefed_dynamic_type, offset, member_list)
if member_list: if member_list:
member_path = '' member_path = ''
for member in member_list: for member in member_list:
@ -605,13 +775,16 @@ def display_match_results (process, result, options, arg_str_description, expr,
if member_path: if member_path:
if options.ivar_regex_blacklist: if options.ivar_regex_blacklist:
for ivar_regex in options.ivar_regex_blacklist: for ivar_regex in options.ivar_regex_blacklist:
if ivar_regex.match(member_path): if ivar_regex.match(
member_path):
print_entry = False print_entry = False
description += '.%s' % (member_path) description += '.%s' % (member_path)
else: else:
description += '%u bytes after %s' % (offset - derefed_dynamic_type_size, derefed_dynamic_type_name) description += '%u bytes after %s' % (
offset - derefed_dynamic_type_size, derefed_dynamic_type_name)
else: else:
# strip the "*" from the end of the name since we were unable to dereference this # strip the "*" from the end of the name since we
# were unable to dereference this
description += dynamic_value.type.name[0:-1] description += dynamic_value.type.name[0:-1]
if print_entry: if print_entry:
match_idx += 1 match_idx += 1
@ -628,10 +801,12 @@ def display_match_results (process, result, options, arg_str_description, expr,
result.AppendMessage(result_output) result.AppendMessage(result_output)
if options.memory: if options.memory:
cmd_result = lldb.SBCommandReturnObject() cmd_result = lldb.SBCommandReturnObject()
if options.format == None: if options.format is None:
memory_command = "memory read --force 0x%x 0x%x" % (malloc_addr, malloc_addr + malloc_size) memory_command = "memory read --force 0x%x 0x%x" % (
malloc_addr, malloc_addr + malloc_size)
else: else:
memory_command = "memory read --force -f %s 0x%x 0x%x" % (options.format, malloc_addr, malloc_addr + malloc_size) memory_command = "memory read --force -f %s 0x%x 0x%x" % (
options.format, malloc_addr, malloc_addr + malloc_size)
if options.verbose: if options.verbose:
result.AppendMessage(memory_command) result.AppendMessage(memory_command)
lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result) lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result)
@ -645,6 +820,7 @@ def display_match_results (process, result, options, arg_str_description, expr,
result.AppendMessage(str(expr_sbvalue.error)) result.AppendMessage(str(expr_sbvalue.error))
return 0 return 0
def get_ptr_refs_options(): def get_ptr_refs_options():
usage = "usage: %prog [options] <EXPR> [EXPR ...]" usage = "usage: %prog [options] <EXPR> [EXPR ...]"
description = '''Searches all allocations on the heap for pointer values on description = '''Searches all allocations on the heap for pointer values on
@ -652,16 +828,29 @@ darwin user space programs. Any matches that were found will dump the malloc
blocks that contain the pointers and might be able to print what kind of blocks that contain the pointers and might be able to print what kind of
objects the pointers are contained in using dynamic type information in the objects the pointers are contained in using dynamic type information in the
program.''' program.'''
parser = optparse.OptionParser(description=description, prog='ptr_refs',usage=usage) parser = optparse.OptionParser(
description=description,
prog='ptr_refs',
usage=usage)
add_common_options(parser) add_common_options(parser)
return parser return parser
def find_variable(debugger, command, result, dict): def find_variable(debugger, command, result, dict):
usage = "usage: %prog [options] <ADDR> [ADDR ...]" usage = "usage: %prog [options] <ADDR> [ADDR ...]"
description = '''Searches for a local variable in all frames that contains a hex ADDR.''' description = '''Searches for a local variable in all frames that contains a hex ADDR.'''
command_args = shlex.split(command) command_args = shlex.split(command)
parser = optparse.OptionParser(description=description, prog='find_variable',usage=usage) parser = optparse.OptionParser(
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) description=description,
prog='find_variable',
usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
try: try:
(options, args) = parser.parse_args(command_args) (options, args) = parser.parse_args(command_args)
except: except:
@ -678,7 +867,8 @@ def find_variable(debugger, command, result, dict):
done = False done = False
for thread in process: for thread in process:
for frame in thread: for frame in thread:
var = find_variable_containing_address(options.verbose, frame, var_addr) var = find_variable_containing_address(
options.verbose, frame, var_addr)
if var: if var:
print var print var
done = True done = True
@ -686,6 +876,7 @@ def find_variable(debugger, command, result, dict):
if done: if done:
break break
def ptr_refs(debugger, command, result, dict): def ptr_refs(debugger, command, result, dict):
command_args = shlex.split(command) command_args = shlex.split(command)
parser = get_ptr_refs_options() parser = get_ptr_refs_options()
@ -704,7 +895,7 @@ def ptr_refs(debugger, command, result, dict):
return return
options.type = 'pointer' options.type = 'pointer'
if options.format == None: if options.format is None:
options.format = "A" # 'A' is "address" format options.format = "A" # 'A' is "address" format
if args: if args:
@ -759,15 +950,26 @@ callback_baton_t baton = { range_callback, 0, {0}, (void *)%s };
user_return_code = '''if (baton.num_matches < MAX_MATCHES) user_return_code = '''if (baton.num_matches < MAX_MATCHES)
baton.matches[baton.num_matches].addr = 0; // Terminate the matches array baton.matches[baton.num_matches].addr = 0; // Terminate the matches array
baton.matches''' baton.matches'''
# Iterate through all of our pointer expressions and display the results # Iterate through all of our pointer expressions and display the
# results
for ptr_expr in args: for ptr_expr in args:
user_init_code = user_init_code_format % (options.max_matches, ptr_expr) user_init_code = user_init_code_format % (
expr = get_iterate_memory_expr(options, process, user_init_code, user_return_code) options.max_matches, ptr_expr)
expr = get_iterate_memory_expr(
options, process, user_init_code, user_return_code)
arg_str_description = 'malloc block containing pointer %s' % ptr_expr arg_str_description = 'malloc block containing pointer %s' % ptr_expr
display_match_results (process, result, options, arg_str_description, expr, True, expr_prefix) display_match_results(
process,
result,
options,
arg_str_description,
expr,
True,
expr_prefix)
else: else:
result.AppendMessage('error: no pointer arguments were given') result.AppendMessage('error: no pointer arguments were given')
def get_cstr_refs_options(): def get_cstr_refs_options():
usage = "usage: %prog [options] <CSTR> [CSTR ...]" usage = "usage: %prog [options] <CSTR> [CSTR ...]"
description = '''Searches all allocations on the heap for C string values on description = '''Searches all allocations on the heap for C string values on
@ -775,13 +977,17 @@ darwin user space programs. Any matches that were found will dump the malloc
blocks that contain the C strings and might be able to print what kind of blocks that contain the C strings and might be able to print what kind of
objects the pointers are contained in using dynamic type information in the objects the pointers are contained in using dynamic type information in the
program.''' program.'''
parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage) parser = optparse.OptionParser(
description=description,
prog='cstr_refs',
usage=usage)
add_common_options(parser) add_common_options(parser)
return parser return parser
def cstr_refs(debugger, command, result, dict): def cstr_refs(debugger, command, result, dict):
command_args = shlex.split(command) command_args = shlex.split(command)
parser = get_cstr_refs_options(); parser = get_cstr_refs_options()
try: try:
(options, args) = parser.parse_args(command_args) (options, args) = parser.parse_args(command_args)
except: except:
@ -796,9 +1002,8 @@ def cstr_refs(debugger, command, result, dict):
result.AppendMessage('error: invalid frame') result.AppendMessage('error: invalid frame')
return return
options.type = 'cstr' options.type = 'cstr'
if options.format == None: if options.format is None:
options.format = "Y" # 'Y' is "bytes with ASCII" format options.format = "Y" # 'Y' is "bytes with ASCII" format
if args: if args:
@ -855,14 +1060,25 @@ callback_baton_t baton = { range_callback, 0, {0}, cstr, (unsigned)strlen(cstr)
user_return_code = '''if (baton.num_matches < MAX_MATCHES) user_return_code = '''if (baton.num_matches < MAX_MATCHES)
baton.matches[baton.num_matches].addr = 0; // Terminate the matches array baton.matches[baton.num_matches].addr = 0; // Terminate the matches array
baton.matches''' baton.matches'''
# Iterate through all of our pointer expressions and display the results # Iterate through all of our pointer expressions and display the
# results
for cstr in args: for cstr in args:
user_init_code = user_init_code_format % (options.max_matches, cstr) user_init_code = user_init_code_format % (
expr = get_iterate_memory_expr(options, process, user_init_code, user_return_code) options.max_matches, cstr)
expr = get_iterate_memory_expr(
options, process, user_init_code, user_return_code)
arg_str_description = 'malloc block containing "%s"' % cstr arg_str_description = 'malloc block containing "%s"' % cstr
display_match_results (process, result, options, arg_str_description, expr, True, expr_prefix) display_match_results(
process,
result,
options,
arg_str_description,
expr,
True,
expr_prefix)
else: else:
result.AppendMessage('error: command takes one or more C string arguments') result.AppendMessage(
'error: command takes one or more C string arguments')
def get_malloc_info_options(): def get_malloc_info_options():
@ -872,10 +1088,14 @@ specified as one or more address expressions. Any matches that were found will
dump the malloc blocks that match or contain the specified address. The matching dump the malloc blocks that match or contain the specified address. The matching
blocks might be able to show what kind of objects they are using dynamic type blocks might be able to show what kind of objects they are using dynamic type
information in the program.''' information in the program.'''
parser = optparse.OptionParser(description=description, prog='malloc_info',usage=usage) parser = optparse.OptionParser(
description=description,
prog='malloc_info',
usage=usage)
add_common_options(parser) add_common_options(parser)
return parser return parser
def malloc_info(debugger, command, result, dict): def malloc_info(debugger, command, result, dict):
command_args = shlex.split(command) command_args = shlex.split(command)
parser = get_malloc_info_options() parser = get_malloc_info_options()
@ -885,6 +1105,7 @@ def malloc_info(debugger, command, result, dict):
return return
malloc_info_impl(debugger, result, options, args) malloc_info_impl(debugger, result, options, args)
def malloc_info_impl(debugger, result, options, args): def malloc_info_impl(debugger, result, options, args):
# We are specifically looking for something on the heap only # We are specifically looking for something on the heap only
options.type = 'malloc_info' options.type = 'malloc_info'
@ -935,30 +1156,37 @@ baton.matches[1].addr = 0;'''
total_matches = 0 total_matches = 0
for ptr_expr in args: for ptr_expr in args:
user_init_code = user_init_code_format % (ptr_expr) user_init_code = user_init_code_format % (ptr_expr)
expr = get_iterate_memory_expr(options, process, user_init_code, 'baton.matches') expr = get_iterate_memory_expr(
options, process, user_init_code, 'baton.matches')
arg_str_description = 'malloc block that contains %s' % ptr_expr arg_str_description = 'malloc block that contains %s' % ptr_expr
total_matches += display_match_results (process, result, options, arg_str_description, expr, True, expr_prefix) total_matches += display_match_results(
process, result, options, arg_str_description, expr, True, expr_prefix)
return total_matches return total_matches
else: else:
result.AppendMessage('error: command takes one or more pointer expressions') result.AppendMessage(
'error: command takes one or more pointer expressions')
return 0 return 0
def get_thread_stack_ranges_struct(process): def get_thread_stack_ranges_struct(process):
'''Create code that defines a structure that represents threads stack bounds '''Create code that defines a structure that represents threads stack bounds
for all threads. It returns a static sized array initialized with all of for all threads. It returns a static sized array initialized with all of
the tid, base, size structs for all the threads.''' the tid, base, size structs for all the threads.'''
stack_dicts = list() stack_dicts = list()
if process: if process:
i = 0; i = 0
for thread in process: for thread in process:
min_sp = thread.frame[0].sp min_sp = thread.frame[0].sp
max_sp = min_sp max_sp = min_sp
for frame in thread.frames: for frame in thread.frames:
sp = frame.sp sp = frame.sp
if sp < min_sp: min_sp = sp if sp < min_sp:
if sp > max_sp: max_sp = sp min_sp = sp
if sp > max_sp:
max_sp = sp
if min_sp < max_sp: if min_sp < max_sp:
stack_dicts.append ({ 'tid' : thread.GetThreadID(), 'base' : min_sp , 'size' : max_sp-min_sp, 'index' : i }) stack_dicts.append({'tid': thread.GetThreadID(
), 'base': min_sp, 'size': max_sp - min_sp, 'index': i})
i += 1 i += 1
stack_dicts_len = len(stack_dicts) stack_dicts_len = len(stack_dicts)
if stack_dicts_len > 0: if stack_dicts_len > 0:
@ -976,6 +1204,7 @@ stacks[%(index)u].size = 0x%(size)x;''' % stack_dict
else: else:
return '' return ''
def get_sections_ranges_struct(process): def get_sections_ranges_struct(process):
'''Create code that defines a structure that represents all segments that '''Create code that defines a structure that represents all segments that
can contain data for all images in "target". It returns a static sized can contain data for all images in "target". It returns a static sized
@ -1008,13 +1237,23 @@ segments[%(index)u].size = 0x%(size)x;''' % segment_dict
else: else:
return '' return ''
def section_ptr_refs(debugger, command, result, dict): def section_ptr_refs(debugger, command, result, dict):
command_args = shlex.split(command) command_args = shlex.split(command)
usage = "usage: %prog [options] <EXPR> [EXPR ...]" usage = "usage: %prog [options] <EXPR> [EXPR ...]"
description = '''Searches section contents for pointer values in darwin user space programs.''' description = '''Searches section contents for pointer values in darwin user space programs.'''
parser = optparse.OptionParser(description=description, prog='section_ptr_refs',usage=usage) parser = optparse.OptionParser(
description=description,
prog='section_ptr_refs',
usage=usage)
add_common_options(parser) add_common_options(parser)
parser.add_option('--section', action='append', type='string', dest='section_names', help='section name to search', default=list()) parser.add_option(
'--section',
action='append',
type='string',
dest='section_names',
help='section name to search',
default=list())
try: try:
(options, args) = parser.parse_args(command_args) (options, args) = parser.parse_args(command_args)
except: except:
@ -1025,7 +1264,8 @@ def section_ptr_refs(debugger, command, result, dict):
sections = list() sections = list()
section_modules = list() section_modules = list()
if not options.section_names: if not options.section_names:
result.AppendMessage('error: at least one section must be specified with the --section option') result.AppendMessage(
'error: at least one section must be specified with the --section option')
return return
target = debugger.GetSelectedTarget() target = debugger.GetSelectedTarget()
@ -1043,9 +1283,12 @@ def section_ptr_refs(debugger, command, result, dict):
frame = target.GetProcess().GetSelectedThread().GetSelectedFrame() frame = target.GetProcess().GetSelectedThread().GetSelectedFrame()
for expr_str in args: for expr_str in args:
for (idx, section) in enumerate(sections): for (idx, section) in enumerate(sections):
expr = 'find_pointer_in_memory(0x%xllu, %ullu, (void *)%s)' % (section.addr.load_addr, section.size, expr_str) expr = 'find_pointer_in_memory(0x%xllu, %ullu, (void *)%s)' % (
arg_str_description = 'section %s.%s containing "%s"' % (section_modules[idx].file.fullpath, section.name, expr_str) section.addr.load_addr, section.size, expr_str)
num_matches = display_match_results (target.GetProcess(), result, options, arg_str_description, expr, False) arg_str_description = 'section %s.%s containing "%s"' % (
section_modules[idx].file.fullpath, section.name, expr_str)
num_matches = display_match_results(
target.GetProcess(), result, options, arg_str_description, expr, False)
if num_matches: if num_matches:
if num_matches < options.max_matches: if num_matches < options.max_matches:
options.max_matches = options.max_matches - num_matches options.max_matches = options.max_matches - num_matches
@ -1054,7 +1297,11 @@ def section_ptr_refs(debugger, command, result, dict):
if options.max_matches == 0: if options.max_matches == 0:
return return
else: else:
result.AppendMessage('error: no sections were found that match any of %s' % (', '.join(options.section_names))) result.AppendMessage(
'error: no sections were found that match any of %s' %
(', '.join(
options.section_names)))
def get_objc_refs_options(): def get_objc_refs_options():
usage = "usage: %prog [options] <CLASS> [CLASS ...]" usage = "usage: %prog [options] <CLASS> [CLASS ...]"
@ -1064,10 +1311,14 @@ in darwin user space programs. Any matches that were found will dump the malloc
blocks that contain the C strings and might be able to print what kind of blocks that contain the C strings and might be able to print what kind of
objects the pointers are contained in using dynamic type information in the objects the pointers are contained in using dynamic type information in the
program.''' program.'''
parser = optparse.OptionParser(description=description, prog='objc_refs',usage=usage) parser = optparse.OptionParser(
description=description,
prog='objc_refs',
usage=usage)
add_common_options(parser) add_common_options(parser)
return parser return parser
def objc_refs(debugger, command, result, dict): def objc_refs(debugger, command, result, dict):
command_args = shlex.split(command) command_args = shlex.split(command)
parser = get_objc_refs_options() parser = get_objc_refs_options()
@ -1086,17 +1337,20 @@ def objc_refs(debugger, command, result, dict):
return return
options.type = 'isa' options.type = 'isa'
if options.format == None: if options.format is None:
options.format = "A" # 'A' is "address" format options.format = "A" # 'A' is "address" format
expr_options = lldb.SBExpressionOptions() expr_options = lldb.SBExpressionOptions()
expr_options.SetIgnoreBreakpoints(True); expr_options.SetIgnoreBreakpoints(True)
expr_options.SetTimeoutInMicroSeconds (3*1000*1000) # 3 second infinite timeout expr_options.SetTimeoutInMicroSeconds(
3 * 1000 * 1000) # 3 second infinite timeout
expr_options.SetTryAllThreads(True) expr_options.SetTryAllThreads(True)
expr_options.SetLanguage(lldb.eLanguageTypeObjC_plus_plus) expr_options.SetLanguage(lldb.eLanguageTypeObjC_plus_plus)
num_objc_classes_value = frame.EvaluateExpression("(int)objc_getClassList((void *)0, (int)0)", expr_options) num_objc_classes_value = frame.EvaluateExpression(
"(int)objc_getClassList((void *)0, (int)0)", expr_options)
if not num_objc_classes_value.error.Success(): if not num_objc_classes_value.error.Success():
result.AppendMessage('error: %s' % num_objc_classes_value.error.GetCString()) result.AppendMessage('error: %s' %
num_objc_classes_value.error.GetCString())
return return
num_objc_classes = num_objc_classes_value.GetValueAsUnsigned() num_objc_classes = num_objc_classes_value.GetValueAsUnsigned()
@ -1197,26 +1451,44 @@ int nc = (int)objc_getClassList(baton.classes, sizeof(baton.classes)/sizeof(Clas
for class_name in args: for class_name in args:
addr_expr_str = "(void *)[%s class]" % class_name addr_expr_str = "(void *)[%s class]" % class_name
expr_options = lldb.SBExpressionOptions() expr_options = lldb.SBExpressionOptions()
expr_options.SetIgnoreBreakpoints(True); expr_options.SetIgnoreBreakpoints(True)
expr_options.SetTimeoutInMicroSeconds (1*1000*1000) # 1 second timeout expr_options.SetTimeoutInMicroSeconds(
1 * 1000 * 1000) # 1 second timeout
expr_options.SetTryAllThreads(True) expr_options.SetTryAllThreads(True)
expr_options.SetLanguage(lldb.eLanguageTypeObjC_plus_plus) expr_options.SetLanguage(lldb.eLanguageTypeObjC_plus_plus)
expr_sbvalue = frame.EvaluateExpression (addr_expr_str, expr_options) expr_sbvalue = frame.EvaluateExpression(
addr_expr_str, expr_options)
if expr_sbvalue.error.Success(): if expr_sbvalue.error.Success():
isa = expr_sbvalue.unsigned isa = expr_sbvalue.unsigned
if isa: if isa:
options.type = 'isa' options.type = 'isa'
result.AppendMessage('Searching for all instances of classes or subclasses of "%s" (isa=0x%x)' % (class_name, isa)) result.AppendMessage(
user_init_code = user_init_code_format % (options.max_matches, num_objc_classes, isa) 'Searching for all instances of classes or subclasses of "%s" (isa=0x%x)' %
expr = get_iterate_memory_expr(options, process, user_init_code, user_return_code) (class_name, isa))
user_init_code = user_init_code_format % (
options.max_matches, num_objc_classes, isa)
expr = get_iterate_memory_expr(
options, process, user_init_code, user_return_code)
arg_str_description = 'objective C classes with isa 0x%x' % isa arg_str_description = 'objective C classes with isa 0x%x' % isa
display_match_results (process, result, options, arg_str_description, expr, True, expr_prefix) display_match_results(
process,
result,
options,
arg_str_description,
expr,
True,
expr_prefix)
else: else:
result.AppendMessage('error: Can\'t find isa for an ObjC class named "%s"' % (class_name)) result.AppendMessage(
'error: Can\'t find isa for an ObjC class named "%s"' %
(class_name))
else: else:
result.AppendMessage('error: expression error for "%s": %s' % (addr_expr_str, expr_sbvalue.error)) result.AppendMessage(
'error: expression error for "%s": %s' %
(addr_expr_str, expr_sbvalue.error))
else: else:
result.AppendMessage('error: command takes one or more C string arguments'); result.AppendMessage(
'error: command takes one or more C string arguments')
if __name__ == '__main__': if __name__ == '__main__':
lldb.debugger = lldb.SBDebugger.Create() lldb.debugger = lldb.SBDebugger.Create()
@ -1229,16 +1501,22 @@ ptr_refs.__doc__ = get_ptr_refs_options().format_help()
cstr_refs.__doc__ = get_cstr_refs_options().format_help() cstr_refs.__doc__ = get_cstr_refs_options().format_help()
malloc_info.__doc__ = get_malloc_info_options().format_help() malloc_info.__doc__ = get_malloc_info_options().format_help()
objc_refs.__doc__ = get_objc_refs_options().format_help() objc_refs.__doc__ = get_objc_refs_options().format_help()
lldb.debugger.HandleCommand('command script add -f %s.ptr_refs ptr_refs' % __name__) lldb.debugger.HandleCommand(
lldb.debugger.HandleCommand('command script add -f %s.cstr_refs cstr_refs' % __name__) 'command script add -f %s.ptr_refs ptr_refs' %
lldb.debugger.HandleCommand('command script add -f %s.malloc_info malloc_info' % __name__) __name__)
lldb.debugger.HandleCommand('command script add -f %s.find_variable find_variable' % __name__) lldb.debugger.HandleCommand(
'command script add -f %s.cstr_refs cstr_refs' %
__name__)
lldb.debugger.HandleCommand(
'command script add -f %s.malloc_info malloc_info' %
__name__)
lldb.debugger.HandleCommand(
'command script add -f %s.find_variable find_variable' %
__name__)
# lldb.debugger.HandleCommand('command script add -f %s.heap heap' % package_name) # lldb.debugger.HandleCommand('command script add -f %s.heap heap' % package_name)
# lldb.debugger.HandleCommand('command script add -f %s.section_ptr_refs section_ptr_refs' % package_name) # lldb.debugger.HandleCommand('command script add -f %s.section_ptr_refs section_ptr_refs' % package_name)
# lldb.debugger.HandleCommand('command script add -f %s.stack_ptr_refs stack_ptr_refs' % package_name) # lldb.debugger.HandleCommand('command script add -f %s.stack_ptr_refs stack_ptr_refs' % package_name)
lldb.debugger.HandleCommand('command script add -f %s.objc_refs objc_refs' % __name__) lldb.debugger.HandleCommand(
'command script add -f %s.objc_refs objc_refs' %
__name__)
print '"malloc_info", "ptr_refs", "cstr_refs", "find_variable", and "objc_refs" commands have been installed, use the "--help" options on these commands for detailed help.' print '"malloc_info", "ptr_refs", "cstr_refs", "find_variable", and "objc_refs" commands have been installed, use the "--help" options on these commands for detailed help.'

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -19,11 +19,11 @@
#include "LLDB/SBDebugger.h" #include "LLDB/SBDebugger.h"
#include "LLDB/SBFunction.h" #include "LLDB/SBFunction.h"
#include "LLDB/SBModule.h" #include "LLDB/SBModule.h"
#include "LLDB/SBProcess.h"
#include "LLDB/SBStream.h" #include "LLDB/SBStream.h"
#include "LLDB/SBSymbol.h" #include "LLDB/SBSymbol.h"
#include "LLDB/SBTarget.h" #include "LLDB/SBTarget.h"
#include "LLDB/SBThread.h" #include "LLDB/SBThread.h"
#include "LLDB/SBProcess.h"
#endif #endif
#include <string> #include <string>
@ -44,10 +44,10 @@ using namespace lldb;
// //
// then (for example): // 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: public:
LLDBSentry() { LLDBSentry() {
// Initialize LLDB // Initialize LLDB
@ -59,38 +59,33 @@ public:
} }
}; };
static struct option g_long_options[] = static struct option g_long_options[] = {
{
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"verbose", no_argument, NULL, 'v'}, {"verbose", no_argument, NULL, 'v'},
{"arch", required_argument, NULL, 'a'}, {"arch", required_argument, NULL, 'a'},
{"platform", required_argument, NULL, 'p'}, {"platform", required_argument, NULL, 'p'},
{ NULL, 0, NULL, 0 } {NULL, 0, NULL, 0}};
};
#define PROGRAM_NAME "lldb-lookup" #define PROGRAM_NAME "lldb-lookup"
void void usage() {
usage () puts("NAME\n"
{
puts (
"NAME\n"
" " PROGRAM_NAME " -- symbolicate addresses using lldb.\n" " " PROGRAM_NAME " -- symbolicate addresses using lldb.\n"
"\n" "\n"
"SYNOPSIS\n" "SYNOPSIS\n"
" " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] [--verbose] [--help] --] <PATH> <ADDRESS> [<ADDRESS>....]\n" " " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] "
"[--verbose] [--help] --] <PATH> <ADDRESS> "
"[<ADDRESS>....]\n"
"\n" "\n"
"DESCRIPTION\n" "DESCRIPTION\n"
" Loads the executable pointed to by <PATH> and looks up and <ADDRESS>\n" " Loads the executable pointed to by <PATH> and looks up and "
"<ADDRESS>\n"
" arguments\n" " arguments\n"
"\n" "\n"
"EXAMPLE\n" "EXAMPLE\n"
" " PROGRAM_NAME " --arch=x86_64 -- /usr/lib/dyld 0x100000000\n" " " PROGRAM_NAME " --arch=x86_64 -- /usr/lib/dyld 0x100000000\n");
);
exit(0); exit(0);
} }
int int main(int argc, char const *argv[]) {
main (int argc, char const *argv[])
{
// Use a sentry object to properly initialize/terminate LLDB. // Use a sentry object to properly initialize/terminate LLDB.
LLDBSentry sentry; LLDBSentry sentry;
@ -105,13 +100,10 @@ main (int argc, char const *argv[])
const char *arch = NULL; const char *arch = NULL;
const char *platform = NULL; const char *platform = NULL;
std::string short_options("h?"); std::string short_options("h?");
for (const struct option *opt = g_long_options; opt->name; ++opt) for (const struct option *opt = g_long_options; opt->name; ++opt) {
{ if (isprint(opt->val)) {
if (isprint(opt->val))
{
short_options.append(1, (char)opt->val); short_options.append(1, (char)opt->val);
switch (opt->has_arg) switch (opt->has_arg) {
{
case no_argument: case no_argument:
break; break;
case required_argument: case required_argument:
@ -130,17 +122,17 @@ main (int argc, char const *argv[])
optind = 1; optind = 1;
#endif #endif
char ch; char ch;
while ((ch = getopt_long_only(argc, (char * const *)argv, short_options.c_str(), g_long_options, 0)) != -1) while ((ch = getopt_long_only(argc, (char *const *)argv,
{ short_options.c_str(), g_long_options, 0)) !=
switch (ch) -1) {
{ switch (ch) {
case 0: case 0:
break; break;
case 'a': case 'a':
if (arch != NULL) if (arch != NULL) {
{ fprintf(stderr,
fprintf (stderr, "error: the --arch option can only be specified once\n"); "error: the --arch option can only be specified once\n");
exit(1); exit(1);
} }
arch = optarg; arch = optarg;
@ -176,27 +168,22 @@ main (int argc, char const *argv[])
SBStream strm; SBStream strm;
strm.RedirectToFileHandle(stdout, false); strm.RedirectToFileHandle(stdout, false);
while ((addr_cstr = argv[++arg_idx]) != NULL) while ((addr_cstr = argv[++arg_idx]) != NULL) {
{
// The second argument in the address that we want to lookup // The second argument in the address that we want to lookup
lldb::addr_t file_addr = strtoull(addr_cstr, NULL, 0); lldb::addr_t file_addr = strtoull(addr_cstr, NULL, 0);
// Create a target using the executable. // Create a target using the executable.
SBTarget target = debugger.CreateTarget (exe_file_path, SBTarget target = debugger.CreateTarget(exe_file_path, arch, platform,
arch, add_dependent_libs, error);
platform, if (!error.Success()) {
add_dependent_libs,
error);
if (!error.Success())
{
fprintf(stderr, "error: %s\n", error.GetCString()); fprintf(stderr, "error: %s\n", error.GetCString());
exit(1); exit(1);
} }
printf ("%sLooking up 0x%llx in '%s':\n", (arg_idx > 1) ? "\n" : "", file_addr, exe_file_path); printf("%sLooking up 0x%llx in '%s':\n", (arg_idx > 1) ? "\n" : "",
file_addr, exe_file_path);
if (target.IsValid()) if (target.IsValid()) {
{
// Find the executable module so we can do a lookup inside it // Find the executable module so we can do a lookup inside it
SBFileSpec exe_file_spec(exe_file_path, true); SBFileSpec exe_file_spec(exe_file_path, true);
SBModule module(target.FindModule(exe_file_spec)); SBModule module(target.FindModule(exe_file_spec));
@ -205,8 +192,7 @@ main (int argc, char const *argv[])
// address that can be used to do a symbol lookup by address // address that can be used to do a symbol lookup by address
SBAddress addr = module.ResolveFileAddress(file_addr); SBAddress addr = module.ResolveFileAddress(file_addr);
bool success = addr.IsValid() && addr.GetSection().IsValid(); bool success = addr.IsValid() && addr.GetSection().IsValid();
if (success) if (success) {
{
// We can resolve a section offset address in the module // We can resolve a section offset address in the module
// and only ask for what we need. You can logical or together // and only ask for what we need. You can logical or together
// bits from the SymbolContextItem enumeration found in // bits from the SymbolContextItem enumeration found in
@ -215,21 +201,22 @@ main (int argc, char const *argv[])
// //
// NOTE: the less you ask for, the less LLDB will parse as // NOTE: the less you ask for, the less LLDB will parse as
// LLDB does partial parsing on just about everything. // LLDB does partial parsing on just about everything.
SBSymbolContext sc (module.ResolveSymbolContextForAddress (addr, eSymbolContextEverything)); SBSymbolContext sc(module.ResolveSymbolContextForAddress(
addr, eSymbolContextEverything));
strm.Printf (" Address: %s + 0x%llx\n Summary: ", addr.GetSection().GetName (), addr.GetOffset()); strm.Printf(" Address: %s + 0x%llx\n Summary: ",
addr.GetSection().GetName(), addr.GetOffset());
addr.GetDescription(strm); addr.GetDescription(strm);
strm.Printf("\n"); strm.Printf("\n");
if (verbose) if (verbose)
sc.GetDescription(strm); sc.GetDescription(strm);
} } else {
else printf(
{ "error: 0x%llx does not resolve to a valid file address in '%s'\n",
printf ("error: 0x%llx does not resolve to a valid file address in '%s'\n", file_addr, exe_file_path); file_addr, exe_file_path);
} }
} }
} }
return 0; return 0;
} }

View File

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

View File

@ -14,6 +14,7 @@ import commands
import optparse import optparse
import shlex import shlex
def create_framestats_options(): def create_framestats_options():
usage = "usage: %prog [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
@ -21,13 +22,41 @@ 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 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. 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 = optparse.OptionParser(
parser.add_option('-i', '--in-scope', action='store_true', dest='inscope', help='in_scope_only = True', default=False) description=description,
parser.add_option('-a', '--arguments', action='store_true', dest='arguments', help='arguments = True', default=False) prog='framestats',
parser.add_option('-l', '--locals', action='store_true', dest='locals', help='locals = True', default=False) usage=usage)
parser.add_option('-s', '--statics', action='store_true', dest='statics', help='statics = True', default=False) 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 return parser
def the_framestats_command(debugger, command, result, dict): def the_framestats_command(debugger, command, result, dict):
# Use the Shell Lexer to properly parse up command options just like a # Use the Shell Lexer to properly parse up command options just like a
# shell would # shell would
@ -51,7 +80,11 @@ def the_framestats_command(debugger, command, result, dict):
if not frame.IsValid(): if not frame.IsValid():
return "no frame here" return "no frame here"
# from now on, replace lldb.<thing>.whatever with <thing>.whatever # 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() variables_count = variables_list.GetSize()
if variables_count == 0: if variables_count == 0:
print >> result, "no variables here" print >> result, "no variables here"
@ -62,9 +95,11 @@ def the_framestats_command(debugger, command, result, dict):
variable_type = variable.GetType() variable_type = variable.GetType()
total_size = total_size + variable_type.GetByteSize() total_size = total_size + variable_type.GetByteSize()
average_size = float(total_size) / variables_count 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 # 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 # 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 # Make the options so we can generate the help text for the new LLDB
@ -72,5 +107,6 @@ def __lldb_init_module (debugger, dict):
parser = create_framestats_options() parser = create_framestats_options()
the_framestats_command.__doc__ = parser.format_help() the_framestats_command.__doc__ = parser.format_help()
# Add any commands contained in this module to LLDB # 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.' print 'The "framestats" command has been installed, type "help framestats" or "framestats --help" for detailed help.'

View File

@ -53,9 +53,14 @@ except ImportError:
# On Darwin, try the currently selected Xcode directory # On Darwin, try the currently selected Xcode directory
xcode_dir = commands.getoutput("xcode-select --print-path") xcode_dir = commands.getoutput("xcode-select --print-path")
if xcode_dir: if xcode_dir:
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python')) lldb_python_dirs.append(
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') os.path.realpath(
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') 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 success = False
for lldb_python_dir in lldb_python_dirs: for lldb_python_dir in lldb_python_dirs:
if os.path.exists(lldb_python_dir): if os.path.exists(lldb_python_dir):
@ -81,19 +86,24 @@ PARSE_MODE_IMAGES = 2
PARSE_MODE_THREGS = 3 PARSE_MODE_THREGS = 3
PARSE_MODE_SYSTEM = 4 PARSE_MODE_SYSTEM = 4
class CrashLog(symbolication.Symbolicator): class CrashLog(symbolication.Symbolicator):
"""Class that does parses darwin crash logs""" """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_state_regex = re.compile('^Thread ([0-9]+) crashed with')
thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)') 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]+) +(.*)') 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_uuid = re.compile(
image_regex_no_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^/]+)/(.*)'); '(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('^$') empty_line_regex = re.compile('^$')
class Thread: class Thread:
"""Class that represents a thread in a darwin crash log""" """Class that represents a thread in a darwin crash log"""
def __init__(self, index, app_specific_backtrace): def __init__(self, index, app_specific_backtrace):
self.index = index self.index = index
self.frames = list() self.frames = list()
@ -128,25 +138,31 @@ class CrashLog(symbolication.Symbolicator):
#prev_frame_index = -1 #prev_frame_index = -1
display_frame_idx = -1 display_frame_idx = -1
for frame_idx, frame in enumerate(self.frames): 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: 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: else:
# Any frame above frame zero and we have to subtract one to get the previous line entry # Any frame above frame zero and we have to subtract one to
symbolicated_frame_addresses = crash_log.symbolicate ((frame.pc & crash_log.addr_mask) - 1, options.verbose) # get the previous line entry
symbolicated_frame_addresses = crash_log.symbolicate(
(frame.pc & crash_log.addr_mask) - 1, options.verbose)
if symbolicated_frame_addresses: if symbolicated_frame_addresses:
symbolicated_frame_address_idx = 0 symbolicated_frame_address_idx = 0
for symbolicated_frame_address in symbolicated_frame_addresses: for symbolicated_frame_address in symbolicated_frame_addresses:
display_frame_idx += 1 display_frame_idx += 1
print '[%3u] %s' % (frame_idx, symbolicated_frame_address) 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 source_context = options.source_context
line_entry = symbolicated_frame_address.get_symbol_context().line_entry line_entry = symbolicated_frame_address.get_symbol_context().line_entry
if line_entry.IsValid(): if line_entry.IsValid():
strm = lldb.SBStream() strm = lldb.SBStream()
if line_entry: 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() source_text = strm.GetData()
if source_text: if source_text:
# Indent the source a bit # Indent the source a bit
@ -158,22 +174,24 @@ class CrashLog(symbolication.Symbolicator):
instructions = symbolicated_frame_address.get_instructions() instructions = symbolicated_frame_address.get_instructions()
if instructions: if instructions:
print print
symbolication.disassemble_instructions (crash_log.get_target(), symbolication.disassemble_instructions(
crash_log.get_target(),
instructions, instructions,
frame.pc, frame.pc,
options.disassemble_before, options.disassemble_before,
options.disassemble_after, frame.index > 0) options.disassemble_after,
frame.index > 0)
print print
symbolicated_frame_address_idx += 1 symbolicated_frame_address_idx += 1
else: else:
print frame print frame
def add_ident(self, ident): def add_ident(self, ident):
if not ident in self.idents: if ident not in self.idents:
self.idents.append(ident) self.idents.append(ident)
def did_crash(self): def did_crash(self):
return self.reason != None return self.reason is not None
def __str__(self): def __str__(self):
if self.app_specific_backtrace: if self.app_specific_backtrace:
@ -184,9 +202,9 @@ class CrashLog(symbolication.Symbolicator):
s += ' %s' % self.reason s += ' %s' % self.reason
return s return s
class Frame: class Frame:
"""Class that represents a stack frame in a thread in a darwin crash log""" """Class that represents a stack frame in a thread in a darwin crash log"""
def __init__(self, index, pc, description): def __init__(self, index, pc, description):
self.pc = pc self.pc = pc
self.description = description self.description = description
@ -194,7 +212,8 @@ class CrashLog(symbolication.Symbolicator):
def __str__(self): def __str__(self):
if self.description: 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: else:
return "[%3u] 0x%16.16x" % (self.index, self.pc) return "[%3u] 0x%16.16x" % (self.index, self.pc)
@ -207,11 +226,23 @@ class CrashLog(symbolication.Symbolicator):
if not os.path.exists(dsymForUUIDBinary): if not os.path.exists(dsymForUUIDBinary):
dsymForUUIDBinary = commands.getoutput('which dsymForUUID') 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): def __init__(
symbolication.Image.__init__(self, path, uuid); self,
self.add_section (symbolication.Section(text_addr_lo, text_addr_hi, "__TEXT")) 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.identifier = identifier
self.version = version self.version = version
@ -224,7 +255,8 @@ class CrashLog(symbolication.Symbolicator):
uuid_str = self.get_normalized_uuid_string() uuid_str = self.get_normalized_uuid_string()
print 'Getting symbols for %s %s...' % (uuid_str, self.path), print 'Getting symbols for %s %s...' % (uuid_str, self.path),
if os.path.exists(self.dsymForUUIDBinary): 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) s = commands.getoutput(dsym_for_uuid_command)
if s: if s:
plist_root = plistlib.readPlistFromString(s) plist_root = plistlib.readPlistFromString(s)
@ -234,12 +266,15 @@ class CrashLog(symbolication.Symbolicator):
if 'DBGArchitecture' in plist: if 'DBGArchitecture' in plist:
self.arch = plist['DBGArchitecture'] self.arch = plist['DBGArchitecture']
if 'DBGDSYMPath' in plist: if 'DBGDSYMPath' in plist:
self.symfile = os.path.realpath(plist['DBGDSYMPath']) self.symfile = os.path.realpath(
plist['DBGDSYMPath'])
if 'DBGSymbolRichExecutable' in plist: if 'DBGSymbolRichExecutable' in plist:
self.path = os.path.expanduser (plist['DBGSymbolRichExecutable']) self.path = os.path.expanduser(
plist['DBGSymbolRichExecutable'])
self.resolved_path = self.path self.resolved_path = self.path
if not self.resolved_path and os.path.exists(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() self_uuid = self.get_uuid()
for line in dwarfdump_cmd_output.splitlines(): for line in dwarfdump_cmd_output.splitlines():
match = self.dwarfdump_uuid_regex.search(line) match = self.dwarfdump_uuid_regex.search(line)
@ -249,12 +284,13 @@ class CrashLog(symbolication.Symbolicator):
if self_uuid == dwarf_uuid: if self_uuid == dwarf_uuid:
self.resolved_path = self.path self.resolved_path = self.path
self.arch = match.group(2) self.arch = match.group(2)
break; break
if not self.resolved_path: if not self.resolved_path:
self.unavailable = True self.unavailable = True
print "error\n error: unable to locate '%s' with UUID %s" % (self.path, uuid_str) print "error\n error: unable to locate '%s' with UUID %s" % (self.path, uuid_str)
return False 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' print 'ok'
# if self.resolved_path: # if self.resolved_path:
# print ' exe = "%s"' % self.resolved_path # print ' exe = "%s"' % self.resolved_path
@ -265,12 +301,10 @@ class CrashLog(symbolication.Symbolicator):
self.unavailable = True self.unavailable = True
return False return False
def __init__(self, path): def __init__(self, path):
"""CrashLog constructor that take a path to a darwin crash log file""" """CrashLog constructor that take a path to a darwin crash log file"""
symbolication.Symbolicator.__init__(self); symbolication.Symbolicator.__init__(self)
self.path = os.path.expanduser(path); self.path = os.path.expanduser(path)
self.info_lines = list() self.info_lines = list()
self.system_profile = list() self.system_profile = list()
self.threads = list() self.threads = list()
@ -280,7 +314,8 @@ class CrashLog(symbolication.Symbolicator):
self.version = -1 self.version = -1
self.error = None self.error = None
self.target = 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: try:
f = open(self.path) f = open(self.path)
except IOError: except IOError:
@ -317,7 +352,8 @@ class CrashLog(symbolication.Symbolicator):
# print 'PARSE_MODE_NORMAL' # print 'PARSE_MODE_NORMAL'
elif parse_mode == PARSE_MODE_NORMAL: elif parse_mode == PARSE_MODE_NORMAL:
if line.startswith('Process:'): if line.startswith('Process:'):
(self.process_name, pid_with_brackets) = line[8:].strip().split(' [') (self.process_name, pid_with_brackets) = line[
8:].strip().split(' [')
self.process_id = pid_with_brackets.strip('[]') self.process_id = pid_with_brackets.strip('[]')
elif line.startswith('Path:'): elif line.startswith('Path:'):
self.process_path = line[5:].strip() self.process_path = line[5:].strip()
@ -328,12 +364,14 @@ class CrashLog(symbolication.Symbolicator):
matched_pair = re.search("(.+)\((.+)\)", version_string) matched_pair = re.search("(.+)\((.+)\)", version_string)
if matched_pair: if matched_pair:
self.process_version = matched_pair.group(1) self.process_version = matched_pair.group(1)
self.process_compatability_version = matched_pair.group(2) self.process_compatability_version = matched_pair.group(
2)
else: else:
self.process = version_string self.process = version_string
self.process_compatability_version = version_string self.process_compatability_version = version_string
elif self.parent_process_regex.search(line): 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_name = parent_process_match.group(1)
self.parent_process_id = parent_process_match.group(2) self.parent_process_id = parent_process_match.group(2)
elif line.startswith('Exception Type:'): elif line.startswith('Exception Type:'):
@ -393,9 +431,10 @@ class CrashLog(symbolication.Symbolicator):
if frame_match: if frame_match:
ident = frame_match.group(2) ident = frame_match.group(2)
thread.add_ident(ident) thread.add_ident(ident)
if not ident in self.idents: if ident not in self.idents:
self.idents.append(ident) 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: else:
print 'error: frame regex failed for line: "%s"' % line print 'error: frame regex failed for line: "%s"' % line
elif parse_mode == PARSE_MODE_IMAGES: elif parse_mode == PARSE_MODE_IMAGES:
@ -424,7 +463,8 @@ class CrashLog(symbolication.Symbolicator):
elif parse_mode == PARSE_MODE_THREGS: elif parse_mode == PARSE_MODE_THREGS:
stripped_line = line.strip() stripped_line = line.strip()
# "r12: 0x00007fff6b5939c8 r13: 0x0000000007000006 r14: 0x0000000000002a03 r15: 0x0000000000000c00" # "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: for reg_value in reg_values:
# print 'reg_value = "%s"' % reg_value # print 'reg_value = "%s"' % reg_value
(reg, value) = reg_value.split(': ') (reg, value) = reg_value.split(': ')
@ -465,7 +505,8 @@ class CrashLog(symbolication.Symbolicator):
self.target = symbolication.Symbolicator.create_target(self) self.target = symbolication.Symbolicator.create_target(self)
if self.target: if self.target:
return 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' print 'crashlog.create_target()...2'
if self.idents: if self.idents:
for ident in self.idents: for ident in self.idents:
@ -486,10 +527,12 @@ class CrashLog(symbolication.Symbolicator):
def get_target(self): def get_target(self):
return self.target return self.target
def usage(): def usage():
print "Usage: lldb-symbolicate.py [-n name] executable-image" print "Usage: lldb-symbolicate.py [-n name] executable-image"
sys.exit(0) sys.exit(0)
class Interactive(cmd.Cmd): class Interactive(cmd.Cmd):
'''Interactive prompt for analyzing one or more Darwin crash logs, type "help" to see a list of supported commands.''' '''Interactive prompt for analyzing one or more Darwin crash logs, type "help" to see a list of supported commands.'''
image_option_parser = None image_option_parser = None
@ -518,7 +561,8 @@ class Interactive(cmd.Cmd):
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 inlined stack frames back to the concrete functions, and disassemble the location of the crash
for the first frame of the crashed thread.''' 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) command_args = shlex.split(line)
try: try:
(options, args) = option_parser.parse_args(command_args) (options, args) = option_parser.parse_args(command_args)
@ -534,7 +578,8 @@ class Interactive(cmd.Cmd):
else: else:
print 'error: crash log index %u is out of range' % (idx) print 'error: crash log index %u is out of range' % (idx)
else: 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)): for idx in range(len(self.crash_logs)):
SymbolicateCrashLog(self.crash_logs[idx], options) SymbolicateCrashLog(self.crash_logs[idx], options)
@ -552,8 +597,14 @@ class Interactive(cmd.Cmd):
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) command_args = shlex.split(line)
if not self.image_option_parser: if not self.image_option_parser:
self.image_option_parser = optparse.OptionParser(description=description, prog='image',usage=usage) self.image_option_parser = optparse.OptionParser(
self.image_option_parser.add_option('-a', '--all', action='store_true', help='show all images', default=False) description=description, prog='image', usage=usage)
self.image_option_parser.add_option(
'-a',
'--all',
action='store_true',
help='show all images',
default=False)
try: try:
(options, args) = self.image_option_parser.parse_args(command_args) (options, args) = self.image_option_parser.parse_args(command_args)
except: except:
@ -577,7 +628,8 @@ class Interactive(cmd.Cmd):
if matches_found == 0: if matches_found == 0:
for (image_idx, image) in enumerate(crash_log.images): for (image_idx, image) in enumerate(crash_log.images):
resolved_image_path = image.get_resolved_path() 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 print '[%u] ' % (crash_log_idx), image
else: else:
for crash_log in self.crash_logs: for crash_log in self.crash_logs:
@ -592,7 +644,7 @@ def interactive_crashlogs(options, args):
for resolved_path in glob.glob(arg): for resolved_path in glob.glob(arg):
crash_log_files.append(resolved_path) crash_log_files.append(resolved_path)
crash_logs = list(); crash_logs = list()
for crash_log_file in crash_log_files: 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) crash_log = CrashLog(crash_log_file)
@ -616,19 +668,31 @@ def interactive_crashlogs(options, args):
def save_crashlog(debugger, command, result, dict): def save_crashlog(debugger, command, result, dict):
usage = "usage: %prog [options] <output-path>" usage = "usage: %prog [options] <output-path>"
description = '''Export the state of current target into a crashlog file''' description = '''Export the state of current target into a crashlog file'''
parser = optparse.OptionParser(description=description, prog='save_crashlog',usage=usage) parser = optparse.OptionParser(
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) 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: try:
(options, args) = parser.parse_args(shlex.split(command)) (options, args) = parser.parse_args(shlex.split(command))
except: except:
result.PutCString ("error: invalid options"); result.PutCString("error: invalid options")
return return
if len(args) != 1: 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 return
out_file = open(args[0], 'w') out_file = open(args[0], 'w')
if not out_file: 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 return
target = debugger.GetSelectedTarget() target = debugger.GetSelectedTarget()
if target: if target:
@ -636,11 +700,16 @@ def save_crashlog(debugger, command, result, dict):
if lldb.process: if lldb.process:
pid = lldb.process.id pid = lldb.process.id
if pid != lldb.LLDB_INVALID_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('Path: %s\n' % (target.executable.fullpath))
out_file.write('Identifier: %s\n' % (identifier)) 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('\nDate/Time: %s\n' %
out_file.write('OS Version: Mac OS X %s (%s)\n' % (platform.mac_ver()[0], commands.getoutput('sysctl -n kern.osversion'))); (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') out_file.write('Report Version: 9\n')
for thread_idx in range(lldb.process.num_threads): for thread_idx in range(lldb.process.num_threads):
thread = lldb.process.thread[thread_idx] 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 frame_offset = frame_pc - frame.function.addr.load_addr
elif frame.symbol: elif frame.symbol:
frame_offset = frame_pc - frame.symbol.addr.load_addr 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: if frame_offset > 0:
out_file.write(' + %u' % (frame_offset)) out_file.write(' + %u' % (frame_offset))
line_entry = frame.line_entry line_entry = frame.line_entry
@ -667,7 +738,9 @@ def save_crashlog(debugger, command, result, dict):
# This will output the fullpath + line + column # This will output the fullpath + line + column
out_file.write(' %s' % (line_entry)) out_file.write(' %s' % (line_entry))
else: 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 column = line_entry.column
if column: if column:
out_file.write(':%u' % (column)) out_file.write(':%u' % (column))
@ -684,11 +757,19 @@ def save_crashlog(debugger, command, result, dict):
module_version = '???' module_version = '???'
module_version_array = module.GetVersion() module_version_array = module.GetVersion()
if module_version_array: if module_version_array:
module_version = '.'.join(map(str,module_version_array)) module_version = '.'.join(
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)) 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() out_file.close()
else: else:
result.PutCString ("error: invalid target"); result.PutCString("error: invalid target")
def Symbolicate(debugger, command, result, dict): def Symbolicate(debugger, command, result, dict):
@ -697,6 +778,7 @@ def Symbolicate(debugger, command, result, dict):
except: 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): def SymbolicateCrashLog(crash_log, options):
if crash_log.error: if crash_log.error:
print crash_log.error print crash_log.error
@ -747,7 +829,7 @@ def SymbolicateCrashLog(crash_log, options):
print 'error: can\'t find image for identifier "%s"' % ident print 'error: can\'t find image for identifier "%s"' % ident
for image in images_to_load: for image in images_to_load:
if not image in loaded_images: if image not in loaded_images:
err = image.add_module(target) err = image.add_module(target)
if err: if err:
print err print err
@ -765,26 +847,113 @@ def SymbolicateCrashLog(crash_log, options):
print print
def CreateSymbolicateCrashLogOptions(command_name, description, add_interactive_options): def CreateSymbolicateCrashLogOptions(
command_name,
description,
add_interactive_options):
usage = "usage: %prog [options] <FILE> [FILE ...]" usage = "usage: %prog [options] <FILE> [FILE ...]"
option_parser = optparse.OptionParser(description=description, prog='crashlog',usage=usage) option_parser = optparse.OptionParser(
option_parser.add_option('--verbose' , '-v', action='store_true', dest='verbose', help='display verbose debug info', default=False) description=description, prog='crashlog', usage=usage)
option_parser.add_option('--debug' , '-g', action='store_true', dest='debug', help='display verbose debug logging', default=False) option_parser.add_option(
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) '--verbose',
option_parser.add_option('--images' , action='store_true', dest='dump_image_list', help='show image list', default=False) '-v',
option_parser.add_option('--debug-delay' , type='int', dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for debugger', default=0) action='store_true',
option_parser.add_option('--crashed-only' , '-c', action='store_true', dest='crashed_only', help='only symbolicate the crashed thread', default=False) dest='verbose',
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) help='display verbose debug info',
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) 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(
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) '--debug',
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) '-g',
option_parser.add_option('--source-frames' , type='int', metavar='NFRAMES', dest='source_frames', help='show source for NFRAMES (default = 4)', default=4) action='store_true',
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) 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: 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 return option_parser
def SymbolicateCrashLogs(command_args): 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 inlined stack frames back to the concrete functions, and disassemble the location of the crash
@ -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 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 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.''' 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: try:
(options, args) = option_parser.parse_args(command_args) (options, args) = option_parser.parse_args(command_args)
except: except:
@ -823,7 +993,8 @@ if __name__ == '__main__':
SymbolicateCrashLogs(sys.argv[1:]) SymbolicateCrashLogs(sys.argv[1:])
lldb.SBDebugger.Destroy(lldb.debugger) lldb.SBDebugger.Destroy(lldb.debugger)
elif getattr(lldb, 'debugger', None): elif getattr(lldb, 'debugger', None):
lldb.debugger.HandleCommand('command script add -f lldb.macosx.crashlog.Symbolicate crashlog') lldb.debugger.HandleCommand(
lldb.debugger.HandleCommand('command script add -f lldb.macosx.crashlog.save_crashlog save_crashlog') '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' print '"crashlog" and "save_crashlog" command installed, use the "--help" option for detailed help'

View File

@ -23,13 +23,16 @@ import shlex
import re import re
import tempfile import tempfile
def start_gdb_log(debugger, command, result, dict): def start_gdb_log(debugger, command, result, dict):
'''Start logging GDB remote packets by enabling logging with timestamps and '''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" thread safe logging. Follow a call to this function with a call to "stop_gdb_log"
in order to dump out the commands.''' in order to dump out the commands.'''
global log_file global log_file
if 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: else:
args_len = len(args) args_len = len(args)
if args_len == 0: if args_len == 0:
@ -38,24 +41,39 @@ def start_gdb_log(debugger, command, result, dict):
log_file = args[0] log_file = args[0]
if log_file: if log_file:
debugger.HandleCommand('log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % log_file); debugger.HandleCommand(
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) '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 return
result.PutCString('error: invalid log file path') result.PutCString('error: invalid log file path')
result.PutCString(usage) result.PutCString(usage)
def parse_time_log(debugger, command, result, dict): def parse_time_log(debugger, command, result, dict):
# Any commands whose names might be followed by more valid C identifier # Any commands whose names might be followed by more valid C identifier
# characters must be listed here # characters must be listed here
command_args = shlex.split(command) command_args = shlex.split(command)
parse_time_log_args(command_args) parse_time_log_args(command_args)
def parse_time_log_args(command_args): def parse_time_log_args(command_args):
usage = "usage: parse_time_log [options] [<LOGFILEPATH>]" 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.''' 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 = optparse.OptionParser(
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) 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: try:
(options, args) = parser.parse_args(command_args) (options, args) = parser.parse_args(command_args)
except: except:
@ -63,6 +81,7 @@ def parse_time_log_args(command_args):
for log_file in args: for log_file in args:
parse_log_file(log_file, options) parse_log_file(log_file, options)
def parse_log_file(file, options): def parse_log_file(file, options):
'''Parse a log file that was contains timestamps. These logs are typically '''Parse a log file that was contains timestamps. These logs are typically
generated using: generated using:
@ -101,7 +120,6 @@ def parse_log_file(file, options):
print line print line
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
parse_time_log_args(sys.argv[1:]) parse_time_log_args(sys.argv[1:])
@ -111,5 +129,6 @@ else:
if lldb.debugger: if lldb.debugger:
# This initializer is being run from LLDB in the embedded command interpreter # This initializer is being run from LLDB in the embedded command interpreter
# Add any commands contained in this module to LLDB # 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' print 'The "parse_time_log" command is now installed and ready for use, type "parse_time_log --help" for more information'

View File

@ -1,10 +1,12 @@
# This implements the "diagnose-nsstring" command, usually installed in the debug session like # This implements the "diagnose-nsstring" command, usually installed in the debug session like
# command script import lldb.diagnose # command script import lldb.diagnose
# it is used when NSString summary formatter fails to replicate the logic that went into LLDB making the # 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 import lldb
def read_memory(process, location, size): def read_memory(process, location, size):
data = "" data = ""
error = lldb.SBError() error = lldb.SBError()
@ -33,6 +35,7 @@ def read_memory(process,location,size):
print e print e
return data return data
def diagnose_nsstring_Command_Impl(debugger, command, result, internal_dict): def diagnose_nsstring_Command_Impl(debugger, command, result, internal_dict):
""" """
A command to diagnose the LLDB NSString data formatter A command to diagnose the LLDB NSString data formatter
@ -105,18 +108,20 @@ struct $__lldb__CFString {\
little_endian = (target.byte_order == lldb.eByteOrderLittle) little_endian = (target.byte_order == lldb.eByteOrderLittle)
ptr_size = target.addr_size ptr_size = target.addr_size
info_bits = dumped.GetChildMemberWithName("_cfinfo").GetChildAtIndex(0 if little_endian else 3).GetValueAsUnsigned(0) info_bits = dumped.GetChildMemberWithName("_cfinfo").GetChildAtIndex(
0 if little_endian else 3).GetValueAsUnsigned(0)
is_mutable = (info_bits & 1) == 1 is_mutable = (info_bits & 1) == 1
is_inline = (info_bits & 0x60) == 0 is_inline = (info_bits & 0x60) == 0
has_explicit_length = (info_bits & (1 | 4)) != 4 has_explicit_length = (info_bits & (1 | 4)) != 4
is_unicode = (info_bits & 0x10) == 0x10 is_unicode = (info_bits & 0x10) == 0x10
is_special = (nsstring.GetDynamicValue(lldb.eDynamicCanRunTarget).GetTypeName() == "NSPathStore2") is_special = (
nsstring.GetDynamicValue(
lldb.eDynamicCanRunTarget).GetTypeName() == "NSPathStore2")
has_null = (info_bits & 8) == 8 has_null = (info_bits & 8) == 8
print >>result, "\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n" % \ 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") (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 explicit_length_offset = 0
if not has_null and has_explicit_length and not is_special: if not has_null and has_explicit_length and not is_special:
explicit_length_offset = 2 * ptr_size explicit_length_offset = 2 * ptr_size
@ -133,8 +138,10 @@ struct $__lldb__CFString {\
print >>result, "There is no explicit length marker - skipping this step\n" print >>result, "There is no explicit length marker - skipping this step\n"
else: else:
explicit_length_offset = nsstring_address + explicit_length_offset explicit_length_offset = nsstring_address + explicit_length_offset
explicit_length = process.ReadUnsignedFromMemory(explicit_length_offset, 4, error) explicit_length = process.ReadUnsignedFromMemory(
print >>result,"Explicit length location is at 0x%x - read value is %d\n" % (explicit_length_offset,explicit_length) 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: if is_mutable:
location = 2 * ptr_size + nsstring_address location = 2 * ptr_size + nsstring_address
@ -160,11 +167,16 @@ struct $__lldb__CFString {\
location = 2 * ptr_size + nsstring_address location = 2 * ptr_size + nsstring_address
location = process.ReadPointerFromMemory(location, error) location = process.ReadPointerFromMemory(location, error)
print >>result, "Expected data location: 0x%x\n" % (location) 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, "1K of data around location: %s\n" % read_memory(
print >>result,"5K of data around string pointer: %s\n" % read_memory(process,nsstring_address,1024*5) 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): def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand("command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" % __name__) debugger.HandleCommand(
"command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" %
__name__)
print 'The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.' 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)

View File

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

View File

@ -3,6 +3,7 @@ class LookupDictionary(dict):
""" """
a dictionary which can lookup value by key, or keys by value a dictionary which can lookup value by key, or keys by value
""" """
def __init__(self, items=[]): def __init__(self, items=[]):
"""items can be a list of pair_lists or a dictionary""" """items can be a list of pair_lists or a dictionary"""
dict.__init__(self, items) dict.__init__(self, items)
@ -53,7 +54,7 @@ class Enum(LookupDictionary):
def __str__(self): def __str__(self):
s = self.get_first_key_for_value(self.value, None) s = self.get_first_key_for_value(self.value, None)
if s == None: if s is None:
s = "%#8.8x" % self.value s = "%#8.8x" % self.value
return s return s

View File

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

View File

@ -12,10 +12,12 @@ import lldb
import os import os
import sys import sys
def disassemble_instructions(insts): def disassemble_instructions(insts):
for i in insts: for i in insts:
print i print i
def usage(): def usage():
print "Usage: disasm.py [-n name] executable-image" print "Usage: disasm.py [-n name] executable-image"
print " By default, it breaks at and disassembles the 'main' function." print " By default, it breaks at and disassembles the 'main' function."
@ -47,7 +49,8 @@ target = debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
if target: if target:
# If the target is valid set a breakpoint at main # 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 print main_bp
@ -74,18 +77,23 @@ if target:
function = frame.GetFunction() function = frame.GetFunction()
# See if we have debug info (a function) # See if we have debug info (a function)
if 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 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) insts = function.GetInstructions(target)
disassemble_instructions(insts) disassemble_instructions(insts)
else: else:
# See if we have a symbol in the symbol table for where we stopped # See if we have a symbol in the symbol table for where
symbol = frame.GetSymbol(); # we stopped
symbol = frame.GetSymbol()
if symbol: 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 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) insts = symbol.GetInstructions(target)
disassemble_instructions(insts) disassemble_instructions(insts)
@ -115,5 +123,4 @@ if target:
process.Kill() process.Kill()
lldb.SBDebugger.Terminate() lldb.SBDebugger.Terminate()

View File

@ -4,6 +4,7 @@ import string
import struct import struct
import sys import sys
class FileExtract: class FileExtract:
'''Decode binary data from a file''' '''Decode binary data from a file'''
@ -131,7 +132,11 @@ class FileExtract:
else: else:
return fail_value 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''' '''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) s = self.read_size(n)
if s: if s:

View File

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

View File

@ -37,8 +37,10 @@ g_byte_order = 'little'
g_number_regex = re.compile('^(0x[0-9a-fA-F]+|[0-9]+)') g_number_regex = re.compile('^(0x[0-9a-fA-F]+|[0-9]+)')
g_thread_id_regex = re.compile('^(-1|[0-9a-fA-F]+|0)') g_thread_id_regex = re.compile('^(-1|[0-9a-fA-F]+|0)')
class TerminalColors: class TerminalColors:
'''Simple terminal colors class''' '''Simple terminal colors class'''
def __init__(self, enabled=True): def __init__(self, enabled=True):
# TODO: discover terminal type from "file" and disable if # TODO: discover terminal type from "file" and disable if
# it can't handle the color codes # it can't handle the color codes
@ -47,52 +49,52 @@ class TerminalColors:
def reset(self): def reset(self):
'''Reset all terminal colors and formatting.''' '''Reset all terminal colors and formatting.'''
if self.enabled: if self.enabled:
return "\x1b[0m"; return "\x1b[0m"
return '' return ''
def bold(self, on=True): def bold(self, on=True):
'''Enable or disable bold depending on the "on" parameter.''' '''Enable or disable bold depending on the "on" parameter.'''
if self.enabled: if self.enabled:
if on: if on:
return "\x1b[1m"; return "\x1b[1m"
else: else:
return "\x1b[22m"; return "\x1b[22m"
return '' return ''
def italics(self, on=True): def italics(self, on=True):
'''Enable or disable italics depending on the "on" parameter.''' '''Enable or disable italics depending on the "on" parameter.'''
if self.enabled: if self.enabled:
if on: if on:
return "\x1b[3m"; return "\x1b[3m"
else: else:
return "\x1b[23m"; return "\x1b[23m"
return '' return ''
def underline(self, on=True): def underline(self, on=True):
'''Enable or disable underline depending on the "on" parameter.''' '''Enable or disable underline depending on the "on" parameter.'''
if self.enabled: if self.enabled:
if on: if on:
return "\x1b[4m"; return "\x1b[4m"
else: else:
return "\x1b[24m"; return "\x1b[24m"
return '' return ''
def inverse(self, on=True): def inverse(self, on=True):
'''Enable or disable inverse depending on the "on" parameter.''' '''Enable or disable inverse depending on the "on" parameter.'''
if self.enabled: if self.enabled:
if on: if on:
return "\x1b[7m"; return "\x1b[7m"
else: else:
return "\x1b[27m"; return "\x1b[27m"
return '' return ''
def strike(self, on=True): def strike(self, on=True):
'''Enable or disable strike through depending on the "on" parameter.''' '''Enable or disable strike through depending on the "on" parameter.'''
if self.enabled: if self.enabled:
if on: if on:
return "\x1b[9m"; return "\x1b[9m"
else: else:
return "\x1b[29m"; return "\x1b[29m"
return '' return ''
def black(self, fg=True): def black(self, fg=True):
@ -100,9 +102,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[30m"; return "\x1b[30m"
else: else:
return "\x1b[40m"; return "\x1b[40m"
return '' return ''
def red(self, fg=True): def red(self, fg=True):
@ -110,9 +112,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[31m"; return "\x1b[31m"
else: else:
return "\x1b[41m"; return "\x1b[41m"
return '' return ''
def green(self, fg=True): def green(self, fg=True):
@ -120,9 +122,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[32m"; return "\x1b[32m"
else: else:
return "\x1b[42m"; return "\x1b[42m"
return '' return ''
def yellow(self, fg=True): def yellow(self, fg=True):
@ -130,9 +132,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[33m"; return "\x1b[33m"
else: else:
return "\x1b[43m"; return "\x1b[43m"
return '' return ''
def blue(self, fg=True): def blue(self, fg=True):
@ -140,9 +142,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[34m"; return "\x1b[34m"
else: else:
return "\x1b[44m"; return "\x1b[44m"
return '' return ''
def magenta(self, fg=True): def magenta(self, fg=True):
@ -150,9 +152,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[35m"; return "\x1b[35m"
else: else:
return "\x1b[45m"; return "\x1b[45m"
return '' return ''
def cyan(self, fg=True): def cyan(self, fg=True):
@ -160,9 +162,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[36m"; return "\x1b[36m"
else: else:
return "\x1b[46m"; return "\x1b[46m"
return '' return ''
def white(self, fg=True): def white(self, fg=True):
@ -170,9 +172,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[37m"; return "\x1b[37m"
else: else:
return "\x1b[47m"; return "\x1b[47m"
return '' return ''
def default(self, fg=True): def default(self, fg=True):
@ -180,9 +182,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[39m"; return "\x1b[39m"
else: else:
return "\x1b[49m"; return "\x1b[49m"
return '' return ''
@ -195,15 +197,26 @@ def start_gdb_log(debugger, command, result, dict):
usage = "usage: start_gdb_log [options] [<LOGFILEPATH>]" usage = "usage: start_gdb_log [options] [<LOGFILEPATH>]"
description = '''The command enables GDB remote packet logging with timestamps. The packets will be logged to <LOGFILEPATH> if supplied, or a temporary file will be used. Logging stops when stop_gdb_log is called and the packet times will description = '''The command enables GDB remote packet logging with timestamps. The packets will be logged to <LOGFILEPATH> if supplied, or a temporary file will be used. Logging stops when stop_gdb_log is called and the packet times will
be aggregated and displayed.''' be aggregated and displayed.'''
parser = optparse.OptionParser(description=description, prog='start_gdb_log',usage=usage) parser = optparse.OptionParser(
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) description=description,
prog='start_gdb_log',
usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
try: try:
(options, args) = parser.parse_args(command_args) (options, args) = parser.parse_args(command_args)
except: except:
return return
if g_log_file: if g_log_file:
result.PutCString ('error: logging is already in progress with file "%s"' % g_log_file) result.PutCString(
'error: logging is already in progress with file "%s"' %
g_log_file)
else: else:
args_len = len(args) args_len = len(args)
if args_len == 0: if args_len == 0:
@ -212,13 +225,18 @@ def start_gdb_log(debugger, command, result, dict):
g_log_file = args[0] g_log_file = args[0]
if g_log_file: if g_log_file:
debugger.HandleCommand('log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % g_log_file); debugger.HandleCommand(
result.PutCString ("GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." % g_log_file) 'log enable --threadsafe --timestamp --file "%s" gdb-remote packets' %
g_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." %
g_log_file)
return return
result.PutCString('error: invalid log file path') result.PutCString('error: invalid log file path')
result.PutCString(usage) result.PutCString(usage)
def stop_gdb_log(debugger, command, result, dict): def stop_gdb_log(debugger, command, result, dict):
'''Stop logging GDB remote packets to the file that was specified in a call '''Stop logging GDB remote packets to the file that was specified in a call
to "start_gdb_log" and normalize the timestamps to be relative to the first to "start_gdb_log" and normalize the timestamps to be relative to the first
@ -230,12 +248,45 @@ def stop_gdb_log(debugger, command, result, dict):
command_args = shlex.split(command) command_args = shlex.split(command)
usage = "usage: stop_gdb_log [options]" usage = "usage: stop_gdb_log [options]"
description = '''The command stops a previously enabled GDB remote packet logging command. Packet logging must have been previously enabled with a call to start_gdb_log.''' description = '''The command stops a previously enabled GDB remote packet logging command. Packet logging must have been previously enabled with a call to start_gdb_log.'''
parser = optparse.OptionParser(description=description, prog='stop_gdb_log',usage=usage) parser = optparse.OptionParser(
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) description=description,
parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='display verbose debug info', default=False) prog='stop_gdb_log',
parser.add_option('-C', '--color', action='store_true', dest='color', help='add terminal colors', default=False) usage=usage)
parser.add_option('-c', '--sort-by-count', action='store_true', dest='sort_count', help='display verbose debug info', default=False) parser.add_option(
parser.add_option('-s', '--symbolicate', action='store_true', dest='symbolicate', help='symbolicate addresses in log using current "lldb.target"', default=False) '-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
parser.add_option(
'-q',
'--quiet',
action='store_true',
dest='quiet',
help='display verbose debug info',
default=False)
parser.add_option(
'-C',
'--color',
action='store_true',
dest='color',
help='add terminal colors',
default=False)
parser.add_option(
'-c',
'--sort-by-count',
action='store_true',
dest='sort_count',
help='display verbose debug info',
default=False)
parser.add_option(
'-s',
'--symbolicate',
action='store_true',
dest='symbolicate',
help='symbolicate addresses in log using current "lldb.target"',
default=False)
try: try:
(options, args) = parser.parse_args(command_args) (options, args) = parser.parse_args(command_args)
except: except:
@ -251,34 +302,41 @@ def stop_gdb_log(debugger, command, result, dict):
print "error: can't symbolicate without a target" print "error: can't symbolicate without a target"
if not g_log_file: if not g_log_file:
result.PutCString ('error: logging must have been previously enabled with a call to "stop_gdb_log"') result.PutCString(
'error: logging must have been previously enabled with a call to "stop_gdb_log"')
elif os.path.exists(g_log_file): elif os.path.exists(g_log_file):
if len(args) == 0: if len(args) == 0:
debugger.HandleCommand('log disable gdb-remote packets'); debugger.HandleCommand('log disable gdb-remote packets')
result.PutCString ("GDB packet logging disabled. Logged packets are in '%s'" % g_log_file) result.PutCString(
"GDB packet logging disabled. Logged packets are in '%s'" %
g_log_file)
parse_gdb_log_file(g_log_file, options) parse_gdb_log_file(g_log_file, options)
else: else:
result.PutCString(usage) result.PutCString(usage)
else: else:
print 'error: the GDB packet log file "%s" does not exist' % g_log_file print 'error: the GDB packet log file "%s" does not exist' % g_log_file
def is_hex_byte(str): def is_hex_byte(str):
if len(str) == 2: if len(str) == 2:
return str[0] in string.hexdigits and str[1] in string.hexdigits; return str[0] in string.hexdigits and str[1] in string.hexdigits
return False return False
# global register info list # global register info list
g_register_infos = list() g_register_infos = list()
g_max_register_info_name_len = 0 g_max_register_info_name_len = 0
class RegisterInfo: class RegisterInfo:
"""Class that represents register information""" """Class that represents register information"""
def __init__(self, kvp): def __init__(self, kvp):
self.info = dict() self.info = dict()
for kv in kvp: for kv in kvp:
key = kv[0] key = kv[0]
value = kv[1] value = kv[1]
self.info[key] = value self.info[key] = value
def name(self): def name(self):
'''Get the name of the register.''' '''Get the name of the register.'''
if self.info and 'name' in self.info: if self.info and 'name' in self.info:
@ -310,9 +368,9 @@ class RegisterInfo:
return '0x%8.8x' % (uval) return '0x%8.8x' % (uval)
elif bit_size == 64: elif bit_size == 64:
return '0x%16.16x' % (uval) return '0x%16.16x' % (uval)
bytes = list(); bytes = list()
uval = packet.get_hex_uint8() uval = packet.get_hex_uint8()
while uval != None: while uval is not None:
bytes.append(uval) bytes.append(uval)
uval = packet.get_hex_uint8() uval = packet.get_hex_uint8()
value_str = '0x' value_str = '0x'
@ -331,8 +389,10 @@ class RegisterInfo:
s += "%s=%s " % (key, self.info[key]) s += "%s=%s " % (key, self.info[key])
return s return s
class Packet: class Packet:
"""Class that represents a packet that contains string data""" """Class that represents a packet that contains string data"""
def __init__(self, packet_str): def __init__(self, packet_str):
self.str = packet_str self.str = packet_str
@ -366,7 +426,8 @@ class Packet:
return fail_value return fail_value
def get_hex_uint8(self): def get_hex_uint8(self):
if self.str and len(self.str) >= 2 and self.str[0] in string.hexdigits and self.str[1] in string.hexdigits: if self.str and len(self.str) >= 2 and self.str[
0] in string.hexdigits and self.str[1] in string.hexdigits:
uval = int(self.str[0:2], 16) uval = int(self.str[0:2], 16)
self.str = self.str[2:] self.str = self.str[2:]
return uval return uval
@ -430,7 +491,6 @@ class Packet:
else: else:
return fail_value return fail_value
def get_hex_ascii_str(self, n=0): def get_hex_ascii_str(self, n=0):
hex_chars = self.get_hex_chars(n) hex_chars = self.get_hex_chars(n)
if hex_chars: if hex_chars:
@ -461,16 +521,16 @@ class Packet:
def get_hex_uint(self, byte_order, n=0): def get_hex_uint(self, byte_order, n=0):
if byte_order == 'big': if byte_order == 'big':
hex_str = self.get_hex_chars(n) hex_str = self.get_hex_chars(n)
if hex_str == None: if hex_str is None:
return None return None
return int(hex_str, 16) return int(hex_str, 16)
else: else:
uval = self.get_hex_uint8() uval = self.get_hex_uint8()
if uval == None: if uval is None:
return None return None
uval_result = 0 uval_result = 0
shift = 0 shift = 0
while uval != None: while uval is not None:
uval_result |= (uval << shift) uval_result |= (uval << shift)
shift += 8 shift += 8
uval = self.get_hex_uint8() uval = self.get_hex_uint8()
@ -502,6 +562,8 @@ class Packet:
return len(self.str) return len(self.str)
g_thread_suffix_regex = re.compile(';thread:([0-9a-fA-F]+);') g_thread_suffix_regex = re.compile(';thread:([0-9a-fA-F]+);')
def get_thread_from_thread_suffix(str): def get_thread_from_thread_suffix(str):
if str: if str:
match = g_thread_suffix_regex.match(str) match = g_thread_suffix_regex.match(str)
@ -509,15 +571,18 @@ def get_thread_from_thread_suffix(str):
return int(match.group(1), 16) return int(match.group(1), 16)
return None return None
def cmd_qThreadStopInfo(options, cmd, args): def cmd_qThreadStopInfo(options, cmd, args):
packet = Packet(args) packet = Packet(args)
tid = packet.get_hex_uint('big') tid = packet.get_hex_uint('big')
print "get_thread_stop_info (tid = 0x%x)" % (tid) print "get_thread_stop_info (tid = 0x%x)" % (tid)
def cmd_stop_reply(options, cmd, args): def cmd_stop_reply(options, cmd, args):
print "get_last_stop_info()" print "get_last_stop_info()"
return False return False
def rsp_stop_reply(options, cmd, cmd_args, rsp): def rsp_stop_reply(options, cmd, cmd_args, rsp):
global g_byte_order global g_byte_order
packet = Packet(rsp) packet = Packet(rsp)
@ -532,7 +597,8 @@ def rsp_stop_reply(options, cmd, cmd_args, rsp):
if reg_num < len(g_register_infos): if reg_num < len(g_register_infos):
reg_info = g_register_infos[reg_num] reg_info = g_register_infos[reg_num]
key_value_pair[0] = reg_info.name() key_value_pair[0] = reg_info.name()
key_value_pair[1] = reg_info.get_value_from_hex_string (key_value_pair[1]) key_value_pair[1] = reg_info.get_value_from_hex_string(
key_value_pair[1])
elif key == 'jthreads' or key == 'jstopinfo': elif key == 'jthreads' or key == 'jstopinfo':
key_value_pair[1] = binascii.unhexlify(key_value_pair[1]) key_value_pair[1] = binascii.unhexlify(key_value_pair[1])
key_value_pairs.insert(0, ['signal', signo]) key_value_pairs.insert(0, ['signal', signo])
@ -552,6 +618,7 @@ def cmd_unknown_packet(options, cmd, args):
print "cmd: %s", cmd print "cmd: %s", cmd
return False return False
def cmd_qSymbol(options, cmd, args): def cmd_qSymbol(options, cmd, args):
if args == ':': if args == ':':
print 'ready to serve symbols' print 'ready to serve symbols'
@ -571,6 +638,7 @@ def cmd_qSymbol(options, cmd, args):
else: else:
print 'error: bad command format' print 'error: bad command format'
def rsp_qSymbol(options, cmd, cmd_args, rsp): def rsp_qSymbol(options, cmd, cmd_args, rsp):
if len(rsp) == 0: if len(rsp) == 0:
print "Unsupported" print "Unsupported"
@ -585,11 +653,13 @@ def rsp_qSymbol(options, cmd, cmd_args, rsp):
else: else:
print 'error: response string should start with "qSymbol:": respnse is "%s"' % (rsp) print 'error: response string should start with "qSymbol:": respnse is "%s"' % (rsp)
def cmd_qXfer(options, cmd, args): def cmd_qXfer(options, cmd, args):
# $qXfer:features:read:target.xml:0,1ffff#14 # $qXfer:features:read:target.xml:0,1ffff#14
print "read target special data %s" % (args) print "read target special data %s" % (args)
return True return True
def rsp_qXfer(options, cmd, cmd_args, rsp): def rsp_qXfer(options, cmd, cmd_args, rsp):
data = string.split(cmd_args, ':') data = string.split(cmd_args, ':')
if data[0] == 'features': if data[0] == 'features':
@ -606,25 +676,30 @@ def rsp_qXfer(options, cmd, cmd_args, rsp):
if not 'value_regnums' in reg_element.attrib: if not 'value_regnums' in reg_element.attrib:
reg_info = RegisterInfo([]) reg_info = RegisterInfo([])
if 'name' in reg_element.attrib: if 'name' in reg_element.attrib:
reg_info.info['name'] = reg_element.attrib['name'] reg_info.info[
'name'] = reg_element.attrib['name']
else: else:
reg_info.info['name'] = 'unspecified' reg_info.info['name'] = 'unspecified'
if 'encoding' in reg_element.attrib: if 'encoding' in reg_element.attrib:
reg_info.info['encoding'] = reg_element.attrib['encoding'] reg_info.info['encoding'] = reg_element.attrib[
'encoding']
else: else:
reg_info.info['encoding'] = 'uint' reg_info.info['encoding'] = 'uint'
if 'offset' in reg_element.attrib: if 'offset' in reg_element.attrib:
reg_info.info['offset'] = reg_element.attrib['offset'] reg_info.info[
'offset'] = reg_element.attrib['offset']
if 'bitsize' in reg_element.attrib: if 'bitsize' in reg_element.attrib:
reg_info.info['bitsize'] = reg_element.attrib['bitsize'] reg_info.info[
'bitsize'] = reg_element.attrib['bitsize']
g_register_infos.append(reg_info) g_register_infos.append(reg_info)
print 'XML for "%s":' % (data[2]) print 'XML for "%s":' % (data[2])
ET.dump(xml_root) ET.dump(xml_root)
def cmd_A(options, cmd, args): def cmd_A(options, cmd, args):
print 'launch process:' print 'launch process:'
packet = Packet(args) packet = Packet(args)
while 1: while True:
arg_len = packet.get_number() arg_len = packet.get_number()
if arg_len == -1: if arg_len == -1:
break break
@ -634,13 +709,15 @@ def cmd_A(options, cmd, args):
if arg_idx == -1: if arg_idx == -1:
break break
if not packet.skip_exact_string(','): if not packet.skip_exact_string(','):
break; break
arg_value = packet.get_hex_ascii_str(arg_len) arg_value = packet.get_hex_ascii_str(arg_len)
print 'argv[%u] = "%s"' % (arg_idx, arg_value) print 'argv[%u] = "%s"' % (arg_idx, arg_value)
def cmd_qC(options, cmd, args): def cmd_qC(options, cmd, args):
print "query_current_thread_id()" print "query_current_thread_id()"
def rsp_qC(options, cmd, cmd_args, rsp): def rsp_qC(options, cmd, cmd_args, rsp):
packet = Packet(rsp) packet = Packet(rsp)
if packet.skip_exact_string("QC"): if packet.skip_exact_string("QC"):
@ -649,6 +726,7 @@ def rsp_qC(options, cmd, cmd_args, rsp):
else: else:
print "current_thread_id = old thread ID" print "current_thread_id = old thread ID"
def cmd_query_packet(options, cmd, args): def cmd_query_packet(options, cmd, args):
if args: if args:
print "%s%s" % (cmd, args) print "%s%s" % (cmd, args)
@ -656,9 +734,11 @@ def cmd_query_packet(options, cmd, args):
print "%s" % (cmd) print "%s" % (cmd)
return False return False
def rsp_ok_error(rsp): def rsp_ok_error(rsp):
print "rsp: ", rsp print "rsp: ", rsp
def rsp_ok_means_supported(options, cmd, cmd_args, rsp): def rsp_ok_means_supported(options, cmd, cmd_args, rsp):
if rsp == 'OK': if rsp == 'OK':
print "%s%s is supported" % (cmd, cmd_args) print "%s%s is supported" % (cmd, cmd_args)
@ -667,6 +747,7 @@ def rsp_ok_means_supported(options, cmd, cmd_args, rsp):
else: else:
print "%s%s -> %s" % (cmd, cmd_args, rsp) print "%s%s -> %s" % (cmd, cmd_args, rsp)
def rsp_ok_means_success(options, cmd, cmd_args, rsp): def rsp_ok_means_success(options, cmd, cmd_args, rsp):
if rsp == 'OK': if rsp == 'OK':
print "success" print "success"
@ -675,6 +756,7 @@ def rsp_ok_means_success(options, cmd, cmd_args, rsp):
else: else:
print "%s%s -> %s" % (cmd, cmd_args, rsp) print "%s%s -> %s" % (cmd, cmd_args, rsp)
def dump_key_value_pairs(key_value_pairs): def dump_key_value_pairs(key_value_pairs):
max_key_len = 0 max_key_len = 0
for key_value_pair in key_value_pairs: for key_value_pair in key_value_pairs:
@ -686,6 +768,7 @@ def dump_key_value_pairs(key_value_pairs):
value = key_value_pair[1] value = key_value_pair[1]
print "%*s = %s" % (max_key_len, key, value) print "%*s = %s" % (max_key_len, key, value)
def rsp_dump_key_value_pairs(options, cmd, cmd_args, rsp): def rsp_dump_key_value_pairs(options, cmd, cmd_args, rsp):
if rsp: if rsp:
print '%s response:' % (cmd) print '%s response:' % (cmd)
@ -695,14 +778,17 @@ def rsp_dump_key_value_pairs(options, cmd, cmd_args, rsp):
else: else:
print "not supported" print "not supported"
def cmd_c(options, cmd, args): def cmd_c(options, cmd, args):
print "continue()" print "continue()"
return False return False
def cmd_s(options, cmd, args): def cmd_s(options, cmd, args):
print "step()" print "step()"
return False return False
def cmd_vCont(options, cmd, args): def cmd_vCont(options, cmd, args):
if args == '?': if args == '?':
print "%s: get supported extended continue modes" % (cmd) print "%s: get supported extended continue modes" % (cmd)
@ -735,6 +821,7 @@ def cmd_vCont(options, cmd, args):
print "extended_continue (%s, other-threads: suspend)" % (s) print "extended_continue (%s, other-threads: suspend)" % (s)
return False return False
def rsp_vCont(options, cmd, cmd_args, rsp): def rsp_vCont(options, cmd, cmd_args, rsp):
if cmd_args == '?': if cmd_args == '?':
# Skip the leading 'vCont;' # Skip the leading 'vCont;'
@ -766,6 +853,7 @@ def rsp_vCont(options, cmd, cmd_args, rsp):
else: else:
print "not supported (cmd = '%s', args = '%s', rsp = '%s')" % (cmd, cmd_args, rsp) print "not supported (cmd = '%s', args = '%s', rsp = '%s')" % (cmd, cmd_args, rsp)
def cmd_vAttach(options, cmd, args): def cmd_vAttach(options, cmd, args):
(extra_command, args) = string.split(args, ';') (extra_command, args) = string.split(args, ';')
if extra_command: if extra_command:
@ -779,6 +867,7 @@ def cmd_qRegisterInfo(options, cmd, args):
print 'query_register_info(reg_num=%i)' % (int(args, 16)) print 'query_register_info(reg_num=%i)' % (int(args, 16))
return False return False
def rsp_qRegisterInfo(options, cmd, cmd_args, rsp): def rsp_qRegisterInfo(options, cmd, cmd_args, rsp):
global g_max_register_info_name_len global g_max_register_info_name_len
print 'query_register_info(reg_num=%i):' % (int(cmd_args, 16)), print 'query_register_info(reg_num=%i):' % (int(cmd_args, 16)),
@ -796,6 +885,7 @@ def rsp_qRegisterInfo(options, cmd, cmd_args, rsp):
print reg_info print reg_info
return False return False
def cmd_qThreadInfo(options, cmd, args): def cmd_qThreadInfo(options, cmd, args):
if cmd == 'qfThreadInfo': if cmd == 'qfThreadInfo':
query_type = 'first' query_type = 'first'
@ -804,6 +894,7 @@ def cmd_qThreadInfo(options, cmd, args):
print 'get_current_thread_list(type=%s)' % (query_type) print 'get_current_thread_list(type=%s)' % (query_type)
return False return False
def rsp_qThreadInfo(options, cmd, cmd_args, rsp): def rsp_qThreadInfo(options, cmd, cmd_args, rsp):
packet = Packet(rsp) packet = Packet(rsp)
response_type = packet.get_char() response_type = packet.get_char()
@ -817,11 +908,13 @@ def rsp_qThreadInfo(options, cmd, cmd_args, rsp):
elif response_type == 'l': elif response_type == 'l':
print 'END' print 'END'
def rsp_hex_big_endian(options, cmd, cmd_args, rsp): def rsp_hex_big_endian(options, cmd, cmd_args, rsp):
packet = Packet(rsp) packet = Packet(rsp)
uval = packet.get_hex_uint('big') uval = packet.get_hex_uint('big')
print '%s: 0x%x' % (cmd, uval) print '%s: 0x%x' % (cmd, uval)
def cmd_read_mem_bin(options, cmd, args): def cmd_read_mem_bin(options, cmd, args):
# x0x7fff5fc39200,0x200 # x0x7fff5fc39200,0x200
packet = Packet(args) packet = Packet(args)
@ -831,6 +924,7 @@ def cmd_read_mem_bin(options, cmd, args):
print 'binary_read_memory (addr = 0x%16.16x, size = %u)' % (addr, size) print 'binary_read_memory (addr = 0x%16.16x, size = %u)' % (addr, size)
return False return False
def rsp_mem_bin_bytes(options, cmd, cmd_args, rsp): def rsp_mem_bin_bytes(options, cmd, cmd_args, rsp):
packet = Packet(cmd_args) packet = Packet(cmd_args)
addr = packet.get_number() addr = packet.get_number()
@ -840,6 +934,7 @@ def rsp_mem_bin_bytes(options, cmd, cmd_args, rsp):
if size > 0: if size > 0:
dump_hex_memory_buffer(addr, rsp) dump_hex_memory_buffer(addr, rsp)
def cmd_read_memory(options, cmd, args): def cmd_read_memory(options, cmd, args):
packet = Packet(args) packet = Packet(args)
addr = packet.get_hex_uint('big') addr = packet.get_hex_uint('big')
@ -848,12 +943,13 @@ def cmd_read_memory(options, cmd, args):
print 'read_memory (addr = 0x%16.16x, size = %u)' % (addr, size) print 'read_memory (addr = 0x%16.16x, size = %u)' % (addr, size)
return False return False
def dump_hex_memory_buffer(addr, hex_byte_str): def dump_hex_memory_buffer(addr, hex_byte_str):
packet = Packet(hex_byte_str) packet = Packet(hex_byte_str)
idx = 0 idx = 0
ascii = '' ascii = ''
uval = packet.get_hex_uint8() uval = packet.get_hex_uint8()
while uval != None: while uval is not None:
if ((idx % 16) == 0): if ((idx % 16) == 0):
if ascii: if ascii:
print ' ', ascii print ' ', ascii
@ -870,6 +966,7 @@ def dump_hex_memory_buffer(addr, hex_byte_str):
print ' ', ascii print ' ', ascii
ascii = '' ascii = ''
def cmd_write_memory(options, cmd, args): def cmd_write_memory(options, cmd, args):
packet = Packet(args) packet = Packet(args)
addr = packet.get_hex_uint('big') addr = packet.get_hex_uint('big')
@ -884,6 +981,7 @@ def cmd_write_memory(options, cmd, args):
dump_hex_memory_buffer(addr, packet.str) dump_hex_memory_buffer(addr, packet.str)
return False return False
def cmd_alloc_memory(options, cmd, args): def cmd_alloc_memory(options, cmd, args):
packet = Packet(args) packet = Packet(args)
byte_size = packet.get_hex_uint('big') byte_size = packet.get_hex_uint('big')
@ -893,11 +991,13 @@ def cmd_alloc_memory(options, cmd, args):
print 'allocate_memory (byte-size = %u (0x%x), permissions = %s)' % (byte_size, byte_size, packet.str) print 'allocate_memory (byte-size = %u (0x%x), permissions = %s)' % (byte_size, byte_size, packet.str)
return False return False
def rsp_alloc_memory(options, cmd, cmd_args, rsp): def rsp_alloc_memory(options, cmd, cmd_args, rsp):
packet = Packet(rsp) packet = Packet(rsp)
addr = packet.get_hex_uint('big') addr = packet.get_hex_uint('big')
print 'addr = 0x%x' % addr print 'addr = 0x%x' % addr
def cmd_dealloc_memory(options, cmd, args): def cmd_dealloc_memory(options, cmd, args):
packet = Packet(args) packet = Packet(args)
addr = packet.get_hex_uint('big') addr = packet.get_hex_uint('big')
@ -906,17 +1006,21 @@ def cmd_dealloc_memory(options, cmd, args):
else: else:
print 'deallocate_memory (addr = 0x%x, permissions = %s)' % (addr, packet.str) print 'deallocate_memory (addr = 0x%x, permissions = %s)' % (addr, packet.str)
return False return False
def rsp_memory_bytes(options, cmd, cmd_args, rsp): def rsp_memory_bytes(options, cmd, cmd_args, rsp):
addr = Packet(cmd_args).get_hex_uint('big') addr = Packet(cmd_args).get_hex_uint('big')
dump_hex_memory_buffer(addr, rsp) dump_hex_memory_buffer(addr, rsp)
def get_register_name_equal_value(options, reg_num, hex_value_str): def get_register_name_equal_value(options, reg_num, hex_value_str):
if reg_num < len(g_register_infos): if reg_num < len(g_register_infos):
reg_info = g_register_infos[reg_num] reg_info = g_register_infos[reg_num]
value_str = reg_info.get_value_from_hex_string(hex_value_str) value_str = reg_info.get_value_from_hex_string(hex_value_str)
s = reg_info.name() + ' = ' s = reg_info.name() + ' = '
if options.symbolicator: if options.symbolicator:
symbolicated_addresses = options.symbolicator.symbolicate (int(value_str, 0)) symbolicated_addresses = options.symbolicator.symbolicate(
int(value_str, 0))
if symbolicated_addresses: if symbolicated_addresses:
s += options.colors.magenta() s += options.colors.magenta()
s += '%s' % symbolicated_addresses[0] s += '%s' % symbolicated_addresses[0]
@ -928,6 +1032,7 @@ def get_register_name_equal_value(options, reg_num, hex_value_str):
reg_value = Packet(hex_value_str).get_hex_uint(g_byte_order) reg_value = Packet(hex_value_str).get_hex_uint(g_byte_order)
return 'reg(%u) = 0x%x' % (reg_num, reg_value) return 'reg(%u) = 0x%x' % (reg_num, reg_value)
def cmd_read_one_reg(options, cmd, args): def cmd_read_one_reg(options, cmd, args):
packet = Packet(args) packet = Packet(args)
reg_num = packet.get_hex_uint('big') reg_num = packet.get_hex_uint('big')
@ -942,17 +1047,19 @@ def cmd_read_one_reg(options, cmd, args):
s = 'read_register (reg_num=%u' % reg_num s = 'read_register (reg_num=%u' % reg_num
if name: if name:
s += ' (%s)' % (name) s += ' (%s)' % (name)
if tid != None: if tid is not None:
s += ', tid = 0x%4.4x' % (tid) s += ', tid = 0x%4.4x' % (tid)
s += ')' s += ')'
print s print s
return False return False
def rsp_read_one_reg(options, cmd, cmd_args, rsp): def rsp_read_one_reg(options, cmd, cmd_args, rsp):
packet = Packet(cmd_args) packet = Packet(cmd_args)
reg_num = packet.get_hex_uint('big') reg_num = packet.get_hex_uint('big')
print get_register_name_equal_value(options, reg_num, rsp) print get_register_name_equal_value(options, reg_num, rsp)
def cmd_write_one_reg(options, cmd, args): def cmd_write_one_reg(options, cmd, args):
packet = Packet(args) packet = Packet(args)
reg_num = packet.get_hex_uint('big') reg_num = packet.get_hex_uint('big')
@ -967,36 +1074,40 @@ def cmd_write_one_reg(options, cmd, args):
s += ' (%s)' % (name) s += ' (%s)' % (name)
s += ', value = ' s += ', value = '
s += get_register_name_equal_value(options, reg_num, hex_value_str) s += get_register_name_equal_value(options, reg_num, hex_value_str)
if tid != None: if tid is not None:
s += ', tid = 0x%4.4x' % (tid) s += ', tid = 0x%4.4x' % (tid)
s += ')' s += ')'
print s print s
return False return False
def dump_all_regs(packet): def dump_all_regs(packet):
for reg_info in g_register_infos: for reg_info in g_register_infos:
nibble_size = reg_info.bit_size() / 4 nibble_size = reg_info.bit_size() / 4
hex_value_str = packet.get_hex_chars(nibble_size) hex_value_str = packet.get_hex_chars(nibble_size)
if hex_value_str != None: if hex_value_str is not None:
value = reg_info.get_value_from_hex_string(hex_value_str) value = reg_info.get_value_from_hex_string(hex_value_str)
print '%*s = %s' % (g_max_register_info_name_len, reg_info.name(), value) print '%*s = %s' % (g_max_register_info_name_len, reg_info.name(), value)
else: else:
return return
def cmd_read_all_regs(cmd, cmd_args): def cmd_read_all_regs(cmd, cmd_args):
packet = Packet(cmd_args) packet = Packet(cmd_args)
packet.get_char() # toss the 'g' command character packet.get_char() # toss the 'g' command character
tid = get_thread_from_thread_suffix(packet.str) tid = get_thread_from_thread_suffix(packet.str)
if tid != None: if tid is not None:
print 'read_all_register(thread = 0x%4.4x)' % tid print 'read_all_register(thread = 0x%4.4x)' % tid
else: else:
print 'read_all_register()' print 'read_all_register()'
return False return False
def rsp_read_all_regs(options, cmd, cmd_args, rsp): def rsp_read_all_regs(options, cmd, cmd_args, rsp):
packet = Packet(rsp) packet = Packet(rsp)
dump_all_regs(packet) dump_all_regs(packet)
def cmd_write_all_regs(options, cmd, args): def cmd_write_all_regs(options, cmd, args):
packet = Packet(args) packet = Packet(args)
print 'write_all_registers()' print 'write_all_registers()'
@ -1005,6 +1116,7 @@ def cmd_write_all_regs(options, cmd, args):
g_bp_types = ["software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp"] g_bp_types = ["software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp"]
def cmd_bp(options, cmd, args): def cmd_bp(options, cmd, args):
if cmd == 'Z': if cmd == 'Z':
s = 'set_' s = 'set_'
@ -1021,6 +1133,7 @@ def cmd_bp(options, cmd, args):
print s print s
return False return False
def cmd_mem_rgn_info(options, cmd, args): def cmd_mem_rgn_info(options, cmd, args):
packet = Packet(args) packet = Packet(args)
packet.get_char() # skip ':' character packet.get_char() # skip ':' character
@ -1028,18 +1141,22 @@ def cmd_mem_rgn_info(options, cmd, args):
print 'get_memory_region_info (addr=0x%x)' % (addr) print 'get_memory_region_info (addr=0x%x)' % (addr)
return False return False
def cmd_kill(options, cmd, args): def cmd_kill(options, cmd, args):
print 'kill_process()' print 'kill_process()'
return False return False
def cmd_jThreadsInfo(options, cmd, args): def cmd_jThreadsInfo(options, cmd, args):
print 'jThreadsInfo()' print 'jThreadsInfo()'
return False return False
def cmd_jGetLoadedDynamicLibrariesInfos(options, cmd, args): def cmd_jGetLoadedDynamicLibrariesInfos(options, cmd, args):
print 'jGetLoadedDynamicLibrariesInfos()' print 'jGetLoadedDynamicLibrariesInfos()'
return False return False
def decode_packet(s, start_index=0): def decode_packet(s, start_index=0):
# print '\ndecode_packet("%s")' % (s[start_index:]) # print '\ndecode_packet("%s")' % (s[start_index:])
index = s.find('}', start_index) index = s.find('}', start_index)
@ -1056,6 +1173,7 @@ def decode_packet(s, start_index = 0):
else: else:
return normal_s return normal_s
def rsp_json(options, cmd, cmd_args, rsp): def rsp_json(options, cmd, cmd_args, rsp):
print '%s() reply:' % (cmd) print '%s() reply:' % (cmd)
json_tree = json.loads(rsp) json_tree = json.loads(rsp)
@ -1112,6 +1230,7 @@ gdb_remote_commands = {
'jGetLoadedDynamicLibrariesInfos:': {'cmd': cmd_jGetLoadedDynamicLibrariesInfos, 'rsp': rsp_jGetLoadedDynamicLibrariesInfos, 'name': 'JSON get loaded dynamic libraries'}, 'jGetLoadedDynamicLibrariesInfos:': {'cmd': cmd_jGetLoadedDynamicLibrariesInfos, 'rsp': rsp_jGetLoadedDynamicLibrariesInfos, 'name': 'JSON get loaded dynamic libraries'},
} }
def calculate_mean_and_standard_deviation(floats): def calculate_mean_and_standard_deviation(floats):
sum = 0.0 sum = 0.0
count = len(floats) count = len(floats)
@ -1125,14 +1244,16 @@ def calculate_mean_and_standard_deviation(floats):
delta = f - mean delta = f - mean
accum += delta * delta accum += delta * delta
std_dev = math.sqrt(accum / (count-1)); std_dev = math.sqrt(accum / (count - 1))
return (mean, std_dev) return (mean, std_dev)
def parse_gdb_log_file(path, options): def parse_gdb_log_file(path, options):
f = open(path) f = open(path)
parse_gdb_log(f, options) parse_gdb_log(f, options)
f.close() f.close()
def parse_gdb_log(file, options): def parse_gdb_log(file, options):
'''Parse a GDB log file that was generated by enabling logging with: '''Parse a GDB log file that was generated by enabling logging with:
(lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets (lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets
@ -1146,11 +1267,13 @@ def parse_gdb_log(file, options):
tricky_commands = ['qRegisterInfo'] tricky_commands = ['qRegisterInfo']
timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$') timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$')
packet_name_regex = re.compile('([A-Za-z_]+)[^a-z]') packet_name_regex = re.compile('([A-Za-z_]+)[^a-z]')
packet_transmit_name_regex = re.compile('(?P<direction>send|read) packet: (?P<packet>.*)') packet_transmit_name_regex = re.compile(
'(?P<direction>send|read) packet: (?P<packet>.*)')
packet_contents_name_regex = re.compile('\$([^#]+)#[0-9a-fA-F]{2}') packet_contents_name_regex = re.compile('\$([^#]+)#[0-9a-fA-F]{2}')
packet_checksum_regex = re.compile('.*#[0-9a-fA-F]{2}$') packet_checksum_regex = re.compile('.*#[0-9a-fA-F]{2}$')
packet_names_regex_str = '(' + '|'.join(gdb_remote_commands.keys()) + ')(.*)'; packet_names_regex_str = '(' + \
packet_names_regex = re.compile(packet_names_regex_str); '|'.join(gdb_remote_commands.keys()) + ')(.*)'
packet_names_regex = re.compile(packet_names_regex_str)
base_time = 0.0 base_time = 0.0
last_time = 0.0 last_time = 0.0
@ -1189,14 +1312,16 @@ def parse_gdb_log(file, options):
print '-->', print '-->',
else: else:
print '<--', print '<--',
if not options.quiet: print 'ACK' if not options.quiet:
print 'ACK'
continue continue
elif packet[0] == '-': elif packet[0] == '-':
if is_command: if is_command:
print '-->', print '-->',
else: else:
print '<--', print '<--',
if not options.quiet: print 'NACK' if not options.quiet:
print 'NACK'
continue continue
elif packet[0] == '$': elif packet[0] == '$':
m = packet_contents_name_regex.match(packet) m = packet_contents_name_regex.match(packet)
@ -1230,7 +1355,8 @@ def parse_gdb_log(file, options):
packet_name = last_command packet_name = last_command
last_command_args = m.group(2) last_command_args = m.group(2)
last_command_packet = contents last_command_packet = contents
hide_next_response = gdb_remote_commands[last_command]['cmd'](options, last_command, last_command_args) hide_next_response = gdb_remote_commands[last_command][
'cmd'](options, last_command, last_command_args)
else: else:
packet_match = packet_name_regex.match(contents) packet_match = packet_name_regex.match(contents)
if packet_match: if packet_match:
@ -1244,7 +1370,8 @@ def parse_gdb_log(file, options):
last_command_args = None last_command_args = None
last_command_packet = None last_command_packet = None
elif last_command: elif last_command:
gdb_remote_commands[last_command]['rsp'](options, last_command, last_command_args, contents) gdb_remote_commands[last_command]['rsp'](
options, last_command, last_command_args, contents)
else: else:
print 'error: invalid packet: "', packet, '"' print 'error: invalid packet: "', packet, '"'
else: else:
@ -1300,30 +1427,68 @@ def parse_gdb_log(file, options):
print '# Packet Time (sec) Percent Count ' print '# Packet Time (sec) Percent Count '
print '#------------------------- ---------- ------- ------' print '#------------------------- ---------- ------- ------'
if options and options.sort_count: if options and options.sort_count:
res = sorted(packet_count, key=packet_count.__getitem__, reverse=True) res = sorted(
packet_count,
key=packet_count.__getitem__,
reverse=True)
else: else:
res = sorted(packet_total_times, key=packet_total_times.__getitem__, reverse=True) res = sorted(
packet_total_times,
key=packet_total_times.__getitem__,
reverse=True)
if last_time > 0.0: if last_time > 0.0:
for item in res: for item in res:
packet_total_time = packet_total_times[item] packet_total_time = packet_total_times[item]
packet_percent = (packet_total_time / total_packet_time)*100.0 packet_percent = (
packet_total_time / total_packet_time) * 100.0
if packet_percent >= 10.0: if packet_percent >= 10.0:
print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item]) print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
else: else:
print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item]) print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
if __name__ == '__main__': if __name__ == '__main__':
usage = "usage: gdbremote [options]" usage = "usage: gdbremote [options]"
description = '''The command disassembles a GDB remote packet log.''' description = '''The command disassembles a GDB remote packet log.'''
parser = optparse.OptionParser(description=description, prog='gdbremote',usage=usage) parser = optparse.OptionParser(
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) description=description,
parser.add_option('-q', '--quiet', action='store_true', dest='quiet', help='display verbose debug info', default=False) prog='gdbremote',
parser.add_option('-C', '--color', action='store_true', dest='color', help='add terminal colors', default=False) usage=usage)
parser.add_option('-c', '--sort-by-count', action='store_true', dest='sort_count', help='display verbose debug info', default=False) parser.add_option(
parser.add_option('--crashlog', type='string', dest='crashlog', help='symbolicate using a darwin crash log file', default=False) '-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
parser.add_option(
'-q',
'--quiet',
action='store_true',
dest='quiet',
help='display verbose debug info',
default=False)
parser.add_option(
'-C',
'--color',
action='store_true',
dest='color',
help='add terminal colors',
default=False)
parser.add_option(
'-c',
'--sort-by-count',
action='store_true',
dest='sort_count',
help='display verbose debug info',
default=False)
parser.add_option(
'--crashlog',
type='string',
dest='crashlog',
help='symbolicate using a darwin crash log file',
default=False)
try: try:
(options, args) = parser.parse_args(sys.argv[1:]) (options, args) = parser.parse_args(sys.argv[1:])
except: except:
@ -1357,6 +1522,8 @@ else:
if lldb.debugger: if lldb.debugger:
# This initializer is being run from LLDB in the embedded command interpreter # This initializer is being run from LLDB in the embedded command interpreter
# Add any commands contained in this module to LLDB # Add any commands contained in this module to LLDB
lldb.debugger.HandleCommand('command script add -f gdbremote.start_gdb_log start_gdb_log') lldb.debugger.HandleCommand(
lldb.debugger.HandleCommand('command script add -f gdbremote.stop_gdb_log stop_gdb_log') 'command script add -f gdbremote.start_gdb_log start_gdb_log')
lldb.debugger.HandleCommand(
'command script add -f gdbremote.stop_gdb_log stop_gdb_log')
print 'The "start_gdb_log" and "stop_gdb_log" commands are now installed and ready for use, type "start_gdb_log --help" or "stop_gdb_log --help" for more information' print 'The "start_gdb_log" and "stop_gdb_log" commands are now installed and ready for use, type "start_gdb_log --help" or "stop_gdb_log --help" for more information'

View File

@ -15,19 +15,22 @@ import os
import shlex import shlex
import sys import sys
def get_globals(raw_path, options): def get_globals(raw_path, options):
error = lldb.SBError() error = lldb.SBError()
# Resolve the path if needed # Resolve the path if needed
path = os.path.expanduser(raw_path) path = os.path.expanduser(raw_path)
# Create a target using path + options # 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: if target:
# Get the executable module # Get the executable module
module = target.module[target.executable.basename] module = target.module[target.executable.basename]
if module: if module:
# Keep track of which variables we have already looked up # Keep track of which variables we have already looked up
global_names = list() 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: for symbol in module.symbols:
if symbol.type == lldb.eSymbolTypeData: if symbol.type == lldb.eSymbolTypeData:
# The symbol is a DATA symbol, lets try and find all global variables # The symbol is a DATA symbol, lets try and find all global variables
@ -37,27 +40,59 @@ def get_globals(raw_path, options):
if global_name not in global_names: if global_name not in global_names:
global_names.append(global_name) global_names.append(global_name)
# Find all global variables by 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: if global_variable_list:
# Print results for anything that matched # Print results for anything that matched
for global_variable in global_variable_list: for global_variable in global_variable_list:
print 'name = %s' % global_variable.name # returns the global variable name as a string # returns the global variable name as a string
print 'value = %s' % global_variable.value # Returns the variable value 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 '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 # Returns an lldb.SBAddress (section offset
print 'file_addr = 0x%x' % global_variable.addr.file_addr # Returns the file virtual address for this global # address) for this global
print 'location = %s' % global_variable.location # returns the global variable value as a string print 'addr = %s' % global_variable.addr
print 'size = %s' % global_variable.size # Returns the size in bytes of this global variable # 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 print
def globals(command_args): def globals(command_args):
'''Extract all globals from any arguments which must be paths to object files.''' '''Extract all globals from any arguments which must be paths to object files.'''
usage = "usage: %prog [options] <PATH> [PATH ...]" 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).''' 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 = optparse.OptionParser(
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) description=description,
parser.add_option('-a', '--arch', type='string', metavar='arch', dest='arch', help='Specify an architecture (or triple) to use when extracting from a file.') prog='globals',
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".') 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: try:
(options, args) = parser.parse_args(command_args) (options, args) = parser.parse_args(command_args)
except: except:
@ -69,4 +104,3 @@ def globals(command_args):
if __name__ == '__main__': if __name__ == '__main__':
lldb.debugger = lldb.SBDebugger.Create() lldb.debugger = lldb.SBDebugger.Create()
globals(sys.argv[1:]) globals(sys.argv[1:])

View File

@ -1,4 +1,6 @@
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: """Handles a subset of GDB-style linespecs. Specifically:
@ -21,52 +23,59 @@ def parse_linespec (linespec, frame, result):
if (not matched): if (not matched):
mo = re.match("^([0-9]+)$", linespec) mo = re.match("^([0-9]+)$", linespec)
if (mo != None): if (mo is not None):
matched = True matched = True
# print "Matched <linenum>" # print "Matched <linenum>"
line_number = int(mo.group(1)) line_number = int(mo.group(1))
line_entry = frame.GetLineEntry() line_entry = frame.GetLineEntry()
if not line_entry.IsValid(): 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 return
breakpoint = target.BreakpointCreateByLocation (line_entry.GetFileSpec(), line_number) breakpoint = target.BreakpointCreateByLocation(
line_entry.GetFileSpec(), line_number)
if (not matched): if (not matched):
mo = re.match("^\+([0-9]+)$", linespec) mo = re.match("^\+([0-9]+)$", linespec)
if (mo != None): if (mo is not None):
matched = True matched = True
# print "Matched +<count>" # print "Matched +<count>"
line_number = int(mo.group(1)) line_number = int(mo.group(1))
line_entry = frame.GetLineEntry() line_entry = frame.GetLineEntry()
if not line_entry.IsValid(): 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 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): if (not matched):
mo = re.match("^\-([0-9]+)$", linespec) mo = re.match("^\-([0-9]+)$", linespec)
if (mo != None): if (mo is not None):
matched = True matched = True
# print "Matched -<count>" # print "Matched -<count>"
line_number = int(mo.group(1)) line_number = int(mo.group(1))
line_entry = frame.GetLineEntry() line_entry = frame.GetLineEntry()
if not line_entry.IsValid(): 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 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): if (not matched):
mo = re.match("^(.*):([0-9]+)$", linespec) mo = re.match("^(.*):([0-9]+)$", linespec)
if (mo != None): if (mo is not None):
matched = True matched = True
# print "Matched <filename>:<linenum>" # print "Matched <filename>:<linenum>"
file_name = mo.group(1) file_name = mo.group(1)
line_number = int(mo.group(2)) line_number = int(mo.group(2))
breakpoint = target.BreakpointCreateByLocation(file_name, line_number) breakpoint = target.BreakpointCreateByLocation(
file_name, line_number)
if (not matched): if (not matched):
mo = re.match("\*((0x)?([0-9a-f]+))$", linespec) mo = re.match("\*((0x)?([0-9a-f]+))$", linespec)
if (mo != None): if (mo is not None):
matched = True matched = True
# print "Matched <address-expression>" # print "Matched <address-expression>"
address = long(mo.group(1), base=0) address = long(mo.group(1), base=0)
@ -79,7 +88,8 @@ def parse_linespec (linespec, frame, result):
num_locations = breakpoint.GetNumLocations() num_locations = breakpoint.GetNumLocations()
if (num_locations == 0): 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 = [] addr_list = []
@ -91,6 +101,7 @@ def parse_linespec (linespec, frame, result):
return addr_list return addr_list
def usage_string(): def usage_string():
return """ Sets the program counter to a specific address. return """ Sets the program counter to a specific address.
@ -106,6 +117,7 @@ Command Options Usage:
<location-id> serves to disambiguate when multiple locations could be meant.""" <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 == ""): if (command == ""):
result.AppendMessage(usage_string()) result.AppendMessage(usage_string())
@ -151,17 +163,28 @@ def jump (debugger, command, result, internal_dict):
if (desired_index >= 0) and (desired_index < len(addresses)): if (desired_index >= 0) and (desired_index < len(addresses)):
desired_address = addresses[desired_index] desired_address = addresses[desired_index]
else: 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 return
else: else:
index = 0 index = 0
result.AppendMessage("The specified location resolves to multiple targets."); result.AppendMessage(
"The specified location resolves to multiple targets.")
for address in addresses: for address in addresses:
stream.Clear() stream.Clear()
address.GetDescription(stream) address.GetDescription(stream)
result.AppendMessage(" Location ID " + str(index) + ": " + stream.GetData()) result.AppendMessage(
" Location ID " +
str(index) +
": " +
stream.GetData())
index = index + 1 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 return
frame.SetPC(desired_address.GetLoadAddress(target)) frame.SetPC(desired_address.GetLoadAddress(target))

View File

@ -6,13 +6,24 @@ import shlex
import string import string
import sys 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 ...]" 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.''' 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 = optparse.OptionParser(
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='Display verbose output.', default=False) 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 return parser
def dump_module_line_tables(debugger, command, result, dict): def dump_module_line_tables(debugger, command, result, dict):
'''Dumps all line tables from all compile units for any modules specified as arguments.''' '''Dumps all line tables from all compile units for any modules specified as arguments.'''
command_args = shlex.split(command) command_args = shlex.split(command)
@ -28,7 +39,7 @@ def dump_module_line_tables(debugger, command, result, dict):
for module_name in command_args: for module_name in command_args:
result.PutCString('Searching for module "%s"' % (module_name,)) result.PutCString('Searching for module "%s"' % (module_name,))
module_fspec = lldb.SBFileSpec(module_name, False) module_fspec = lldb.SBFileSpec(module_name, False)
module = target.FindModule (module_fspec); module = target.FindModule(module_fspec)
if module: if module:
for cu_idx in range(module.GetNumCompileUnits()): for cu_idx in range(module.GetNumCompileUnits()):
cu = module.GetCompileUnitAtIndex(cu_idx) cu = module.GetCompileUnitAtIndex(cu_idx)
@ -37,15 +48,21 @@ def dump_module_line_tables(debugger, command, result, dict):
line_entry = cu.GetLineEntryAtIndex(line_idx) line_entry = cu.GetLineEntryAtIndex(line_idx)
start_file_addr = line_entry.addr.file_addr start_file_addr = line_entry.addr.file_addr
end_file_addr = line_entry.end_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 options.verbose:
if start_file_addr != end_file_addr: 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: else:
if start_file_addr == end_file_addr: if start_file_addr == end_file_addr:
result.PutCString('%#x: END' % (start_file_addr)) result.PutCString('%#x: END' %
(start_file_addr))
else: 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: if start_file_addr == end_file_addr:
result.Printf("\n") result.Printf("\n")
else: else:
@ -55,5 +72,7 @@ def dump_module_line_tables(debugger, command, result, dict):
parser = create_dump_module_line_tables_options() parser = create_dump_module_line_tables_options()
dump_module_line_tables.__doc__ = parser.format_help() 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' print 'Installed "dump_module_line_tables" command'

View File

@ -6,7 +6,9 @@ import sys
from Tkinter import * from Tkinter import *
import ttk import ttk
class ValueTreeItemDelegate(object): class ValueTreeItemDelegate(object):
def __init__(self, value): def __init__(self, value):
self.value = value self.value = value
@ -34,25 +36,33 @@ class ValueTreeItemDelegate(object):
def get_child_item_dictionaries(self): def get_child_item_dictionaries(self):
item_dicts = list() item_dicts = list()
for i in range(self.value.num_children): 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()) item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class FrameTreeItemDelegate(object): class FrameTreeItemDelegate(object):
def __init__(self, frame): def __init__(self, frame):
self.frame = frame self.frame = frame
def get_item_dictionary(self): def get_item_dictionary(self):
id = self.frame.GetFrameID() id = self.frame.GetFrameID()
name = 'frame #%u' % (id); name = 'frame #%u' % (id)
value = '0x%16.16x' % (self.frame.GetPC()) value = '0x%16.16x' % (self.frame.GetPC())
stream = lldb.SBStream() stream = lldb.SBStream()
self.frame.GetDescription(stream) self.frame.GetDescription(stream)
summary = stream.GetData().split("`")[1] summary = stream.GetData().split("`")[1]
return { '#0' : name, return {
'#0': name,
'value': value, 'value': value,
'summary': summary, 'summary': summary,
'children' : self.frame.GetVariables(True, True, True, True).GetSize() > 0, 'children': self.frame.GetVariables(
True,
True,
True,
True).GetSize() > 0,
'tree-item-delegate': self} 'tree-item-delegate': self}
def get_child_item_dictionaries(self): def get_child_item_dictionaries(self):
@ -64,7 +74,9 @@ class FrameTreeItemDelegate(object):
item_dicts.append(item_delegate.get_item_dictionary()) item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class ThreadTreeItemDelegate(object): class ThreadTreeItemDelegate(object):
def __init__(self, thread): def __init__(self, thread):
self.thread = thread self.thread = thread
@ -86,7 +98,9 @@ class ThreadTreeItemDelegate(object):
item_dicts.append(item_delegate.get_item_dictionary()) item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class ProcessTreeItemDelegate(object): class ProcessTreeItemDelegate(object):
def __init__(self, process): def __init__(self, process):
self.process = process self.process = process
@ -108,7 +122,9 @@ class ProcessTreeItemDelegate(object):
item_dicts.append(item_delegate.get_item_dictionary()) item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class TargetTreeItemDelegate(object): class TargetTreeItemDelegate(object):
def __init__(self, target): def __init__(self, target):
self.target = target self.target = target
@ -127,7 +143,9 @@ class TargetTreeItemDelegate(object):
item_dicts.append(image_item_delegate.get_item_dictionary()) item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class TargetImagesTreeItemDelegate(object): class TargetImagesTreeItemDelegate(object):
def __init__(self, target): def __init__(self, target):
self.target = target self.target = target
@ -145,11 +163,14 @@ class TargetImagesTreeItemDelegate(object):
item_dicts = list() item_dicts = list()
for i in range(self.target.GetNumModules()): for i in range(self.target.GetNumModules()):
module = self.target.GetModuleAtIndex(i) 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()) item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class ModuleTreeItemDelegate(object): class ModuleTreeItemDelegate(object):
def __init__(self, target, module, index): def __init__(self, target, module, index):
self.target = target self.target = target
self.module = module self.module = module
@ -167,17 +188,22 @@ class ModuleTreeItemDelegate(object):
def get_child_item_dictionaries(self): def get_child_item_dictionaries(self):
item_dicts = list() 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()) 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()) 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()) item_dicts.append(comp_units_item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class ModuleSectionsTreeItemDelegate(object): class ModuleSectionsTreeItemDelegate(object):
def __init__(self, target, module): def __init__(self, target, module):
self.target = target self.target = target
self.module = module self.module = module
@ -201,7 +227,9 @@ class ModuleSectionsTreeItemDelegate(object):
item_dicts.append(image_item_delegate.get_item_dictionary()) item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class SectionTreeItemDelegate(object): class SectionTreeItemDelegate(object):
def __init__(self, target, section): def __init__(self, target, section):
self.target = target self.target = target
self.section = section self.section = section
@ -229,7 +257,9 @@ class SectionTreeItemDelegate(object):
item_dicts.append(image_item_delegate.get_item_dictionary()) item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class ModuleCompileUnitsTreeItemDelegate(object): class ModuleCompileUnitsTreeItemDelegate(object):
def __init__(self, target, module): def __init__(self, target, module):
self.target = target self.target = target
self.module = module self.module = module
@ -253,7 +283,9 @@ class ModuleCompileUnitsTreeItemDelegate(object):
item_dicts.append(image_item_delegate.get_item_dictionary()) item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class CompileUnitTreeItemDelegate(object): class CompileUnitTreeItemDelegate(object):
def __init__(self, target, cu): def __init__(self, target, cu):
self.target = target self.target = target
self.cu = cu self.cu = cu
@ -275,7 +307,9 @@ class CompileUnitTreeItemDelegate(object):
item_dicts.append(item_delegate.get_item_dictionary()) item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class LineTableTreeItemDelegate(object): class LineTableTreeItemDelegate(object):
def __init__(self, target, cu): def __init__(self, target, cu):
self.target = target self.target = target
self.cu = cu self.cu = cu
@ -296,11 +330,14 @@ class LineTableTreeItemDelegate(object):
num_lines = self.cu.GetNumLineEntries() num_lines = self.cu.GetNumLineEntries()
for i in range(num_lines): for i in range(num_lines):
line_entry = self.cu.GetLineEntryAtIndex(i) 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()) item_dicts.append(item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class LineEntryTreeItemDelegate(object): class LineEntryTreeItemDelegate(object):
def __init__(self, target, line_entry, index): def __init__(self, target, line_entry, index):
self.target = target self.target = target
self.line_entry = line_entry self.line_entry = line_entry
@ -314,7 +351,8 @@ class LineEntryTreeItemDelegate(object):
value = '0x%16.16x' % (load_addr) value = '0x%16.16x' % (load_addr)
else: else:
value = '0x%16.16x *' % (address.file_addr) value = '0x%16.16x *' % (address.file_addr)
summary = self.line_entry.GetFileSpec().fullpath + ':' + str(self.line_entry.line) summary = self.line_entry.GetFileSpec().fullpath + ':' + \
str(self.line_entry.line)
return {'#0': name, return {'#0': name,
'value': value, 'value': value,
'summary': summary, 'summary': summary,
@ -325,7 +363,9 @@ class LineEntryTreeItemDelegate(object):
item_dicts = list() item_dicts = list()
return item_dicts return item_dicts
class InstructionTreeItemDelegate(object): class InstructionTreeItemDelegate(object):
def __init__(self, target, instr): def __init__(self, target, instr):
self.target = target self.target = target
self.instr = instr self.instr = instr
@ -337,7 +377,8 @@ class InstructionTreeItemDelegate(object):
name = '0x%16.16x' % (load_addr) name = '0x%16.16x' % (load_addr)
else: else:
name = '0x%16.16x *' % (address.file_addr) 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) summary = self.instr.GetComment(self.target)
return {'#0': name, return {'#0': name,
'value': value, 'value': value,
@ -345,7 +386,9 @@ class InstructionTreeItemDelegate(object):
'children': False, 'children': False,
'tree-item-delegate': self} 'tree-item-delegate': self}
class ModuleSymbolsTreeItemDelegate(object): class ModuleSymbolsTreeItemDelegate(object):
def __init__(self, target, module): def __init__(self, target, module):
self.target = target self.target = target
self.module = module self.module = module
@ -365,11 +408,14 @@ class ModuleSymbolsTreeItemDelegate(object):
num_symbols = self.module.GetNumSymbols() num_symbols = self.module.GetNumSymbols()
for i in range(num_symbols): for i in range(num_symbols):
symbol = self.module.GetSymbolAtIndex(i) 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()) item_dicts.append(image_item_delegate.get_item_dictionary())
return item_dicts return item_dicts
class SymbolTreeItemDelegate(object): class SymbolTreeItemDelegate(object):
def __init__(self, target, symbol, index): def __init__(self, target, symbol, index):
self.target = target self.target = target
self.symbol = symbol self.symbol = symbol
@ -395,7 +441,6 @@ class SymbolTreeItemDelegate(object):
return item_dicts return item_dicts
class DelegateTree(ttk.Frame): class DelegateTree(ttk.Frame):
def __init__(self, column_dicts, delegate, title, name): def __init__(self, column_dicts, delegate, title, name):
@ -421,14 +466,20 @@ class DelegateTree(ttk.Frame):
self.tree = ttk.Treeview(columns=column_ids) self.tree = ttk.Treeview(columns=column_ids)
scroll_bar_v = ttk.Scrollbar(orient=VERTICAL, command=self.tree.yview) scroll_bar_v = ttk.Scrollbar(orient=VERTICAL, command=self.tree.yview)
scroll_bar_h = ttk.Scrollbar(orient=HORIZONTAL, command= self.tree.xview) scroll_bar_h = ttk.Scrollbar(
orient=HORIZONTAL, command=self.tree.xview)
self.tree['yscroll'] = scroll_bar_v.set self.tree['yscroll'] = scroll_bar_v.set
self.tree['xscroll'] = scroll_bar_h.set self.tree['xscroll'] = scroll_bar_h.set
# setup column headings and columns properties # setup column headings and columns properties
for columns_dict in self.columns_dicts: for columns_dict in self.columns_dicts:
self.tree.heading(columns_dict['id'], text=columns_dict['text'], anchor=columns_dict['anchor']) self.tree.heading(
self.tree.column(columns_dict['id'], stretch=columns_dict['stretch']) 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 # add tree and scrollbars to frame
self.tree.grid(in_=frame, row=0, column=0, sticky=NSEW) self.tree.grid(in_=frame, row=0, column=0, sticky=NSEW)
@ -477,12 +528,15 @@ class DelegateTree(ttk.Frame):
if self.tree.item(first_child, option='text') == 'dummy': if self.tree.item(first_child, option='text') == 'dummy':
self.tree.delete(first_child) self.tree.delete(first_child)
item_dict = self.item_id_to_item_dict[item_id] 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) self.insert_items(item_id, item_dicts)
@lldb.command("tk-variables") @lldb.command("tk-variables")
def tk_variable_display(debugger, command, result, dict): 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() target = debugger.GetSelectedTarget()
if not target: if not target:
print >>result, "invalid target" print >>result, "invalid target"
@ -505,12 +559,18 @@ def tk_variable_display(debugger, command, result, dict):
{'id': 'typename', 'text': 'Type', 'anchor': W, 'stretch': 0}, {'id': 'typename', 'text': 'Type', 'anchor': W, 'stretch': 0},
{'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0}, {'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0},
{'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}] {'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}]
tree = DelegateTree(column_dicts, FrameTreeItemDelegate(frame), 'Variables', 'lldb-tk-variables') tree = DelegateTree(
column_dicts,
FrameTreeItemDelegate(frame),
'Variables',
'lldb-tk-variables')
tree.mainloop() tree.mainloop()
@lldb.command("tk-process") @lldb.command("tk-process")
def tk_process_display(debugger, command, result, dict): 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() target = debugger.GetSelectedTarget()
if not target: if not target:
print >>result, "invalid target" print >>result, "invalid target"
@ -522,14 +582,20 @@ def tk_process_display(debugger, command, result, dict):
# Parse command line args # Parse command line args
columnd_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0}, columnd_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0},
{'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0}, {'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0},
{ 'id' : 'summary', 'text' : 'Summary', 'anchor' : W , 'stretch' : 1 }]; {'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}]
command_args = shlex.split(command) 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() tree.mainloop()
@lldb.command("tk-target") @lldb.command("tk-target")
def tk_target_display(debugger, command, result, dict): 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() target = debugger.GetSelectedTarget()
if not target: if not target:
print >>result, "invalid target" print >>result, "invalid target"
@ -537,8 +603,11 @@ def tk_target_display(debugger, command, result, dict):
# Parse command line args # Parse command line args
columnd_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0}, columnd_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0},
{'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0}, {'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0},
{ 'id' : 'summary', 'text' : 'Summary', 'anchor' : W , 'stretch' : 1 }]; {'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}]
command_args = shlex.split(command) 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() tree.mainloop()

View File

@ -176,6 +176,7 @@ N_LENG = 0xfe
vm_prot_names = ['---', 'r--', '-w-', 'rw-', '--x', 'r-x', '-wx', 'rwx'] vm_prot_names = ['---', 'r--', '-w-', 'rw-', '--x', 'r-x', '-wx', 'rwx']
def dump_memory(base_addr, data, hex_bytes_len, num_per_line): def dump_memory(base_addr, data, hex_bytes_len, num_per_line):
hex_bytes = data.encode('hex') hex_bytes = data.encode('hex')
if hex_bytes_len == -1: if hex_bytes_len == -1:
@ -209,6 +210,7 @@ def dump_memory(base_addr, data, hex_bytes_len, num_per_line):
class TerminalColors: class TerminalColors:
'''Simple terminal colors class''' '''Simple terminal colors class'''
def __init__(self, enabled=True): def __init__(self, enabled=True):
# TODO: discover terminal type from "file" and disable if # TODO: discover terminal type from "file" and disable if
# it can't handle the color codes # it can't handle the color codes
@ -217,52 +219,52 @@ class TerminalColors:
def reset(self): def reset(self):
'''Reset all terminal colors and formatting.''' '''Reset all terminal colors and formatting.'''
if self.enabled: if self.enabled:
return "\x1b[0m"; return "\x1b[0m"
return '' return ''
def bold(self, on=True): def bold(self, on=True):
'''Enable or disable bold depending on the "on" parameter.''' '''Enable or disable bold depending on the "on" parameter.'''
if self.enabled: if self.enabled:
if on: if on:
return "\x1b[1m"; return "\x1b[1m"
else: else:
return "\x1b[22m"; return "\x1b[22m"
return '' return ''
def italics(self, on=True): def italics(self, on=True):
'''Enable or disable italics depending on the "on" parameter.''' '''Enable or disable italics depending on the "on" parameter.'''
if self.enabled: if self.enabled:
if on: if on:
return "\x1b[3m"; return "\x1b[3m"
else: else:
return "\x1b[23m"; return "\x1b[23m"
return '' return ''
def underline(self, on=True): def underline(self, on=True):
'''Enable or disable underline depending on the "on" parameter.''' '''Enable or disable underline depending on the "on" parameter.'''
if self.enabled: if self.enabled:
if on: if on:
return "\x1b[4m"; return "\x1b[4m"
else: else:
return "\x1b[24m"; return "\x1b[24m"
return '' return ''
def inverse(self, on=True): def inverse(self, on=True):
'''Enable or disable inverse depending on the "on" parameter.''' '''Enable or disable inverse depending on the "on" parameter.'''
if self.enabled: if self.enabled:
if on: if on:
return "\x1b[7m"; return "\x1b[7m"
else: else:
return "\x1b[27m"; return "\x1b[27m"
return '' return ''
def strike(self, on=True): def strike(self, on=True):
'''Enable or disable strike through depending on the "on" parameter.''' '''Enable or disable strike through depending on the "on" parameter.'''
if self.enabled: if self.enabled:
if on: if on:
return "\x1b[9m"; return "\x1b[9m"
else: else:
return "\x1b[29m"; return "\x1b[29m"
return '' return ''
def black(self, fg=True): def black(self, fg=True):
@ -270,9 +272,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[30m"; return "\x1b[30m"
else: else:
return "\x1b[40m"; return "\x1b[40m"
return '' return ''
def red(self, fg=True): def red(self, fg=True):
@ -280,9 +282,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[31m"; return "\x1b[31m"
else: else:
return "\x1b[41m"; return "\x1b[41m"
return '' return ''
def green(self, fg=True): def green(self, fg=True):
@ -290,9 +292,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[32m"; return "\x1b[32m"
else: else:
return "\x1b[42m"; return "\x1b[42m"
return '' return ''
def yellow(self, fg=True): def yellow(self, fg=True):
@ -300,9 +302,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[43m"; return "\x1b[43m"
else: else:
return "\x1b[33m"; return "\x1b[33m"
return '' return ''
def blue(self, fg=True): def blue(self, fg=True):
@ -310,9 +312,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[34m"; return "\x1b[34m"
else: else:
return "\x1b[44m"; return "\x1b[44m"
return '' return ''
def magenta(self, fg=True): def magenta(self, fg=True):
@ -320,9 +322,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[35m"; return "\x1b[35m"
else: else:
return "\x1b[45m"; return "\x1b[45m"
return '' return ''
def cyan(self, fg=True): def cyan(self, fg=True):
@ -330,9 +332,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[36m"; return "\x1b[36m"
else: else:
return "\x1b[46m"; return "\x1b[46m"
return '' return ''
def white(self, fg=True): def white(self, fg=True):
@ -340,9 +342,9 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[37m"; return "\x1b[37m"
else: else:
return "\x1b[47m"; return "\x1b[47m"
return '' return ''
def default(self, fg=True): def default(self, fg=True):
@ -350,11 +352,12 @@ class TerminalColors:
The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.'''
if self.enabled: if self.enabled:
if fg: if fg:
return "\x1b[39m"; return "\x1b[39m"
else: else:
return "\x1b[49m"; return "\x1b[49m"
return '' return ''
def swap_unpack_char(): def swap_unpack_char():
"""Returns the unpack prefix that will for non-native endian-ness.""" """Returns the unpack prefix that will for non-native endian-ness."""
if struct.pack('H', 1).startswith("\x00"): if struct.pack('H', 1).startswith("\x00"):
@ -374,6 +377,7 @@ def dump_hex_bytes(addr, s, bytes_per_line=16):
i += 1 i += 1
print line print line
def dump_hex_byte_string_diff(addr, a, b, bytes_per_line=16): def dump_hex_byte_string_diff(addr, a, b, bytes_per_line=16):
i = 0 i = 0
line = '' line = ''
@ -402,13 +406,16 @@ def dump_hex_byte_string_diff(addr, a, b, bytes_per_line=16):
if line: if line:
print line print line
line = '%#8.8x: ' % (addr + i) line = '%#8.8x: ' % (addr + i)
if mismatch: line += tty_colors.red() if mismatch:
line += tty_colors.red()
line += "%02X " % ord(ch) line += "%02X " % ord(ch)
if mismatch: line += tty_colors.default() if mismatch:
line += tty_colors.default()
i += 1 i += 1
print line print line
class Mach: class Mach:
"""Class that does everything mach-o related""" """Class that does everything mach-o related"""
@ -421,11 +428,14 @@ class Mach:
def set_cpu_type(self, c): def set_cpu_type(self, c):
self.cpu = c self.cpu = c
def set_cpu_subtype(self, s): def set_cpu_subtype(self, s):
self.sub = s self.sub = s
def set_arch(self, c, s): def set_arch(self, c, s):
self.cpu = c self.cpu = c
self.sub = s self.sub = s
def is_64_bit(self): def is_64_bit(self):
return (self.cpu & CPU_ARCH_ABI64) != 0 return (self.cpu & CPU_ARCH_ABI64) != 0
@ -472,7 +482,6 @@ class Mach:
return info[0] return info[0]
return "{0}.{1}".format(self.cpu, self.sub) return "{0}.{1}".format(self.cpu, self.sub)
class Magic(dict_utils.Enum): class Magic(dict_utils.Enum):
enum = { enum = {
@ -495,7 +504,7 @@ class Mach:
def unpack(self, data): def unpack(self, data):
data.set_byte_order('native') data.set_byte_order('native')
self.value = data.get_uint32(); self.value = data.get_uint32()
def get_byte_order(self): def get_byte_order(self):
if self.value == MH_CIGAM or self.value == MH_CIGAM_64 or self.value == FAT_CIGAM: if self.value == MH_CIGAM or self.value == MH_CIGAM_64 or self.value == FAT_CIGAM:
@ -512,17 +521,18 @@ class Mach:
self.path = None self.path = None
def extract(self, path, extractor): def extract(self, path, extractor):
self.path = path; self.path = path
self.unpack(extractor) self.unpack(extractor)
def parse(self, path): def parse(self, path):
self.path = path; self.path = path
try: try:
f = open(self.path) f = open(self.path)
file_extractor = file_extract.FileExtract(f, '=') file_extractor = file_extract.FileExtract(f, '=')
self.unpack(file_extractor) self.unpack(file_extractor)
# f.close() # f.close()
except IOError as (errno, strerror): except IOError as xxx_todo_changeme:
(errno, strerror) = xxx_todo_changeme.args
print "I/O error({0}): {1}".format(errno, strerror) print "I/O error({0}): {1}".format(errno, strerror)
except ValueError: except ValueError:
print "Could not convert data to an integer." print "Could not convert data to an integer."
@ -566,11 +576,11 @@ class Mach:
else: else:
self.content = None self.content = None
if self.content != None: if self.content is not None:
self.content.unpack(data, self.magic) self.content.unpack(data, self.magic)
def is_valid(self): def is_valid(self):
return self.content != None return self.content is not None
class Universal: class Universal:
@ -668,7 +678,8 @@ class Mach:
def dump_symbol_names_matching_regex(self, regex, file=None): def dump_symbol_names_matching_regex(self, regex, file=None):
for i in range(self.nfat_arch): for i in range(self.nfat_arch):
self.archs[i].mach.dump_symbol_names_matching_regex(regex, file) self.archs[i].mach.dump_symbol_names_matching_regex(
regex, file)
class ArchInfo: class ArchInfo:
@ -682,7 +693,8 @@ class Mach:
def unpack(self, data): def unpack(self, data):
# Universal headers are always in big endian # Universal headers are always in big endian
data.set_byte_order('big') data.set_byte_order('big')
self.arch.cpu, self.arch.sub, self.offset, self.size, self.align = data.get_n_uint32(5) self.arch.cpu, self.arch.sub, self.offset, self.size, self.align = data.get_n_uint32(
5)
def dump_header(self, dump_description=True, options=None): def dump_header(self, dump_description=True, options=None):
if options.verbose: if options.verbose:
@ -691,21 +703,27 @@ class Mach:
else: else:
print "ARCH FILEOFFSET FILESIZE ALIGN" print "ARCH FILEOFFSET FILESIZE ALIGN"
print "---------- ---------- ---------- ----------" print "---------- ---------- ---------- ----------"
def dump_flat(self, options): def dump_flat(self, options):
if options.verbose: if options.verbose:
print "%#8.8x %#8.8x %#8.8x %#8.8x %#8.8x" % (self.arch.cpu, self.arch.sub, self.offset, self.size, self.align) print "%#8.8x %#8.8x %#8.8x %#8.8x %#8.8x" % (self.arch.cpu, self.arch.sub, self.offset, self.size, self.align)
else: else:
print "%-10s %#8.8x %#8.8x %#8.8x" % (self.arch, self.offset, self.size, self.align) print "%-10s %#8.8x %#8.8x %#8.8x" % (self.arch, self.offset, self.size, self.align)
def dump(self): def dump(self):
print " cputype: %#8.8x" % self.arch.cpu print " cputype: %#8.8x" % self.arch.cpu
print "cpusubtype: %#8.8x" % self.arch.sub print "cpusubtype: %#8.8x" % self.arch.sub
print " offset: %#8.8x" % self.offset print " offset: %#8.8x" % self.offset
print " size: %#8.8x" % self.size print " size: %#8.8x" % self.size
print " align: %#8.8x" % self.align print " align: %#8.8x" % self.align
def __str__(self): def __str__(self):
return "Mach.Universal.ArchInfo: %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x" % (self.arch.cpu, self.arch.sub, self.offset, self.size, self.align) return "Mach.Universal.ArchInfo: %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x" % (
self.arch.cpu, self.arch.sub, self.offset, self.size, self.align)
def __repr__(self): def __repr__(self):
return "Mach.Universal.ArchInfo: %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x" % (self.arch.cpu, self.arch.sub, self.offset, self.size, self.align) return "Mach.Universal.ArchInfo: %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x" % (
self.arch.cpu, self.arch.sub, self.offset, self.size, self.align)
class Flags: class Flags:
@ -821,7 +839,8 @@ class Mach:
self.magic = magic self.magic = magic
self.file_off = self.file_off - 4 self.file_off = self.file_off - 4
data.set_byte_order(self.magic.get_byte_order()) data.set_byte_order(self.magic.get_byte_order())
self.arch.cpu, self.arch.sub, self.filetype.value, self.ncmds, self.sizeofcmds, bits = data.get_n_uint32(6) self.arch.cpu, self.arch.sub, self.filetype.value, self.ncmds, self.sizeofcmds, bits = data.get_n_uint32(
6)
self.flags.bits = bits self.flags.bits = bits
if self.is_64_bit(): if self.is_64_bit():
@ -840,7 +859,7 @@ class Mach:
def unpack_load_command(self, data): def unpack_load_command(self, data):
lc = Mach.LoadCommand() lc = Mach.LoadCommand()
lc.unpack(self, data) lc.unpack(self, data)
lc_command = lc.command.get_enum_value(); lc_command = lc.command.get_enum_value()
if (lc_command == LC_SEGMENT or if (lc_command == LC_SEGMENT or
lc_command == LC_SEGMENT_64): lc_command == LC_SEGMENT_64):
lc = Mach.SegmentLoadCommand(lc) lc = Mach.SegmentLoadCommand(lc)
@ -950,6 +969,7 @@ class Mach:
if not result: if not result:
print 'error: mach files differ' print 'error: mach files differ'
return result return result
def dump_header(self, dump_description=True, options=None): def dump_header(self, dump_description=True, options=None):
if options.verbose: if options.verbose:
print "MAGIC CPU SUBTYPE FILETYPE NUM CMDS SIZE CMDS FLAGS" print "MAGIC CPU SUBTYPE FILETYPE NUM CMDS SIZE CMDS FLAGS"
@ -1032,10 +1052,12 @@ class Mach:
outfile = open(options.outfile, 'w') outfile = open(options.outfile, 'w')
if options.extract_modules: if options.extract_modules:
# print "Extracting modules from mach file..." # print "Extracting modules from mach file..."
data = file_extract.FileExtract(StringIO.StringIO(sect_bytes), self.data.byte_order) data = file_extract.FileExtract(
StringIO.StringIO(sect_bytes), self.data.byte_order)
version = data.get_uint32() version = data.get_uint32()
num_modules = data.get_uint32() num_modules = data.get_uint32()
#print "version = %u, num_modules = %u" % (version, num_modules) # print "version = %u, num_modules = %u" %
# (version, num_modules)
for i in range(num_modules): for i in range(num_modules):
data_offset = data.get_uint64() data_offset = data.get_uint64()
data_size = data.get_uint64() data_size = data.get_uint64()
@ -1044,7 +1066,12 @@ class Mach:
flags = data.get_uint32() flags = data.get_uint32()
data.seek(name_offset) data.seek(name_offset)
module_name = data.get_c_string() module_name = data.get_c_string()
#print "module[%u] data_offset = %#16.16x, data_size = %#16.16x, name_offset = %#16.16x (%s), language = %u, flags = %#x" % (i, data_offset, data_size, name_offset, module_name, language, flags) # print "module[%u] data_offset = %#16.16x,
# data_size = %#16.16x, name_offset =
# %#16.16x (%s), language = %u, flags =
# %#x" % (i, data_offset, data_size,
# name_offset, module_name, language,
# flags)
data.seek(data_offset) data.seek(data_offset)
outfile.write(data.read_size(data_size)) outfile.write(data.read_size(data_size))
else: else:
@ -1119,6 +1146,7 @@ class Mach:
return self.magic.is_64_bit() return self.magic.is_64_bit()
class LoadCommand: class LoadCommand:
class Command(dict_utils.Enum): class Command(dict_utils.Enum):
enum = { enum = {
'LC_SEGMENT': LC_SEGMENT, 'LC_SEGMENT': LC_SEGMENT,
@ -1166,9 +1194,8 @@ class Mach:
def __init__(self, initial_value=0): def __init__(self, initial_value=0):
dict_utils.Enum.__init__(self, initial_value, self.enum) dict_utils.Enum.__init__(self, initial_value, self.enum)
def __init__(self, c=None, l=0, o=0): def __init__(self, c=None, l=0, o=0):
if c != None: if c is not None:
self.command = c self.command = c
else: else:
self.command = Mach.LoadCommand.Command(0) self.command = Mach.LoadCommand.Command(0)
@ -1184,7 +1211,8 @@ class Mach:
def __str__(self): def __str__(self):
lc_name = self.command.get_enum_name() lc_name = self.command.get_enum_name()
return '%#8.8x: <%#4.4x> %-24s' % (self.file_off, self.length, lc_name) return '%#8.8x: <%#4.4x> %-24s' % (self.file_off,
self.length, lc_name)
class Section: class Section:
@ -1210,32 +1238,39 @@ class Mach:
self.segname = data.get_fixed_length_c_string(16, '', True) self.segname = data.get_fixed_length_c_string(16, '', True)
if self.is_64: if self.is_64:
self.addr, self.size = data.get_n_uint64(2) self.addr, self.size = data.get_n_uint64(2)
self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2, self.reserved3 = data.get_n_uint32(8) self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2, self.reserved3 = data.get_n_uint32(
8)
else: else:
self.addr, self.size = data.get_n_uint32(2) self.addr, self.size = data.get_n_uint32(2)
self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2 = data.get_n_uint32(7) self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2 = data.get_n_uint32(
7)
def dump_header(self): def dump_header(self):
if self.is_64: if self.is_64:
print "INDEX ADDRESS SIZE OFFSET ALIGN RELOFF NRELOC FLAGS RESERVED1 RESERVED2 RESERVED3 NAME"; print "INDEX ADDRESS SIZE OFFSET ALIGN RELOFF NRELOC FLAGS RESERVED1 RESERVED2 RESERVED3 NAME"
print "===== ------------------ ------------------ ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------------"; print "===== ------------------ ------------------ ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------------"
else: else:
print "INDEX ADDRESS SIZE OFFSET ALIGN RELOFF NRELOC FLAGS RESERVED1 RESERVED2 NAME"; print "INDEX ADDRESS SIZE OFFSET ALIGN RELOFF NRELOC FLAGS RESERVED1 RESERVED2 NAME"
print "===== ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------------"; print "===== ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------------"
def __str__(self): def __str__(self):
if self.is_64: if self.is_64:
return "[%3u] %#16.16x %#16.16x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %s.%s" % (self.index, self.addr, self.size, self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2, self.reserved3, self.segname, self.sectname) return "[%3u] %#16.16x %#16.16x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %s.%s" % (
self.index, self.addr, self.size, self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2, self.reserved3, self.segname, self.sectname)
else: else:
return "[%3u] %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %s.%s" % (self.index, self.addr, self.size, self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2, self.segname, self.sectname) return "[%3u] %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %s.%s" % (
self.index, self.addr, self.size, self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2, self.segname, self.sectname)
def get_contents(self, mach_file): def get_contents(self, mach_file):
'''Get the section contents as a python string''' '''Get the section contents as a python string'''
if self.size > 0 and mach_file.get_segment(self.segname).filesize > 0: if self.size > 0 and mach_file.get_segment(
self.segname).filesize > 0:
data = mach_file.get_data() data = mach_file.get_data()
if data: if data:
section_data_offset = mach_file.file_off + self.offset section_data_offset = mach_file.file_off + self.offset
#print '%s.%s is at offset 0x%x with size 0x%x' % (self.segname, self.sectname, section_data_offset, self.size) # print '%s.%s is at offset 0x%x with size 0x%x' %
# (self.segname, self.sectname, section_data_offset,
# self.size)
data.push_offset_and_seek(section_data_offset) data.push_offset_and_seek(section_data_offset)
bytes = data.read_size(self.size) bytes = data.read_size(self.size)
data.pop_offset_and_seek() data.pop_offset_and_seek()
@ -1243,6 +1278,7 @@ class Mach:
return None return None
class DylibLoadCommand(LoadCommand): class DylibLoadCommand(LoadCommand):
def __init__(self, lc): def __init__(self, lc):
Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off)
self.name = None self.name = None
@ -1252,17 +1288,21 @@ class Mach:
def unpack(self, mach_file, data): def unpack(self, mach_file, data):
byte_order_char = mach_file.magic.get_byte_order() byte_order_char = mach_file.magic.get_byte_order()
name_offset, self.timestamp, self.current_version, self.compatibility_version = data.get_n_uint32(4) name_offset, self.timestamp, self.current_version, self.compatibility_version = data.get_n_uint32(
4)
data.seek(self.file_off + name_offset, 0) data.seek(self.file_off + name_offset, 0)
self.name = data.get_fixed_length_c_string(self.length - 24) self.name = data.get_fixed_length_c_string(self.length - 24)
def __str__(self): def __str__(self):
s = Mach.LoadCommand.__str__(self); s = Mach.LoadCommand.__str__(self)
s += "%#8.8x %#8.8x %#8.8x " % (self.timestamp, self.current_version, self.compatibility_version) s += "%#8.8x %#8.8x %#8.8x " % (self.timestamp,
self.current_version,
self.compatibility_version)
s += self.name s += self.name
return s return s
class LoadDYLDLoadCommand(LoadCommand): class LoadDYLDLoadCommand(LoadCommand):
def __init__(self, lc): def __init__(self, lc):
Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off)
self.name = None self.name = None
@ -1272,12 +1312,14 @@ class Mach:
self.name = data.get_fixed_length_c_string(self.length - 12) self.name = data.get_fixed_length_c_string(self.length - 12)
def __str__(self): def __str__(self):
s = Mach.LoadCommand.__str__(self); s = Mach.LoadCommand.__str__(self)
s += "%s" % self.name s += "%s" % self.name
return s return s
class UnixThreadLoadCommand(LoadCommand): class UnixThreadLoadCommand(LoadCommand):
class ThreadState: class ThreadState:
def __init__(self): def __init__(self):
self.flavor = 0 self.flavor = 0
self.count = 0 self.count = 0
@ -1288,7 +1330,8 @@ class Mach:
self.register_values = data.get_n_uint32(self.count) self.register_values = data.get_n_uint32(self.count)
def __str__(self): def __str__(self):
s = "flavor = %u, count = %u, regs =" % (self.flavor, self.count) s = "flavor = %u, count = %u, regs =" % (
self.flavor, self.count)
i = 0 i = 0
for register_value in self.register_values: for register_value in self.register_values:
if i % 8 == 0: if i % 8 == 0:
@ -1307,12 +1350,13 @@ class Mach:
self.reg_sets.append(reg_set) self.reg_sets.append(reg_set)
def __str__(self): def __str__(self):
s = Mach.LoadCommand.__str__(self); s = Mach.LoadCommand.__str__(self)
for reg_set in self.reg_sets: for reg_set in self.reg_sets:
s += "%s" % reg_set s += "%s" % reg_set
return s return s
class DYLDInfoOnlyLoadCommand(LoadCommand): class DYLDInfoOnlyLoadCommand(LoadCommand):
def __init__(self, lc): def __init__(self, lc):
Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off)
self.rebase_off = 0 self.rebase_off = 0
@ -1328,18 +1372,25 @@ class Mach:
def unpack(self, mach_file, data): def unpack(self, mach_file, data):
byte_order_char = mach_file.magic.get_byte_order() byte_order_char = mach_file.magic.get_byte_order()
self.rebase_off, self.rebase_size, self.bind_off, self.bind_size, self.weak_bind_off, self.weak_bind_size, self.lazy_bind_off, self.lazy_bind_size, self.export_off, self.export_size = data.get_n_uint32(10) self.rebase_off, self.rebase_size, self.bind_off, self.bind_size, self.weak_bind_off, self.weak_bind_size, self.lazy_bind_off, self.lazy_bind_size, self.export_off, self.export_size = data.get_n_uint32(
10)
def __str__(self): def __str__(self):
s = Mach.LoadCommand.__str__(self); s = Mach.LoadCommand.__str__(self)
s += "rebase_off = %#8.8x, rebase_size = %u, " % (self.rebase_off, self.rebase_size) s += "rebase_off = %#8.8x, rebase_size = %u, " % (
s += "bind_off = %#8.8x, bind_size = %u, " % (self.bind_off, self.bind_size) self.rebase_off, self.rebase_size)
s += "weak_bind_off = %#8.8x, weak_bind_size = %u, " % (self.weak_bind_off, self.weak_bind_size) s += "bind_off = %#8.8x, bind_size = %u, " % (
s += "lazy_bind_off = %#8.8x, lazy_bind_size = %u, " % (self.lazy_bind_off, self.lazy_bind_size) self.bind_off, self.bind_size)
s += "export_off = %#8.8x, export_size = %u, " % (self.export_off, self.export_size) s += "weak_bind_off = %#8.8x, weak_bind_size = %u, " % (
self.weak_bind_off, self.weak_bind_size)
s += "lazy_bind_off = %#8.8x, lazy_bind_size = %u, " % (
self.lazy_bind_off, self.lazy_bind_size)
s += "export_off = %#8.8x, export_size = %u, " % (
self.export_off, self.export_size)
return s return s
class DYLDSymtabLoadCommand(LoadCommand): class DYLDSymtabLoadCommand(LoadCommand):
def __init__(self, lc): def __init__(self, lc):
Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off)
self.ilocalsym = 0 self.ilocalsym = 0
@ -1363,10 +1414,11 @@ class Mach:
def unpack(self, mach_file, data): def unpack(self, mach_file, data):
byte_order_char = mach_file.magic.get_byte_order() byte_order_char = mach_file.magic.get_byte_order()
self.ilocalsym, self.nlocalsym, self.iextdefsym, self.nextdefsym, self.iundefsym, self.nundefsym, self.tocoff, self.ntoc, self.modtaboff, self.nmodtab, self.extrefsymoff, self.nextrefsyms, self.indirectsymoff, self.nindirectsyms, self.extreloff, self.nextrel, self.locreloff, self.nlocrel = data.get_n_uint32(18) self.ilocalsym, self.nlocalsym, self.iextdefsym, self.nextdefsym, self.iundefsym, self.nundefsym, self.tocoff, self.ntoc, self.modtaboff, self.nmodtab, self.extrefsymoff, self.nextrefsyms, self.indirectsymoff, self.nindirectsyms, self.extreloff, self.nextrel, self.locreloff, self.nlocrel = data.get_n_uint32(
18)
def __str__(self): def __str__(self):
s = Mach.LoadCommand.__str__(self); s = Mach.LoadCommand.__str__(self)
# s += "ilocalsym = %u, nlocalsym = %u, " % (self.ilocalsym, self.nlocalsym) # s += "ilocalsym = %u, nlocalsym = %u, " % (self.ilocalsym, self.nlocalsym)
# s += "iextdefsym = %u, nextdefsym = %u, " % (self.iextdefsym, self.nextdefsym) # s += "iextdefsym = %u, nextdefsym = %u, " % (self.iextdefsym, self.nextdefsym)
# s += "iundefsym %u, nundefsym = %u, " % (self.iundefsym, self.nundefsym) # s += "iundefsym %u, nundefsym = %u, " % (self.iundefsym, self.nundefsym)
@ -1375,19 +1427,30 @@ class Mach:
# s += "extrefsymoff = %#8.8x, nextrefsyms = %u, " % (self.extrefsymoff, self.nextrefsyms) # s += "extrefsymoff = %#8.8x, nextrefsyms = %u, " % (self.extrefsymoff, self.nextrefsyms)
# s += "indirectsymoff = %#8.8x, nindirectsyms = %u, " % (self.indirectsymoff, self.nindirectsyms) # s += "indirectsymoff = %#8.8x, nindirectsyms = %u, " % (self.indirectsymoff, self.nindirectsyms)
# s += "extreloff = %#8.8x, nextrel = %u, " % (self.extreloff, self.nextrel) # s += "extreloff = %#8.8x, nextrel = %u, " % (self.extreloff, self.nextrel)
# s += "locreloff = %#8.8x, nlocrel = %u" % (self.locreloff, self.nlocrel) # s += "locreloff = %#8.8x, nlocrel = %u" % (self.locreloff,
s += "ilocalsym = %-10u, nlocalsym = %u\n" % (self.ilocalsym, self.nlocalsym) # self.nlocrel)
s += " iextdefsym = %-10u, nextdefsym = %u\n" % (self.iextdefsym, self.nextdefsym) s += "ilocalsym = %-10u, nlocalsym = %u\n" % (
s += " iundefsym = %-10u, nundefsym = %u\n" % (self.iundefsym, self.nundefsym) self.ilocalsym, self.nlocalsym)
s += " tocoff = %#8.8x, ntoc = %u\n" % (self.tocoff, self.ntoc) s += " iextdefsym = %-10u, nextdefsym = %u\n" % (
s += " modtaboff = %#8.8x, nmodtab = %u\n" % (self.modtaboff, self.nmodtab) self.iextdefsym, self.nextdefsym)
s += " extrefsymoff = %#8.8x, nextrefsyms = %u\n" % (self.extrefsymoff, self.nextrefsyms) s += " iundefsym = %-10u, nundefsym = %u\n" % (
s += " indirectsymoff = %#8.8x, nindirectsyms = %u\n" % (self.indirectsymoff, self.nindirectsyms) self.iundefsym, self.nundefsym)
s += " extreloff = %#8.8x, nextrel = %u\n" % (self.extreloff, self.nextrel) s += " tocoff = %#8.8x, ntoc = %u\n" % (
s += " locreloff = %#8.8x, nlocrel = %u" % (self.locreloff, self.nlocrel) self.tocoff, self.ntoc)
s += " modtaboff = %#8.8x, nmodtab = %u\n" % (
self.modtaboff, self.nmodtab)
s += " extrefsymoff = %#8.8x, nextrefsyms = %u\n" % (
self.extrefsymoff, self.nextrefsyms)
s += " indirectsymoff = %#8.8x, nindirectsyms = %u\n" % (
self.indirectsymoff, self.nindirectsyms)
s += " extreloff = %#8.8x, nextrel = %u\n" % (
self.extreloff, self.nextrel)
s += " locreloff = %#8.8x, nlocrel = %u" % (
self.locreloff, self.nlocrel)
return s return s
class SymtabLoadCommand(LoadCommand): class SymtabLoadCommand(LoadCommand):
def __init__(self, lc): def __init__(self, lc):
Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off)
self.symoff = 0 self.symoff = 0
@ -1397,15 +1460,17 @@ class Mach:
def unpack(self, mach_file, data): def unpack(self, mach_file, data):
byte_order_char = mach_file.magic.get_byte_order() byte_order_char = mach_file.magic.get_byte_order()
self.symoff, self.nsyms, self.stroff, self.strsize = data.get_n_uint32(4) self.symoff, self.nsyms, self.stroff, self.strsize = data.get_n_uint32(
4)
def __str__(self): def __str__(self):
s = Mach.LoadCommand.__str__(self); s = Mach.LoadCommand.__str__(self)
s += "symoff = %#8.8x, nsyms = %u, stroff = %#8.8x, strsize = %u" % (self.symoff, self.nsyms, self.stroff, self.strsize) s += "symoff = %#8.8x, nsyms = %u, stroff = %#8.8x, strsize = %u" % (
self.symoff, self.nsyms, self.stroff, self.strsize)
return s return s
class UUIDLoadCommand(LoadCommand): class UUIDLoadCommand(LoadCommand):
def __init__(self, lc): def __init__(self, lc):
Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off)
self.uuid = None self.uuid = None
@ -1419,11 +1484,12 @@ class Mach:
mach_file.uuid = self.uuid mach_file.uuid = self.uuid
def __str__(self): def __str__(self):
s = Mach.LoadCommand.__str__(self); s = Mach.LoadCommand.__str__(self)
s += self.uuid.__str__() s += self.uuid.__str__()
return s return s
class DataBlobLoadCommand(LoadCommand): class DataBlobLoadCommand(LoadCommand):
def __init__(self, lc): def __init__(self, lc):
Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off)
self.dataoff = 0 self.dataoff = 0
@ -1434,11 +1500,13 @@ class Mach:
self.dataoff, self.datasize = data.get_n_uint32(2) self.dataoff, self.datasize = data.get_n_uint32(2)
def __str__(self): def __str__(self):
s = Mach.LoadCommand.__str__(self); s = Mach.LoadCommand.__str__(self)
s += "dataoff = %#8.8x, datasize = %u" % (self.dataoff, self.datasize) s += "dataoff = %#8.8x, datasize = %u" % (
self.dataoff, self.datasize)
return s return s
class EncryptionInfoLoadCommand(LoadCommand): class EncryptionInfoLoadCommand(LoadCommand):
def __init__(self, lc): def __init__(self, lc):
Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off)
self.cryptoff = 0 self.cryptoff = 0
@ -1450,8 +1518,9 @@ class Mach:
self.cryptoff, self.cryptsize, self.cryptid = data.get_n_uint32(3) self.cryptoff, self.cryptsize, self.cryptid = data.get_n_uint32(3)
def __str__(self): def __str__(self):
s = Mach.LoadCommand.__str__(self); s = Mach.LoadCommand.__str__(self)
s += "file-range = [%#8.8x - %#8.8x), cryptsize = %u, cryptid = %u" % (self.cryptoff, self.cryptoff + self.cryptsize, self.cryptsize, self.cryptid) s += "file-range = [%#8.8x - %#8.8x), cryptsize = %u, cryptid = %u" % (
self.cryptoff, self.cryptoff + self.cryptsize, self.cryptsize, self.cryptid)
return s return s
class SegmentLoadCommand(LoadCommand): class SegmentLoadCommand(LoadCommand):
@ -1469,13 +1538,16 @@ class Mach:
self.flags = 0 self.flags = 0
def unpack(self, mach_file, data): def unpack(self, mach_file, data):
is_64 = self.command.get_enum_value() == LC_SEGMENT_64; is_64 = self.command.get_enum_value() == LC_SEGMENT_64
self.segname = data.get_fixed_length_c_string(16, '', True) self.segname = data.get_fixed_length_c_string(16, '', True)
if is_64: if is_64:
self.vmaddr, self.vmsize, self.fileoff, self.filesize = data.get_n_uint64(4) self.vmaddr, self.vmsize, self.fileoff, self.filesize = data.get_n_uint64(
4)
else: else:
self.vmaddr, self.vmsize, self.fileoff, self.filesize = data.get_n_uint32(4) self.vmaddr, self.vmsize, self.fileoff, self.filesize = data.get_n_uint32(
self.maxprot, self.initprot, self.nsects, self.flags = data.get_n_uint32(4) 4)
self.maxprot, self.initprot, self.nsects, self.flags = data.get_n_uint32(
4)
mach_file.segments.append(self) mach_file.segments.append(self)
for i in range(self.nsects): for i in range(self.nsects):
section = Mach.Section() section = Mach.Section()
@ -1483,19 +1555,23 @@ class Mach:
section.index = len(mach_file.sections) section.index = len(mach_file.sections)
mach_file.sections.append(section) mach_file.sections.append(section)
def __str__(self): def __str__(self):
s = Mach.LoadCommand.__str__(self); s = Mach.LoadCommand.__str__(self)
if self.command.get_enum_value() == LC_SEGMENT: if self.command.get_enum_value() == LC_SEGMENT:
s += "%#8.8x %#8.8x %#8.8x %#8.8x " % (self.vmaddr, self.vmsize, self.fileoff, self.filesize) s += "%#8.8x %#8.8x %#8.8x %#8.8x " % (
self.vmaddr, self.vmsize, self.fileoff, self.filesize)
else: else:
s += "%#16.16x %#16.16x %#16.16x %#16.16x " % (self.vmaddr, self.vmsize, self.fileoff, self.filesize) s += "%#16.16x %#16.16x %#16.16x %#16.16x " % (
s += "%s %s %3u %#8.8x" % (vm_prot_names[self.maxprot], vm_prot_names[self.initprot], self.nsects, self.flags) self.vmaddr, self.vmsize, self.fileoff, self.filesize)
s += "%s %s %3u %#8.8x" % (vm_prot_names[self.maxprot], vm_prot_names[
self.initprot], self.nsects, self.flags)
s += ' ' + self.segname s += ' ' + self.segname
return s return s
class NList: class NList:
class Type: class Type:
class Stab(dict_utils.Enum): class Stab(dict_utils.Enum):
enum = { enum = {
'N_GSYM': N_GSYM, 'N_GSYM': N_GSYM,
@ -1561,7 +1637,6 @@ class Mach:
type_str += ' | EXT ' type_str += ' | EXT '
return type_str return type_str
def __init__(self): def __init__(self):
self.index = 0 self.index = 0
self.name_offset = 0 self.name_offset = 0
@ -1580,7 +1655,10 @@ class Mach:
self.value = data.get_uint64() self.value = data.get_uint64()
else: else:
self.value = data.get_uint32() self.value = data.get_uint32()
data.push_offset_and_seek (mach_file.file_off + symtab_lc.stroff + self.name_offset) data.push_offset_and_seek(
mach_file.file_off +
symtab_lc.stroff +
self.name_offset)
# print "get string for symbol[%u]" % self.index # print "get string for symbol[%u]" % self.index
self.name = data.get_c_string() self.name = data.get_c_string()
data.pop_offset_and_seek() data.pop_offset_and_seek()
@ -1589,8 +1667,8 @@ class Mach:
name_display = '' name_display = ''
if len(self.name): if len(self.name):
name_display = ' "%s"' % self.name name_display = ' "%s"' % self.name
return '%#8.8x %#2.2x (%-20s) %#2.2x %#4.4x %16.16x%s' % (self.name_offset, self.type.value, self.type, self.sect_idx, self.desc, self.value, name_display) return '%#8.8x %#2.2x (%-20s) %#2.2x %#4.4x %16.16x%s' % (self.name_offset,
self.type.value, self.type, self.sect_idx, self.desc, self.value, name_display)
class Interactive(cmd.Cmd): class Interactive(cmd.Cmd):
'''Interactive command interpreter to mach-o files.''' '''Interactive command interpreter to mach-o files.'''
@ -1636,20 +1714,101 @@ class Mach:
return False return False
if __name__ == '__main__': if __name__ == '__main__':
parser = optparse.OptionParser(description='A script that parses skinny and universal mach-o files.') parser = optparse.OptionParser(
parser.add_option('--arch', '-a', type='string', metavar='arch', dest='archs', action='append', help='specify one or more architectures by name') description='A script that parses skinny and universal mach-o files.')
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) parser.add_option(
parser.add_option('-H', '--header', action='store_true', dest='dump_header', help='dump the mach-o file header', default=False) '--arch',
parser.add_option('-l', '--load-commands', action='store_true', dest='dump_load_commands', help='dump the mach-o load commands', default=False) '-a',
parser.add_option('-s', '--symtab', action='store_true', dest='dump_symtab', help='dump the mach-o symbol table', default=False) type='string',
parser.add_option('-S', '--sections', action='store_true', dest='dump_sections', help='dump the mach-o sections', default=False) metavar='arch',
parser.add_option('--section', type='string', metavar='sectname', dest='section_names', action='append', help='Specify one or more section names to dump', default=[]) dest='archs',
parser.add_option('-o', '--out', type='string', dest='outfile', help='Used in conjunction with the --section=NAME option to save a single section\'s data to disk.', default=False) action='append',
parser.add_option('-i', '--interactive', action='store_true', dest='interactive', help='enable interactive mode', default=False) help='specify one or more architectures by name')
parser.add_option('-m', '--mangled', action='store_true', dest='find_mangled', help='dump all mangled names in a mach file', default=False) parser.add_option(
parser.add_option('-c', '--compare', action='store_true', dest='compare', help='compare two mach files', default=False) '-v',
parser.add_option('-M', '--extract-modules', action='store_true', dest='extract_modules', help='Extract modules from file', default=False) '--verbose',
parser.add_option('-C', '--count', type='int', dest='max_count', help='Sets the max byte count when dumping section data', default=-1) action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
parser.add_option(
'-H',
'--header',
action='store_true',
dest='dump_header',
help='dump the mach-o file header',
default=False)
parser.add_option(
'-l',
'--load-commands',
action='store_true',
dest='dump_load_commands',
help='dump the mach-o load commands',
default=False)
parser.add_option(
'-s',
'--symtab',
action='store_true',
dest='dump_symtab',
help='dump the mach-o symbol table',
default=False)
parser.add_option(
'-S',
'--sections',
action='store_true',
dest='dump_sections',
help='dump the mach-o sections',
default=False)
parser.add_option(
'--section',
type='string',
metavar='sectname',
dest='section_names',
action='append',
help='Specify one or more section names to dump',
default=[])
parser.add_option(
'-o',
'--out',
type='string',
dest='outfile',
help='Used in conjunction with the --section=NAME option to save a single section\'s data to disk.',
default=False)
parser.add_option(
'-i',
'--interactive',
action='store_true',
dest='interactive',
help='enable interactive mode',
default=False)
parser.add_option(
'-m',
'--mangled',
action='store_true',
dest='find_mangled',
help='dump all mangled names in a mach file',
default=False)
parser.add_option(
'-c',
'--compare',
action='store_true',
dest='compare',
help='compare two mach files',
default=False)
parser.add_option(
'-M',
'--extract-modules',
action='store_true',
dest='extract_modules',
help='Extract modules from file',
default=False)
parser.add_option(
'-C',
'--count',
type='int',
dest='max_count',
help='Sets the max byte count when dumping section data',
default=-1)
(options, mach_files) = parser.parse_args() (options, mach_files) = parser.parse_args()
if options.extract_modules: if options.extract_modules:
@ -1684,4 +1843,3 @@ if __name__ == '__main__':
interpreter.cmdloop() interpreter.cmdloop()
else: else:
mach.dump(options) mach.dump(options)

View File

@ -26,9 +26,14 @@ except ImportError:
# On Darwin, try the currently selected Xcode directory # On Darwin, try the currently selected Xcode directory
xcode_dir = commands.getoutput("xcode-select --print-path") xcode_dir = commands.getoutput("xcode-select --print-path")
if xcode_dir: if xcode_dir:
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python')) lldb_python_dirs.append(
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') os.path.realpath(
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') 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 success = False
for lldb_python_dir in lldb_python_dirs: for lldb_python_dir in lldb_python_dirs:
if os.path.exists(lldb_python_dir): if os.path.exists(lldb_python_dir):
@ -53,6 +58,7 @@ import string
import struct import struct
import time import time
def append_data_callback(option, opt_str, value, parser): def append_data_callback(option, opt_str, value, parser):
if opt_str == "--uint8": if opt_str == "--uint8":
int8 = int(value, 0) int8 = int(value, 0)
@ -79,24 +85,100 @@ def append_data_callback(option, opt_str, value, parser):
int64 = int(value, 0) int64 = int(value, 0)
parser.values.data += struct.pack('1q', int64) parser.values.data += struct.pack('1q', int64)
def create_memfind_options(): def create_memfind_options():
usage = "usage: %prog [options] STARTADDR [ENDADDR]" 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 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. can be specified multiple times to look for longer streams of data.
''' '''
parser = optparse.OptionParser(description=description, prog='memfind',usage=usage) parser = optparse.OptionParser(
parser.add_option('-s', '--size', type='int', metavar='BYTESIZE', dest='size', help='Specify the byte size to search.', default=0) description=description,
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='') prog='memfind',
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='') usage=usage)
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(
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='') '-s',
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='') '--size',
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='') type='int',
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='') metavar='BYTESIZE',
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='') 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 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 # Use the Shell Lexer to properly parse up command options just like a
# shell would # shell would
@ -113,27 +195,37 @@ def memfind_command (debugger, command, result, dict):
# return # return
memfind(debugger.GetSelectedTarget(), options, args, result) memfind(debugger.GetSelectedTarget(), options, args, result)
def print_error(str, show_usage, result): def print_error(str, show_usage, result):
print >>result, str print >>result, str
if show_usage: if show_usage:
print >>result, create_memfind_options().format_help() print >>result, create_memfind_options().format_help()
def memfind(target, options, args, result): def memfind(target, options, args, result):
num_args = len(args) num_args = len(args)
start_addr = 0 start_addr = 0
if num_args == 1: if num_args == 1:
if options.size > 0: 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 return
start_addr = int(args[0], 0) start_addr = int(args[0], 0)
elif num_args == 2: elif num_args == 2:
if options.size != 0: 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 return
start_addr = int(args[0], 0) start_addr = int(args[0], 0)
end_addr = int(args[1], 0) end_addr = int(args[1], 0)
if start_addr >= end_addr: 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 return
options.size = end_addr - start_addr options.size = end_addr - start_addr
else: else:
@ -156,7 +248,8 @@ def memfind (target, options, args, result):
bytes = process.ReadMemory(start_addr, options.size, error) bytes = process.ReadMemory(start_addr, options.size, error)
if error.Success(): if error.Success():
num_matches = 0 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: for byte in options.data:
print >>result, '%2.2x' % ord(byte), print >>result, '%2.2x' % ord(byte),
print >>result print >>result
@ -164,7 +257,8 @@ def memfind (target, options, args, result):
match_index = string.find(bytes, options.data) match_index = string.find(bytes, options.data)
while match_index != -1: while match_index != -1:
num_matches = num_matches + 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) match_index = string.find(bytes, options.data, match_index + 1)
if num_matches == 0: 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' print 'error: this script is designed to be used within the embedded script interpreter in LLDB'
elif getattr(lldb, 'debugger', None): elif getattr(lldb, 'debugger', None):
memfind_command.__doc__ = create_memfind_options().format_help() 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' print '"memfind" command installed, use the "--help" option for detailed help'

View File

@ -3,6 +3,7 @@
import lldb import lldb
import struct import struct
class OperatingSystemPlugIn(object): class OperatingSystemPlugIn(object):
"""Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class""" """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class"""
@ -14,7 +15,7 @@ class OperatingSystemPlugIn(object):
self.process = None self.process = None
self.registers = None self.registers = None
self.threads = 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.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
@ -26,7 +27,12 @@ class OperatingSystemPlugIn(object):
def create_thread(self, tid, context): def create_thread(self, tid, context):
if tid == 0x444444444: 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) self.threads.append(thread_info)
return thread_info return thread_info
return None 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() # 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 # 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 # 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. # described by the dictionary returned from a call to the
self.threads = [ # get_register_info() method.
{ 'tid' : 0x111111111, 'name' : 'one' , 'queue' : 'queue1', 'state' : 'stopped', 'stop_reason' : 'breakpoint'}, self.threads = [{'tid': 0x111111111,
{ 'tid' : 0x222222222, 'name' : 'two' , 'queue' : 'queue2', 'state' : 'stopped', 'stop_reason' : 'none' }, 'name': 'one',
{ 'tid' : 0x333333333, 'name' : 'three', 'queue' : 'queue3', 'state' : 'stopped', 'stop_reason' : 'trace' , 'register_data_addr' : 0x100000000 } '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 return self.threads
def get_register_info(self): def get_register_info(self):
if self.registers == None: if self.registers is None:
self.registers = dict() self.registers = dict()
triple = self.process.target.triple triple = self.process.target.triple
if triple: if triple:
@ -91,14 +109,123 @@ class OperatingSystemPlugIn(object):
def get_register_data(self, tid): def get_register_data(self, tid):
if tid == 0x111111111: 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: 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: 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: 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: 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 return None

View File

@ -32,9 +32,14 @@ except ImportError:
# On Darwin, try the currently selected Xcode directory # On Darwin, try the currently selected Xcode directory
xcode_dir = commands.getoutput("xcode-select --print-path") xcode_dir = commands.getoutput("xcode-select --print-path")
if xcode_dir: if xcode_dir:
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python')) lldb_python_dirs.append(
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') os.path.realpath(
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') 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 success = False
for lldb_python_dir in lldb_python_dirs: for lldb_python_dir in lldb_python_dirs:
if os.path.exists(lldb_python_dir): if os.path.exists(lldb_python_dir):
@ -54,6 +59,7 @@ except ImportError:
class Timer: class Timer:
def __enter__(self): def __enter__(self):
self.start = time.clock() self.start = time.clock()
return self return self
@ -62,17 +68,23 @@ class Timer:
self.end = time.clock() self.end = time.clock()
self.interval = self.end - self.start self.interval = self.end - self.start
class Action(object): class Action(object):
"""Class that encapsulates actions to take when a thread stops for a reason.""" """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 = callback
self.callback_owner = callback_owner 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" assert False, "performance.Action.ThreadStopped(self, thread) must be overridden in a subclass"
class PlanCompleteAction (Action): 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) Action.__init__(self, callback, callback_owner)
def ThreadStopped(self, thread): def ThreadStopped(self, thread):
if thread.GetStopReason() == lldb.eStopReasonPlanComplete: if thread.GetStopReason() == lldb.eStopReasonPlanComplete:
if self.callback: if self.callback:
@ -85,7 +97,16 @@ class PlanCompleteAction (Action):
class BreakpointAction (Action): 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) Action.__init__(self, callback, callback_owner)
self.modules = lldb.SBFileSpecList() self.modules = lldb.SBFileSpecList()
self.files = lldb.SBFileSpecList() self.files = lldb.SBFileSpecList()
@ -97,7 +118,8 @@ class BreakpointAction (Action):
if module: if module:
if isinstance(module, types.ListType): if isinstance(module, types.ListType):
for module_path in module: 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): elif isinstance(module, types.StringTypes):
self.modules.Append(lldb.SBFileSpec(module, False)) self.modules.Append(lldb.SBFileSpec(module, False))
if name: if name:
@ -109,9 +131,14 @@ class BreakpointAction (Action):
self.files.Append(lldb.SBFileSpec(f, False)) self.files.Append(lldb.SBFileSpec(f, False))
elif isinstance(file, types.StringTypes): elif isinstance(file, types.StringTypes):
self.files.Append(lldb.SBFileSpec(file, False)) 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: elif file and line:
self.breakpoints.append (self.target.BreakpointCreateByLocation(file, line)) self.breakpoints.append(
self.target.BreakpointCreateByLocation(
file, line))
def ThreadStopped(self, thread): def ThreadStopped(self, thread):
if thread.GetStopReason() == lldb.eStopReasonBreakpoint: if thread.GetStopReason() == lldb.eStopReasonBreakpoint:
for bp in self.breakpoints: for bp in self.breakpoints:
@ -123,8 +150,11 @@ class BreakpointAction (Action):
self.callback(thread) self.callback(thread)
return True return True
return False return False
class TestCase: class TestCase:
"""Class that aids in running performance tests.""" """Class that aids in running performance tests."""
def __init__(self): def __init__(self):
self.verbose = False self.verbose = False
self.debugger = lldb.SBDebugger.Create() self.debugger = lldb.SBDebugger.Create()
@ -151,7 +181,8 @@ class TestCase:
if not error.Success(): if not error.Success():
print "error: %s" % error.GetCString() print "error: %s" % error.GetCString()
if self.process: 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 True
return False return False
@ -225,32 +256,48 @@ class TestCase:
if select_thread and not selected_thread: if select_thread and not selected_thread:
self.thread = thread self.thread = thread
selected_thread = self.process.SetSelectedThread(thread) selected_thread = self.process.SetSelectedThread(
thread)
for action in self.user_actions: for action in self.user_actions:
action.ThreadStopped(thread) action.ThreadStopped(thread)
if fatal: if fatal:
# if self.verbose: # if self.verbose:
# Xcode.RunCommand(self.debugger,"bt all",true) # Xcode.RunCommand(self.debugger,"bt all",true)
sys.exit(1) sys.exit(1)
return event return event
class Measurement: class Measurement:
'''A class that encapsulates a measurement''' '''A class that encapsulates a measurement'''
def __init__(self): def __init__(self):
object.__init__(self) object.__init__(self)
def Measure(self): def Measure(self):
assert False, "performance.Measurement.Measure() must be subclassed" assert False, "performance.Measurement.Measure() must be subclassed"
class MemoryMeasurement(Measurement): class MemoryMeasurement(Measurement):
'''A class that can measure memory statistics for a process.''' '''A class that can measure memory statistics for a process.'''
def __init__(self, pid): def __init__(self, pid):
Measurement.__init__(self) Measurement.__init__(self)
self.pid = pid self.pid = pid
self.stats = ["rprvt","rshrd","rsize","vsize","vprvt","kprvt","kshrd","faults","cow","pageins"] self.stats = [
self.command = "top -l 1 -pid %u -stats %s" % (self.pid, ",".join(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() self.value = dict()
def Measure(self): def Measure(self):
@ -283,6 +330,7 @@ class MemoryMeasurement(Measurement):
class TesterTestCase(TestCase): class TesterTestCase(TestCase):
def __init__(self): def __init__(self):
TestCase.__init__(self) TestCase.__init__(self)
self.verbose = True self.verbose = True
@ -308,10 +356,19 @@ class TesterTestCase(TestCase):
if self.target: if self.target:
with Timer() as breakpoint_timer: with Timer() as breakpoint_timer:
bp = self.target.BreakpointCreateByName("main") 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(
self.user_actions.append (PlanCompleteAction(callback=TesterTestCase.PlanComplete, callback_owner=self)) BreakpointAction(
breakpoint=bp,
callback=TesterTestCase.BreakpointHit,
callback_owner=self))
self.user_actions.append(
PlanCompleteAction(
callback=TesterTestCase.PlanComplete,
callback_owner=self))
if self.Launch(): if self.Launch():
while not self.done: while not self.done:

View File

@ -28,9 +28,14 @@ except ImportError:
# On Darwin, try the currently selected Xcode directory # On Darwin, try the currently selected Xcode directory
xcode_dir = commands.getoutput("xcode-select --print-path") xcode_dir = commands.getoutput("xcode-select --print-path")
if xcode_dir: if xcode_dir:
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python')) lldb_python_dirs.append(
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') os.path.realpath(
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') 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 success = False
for lldb_python_dir in lldb_python_dirs: for lldb_python_dir in lldb_python_dirs:
if os.path.exists(lldb_python_dir): if os.path.exists(lldb_python_dir):
@ -48,11 +53,13 @@ except ImportError:
print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly" print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
sys.exit(1) sys.exit(1)
def print_threads(process, options): def print_threads(process, options):
if options.show_threads: if options.show_threads:
for thread in process: for thread in process:
print '%s %s' % (thread, thread.GetFrameAtIndex(0)) print '%s %s' % (thread, thread.GetFrameAtIndex(0))
def run_commands(command_interpreter, commands): def run_commands(command_interpreter, commands):
return_obj = lldb.SBCommandReturnObject() return_obj = lldb.SBCommandReturnObject()
for command in commands: for command in commands:
@ -64,6 +71,7 @@ def run_commands(command_interpreter, commands):
if options.stop_on_error: if options.stop_on_error:
break break
def main(argv): def main(argv):
description = '''Debugs a program using the LLDB python API and uses asynchronous broadcast events to watch for process state changes.''' description = '''Debugs a program using the LLDB python API and uses asynchronous broadcast events to watch for process state changes.'''
epilog = '''Examples: epilog = '''Examples:
@ -76,24 +84,144 @@ def main(argv):
''' '''
optparse.OptionParser.format_epilog = lambda self, formatter: self.epilog 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 = optparse.OptionParser(
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help="Enable verbose logging.", default=False) description=description,
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.') prog='process_events',
parser.add_option('-a', '--arch', type='string', dest='arch', help='The architecture to use when creating the debug target.', default=None) usage='usage: process_events [options] program [arg1 arg2]',
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) epilog=epilog)
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(
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=[]) '-v',
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=[]) '--verbose',
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=[]) action='store_true',
parser.add_option('-T', '--no-threads', action='store_false', dest='show_threads', help="Don't show threads when process stops.", default=True) dest='verbose',
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) help="Enable verbose logging.",
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) default=False)
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(
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.') '-b',
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) '--breakpoint',
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) action='append',
parser.add_option('-P', '--attach-name', type='string', dest='attach_name', metavar='PROCESSNAME', help='Specify a process to attach to by name.', default=None) type='string',
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) 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: try:
(options, args) = parser.parse_args(argv) (options, args) = parser.parse_args(argv)
except: except:
@ -117,7 +245,8 @@ def main(argv):
sys.exit(1) sys.exit(1)
elif not options.attach_name is None: elif not options.attach_name is None:
if options.run_count == 1: 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: else:
print "error: --run-count can't be used with the --attach-name option" print "error: --run-count can't be used with the --attach-name option"
sys.exit(1) sys.exit(1)
@ -125,8 +254,6 @@ def main(argv):
print 'error: a program path for a program to debug and its arguments are required' print 'error: a program path for a program to debug and its arguments are required'
sys.exit(1) sys.exit(1)
# Create a new debugger instance # Create a new debugger instance
debugger = lldb.SBDebugger.Create() debugger = lldb.SBDebugger.Create()
debugger.SetAsync(True) debugger.SetAsync(True)
@ -136,12 +263,14 @@ def main(argv):
if exe: if exe:
print "Creating a target for '%s'" % exe print "Creating a target for '%s'" % exe
error = lldb.SBError() 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: if target:
# Set any breakpoints that were specified in the args if we are launching. We use the # 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: if launch_info and options.breakpoints:
for bp in options.breakpoints: for bp in options.breakpoints:
debugger.HandleCommand("_regexp-break %s" % (bp)) debugger.HandleCommand("_regexp-break %s" % (bp))
@ -175,7 +304,8 @@ def main(argv):
pid = process.GetProcessID() pid = process.GetProcessID()
print 'Process is %i' % (pid) print 'Process is %i' % (pid)
if attach_info: 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() process.Continue()
listener = debugger.GetListener() listener = debugger.GetListener()
@ -196,20 +326,25 @@ def main(argv):
if stop_idx == 0: if stop_idx == 0:
if launch_info: if launch_info:
print "process %u launched" % (pid) print "process %u launched" % (pid)
run_commands(command_interpreter, ['breakpoint list']) run_commands(
command_interpreter, ['breakpoint list'])
else: else:
print "attached to process %u" % (pid) print "attached to process %u" % (pid)
for m in target.modules: for m in target.modules:
print m print m
if options.breakpoints: if options.breakpoints:
for bp in options.breakpoints: for bp in options.breakpoints:
debugger.HandleCommand( "_regexp-break %s" % (bp)) debugger.HandleCommand(
run_commands(command_interpreter, ['breakpoint list']) "_regexp-break %s" % (bp))
run_commands (command_interpreter, options.launch_commands) run_commands(
command_interpreter, ['breakpoint list'])
run_commands(
command_interpreter, options.launch_commands)
else: else:
if options.verbose: if options.verbose:
print "process %u stopped" % (pid) print "process %u stopped" % (pid)
run_commands (command_interpreter, options.stop_commands) run_commands(
command_interpreter, options.stop_commands)
stop_idx += 1 stop_idx += 1
print_threads(process, options) print_threads(process, options)
print "continuing process %u" % (pid) print "continuing process %u" % (pid)
@ -220,18 +355,22 @@ def main(argv):
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: else:
print "process %u exited with status %u" % (pid, process.GetExitStatus()) print "process %u exited with status %u" % (pid, process.GetExitStatus())
run_commands (command_interpreter, options.exit_commands) run_commands(
command_interpreter, options.exit_commands)
done = True done = True
elif state == lldb.eStateCrashed: elif state == lldb.eStateCrashed:
print "process %u crashed" % (pid) print "process %u crashed" % (pid)
print_threads(process, options) print_threads(process, options)
run_commands (command_interpreter, options.crash_commands) run_commands(
command_interpreter, options.crash_commands)
done = True done = True
elif state == lldb.eStateDetached: elif state == lldb.eStateDetached:
print "process %u detached" % (pid) print "process %u detached" % (pid)
done = True done = True
elif state == lldb.eStateRunning: 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: if options.verbose:
print "process %u resumed" % (pid) print "process %u resumed" % (pid)
elif state == lldb.eStateUnloaded: elif state == lldb.eStateUnloaded:

View File

@ -2,7 +2,9 @@ import sys
import inspect import inspect
from collections import OrderedDict from collections import OrderedDict
class TracebackFancy: class TracebackFancy:
def __init__(self, traceback): def __init__(self, traceback):
self.t = traceback self.t = traceback
@ -10,18 +12,21 @@ class TracebackFancy:
return FrameFancy(self.t.tb_frame) return FrameFancy(self.t.tb_frame)
def getLineNumber(self): def getLineNumber(self):
return self.t.tb_lineno if self.t != None else None return self.t.tb_lineno if self.t is not None else None
def getNext(self): def getNext(self):
return TracebackFancy(self.t.tb_next) return TracebackFancy(self.t.tb_next)
def __str__(self): def __str__(self):
if self.t == None: if self.t is None:
return "" return ""
str_self = "%s @ %s" % (self.getFrame().getName(), self.getLineNumber()) str_self = "%s @ %s" % (
self.getFrame().getName(), self.getLineNumber())
return str_self + "\n" + self.getNext().__str__() return str_self + "\n" + self.getNext().__str__()
class ExceptionFancy: class ExceptionFancy:
def __init__(self, frame): def __init__(self, frame):
self.etraceback = frame.f_exc_traceback self.etraceback = frame.f_exc_traceback
self.etype = frame.exc_type self.etype = frame.exc_type
@ -36,7 +41,7 @@ class ExceptionFancy:
return TracebackFancy(self.etraceback) return TracebackFancy(self.etraceback)
def __nonzero__(self): def __nonzero__(self):
return self.etraceback != None or self.etype != None or self.evalue != None return self.etraceback is not None or self.etype is not None or self.evalue is not None
def getType(self): def getType(self):
return str(self.etype) return str(self.etype)
@ -44,26 +49,30 @@ class ExceptionFancy:
def getValue(self): def getValue(self):
return self.evalue return self.evalue
class CodeFancy: class CodeFancy:
def __init__(self, code): def __init__(self, code):
self.c = code self.c = code
def getArgCount(self): def getArgCount(self):
return self.c.co_argcount if self.c != None else 0 return self.c.co_argcount if self.c is not None else 0
def getFilename(self): def getFilename(self):
return self.c.co_filename if self.c != None else "" return self.c.co_filename if self.c is not None else ""
def getVariables(self): def getVariables(self):
return self.c.co_varnames if self.c != None else [] return self.c.co_varnames if self.c is not None else []
def getName(self): def getName(self):
return self.c.co_name if self.c != None else "" return self.c.co_name if self.c is not None else ""
def getFileName(self): def getFileName(self):
return self.c.co_filename if self.c != None else "" return self.c.co_filename if self.c is not None else ""
class ArgsFancy: class ArgsFancy:
def __init__(self, frame, arginfo): def __init__(self, frame, arginfo):
self.f = frame self.f = frame
self.a = arginfo self.a = arginfo
@ -116,7 +125,9 @@ class ArgsFancy:
return self.f.f_locals[kwargs] return self.f.f_locals[kwargs]
return {} return {}
class FrameFancy: class FrameFancy:
def __init__(self, frame): def __init__(self, frame):
self.f = frame self.f = frame
@ -124,27 +135,31 @@ class FrameFancy:
return FrameFancy(self.f.f_back) return FrameFancy(self.f.f_back)
def getLineNumber(self): def getLineNumber(self):
return self.f.f_lineno if self.f != None else 0 return self.f.f_lineno if self.f is not None else 0
def getCodeInformation(self): def getCodeInformation(self):
return CodeFancy(self.f.f_code) if self.f != None else None return CodeFancy(self.f.f_code) if self.f is not None else None
def getExceptionInfo(self): def getExceptionInfo(self):
return ExceptionFancy(self.f) if self.f != None else None return ExceptionFancy(self.f) if self.f is not None else None
def getName(self): def getName(self):
return self.getCodeInformation().getName() if self.f != None else "" return self.getCodeInformation().getName() if self.f is not None else ""
def getFileName(self): def getFileName(self):
return self.getCodeInformation().getFileName() if self.f != None else "" return self.getCodeInformation().getFileName() if self.f is not None else ""
def getLocals(self): def getLocals(self):
return self.f.f_locals if self.f != None else {} return self.f.f_locals if self.f is not None else {}
def getArgumentInfo(self): def getArgumentInfo(self):
return ArgsFancy(self.f,inspect.getargvalues(self.f)) if self.f != None else None return ArgsFancy(
self.f, inspect.getargvalues(
self.f)) if self.f is not None else None
class TracerClass: class TracerClass:
def callEvent(self, frame): def callEvent(self, frame):
pass pass
@ -170,24 +185,25 @@ tracer_impl = TracerClass()
def the_tracer_entrypoint(frame, event, args): def the_tracer_entrypoint(frame, event, args):
if tracer_impl == None: if tracer_impl is None:
return None return None
if event == "call": if event == "call":
call_retval = tracer_impl.callEvent(FrameFancy(frame)) call_retval = tracer_impl.callEvent(FrameFancy(frame))
if call_retval == False: if not call_retval:
return None return None
return the_tracer_entrypoint return the_tracer_entrypoint
elif event == "line": elif event == "line":
line_retval = tracer_impl.lineEvent(FrameFancy(frame)) line_retval = tracer_impl.lineEvent(FrameFancy(frame))
if line_retval == False: if not line_retval:
return None return None
return the_tracer_entrypoint return the_tracer_entrypoint
elif event == "return": elif event == "return":
tracer_impl.returnEvent(FrameFancy(frame), args) tracer_impl.returnEvent(FrameFancy(frame), args)
elif event == "exception": elif event == "exception":
exty, exva, extb = args exty, exva, extb = args
exception_retval = tracer_impl.exceptionEvent(FrameFancy(frame),ExceptionFancy(extb,exty,exva)) exception_retval = tracer_impl.exceptionEvent(
if exception_retval == False: FrameFancy(frame), ExceptionFancy(extb, exty, exva))
if not exception_retval:
return None return None
return the_tracer_entrypoint return the_tracer_entrypoint
elif event == "c_call": elif event == "c_call":
@ -198,16 +214,20 @@ def the_tracer_entrypoint(frame,event,args):
tracer_impl.cExceptionEvent(FrameFancy(frame), args) tracer_impl.cExceptionEvent(FrameFancy(frame), args)
return None return None
def enable(t=None): def enable(t=None):
global tracer_impl global tracer_impl
if t: if t:
tracer_impl = t tracer_impl = t
sys.settrace(the_tracer_entrypoint) sys.settrace(the_tracer_entrypoint)
def disable(): def disable():
sys.settrace(None) sys.settrace(None)
class LoggingTracer: class LoggingTracer:
def callEvent(self, frame): def callEvent(self, frame):
print "call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo()) print "call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
@ -221,8 +241,12 @@ class LoggingTracer:
print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber()) print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
print "tb: " + str(exception.getTraceback()) print "tb: " + str(exception.getTraceback())
# the same functionality as LoggingTracer, but with a little more lldb-specific smarts # the same functionality as LoggingTracer, but with a little more
# lldb-specific smarts
class LLDBAwareTracer: class LLDBAwareTracer:
def callEvent(self, frame): def callEvent(self, frame):
if frame.getName() == "<module>": if frame.getName() == "<module>":
return return
@ -232,7 +256,8 @@ class LLDBAwareTracer:
if "Python.framework" in frame.getFileName(): if "Python.framework" in frame.getFileName():
print "call into Python at " + frame.getName() print "call into Python at " + frame.getName()
return return
if frame.getName() == "__init__" and frame.getCaller().getName() == "run_one_line" and frame.getCaller().getLineNumber() == 101: if frame.getName() == "__init__" and frame.getCaller().getName(
) == "run_one_line" and frame.getCaller().getLineNumber() == 101:
return False return False
strout = "call " + frame.getName() strout = "call " + frame.getName()
if (frame.getCaller().getFileName() == ""): if (frame.getCaller().getFileName() == ""):
@ -243,7 +268,8 @@ class LLDBAwareTracer:
continue continue
strout = strout + ("%s = %s " % (arg, args[arg])) strout = strout + ("%s = %s " % (arg, args[arg]))
else: else:
strout += " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo()) strout += " from " + frame.getCaller().getName() + " @ " + \
str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
print strout print strout
def lineEvent(self, frame): def lineEvent(self, frame):
@ -255,7 +281,8 @@ class LLDBAwareTracer:
if "Python.framework" in frame.getFileName(): if "Python.framework" in frame.getFileName():
print "running into Python at " + frame.getName() + " @ " + str(frame.getLineNumber()) print "running into Python at " + frame.getName() + " @ " + str(frame.getLineNumber())
return return
strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + \
" locals are "
if (frame.getCaller().getFileName() == ""): if (frame.getCaller().getFileName() == ""):
locals = frame.getLocals() locals = frame.getLocals()
for local in locals: for local in locals:
@ -276,7 +303,8 @@ class LLDBAwareTracer:
if "Python.framework" in frame.getFileName(): if "Python.framework" in frame.getFileName():
print "return from Python at " + frame.getName() + " return value is " + str(retval) print "return from Python at " + frame.getName() + " return value is " + str(retval)
return return
strout = "return from " + frame.getName() + " return value is " + str(retval) + " locals are " strout = "return from " + frame.getName() + " return value is " + \
str(retval) + " locals are "
if (frame.getCaller().getFileName() == ""): if (frame.getCaller().getFileName() == ""):
locals = frame.getLocals() locals = frame.getLocals()
for local in locals: for local in locals:
@ -294,19 +322,23 @@ class LLDBAwareTracer:
print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber()) print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
print "tb: " + str(exception.getTraceback()) print "tb: " + str(exception.getTraceback())
def f(x, y=None): def f(x, y=None):
if x > 0: if x > 0:
return 2 + f(x - 2) return 2 + f(x - 2)
return 35 return 35
def g(x): def g(x):
return 1.134 / x return 1.134 / x
def print_keyword_args(**kwargs): def print_keyword_args(**kwargs):
# kwargs is a dict of the keyword args passed to the function # kwargs is a dict of the keyword args passed to the function
for key, value in kwargs.iteritems(): for key, value in kwargs.iteritems():
print "%s = %s" % (key, value) print "%s = %s" % (key, value)
def total(initial=5, *numbers, **keywords): def total(initial=5, *numbers, **keywords):
count = initial count = initial
for number in numbers: for number in numbers:

View File

@ -2,6 +2,7 @@
import lldb import lldb
class value(object): class value(object):
'''A class that wraps an lldb.SBValue object and returns an object that '''A class that wraps an lldb.SBValue object and returns an object that
can be used as an object with attribytes:\n 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.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 argv.children - return a list of sbvalue objects that represents all of the children of this value
''' '''
def __init__(self, sbvalue): def __init__(self, sbvalue):
self.sbvalue = sbvalue self.sbvalue = sbvalue
@ -37,8 +39,10 @@ class value(object):
return self.sbvalue.__str__() return self.sbvalue.__str__()
def __getitem__(self, key): def __getitem__(self, key):
if type(key) is int: if isinstance(key, int):
return value(self.sbvalue.GetChildAtIndex(key, lldb.eNoDynamicValues, True)) return value(
self.sbvalue.GetChildAtIndex(
key, lldb.eNoDynamicValues, True))
raise TypeError raise TypeError
def __getattr__(self, name): def __getattr__(self, name):
@ -79,14 +83,21 @@ class value(object):
# the value for the lldb.SBValue # the value for the lldb.SBValue
children = [] children = []
for i in range(self.sbvalue.GetNumChildren()): for i in range(self.sbvalue.GetNumChildren()):
children.append(value(self.sbvalue.GetChildAtIndex(i, lldb.eNoDynamicValues, True))) children.append(
value(
self.sbvalue.GetChildAtIndex(
i,
lldb.eNoDynamicValues,
True)))
return children return children
raise AttributeError raise AttributeError
class variable(object): class variable(object):
'''A class that treats a lldb.SBValue and allows it to be used just as '''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 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"''' in your code, you would be able to do: "pt.x + pt.y"'''
def __init__(self, sbvalue): def __init__(self, sbvalue):
self.sbvalue = sbvalue self.sbvalue = sbvalue
@ -101,8 +112,11 @@ class variable(object):
def __getitem__(self, key): def __getitem__(self, key):
# Allow array access if this value has children... # Allow array access if this value has children...
if type(key) is int: if isinstance(key, int):
return variable(self.sbvalue.GetValueForExpressionPath("[%i]" % key)) return variable(
self.sbvalue.GetValueForExpressionPath(
"[%i]" %
key))
raise TypeError raise TypeError
def __getattr__(self, name): def __getattr__(self, name):
@ -252,4 +266,3 @@ class variable(object):
def __hex__(self): def __hex__(self):
return '0x%x' % self.sbvalue.GetValueAsSigned() return '0x%x' % self.sbvalue.GetValueAsSigned()

View File

@ -95,7 +95,9 @@
import lldb import lldb
class SimpleStep: class SimpleStep:
def __init__(self, thread_plan, dict): def __init__(self, thread_plan, dict):
self.thread_plan = thread_plan self.thread_plan = thread_plan
self.start_address = thread_plan.GetThread().GetFrameAtIndex(0).GetPC() self.start_address = thread_plan.GetThread().GetFrameAtIndex(0).GetPC()
@ -120,11 +122,14 @@ class SimpleStep:
def should_step(self): def should_step(self):
return True return True
class StepWithPlan: class StepWithPlan:
def __init__(self, thread_plan, dict): def __init__(self, thread_plan, dict):
self.thread_plan = thread_plan self.thread_plan = thread_plan
self.start_address = thread_plan.GetThread().GetFrameAtIndex(0).GetPCAddress() 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 # Since all I'm doing is running a plan, I will only ever get askedthis
@ -145,7 +150,9 @@ class StepWithPlan:
# and when it stops at each line, it checks some condition (in this example the # 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. # value of a variable) and stops if that condition is true.
class StepCheckingCondition: class StepCheckingCondition:
def __init__(self, thread_plan, dict): def __init__(self, thread_plan, dict):
self.thread_plan = thread_plan self.thread_plan = thread_plan
self.start_frame = thread_plan.GetThread().GetFrameAtIndex(0) self.start_frame = thread_plan.GetThread().GetFrameAtIndex(0)
@ -157,7 +164,8 @@ class StepCheckingCondition:
start_address = cur_line_entry.GetStartAddress() start_address = cur_line_entry.GetStartAddress()
end_address = cur_line_entry.GetEndAddress() end_address = cur_line_entry.GetEndAddress()
line_range = end_address.GetFileAddress() - start_address.GetFileAddress() 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 # We are stepping, so if we stop for any other reason, it isn't
@ -202,10 +210,13 @@ class StepCheckingCondition:
# plans are not a safe place to call lldb command-line commands, so the information # plans are not a safe place to call lldb command-line commands, so the information
# is gathered through SB API calls. # is gathered through SB API calls.
class FinishPrintAndContinue: class FinishPrintAndContinue:
def __init__(self, thread_plan, dict): def __init__(self, thread_plan, dict):
self.thread_plan = thread_plan 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() self.thread = self.thread_plan.GetThread()
def is_stale(self): def is_stale(self):

View File

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

View File

@ -3,6 +3,7 @@
import lldb import lldb
import shlex import shlex
def dump_module_sources(module, result): def dump_module_sources(module, result):
if module: if module:
print >> result, "Module: %s" % (module.file) print >> result, "Module: %s" % (module.file)
@ -10,6 +11,7 @@ def dump_module_sources(module, result):
if compile_unit.file: if compile_unit.file:
print >> result, " %s" % (compile_unit.file) print >> result, " %s" % (compile_unit.file)
def info_sources(debugger, command, result, dict): 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) module_names = shlex.split(command)
@ -24,5 +26,6 @@ def info_sources(debugger, command, result, dict):
def __lldb_init_module(debugger, dict): def __lldb_init_module(debugger, dict):
# Add any commands contained in this module to LLDB # 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.' print 'The "info_sources" command has been installed, type "help info_sources" or "info_sources --help" for detailed help.'

View File

@ -5,12 +5,20 @@ import commands
import optparse import optparse
import shlex import shlex
def stack_frames(debugger, command, result, dict): def stack_frames(debugger, command, result, dict):
command_args = shlex.split(command) command_args = shlex.split(command)
usage = "usage: %prog [options] <PATH> [PATH ...]" 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.''' 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 = optparse.OptionParser(
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) description=description, prog='ls', usage=usage)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
try: try:
(options, args) = parser.parse_args(command_args) (options, args) = parser.parse_args(command_args)
except: except:
@ -28,7 +36,8 @@ def stack_frames(debugger, command, result, dict):
frame_size = 0 frame_size = 0
if frame.idx == 1: if frame.idx == 1:
if frame.fp == last_frame.fp: 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 first_frame_size = 0
frame_size = frame.fp - frame.sp frame_size = frame.fp - frame.sp
else: else:
@ -55,5 +64,6 @@ def stack_frames(debugger, command, result, dict):
print frame_info 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." print "A new command called 'stack_frames' was added, type 'stack_frames --help' for more information."

View File

@ -37,16 +37,23 @@ import sys
import time import time
import uuid import uuid
class Address: class Address:
"""Class that represents an address that will be symbolicated""" """Class that represents an address that will be symbolicated"""
def __init__(self, target, load_addr): def __init__(self, target, load_addr):
self.target = target self.target = target
self.load_addr = load_addr # The load address that this object represents self.load_addr = load_addr # The load address that this object represents
self.so_addr = None # the resolved lldb.SBAddress (if any), named so_addr for section/offset address # the resolved lldb.SBAddress (if any), named so_addr for
# section/offset address
self.so_addr = None
self.sym_ctx = None # The cached symbol context for this address self.sym_ctx = None # The cached symbol context for this address
self.description = None # Any original textual description of this address to be used as a backup in case symbolication fails # Any original textual description of this address to be used as a
# backup in case symbolication fails
self.description = None
self.symbolication = None # The cached symbolicated string that describes this address self.symbolication = None # The cached symbolicated string that describes this address
self.inlined = False self.inlined = False
def __str__(self): def __str__(self):
s = "%#16.16x" % (self.load_addr) s = "%#16.16x" % (self.load_addr)
if self.symbolication: if self.symbolication:
@ -58,7 +65,7 @@ class Address:
return s return s
def resolve_addr(self): def resolve_addr(self):
if self.so_addr == None: if self.so_addr is None:
self.so_addr = self.target.ResolveLoadAddress(self.load_addr) self.so_addr = self.target.ResolveLoadAddress(self.load_addr)
return self.so_addr return self.so_addr
@ -66,10 +73,11 @@ class Address:
return self.inlined return self.inlined
def get_symbol_context(self): def get_symbol_context(self):
if self.sym_ctx == None: if self.sym_ctx is None:
sb_addr = self.resolve_addr() sb_addr = self.resolve_addr()
if sb_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: else:
self.sym_ctx = lldb.SBSymbolContext() self.sym_ctx = lldb.SBSymbolContext()
return self.sym_ctx return self.sym_ctx
@ -84,7 +92,7 @@ class Address:
return None return None
def symbolicate(self, verbose=False): def symbolicate(self, verbose=False):
if self.symbolication == None: if self.symbolication is None:
self.symbolication = '' self.symbolication = ''
self.inlined = False self.inlined = False
sym_ctx = self.get_symbol_context() sym_ctx = self.get_symbol_context()
@ -101,17 +109,21 @@ class Address:
block = sym_ctx.GetBlock() block = sym_ctx.GetBlock()
line_entry = sym_ctx.GetLineEntry() line_entry = sym_ctx.GetLineEntry()
symbol = sym_ctx.GetSymbol() symbol = sym_ctx.GetSymbol()
inlined_block = block.GetContainingInlinedBlock(); inlined_block = block.GetContainingInlinedBlock()
if function: if function:
self.symbolication += function.GetName() self.symbolication += function.GetName()
if inlined_block: if inlined_block:
self.inlined = True self.inlined = True
self.symbolication += ' [inlined] ' + inlined_block.GetInlinedName(); self.symbolication += ' [inlined] ' + \
block_range_idx = inlined_block.GetRangeIndexForBlockAddress (self.so_addr) inlined_block.GetInlinedName()
block_range_idx = inlined_block.GetRangeIndexForBlockAddress(
self.so_addr)
if block_range_idx < lldb.UINT32_MAX: if block_range_idx < lldb.UINT32_MAX:
block_range_start_addr = inlined_block.GetRangeStartAddress (block_range_idx) block_range_start_addr = inlined_block.GetRangeStartAddress(
function_start_load_addr = block_range_start_addr.GetLoadAddress (self.target) block_range_idx)
function_start_load_addr = block_range_start_addr.GetLoadAddress(
self.target)
if function_start_load_addr == -1: 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: elif symbol:
@ -121,7 +133,8 @@ class Address:
self.symbolication = '' self.symbolication = ''
return False 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 function_offset = self.load_addr - function_start_load_addr
if function_offset > 0: if function_offset > 0:
self.symbolication += " + %u" % (function_offset) self.symbolication += " + %u" % (function_offset)
@ -142,11 +155,13 @@ class Address:
return True return True
return False return False
class Section: class Section:
"""Class that represents an load address range""" """Class that represents an load address range"""
sect_info_regex = re.compile('(?P<name>[^=]+)=(?P<range>.*)') sect_info_regex = re.compile('(?P<name>[^=]+)=(?P<range>.*)')
addr_regex = re.compile('^\s*(?P<start>0x[0-9A-Fa-f]+)\s*$') 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.start_addr = start_addr
@ -157,13 +172,17 @@ class Section:
def InitWithSBTargetAndSBSection(cls, target, section): def InitWithSBTargetAndSBSection(cls, target, section):
sect_load_addr = section.GetLoadAddress(target) sect_load_addr = section.GetLoadAddress(target)
if sect_load_addr != lldb.LLDB_INVALID_ADDRESS: 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 return obj
else: else:
return None return None
def contains(self, addr): 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): def set_from_string(self, s):
match = self.sect_info_regex.match(s) match = self.sect_info_regex.match(s)
@ -195,15 +214,17 @@ class Section:
def __str__(self): def __str__(self):
if self.name: if self.name:
if self.end_addr != None: if self.end_addr is not None:
if self.start_addr != None: if self.start_addr is not None:
return "%s=[0x%16.16x - 0x%16.16x)" % (self.name, self.start_addr, self.end_addr) return "%s=[0x%16.16x - 0x%16.16x)" % (
self.name, self.start_addr, self.end_addr)
else: else:
if self.start_addr != None: if self.start_addr is not None:
return "%s=0x%16.16x" % (self.name, self.start_addr) return "%s=0x%16.16x" % (self.name, self.start_addr)
return self.name return self.name
return "<invalid>" return "<invalid>"
class Image: class Image:
"""A class that represents an executable image and any associated data""" """A class that represents an executable image and any associated data"""
@ -229,7 +250,8 @@ class Image:
obj.resolved = True obj.resolved = True
obj.arch = module.triple obj.arch = module.triple
for section in module.sections: for section in module.sections:
symb_section = Section.InitWithSBTargetAndSBSection(target, section) symb_section = Section.InitWithSBTargetAndSBSection(
target, section)
if symb_section: if symb_section:
obj.section_infos.append(symb_section) obj.section_infos.append(symb_section)
obj.arch = module.triple obj.arch = module.triple
@ -268,7 +290,7 @@ class Image:
s += "%s " % (resolved_path) s += "%s " % (resolved_path)
for section_info in self.section_infos: for section_info in self.section_infos:
s += ", %s" % (section_info) s += ", %s" % (section_info)
if self.slide != None: if self.slide is not None:
s += ', slide = 0x%16.16x' % self.slide s += ', slide = 0x%16.16x' % self.slide
return s return s
@ -301,7 +323,7 @@ class Image:
return None return None
def has_section_load_info(self): 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): def load_module(self, target):
if self.unavailable: if self.unavailable:
@ -315,9 +337,11 @@ class Image:
num_sections_loaded = 0 num_sections_loaded = 0
for section_info in self.section_infos: for section_info in self.section_infos:
if section_info.name: if section_info.name:
section = self.module.FindSection (section_info.name) section = self.module.FindSection(
section_info.name)
if section: if section:
error = target.SetSectionLoadAddress (section, section_info.start_addr) error = target.SetSectionLoadAddress(
section, section_info.start_addr)
if error.Success(): if error.Success():
num_sections_loaded += 1 num_sections_loaded += 1
else: else:
@ -325,11 +349,13 @@ class Image:
else: else:
return 'error: unable to find the section named "%s"' % section_info.name return 'error: unable to find the section named "%s"' % section_info.name
else: 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: if num_sections_loaded == 0:
return 'error: no sections were successfully loaded' return 'error: no sections were successfully loaded'
else: else:
err = target.SetModuleLoadAddress(self.module, self.slide) err = target.SetModuleLoadAddress(
self.module, self.slide)
if err.Fail(): if err.Fail():
return err.GetCString() return err.GetCString()
return None return None
@ -343,7 +369,8 @@ class Image:
def add_module(self, target): def add_module(self, target):
'''Add the Image described in this object to "target" and load the sections if "load" is True.''' '''Add the Image described in this object to "target" and load the sections if "load" is True.'''
if target: 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() uuid_str = self.get_normalized_uuid_string()
if uuid_str: if uuid_str:
self.module = target.AddModule(None, None, uuid_str) self.module = target.AddModule(None, None, uuid_str)
@ -352,9 +379,11 @@ class Image:
if self.unavailable: if self.unavailable:
return None return None
resolved_path = self.get_resolved_path() 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: 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(): if self.has_section_load_info():
return self.load_module(target) return self.load_module(target)
else: else:
@ -388,11 +417,12 @@ class Image:
return None return None
if self.locate_module_and_debug_symbols(): if self.locate_module_and_debug_symbols():
resolved_path = self.get_resolved_path(); resolved_path = self.get_resolved_path()
path_spec = lldb.SBFileSpec(resolved_path) path_spec = lldb.SBFileSpec(resolved_path)
#result.PutCString ('plist[%s] = %s' % (uuid, self.plist)) #result.PutCString ('plist[%s] = %s' % (uuid, self.plist))
error = lldb.SBError() 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: if target:
self.module = target.FindModule(path_spec) self.module = target.FindModule(path_spec)
if self.has_section_load_info(): if self.has_section_load_info():
@ -406,6 +436,7 @@ class Image:
print 'error: unable to locate main executable (%s) "%s"' % (self.arch, self.path) print 'error: unable to locate main executable (%s) "%s"' % (self.arch, self.path)
return None return None
class Symbolicator: class Symbolicator:
def __init__(self): def __init__(self):
@ -418,7 +449,7 @@ class Symbolicator:
def InitWithSBTarget(cls, target): def InitWithSBTarget(cls, target):
obj = cls() obj = cls()
obj.target = target obj.target = target
obj.images = list(); obj.images = list()
triple = target.triple triple = target.triple
if triple: if triple:
arch = triple.split('-')[0] arch = triple.split('-')[0]
@ -478,7 +509,6 @@ class Symbolicator:
return self.target return self.target
return None return None
def symbolicate(self, load_addr, verbose=False): def symbolicate(self, load_addr, verbose=False):
if not self.target: if not self.target:
self.create_target() self.create_target()
@ -502,15 +532,18 @@ class Symbolicator:
symbolicated_addresses = list() symbolicated_addresses = list()
symbolicated_addresses.append(symbolicated_address) symbolicated_addresses.append(symbolicated_address)
# See if we were able to reconstruct anything? # See if we were able to reconstruct anything?
while 1: while True:
inlined_parent_so_addr = lldb.SBAddress() 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: if not inlined_parent_sym_ctx:
break break
if not inlined_parent_so_addr: if not inlined_parent_so_addr:
break 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.sym_ctx = inlined_parent_sym_ctx
symbolicated_address.so_addr = inlined_parent_so_addr symbolicated_address.so_addr = inlined_parent_so_addr
symbolicated_address.symbolicate(verbose) symbolicated_address.symbolicate(verbose)
@ -525,12 +558,18 @@ class Symbolicator:
return None 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() lines = list()
pc_index = -1 pc_index = -1
comment_column = 50 comment_column = 50
for inst_idx, inst in enumerate(instructions): for inst_idx, inst in enumerate(instructions):
inst_pc = inst.GetAddress().GetLoadAddress(target); inst_pc = inst.GetAddress().GetLoadAddress(target)
if pc == inst_pc: if pc == inst_pc:
pc_index = inst_idx pc_index = inst_idx
mnemonic = inst.GetMnemonic(target) mnemonic = inst.GetMnemonic(target)
@ -545,7 +584,8 @@ def disassemble_instructions (target, instructions, pc, insts_before_pc, insts_a
lines[-1] += "; %s" % comment lines[-1] += "; %s" % comment
if pc_index >= 0: 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: if non_zeroeth_frame and pc_index > 0:
pc_index = pc_index - 1 pc_index = pc_index - 1
if insts_before_pc == -1: if insts_before_pc == -1:
@ -566,6 +606,7 @@ def disassemble_instructions (target, instructions, pc, insts_before_pc, insts_a
else: else:
print ' ', lines[i] print ' ', lines[i]
def print_module_section_data(section): def print_module_section_data(section):
print section print section
section_data = section.GetSectionData() section_data = section.GetSectionData()
@ -574,42 +615,87 @@ def print_module_section_data (section):
section_data.GetDescription(ostream, section.GetFileAddress()) section_data.GetDescription(ostream, section.GetFileAddress())
print ostream.GetData() print ostream.GetData()
def print_module_section(section, depth): def print_module_section(section, depth):
print section print section
if depth > 0: if depth > 0:
num_sub_sections = section.GetNumSubSections() num_sub_sections = section.GetNumSubSections()
for sect_idx in range(num_sub_sections): 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(): 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: for sym in module:
print sym print sym
def Symbolicate(command_args): def Symbolicate(command_args):
usage = "usage: %prog [options] <addr1> [addr2 ...]" usage = "usage: %prog [options] <addr1> [addr2 ...]"
description = '''Symbolicate one or more addresses using LLDB's python scripting API..''' description = '''Symbolicate one or more addresses using LLDB's python scripting API..'''
parser = optparse.OptionParser(description=description, prog='crashlog.py',usage=usage) parser = optparse.OptionParser(
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) description=description,
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".') prog='crashlog.py',
parser.add_option('-f', '--file', type='string', metavar='file', dest='file', help='Specify a file to use when symbolicating') usage=usage)
parser.add_option('-a', '--arch', type='string', metavar='arch', dest='arch', help='Specify a architecture to use when symbolicating') parser.add_option(
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) '-v',
parser.add_option('--section', type='string', action='append', dest='section_strings', help='specify <sect-name>=<start-addr> or <sect-name>=<start-addr>-<end-addr>') '--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: try:
(options, args) = parser.parse_args(command_args) (options, args) = parser.parse_args(command_args)
except: except:
return return
symbolicator = Symbolicator() symbolicator = Symbolicator()
images = list(); images = list()
if options.file: if options.file:
image = Image(options.file); image = Image(options.file)
image.arch = options.arch 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: if options.section_strings:
for section_str in options.section_strings: for section_str in options.section_strings:
section = Section() section = Section()
@ -617,7 +703,7 @@ def Symbolicate(command_args):
image.add_section(section) image.add_section(section)
else: else:
sys.exit(1) sys.exit(1)
if options.slide != None: if options.slide is not None:
image.slide = options.slide image.slide = options.slide
symbolicator.images.append(image) symbolicator.images.append(image)
@ -627,7 +713,8 @@ def Symbolicate(command_args):
if target: if target:
for addr_str in args: for addr_str in args:
addr = int(addr_str, 0) 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: for symbolicated_addr in symbolicated_addrs:
print symbolicated_addr print symbolicated_addr
print print

View File

@ -27,9 +27,14 @@ except ImportError:
# On Darwin, try the currently selected Xcode directory # On Darwin, try the currently selected Xcode directory
xcode_dir = commands.getoutput("xcode-select --print-path") xcode_dir = commands.getoutput("xcode-select --print-path")
if xcode_dir: if xcode_dir:
lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python')) lldb_python_dirs.append(
lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') os.path.realpath(
lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') 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 success = False
for lldb_python_dir in lldb_python_dirs: for lldb_python_dir in lldb_python_dirs:
if os.path.exists(lldb_python_dir): if os.path.exists(lldb_python_dir):
@ -52,12 +57,14 @@ import optparse
import shlex import shlex
import time import time
def regex_option_callback(option, opt_str, value, parser): def regex_option_callback(option, opt_str, value, parser):
if opt_str == "--std": if opt_str == "--std":
value = '^std::' value = '^std::'
regex = re.compile(value) 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): def create_types_options(for_lldb_command):
if for_lldb_command: if for_lldb_command:
usage = "usage: %prog [options]" usage = "usage: %prog [options]"
@ -77,23 +84,84 @@ 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 specified with the --types TYPENAME option, all structure and class types will
be verified in all specified modules. 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: 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(
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".') '-a',
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=[]) '--arch',
parser.add_option('-d', '--debug', action='store_true', dest='debug', help='Pause 10 seconds to wait for a debugger to attach.', default=False) type='string',
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=[]) dest='arch',
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='Enable verbose logging and information.', default=False) help='The architecture to use when creating the debug target.',
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=[]) default=None)
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(
'-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 return parser
def verify_type(target, options, type): def verify_type(target, options, type):
print type print type
typename = type.GetName() typename = type.GetName()
# print 'type: %s' % (typename) # 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() byte_size = type.GetByteSize()
# if end_offset < byte_size: # if end_offset < byte_size:
# last_member_padding = byte_size - end_offset # 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 'Padding percentage: %2.2f %%' % ((float(padding) / float(byte_size)) * 100.0)
print 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 prev_end_offset = base_offset
typename = type.GetName() typename = type.GetName()
byte_size = type.GetByteSize() byte_size = type.GetByteSize()
@ -132,7 +208,8 @@ def verify_type_recursive (target, options, type, member_name, depth, base_offse
member_is_class_or_struct = False member_is_class_or_struct = False
if member_type_class == lldb.eTypeClassStruct or member_type_class == lldb.eTypeClassClass: if member_type_class == lldb.eTypeClassStruct or member_type_class == lldb.eTypeClassClass:
member_is_class_or_struct = True 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() ptr_size = target.GetAddressByteSize()
print '%+4u <%3u> %s__vtbl_ptr_type * _vptr;' % (prev_end_offset, ptr_size, ' ' * (depth + 1)) print '%+4u <%3u> %s__vtbl_ptr_type * _vptr;' % (prev_end_offset, ptr_size, ' ' * (depth + 1))
prev_end_offset = ptr_size 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)) print '%+4u <%3u> %s<PADDING>' % (prev_end_offset, member_padding, ' ' * (depth + 1))
if member_is_class_or_struct: 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: else:
prev_end_offset = member_total_offset + member_byte_size prev_end_offset = member_total_offset + member_byte_size
member_typename = member_type.GetName() member_typename = member_type.GetName()
@ -165,6 +249,7 @@ def verify_type_recursive (target, options, type, member_name, depth, base_offse
return (prev_end_offset, padding) 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 # Use the Shell Lexer to properly parse up command options just like a
# shell would # shell would
@ -176,9 +261,12 @@ def check_padding_command (debugger, command, result, dict):
# if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit # 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) # (courtesy of OptParse dealing with argument errors by throwing SystemExit)
result.SetStatus(lldb.eReturnStatusFailed) result.SetStatus(lldb.eReturnStatusFailed)
return "option parsing failed" # returning a string is the same as returning an error whose description is the string # returning a string is the same as returning an error whose
# description is the string
return "option parsing failed"
verify_types(debugger.GetSelectedTarget(), options) verify_types(debugger.GetSelectedTarget(), options)
@lldb.command("parse_all_struct_class_types") @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) command_args = shlex.split(command)
@ -224,7 +312,8 @@ def verify_types (target, options):
else: else:
print 'error: no type matches "%s" in "%s"' % (typename, module.file) print 'error: no type matches "%s" in "%s"' % (typename, module.file)
else: 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) print 'Found %u types in "%s"' % (len(types), module.file)
for type in types: for type in types:
verify_type(target, options, type) verify_type(target, options, type)
@ -248,7 +337,8 @@ if __name__ == '__main__':
for path in args: for path in args:
# in a command - the lldb.* convenience variables are not to be used # in a command - the lldb.* convenience variables are not to be used
# and their values (if any) are undefined # and their values (if any) are undefined
# this is the best practice to access those objects from within a command # this is the best practice to access those objects from within a
# command
error = lldb.SBError() error = lldb.SBError()
target = debugger.CreateTarget(path, target = debugger.CreateTarget(path,
options.arch, options.arch,
@ -261,5 +351,6 @@ if __name__ == '__main__':
verify_types(target, options) verify_types(target, options)
elif getattr(lldb, 'debugger', None): 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' print '"check_padding" command installed, use the "--help" option for detailed help'

View File

@ -98,7 +98,7 @@ name_to_gcc_dwarf_regnum = {
'ymm13': 44, 'ymm13': 44,
'ymm14': 45, 'ymm14': 45,
'ymm15': 46 'ymm15': 46
}; }
name_to_gdb_regnum = { name_to_gdb_regnum = {
'rax': 0, 'rax': 0,
@ -174,7 +174,7 @@ name_to_gdb_regnum = {
'ymm13': 70, 'ymm13': 70,
'ymm14': 71, 'ymm14': 71,
'ymm15': 72 'ymm15': 72
}; }
name_to_generic_regnum = { name_to_generic_regnum = {
'rip': LLDB_REGNUM_GENERIC_PC, 'rip': LLDB_REGNUM_GENERIC_PC,
@ -186,7 +186,8 @@ name_to_generic_regnum = {
'rcx': LLDB_REGNUM_GENERIC_ARG4, 'rcx': LLDB_REGNUM_GENERIC_ARG4,
'r8': LLDB_REGNUM_GENERIC_ARG5, 'r8': LLDB_REGNUM_GENERIC_ARG5,
'r9': LLDB_REGNUM_GENERIC_ARG6 '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: if reg_name in reg_num_dict:
@ -194,133 +195,550 @@ def get_reg_num (reg_num_dict, reg_name):
return LLDB_INVALID_REGNUM return LLDB_INVALID_REGNUM
x86_64_register_infos = [ x86_64_register_infos = [
{ 'name':'rax' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rax',
{ 'name':'rbx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'set': 0,
{ 'name':'rcx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg4' }, 'bitsize': 64,
{ 'name':'rdx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg3' }, 'encoding': eEncodingUint,
{ 'name':'rsi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg2' }, 'format': eFormatAddressInfo},
{ 'name':'rdi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg1' }, {'name': 'rbx',
{ 'name':'rbp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'fp' }, 'set': 0,
{ 'name':'rsp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'sp' }, 'bitsize': 64,
{ 'name':'r8' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg5' }, 'encoding': eEncodingUint,
{ 'name':'r9' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg6' }, 'format': eFormatAddressInfo},
{ 'name':'r10' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rcx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'r11' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'format': eFormatAddressInfo, 'alt-name': 'arg4'},
{ 'name':'r12' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rdx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'r13' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'format': eFormatAddressInfo, 'alt-name': 'arg3'},
{ 'name':'r14' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rsi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'r15' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'format': eFormatAddressInfo, 'alt-name': 'arg2'},
{ 'name':'rip' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'pc' }, {'name': 'rdi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'rflags', 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'arg1'},
{ 'name':'cs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'rbp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'ss' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'fp'},
{ 'name':'ds' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'rsp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'es' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'sp'},
{ 'name':'fs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'r8', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'gs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'arg5'},
{ 'name':'stmm0' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r9', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'stmm1' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo, 'alt-name': 'arg6'},
{ 'name':'stmm2' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r10',
{ 'name':'stmm3' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'stmm4' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'stmm5' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'stmm6' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'stmm7' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r11',
{ 'name':'fctrl' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'set': 0,
{ 'name':'fstat' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'bitsize': 64,
{ 'name':'ftag' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'encoding': eEncodingUint,
{ 'name':'fiseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo},
{ 'name':'fioff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'r12',
{ 'name':'foseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'set': 0,
{ 'name':'fooff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'bitsize': 64,
{ 'name':'fop' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'encoding': eEncodingUint,
{ 'name':'xmm0' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'xmm1' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r13',
{ 'name':'xmm2' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'xmm3' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'xmm4' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'xmm5' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'xmm6' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r14',
{ 'name':'xmm7' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'xmm8' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'xmm9' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'xmm10' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'xmm11' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r15',
{ 'name':'xmm12' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'xmm13' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'xmm14' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'xmm15' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'mxcsr' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'rip', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'orig_rax' , 'set':1, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'pc'},
# Registers that are contained in or composed of one of more other registers {'name': 'rflags', 'set': 0, 'bitsize': 32,
{ 'name':'eax' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'ebx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[31:0]' }, {'name': 'cs', 'set': 0, 'bitsize': 32,
{ 'name':'ecx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'edx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[31:0]' }, {'name': 'ss', 'set': 0, 'bitsize': 32,
{ 'name':'edi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'esi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[31:0]' }, {'name': 'ds', 'set': 0, 'bitsize': 32,
{ 'name':'ebp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'esp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[31:0]' }, {'name': 'es', 'set': 0, 'bitsize': 32,
{ 'name':'r8d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'r9d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[31:0]' }, {'name': 'fs', 'set': 0, 'bitsize': 32,
{ 'name':'r10d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'r11d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[31:0]' }, {'name': 'gs', 'set': 0, 'bitsize': 32,
{ 'name':'r12d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'r13d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[31:0]' }, {'name': 'stmm0',
{ 'name':'r14d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[31:0]' }, 'set': 1,
{ 'name':'r15d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[31:0]' }, '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': 'ax',
{ 'name':'bx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:0]' }, 'set': 0,
{ 'name':'cx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:0]' }, 'bitsize': 16,
{ 'name':'dx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:0]' }, 'encoding': eEncodingUint,
{ 'name':'di' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[15:0]' }, 'format': eFormatHex,
{ 'name':'si' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[15:0]' }, 'slice': 'rax[15:0]'},
{ 'name':'bp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[15:0]' }, {'name': 'bx',
{ 'name':'sp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[15:0]' }, 'set': 0,
{ 'name':'r8w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[15:0]' }, 'bitsize': 16,
{ 'name':'r9w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[15:0]' }, 'encoding': eEncodingUint,
{ 'name':'r10w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[15:0]' }, 'format': eFormatHex,
{ 'name':'r11w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[15:0]' }, 'slice': 'rbx[15:0]'},
{ 'name':'r12w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[15:0]' }, {'name': 'cx',
{ 'name':'r13w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[15:0]' }, 'set': 0,
{ 'name':'r14w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[15:0]' }, 'bitsize': 16,
{ 'name':'r15w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[15:0]' }, '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': 'ah',
{ 'name':'bh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:8]' }, 'set': 0,
{ 'name':'ch' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:8]' }, 'bitsize': 8,
{ 'name':'dh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15: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': 'al',
{ 'name':'bl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[7:0]' }, 'set': 0,
{ 'name':'cl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[7:0]' }, 'bitsize': 8,
{ 'name':'dl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[7:0]' }, 'encoding': eEncodingUint,
{ 'name':'dil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[7:0]' }, 'format': eFormatHex,
{ 'name':'sil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[7:0]' }, 'slice': 'rax[7:0]'},
{ 'name':'bpl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[7:0]' }, {'name': 'bl',
{ 'name':'spl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[7:0]' }, 'set': 0,
{ 'name':'r8l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[7:0]' }, 'bitsize': 8,
{ 'name':'r9l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[7:0]' }, 'encoding': eEncodingUint,
{ 'name':'r10l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[7:0]' }, 'format': eFormatHex,
{ 'name':'r11l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[7:0]' }, 'slice': 'rbx[7:0]'},
{ 'name':'r12l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[7:0]' }, {'name': 'cl',
{ 'name':'r13l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[7:0]' }, 'set': 0,
{ 'name':'r14l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[7:0]' }, 'bitsize': 8,
{ 'name':'r15l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[7:0]' }, '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 g_target_definition = None
def get_target_definition(): def get_target_definition():
global g_target_definition global g_target_definition
if g_target_definition == None: if g_target_definition is None:
g_target_definition = {} g_target_definition = {}
offset = 0 offset = 0
for reg_info in x86_64_register_infos: for reg_info in x86_64_register_infos:
reg_name = reg_info['name'] 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: if 'slice' not in reg_info and 'composite' not in reg_info:
reg_info['offset'] = offset reg_info['offset'] = offset
offset += reg_info['bitsize'] / 8 offset += reg_info['bitsize'] / 8
@ -341,13 +759,17 @@ def get_target_definition ():
if reg_num != LLDB_INVALID_REGNUM: if reg_num != LLDB_INVALID_REGNUM:
reg_info['gdb'] = reg_num 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['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['g-packet-size'] = offset
g_target_definition['breakpoint-pc-offset'] = -1 g_target_definition['breakpoint-pc-offset'] = -1
return g_target_definition return g_target_definition
def get_dynamic_setting(target, setting_name): def get_dynamic_setting(target, setting_name):
if setting_name == 'gdb-server-target-definition': if setting_name == 'gdb-server-target-definition':
return get_target_definition() return get_target_definition()

View File

@ -98,7 +98,7 @@ name_to_gcc_dwarf_regnum = {
'ymm13': 44, 'ymm13': 44,
'ymm14': 45, 'ymm14': 45,
'ymm15': 46 'ymm15': 46
}; }
name_to_gdb_regnum = { name_to_gdb_regnum = {
'rax': 0, 'rax': 0,
@ -174,7 +174,7 @@ name_to_gdb_regnum = {
'ymm13': 70, 'ymm13': 70,
'ymm14': 71, 'ymm14': 71,
'ymm15': 72 'ymm15': 72
}; }
name_to_generic_regnum = { name_to_generic_regnum = {
'rip': LLDB_REGNUM_GENERIC_PC, 'rip': LLDB_REGNUM_GENERIC_PC,
@ -186,7 +186,8 @@ name_to_generic_regnum = {
'rcx': LLDB_REGNUM_GENERIC_ARG4, 'rcx': LLDB_REGNUM_GENERIC_ARG4,
'r8': LLDB_REGNUM_GENERIC_ARG5, 'r8': LLDB_REGNUM_GENERIC_ARG5,
'r9': LLDB_REGNUM_GENERIC_ARG6 '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: if reg_name in reg_num_dict:
@ -194,132 +195,548 @@ def get_reg_num (reg_num_dict, reg_name):
return LLDB_INVALID_REGNUM return LLDB_INVALID_REGNUM
x86_64_register_infos = [ x86_64_register_infos = [
{ 'name':'rax' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rax',
{ 'name':'rbx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'set': 0,
{ 'name':'rcx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg4' }, 'bitsize': 64,
{ 'name':'rdx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg3' }, 'encoding': eEncodingUint,
{ 'name':'rsi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg2' }, 'format': eFormatAddressInfo},
{ 'name':'rdi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg1' }, {'name': 'rbx',
{ 'name':'rbp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'fp' }, 'set': 0,
{ 'name':'rsp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'sp' }, 'bitsize': 64,
{ 'name':'r8' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg5' }, 'encoding': eEncodingUint,
{ 'name':'r9' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg6' }, 'format': eFormatAddressInfo},
{ 'name':'r10' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rcx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'r11' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'format': eFormatAddressInfo, 'alt-name': 'arg4'},
{ 'name':'r12' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rdx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'r13' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'format': eFormatAddressInfo, 'alt-name': 'arg3'},
{ 'name':'r14' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rsi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'r15' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'format': eFormatAddressInfo, 'alt-name': 'arg2'},
{ 'name':'rip' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'pc' }, {'name': 'rdi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'rflags', 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'arg1'},
{ 'name':'cs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'rbp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'ss' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'fp'},
{ 'name':'ds' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'rsp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'es' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'sp'},
{ 'name':'fs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'r8', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'gs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'arg5'},
{ 'name':'stmm0' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r9', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'stmm1' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo, 'alt-name': 'arg6'},
{ 'name':'stmm2' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r10',
{ 'name':'stmm3' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'stmm4' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'stmm5' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'stmm6' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'stmm7' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r11',
{ 'name':'fctrl' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'set': 0,
{ 'name':'fstat' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'bitsize': 64,
{ 'name':'ftag' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'encoding': eEncodingUint,
{ 'name':'fiseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo},
{ 'name':'fioff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'r12',
{ 'name':'foseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'set': 0,
{ 'name':'fooff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'bitsize': 64,
{ 'name':'fop' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'encoding': eEncodingUint,
{ 'name':'xmm0' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'xmm1' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r13',
{ 'name':'xmm2' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'xmm3' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'xmm4' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'xmm5' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'xmm6' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r14',
{ 'name':'xmm7' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'xmm8' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'xmm9' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'xmm10' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'xmm11' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r15',
{ 'name':'xmm12' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'xmm13' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'xmm14' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'xmm15' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'mxcsr' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'rip', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
# Registers that are contained in or composed of one of more other registers 'format': eFormatAddressInfo, 'alt-name': 'pc'},
{ 'name':'eax' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[31:0]' }, {'name': 'rflags', 'set': 0, 'bitsize': 32,
{ 'name':'ebx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'ecx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[31:0]' }, {'name': 'cs', 'set': 0, 'bitsize': 32,
{ 'name':'edx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'edi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[31:0]' }, {'name': 'ss', 'set': 0, 'bitsize': 32,
{ 'name':'esi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'ebp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[31:0]' }, {'name': 'ds', 'set': 0, 'bitsize': 32,
{ 'name':'esp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'r8d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[31:0]' }, {'name': 'es', 'set': 0, 'bitsize': 32,
{ 'name':'r9d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'r10d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[31:0]' }, {'name': 'fs', 'set': 0, 'bitsize': 32,
{ 'name':'r11d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'r12d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[31:0]' }, {'name': 'gs', 'set': 0, 'bitsize': 32,
{ 'name':'r13d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'r14d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[31:0]' }, {'name': 'stmm0',
{ 'name':'r15d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[31:0]' }, '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': 'ax',
{ 'name':'bx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:0]' }, 'set': 0,
{ 'name':'cx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:0]' }, 'bitsize': 16,
{ 'name':'dx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:0]' }, 'encoding': eEncodingUint,
{ 'name':'di' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[15:0]' }, 'format': eFormatHex,
{ 'name':'si' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[15:0]' }, 'slice': 'rax[15:0]'},
{ 'name':'bp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[15:0]' }, {'name': 'bx',
{ 'name':'sp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[15:0]' }, 'set': 0,
{ 'name':'r8w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[15:0]' }, 'bitsize': 16,
{ 'name':'r9w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[15:0]' }, 'encoding': eEncodingUint,
{ 'name':'r10w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[15:0]' }, 'format': eFormatHex,
{ 'name':'r11w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[15:0]' }, 'slice': 'rbx[15:0]'},
{ 'name':'r12w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[15:0]' }, {'name': 'cx',
{ 'name':'r13w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[15:0]' }, 'set': 0,
{ 'name':'r14w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[15:0]' }, 'bitsize': 16,
{ 'name':'r15w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[15:0]' }, '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': 'ah',
{ 'name':'bh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:8]' }, 'set': 0,
{ 'name':'ch' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:8]' }, 'bitsize': 8,
{ 'name':'dh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15: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': 'al',
{ 'name':'bl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[7:0]' }, 'set': 0,
{ 'name':'cl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[7:0]' }, 'bitsize': 8,
{ 'name':'dl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[7:0]' }, 'encoding': eEncodingUint,
{ 'name':'dil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[7:0]' }, 'format': eFormatHex,
{ 'name':'sil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[7:0]' }, 'slice': 'rax[7:0]'},
{ 'name':'bpl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[7:0]' }, {'name': 'bl',
{ 'name':'spl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[7:0]' }, 'set': 0,
{ 'name':'r8l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[7:0]' }, 'bitsize': 8,
{ 'name':'r9l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[7:0]' }, 'encoding': eEncodingUint,
{ 'name':'r10l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[7:0]' }, 'format': eFormatHex,
{ 'name':'r11l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[7:0]' }, 'slice': 'rbx[7:0]'},
{ 'name':'r12l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[7:0]' }, {'name': 'cl',
{ 'name':'r13l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[7:0]' }, 'set': 0,
{ 'name':'r14l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[7:0]' }, 'bitsize': 8,
{ 'name':'r15l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[7:0]' }, '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 g_target_definition = None
def get_target_definition(): def get_target_definition():
global g_target_definition global g_target_definition
if g_target_definition == None: if g_target_definition is None:
g_target_definition = {} g_target_definition = {}
offset = 0 offset = 0
for reg_info in x86_64_register_infos: for reg_info in x86_64_register_infos:
reg_name = reg_info['name'] 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: if 'slice' not in reg_info and 'composite' not in reg_info:
reg_info['offset'] = offset reg_info['offset'] = offset
offset += reg_info['bitsize'] / 8 offset += reg_info['bitsize'] / 8
@ -340,13 +757,17 @@ def get_target_definition ():
if reg_num != LLDB_INVALID_REGNUM: if reg_num != LLDB_INVALID_REGNUM:
reg_info['gdb'] = reg_num 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['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['g-packet-size'] = offset
g_target_definition['breakpoint-pc-offset'] = -1 g_target_definition['breakpoint-pc-offset'] = -1
return g_target_definition return g_target_definition
def get_dynamic_setting(target, setting_name): def get_dynamic_setting(target, setting_name):
if setting_name == 'gdb-server-target-definition': if setting_name == 'gdb-server-target-definition':
return get_target_definition() return get_target_definition()

View File

@ -98,7 +98,7 @@ name_to_gcc_dwarf_regnum = {
'ymm13': 44, 'ymm13': 44,
'ymm14': 45, 'ymm14': 45,
'ymm15': 46 'ymm15': 46
}; }
name_to_gdb_regnum = { name_to_gdb_regnum = {
'rax': 0, 'rax': 0,
@ -174,7 +174,7 @@ name_to_gdb_regnum = {
'ymm13': 70, 'ymm13': 70,
'ymm14': 71, 'ymm14': 71,
'ymm15': 72 'ymm15': 72
}; }
name_to_generic_regnum = { name_to_generic_regnum = {
'rip': LLDB_REGNUM_GENERIC_PC, 'rip': LLDB_REGNUM_GENERIC_PC,
@ -186,7 +186,7 @@ name_to_generic_regnum = {
'rcx': LLDB_REGNUM_GENERIC_ARG4, 'rcx': LLDB_REGNUM_GENERIC_ARG4,
'r8': LLDB_REGNUM_GENERIC_ARG5, 'r8': LLDB_REGNUM_GENERIC_ARG5,
'r9': LLDB_REGNUM_GENERIC_ARG6 'r9': LLDB_REGNUM_GENERIC_ARG6
}; }
def get_reg_num(reg_num_dict, reg_name): def get_reg_num(reg_num_dict, reg_name):
@ -194,138 +194,555 @@ def get_reg_num (reg_num_dict, reg_name):
return reg_num_dict[reg_name] return reg_num_dict[reg_name]
return LLDB_INVALID_REGNUM 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: if reg_name in reg_num_dict:
return reg_num_dict[reg_name] return reg_num_dict[reg_name]
return LLDB_INVALID_REGNUM return LLDB_INVALID_REGNUM
x86_64_register_infos = [ x86_64_register_infos = [
{ 'name':'rax' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rax',
{ 'name':'rbx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'set': 0,
{ 'name':'rcx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg4' }, 'bitsize': 64,
{ 'name':'rdx' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg3' }, 'encoding': eEncodingUint,
{ 'name':'rsi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg2' }, 'format': eFormatAddressInfo},
{ 'name':'rdi' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg1' }, {'name': 'rbx',
{ 'name':'rbp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'fp' }, 'set': 0,
{ 'name':'rsp' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'sp' }, 'bitsize': 64,
{ 'name':'r8' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg5' }, 'encoding': eEncodingUint,
{ 'name':'r9' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'arg6' }, 'format': eFormatAddressInfo},
{ 'name':'r10' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rcx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'r11' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'format': eFormatAddressInfo, 'alt-name': 'arg4'},
{ 'name':'r12' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rdx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'r13' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'format': eFormatAddressInfo, 'alt-name': 'arg3'},
{ 'name':'r14' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, {'name': 'rsi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'r15' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo }, 'format': eFormatAddressInfo, 'alt-name': 'arg2'},
{ 'name':'rip' , 'set':0, 'bitsize':64 , 'encoding':eEncodingUint , 'format':eFormatAddressInfo, 'alt-name':'pc' }, {'name': 'rdi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'rflags', 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'arg1'},
{ 'name':'cs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'rbp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'ss' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'fp'},
{ 'name':'ds' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'rsp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'es' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'sp'},
{ 'name':'fs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'r8', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'gs' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo, 'alt-name': 'arg5'},
{ 'name':'stmm0' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r9', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
{ 'name':'stmm1' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo, 'alt-name': 'arg6'},
{ 'name':'stmm2' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r10',
{ 'name':'stmm3' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'stmm4' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'stmm5' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'stmm6' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'stmm7' , 'set':1, 'bitsize':80 , 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r11',
{ 'name':'fctrl' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'set': 0,
{ 'name':'fstat' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'bitsize': 64,
{ 'name':'ftag' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'encoding': eEncodingUint,
{ 'name':'fiseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'format': eFormatAddressInfo},
{ 'name':'fioff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'r12',
{ 'name':'foseg' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'set': 0,
{ 'name':'fooff' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'bitsize': 64,
{ 'name':'fop' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, 'encoding': eEncodingUint,
{ 'name':'xmm0' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'xmm1' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r13',
{ 'name':'xmm2' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'xmm3' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'xmm4' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'xmm5' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'xmm6' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r14',
{ 'name':'xmm7' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'xmm8' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'xmm9' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'xmm10' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'xmm11' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, {'name': 'r15',
{ 'name':'xmm12' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'set': 0,
{ 'name':'xmm13' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'bitsize': 64,
{ 'name':'xmm14' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'encoding': eEncodingUint,
{ 'name':'xmm15' , 'set':1, 'bitsize':128, 'encoding':eEncodingVector, 'format':eFormatVectorOfUInt8 }, 'format': eFormatAddressInfo},
{ 'name':'mxcsr' , 'set':1, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex }, {'name': 'rip', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint,
# Registers that are contained in or composed of one of more other registers 'format': eFormatAddressInfo, 'alt-name': 'pc'},
{ 'name':'eax' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rax[31:0]' }, {'name': 'rflags', 'set': 0, 'bitsize': 32,
{ 'name':'ebx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'ecx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[31:0]' }, {'name': 'cs', 'set': 0, 'bitsize': 32,
{ 'name':'edx' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'edi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[31:0]' }, {'name': 'ss', 'set': 0, 'bitsize': 32,
{ 'name':'esi' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'ebp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[31:0]' }, {'name': 'ds', 'set': 0, 'bitsize': 32,
{ 'name':'esp' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'r8d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[31:0]' }, {'name': 'es', 'set': 0, 'bitsize': 32,
{ 'name':'r9d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'r10d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[31:0]' }, {'name': 'fs', 'set': 0, 'bitsize': 32,
{ 'name':'r11d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'r12d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[31:0]' }, {'name': 'gs', 'set': 0, 'bitsize': 32,
{ 'name':'r13d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[31:0]' }, 'encoding': eEncodingUint, 'format': eFormatHex},
{ 'name':'r14d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[31:0]' }, {'name': 'stmm0',
{ 'name':'r15d' , 'set':0, 'bitsize':32 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[31:0]' }, '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': 'ax',
{ 'name':'bx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:0]' }, 'set': 0,
{ 'name':'cx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:0]' }, 'bitsize': 16,
{ 'name':'dx' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15:0]' }, 'encoding': eEncodingUint,
{ 'name':'di' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[15:0]' }, 'format': eFormatHex,
{ 'name':'si' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[15:0]' }, 'slice': 'rax[15:0]'},
{ 'name':'bp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[15:0]' }, {'name': 'bx',
{ 'name':'sp' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[15:0]' }, 'set': 0,
{ 'name':'r8w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[15:0]' }, 'bitsize': 16,
{ 'name':'r9w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[15:0]' }, 'encoding': eEncodingUint,
{ 'name':'r10w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[15:0]' }, 'format': eFormatHex,
{ 'name':'r11w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[15:0]' }, 'slice': 'rbx[15:0]'},
{ 'name':'r12w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[15:0]' }, {'name': 'cx',
{ 'name':'r13w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[15:0]' }, 'set': 0,
{ 'name':'r14w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[15:0]' }, 'bitsize': 16,
{ 'name':'r15w' , 'set':0, 'bitsize':16 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[15:0]' }, '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': 'ah',
{ 'name':'bh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[15:8]' }, 'set': 0,
{ 'name':'ch' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[15:8]' }, 'bitsize': 8,
{ 'name':'dh' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[15: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': 'al',
{ 'name':'bl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbx[7:0]' }, 'set': 0,
{ 'name':'cl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rcx[7:0]' }, 'bitsize': 8,
{ 'name':'dl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdx[7:0]' }, 'encoding': eEncodingUint,
{ 'name':'dil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rdi[7:0]' }, 'format': eFormatHex,
{ 'name':'sil' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsi[7:0]' }, 'slice': 'rax[7:0]'},
{ 'name':'bpl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rbp[7:0]' }, {'name': 'bl',
{ 'name':'spl' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'rsp[7:0]' }, 'set': 0,
{ 'name':'r8l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r8[7:0]' }, 'bitsize': 8,
{ 'name':'r9l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r9[7:0]' }, 'encoding': eEncodingUint,
{ 'name':'r10l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r10[7:0]' }, 'format': eFormatHex,
{ 'name':'r11l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r11[7:0]' }, 'slice': 'rbx[7:0]'},
{ 'name':'r12l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r12[7:0]' }, {'name': 'cl',
{ 'name':'r13l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r13[7:0]' }, 'set': 0,
{ 'name':'r14l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r14[7:0]' }, 'bitsize': 8,
{ 'name':'r15l' , 'set':0, 'bitsize':8 , 'encoding':eEncodingUint , 'format':eFormatHex , 'slice': 'r15[7:0]' }, '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 g_target_definition = None
def get_target_definition(): def get_target_definition():
global g_target_definition global g_target_definition
if g_target_definition == None: if g_target_definition is None:
g_target_definition = {} g_target_definition = {}
offset = 0 offset = 0
for reg_info in x86_64_register_infos: for reg_info in x86_64_register_infos:
reg_name = reg_info['name'] 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: if 'slice' not in reg_info and 'composite' not in reg_info:
reg_info['offset'] = offset reg_info['offset'] = offset
offset += reg_info['bitsize'] / 8 offset += reg_info['bitsize'] / 8
@ -346,12 +763,16 @@ def get_target_definition ():
if reg_num != LLDB_INVALID_REGNUM: if reg_num != LLDB_INVALID_REGNUM:
reg_info['gdb'] = reg_num 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['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 g_target_definition['g-packet-size'] = offset
return g_target_definition return g_target_definition
def get_dynamic_setting(target, setting_name): def get_dynamic_setting(target, setting_name):
if setting_name == 'gdb-server-target-definition': if setting_name == 'gdb-server-target-definition':
return get_target_definition() return get_target_definition()

View File

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

View File

@ -59,7 +59,7 @@ def DFS (root, word, cur_path):
# Check to see if left child is NULL # Check to see if left child is NULL
if left_child_ptr.GetValue() == None: if left_child_ptr.GetValue() is None:
return "" return ""
else: else:
cur_path = cur_path + "L" cur_path = cur_path + "L"
@ -68,7 +68,7 @@ def DFS (root, word, cur_path):
# Check to see if right child is NULL # Check to see if right child is NULL
if right_child_ptr.GetValue() == None: if right_child_ptr.GetValue() is None:
return "" return ""
else: else:
cur_path = cur_path + "R" cur_path = cur_path + "R"
@ -84,14 +84,14 @@ def tree_size (root):
the one defined in dictionary.c It uses LLDB API the one defined in dictionary.c It uses LLDB API
functions to examine and traverse the tree nodes. functions to examine and traverse the tree nodes.
""" """
if (root.GetValue == None): if (root.GetValue is None):
return 0 return 0
if (int(root.GetValue(), 16) == 0): if (int(root.GetValue(), 16) == 0):
return 0 return 0
left_size = tree_size (root.GetChildAtIndex(1)); left_size = tree_size(root.GetChildAtIndex(1))
right_size = tree_size (root.GetChildAtIndex(2)); right_size = tree_size(root.GetChildAtIndex(2))
total_size = left_size + right_size + 1 total_size = left_size + right_size + 1
return total_size return total_size
@ -107,12 +107,12 @@ def print_tree (root):
the one defined in dictionary.c It uses LLDB API the one defined in dictionary.c It uses LLDB API
functions to examine and traverse the tree nodes. functions to examine and traverse the tree nodes.
""" """
if (root.GetChildAtIndex(1).GetValue() != None) and (int (root.GetChildAtIndex(1).GetValue(), 16) != 0): if (root.GetChildAtIndex(1).GetValue() is not None) and (
int(root.GetChildAtIndex(1).GetValue(), 16) != 0):
print_tree(root.GetChildAtIndex(1)) print_tree(root.GetChildAtIndex(1))
print root.GetChildAtIndex(0).GetSummary() print root.GetChildAtIndex(0).GetSummary()
if (root.GetChildAtIndex(2).GetValue() != None) and (int (root.GetChildAtIndex(2).GetValue(), 16) != 0): if (root.GetChildAtIndex(2).GetValue() is not None) and (
int(root.GetChildAtIndex(2).GetValue(), 16) != 0):
print_tree(root.GetChildAtIndex(2)) print_tree(root.GetChildAtIndex(2))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,9 @@ import sys
import os.path import os.path
import inspect import inspect
class NopLogger: class NopLogger:
def __init__(self): def __init__(self):
pass pass
@ -18,6 +20,7 @@ class NopLogger:
class StdoutLogger: class StdoutLogger:
def __init__(self): def __init__(self):
pass pass
@ -30,7 +33,9 @@ class StdoutLogger:
def close(self): def close(self):
pass pass
class FileLogger: class FileLogger:
def __init__(self, name): def __init__(self, name):
self.file = None self.file = None
try: try:
@ -43,17 +48,17 @@ class FileLogger:
pass pass
def write(self, data): def write(self, data):
if self.file != None: if self.file is not None:
print(data, file=self.file) print(data, file=self.file)
else: else:
print(data) print(data)
def flush(self): def flush(self):
if self.file != None: if self.file is not None:
self.file.flush() self.file.flush()
def close(self): def close(self):
if self.file != None: if self.file is not None:
self.file.close() self.file.close()
self.file = None self.file = None
@ -61,8 +66,13 @@ class FileLogger:
# define lldb.formatters.Logger._lldb_formatters_debug_level to any number greater than 0 # 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 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 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: class Logger:
def __init__(self, autoflush=False, logcaller=False): def __init__(self, autoflush=False, logcaller=False):
global _lldb_formatters_debug_level global _lldb_formatters_debug_level
global _lldb_formatters_debug_filename global _lldb_formatters_debug_filename
@ -77,7 +87,8 @@ class Logger:
return return
want_file = False want_file = False
try: try:
want_file = (_lldb_formatters_debug_filename != None and _lldb_formatters_debug_filename != '' and _lldb_formatters_debug_filename != 0) want_file = (_lldb_formatters_debug_filename is not None and _lldb_formatters_debug_filename !=
'' and _lldb_formatters_debug_filename != 0)
except: except:
pass pass
if want_file: if want_file:
@ -99,10 +110,11 @@ class Logger:
def _log_caller(self): def _log_caller(self):
caller = inspect.stack()[2] caller = inspect.stack()[2]
try: try:
if caller != None and len(caller) > 3: if caller is not None and len(caller) > 3:
self.write('Logging from function ' + str(caller)) self.write('Logging from function ' + str(caller))
else: else:
self.write('Caller info not available - Required caller logging not possible') self.write(
'Caller info not available - Required caller logging not possible')
finally: finally:
del caller # needed per Python docs to avoid keeping objects alive longer than we care del caller # needed per Python docs to avoid keeping objects alive longer than we care
@ -119,4 +131,3 @@ class Logger:
def close(self): def close(self):
self.impl.close() self.impl.close()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,9 +5,13 @@ part of The LLVM Compiler Infrastructure
This file is distributed under the University of Illinois Open Source This file is distributed under the University of Illinois Open Source
License. See LICENSE.TXT for details. License. See LICENSE.TXT for details.
""" """
class AttributesDictionary: class AttributesDictionary:
def __init__(self, allow_reset=True): def __init__(self, allow_reset=True):
self.__dict__['_dictionary'] = {} # need to do it this way to prevent endless recursion # need to do it this way to prevent endless recursion
self.__dict__['_dictionary'] = {}
self.__dict__['_allow_reset'] = allow_reset self.__dict__['_allow_reset'] = allow_reset
def __getattr__(self, name): def __getattr__(self, name):

View File

@ -7,7 +7,9 @@ License. See LICENSE.TXT for details.
""" """
import lldb.formatters.metrics import lldb.formatters.metrics
class Cache: class Cache:
def __init__(self): def __init__(self):
self.data = {} self.data = {}
self.statistics = lldb.formatters.metrics.Metrics() self.statistics = lldb.formatters.metrics.Metrics()
@ -32,4 +34,3 @@ class Cache:
else: else:
self.statistics.metric_hit('miss', key) self.statistics.metric_hit('miss', key)
return default return default

View File

@ -6,10 +6,13 @@ This file is distributed under the University of Illinois Open Source
License. See LICENSE.TXT for details. License. See LICENSE.TXT for details.
""" """
import lldb import lldb
import time, datetime import time
import datetime
import inspect import inspect
class TimeMetrics: class TimeMetrics:
@staticmethod @staticmethod
def generate(label=None): def generate(label=None):
return TimeMetrics(label) return TimeMetrics(label)
@ -25,42 +28,57 @@ class TimeMetrics:
def __exit__(self, a, b, c): def __exit__(self, a, b, c):
self.exit_time = time.clock() self.exit_time = time.clock()
print("It took " + str(self.exit_time - self.enter_time) + " time units to run through " + self.function + self.label) print("It took " + str(self.exit_time - self.enter_time) +
" time units to run through " + self.function + self.label)
return False return False
class Counter: class Counter:
def __init__(self): def __init__(self):
self.count = 0 self.count = 0
self.list = [] self.list = []
def update(self, name): def update(self, name):
self.count = self.count + 1 self.count = self.count + 1
# avoid getting the full dump of this ValueObject just to save its metrics # avoid getting the full dump of this ValueObject just to save its
# metrics
if isinstance(name, lldb.SBValue): if isinstance(name, lldb.SBValue):
self.list.append(name.GetName()) self.list.append(name.GetName())
else: else:
self.list.append(str(name)) self.list.append(str(name))
def __str__(self): def __str__(self):
return str(self.count) + " times, for items [" + str(self.list) + "]" return str(self.count) + " times, for items [" + str(self.list) + "]"
class MetricsPrinter_Verbose: class MetricsPrinter_Verbose:
def __init__(self, metrics): def __init__(self, metrics):
self.metrics = metrics self.metrics = metrics
def __str__(self): def __str__(self):
string = "" string = ""
for key, value in self.metrics.metrics.items(): for key, value in self.metrics.metrics.items():
string = string + "metric " + str(key) + ": " + str(value) + "\n" string = string + "metric " + str(key) + ": " + str(value) + "\n"
return string return string
class MetricsPrinter_Compact: class MetricsPrinter_Compact:
def __init__(self, metrics): def __init__(self, metrics):
self.metrics = metrics self.metrics = metrics
def __str__(self): def __str__(self):
string = "" string = ""
for key, value in self.metrics.metrics.items(): for key, value in self.metrics.metrics.items():
string = string + "metric " + str(key) + " was hit " + str(value.count) + " times\n" string = string + "metric " + \
str(key) + " was hit " + str(value.count) + " times\n"
return string return string
class Metrics: class Metrics:
def __init__(self): def __init__(self):
self.metrics = {} self.metrics = {}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,6 @@
typedef unsigned int uint32_t; typedef unsigned int uint32_t;
enum MaskingOperator enum MaskingOperator {
{
eMaskingOperatorDefault = 0, eMaskingOperatorDefault = 0,
eMaskingOperatorAnd = 1, eMaskingOperatorAnd = 1,
eMaskingOperatorOr = 2, eMaskingOperatorOr = 2,
@ -10,26 +9,19 @@ enum MaskingOperator
eMaskingOperatorNor = 5 eMaskingOperatorNor = 5
}; };
class MaskedData class MaskedData {
{
private: private:
uint32_t value; uint32_t value;
uint32_t mask; uint32_t mask;
MaskingOperator oper; MaskingOperator oper;
public:
MaskedData( uint32_t V = 0,
uint32_t M = 0,
MaskingOperator P = eMaskingOperatorDefault) :
value(V),
mask(M),
oper(P)
{
}
uint32_t apply() public:
{ MaskedData(uint32_t V = 0, uint32_t M = 0,
switch(oper) MaskingOperator P = eMaskingOperatorDefault)
{ : value(V), mask(M), oper(P) {}
uint32_t apply() {
switch (oper) {
case eMaskingOperatorAnd: case eMaskingOperatorAnd:
return value & mask; return value & mask;
case eMaskingOperatorOr: case eMaskingOperatorOr:
@ -46,24 +38,14 @@ public:
} }
} }
void setValue(uint32_t V) void setValue(uint32_t V) { value = V; }
{
value = V;
}
void setMask (uint32_t M) void setMask(uint32_t M) { mask = M; }
{
mask = M;
}
void setOperator(MaskingOperator P) void setOperator(MaskingOperator P) { oper = P; }
{
oper = P;
}
}; };
int main() int main() {
{
MaskedData data_1(0xFF0F, 0xA01F, eMaskingOperatorAnd); MaskedData data_1(0xFF0F, 0xA01F, eMaskingOperatorAnd);
MaskedData data_2(data_1.apply(), 0x1AFC, eMaskingOperatorXor); MaskedData data_2(data_1.apply(), 0x1AFC, eMaskingOperatorXor);
MaskedData data_3(data_2.apply(), 0xFFCF, eMaskingOperatorOr); MaskedData data_3(data_2.apply(), 0xFFCF, eMaskingOperatorOr);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,13 +15,11 @@
#include <stdio.h> #include <stdio.h>
#include <vector> #include <vector>
namespace lldb { namespace lldb {
class SBBroadcaster; class SBBroadcaster;
class LLDB_API SBEvent class LLDB_API SBEvent {
{
public: public:
SBEvent(); SBEvent();
@ -36,41 +34,29 @@ public:
~SBEvent(); ~SBEvent();
const SBEvent & const SBEvent &operator=(const lldb::SBEvent &rhs);
operator = (const lldb::SBEvent &rhs);
bool bool IsValid() const;
IsValid() const;
const char * const char *GetDataFlavor();
GetDataFlavor ();
uint32_t uint32_t GetType() const;
GetType () const;
lldb::SBBroadcaster lldb::SBBroadcaster GetBroadcaster() const;
GetBroadcaster () const;
const char * const char *GetBroadcasterClass() const;
GetBroadcasterClass () const;
bool bool BroadcasterMatchesPtr(const lldb::SBBroadcaster *broadcaster);
BroadcasterMatchesPtr (const lldb::SBBroadcaster *broadcaster);
bool bool BroadcasterMatchesRef(const lldb::SBBroadcaster &broadcaster);
BroadcasterMatchesRef (const lldb::SBBroadcaster &broadcaster);
void void Clear();
Clear();
static const char * static const char *GetCStringFromEvent(const lldb::SBEvent &event);
GetCStringFromEvent (const lldb::SBEvent &event);
bool bool GetDescription(lldb::SBStream &description);
GetDescription (lldb::SBStream &description);
bool bool GetDescription(lldb::SBStream &description) const;
GetDescription (lldb::SBStream &description) const;
protected: protected:
friend class SBListener; friend class SBListener;
@ -82,20 +68,15 @@ protected:
friend class SBThread; friend class SBThread;
friend class SBWatchpoint; friend class SBWatchpoint;
lldb::EventSP & lldb::EventSP &GetSP() const;
GetSP () const;
void void reset(lldb::EventSP &event_sp);
reset (lldb::EventSP &event_sp);
void void reset(lldb_private::Event *event);
reset (lldb_private::Event* event);
lldb_private::Event * lldb_private::Event *get() const;
get () const;
private: private:
mutable lldb::EventSP m_event_sp; mutable lldb::EventSP m_event_sp;
mutable lldb_private::Event *m_opaque_ptr; mutable lldb_private::Event *m_opaque_ptr;
}; };

View File

@ -1,4 +1,5 @@
//===-- SBExecutionContext.h -----------------------------------------*- C++ -*-===// //===-- SBExecutionContext.h -----------------------------------------*- C++
//-*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -15,11 +16,9 @@
#include <stdio.h> #include <stdio.h>
#include <vector> #include <vector>
namespace lldb { namespace lldb {
class LLDB_API SBExecutionContext class LLDB_API SBExecutionContext {
{
friend class SBCommandInterpreter; friend class SBCommandInterpreter;
public: public:
@ -33,39 +32,32 @@ public:
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 & const SBExecutionContext &operator=(const lldb::SBExecutionContext &rhs);
operator = (const lldb::SBExecutionContext &rhs);
SBTarget SBTarget GetTarget() const;
GetTarget () const;
SBProcess SBProcess GetProcess() const;
GetProcess () const;
SBThread SBThread GetThread() const;
GetThread () const;
SBFrame SBFrame GetFrame() const;
GetFrame () const;
protected: protected:
ExecutionContextRefSP & ExecutionContextRefSP &GetSP() const;
GetSP () const;
void void reset(lldb::ExecutionContextRefSP &event_sp);
reset (lldb::ExecutionContextRefSP &event_sp);
lldb_private::ExecutionContextRef * lldb_private::ExecutionContextRef *get() const;
get () const;
private: private:
mutable lldb::ExecutionContextRefSP m_exe_ctx_sp; mutable lldb::ExecutionContextRefSP m_exe_ctx_sp;
}; };

View File

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

View File

@ -14,54 +14,42 @@
namespace lldb { namespace lldb {
class LLDB_API SBFileSpec class LLDB_API SBFileSpec {
{
public: 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 & const SBFileSpec &operator=(const lldb::SBFileSpec &rhs);
operator = (const lldb::SBFileSpec &rhs);
bool bool IsValid() const;
IsValid() const;
bool bool Exists() const;
Exists () const;
bool bool ResolveExecutableLocation();
ResolveExecutableLocation ();
const char * const char *GetFilename() const;
GetFilename() const;
const char * const char *GetDirectory() const;
GetDirectory() const;
void void SetFilename(const char *filename);
SetFilename(const char *filename);
void void SetDirectory(const char *directory);
SetDirectory(const char *directory);
uint32_t uint32_t GetPath(char *dst_path, size_t dst_len) const;
GetPath (char *dst_path, size_t dst_len) const;
static int static int ResolvePath(const char *src_path, char *dst_path, size_t dst_len);
ResolvePath (const char *src_path, char *dst_path, size_t dst_len);
bool bool GetDescription(lldb::SBStream &description) const;
GetDescription (lldb::SBStream &description) const;
void void AppendPathComponent(const char *file_or_directory);
AppendPathComponent (const char *file_or_directory);
private: private:
friend class SBAttachInfo; friend class SBAttachInfo;
@ -83,25 +71,19 @@ private:
SBFileSpec(const lldb_private::FileSpec &fspec); SBFileSpec(const lldb_private::FileSpec &fspec);
void void SetFileSpec(const lldb_private::FileSpec &fspec);
SetFileSpec (const lldb_private::FileSpec& fspec);
const lldb_private::FileSpec * const lldb_private::FileSpec *operator->() const;
operator->() const;
const lldb_private::FileSpec * const lldb_private::FileSpec *get() const;
get() const;
const lldb_private::FileSpec & const lldb_private::FileSpec &operator*() const;
operator*() const;
const lldb_private::FileSpec & const lldb_private::FileSpec &ref() const;
ref() const;
std::unique_ptr<lldb_private::FileSpec> m_opaque_ap; std::unique_ptr<lldb_private::FileSpec> m_opaque_ap;
}; };
} // namespace lldb } // namespace lldb
#endif // LLDB_SBFileSpec_h_ #endif // LLDB_SBFileSpec_h_

View File

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

View File

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

View File

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

View File

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

View File

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

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