diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 18:01:57 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 18:01:57 +0000 |
commit | 88c643b6fec27eec436c8d138fee6346e92337d6 (patch) | |
tree | 82cd13b2f3cde1c9e5f79689ba4e6ba67694843f /examples/python | |
parent | 94994d372d014ce4c8758b9605d63fae651bd8aa (diff) |
Notes
Diffstat (limited to 'examples/python')
34 files changed, 0 insertions, 13446 deletions
diff --git a/examples/python/bsd.py b/examples/python/bsd.py deleted file mode 100755 index 3e9528c65845..000000000000 --- a/examples/python/bsd.py +++ /dev/null @@ -1,564 +0,0 @@ -#!/usr/bin/python - -import cmd -import optparse -import os -import shlex -import struct -import sys - -ARMAG = "!<arch>\n" -SARMAG = 8 -ARFMAG = "`\n" -AR_EFMT1 = "#1/" - - -def memdump(src, bytes_per_line=16, address=0): - FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' - for x in range(256)]) - for i in range(0, len(src), bytes_per_line): - s = src[i:i+bytes_per_line] - hex_bytes = ' '.join(["%02x" % (ord(x)) for x in s]) - ascii = s.translate(FILTER) - print("%#08.8x: %-*s %s" % (address+i, bytes_per_line*3, hex_bytes, - ascii)) - - -class Object(object): - def __init__(self, file): - def read_str(file, str_len): - return file.read(str_len).rstrip('\0 ') - - def read_int(file, str_len, base): - return int(read_str(file, str_len), base) - - self.offset = file.tell() - self.file = file - self.name = read_str(file, 16) - self.date = read_int(file, 12, 10) - self.uid = read_int(file, 6, 10) - self.gid = read_int(file, 6, 10) - self.mode = read_int(file, 8, 8) - self.size = read_int(file, 10, 10) - if file.read(2) != ARFMAG: - raise ValueError('invalid BSD object at offset %#08.8x' % ( - self.offset)) - # If we have an extended name read it. Extended names start with - name_len = 0 - if self.name.startswith(AR_EFMT1): - name_len = int(self.name[len(AR_EFMT1):], 10) - self.name = read_str(file, name_len) - self.obj_offset = file.tell() - self.obj_size = self.size - name_len - file.seek(self.obj_size, 1) - - def dump(self, f=sys.stdout, flat=True): - if flat: - f.write('%#08.8x: %#08.8x %5u %5u %6o %#08.8x %s\n' % (self.offset, - self.date, self.uid, self.gid, self.mode, self.size, - self.name)) - else: - f.write('%#08.8x: \n' % self.offset) - f.write(' name = "%s"\n' % self.name) - f.write(' date = %#08.8x\n' % self.date) - f.write(' uid = %i\n' % self.uid) - f.write(' gid = %i\n' % self.gid) - f.write(' mode = %o\n' % self.mode) - f.write(' size = %#08.8x\n' % (self.size)) - self.file.seek(self.obj_offset, 0) - first_bytes = self.file.read(4) - f.write('bytes = ') - memdump(first_bytes) - - def get_bytes(self): - saved_pos = self.file.tell() - self.file.seek(self.obj_offset, 0) - bytes = self.file.read(self.obj_size) - self.file.seek(saved_pos, 0) - return bytes - - def save(self, path=None, overwrite=False): - ''' - Save the contents of the object to disk using 'path' argument as - the path, or save it to the current working directory using the - object name. - ''' - - if path is None: - path = self.name - if not overwrite and os.path.exists(path): - print('error: outfile "%s" already exists' % (path)) - return - print('Saving "%s" to "%s"...' % (self.name, path)) - with open(path, 'w') as f: - f.write(self.get_bytes()) - - -class StringTable(object): - def __init__(self, bytes): - self.bytes = bytes - - def get_string(self, offset): - length = len(self.bytes) - if offset >= length: - return None - return self.bytes[offset:self.bytes.find('\0', offset)] - - -class Archive(object): - def __init__(self, path): - self.path = path - self.file = open(path, 'r') - self.objects = [] - self.offset_to_object = {} - if self.file.read(SARMAG) != ARMAG: - print("error: file isn't a BSD archive") - while True: - try: - self.objects.append(Object(self.file)) - except ValueError: - break - - def get_object_at_offset(self, offset): - if offset in self.offset_to_object: - return self.offset_to_object[offset] - for obj in self.objects: - if obj.offset == offset: - self.offset_to_object[offset] = obj - return obj - return None - - def find(self, name, mtime=None, f=sys.stdout): - ''' - Find an object(s) by name with optional modification time. There - can be multple objects with the same name inside and possibly with - the same modification time within a BSD archive so clients must be - prepared to get multiple results. - ''' - matches = [] - for obj in self.objects: - if obj.name == name and (mtime is None or mtime == obj.date): - matches.append(obj) - return matches - - @classmethod - def dump_header(self, f=sys.stdout): - f.write(' DATE UID GID MODE SIZE NAME\n') - f.write(' ---------- ----- ----- ------ ---------- ' - '--------------\n') - - def get_symdef(self): - def get_uint32(file): - '''Extract a uint32_t from the current file position.''' - v, = struct.unpack('=I', file.read(4)) - return v - - for obj in self.objects: - symdef = [] - if obj.name.startswith("__.SYMDEF"): - self.file.seek(obj.obj_offset, 0) - ranlib_byte_size = get_uint32(self.file) - num_ranlib_structs = ranlib_byte_size/8 - str_offset_pairs = [] - for _ in range(num_ranlib_structs): - strx = get_uint32(self.file) - offset = get_uint32(self.file) - str_offset_pairs.append((strx, offset)) - strtab_len = get_uint32(self.file) - strtab = StringTable(self.file.read(strtab_len)) - for s in str_offset_pairs: - symdef.append((strtab.get_string(s[0]), s[1])) - return symdef - - def get_object_dicts(self): - ''' - Returns an array of object dictionaries that contain they following - keys: - 'object': the actual bsd.Object instance - 'symdefs': an array of symbol names that the object contains - as found in the "__.SYMDEF" item in the archive - ''' - symdefs = self.get_symdef() - symdef_dict = {} - if symdefs: - for (name, offset) in symdefs: - if offset in symdef_dict: - object_dict = symdef_dict[offset] - else: - object_dict = { - 'object': self.get_object_at_offset(offset), - 'symdefs': [] - } - symdef_dict[offset] = object_dict - object_dict['symdefs'].append(name) - object_dicts = [] - for offset in sorted(symdef_dict): - object_dicts.append(symdef_dict[offset]) - return object_dicts - - def dump(self, f=sys.stdout, flat=True): - f.write('%s:\n' % self.path) - if flat: - self.dump_header(f=f) - for obj in self.objects: - obj.dump(f=f, flat=flat) - -class Interactive(cmd.Cmd): - '''Interactive prompt for exploring contents of BSD archive files, type - "help" to see a list of supported commands.''' - image_option_parser = None - - def __init__(self, archives): - cmd.Cmd.__init__(self) - self.use_rawinput = False - self.intro = ('Interactive BSD archive prompt, type "help" to see a ' - 'list of supported commands.') - self.archives = archives - self.prompt = '% ' - - def default(self, line): - '''Catch all for unknown command, which will exit the interpreter.''' - print("unknown command: %s" % line) - return True - - def do_q(self, line): - '''Quit command''' - return True - - def do_quit(self, line): - '''Quit command''' - return True - - def do_extract(self, line): - args = shlex.split(line) - if args: - extracted = False - for object_name in args: - for archive in self.archives: - matches = archive.find(object_name) - if matches: - for object in matches: - object.save(overwrite=False) - extracted = True - if not extracted: - print('error: no object matches "%s" in any archives' % ( - object_name)) - else: - print('error: must specify the name of an object to extract') - - def do_ls(self, line): - args = shlex.split(line) - if args: - for object_name in args: - for archive in self.archives: - matches = archive.find(object_name) - if matches: - for object in matches: - object.dump(flat=False) - else: - print('error: no object matches "%s" in "%s"' % ( - object_name, archive.path)) - else: - for archive in self.archives: - archive.dump(flat=True) - print('') - - - -def main(): - parser = optparse.OptionParser( - prog='bsd', - description='Utility for BSD archives') - parser.add_option( - '--object', - type='string', - dest='object_name', - default=None, - help=('Specify the name of a object within the BSD archive to get ' - 'information on')) - parser.add_option( - '-s', '--symbol', - type='string', - dest='find_symbol', - default=None, - help=('Specify the name of a symbol within the BSD archive to get ' - 'information on from SYMDEF')) - parser.add_option( - '--symdef', - action='store_true', - dest='symdef', - default=False, - help=('Dump the information in the SYMDEF.')) - parser.add_option( - '-v', '--verbose', - action='store_true', - dest='verbose', - default=False, - help='Enable verbose output') - parser.add_option( - '-e', '--extract', - action='store_true', - dest='extract', - default=False, - help=('Specify this to extract the object specified with the --object ' - 'option. There must be only one object with a matching name or ' - 'the --mtime option must be specified to uniquely identify a ' - 'single object.')) - parser.add_option( - '-m', '--mtime', - type='int', - dest='mtime', - default=None, - help=('Specify the modification time of the object an object. This ' - 'option is used with either the --object or --extract options.')) - parser.add_option( - '-o', '--outfile', - type='string', - dest='outfile', - default=None, - help=('Specify a different name or path for the file to extract when ' - 'using the --extract option. If this option isn\'t specified, ' - 'then the extracted object file will be extracted into the ' - 'current working directory if a file doesn\'t already exist ' - 'with that name.')) - parser.add_option( - '-i', '--interactive', - action='store_true', - dest='interactive', - default=False, - help=('Enter an interactive shell that allows users to interactively ' - 'explore contents of .a files.')) - - (options, args) = parser.parse_args(sys.argv[1:]) - - if options.interactive: - archives = [] - for path in args: - archives.append(Archive(path)) - interpreter = Interactive(archives) - interpreter.cmdloop() - return - - for path in args: - archive = Archive(path) - if options.object_name: - print('%s:\n' % (path)) - matches = archive.find(options.object_name, options.mtime) - if matches: - dump_all = True - if options.extract: - if len(matches) == 1: - dump_all = False - matches[0].save(path=options.outfile, overwrite=False) - else: - print('error: multiple objects match "%s". Specify ' - 'the modification time using --mtime.' % ( - options.object_name)) - if dump_all: - for obj in matches: - obj.dump(flat=False) - else: - print('error: object "%s" not found in archive' % ( - options.object_name)) - elif options.find_symbol: - symdefs = archive.get_symdef() - if symdefs: - success = False - for (name, offset) in symdefs: - obj = archive.get_object_at_offset(offset) - if name == options.find_symbol: - print('Found "%s" in:' % (options.find_symbol)) - obj.dump(flat=False) - success = True - if not success: - print('Didn\'t find "%s" in any objects' % ( - options.find_symbol)) - else: - print("error: no __.SYMDEF was found") - elif options.symdef: - object_dicts = archive.get_object_dicts() - for object_dict in object_dicts: - object_dict['object'].dump(flat=False) - print("symbols:") - for name in object_dict['symdefs']: - print(" %s" % (name)) - else: - archive.dump(flat=not options.verbose) - - -if __name__ == '__main__': - main() - - -def print_mtime_error(result, dmap_mtime, actual_mtime): - print >>result, ("error: modification time in debug map (%#08.8x) doesn't " - "match the .o file modification time (%#08.8x)" % ( - dmap_mtime, actual_mtime)) - - -def print_file_missing_error(result, path): - print >>result, "error: file \"%s\" doesn't exist" % (path) - - -def print_multiple_object_matches(result, object_name, mtime, matches): - print >>result, ("error: multiple matches for object '%s' with with " - "modification time %#08.8x:" % (object_name, mtime)) - Archive.dump_header(f=result) - for match in matches: - match.dump(f=result, flat=True) - - -def print_archive_object_error(result, object_name, mtime, archive): - matches = archive.find(object_name, f=result) - if len(matches) > 0: - print >>result, ("error: no objects have a modification time that " - "matches %#08.8x for '%s'. Potential matches:" % ( - mtime, object_name)) - Archive.dump_header(f=result) - for match in matches: - match.dump(f=result, flat=True) - else: - print >>result, "error: no object named \"%s\" found in archive:" % ( - object_name) - Archive.dump_header(f=result) - for match in archive.objects: - match.dump(f=result, flat=True) - # archive.dump(f=result, flat=True) - - -class VerifyDebugMapCommand: - name = "verify-debug-map-objects" - - def create_options(self): - usage = "usage: %prog [options]" - description = '''This command reports any .o files that are missing -or whose modification times don't match in the debug map of an executable.''' - - self.parser = optparse.OptionParser( - description=description, - prog=self.name, - usage=usage, - add_help_option=False) - - self.parser.add_option( - '-e', '--errors', - action='store_true', - dest='errors', - default=False, - help="Only show errors") - - def get_short_help(self): - return "Verify debug map object files." - - def get_long_help(self): - return self.help_string - - def __init__(self, debugger, unused): - self.create_options() - self.help_string = self.parser.format_help() - - def __call__(self, debugger, command, exe_ctx, result): - import lldb - # Use the Shell Lexer to properly parse up command options just like a - # shell would - command_args = shlex.split(command) - - try: - (options, args) = self.parser.parse_args(command_args) - except: - result.SetError("option parsing failed") - return - - # Always get program state from the SBExecutionContext passed in - target = exe_ctx.GetTarget() - if not target.IsValid(): - result.SetError("invalid target") - return - archives = {} - for module_spec in args: - module = target.module[module_spec] - if not (module and module.IsValid()): - result.SetError('error: invalid module specification: "%s". ' - 'Specify the full path, basename, or UUID of ' - 'a module ' % (module_spec)) - return - num_symbols = module.GetNumSymbols() - num_errors = 0 - for i in range(num_symbols): - symbol = module.GetSymbolAtIndex(i) - if symbol.GetType() != lldb.eSymbolTypeObjectFile: - continue - path = symbol.GetName() - if not path: - continue - # Extract the value of the symbol by dumping the - # symbol. The value is the mod time. - dmap_mtime = int(str(symbol).split('value = ') - [1].split(',')[0], 16) - if not options.errors: - print >>result, '%s' % (path) - if os.path.exists(path): - actual_mtime = int(os.stat(path).st_mtime) - if dmap_mtime != actual_mtime: - num_errors += 1 - if options.errors: - print >>result, '%s' % (path), - print_mtime_error(result, dmap_mtime, - actual_mtime) - elif path[-1] == ')': - (archive_path, object_name) = path[0:-1].split('(') - if not archive_path and not object_name: - num_errors += 1 - if options.errors: - print >>result, '%s' % (path), - print_file_missing_error(path) - continue - if not os.path.exists(archive_path): - num_errors += 1 - if options.errors: - print >>result, '%s' % (path), - print_file_missing_error(archive_path) - continue - if archive_path in archives: - archive = archives[archive_path] - else: - archive = Archive(archive_path) - archives[archive_path] = archive - matches = archive.find(object_name, dmap_mtime) - num_matches = len(matches) - if num_matches == 1: - print >>result, '1 match' - obj = matches[0] - if obj.date != dmap_mtime: - num_errors += 1 - if options.errors: - print >>result, '%s' % (path), - print_mtime_error(result, dmap_mtime, obj.date) - elif num_matches == 0: - num_errors += 1 - if options.errors: - print >>result, '%s' % (path), - print_archive_object_error(result, object_name, - dmap_mtime, archive) - elif num_matches > 1: - num_errors += 1 - if options.errors: - print >>result, '%s' % (path), - print_multiple_object_matches(result, - object_name, - dmap_mtime, matches) - if num_errors > 0: - print >>result, "%u errors found" % (num_errors) - else: - print >>result, "No errors detected in debug map" - - -def __lldb_init_module(debugger, dict): - # This initializer is being run from LLDB in the embedded command - # interpreter. - # Add any commands contained in this module to LLDB - debugger.HandleCommand( - 'command script add -c %s.VerifyDebugMapCommand %s' % ( - __name__, VerifyDebugMapCommand.name)) - print('The "%s" command has been installed, type "help %s" for detailed ' - 'help.' % (VerifyDebugMapCommand.name, VerifyDebugMapCommand.name)) diff --git a/examples/python/cmdtemplate.py b/examples/python/cmdtemplate.py deleted file mode 100644 index 0acb04ef4715..000000000000 --- a/examples/python/cmdtemplate.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/python - -# --------------------------------------------------------------------- -# Be sure to add the python path that points to the LLDB shared library. -# -# # To use this in the embedded python interpreter using "lldb" just -# import it with the full path using the "command script import" -# command -# (lldb) command script import /path/to/cmdtemplate.py -# --------------------------------------------------------------------- - -import inspect -import lldb -import optparse -import shlex -import sys - - -class FrameStatCommand: - program = 'framestats' - - @classmethod - def register_lldb_command(cls, debugger, module_name): - parser = cls.create_options() - cls.__doc__ = parser.format_help() - # Add any commands contained in this module to LLDB - command = 'command script add -c %s.%s %s' % (module_name, - cls.__name__, - cls.program) - debugger.HandleCommand(command) - print('The "{0}" command has been installed, type "help {0}" or "{0} ' - '--help" for detailed help.'.format(cls.program)) - - @classmethod - def create_options(cls): - - usage = "usage: %prog [options]" - description = ('This command is meant to be an example of how to make ' - 'an LLDB command that does something useful, follows ' - 'best practices, and exploits the SB API. ' - 'Specifically, this command computes the aggregate ' - 'and average size of the variables in the current ' - 'frame and allows you to tweak exactly which variables ' - 'are to be accounted in the computation.') - - # Pass add_help_option = False, since this keeps the command in line - # with lldb commands, and we wire up "help command" to work by - # providing the long & short help methods below. - parser = optparse.OptionParser( - description=description, - prog=cls.program, - usage=usage, - add_help_option=False) - - parser.add_option( - '-i', - '--in-scope', - action='store_true', - dest='inscope', - help='in_scope_only = True', - default=True) - - parser.add_option( - '-a', - '--arguments', - action='store_true', - dest='arguments', - help='arguments = True', - default=True) - - parser.add_option( - '-l', - '--locals', - action='store_true', - dest='locals', - help='locals = True', - default=True) - - parser.add_option( - '-s', - '--statics', - action='store_true', - dest='statics', - help='statics = True', - default=True) - - return parser - - def get_short_help(self): - return "Example command for use in debugging" - - def get_long_help(self): - return self.help_string - - def __init__(self, debugger, unused): - self.parser = self.create_options() - self.help_string = self.parser.format_help() - - def __call__(self, debugger, command, exe_ctx, result): - # Use the Shell Lexer to properly parse up command options just like a - # shell would - command_args = shlex.split(command) - - try: - (options, args) = self.parser.parse_args(command_args) - except: - # if you don't handle exceptions, passing an incorrect argument to - # the OptionParser will cause LLDB to exit (courtesy of OptParse - # dealing with argument errors by throwing SystemExit) - result.SetError("option parsing failed") - return - - # Always get program state from the lldb.SBExecutionContext passed - # in as exe_ctx - frame = exe_ctx.GetFrame() - if not frame.IsValid(): - result.SetError("invalid frame") - return - - variables_list = frame.GetVariables( - options.arguments, - options.locals, - options.statics, - options.inscope) - variables_count = variables_list.GetSize() - if variables_count == 0: - print >> result, "no variables here" - return - total_size = 0 - for i in range(0, variables_count): - variable = variables_list.GetValueAtIndex(i) - variable_type = variable.GetType() - total_size = total_size + variable_type.GetByteSize() - average_size = float(total_size) / variables_count - print >>result, ("Your frame has %d variables. Their total size " - "is %d bytes. The average size is %f bytes") % ( - variables_count, total_size, average_size) - # not returning anything is akin to returning success - - -def __lldb_init_module(debugger, dict): - # Register all classes that have a register_lldb_command method - for _name, cls in inspect.getmembers(sys.modules[__name__]): - if inspect.isclass(cls) and callable(getattr(cls, - "register_lldb_command", - None)): - cls.register_lldb_command(debugger, __name__) diff --git a/examples/python/crashlog.py b/examples/python/crashlog.py deleted file mode 100755 index 7eb86db7ce09..000000000000 --- a/examples/python/crashlog.py +++ /dev/null @@ -1,1027 +0,0 @@ -#!/usr/bin/python - -#---------------------------------------------------------------------- -# Be sure to add the python path that points to the LLDB shared library. -# -# To use this in the embedded python interpreter using "lldb": -# -# cd /path/containing/crashlog.py -# lldb -# (lldb) script import crashlog -# "crashlog" command installed, type "crashlog --help" for detailed help -# (lldb) crashlog ~/Library/Logs/DiagnosticReports/a.crash -# -# The benefit of running the crashlog command inside lldb in the -# embedded python interpreter is when the command completes, there -# will be a target with all of the files loaded at the locations -# described in the crash log. Only the files that have stack frames -# in the backtrace will be loaded unless the "--load-all" option -# has been specified. This allows users to explore the program in the -# state it was in right at crash time. -# -# On MacOSX csh, tcsh: -# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash ) -# -# On MacOSX sh, bash: -# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash -#---------------------------------------------------------------------- - -import commands -import cmd -import datetime -import glob -import optparse -import os -import platform -import plistlib -import pprint # pp = pprint.PrettyPrinter(indent=4); pp.pprint(command_args) -import re -import shlex -import string -import sys -import time -import uuid - -try: - # Just try for LLDB in case PYTHONPATH is already correctly setup - import lldb -except ImportError: - lldb_python_dirs = list() - # lldb is not in the PYTHONPATH, try some defaults for the current platform - platform_system = platform.system() - if platform_system == 'Darwin': - # On Darwin, try the currently selected Xcode directory - xcode_dir = commands.getoutput("xcode-select --print-path") - if xcode_dir: - lldb_python_dirs.append( - os.path.realpath( - xcode_dir + - '/../SharedFrameworks/LLDB.framework/Resources/Python')) - lldb_python_dirs.append( - xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') - lldb_python_dirs.append( - '/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') - success = False - for lldb_python_dir in lldb_python_dirs: - if os.path.exists(lldb_python_dir): - if not (sys.path.__contains__(lldb_python_dir)): - sys.path.append(lldb_python_dir) - try: - import lldb - except ImportError: - pass - else: - print 'imported lldb from: "%s"' % (lldb_python_dir) - success = True - break - if not success: - print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly" - sys.exit(1) - -from lldb.utils import symbolication - -PARSE_MODE_NORMAL = 0 -PARSE_MODE_THREAD = 1 -PARSE_MODE_IMAGES = 2 -PARSE_MODE_THREGS = 3 -PARSE_MODE_SYSTEM = 4 - - -class CrashLog(symbolication.Symbolicator): - """Class that does parses darwin crash logs""" - parent_process_regex = re.compile('^Parent Process:\s*(.*)\[(\d+)\]') - thread_state_regex = re.compile('^Thread ([0-9]+) crashed with') - thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)') - app_backtrace_regex = re.compile( - '^Application Specific Backtrace ([0-9]+)([^:]*):(.*)') - frame_regex = re.compile('^([0-9]+)\s+(.+?)\s+(0x[0-9a-fA-F]{7}[0-9a-fA-F]+) +(.*)') - image_regex_uuid = re.compile( - '(0x[0-9a-fA-F]+)[-\s]+(0x[0-9a-fA-F]+)\s+[+]?(.+?)\s+(\(.+\))?\s?(<([-0-9a-fA-F]+)>)? (.*)') - empty_line_regex = re.compile('^$') - - class Thread: - """Class that represents a thread in a darwin crash log""" - - def __init__(self, index, app_specific_backtrace): - self.index = index - self.frames = list() - self.idents = list() - self.registers = dict() - self.reason = None - self.queue = None - self.app_specific_backtrace = app_specific_backtrace - - def dump(self, prefix): - if self.app_specific_backtrace: - print "%Application Specific Backtrace[%u] %s" % (prefix, self.index, self.reason) - else: - print "%sThread[%u] %s" % (prefix, self.index, self.reason) - if self.frames: - print "%s Frames:" % (prefix) - for frame in self.frames: - frame.dump(prefix + ' ') - if self.registers: - print "%s Registers:" % (prefix) - for reg in self.registers.keys(): - print "%s %-5s = %#16.16x" % (prefix, reg, self.registers[reg]) - - def dump_symbolicated(self, crash_log, options): - this_thread_crashed = self.app_specific_backtrace - if not this_thread_crashed: - this_thread_crashed = self.did_crash() - if options.crashed_only and this_thread_crashed == False: - return - - print "%s" % self - #prev_frame_index = -1 - display_frame_idx = -1 - for frame_idx, frame in enumerate(self.frames): - disassemble = ( - this_thread_crashed or options.disassemble_all_threads) and frame_idx < options.disassemble_depth - if frame_idx == 0: - symbolicated_frame_addresses = crash_log.symbolicate( - frame.pc & crash_log.addr_mask, options.verbose) - else: - # Any frame above frame zero and we have to subtract one to - # get the previous line entry - symbolicated_frame_addresses = crash_log.symbolicate( - (frame.pc & crash_log.addr_mask) - 1, options.verbose) - - if symbolicated_frame_addresses: - symbolicated_frame_address_idx = 0 - for symbolicated_frame_address in symbolicated_frame_addresses: - display_frame_idx += 1 - print '[%3u] %s' % (frame_idx, symbolicated_frame_address) - if (options.source_all or self.did_crash( - )) and display_frame_idx < options.source_frames and options.source_context: - source_context = options.source_context - line_entry = symbolicated_frame_address.get_symbol_context().line_entry - if line_entry.IsValid(): - strm = lldb.SBStream() - if line_entry: - lldb.debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers( - line_entry.file, line_entry.line, source_context, source_context, "->", strm) - source_text = strm.GetData() - if source_text: - # Indent the source a bit - indent_str = ' ' - join_str = '\n' + indent_str - print '%s%s' % (indent_str, join_str.join(source_text.split('\n'))) - if symbolicated_frame_address_idx == 0: - if disassemble: - instructions = symbolicated_frame_address.get_instructions() - if instructions: - print - symbolication.disassemble_instructions( - crash_log.get_target(), - instructions, - frame.pc, - options.disassemble_before, - options.disassemble_after, - frame.index > 0) - print - symbolicated_frame_address_idx += 1 - else: - print frame - - def add_ident(self, ident): - if ident not in self.idents: - self.idents.append(ident) - - def did_crash(self): - return self.reason is not None - - def __str__(self): - if self.app_specific_backtrace: - s = "Application Specific Backtrace[%u]" % self.index - else: - s = "Thread[%u]" % self.index - if self.reason: - s += ' %s' % self.reason - return s - - class Frame: - """Class that represents a stack frame in a thread in a darwin crash log""" - - def __init__(self, index, pc, description): - self.pc = pc - self.description = description - self.index = index - - def __str__(self): - if self.description: - return "[%3u] 0x%16.16x %s" % ( - self.index, self.pc, self.description) - else: - return "[%3u] 0x%16.16x" % (self.index, self.pc) - - def dump(self, prefix): - print "%s%s" % (prefix, str(self)) - - class DarwinImage(symbolication.Image): - """Class that represents a binary images in a darwin crash log""" - dsymForUUIDBinary = os.path.expanduser('~rc/bin/dsymForUUID') - if not os.path.exists(dsymForUUIDBinary): - dsymForUUIDBinary = commands.getoutput('which dsymForUUID') - - dwarfdump_uuid_regex = re.compile( - 'UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*') - - def __init__( - self, - text_addr_lo, - text_addr_hi, - identifier, - version, - uuid, - path): - symbolication.Image.__init__(self, path, uuid) - self.add_section( - symbolication.Section( - text_addr_lo, - text_addr_hi, - "__TEXT")) - self.identifier = identifier - self.version = version - - def find_matching_slice(self): - dwarfdump_cmd_output = commands.getoutput( - 'dwarfdump --uuid "%s"' % self.path) - self_uuid = self.get_uuid() - for line in dwarfdump_cmd_output.splitlines(): - match = self.dwarfdump_uuid_regex.search(line) - if match: - dwarf_uuid_str = match.group(1) - dwarf_uuid = uuid.UUID(dwarf_uuid_str) - if self_uuid == dwarf_uuid: - self.resolved_path = self.path - self.arch = match.group(2) - return True - if not self.resolved_path: - self.unavailable = True - print("error\n error: unable to locate '%s' with UUID %s" - % (self.path, uuid_str)) - return False - - def locate_module_and_debug_symbols(self): - # Don't load a module twice... - if self.resolved: - return True - # Mark this as resolved so we don't keep trying - self.resolved = True - uuid_str = self.get_normalized_uuid_string() - print 'Getting symbols for %s %s...' % (uuid_str, self.path), - if os.path.exists(self.dsymForUUIDBinary): - dsym_for_uuid_command = '%s %s' % ( - self.dsymForUUIDBinary, uuid_str) - s = commands.getoutput(dsym_for_uuid_command) - if s: - try: - plist_root = plistlib.readPlistFromString(s) - except: - print("Got exception: ", sys.exc_value, " handling dsymForUUID output: \n", s) - raise - if plist_root: - plist = plist_root[uuid_str] - if plist: - if 'DBGArchitecture' in plist: - self.arch = plist['DBGArchitecture'] - if 'DBGDSYMPath' in plist: - self.symfile = os.path.realpath( - plist['DBGDSYMPath']) - if 'DBGSymbolRichExecutable' in plist: - self.path = os.path.expanduser( - plist['DBGSymbolRichExecutable']) - self.resolved_path = self.path - if not self.resolved_path and os.path.exists(self.path): - if not self.find_matching_slice(): - return False - if not self.resolved_path and not os.path.exists(self.path): - try: - import subprocess - dsym = subprocess.check_output( - ["/usr/bin/mdfind", - "com_apple_xcode_dsym_uuids == %s"%uuid_str])[:-1] - if dsym and os.path.exists(dsym): - print('falling back to binary inside "%s"'%dsym) - self.symfile = dsym - dwarf_dir = os.path.join(dsym, 'Contents/Resources/DWARF') - for filename in os.listdir(dwarf_dir): - self.path = os.path.join(dwarf_dir, filename) - if not self.find_matching_slice(): - return False - break - except: - pass - if (self.resolved_path and os.path.exists(self.resolved_path)) or ( - self.path and os.path.exists(self.path)): - print 'ok' - # if self.resolved_path: - # print ' exe = "%s"' % self.resolved_path - # if self.symfile: - # print ' dsym = "%s"' % self.symfile - return True - else: - self.unavailable = True - return False - - def __init__(self, path): - """CrashLog constructor that take a path to a darwin crash log file""" - symbolication.Symbolicator.__init__(self) - self.path = os.path.expanduser(path) - self.info_lines = list() - self.system_profile = list() - self.threads = list() - self.backtraces = list() # For application specific backtraces - self.idents = list() # A list of the required identifiers for doing all stack backtraces - self.crashed_thread_idx = -1 - self.version = -1 - self.error = None - self.target = None - # With possible initial component of ~ or ~user replaced by that user's - # home directory. - try: - f = open(self.path) - except IOError: - self.error = 'error: cannot open "%s"' % self.path - return - - self.file_lines = f.read().splitlines() - parse_mode = PARSE_MODE_NORMAL - thread = None - app_specific_backtrace = False - for line in self.file_lines: - # print line - line_len = len(line) - if line_len == 0: - if thread: - if parse_mode == PARSE_MODE_THREAD: - if thread.index == self.crashed_thread_idx: - thread.reason = '' - if self.thread_exception: - thread.reason += self.thread_exception - if self.thread_exception_data: - thread.reason += " (%s)" % self.thread_exception_data - if app_specific_backtrace: - self.backtraces.append(thread) - else: - self.threads.append(thread) - thread = None - else: - # only append an extra empty line if the previous line - # in the info_lines wasn't empty - if len(self.info_lines) > 0 and len(self.info_lines[-1]): - self.info_lines.append(line) - parse_mode = PARSE_MODE_NORMAL - # print 'PARSE_MODE_NORMAL' - elif parse_mode == PARSE_MODE_NORMAL: - if line.startswith('Process:'): - (self.process_name, pid_with_brackets) = line[ - 8:].strip().split(' [') - self.process_id = pid_with_brackets.strip('[]') - elif line.startswith('Path:'): - self.process_path = line[5:].strip() - elif line.startswith('Identifier:'): - self.process_identifier = line[11:].strip() - elif line.startswith('Version:'): - version_string = line[8:].strip() - matched_pair = re.search("(.+)\((.+)\)", version_string) - if matched_pair: - self.process_version = matched_pair.group(1) - self.process_compatability_version = matched_pair.group( - 2) - else: - self.process = version_string - self.process_compatability_version = version_string - elif self.parent_process_regex.search(line): - parent_process_match = self.parent_process_regex.search( - line) - self.parent_process_name = parent_process_match.group(1) - self.parent_process_id = parent_process_match.group(2) - elif line.startswith('Exception Type:'): - self.thread_exception = line[15:].strip() - continue - elif line.startswith('Exception Codes:'): - self.thread_exception_data = line[16:].strip() - continue - elif line.startswith('Exception Subtype:'): # iOS - self.thread_exception_data = line[18:].strip() - continue - elif line.startswith('Crashed Thread:'): - self.crashed_thread_idx = int(line[15:].strip().split()[0]) - continue - elif line.startswith('Triggered by Thread:'): # iOS - self.crashed_thread_idx = int(line[20:].strip().split()[0]) - continue - elif line.startswith('Report Version:'): - self.version = int(line[15:].strip()) - continue - elif line.startswith('System Profile:'): - parse_mode = PARSE_MODE_SYSTEM - continue - elif (line.startswith('Interval Since Last Report:') or - line.startswith('Crashes Since Last Report:') or - line.startswith('Per-App Interval Since Last Report:') or - line.startswith('Per-App Crashes Since Last Report:') or - line.startswith('Sleep/Wake UUID:') or - line.startswith('Anonymous UUID:')): - # ignore these - continue - elif line.startswith('Thread'): - thread_state_match = self.thread_state_regex.search(line) - if thread_state_match: - app_specific_backtrace = False - thread_state_match = self.thread_regex.search(line) - thread_idx = int(thread_state_match.group(1)) - parse_mode = PARSE_MODE_THREGS - thread = self.threads[thread_idx] - else: - thread_match = self.thread_regex.search(line) - if thread_match: - app_specific_backtrace = False - parse_mode = PARSE_MODE_THREAD - thread_idx = int(thread_match.group(1)) - thread = CrashLog.Thread(thread_idx, False) - continue - elif line.startswith('Binary Images:'): - parse_mode = PARSE_MODE_IMAGES - continue - elif line.startswith('Application Specific Backtrace'): - app_backtrace_match = self.app_backtrace_regex.search(line) - if app_backtrace_match: - parse_mode = PARSE_MODE_THREAD - app_specific_backtrace = True - idx = int(app_backtrace_match.group(1)) - thread = CrashLog.Thread(idx, True) - elif line.startswith('Last Exception Backtrace:'): # iOS - parse_mode = PARSE_MODE_THREAD - app_specific_backtrace = True - idx = 1 - thread = CrashLog.Thread(idx, True) - self.info_lines.append(line.strip()) - elif parse_mode == PARSE_MODE_THREAD: - if line.startswith('Thread'): - continue - frame_match = self.frame_regex.search(line) - if frame_match: - ident = frame_match.group(2) - thread.add_ident(ident) - if ident not in self.idents: - self.idents.append(ident) - thread.frames.append(CrashLog.Frame(int(frame_match.group(1)), int( - frame_match.group(3), 0), frame_match.group(4))) - else: - print 'error: frame regex failed for line: "%s"' % line - elif parse_mode == PARSE_MODE_IMAGES: - image_match = self.image_regex_uuid.search(line) - if image_match: - (img_lo, img_hi, img_name, img_version, - _, img_uuid, img_path) = image_match.groups() - image = CrashLog.DarwinImage(int(img_lo, 0), int(img_hi, 0), - img_name.strip(), - img_version.strip() - if img_version else "", - uuid.UUID(img_uuid), img_path) - self.images.append(image) - else: - print "error: image regex failed for: %s" % line - - elif parse_mode == PARSE_MODE_THREGS: - stripped_line = line.strip() - # "r12: 0x00007fff6b5939c8 r13: 0x0000000007000006 r14: 0x0000000000002a03 r15: 0x0000000000000c00" - reg_values = re.findall( - '([a-zA-Z0-9]+: 0[Xx][0-9a-fA-F]+) *', stripped_line) - for reg_value in reg_values: - # print 'reg_value = "%s"' % reg_value - (reg, value) = reg_value.split(': ') - # print 'reg = "%s"' % reg - # print 'value = "%s"' % value - thread.registers[reg.strip()] = int(value, 0) - elif parse_mode == PARSE_MODE_SYSTEM: - self.system_profile.append(line) - f.close() - - def dump(self): - print "Crash Log File: %s" % (self.path) - if self.backtraces: - print "\nApplication Specific Backtraces:" - for thread in self.backtraces: - thread.dump(' ') - print "\nThreads:" - for thread in self.threads: - thread.dump(' ') - print "\nImages:" - for image in self.images: - image.dump(' ') - - def find_image_with_identifier(self, identifier): - for image in self.images: - if image.identifier == identifier: - return image - regex_text = '^.*\.%s$' % (re.escape(identifier)) - regex = re.compile(regex_text) - for image in self.images: - if regex.match(image.identifier): - return image - return None - - def create_target(self): - # print 'crashlog.create_target()...' - if self.target is None: - self.target = symbolication.Symbolicator.create_target(self) - if self.target: - return self.target - # We weren't able to open the main executable as, but we can still - # symbolicate - print 'crashlog.create_target()...2' - if self.idents: - for ident in self.idents: - image = self.find_image_with_identifier(ident) - if image: - self.target = image.create_target() - if self.target: - return self.target # success - print 'crashlog.create_target()...3' - for image in self.images: - self.target = image.create_target() - if self.target: - return self.target # success - print 'crashlog.create_target()...4' - print 'error: unable to locate any executables from the crash log' - return self.target - - def get_target(self): - return self.target - - -def usage(): - print "Usage: lldb-symbolicate.py [-n name] executable-image" - sys.exit(0) - - -class Interactive(cmd.Cmd): - '''Interactive prompt for analyzing one or more Darwin crash logs, type "help" to see a list of supported commands.''' - image_option_parser = None - - def __init__(self, crash_logs): - cmd.Cmd.__init__(self) - self.use_rawinput = False - self.intro = 'Interactive crashlogs prompt, type "help" to see a list of supported commands.' - self.crash_logs = crash_logs - self.prompt = '% ' - - def default(self, line): - '''Catch all for unknown command, which will exit the interpreter.''' - print "uknown command: %s" % line - return True - - def do_q(self, line): - '''Quit command''' - return True - - def do_quit(self, line): - '''Quit command''' - return True - - def do_symbolicate(self, line): - description = '''Symbolicate one or more darwin crash log files by index to provide source file and line information, - inlined stack frames back to the concrete functions, and disassemble the location of the crash - for the first frame of the crashed thread.''' - option_parser = CreateSymbolicateCrashLogOptions( - 'symbolicate', description, False) - command_args = shlex.split(line) - try: - (options, args) = option_parser.parse_args(command_args) - except: - return - - if args: - # We have arguments, they must valid be crash log file indexes - for idx_str in args: - idx = int(idx_str) - if idx < len(self.crash_logs): - SymbolicateCrashLog(self.crash_logs[idx], options) - else: - print 'error: crash log index %u is out of range' % (idx) - else: - # No arguments, symbolicate all crash logs using the options - # provided - for idx in range(len(self.crash_logs)): - SymbolicateCrashLog(self.crash_logs[idx], options) - - def do_list(self, line=None): - '''Dump a list of all crash logs that are currently loaded. - - USAGE: list''' - print '%u crash logs are loaded:' % len(self.crash_logs) - for (crash_log_idx, crash_log) in enumerate(self.crash_logs): - print '[%u] = %s' % (crash_log_idx, crash_log.path) - - def do_image(self, line): - '''Dump information about one or more binary images in the crash log given an image basename, or all images if no arguments are provided.''' - usage = "usage: %prog [options] <PATH> [PATH ...]" - description = '''Dump information about one or more images in all crash logs. The <PATH> can be a full path, image basename, or partial path. Searches are done in this order.''' - command_args = shlex.split(line) - if not self.image_option_parser: - self.image_option_parser = optparse.OptionParser( - description=description, prog='image', usage=usage) - self.image_option_parser.add_option( - '-a', - '--all', - action='store_true', - help='show all images', - default=False) - try: - (options, args) = self.image_option_parser.parse_args(command_args) - except: - return - - if args: - for image_path in args: - fullpath_search = image_path[0] == '/' - for (crash_log_idx, crash_log) in enumerate(self.crash_logs): - matches_found = 0 - for (image_idx, image) in enumerate(crash_log.images): - if fullpath_search: - if image.get_resolved_path() == image_path: - matches_found += 1 - print '[%u] ' % (crash_log_idx), image - else: - image_basename = image.get_resolved_path_basename() - if image_basename == image_path: - matches_found += 1 - print '[%u] ' % (crash_log_idx), image - if matches_found == 0: - for (image_idx, image) in enumerate(crash_log.images): - resolved_image_path = image.get_resolved_path() - if resolved_image_path and string.find( - image.get_resolved_path(), image_path) >= 0: - print '[%u] ' % (crash_log_idx), image - else: - for crash_log in self.crash_logs: - for (image_idx, image) in enumerate(crash_log.images): - print '[%u] %s' % (image_idx, image) - return False - - -def interactive_crashlogs(options, args): - crash_log_files = list() - for arg in args: - for resolved_path in glob.glob(arg): - crash_log_files.append(resolved_path) - - crash_logs = list() - for crash_log_file in crash_log_files: - # print 'crash_log_file = "%s"' % crash_log_file - crash_log = CrashLog(crash_log_file) - if crash_log.error: - print crash_log.error - continue - if options.debug: - crash_log.dump() - if not crash_log.images: - print 'error: no images in crash log "%s"' % (crash_log) - continue - else: - crash_logs.append(crash_log) - - interpreter = Interactive(crash_logs) - # List all crash logs that were imported - interpreter.do_list() - interpreter.cmdloop() - - -def save_crashlog(debugger, command, exe_ctx, result, dict): - usage = "usage: %prog [options] <output-path>" - description = '''Export the state of current target into a crashlog file''' - parser = optparse.OptionParser( - description=description, - prog='save_crashlog', - usage=usage) - parser.add_option( - '-v', - '--verbose', - action='store_true', - dest='verbose', - help='display verbose debug info', - default=False) - try: - (options, args) = parser.parse_args(shlex.split(command)) - except: - result.PutCString("error: invalid options") - return - if len(args) != 1: - result.PutCString( - "error: invalid arguments, a single output file is the only valid argument") - return - out_file = open(args[0], 'w') - if not out_file: - result.PutCString( - "error: failed to open file '%s' for writing...", - args[0]) - return - target = exe_ctx.target - if target: - identifier = target.executable.basename - process = exe_ctx.process - if process: - pid = process.id - if pid != lldb.LLDB_INVALID_PROCESS_ID: - out_file.write( - 'Process: %s [%u]\n' % - (identifier, pid)) - out_file.write('Path: %s\n' % (target.executable.fullpath)) - out_file.write('Identifier: %s\n' % (identifier)) - out_file.write('\nDate/Time: %s\n' % - (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) - out_file.write( - 'OS Version: Mac OS X %s (%s)\n' % - (platform.mac_ver()[0], commands.getoutput('sysctl -n kern.osversion'))) - out_file.write('Report Version: 9\n') - for thread_idx in range(process.num_threads): - thread = process.thread[thread_idx] - out_file.write('\nThread %u:\n' % (thread_idx)) - for (frame_idx, frame) in enumerate(thread.frames): - frame_pc = frame.pc - frame_offset = 0 - if frame.function: - block = frame.GetFrameBlock() - block_range = block.range[frame.addr] - if block_range: - block_start_addr = block_range[0] - frame_offset = frame_pc - block_start_addr.load_addr - else: - frame_offset = frame_pc - frame.function.addr.load_addr - elif frame.symbol: - frame_offset = frame_pc - frame.symbol.addr.load_addr - out_file.write( - '%-3u %-32s 0x%16.16x %s' % - (frame_idx, frame.module.file.basename, frame_pc, frame.name)) - if frame_offset > 0: - out_file.write(' + %u' % (frame_offset)) - line_entry = frame.line_entry - if line_entry: - if options.verbose: - # This will output the fullpath + line + column - out_file.write(' %s' % (line_entry)) - else: - out_file.write( - ' %s:%u' % - (line_entry.file.basename, line_entry.line)) - column = line_entry.column - if column: - out_file.write(':%u' % (column)) - out_file.write('\n') - - out_file.write('\nBinary Images:\n') - for module in target.modules: - text_segment = module.section['__TEXT'] - if text_segment: - text_segment_load_addr = text_segment.GetLoadAddress(target) - if text_segment_load_addr != lldb.LLDB_INVALID_ADDRESS: - text_segment_end_load_addr = text_segment_load_addr + text_segment.size - identifier = module.file.basename - module_version = '???' - module_version_array = module.GetVersion() - if module_version_array: - module_version = '.'.join( - map(str, module_version_array)) - out_file.write( - ' 0x%16.16x - 0x%16.16x %s (%s - ???) <%s> %s\n' % - (text_segment_load_addr, - text_segment_end_load_addr, - identifier, - module_version, - module.GetUUIDString(), - module.file.fullpath)) - out_file.close() - else: - result.PutCString("error: invalid target") - - -def Symbolicate(debugger, command, result, dict): - try: - SymbolicateCrashLogs(shlex.split(command)) - except: - result.PutCString("error: python exception %s" % sys.exc_info()[0]) - - -def SymbolicateCrashLog(crash_log, options): - if crash_log.error: - print crash_log.error - return - if options.debug: - crash_log.dump() - if not crash_log.images: - print 'error: no images in crash log' - return - - if options.dump_image_list: - print "Binary Images:" - for image in crash_log.images: - if options.verbose: - print image.debug_dump() - else: - print image - - target = crash_log.create_target() - if not target: - return - exe_module = target.GetModuleAtIndex(0) - images_to_load = list() - loaded_images = list() - if options.load_all_images: - # --load-all option was specified, load everything up - for image in crash_log.images: - images_to_load.append(image) - else: - # Only load the images found in stack frames for the crashed threads - if options.crashed_only: - for thread in crash_log.threads: - if thread.did_crash(): - for ident in thread.idents: - images = crash_log.find_images_with_identifier(ident) - if images: - for image in images: - images_to_load.append(image) - else: - print 'error: can\'t find image for identifier "%s"' % ident - else: - for ident in crash_log.idents: - images = crash_log.find_images_with_identifier(ident) - if images: - for image in images: - images_to_load.append(image) - else: - print 'error: can\'t find image for identifier "%s"' % ident - - for image in images_to_load: - if image not in loaded_images: - err = image.add_module(target) - if err: - print err - else: - # print 'loaded %s' % image - loaded_images.append(image) - - if crash_log.backtraces: - for thread in crash_log.backtraces: - thread.dump_symbolicated(crash_log, options) - print - - for thread in crash_log.threads: - thread.dump_symbolicated(crash_log, options) - print - - -def CreateSymbolicateCrashLogOptions( - command_name, - description, - add_interactive_options): - usage = "usage: %prog [options] <FILE> [FILE ...]" - option_parser = optparse.OptionParser( - description=description, prog='crashlog', usage=usage) - option_parser.add_option( - '--verbose', - '-v', - action='store_true', - dest='verbose', - help='display verbose debug info', - default=False) - option_parser.add_option( - '--debug', - '-g', - action='store_true', - dest='debug', - help='display verbose debug logging', - default=False) - option_parser.add_option( - '--load-all', - '-a', - action='store_true', - dest='load_all_images', - help='load all executable images, not just the images found in the crashed stack frames', - default=False) - option_parser.add_option( - '--images', - action='store_true', - dest='dump_image_list', - help='show image list', - default=False) - option_parser.add_option( - '--debug-delay', - type='int', - dest='debug_delay', - metavar='NSEC', - help='pause for NSEC seconds for debugger', - default=0) - option_parser.add_option( - '--crashed-only', - '-c', - action='store_true', - dest='crashed_only', - help='only symbolicate the crashed thread', - default=False) - option_parser.add_option( - '--disasm-depth', - '-d', - type='int', - dest='disassemble_depth', - help='set the depth in stack frames that should be disassembled (default is 1)', - default=1) - option_parser.add_option( - '--disasm-all', - '-D', - action='store_true', - dest='disassemble_all_threads', - help='enabled disassembly of frames on all threads (not just the crashed thread)', - default=False) - option_parser.add_option( - '--disasm-before', - '-B', - type='int', - dest='disassemble_before', - help='the number of instructions to disassemble before the frame PC', - default=4) - option_parser.add_option( - '--disasm-after', - '-A', - type='int', - dest='disassemble_after', - help='the number of instructions to disassemble after the frame PC', - default=4) - option_parser.add_option( - '--source-context', - '-C', - type='int', - metavar='NLINES', - dest='source_context', - help='show NLINES source lines of source context (default = 4)', - default=4) - option_parser.add_option( - '--source-frames', - type='int', - metavar='NFRAMES', - dest='source_frames', - help='show source for NFRAMES (default = 4)', - default=4) - option_parser.add_option( - '--source-all', - action='store_true', - dest='source_all', - help='show source for all threads, not just the crashed thread', - default=False) - if add_interactive_options: - option_parser.add_option( - '-i', - '--interactive', - action='store_true', - help='parse all crash logs and enter interactive mode', - default=False) - return option_parser - - -def SymbolicateCrashLogs(command_args): - description = '''Symbolicate one or more darwin crash log files to provide source file and line information, -inlined stack frames back to the concrete functions, and disassemble the location of the crash -for the first frame of the crashed thread. -If this script is imported into the LLDB command interpreter, a "crashlog" command will be added to the interpreter -for use at the LLDB command line. After a crash log has been parsed and symbolicated, a target will have been -created that has all of the shared libraries loaded at the load addresses found in the crash log file. This allows -you to explore the program as if it were stopped at the locations described in the crash log and functions can -be disassembled and lookups can be performed using the addresses found in the crash log.''' - option_parser = CreateSymbolicateCrashLogOptions( - 'crashlog', description, True) - try: - (options, args) = option_parser.parse_args(command_args) - except: - return - - if options.debug: - print 'command_args = %s' % command_args - print 'options', options - print 'args', args - - if options.debug_delay > 0: - print "Waiting %u seconds for debugger to attach..." % options.debug_delay - time.sleep(options.debug_delay) - error = lldb.SBError() - - if args: - if options.interactive: - interactive_crashlogs(options, args) - else: - for crash_log_file in args: - crash_log = CrashLog(crash_log_file) - SymbolicateCrashLog(crash_log, options) -if __name__ == '__main__': - # Create a new debugger instance - lldb.debugger = lldb.SBDebugger.Create() - SymbolicateCrashLogs(sys.argv[1:]) - lldb.SBDebugger.Destroy(lldb.debugger) -elif getattr(lldb, 'debugger', None): - lldb.debugger.HandleCommand( - 'command script add -f lldb.macosx.crashlog.Symbolicate crashlog') - lldb.debugger.HandleCommand( - 'command script add -f lldb.macosx.crashlog.save_crashlog save_crashlog') - print '"crashlog" and "save_crashlog" command installed, use the "--help" option for detailed help' diff --git a/examples/python/delta.py b/examples/python/delta.py deleted file mode 100755 index 1b192aceb9da..000000000000 --- a/examples/python/delta.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/python - -#---------------------------------------------------------------------- -# This module will enable GDB remote packet logging when the -# 'start_gdb_log' command is called with a filename to log to. When the -# 'stop_gdb_log' command is called, it will disable the logging and -# print out statistics about how long commands took to execute and also -# will primnt ou -# Be sure to add the python path that points to the LLDB shared library. -# -# To use this in the embedded python interpreter using "lldb" just -# import it with the full path using the "command script import" -# command. This can be done from the LLDB command line: -# (lldb) command script import /path/to/gdbremote.py -# Or it can be added to your ~/.lldbinit file so this module is always -# available. -#---------------------------------------------------------------------- - -import commands -import optparse -import os -import shlex -import re -import tempfile - - -def start_gdb_log(debugger, command, result, dict): - '''Start logging GDB remote packets by enabling logging with timestamps and - thread safe logging. Follow a call to this function with a call to "stop_gdb_log" - in order to dump out the commands.''' - global log_file - if log_file: - result.PutCString( - 'error: logging is already in progress with file "%s"', - log_file) - else: - args_len = len(args) - if args_len == 0: - log_file = tempfile.mktemp() - elif len(args) == 1: - log_file = args[0] - - if log_file: - debugger.HandleCommand( - 'log enable --threadsafe --timestamp --file "%s" gdb-remote packets' % - log_file) - result.PutCString( - "GDB packet logging enable with log file '%s'\nUse the 'stop_gdb_log' command to stop logging and show packet statistics." % - log_file) - return - - result.PutCString('error: invalid log file path') - result.PutCString(usage) - - -def parse_time_log(debugger, command, result, dict): - # Any commands whose names might be followed by more valid C identifier - # characters must be listed here - command_args = shlex.split(command) - parse_time_log_args(command_args) - - -def parse_time_log_args(command_args): - usage = "usage: parse_time_log [options] [<LOGFILEPATH>]" - description = '''Parse a log file that contains timestamps and convert the timestamps to delta times between log lines.''' - parser = optparse.OptionParser( - description=description, - prog='parse_time_log', - usage=usage) - parser.add_option( - '-v', - '--verbose', - action='store_true', - dest='verbose', - help='display verbose debug info', - default=False) - try: - (options, args) = parser.parse_args(command_args) - except: - return - for log_file in args: - parse_log_file(log_file, options) - - -def parse_log_file(file, options): - '''Parse a log file that was contains timestamps. These logs are typically - generated using: - (lldb) log enable --threadsafe --timestamp --file <FILE> .... - - This log file will contain timestamps and this function will then normalize - those packets to be relative to the first value timestamp that is found and - show delta times between log lines and also keep track of how long it takes - for GDB remote commands to make a send/receive round trip. This can be - handy when trying to figure out why some operation in the debugger is taking - a long time during a preset set of debugger commands.''' - - print '#----------------------------------------------------------------------' - print "# Log file: '%s'" % file - print '#----------------------------------------------------------------------' - - timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$') - - base_time = 0.0 - last_time = 0.0 - file = open(file) - lines = file.read().splitlines() - for line in lines: - match = timestamp_regex.match(line) - if match: - curr_time = float(match.group(2)) - delta = 0.0 - if base_time: - delta = curr_time - last_time - else: - base_time = curr_time - - print '%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3)) - last_time = curr_time - else: - print line - - -if __name__ == '__main__': - import sys - parse_time_log_args(sys.argv[1:]) - -else: - import lldb - if lldb.debugger: - # This initializer is being run from LLDB in the embedded command interpreter - # Add any commands contained in this module to LLDB - lldb.debugger.HandleCommand( - 'command script add -f delta.parse_time_log parse_time_log') - print 'The "parse_time_log" command is now installed and ready for use, type "parse_time_log --help" for more information' diff --git a/examples/python/diagnose_nsstring.py b/examples/python/diagnose_nsstring.py deleted file mode 100644 index 0404f714f74a..000000000000 --- a/examples/python/diagnose_nsstring.py +++ /dev/null @@ -1,183 +0,0 @@ -# This implements the "diagnose-nsstring" command, usually installed in the debug session like -# command script import lldb.diagnose -# it is used when NSString summary formatter fails to replicate the logic that went into LLDB making the -# decisions it did and providing some useful context information that can -# be used for improving the formatter - -import lldb - - -def read_memory(process, location, size): - data = "" - error = lldb.SBError() - for x in range(0, size - 1): - byte = process.ReadUnsignedFromMemory(x + location, 1, error) - if error.fail: - data = data + "err%s" % "" if x == size - 2 else ":" - else: - try: - data = data + "0x%x" % byte - if byte == 0: - data = data + "(\\0)" - elif byte == 0xa: - data = data + "(\\a)" - elif byte == 0xb: - data = data + "(\\b)" - elif byte == 0xc: - data = data + "(\\c)" - elif byte == '\n': - data = data + "(\\n)" - else: - data = data + "(%s)" % chr(byte) - if x < size - 2: - data = data + ":" - except Exception as e: - print e - return data - - -def diagnose_nsstring_Command_Impl(debugger, command, result, internal_dict): - """ - A command to diagnose the LLDB NSString data formatter - invoke as - (lldb) diagnose-nsstring <expr returning NSString> - e.g. - (lldb) diagnose-nsstring @"Hello world" - """ - target = debugger.GetSelectedTarget() - process = target.GetProcess() - thread = process.GetSelectedThread() - frame = thread.GetSelectedFrame() - if not target.IsValid() or not process.IsValid(): - return "unable to get target/process - cannot proceed" - options = lldb.SBExpressionOptions() - options.SetFetchDynamicValue() - error = lldb.SBError() - if frame.IsValid(): - nsstring = frame.EvaluateExpression(command, options) - else: - nsstring = target.EvaluateExpression(command, options) - print >>result, str(nsstring) - nsstring_address = nsstring.GetValueAsUnsigned(0) - if nsstring_address == 0: - return "unable to obtain the string - cannot proceed" - expression = "\ -struct $__lldb__notInlineMutable {\ - char* buffer;\ - signed long length;\ - signed long capacity;\ - unsigned int hasGap:1;\ - unsigned int isFixedCapacity:1;\ - unsigned int isExternalMutable:1;\ - unsigned int capacityProvidedExternally:1;\n\ -#if __LP64__\n\ - unsigned long desiredCapacity:60;\n\ -#else\n\ - unsigned long desiredCapacity:28;\n\ -#endif\n\ - void* contentsAllocator;\ -};\ -\ -struct $__lldb__CFString {\ - void* _cfisa;\ - uint8_t _cfinfo[4];\ - uint32_t _rc;\ - union {\ - struct __inline1 {\ - signed long length;\ - } inline1;\ - struct __notInlineImmutable1 {\ - char* buffer;\ - signed long length;\ - void* contentsDeallocator;\ - } notInlineImmutable1;\ - struct __notInlineImmutable2 {\ - char* buffer;\ - void* contentsDeallocator;\ - } notInlineImmutable2;\ - struct $__lldb__notInlineMutable notInlineMutable;\ - } variants;\ -};\ -" - - expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address - # print expression - dumped = target.EvaluateExpression(expression, options) - print >>result, str(dumped) - - little_endian = (target.byte_order == lldb.eByteOrderLittle) - ptr_size = target.addr_size - - info_bits = dumped.GetChildMemberWithName("_cfinfo").GetChildAtIndex( - 0 if little_endian else 3).GetValueAsUnsigned(0) - is_mutable = (info_bits & 1) == 1 - is_inline = (info_bits & 0x60) == 0 - has_explicit_length = (info_bits & (1 | 4)) != 4 - is_unicode = (info_bits & 0x10) == 0x10 - is_special = ( - nsstring.GetDynamicValue( - lldb.eDynamicCanRunTarget).GetTypeName() == "NSPathStore2") - has_null = (info_bits & 8) == 8 - - print >>result, "\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n" % \ - (info_bits, "yes" if is_mutable else "no", "yes" if is_inline else "no", "yes" if has_explicit_length else "no", "yes" if is_unicode else "no", "yes" if is_special else "no", "yes" if has_null else "no") - - explicit_length_offset = 0 - if not has_null and has_explicit_length and not is_special: - explicit_length_offset = 2 * ptr_size - if is_mutable and not is_inline: - explicit_length_offset = explicit_length_offset + ptr_size - elif is_inline: - pass - elif not is_inline and not is_mutable: - explicit_length_offset = explicit_length_offset + ptr_size - else: - explicit_length_offset = 0 - - if explicit_length_offset == 0: - print >>result, "There is no explicit length marker - skipping this step\n" - else: - explicit_length_offset = nsstring_address + explicit_length_offset - explicit_length = process.ReadUnsignedFromMemory( - explicit_length_offset, 4, error) - print >>result, "Explicit length location is at 0x%x - read value is %d\n" % ( - explicit_length_offset, explicit_length) - - if is_mutable: - location = 2 * ptr_size + nsstring_address - location = process.ReadPointerFromMemory(location, error) - elif is_inline and has_explicit_length and not is_unicode and not is_special and not is_mutable: - location = 3 * ptr_size + nsstring_address - elif is_unicode: - location = 2 * ptr_size + nsstring_address - if is_inline: - if not has_explicit_length: - print >>result, "Unicode & Inline & !Explicit is a new combo - no formula for it" - else: - location += ptr_size - else: - location = process.ReadPointerFromMemory(location, error) - elif is_special: - location = nsstring_address + ptr_size + 4 - elif is_inline: - location = 2 * ptr_size + nsstring_address - if not has_explicit_length: - location += 1 - else: - location = 2 * ptr_size + nsstring_address - location = process.ReadPointerFromMemory(location, error) - print >>result, "Expected data location: 0x%x\n" % (location) - print >>result, "1K of data around location: %s\n" % read_memory( - process, location, 1024) - print >>result, "5K of data around string pointer: %s\n" % read_memory( - process, nsstring_address, 1024 * 5) - - -def __lldb_init_module(debugger, internal_dict): - debugger.HandleCommand( - "command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" % - __name__) - print 'The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.' - -__lldb_init_module(lldb.debugger, None) -__lldb_init_module = None diff --git a/examples/python/diagnose_unwind.py b/examples/python/diagnose_unwind.py deleted file mode 100644 index b90372970e5d..000000000000 --- a/examples/python/diagnose_unwind.py +++ /dev/null @@ -1,313 +0,0 @@ -# This implements the "diagnose-unwind" command, usually installed -# in the debug session like -# command script import lldb.diagnose -# it is used when lldb's backtrace fails -- it collects and prints -# information about the stack frames, and tries an alternate unwind -# algorithm, that will help to understand why lldb's unwind algorithm -# did not succeed. - -import optparse -import lldb -import re -import shlex - -# Print the frame number, pc, frame pointer, module UUID and function name -# Returns the SBModule that contains the PC, if it could be found - - -def backtrace_print_frame(target, frame_num, addr, fp): - process = target.GetProcess() - addr_for_printing = addr - addr_width = process.GetAddressByteSize() * 2 - if frame_num > 0: - addr = addr - 1 - - sbaddr = lldb.SBAddress() - try: - sbaddr.SetLoadAddress(addr, target) - module_description = "" - if sbaddr.GetModule(): - module_filename = "" - module_uuid_str = sbaddr.GetModule().GetUUIDString() - if module_uuid_str is None: - module_uuid_str = "" - if sbaddr.GetModule().GetFileSpec(): - module_filename = sbaddr.GetModule().GetFileSpec().GetFilename() - if module_filename is None: - module_filename = "" - if module_uuid_str != "" or module_filename != "": - module_description = '%s %s' % ( - module_filename, module_uuid_str) - except Exception: - print '%2d: pc==0x%-*x fp==0x%-*x' % (frame_num, addr_width, addr_for_printing, addr_width, fp) - return - - sym_ctx = target.ResolveSymbolContextForAddress( - sbaddr, lldb.eSymbolContextEverything) - if sym_ctx.IsValid() and sym_ctx.GetSymbol().IsValid(): - function_start = sym_ctx.GetSymbol().GetStartAddress().GetLoadAddress(target) - offset = addr - function_start - print '%2d: pc==0x%-*x fp==0x%-*x %s %s + %d' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description, sym_ctx.GetSymbol().GetName(), offset) - else: - print '%2d: pc==0x%-*x fp==0x%-*x %s' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description) - return sbaddr.GetModule() - -# A simple stack walk algorithm that follows the frame chain. -# Returns a two-element list; the first element is a list of modules -# seen and the second element is a list of addresses seen during the backtrace. - - -def simple_backtrace(debugger): - target = debugger.GetSelectedTarget() - process = target.GetProcess() - cur_thread = process.GetSelectedThread() - - initial_fp = cur_thread.GetFrameAtIndex(0).GetFP() - - # If the pseudoreg "fp" isn't recognized, on arm hardcode to r7 which is - # correct for Darwin programs. - if initial_fp == lldb.LLDB_INVALID_ADDRESS and target.triple[0:3] == "arm": - for reggroup in cur_thread.GetFrameAtIndex(1).registers: - if reggroup.GetName() == "General Purpose Registers": - for reg in reggroup: - if reg.GetName() == "r7": - initial_fp = int(reg.GetValue(), 16) - - module_list = [] - address_list = [cur_thread.GetFrameAtIndex(0).GetPC()] - this_module = backtrace_print_frame( - target, 0, cur_thread.GetFrameAtIndex(0).GetPC(), initial_fp) - print_stack_frame(process, initial_fp) - print "" - if this_module is not None: - module_list.append(this_module) - if cur_thread.GetNumFrames() < 2: - return [module_list, address_list] - - cur_fp = process.ReadPointerFromMemory(initial_fp, lldb.SBError()) - cur_pc = process.ReadPointerFromMemory( - initial_fp + process.GetAddressByteSize(), lldb.SBError()) - - frame_num = 1 - - while cur_pc != 0 and cur_fp != 0 and cur_pc != lldb.LLDB_INVALID_ADDRESS and cur_fp != lldb.LLDB_INVALID_ADDRESS: - address_list.append(cur_pc) - this_module = backtrace_print_frame(target, frame_num, cur_pc, cur_fp) - print_stack_frame(process, cur_fp) - print "" - if this_module is not None: - module_list.append(this_module) - frame_num = frame_num + 1 - next_pc = 0 - next_fp = 0 - if target.triple[ - 0:6] == "x86_64" or target.triple[ - 0:4] == "i386" or target.triple[ - 0:3] == "arm": - error = lldb.SBError() - next_pc = process.ReadPointerFromMemory( - cur_fp + process.GetAddressByteSize(), error) - if not error.Success(): - next_pc = 0 - next_fp = process.ReadPointerFromMemory(cur_fp, error) - if not error.Success(): - next_fp = 0 - # Clear the 0th bit for arm frames - this indicates it is a thumb frame - if target.triple[0:3] == "arm" and (next_pc & 1) == 1: - next_pc = next_pc & ~1 - cur_pc = next_pc - cur_fp = next_fp - this_module = backtrace_print_frame(target, frame_num, cur_pc, cur_fp) - print_stack_frame(process, cur_fp) - print "" - if this_module is not None: - module_list.append(this_module) - return [module_list, address_list] - - -def print_stack_frame(process, fp): - if fp == 0 or fp == lldb.LLDB_INVALID_ADDRESS or fp == 1: - return - addr_size = process.GetAddressByteSize() - addr = fp - (2 * addr_size) - i = 0 - outline = "Stack frame from $fp-%d: " % (2 * addr_size) - error = lldb.SBError() - try: - while i < 5 and error.Success(): - address = process.ReadPointerFromMemory( - addr + (i * addr_size), error) - outline += " 0x%x" % address - i += 1 - print outline - except Exception: - return - - -def diagnose_unwind(debugger, command, result, dict): - """ - Gather diagnostic information to help debug incorrect unwind (backtrace) - behavior in lldb. When there is a backtrace that doesn't look - correct, run this command with the correct thread selected and a - large amount of diagnostic information will be printed, it is likely - to be helpful when reporting the problem. - """ - - command_args = shlex.split(command) - parser = create_diagnose_unwind_options() - try: - (options, args) = parser.parse_args(command_args) - except: - return - target = debugger.GetSelectedTarget() - if target: - process = target.GetProcess() - if process: - thread = process.GetSelectedThread() - if thread: - lldb_versions_match = re.search( - r'[lL][lL][dD][bB]-(\d+)([.](\d+))?([.](\d+))?', - debugger.GetVersionString()) - lldb_version = 0 - lldb_minor = 0 - if len(lldb_versions_match.groups() - ) >= 1 and lldb_versions_match.groups()[0]: - lldb_major = int(lldb_versions_match.groups()[0]) - if len(lldb_versions_match.groups() - ) >= 5 and lldb_versions_match.groups()[4]: - lldb_minor = int(lldb_versions_match.groups()[4]) - - modules_seen = [] - addresses_seen = [] - - print 'LLDB version %s' % debugger.GetVersionString() - print 'Unwind diagnostics for thread %d' % thread.GetIndexID() - print "" - print "=============================================================================================" - print "" - print "OS plugin setting:" - debugger.HandleCommand( - "settings show target.process.python-os-plugin-path") - print "" - print "Live register context:" - thread.SetSelectedFrame(0) - debugger.HandleCommand("register read") - print "" - print "=============================================================================================" - print "" - print "lldb's unwind algorithm:" - print "" - frame_num = 0 - for frame in thread.frames: - if not frame.IsInlined(): - this_module = backtrace_print_frame( - target, frame_num, frame.GetPC(), frame.GetFP()) - print_stack_frame(process, frame.GetFP()) - print "" - if this_module is not None: - modules_seen.append(this_module) - addresses_seen.append(frame.GetPC()) - frame_num = frame_num + 1 - print "" - print "=============================================================================================" - print "" - print "Simple stack walk algorithm:" - print "" - (module_list, address_list) = simple_backtrace(debugger) - if module_list and module_list is not None: - modules_seen += module_list - if address_list and address_list is not None: - addresses_seen = set(addresses_seen) - addresses_seen.update(set(address_list)) - - print "" - print "=============================================================================================" - print "" - print "Modules seen in stack walks:" - print "" - modules_already_seen = set() - for module in modules_seen: - if module is not None and module.GetFileSpec().GetFilename() is not None: - if not module.GetFileSpec().GetFilename() in modules_already_seen: - debugger.HandleCommand( - 'image list %s' % - module.GetFileSpec().GetFilename()) - modules_already_seen.add( - module.GetFileSpec().GetFilename()) - - print "" - print "=============================================================================================" - print "" - print "Disassembly ofaddresses seen in stack walks:" - print "" - additional_addresses_to_disassemble = addresses_seen - for frame in thread.frames: - if not frame.IsInlined(): - print "--------------------------------------------------------------------------------------" - print "" - print "Disassembly of %s, frame %d, address 0x%x" % (frame.GetFunctionName(), frame.GetFrameID(), frame.GetPC()) - print "" - if target.triple[ - 0:6] == "x86_64" or target.triple[ - 0:4] == "i386": - debugger.HandleCommand( - 'disassemble -F att -a 0x%x' % frame.GetPC()) - else: - debugger.HandleCommand( - 'disassemble -a 0x%x' % - frame.GetPC()) - if frame.GetPC() in additional_addresses_to_disassemble: - additional_addresses_to_disassemble.remove( - frame.GetPC()) - - for address in list(additional_addresses_to_disassemble): - print "--------------------------------------------------------------------------------------" - print "" - print "Disassembly of 0x%x" % address - print "" - if target.triple[ - 0:6] == "x86_64" or target.triple[ - 0:4] == "i386": - debugger.HandleCommand( - 'disassemble -F att -a 0x%x' % address) - else: - debugger.HandleCommand('disassemble -a 0x%x' % address) - - print "" - print "=============================================================================================" - print "" - additional_addresses_to_show_unwind = addresses_seen - for frame in thread.frames: - if not frame.IsInlined(): - print "--------------------------------------------------------------------------------------" - print "" - print "Unwind instructions for %s, frame %d" % (frame.GetFunctionName(), frame.GetFrameID()) - print "" - debugger.HandleCommand( - 'image show-unwind -a "0x%x"' % frame.GetPC()) - if frame.GetPC() in additional_addresses_to_show_unwind: - additional_addresses_to_show_unwind.remove( - frame.GetPC()) - - for address in list(additional_addresses_to_show_unwind): - print "--------------------------------------------------------------------------------------" - print "" - print "Unwind instructions for 0x%x" % address - print "" - debugger.HandleCommand( - 'image show-unwind -a "0x%x"' % address) - - -def create_diagnose_unwind_options(): - usage = "usage: %prog" - description = '''Print diagnostic information about a thread backtrace which will help to debug unwind problems''' - parser = optparse.OptionParser( - description=description, - prog='diagnose_unwind', - usage=usage) - return parser - -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.' diff --git a/examples/python/dict_utils.py b/examples/python/dict_utils.py deleted file mode 100755 index 7cdd0ac6f3c2..000000000000 --- a/examples/python/dict_utils.py +++ /dev/null @@ -1,62 +0,0 @@ - -class LookupDictionary(dict): - """ - a dictionary which can lookup value by key, or keys by value - """ - - def __init__(self, items=[]): - """items can be a list of pair_lists or a dictionary""" - dict.__init__(self, items) - - def get_keys_for_value(self, value, fail_value=None): - """find the key(s) as a list given a value""" - list_result = [item[0] for item in self.items() if item[1] == value] - if len(list_result) > 0: - return list_result - return fail_value - - def get_first_key_for_value(self, value, fail_value=None): - """return the first key of this dictionary given the value""" - list_result = [item[0] for item in self.items() if item[1] == value] - if len(list_result) > 0: - return list_result[0] - return fail_value - - def get_value(self, key, fail_value=None): - """find the value given a key""" - if key in self: - return self[key] - return fail_value - - -class Enum(LookupDictionary): - - def __init__(self, initial_value=0, items=[]): - """items can be a list of pair_lists or a dictionary""" - LookupDictionary.__init__(self, items) - self.value = initial_value - - def set_value(self, v): - v_typename = typeof(v).__name__ - if v_typename == 'str': - if str in self: - v = self[v] - else: - v = 0 - else: - self.value = v - - def get_enum_value(self): - return self.value - - def get_enum_name(self): - return self.__str__() - - def __str__(self): - s = self.get_first_key_for_value(self.value, None) - if s is None: - s = "%#8.8x" % self.value - return s - - def __repr__(self): - return self.__str__() diff --git a/examples/python/disasm-stress-test.py b/examples/python/disasm-stress-test.py deleted file mode 100755 index 2c20ffb92369..000000000000 --- a/examples/python/disasm-stress-test.py +++ /dev/null @@ -1,230 +0,0 @@ -#!/usr/bin/python - -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.add_argument( - '--arch', - required=True, - action='store', - help='The architecture whose disassembler is to be tested') -parser.add_argument( - '--bytes', - required=True, - action='store', - type=int, - help='The byte width of instructions for that architecture') -parser.add_argument( - '--random', - required=False, - action='store_true', - help='Enables non-sequential testing') -parser.add_argument( - '--start', - required=False, - action='store', - type=int, - help='The first instruction value to test') -parser.add_argument( - '--skip', - required=False, - action='store', - type=int, - help='The interval between instructions to test') -parser.add_argument( - '--log', - required=False, - action='store', - help='A log file to write the most recent instruction being tested') -parser.add_argument( - '--time', - required=False, - action='store_true', - help='Every 100,000 instructions, print an ETA to standard out') -parser.add_argument( - '--lldb', - required=False, - action='store', - help='The path to LLDB.framework, if LLDB should be overridden') - -arguments = sys.argv[1:] - -arg_ns = parser.parse_args(arguments) - - -def AddLLDBToSysPathOnMacOSX(): - def GetLLDBFrameworkPath(): - lldb_path = subprocess.check_output(["xcrun", "-find", "lldb"]) - re_result = re.match("(.*)/Developer/usr/bin/lldb", lldb_path) - if re_result is None: - return None - xcode_contents_path = re_result.group(1) - return xcode_contents_path + "/SharedFrameworks/LLDB.framework" - - lldb_framework_path = GetLLDBFrameworkPath() - - if lldb_framework_path is None: - print "Couldn't find LLDB.framework" - sys.exit(-1) - - sys.path.append(lldb_framework_path + "/Resources/Python") - -if arg_ns.lldb is None: - AddLLDBToSysPathOnMacOSX() -else: - sys.path.append(arg_ns.lldb + "/Resources/Python") - -import lldb - -debugger = lldb.SBDebugger.Create() - -if debugger.IsValid() == False: - print "Couldn't create an SBDebugger" - sys.exit(-1) - -target = debugger.CreateTargetWithFileAndArch(None, arg_ns.arch) - -if target.IsValid() == False: - print "Couldn't create an SBTarget for architecture " + arg_ns.arch - sys.exit(-1) - - -def ResetLogFile(log_file): - if log_file != sys.stdout: - log_file.seek(0) - - -def PrintByteArray(log_file, byte_array): - for byte in byte_array: - print >>log_file, hex(byte) + " ", - print >>log_file - - -class SequentialInstructionProvider: - - def __init__(self, byte_width, log_file, start=0, skip=1): - self.m_byte_width = byte_width - self.m_log_file = log_file - self.m_start = start - self.m_skip = skip - self.m_value = start - self.m_last = (1 << (byte_width * 8)) - 1 - - def PrintCurrentState(self, ret): - ResetLogFile(self.m_log_file) - print >>self.m_log_file, self.m_value - PrintByteArray(self.m_log_file, ret) - - def GetNextInstruction(self): - if self.m_value > self.m_last: - return None - ret = bytearray(self.m_byte_width) - for i in range(self.m_byte_width): - ret[self.m_byte_width - (i + 1)] = (self.m_value >> (i * 8)) & 255 - self.PrintCurrentState(ret) - self.m_value += self.m_skip - return ret - - def GetNumInstructions(self): - return (self.m_last - self.m_start) / self.m_skip - - def __iter__(self): - return self - - def next(self): - ret = self.GetNextInstruction() - if ret is None: - raise StopIteration - return ret - - -class RandomInstructionProvider: - - def __init__(self, byte_width, log_file): - self.m_byte_width = byte_width - self.m_log_file = log_file - self.m_random_file = open("/dev/random", 'r') - - def PrintCurrentState(self, ret): - ResetLogFile(self.m_log_file) - PrintByteArray(self.m_log_file, ret) - - def GetNextInstruction(self): - ret = bytearray(self.m_byte_width) - for i in range(self.m_byte_width): - ret[i] = self.m_random_file.read(1) - self.PrintCurrentState(ret) - return ret - - def __iter__(self): - return self - - def next(self): - ret = self.GetNextInstruction() - if ret is None: - raise StopIteration - return ret - -log_file = None - - -def GetProviderWithArguments(args): - global log_file - if args.log is not None: - log_file = open(args.log, 'w') - else: - log_file = sys.stdout - instruction_provider = None - if args.random: - instruction_provider = RandomInstructionProvider(args.bytes, log_file) - else: - start = 0 - skip = 1 - if args.start is not None: - start = args.start - if args.skip is not None: - skip = args.skip - instruction_provider = SequentialInstructionProvider( - args.bytes, log_file, start, skip) - return instruction_provider - -instruction_provider = GetProviderWithArguments(arg_ns) - -fake_address = lldb.SBAddress() - -actually_time = arg_ns.time and not arg_ns.random - -if actually_time: - num_instructions_logged = 0 - total_num_instructions = instruction_provider.GetNumInstructions() - start_time = time.time() - -for inst_bytes in instruction_provider: - if actually_time: - if (num_instructions_logged != 0) and ( - num_instructions_logged % 100000 == 0): - curr_time = time.time() - elapsed_time = curr_time - start_time - remaining_time = float( - total_num_instructions - num_instructions_logged) * ( - float(elapsed_time) / float(num_instructions_logged)) - print str(datetime.timedelta(seconds=remaining_time)) - num_instructions_logged = num_instructions_logged + 1 - inst_list = target.GetInstructions(fake_address, inst_bytes) - if not inst_list.IsValid(): - print >>log_file, "Invalid instruction list" - continue - inst = inst_list.GetInstructionAtIndex(0) - if not inst.IsValid(): - print >>log_file, "Invalid instruction" - continue - instr_output_stream = lldb.SBStream() - inst.GetDescription(instr_output_stream) - print >>log_file, instr_output_stream.GetData() diff --git a/examples/python/disasm.py b/examples/python/disasm.py deleted file mode 100755 index af024a6887da..000000000000 --- a/examples/python/disasm.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/python - -#---------------------------------------------------------------------- -# Be sure to add the python path that points to the LLDB shared library. -# On MacOSX csh, tcsh: -# setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python -# On MacOSX sh, bash: -# export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python -#---------------------------------------------------------------------- - -import lldb -import os -import sys - - -def disassemble_instructions(insts): - for i in insts: - print i - - -def usage(): - print "Usage: disasm.py [-n name] executable-image" - print " By default, it breaks at and disassembles the 'main' function." - sys.exit(0) - -if len(sys.argv) == 2: - fname = 'main' - exe = sys.argv[1] -elif len(sys.argv) == 4: - if sys.argv[1] != '-n': - usage() - else: - fname = sys.argv[2] - exe = sys.argv[3] -else: - usage() - -# Create a new debugger instance -debugger = lldb.SBDebugger.Create() - -# When we step or continue, don't return from the function until the process -# stops. We do this by setting the async mode to false. -debugger.SetAsync(False) - -# Create a target from a file and arch -print "Creating a target for '%s'" % exe - -target = debugger.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT) - -if target: - # If the target is valid set a breakpoint at main - main_bp = target.BreakpointCreateByName( - fname, target.GetExecutable().GetFilename()) - - print main_bp - - # Launch the process. Since we specified synchronous mode, we won't return - # from this function until we hit the breakpoint at main - process = target.LaunchSimple(None, None, os.getcwd()) - - # Make sure the launch went ok - if process: - # Print some simple process info - state = process.GetState() - print process - if state == lldb.eStateStopped: - # Get the first thread - thread = process.GetThreadAtIndex(0) - if thread: - # Print some simple thread info - print thread - # Get the first frame - frame = thread.GetFrameAtIndex(0) - if frame: - # Print some simple frame info - print frame - function = frame.GetFunction() - # See if we have debug info (a function) - if function: - # We do have a function, print some info for the - # function - print function - # Now get all instructions for this function and print - # them - insts = function.GetInstructions(target) - disassemble_instructions(insts) - else: - # See if we have a symbol in the symbol table for where - # we stopped - symbol = frame.GetSymbol() - if symbol: - # We do have a symbol, print some info for the - # symbol - print symbol - # Now get all instructions for this symbol and - # print them - insts = symbol.GetInstructions(target) - disassemble_instructions(insts) - - registerList = frame.GetRegisters() - print "Frame registers (size of register set = %d):" % registerList.GetSize() - for value in registerList: - # print value - print "%s (number of children = %d):" % (value.GetName(), value.GetNumChildren()) - for child in value: - print "Name: ", child.GetName(), " Value: ", child.GetValue() - - print "Hit the breakpoint at main, enter to continue and wait for program to exit or 'Ctrl-D'/'quit' to terminate the program" - next = sys.stdin.readline() - if not next or next.rstrip('\n') == 'quit': - print "Terminating the inferior process..." - process.Kill() - else: - # Now continue to the program exit - process.Continue() - # When we return from the above function we will hopefully be at the - # program exit. Print out some process info - print process - elif state == lldb.eStateExited: - print "Didn't hit the breakpoint at main, program has exited..." - else: - print "Unexpected process state: %s, killing process..." % debugger.StateAsCString(state) - process.Kill() - - -lldb.SBDebugger.Terminate() diff --git a/examples/python/disassembly_mode.py b/examples/python/disassembly_mode.py deleted file mode 100644 index 19647cc6555e..000000000000 --- a/examples/python/disassembly_mode.py +++ /dev/null @@ -1,48 +0,0 @@ -""" Adds the 'toggle-disassembly' command to switch you into a disassembly only mode """ -import lldb - -class DisassemblyMode: - def __init__(self, debugger, unused): - self.dbg = debugger - self.interp = debugger.GetCommandInterpreter() - self.store_state() - self.mode_off = True - - def store_state(self): - self.dis_count = self.get_string_value("stop-disassembly-count") - self.dis_display = self.get_string_value("stop-disassembly-display") - self.before_count = self.get_string_value("stop-line-count-before") - self.after_count = self.get_string_value("stop-line-count-after") - - def get_string_value(self, setting): - result = lldb.SBCommandReturnObject() - self.interp.HandleCommand("settings show " + setting, result) - value = result.GetOutput().split(" = ")[1].rstrip("\n") - return value - - def set_value(self, setting, value): - result = lldb.SBCommandReturnObject() - self.interp.HandleCommand("settings set " + setting + " " + value, result) - - def __call__(self, debugger, command, exe_ctx, result): - if self.mode_off: - self.mode_off = False - self.store_state() - self.set_value("stop-disassembly-display","always") - self.set_value("stop-disassembly-count", "8") - self.set_value("stop-line-count-before", "0") - self.set_value("stop-line-count-after", "0") - result.AppendMessage("Disassembly mode on.") - else: - self.mode_off = True - self.set_value("stop-disassembly-display",self.dis_display) - self.set_value("stop-disassembly-count", self.dis_count) - self.set_value("stop-line-count-before", self.before_count) - self.set_value("stop-line-count-after", self.after_count) - result.AppendMessage("Disassembly mode off.") - - def get_short_help(self): - return "Toggles between a disassembly only mode and normal source mode\n" - -def __lldb_init_module(debugger, unused): - debugger.HandleCommand("command script add -c disassembly_mode.DisassemblyMode toggle-disassembly") diff --git a/examples/python/file_extract.py b/examples/python/file_extract.py deleted file mode 100755 index 7a617e911068..000000000000 --- a/examples/python/file_extract.py +++ /dev/null @@ -1,226 +0,0 @@ -#! /usr/bin/env python - -import string -import struct -import sys - - -class FileExtract: - '''Decode binary data from a file''' - - def __init__(self, f, b='='): - '''Initialize with an open binary file and optional byte order''' - - self.file = f - self.byte_order = b - self.offsets = list() - - def set_byte_order(self, b): - '''Set the byte order, valid values are "big", "little", "swap", "native", "<", ">", "@", "="''' - if b == 'big': - self.byte_order = '>' - elif b == 'little': - self.byte_order = '<' - elif b == 'swap': - # swap what ever the current byte order is - self.byte_order = swap_unpack_char() - elif b == 'native': - self.byte_order = '=' - elif b == '<' or b == '>' or b == '@' or b == '=': - self.byte_order = b - else: - print "error: invalid byte order specified: '%s'" % b - - def is_in_memory(self): - return False - - def seek(self, offset, whence=0): - if self.file: - return self.file.seek(offset, whence) - raise ValueError - - def tell(self): - if self.file: - return self.file.tell() - raise ValueError - - def read_size(self, byte_size): - s = self.file.read(byte_size) - if len(s) != byte_size: - return None - return s - - def push_offset_and_seek(self, offset): - '''Push the current file offset and seek to "offset"''' - self.offsets.append(self.file.tell()) - self.file.seek(offset, 0) - - def pop_offset_and_seek(self): - '''Pop a previously pushed file offset, or do nothing if there were no previously pushed offsets''' - if len(self.offsets) > 0: - self.file.seek(self.offsets.pop()) - - def get_sint8(self, fail_value=0): - '''Extract a single int8_t from the binary file at the current file position, returns a single integer''' - s = self.read_size(1) - if s: - v, = struct.unpack(self.byte_order + 'b', s) - return v - else: - return fail_value - - def get_uint8(self, fail_value=0): - '''Extract a single uint8_t from the binary file at the current file position, returns a single integer''' - s = self.read_size(1) - if s: - v, = struct.unpack(self.byte_order + 'B', s) - return v - else: - return fail_value - - def get_sint16(self, fail_value=0): - '''Extract a single int16_t from the binary file at the current file position, returns a single integer''' - s = self.read_size(2) - if s: - v, = struct.unpack(self.byte_order + 'h', s) - return v - else: - return fail_value - - def get_uint16(self, fail_value=0): - '''Extract a single uint16_t from the binary file at the current file position, returns a single integer''' - s = self.read_size(2) - if s: - v, = struct.unpack(self.byte_order + 'H', s) - return v - else: - return fail_value - - def get_sint32(self, fail_value=0): - '''Extract a single int32_t from the binary file at the current file position, returns a single integer''' - s = self.read_size(4) - if s: - v, = struct.unpack(self.byte_order + 'i', s) - return v - else: - return fail_value - - def get_uint32(self, fail_value=0): - '''Extract a single uint32_t from the binary file at the current file position, returns a single integer''' - s = self.read_size(4) - if s: - v, = struct.unpack(self.byte_order + 'I', s) - return v - else: - return fail_value - - def get_sint64(self, fail_value=0): - '''Extract a single int64_t from the binary file at the current file position, returns a single integer''' - s = self.read_size(8) - if s: - v, = struct.unpack(self.byte_order + 'q', s) - return v - else: - return fail_value - - def get_uint64(self, fail_value=0): - '''Extract a single uint64_t from the binary file at the current file position, returns a single integer''' - s = self.read_size(8) - if s: - v, = struct.unpack(self.byte_order + 'Q', s) - return v - else: - return fail_value - - def get_fixed_length_c_string( - self, - n, - fail_value='', - isprint_only_with_space_padding=False): - '''Extract a single fixed length C string from the binary file at the current file position, returns a single C string''' - s = self.read_size(n) - if s: - cstr, = struct.unpack(self.byte_order + ("%i" % n) + 's', s) - # Strip trialing NULLs - cstr = string.strip(cstr, "\0") - if isprint_only_with_space_padding: - for c in cstr: - if c in string.printable or ord(c) == 0: - continue - return fail_value - return cstr - else: - return fail_value - - def get_c_string(self): - '''Extract a single NULL terminated C string from the binary file at the current file position, returns a single C string''' - cstr = '' - byte = self.get_uint8() - while byte != 0: - cstr += "%c" % byte - byte = self.get_uint8() - return cstr - - def get_n_sint8(self, n, fail_value=0): - '''Extract "n" int8_t integers from the binary file at the current file position, returns a list of integers''' - s = self.read_size(n) - if s: - return struct.unpack(self.byte_order + ("%u" % n) + 'b', s) - else: - return (fail_value,) * n - - def get_n_uint8(self, n, fail_value=0): - '''Extract "n" uint8_t integers from the binary file at the current file position, returns a list of integers''' - s = self.read_size(n) - if s: - return struct.unpack(self.byte_order + ("%u" % n) + 'B', s) - else: - return (fail_value,) * n - - def get_n_sint16(self, n, fail_value=0): - '''Extract "n" int16_t integers from the binary file at the current file position, returns a list of integers''' - s = self.read_size(2 * n) - if s: - return struct.unpack(self.byte_order + ("%u" % n) + 'h', s) - else: - return (fail_value,) * n - - def get_n_uint16(self, n, fail_value=0): - '''Extract "n" uint16_t integers from the binary file at the current file position, returns a list of integers''' - s = self.read_size(2 * n) - if s: - return struct.unpack(self.byte_order + ("%u" % n) + 'H', s) - else: - return (fail_value,) * n - - def get_n_sint32(self, n, fail_value=0): - '''Extract "n" int32_t integers from the binary file at the current file position, returns a list of integers''' - s = self.read_size(4 * n) - if s: - return struct.unpack(self.byte_order + ("%u" % n) + 'i', s) - else: - return (fail_value,) * n - - def get_n_uint32(self, n, fail_value=0): - '''Extract "n" uint32_t integers from the binary file at the current file position, returns a list of integers''' - s = self.read_size(4 * n) - if s: - return struct.unpack(self.byte_order + ("%u" % n) + 'I', s) - else: - return (fail_value,) * n - - def get_n_sint64(self, n, fail_value=0): - '''Extract "n" int64_t integers from the binary file at the current file position, returns a list of integers''' - s = self.read_size(8 * n) - if s: - return struct.unpack(self.byte_order + ("%u" % n) + 'q', s) - else: - return (fail_value,) * n - - def get_n_uint64(self, n, fail_value=0): - '''Extract "n" uint64_t integers from the binary file at the current file position, returns a list of integers''' - s = self.read_size(8 * n) - if s: - return struct.unpack(self.byte_order + ("%u" % n) + 'Q', s) - else: - return (fail_value,) * n diff --git a/examples/python/gdb_disassemble.py b/examples/python/gdb_disassemble.py deleted file mode 100755 index 2590aba8c85c..000000000000 --- a/examples/python/gdb_disassemble.py +++ /dev/null @@ -1,26 +0,0 @@ -import lldb - - -def disassemble(debugger, command, result, dict): - if lldb.frame.function: - instructions = lldb.frame.function.instructions - start_addr = lldb.frame.function.addr.load_addr - name = lldb.frame.function.name - elif lldb.frame.symbol: - instructions = lldb.frame.symbol.instructions - start_addr = lldb.frame.symbol.addr.load_addr - name = lldb.frame.symbol.name - - for inst in instructions: - inst_addr = inst.addr.load_addr - inst_offset = inst_addr - start_addr - comment = inst.comment - if comment: - print "<%s + %-4u> 0x%x %8s %s ; %s" % (name, inst_offset, inst_addr, inst.mnemonic, inst.operands, comment) - else: - print "<%s + %-4u> 0x%x %8s %s" % (name, inst_offset, inst_addr, inst.mnemonic, inst.operands) - -# Install the command when the module gets imported -lldb.debugger.HandleCommand( - 'command script add -f gdb_disassemble.disassemble gdb-disassemble') -print 'Installed "gdb-disassemble" command for disassembly' diff --git a/examples/python/gdbremote.py b/examples/python/gdbremote.py deleted file mode 100755 index 4ca8a1b82e84..000000000000 --- a/examples/python/gdbremote.py +++ /dev/null @@ -1,1630 +0,0 @@ -#!/usr/bin/python - -#---------------------------------------------------------------------- -# This module will enable GDB remote packet logging when the -# 'start_gdb_log' command is called with a filename to log to. When the -# 'stop_gdb_log' command is called, it will disable the logging and -# print out statistics about how long commands took to execute and also -# will primnt ou -# Be sure to add the python path that points to the LLDB shared library. -# -# To use this in the embedded python interpreter using "lldb" just -# import it with the full path using the "command script import" -# command. This can be done from the LLDB command line: -# (lldb) command script import /path/to/gdbremote.py -# Or it can be added to your ~/.lldbinit file so this module is always -# available. -#---------------------------------------------------------------------- - -import binascii -import commands -import json -import math -import optparse -import os -import re -import shlex -import string -import sys -import tempfile -import xml.etree.ElementTree as ET - -#---------------------------------------------------------------------- -# Global variables -#---------------------------------------------------------------------- -g_log_file = '' -g_byte_order = 'little' -g_number_regex = re.compile('^(0x[0-9a-fA-F]+|[0-9]+)') -g_thread_id_regex = re.compile('^(-1|[0-9a-fA-F]+|0)') - - -class TerminalColors: - '''Simple terminal colors class''' - - def __init__(self, enabled=True): - # TODO: discover terminal type from "file" and disable if - # it can't handle the color codes - self.enabled = enabled - - def reset(self): - '''Reset all terminal colors and formatting.''' - if self.enabled: - return "\x1b[0m" - return '' - - def bold(self, on=True): - '''Enable or disable bold depending on the "on" parameter.''' - if self.enabled: - if on: - return "\x1b[1m" - else: - return "\x1b[22m" - return '' - - def italics(self, on=True): - '''Enable or disable italics depending on the "on" parameter.''' - if self.enabled: - if on: - return "\x1b[3m" - else: - return "\x1b[23m" - return '' - - def underline(self, on=True): - '''Enable or disable underline depending on the "on" parameter.''' - if self.enabled: - if on: - return "\x1b[4m" - else: - return "\x1b[24m" - return '' - - def inverse(self, on=True): - '''Enable or disable inverse depending on the "on" parameter.''' - if self.enabled: - if on: - return "\x1b[7m" - else: - return "\x1b[27m" - return '' - - def strike(self, on=True): - '''Enable or disable strike through depending on the "on" parameter.''' - if self.enabled: - if on: - return "\x1b[9m" - else: - return "\x1b[29m" - return '' - - def black(self, fg=True): - '''Set the foreground or background color to black. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[30m" - else: - return "\x1b[40m" - return '' - - def red(self, fg=True): - '''Set the foreground or background color to red. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[31m" - else: - return "\x1b[41m" - return '' - - def green(self, fg=True): - '''Set the foreground or background color to green. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[32m" - else: - return "\x1b[42m" - return '' - - def yellow(self, fg=True): - '''Set the foreground or background color to yellow. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[33m" - else: - return "\x1b[43m" - return '' - - def blue(self, fg=True): - '''Set the foreground or background color to blue. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[34m" - else: - return "\x1b[44m" - return '' - - def magenta(self, fg=True): - '''Set the foreground or background color to magenta. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[35m" - else: - return "\x1b[45m" - return '' - - def cyan(self, fg=True): - '''Set the foreground or background color to cyan. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[36m" - else: - return "\x1b[46m" - return '' - - def white(self, fg=True): - '''Set the foreground or background color to white. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[37m" - else: - return "\x1b[47m" - return '' - - def default(self, fg=True): - '''Set the foreground or background color to the default. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[39m" - else: - return "\x1b[49m" - return '' - - -def start_gdb_log(debugger, command, result, dict): - '''Start logging GDB remote packets by enabling logging with timestamps and - thread safe logging. Follow a call to this function with a call to "stop_gdb_log" - in order to dump out the commands.''' - global g_log_file - command_args = shlex.split(command) - 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 - be aggregated and displayed.''' - parser = optparse.OptionParser( - 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: - (options, args) = parser.parse_args(command_args) - except: - return - - if g_log_file: - result.PutCString( - 'error: logging is already in progress with file "%s"' % - g_log_file) - else: - args_len = len(args) - if args_len == 0: - g_log_file = tempfile.mktemp() - elif len(args) == 1: - g_log_file = args[0] - - if g_log_file: - debugger.HandleCommand( - '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 - - result.PutCString('error: invalid log file path') - result.PutCString(usage) - - -def stop_gdb_log(debugger, command, result, dict): - '''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 - timestamp in the log file. Also print out statistics for how long each - command took to allow performance bottlenecks to be determined.''' - global g_log_file - # Any commands whose names might be followed by more valid C identifier - # characters must be listed here - command_args = shlex.split(command) - 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.''' - parser = optparse.OptionParser( - description=description, - prog='stop_gdb_log', - usage=usage) - parser.add_option( - '-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: - (options, args) = parser.parse_args(command_args) - except: - return - options.colors = TerminalColors(options.color) - options.symbolicator = None - if options.symbolicate: - if lldb.target: - import lldb.utils.symbolication - options.symbolicator = lldb.utils.symbolication.Symbolicator() - options.symbolicator.target = lldb.target - else: - print "error: can't symbolicate without a target" - - if not g_log_file: - result.PutCString( - 'error: logging must have been previously enabled with a call to "stop_gdb_log"') - elif os.path.exists(g_log_file): - if len(args) == 0: - debugger.HandleCommand('log disable gdb-remote packets') - result.PutCString( - "GDB packet logging disabled. Logged packets are in '%s'" % - g_log_file) - parse_gdb_log_file(g_log_file, options) - else: - result.PutCString(usage) - else: - print 'error: the GDB packet log file "%s" does not exist' % g_log_file - - -def is_hex_byte(str): - if len(str) == 2: - return str[0] in string.hexdigits and str[1] in string.hexdigits - return False - -def get_hex_string_if_all_printable(str): - try: - s = binascii.unhexlify(str) - if all(c in string.printable for c in s): - return s - except TypeError: - pass - return None - -# global register info list -g_register_infos = list() -g_max_register_info_name_len = 0 - - -class RegisterInfo: - """Class that represents register information""" - - def __init__(self, kvp): - self.info = dict() - for kv in kvp: - key = kv[0] - value = kv[1] - self.info[key] = value - - def name(self): - '''Get the name of the register.''' - if self.info and 'name' in self.info: - return self.info['name'] - return None - - def bit_size(self): - '''Get the size in bits of the register.''' - if self.info and 'bitsize' in self.info: - return int(self.info['bitsize']) - return 0 - - def byte_size(self): - '''Get the size in bytes of the register.''' - return self.bit_size() / 8 - - def get_value_from_hex_string(self, hex_str): - '''Dump the register value given a native byte order encoded hex ASCII byte string.''' - encoding = self.info['encoding'] - bit_size = self.bit_size() - packet = Packet(hex_str) - if encoding == 'uint': - uval = packet.get_hex_uint(g_byte_order) - if bit_size == 8: - return '0x%2.2x' % (uval) - elif bit_size == 16: - return '0x%4.4x' % (uval) - elif bit_size == 32: - return '0x%8.8x' % (uval) - elif bit_size == 64: - return '0x%16.16x' % (uval) - bytes = list() - uval = packet.get_hex_uint8() - while uval is not None: - bytes.append(uval) - uval = packet.get_hex_uint8() - value_str = '0x' - if g_byte_order == 'little': - bytes.reverse() - for byte in bytes: - value_str += '%2.2x' % byte - return '%s' % (value_str) - - def __str__(self): - '''Dump the register info key/value pairs''' - s = '' - for key in self.info.keys(): - if s: - s += ', ' - s += "%s=%s " % (key, self.info[key]) - return s - - -class Packet: - """Class that represents a packet that contains string data""" - - def __init__(self, packet_str): - self.str = packet_str - - def peek_char(self): - ch = 0 - if self.str: - ch = self.str[0] - return ch - - def get_char(self): - ch = 0 - if self.str: - ch = self.str[0] - self.str = self.str[1:] - return ch - - def skip_exact_string(self, s): - if self.str and self.str.startswith(s): - self.str = self.str[len(s):] - return True - else: - return False - - def get_thread_id(self, fail_value=-1): - match = g_number_regex.match(self.str) - if match: - number_str = match.group(1) - self.str = self.str[len(number_str):] - return int(number_str, 0) - else: - return fail_value - - 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: - uval = int(self.str[0:2], 16) - self.str = self.str[2:] - return uval - return None - - def get_hex_uint16(self, byte_order): - uval = 0 - if byte_order == 'big': - uval |= self.get_hex_uint8() << 8 - uval |= self.get_hex_uint8() - else: - uval |= self.get_hex_uint8() - uval |= self.get_hex_uint8() << 8 - return uval - - def get_hex_uint32(self, byte_order): - uval = 0 - if byte_order == 'big': - uval |= self.get_hex_uint8() << 24 - uval |= self.get_hex_uint8() << 16 - uval |= self.get_hex_uint8() << 8 - uval |= self.get_hex_uint8() - else: - uval |= self.get_hex_uint8() - uval |= self.get_hex_uint8() << 8 - uval |= self.get_hex_uint8() << 16 - uval |= self.get_hex_uint8() << 24 - return uval - - def get_hex_uint64(self, byte_order): - uval = 0 - if byte_order == 'big': - uval |= self.get_hex_uint8() << 56 - uval |= self.get_hex_uint8() << 48 - uval |= self.get_hex_uint8() << 40 - uval |= self.get_hex_uint8() << 32 - uval |= self.get_hex_uint8() << 24 - uval |= self.get_hex_uint8() << 16 - uval |= self.get_hex_uint8() << 8 - uval |= self.get_hex_uint8() - else: - uval |= self.get_hex_uint8() - uval |= self.get_hex_uint8() << 8 - uval |= self.get_hex_uint8() << 16 - uval |= self.get_hex_uint8() << 24 - uval |= self.get_hex_uint8() << 32 - uval |= self.get_hex_uint8() << 40 - uval |= self.get_hex_uint8() << 48 - uval |= self.get_hex_uint8() << 56 - return uval - - def get_number(self, fail_value=-1): - '''Get a number from the packet. The number must be in big endian format and should be parsed - according to its prefix (starts with "0x" means hex, starts with "0" means octal, starts with - [1-9] means decimal, etc)''' - match = g_number_regex.match(self.str) - if match: - number_str = match.group(1) - self.str = self.str[len(number_str):] - return int(number_str, 0) - else: - return fail_value - - def get_hex_ascii_str(self, n=0): - hex_chars = self.get_hex_chars(n) - if hex_chars: - return binascii.unhexlify(hex_chars) - else: - return None - - def get_hex_chars(self, n=0): - str_len = len(self.str) - if n == 0: - # n was zero, so we need to determine all hex chars and - # stop when we hit the end of the string of a non-hex character - while n < str_len and self.str[n] in string.hexdigits: - n = n + 1 - else: - if n > str_len: - return None # Not enough chars - # Verify all chars are hex if a length was specified - for i in range(n): - if self.str[i] not in string.hexdigits: - return None # Not all hex digits - if n == 0: - return None - hex_str = self.str[0:n] - self.str = self.str[n:] - return hex_str - - def get_hex_uint(self, byte_order, n=0): - if byte_order == 'big': - hex_str = self.get_hex_chars(n) - if hex_str is None: - return None - return int(hex_str, 16) - else: - uval = self.get_hex_uint8() - if uval is None: - return None - uval_result = 0 - shift = 0 - while uval is not None: - uval_result |= (uval << shift) - shift += 8 - uval = self.get_hex_uint8() - return uval_result - - def get_key_value_pairs(self): - kvp = list() - if ';' in self.str: - key_value_pairs = string.split(self.str, ';') - for key_value_pair in key_value_pairs: - if len(key_value_pair): - kvp.append(string.split(key_value_pair, ':')) - return kvp - - def split(self, ch): - return string.split(self.str, ch) - - def split_hex(self, ch, byte_order): - hex_values = list() - strings = string.split(self.str, ch) - for str in strings: - hex_values.append(Packet(str).get_hex_uint(byte_order)) - return hex_values - - def __str__(self): - return self.str - - def __len__(self): - return len(self.str) - -g_thread_suffix_regex = re.compile(';thread:([0-9a-fA-F]+);') - - -def get_thread_from_thread_suffix(str): - if str: - match = g_thread_suffix_regex.match(str) - if match: - return int(match.group(1), 16) - return None - - -def cmd_qThreadStopInfo(options, cmd, args): - packet = Packet(args) - tid = packet.get_hex_uint('big') - print "get_thread_stop_info (tid = 0x%x)" % (tid) - - -def cmd_stop_reply(options, cmd, args): - print "get_last_stop_info()" - return False - - -def rsp_stop_reply(options, cmd, cmd_args, rsp): - global g_byte_order - packet = Packet(rsp) - stop_type = packet.get_char() - if stop_type == 'T' or stop_type == 'S': - signo = packet.get_hex_uint8() - key_value_pairs = packet.get_key_value_pairs() - for key_value_pair in key_value_pairs: - key = key_value_pair[0] - if is_hex_byte(key): - reg_num = Packet(key).get_hex_uint8() - if reg_num < len(g_register_infos): - reg_info = g_register_infos[reg_num] - key_value_pair[0] = reg_info.name() - key_value_pair[1] = reg_info.get_value_from_hex_string( - key_value_pair[1]) - elif key == 'jthreads' or key == 'jstopinfo': - key_value_pair[1] = binascii.unhexlify(key_value_pair[1]) - key_value_pairs.insert(0, ['signal', signo]) - print 'stop_reply():' - dump_key_value_pairs(key_value_pairs) - elif stop_type == 'W': - exit_status = packet.get_hex_uint8() - print 'stop_reply(): exit (status=%i)' % exit_status - elif stop_type == 'O': - print 'stop_reply(): stdout = "%s"' % packet.str - - -def cmd_unknown_packet(options, cmd, args): - if args: - print "cmd: %s, args: %s", cmd, args - else: - print "cmd: %s", cmd - return False - - -def cmd_qSymbol(options, cmd, args): - if args == ':': - print 'ready to serve symbols' - else: - packet = Packet(args) - symbol_addr = packet.get_hex_uint('big') - if symbol_addr is None: - if packet.skip_exact_string(':'): - symbol_name = packet.get_hex_ascii_str() - print 'lookup_symbol("%s") -> symbol not available yet' % (symbol_name) - else: - print 'error: bad command format' - else: - if packet.skip_exact_string(':'): - symbol_name = packet.get_hex_ascii_str() - print 'lookup_symbol("%s") -> 0x%x' % (symbol_name, symbol_addr) - else: - print 'error: bad command format' - -def cmd_QSetWithHexString(options, cmd, args): - print '%s("%s")' % (cmd[:-1], binascii.unhexlify(args)) - -def cmd_QSetWithString(options, cmd, args): - print '%s("%s")' % (cmd[:-1], args) - -def cmd_QSetWithUnsigned(options, cmd, args): - print '%s(%i)' % (cmd[:-1], int(args)) - -def rsp_qSymbol(options, cmd, cmd_args, rsp): - if len(rsp) == 0: - print "Unsupported" - else: - if rsp == "OK": - print "No more symbols to lookup" - else: - packet = Packet(rsp) - if packet.skip_exact_string("qSymbol:"): - symbol_name = packet.get_hex_ascii_str() - print 'lookup_symbol("%s")' % (symbol_name) - else: - print 'error: response string should start with "qSymbol:": respnse is "%s"' % (rsp) - - -def cmd_qXfer(options, cmd, args): - # $qXfer:features:read:target.xml:0,1ffff#14 - print "read target special data %s" % (args) - return True - - -def rsp_qXfer(options, cmd, cmd_args, rsp): - data = string.split(cmd_args, ':') - if data[0] == 'features': - if data[1] == 'read': - filename, extension = os.path.splitext(data[2]) - if extension == '.xml': - response = Packet(rsp) - xml_string = response.get_hex_ascii_str() - if xml_string: - ch = xml_string[0] - if ch == 'l': - xml_string = xml_string[1:] - xml_root = ET.fromstring(xml_string) - for reg_element in xml_root.findall("./feature/reg"): - if not 'value_regnums' in reg_element.attrib: - reg_info = RegisterInfo([]) - if 'name' in reg_element.attrib: - reg_info.info[ - 'name'] = reg_element.attrib['name'] - else: - reg_info.info['name'] = 'unspecified' - if 'encoding' in reg_element.attrib: - reg_info.info['encoding'] = reg_element.attrib[ - 'encoding'] - else: - reg_info.info['encoding'] = 'uint' - if 'offset' in reg_element.attrib: - reg_info.info[ - 'offset'] = reg_element.attrib['offset'] - if 'bitsize' in reg_element.attrib: - reg_info.info[ - 'bitsize'] = reg_element.attrib['bitsize'] - g_register_infos.append(reg_info) - print 'XML for "%s":' % (data[2]) - ET.dump(xml_root) - - -def cmd_A(options, cmd, args): - print 'launch process:' - packet = Packet(args) - while True: - arg_len = packet.get_number() - if arg_len == -1: - break - if not packet.skip_exact_string(','): - break - arg_idx = packet.get_number() - if arg_idx == -1: - break - if not packet.skip_exact_string(','): - break - arg_value = packet.get_hex_ascii_str(arg_len) - print 'argv[%u] = "%s"' % (arg_idx, arg_value) - - -def cmd_qC(options, cmd, args): - print "query_current_thread_id()" - - -def rsp_qC(options, cmd, cmd_args, rsp): - packet = Packet(rsp) - if packet.skip_exact_string("QC"): - tid = packet.get_thread_id() - print "current_thread_id = %#x" % (tid) - else: - print "current_thread_id = old thread ID" - - -def cmd_query_packet(options, cmd, args): - if args: - print "%s%s" % (cmd, args) - else: - print "%s" % (cmd) - return False - - -def rsp_ok_error(rsp): - print "rsp: ", rsp - - -def rsp_ok_means_supported(options, cmd, cmd_args, rsp): - if rsp == 'OK': - print "%s%s is supported" % (cmd, cmd_args) - elif rsp == '': - print "%s%s is not supported" % (cmd, cmd_args) - else: - print "%s%s -> %s" % (cmd, cmd_args, rsp) - - -def rsp_ok_means_success(options, cmd, cmd_args, rsp): - if rsp == 'OK': - print "success" - elif rsp == '': - print "%s%s is not supported" % (cmd, cmd_args) - else: - print "%s%s -> %s" % (cmd, cmd_args, rsp) - - -def dump_key_value_pairs(key_value_pairs): - max_key_len = 0 - for key_value_pair in key_value_pairs: - key_len = len(key_value_pair[0]) - if max_key_len < key_len: - max_key_len = key_len - for key_value_pair in key_value_pairs: - key = key_value_pair[0] - value = key_value_pair[1] - unhex_value = get_hex_string_if_all_printable(value) - if unhex_value: - print "%*s = %s (%s)" % (max_key_len, key, value, unhex_value) - else: - print "%*s = %s" % (max_key_len, key, value) - - -def rsp_dump_key_value_pairs(options, cmd, cmd_args, rsp): - if rsp: - print '%s response:' % (cmd) - packet = Packet(rsp) - key_value_pairs = packet.get_key_value_pairs() - dump_key_value_pairs(key_value_pairs) - else: - print "not supported" - - -def cmd_c(options, cmd, args): - print "continue()" - return False - - -def cmd_s(options, cmd, args): - print "step()" - return False - - -def cmd_qSpeedTest(options, cmd, args): - print("qSpeedTest: cmd='%s', args='%s'" % (cmd, args)) - - -def rsp_qSpeedTest(options, cmd, cmd_args, rsp): - print("qSpeedTest: rsp='%s' cmd='%s', args='%s'" % (rsp, cmd, args)) - - -def cmd_vCont(options, cmd, args): - if args == '?': - print "%s: get supported extended continue modes" % (cmd) - else: - got_other_threads = 0 - s = '' - for thread_action in string.split(args[1:], ';'): - (short_action, thread) = string.split(thread_action, ':') - tid = int(thread, 16) - if short_action == 'c': - action = 'continue' - elif short_action == 's': - action = 'step' - elif short_action[0] == 'C': - action = 'continue with signal 0x%s' % (short_action[1:]) - elif short_action == 'S': - action = 'step with signal 0x%s' % (short_action[1:]) - else: - action = short_action - if s: - s += ', ' - if tid == -1: - got_other_threads = 1 - s += 'other-threads:' - else: - s += 'thread 0x%4.4x: %s' % (tid, action) - if got_other_threads: - print "extended_continue (%s)" % (s) - else: - print "extended_continue (%s, other-threads: suspend)" % (s) - return False - - -def rsp_vCont(options, cmd, cmd_args, rsp): - if cmd_args == '?': - # Skip the leading 'vCont;' - rsp = rsp[6:] - modes = string.split(rsp, ';') - s = "%s: supported extended continue modes include: " % (cmd) - - for i, mode in enumerate(modes): - if i: - s += ', ' - if mode == 'c': - s += 'continue' - elif mode == 'C': - s += 'continue with signal' - elif mode == 's': - s += 'step' - elif mode == 'S': - s += 'step with signal' - elif mode == 't': - s += 'stop' - # else: - # s += 'unrecognized vCont mode: ', str(mode) - print s - elif rsp: - if rsp[0] == 'T' or rsp[0] == 'S' or rsp[0] == 'W' or rsp[0] == 'X': - rsp_stop_reply(options, cmd, cmd_args, rsp) - return - if rsp[0] == 'O': - print "stdout: %s" % (rsp) - return - else: - print "not supported (cmd = '%s', args = '%s', rsp = '%s')" % (cmd, cmd_args, rsp) - - -def cmd_vAttach(options, cmd, args): - (extra_command, args) = string.split(args, ';') - if extra_command: - print "%s%s(%s)" % (cmd, extra_command, args) - else: - print "attach(pid = %u)" % int(args, 16) - return False - - -def cmd_qRegisterInfo(options, cmd, args): - print 'query_register_info(reg_num=%i)' % (int(args, 16)) - return False - - -def rsp_qRegisterInfo(options, cmd, cmd_args, rsp): - global g_max_register_info_name_len - print 'query_register_info(reg_num=%i):' % (int(cmd_args, 16)), - if len(rsp) == 3 and rsp[0] == 'E': - g_max_register_info_name_len = 0 - for reg_info in g_register_infos: - name_len = len(reg_info.name()) - if g_max_register_info_name_len < name_len: - g_max_register_info_name_len = name_len - print' DONE' - else: - packet = Packet(rsp) - reg_info = RegisterInfo(packet.get_key_value_pairs()) - g_register_infos.append(reg_info) - print reg_info - return False - - -def cmd_qThreadInfo(options, cmd, args): - if cmd == 'qfThreadInfo': - query_type = 'first' - else: - query_type = 'subsequent' - print 'get_current_thread_list(type=%s)' % (query_type) - return False - - -def rsp_qThreadInfo(options, cmd, cmd_args, rsp): - packet = Packet(rsp) - response_type = packet.get_char() - if response_type == 'm': - tids = packet.split_hex(';', 'big') - for i, tid in enumerate(tids): - if i: - print ',', - print '0x%x' % (tid), - print - elif response_type == 'l': - print 'END' - - -def rsp_hex_big_endian(options, cmd, cmd_args, rsp): - if rsp == '': - print "%s%s is not supported" % (cmd, cmd_args) - else: - packet = Packet(rsp) - uval = packet.get_hex_uint('big') - print '%s: 0x%x' % (cmd, uval) - - -def cmd_read_mem_bin(options, cmd, args): - # x0x7fff5fc39200,0x200 - packet = Packet(args) - addr = packet.get_hex_uint('big') - comma = packet.get_char() - size = packet.get_hex_uint('big') - print 'binary_read_memory (addr = 0x%16.16x, size = %u)' % (addr, size) - return False - - -def rsp_mem_bin_bytes(options, cmd, cmd_args, rsp): - packet = Packet(cmd_args) - addr = packet.get_hex_uint('big') - comma = packet.get_char() - size = packet.get_hex_uint('big') - print 'memory:' - if size > 0: - dump_hex_memory_buffer(addr, rsp) - - -def cmd_read_memory(options, cmd, args): - packet = Packet(args) - addr = packet.get_hex_uint('big') - comma = packet.get_char() - size = packet.get_hex_uint('big') - print 'read_memory (addr = 0x%16.16x, size = %u)' % (addr, size) - return False - - -def dump_hex_memory_buffer(addr, hex_byte_str): - packet = Packet(hex_byte_str) - idx = 0 - ascii = '' - uval = packet.get_hex_uint8() - while uval is not None: - if ((idx % 16) == 0): - if ascii: - print ' ', ascii - ascii = '' - print '0x%x:' % (addr + idx), - print '%2.2x' % (uval), - if 0x20 <= uval and uval < 0x7f: - ascii += '%c' % uval - else: - ascii += '.' - uval = packet.get_hex_uint8() - idx = idx + 1 - if ascii: - print ' ', ascii - ascii = '' - - -def cmd_write_memory(options, cmd, args): - packet = Packet(args) - addr = packet.get_hex_uint('big') - if packet.get_char() != ',': - print 'error: invalid write memory command (missing comma after address)' - return - size = packet.get_hex_uint('big') - if packet.get_char() != ':': - print 'error: invalid write memory command (missing colon after size)' - return - print 'write_memory (addr = 0x%16.16x, size = %u, data:' % (addr, size) - dump_hex_memory_buffer(addr, packet.str) - return False - - -def cmd_alloc_memory(options, cmd, args): - packet = Packet(args) - byte_size = packet.get_hex_uint('big') - if packet.get_char() != ',': - print 'error: invalid allocate memory command (missing comma after address)' - return - print 'allocate_memory (byte-size = %u (0x%x), permissions = %s)' % (byte_size, byte_size, packet.str) - return False - - -def rsp_alloc_memory(options, cmd, cmd_args, rsp): - packet = Packet(rsp) - addr = packet.get_hex_uint('big') - print 'addr = 0x%x' % addr - - -def cmd_dealloc_memory(options, cmd, args): - packet = Packet(args) - addr = packet.get_hex_uint('big') - if packet.get_char() != ',': - print 'error: invalid allocate memory command (missing comma after address)' - else: - print 'deallocate_memory (addr = 0x%x, permissions = %s)' % (addr, packet.str) - return False - - -def rsp_memory_bytes(options, cmd, cmd_args, rsp): - addr = Packet(cmd_args).get_hex_uint('big') - dump_hex_memory_buffer(addr, rsp) - - -def get_register_name_equal_value(options, reg_num, hex_value_str): - if reg_num < len(g_register_infos): - reg_info = g_register_infos[reg_num] - value_str = reg_info.get_value_from_hex_string(hex_value_str) - s = reg_info.name() + ' = ' - if options.symbolicator: - symbolicated_addresses = options.symbolicator.symbolicate( - int(value_str, 0)) - if symbolicated_addresses: - s += options.colors.magenta() - s += '%s' % symbolicated_addresses[0] - s += options.colors.reset() - return s - s += value_str - return s - else: - reg_value = Packet(hex_value_str).get_hex_uint(g_byte_order) - return 'reg(%u) = 0x%x' % (reg_num, reg_value) - - -def cmd_read_one_reg(options, cmd, args): - packet = Packet(args) - reg_num = packet.get_hex_uint('big') - tid = get_thread_from_thread_suffix(packet.str) - name = None - if reg_num < len(g_register_infos): - name = g_register_infos[reg_num].name() - if packet.str: - packet.get_char() # skip ; - thread_info = packet.get_key_value_pairs() - tid = int(thread_info[0][1], 16) - s = 'read_register (reg_num=%u' % reg_num - if name: - s += ' (%s)' % (name) - if tid is not None: - s += ', tid = 0x%4.4x' % (tid) - s += ')' - print s - return False - - -def rsp_read_one_reg(options, cmd, cmd_args, rsp): - packet = Packet(cmd_args) - reg_num = packet.get_hex_uint('big') - print get_register_name_equal_value(options, reg_num, rsp) - - -def cmd_write_one_reg(options, cmd, args): - packet = Packet(args) - reg_num = packet.get_hex_uint('big') - if packet.get_char() != '=': - print 'error: invalid register write packet' - else: - name = None - hex_value_str = packet.get_hex_chars() - tid = get_thread_from_thread_suffix(packet.str) - s = 'write_register (reg_num=%u' % reg_num - if name: - s += ' (%s)' % (name) - s += ', value = ' - s += get_register_name_equal_value(options, reg_num, hex_value_str) - if tid is not None: - s += ', tid = 0x%4.4x' % (tid) - s += ')' - print s - return False - - -def dump_all_regs(packet): - for reg_info in g_register_infos: - nibble_size = reg_info.bit_size() / 4 - hex_value_str = packet.get_hex_chars(nibble_size) - if hex_value_str is not None: - value = reg_info.get_value_from_hex_string(hex_value_str) - print '%*s = %s' % (g_max_register_info_name_len, reg_info.name(), value) - else: - return - - -def cmd_read_all_regs(cmd, cmd_args): - packet = Packet(cmd_args) - packet.get_char() # toss the 'g' command character - tid = get_thread_from_thread_suffix(packet.str) - if tid is not None: - print 'read_all_register(thread = 0x%4.4x)' % tid - else: - print 'read_all_register()' - return False - - -def rsp_read_all_regs(options, cmd, cmd_args, rsp): - packet = Packet(rsp) - dump_all_regs(packet) - - -def cmd_write_all_regs(options, cmd, args): - packet = Packet(args) - print 'write_all_registers()' - dump_all_regs(packet) - return False - -g_bp_types = ["software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp"] - - -def cmd_bp(options, cmd, args): - if cmd == 'Z': - s = 'set_' - else: - s = 'clear_' - packet = Packet(args) - bp_type = packet.get_hex_uint('big') - packet.get_char() # Skip , - bp_addr = packet.get_hex_uint('big') - packet.get_char() # Skip , - bp_size = packet.get_hex_uint('big') - s += g_bp_types[bp_type] - s += " (addr = 0x%x, size = %u)" % (bp_addr, bp_size) - print s - return False - - -def cmd_mem_rgn_info(options, cmd, args): - packet = Packet(args) - packet.get_char() # skip ':' character - addr = packet.get_hex_uint('big') - print 'get_memory_region_info (addr=0x%x)' % (addr) - return False - - -def cmd_kill(options, cmd, args): - print 'kill_process()' - return False - - -def cmd_jThreadsInfo(options, cmd, args): - print 'jThreadsInfo()' - return False - - -def cmd_jGetLoadedDynamicLibrariesInfos(options, cmd, args): - print 'jGetLoadedDynamicLibrariesInfos()' - return False - - -def decode_packet(s, start_index=0): - # print '\ndecode_packet("%s")' % (s[start_index:]) - index = s.find('}', start_index) - have_escapes = index != -1 - if have_escapes: - normal_s = s[start_index:index] - else: - normal_s = s[start_index:] - # print 'normal_s = "%s"' % (normal_s) - if have_escapes: - escape_char = '%c' % (ord(s[index + 1]) ^ 0x20) - # print 'escape_char for "%s" = %c' % (s[index:index+2], escape_char) - return normal_s + escape_char + decode_packet(s, index + 2) - else: - return normal_s - - -def rsp_json(options, cmd, cmd_args, rsp): - print '%s() reply:' % (cmd) - json_tree = json.loads(rsp) - print json.dumps(json_tree, indent=4, separators=(',', ': ')) - - -def rsp_jGetLoadedDynamicLibrariesInfos(options, cmd, cmd_args, rsp): - if cmd_args: - rsp_json(options, cmd, cmd_args, rsp) - else: - rsp_ok_means_supported(options, cmd, cmd_args, rsp) - -gdb_remote_commands = { - '\\?': {'cmd': cmd_stop_reply, 'rsp': rsp_stop_reply, 'name': "stop reply pacpket"}, - 'qThreadStopInfo': {'cmd': cmd_qThreadStopInfo, 'rsp': rsp_stop_reply, 'name': "stop reply pacpket"}, - 'QStartNoAckMode': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query if no ack mode is supported"}, - 'QThreadSuffixSupported': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query if thread suffix is supported"}, - 'QListThreadsInStopReply': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query if threads in stop reply packets are supported"}, - 'QSetDetachOnError:': {'cmd': cmd_QSetWithUnsigned, 'rsp': rsp_ok_means_success, 'name': "set if we should detach on error"}, - 'QSetDisableASLR:': {'cmd': cmd_QSetWithUnsigned, 'rsp': rsp_ok_means_success, 'name': "set if we should disable ASLR"}, - 'qLaunchSuccess': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_success, 'name': "check on launch success for the A packet"}, - 'A': {'cmd': cmd_A, 'rsp': rsp_ok_means_success, 'name': "launch process"}, - 'QLaunchArch:': {'cmd': cmd_QSetWithString, 'rsp': rsp_ok_means_supported, 'name': "set the arch to launch in case the file contains multiple architectures"}, - 'qVAttachOrWaitSupported': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "set the launch architecture"}, - 'qHostInfo': {'cmd': cmd_query_packet, 'rsp': rsp_dump_key_value_pairs, 'name': "get host information"}, - 'qC': {'cmd': cmd_qC, 'rsp': rsp_qC, 'name': "return the current thread ID"}, - 'vCont': {'cmd': cmd_vCont, 'rsp': rsp_vCont, 'name': "extended continue command"}, - 'qSpeedTest': {'cmd':cmd_qSpeedTest, 'rsp': rsp_qSpeedTest, 'name': 'speed test packdet'}, - 'vAttach': {'cmd': cmd_vAttach, 'rsp': rsp_stop_reply, 'name': "attach to process"}, - 'c': {'cmd': cmd_c, 'rsp': rsp_stop_reply, 'name': "continue"}, - 's': {'cmd': cmd_s, 'rsp': rsp_stop_reply, 'name': "step"}, - 'qRegisterInfo': {'cmd': cmd_qRegisterInfo, 'rsp': rsp_qRegisterInfo, 'name': "query register info"}, - 'qfThreadInfo': {'cmd': cmd_qThreadInfo, 'rsp': rsp_qThreadInfo, 'name': "get current thread list"}, - 'qsThreadInfo': {'cmd': cmd_qThreadInfo, 'rsp': rsp_qThreadInfo, 'name': "get current thread list"}, - 'qShlibInfoAddr': {'cmd': cmd_query_packet, 'rsp': rsp_hex_big_endian, 'name': "get shared library info address"}, - 'qMemoryRegionInfo': {'cmd': cmd_mem_rgn_info, 'rsp': rsp_dump_key_value_pairs, 'name': "get memory region information"}, - 'qProcessInfo': {'cmd': cmd_query_packet, 'rsp': rsp_dump_key_value_pairs, 'name': "get process info"}, - 'qSupported': {'cmd': cmd_query_packet, 'rsp': rsp_ok_means_supported, 'name': "query supported"}, - 'qXfer:': {'cmd': cmd_qXfer, 'rsp': rsp_qXfer, 'name': "qXfer"}, - 'qSymbol:': {'cmd': cmd_qSymbol, 'rsp': rsp_qSymbol, 'name': "qSymbol"}, - 'QSetSTDIN:' : {'cmd' : cmd_QSetWithHexString, 'rsp' : rsp_ok_means_success, 'name': "set STDIN prior to launching with A packet"}, - 'QSetSTDOUT:' : {'cmd' : cmd_QSetWithHexString, 'rsp' : rsp_ok_means_success, 'name': "set STDOUT prior to launching with A packet"}, - 'QSetSTDERR:' : {'cmd' : cmd_QSetWithHexString, 'rsp' : rsp_ok_means_success, 'name': "set STDERR prior to launching with A packet"}, - 'QEnvironment:' : {'cmd' : cmd_QSetWithString, 'rsp' : rsp_ok_means_success, 'name': "set an environment variable prior to launching with A packet"}, - 'QEnvironmentHexEncoded:' : {'cmd' : cmd_QSetWithHexString, 'rsp' : rsp_ok_means_success, 'name': "set an environment variable prior to launching with A packet"}, - 'x': {'cmd': cmd_read_mem_bin, 'rsp': rsp_mem_bin_bytes, 'name': "read memory binary"}, - 'X': {'cmd': cmd_write_memory, 'rsp': rsp_ok_means_success, 'name': "write memory binary"}, - 'm': {'cmd': cmd_read_memory, 'rsp': rsp_memory_bytes, 'name': "read memory"}, - 'M': {'cmd': cmd_write_memory, 'rsp': rsp_ok_means_success, 'name': "write memory"}, - '_M': {'cmd': cmd_alloc_memory, 'rsp': rsp_alloc_memory, 'name': "allocate memory"}, - '_m': {'cmd': cmd_dealloc_memory, 'rsp': rsp_ok_means_success, 'name': "deallocate memory"}, - 'p': {'cmd': cmd_read_one_reg, 'rsp': rsp_read_one_reg, 'name': "read single register"}, - 'P': {'cmd': cmd_write_one_reg, 'rsp': rsp_ok_means_success, 'name': "write single register"}, - 'g': {'cmd': cmd_read_all_regs, 'rsp': rsp_read_all_regs, 'name': "read all registers"}, - 'G': {'cmd': cmd_write_all_regs, 'rsp': rsp_ok_means_success, 'name': "write all registers"}, - 'z': {'cmd': cmd_bp, 'rsp': rsp_ok_means_success, 'name': "clear breakpoint or watchpoint"}, - 'Z': {'cmd': cmd_bp, 'rsp': rsp_ok_means_success, 'name': "set breakpoint or watchpoint"}, - 'k': {'cmd': cmd_kill, 'rsp': rsp_stop_reply, 'name': "kill process"}, - 'jThreadsInfo': {'cmd': cmd_jThreadsInfo, 'rsp': rsp_json, 'name': "JSON get all threads info"}, - 'jGetLoadedDynamicLibrariesInfos:': {'cmd': cmd_jGetLoadedDynamicLibrariesInfos, 'rsp': rsp_jGetLoadedDynamicLibrariesInfos, 'name': 'JSON get loaded dynamic libraries'}, -} - - -def calculate_mean_and_standard_deviation(floats): - sum = 0.0 - count = len(floats) - if count == 0: - return (0.0, 0.0) - for f in floats: - sum += f - mean = sum / count - accum = 0.0 - for f in floats: - delta = f - mean - accum += delta * delta - - std_dev = math.sqrt(accum / (count - 1)) - return (mean, std_dev) - - -def parse_gdb_log_file(path, options): - f = open(path) - parse_gdb_log(f, options) - f.close() - - -def round_up(n, incr): - return float(((int(n) + incr) / incr) * incr) - - -def plot_latencies(sec_times): - # import numpy as np - import matplotlib.pyplot as plt - - for (i, name) in enumerate(sec_times.keys()): - times = sec_times[name] - if len(times) <= 1: - continue - plt.subplot(2, 1, 1) - plt.title('Packet "%s" Times' % (name)) - plt.xlabel('Packet') - units = 'ms' - adj_times = [] - max_time = 0.0 - for time in times: - time = time * 1000.0 - adj_times.append(time) - if time > max_time: - max_time = time - if max_time < 1.0: - units = 'us' - max_time = 0.0 - for i in range(len(adj_times)): - adj_times[i] *= 1000.0 - if adj_times[i] > max_time: - max_time = adj_times[i] - plt.ylabel('Time (%s)' % (units)) - max_y = None - for i in [5.0, 10.0, 25.0, 50.0]: - if max_time < i: - max_y = round_up(max_time, i) - break - if max_y is None: - max_y = round_up(max_time, 100.0) - plt.ylim(0.0, max_y) - plt.plot(adj_times, 'o-') - plt.show() - - -def parse_gdb_log(file, options): - '''Parse a GDB log file that was generated by enabling logging with: - (lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets - This log file will contain timestamps and this function will then normalize - those packets to be relative to the first value timestamp that is found and - show delta times between log lines and also keep track of how long it takes - for GDB remote commands to make a send/receive round trip. This can be - handy when trying to figure out why some operation in the debugger is taking - a long time during a preset set of debugger commands.''' - - tricky_commands = ['qRegisterInfo'] - timestamp_regex = re.compile('(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$') - packet_name_regex = re.compile('([A-Za-z_]+)[^a-z]') - 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_checksum_regex = re.compile('.*#[0-9a-fA-F]{2}$') - packet_names_regex_str = '(' + \ - '|'.join(gdb_remote_commands.keys()) + ')(.*)' - packet_names_regex = re.compile(packet_names_regex_str) - - base_time = 0.0 - last_time = 0.0 - min_time = 100000000.0 - packet_total_times = {} - all_packet_times = [] - packet_times = {} - packet_counts = {} - lines = file.read().splitlines() - last_command = None - last_command_args = None - last_command_packet = None - hide_next_response = False - num_lines = len(lines) - skip_count = 0 - for (line_index, line) in enumerate(lines): - # See if we need to skip any lines - if skip_count > 0: - skip_count -= 1 - continue - m = packet_transmit_name_regex.search(line) - is_command = False - direction = None - if m: - direction = m.group('direction') - is_command = direction == 'send' - packet = m.group('packet') - sys.stdout.write(options.colors.green()) - if not options.quiet and not hide_next_response: - print '# ', line - sys.stdout.write(options.colors.reset()) - - # print 'direction = "%s", packet = "%s"' % (direction, packet) - - if packet[0] == '+': - if is_command: - print '-->', - else: - print '<--', - if not options.quiet: - print 'ACK' - continue - elif packet[0] == '-': - if is_command: - print '-->', - else: - print '<--', - if not options.quiet: - print 'NACK' - continue - elif packet[0] == '$': - m = packet_contents_name_regex.match(packet) - if not m and packet[0] == '$': - multiline_packet = packet - idx = line_index + 1 - while idx < num_lines: - if not options.quiet and not hide_next_response: - print '# ', lines[idx] - multiline_packet += lines[idx] - m = packet_contents_name_regex.match(multiline_packet) - if m: - packet = multiline_packet - skip_count = idx - line_index - break - else: - idx += 1 - if m: - if is_command: - print '-->', - else: - print '<--', - contents = decode_packet(m.group(1)) - if is_command: - hide_next_response = False - m = packet_names_regex.match(contents) - if m: - last_command = m.group(1) - if last_command == '?': - last_command = '\\?' - packet_name = last_command - last_command_args = m.group(2) - last_command_packet = contents - hide_next_response = gdb_remote_commands[last_command][ - 'cmd'](options, last_command, last_command_args) - else: - packet_match = packet_name_regex.match(contents) - if packet_match: - packet_name = packet_match.group(1) - for tricky_cmd in tricky_commands: - if packet_name.find(tricky_cmd) == 0: - packet_name = tricky_cmd - else: - packet_name = contents - last_command = None - last_command_args = None - last_command_packet = None - elif last_command: - gdb_remote_commands[last_command]['rsp']( - options, last_command, last_command_args, contents) - else: - print 'error: invalid packet: "', packet, '"' - else: - print '???' - else: - print '## ', line - match = timestamp_regex.match(line) - if match: - curr_time = float(match.group(2)) - if last_time and not is_command: - delta = curr_time - last_time - all_packet_times.append(delta) - delta = 0.0 - if base_time: - delta = curr_time - last_time - else: - base_time = curr_time - - if not is_command: - if line.find('read packet: $') >= 0 and packet_name: - if packet_name in packet_total_times: - packet_total_times[packet_name] += delta - packet_counts[packet_name] += 1 - else: - packet_total_times[packet_name] = delta - packet_counts[packet_name] = 1 - if packet_name not in packet_times: - packet_times[packet_name] = [] - packet_times[packet_name].append(delta) - packet_name = None - if min_time > delta: - min_time = delta - - if not options or not options.quiet: - print '%s%.6f %+.6f%s' % (match.group(1), - curr_time - base_time, - delta, - match.group(3)) - last_time = curr_time - # else: - # print line - (average, std_dev) = calculate_mean_and_standard_deviation(all_packet_times) - if average and std_dev: - print '%u packets with average packet time of %f and standard deviation of %f' % (len(all_packet_times), average, std_dev) - if packet_total_times: - total_packet_time = 0.0 - total_packet_count = 0 - for key, vvv in packet_total_times.items(): - # print ' key = (%s) "%s"' % (type(key), key) - # print 'value = (%s) %s' % (type(vvv), vvv) - # if type(vvv) == 'float': - total_packet_time += vvv - for key, vvv in packet_counts.items(): - total_packet_count += vvv - - print '#------------------------------------------------------------' - print '# Packet timing summary:' - print '# Totals: time = %6f, count = %6d' % (total_packet_time, - total_packet_count) - print '# Min packet time: time = %6f' % (min_time) - print '#------------------------------------------------------------' - print '# Packet Time (sec) Percent Count Latency' - print '#------------------------- ----------- ------- ------ -------' - if options and options.sort_count: - res = sorted( - packet_counts, - key=packet_counts.__getitem__, - reverse=True) - else: - res = sorted( - packet_total_times, - key=packet_total_times.__getitem__, - reverse=True) - - if last_time > 0.0: - for item in res: - packet_total_time = packet_total_times[item] - packet_percent = ( - packet_total_time / total_packet_time) * 100.0 - packet_count = packet_counts[item] - print " %24s %11.6f %5.2f%% %6d %9.6f" % ( - item, packet_total_time, packet_percent, packet_count, - float(packet_total_time) / float(packet_count)) - if options.plot: - plot_latencies(packet_times) - -if __name__ == '__main__': - usage = "usage: gdbremote [options]" - description = '''The command disassembles a GDB remote packet log.''' - parser = optparse.OptionParser( - description=description, - prog='gdbremote', - usage=usage) - parser.add_option( - '-v', - '--verbose', - action='store_true', - dest='verbose', - help='display verbose debug info', - default=False) - parser.add_option( - '--plot', - action='store_true', - dest='plot', - help='plot packet latencies by packet type', - 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: - (options, args) = parser.parse_args(sys.argv[1:]) - except: - print 'error: argument error' - sys.exit(1) - - options.colors = TerminalColors(options.color) - options.symbolicator = None - if options.crashlog: - import lldb - lldb.debugger = lldb.SBDebugger.Create() - import lldb.macosx.crashlog - options.symbolicator = lldb.macosx.crashlog.CrashLog(options.crashlog) - print '%s' % (options.symbolicator) - - # This script is being run from the command line, create a debugger in case we are - # going to use any debugger functions in our function. - if len(args): - for file in args: - print '#----------------------------------------------------------------------' - print "# GDB remote log file: '%s'" % file - print '#----------------------------------------------------------------------' - parse_gdb_log_file(file, options) - if options.symbolicator: - print '%s' % (options.symbolicator) - else: - parse_gdb_log(sys.stdin, options) - -else: - import lldb - if lldb.debugger: - # This initializer is being run from LLDB in the embedded command interpreter - # Add any commands contained in this module to LLDB - lldb.debugger.HandleCommand( - 'command script add -f 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' diff --git a/examples/python/globals.py b/examples/python/globals.py deleted file mode 100755 index 43bd915b3933..000000000000 --- a/examples/python/globals.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/python - -#---------------------------------------------------------------------- -# For the shells csh, tcsh: -# ( setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python ; ./globals.py <path> [<path> ...]) -# -# For the shells sh, bash: -# PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python ./globals.py <path> [<path> ...] -#---------------------------------------------------------------------- - -import lldb -import commands -import optparse -import os -import shlex -import sys - - -def get_globals(raw_path, options): - error = lldb.SBError() - # Resolve the path if needed - path = os.path.expanduser(raw_path) - # Create a target using path + options - target = lldb.debugger.CreateTarget( - path, options.arch, options.platform, False, error) - if target: - # Get the executable module - module = target.module[target.executable.basename] - if module: - # Keep track of which variables we have already looked up - global_names = list() - # Iterate through all symbols in the symbol table and watch for any - # DATA symbols - for symbol in module.symbols: - if symbol.type == lldb.eSymbolTypeData: - # The symbol is a DATA symbol, lets try and find all global variables - # that match this name and print them - global_name = symbol.name - # Make sure we don't lookup the same variable twice - if global_name not in global_names: - global_names.append(global_name) - # Find all global variables by name - global_variable_list = module.FindGlobalVariables( - target, global_name, lldb.UINT32_MAX) - if global_variable_list: - # Print results for anything that matched - for global_variable in global_variable_list: - # returns the global variable name as a string - print 'name = %s' % global_variable.name - # Returns the variable value as a string - print 'value = %s' % global_variable.value - print 'type = %s' % global_variable.type # Returns an lldb.SBType object - # Returns an lldb.SBAddress (section offset - # address) for this global - print 'addr = %s' % global_variable.addr - # Returns the file virtual address for this - # global - print 'file_addr = 0x%x' % global_variable.addr.file_addr - # returns the global variable value as a string - print 'location = %s' % global_variable.location - # Returns the size in bytes of this global - # variable - print 'size = %s' % global_variable.size - print - - -def globals(command_args): - '''Extract all globals from any arguments which must be paths to object files.''' - usage = "usage: %prog [options] <PATH> [PATH ...]" - description = '''This command will find all globals in the specified object file and return an list() of lldb.SBValue objects (which might be empty).''' - parser = optparse.OptionParser( - description=description, - prog='globals', - usage=usage) - parser.add_option( - '-v', - '--verbose', - action='store_true', - dest='verbose', - help='display verbose debug info', - default=False) - parser.add_option( - '-a', - '--arch', - type='string', - metavar='arch', - dest='arch', - help='Specify an architecture (or triple) to use when extracting from a file.') - parser.add_option( - '-p', - '--platform', - type='string', - metavar='platform', - dest='platform', - help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".') - try: - (options, args) = parser.parse_args(command_args) - except: - return - - for path in args: - get_globals(path, options) - -if __name__ == '__main__': - lldb.debugger = lldb.SBDebugger.Create() - globals(sys.argv[1:]) diff --git a/examples/python/jump.py b/examples/python/jump.py deleted file mode 100644 index 6e41b4c8098f..000000000000 --- a/examples/python/jump.py +++ /dev/null @@ -1,196 +0,0 @@ -import lldb -import re - - -def parse_linespec(linespec, frame, result): - """Handles a subset of GDB-style linespecs. Specifically: - - number - A line in the current file - +offset - The line /offset/ lines after this line - -offset - The line /offset/ lines before this line - filename:number - Line /number/ in file /filename/ - function - The start of /function/ - *address - The pointer target of /address/, which must be a literal (but see `` in LLDB) - - We explicitly do not handle filename:function because it is ambiguous in Objective-C. - - This function returns a list of addresses.""" - - breakpoint = None - target = frame.GetThread().GetProcess().GetTarget() - - matched = False - - if (not matched): - mo = re.match("^([0-9]+)$", linespec) - if (mo is not None): - matched = True - # print "Matched <linenum>" - line_number = int(mo.group(1)) - line_entry = frame.GetLineEntry() - if not line_entry.IsValid(): - result.AppendMessage( - "Specified a line in the current file, but the current frame doesn't have line table information.") - return - breakpoint = target.BreakpointCreateByLocation( - line_entry.GetFileSpec(), line_number) - - if (not matched): - mo = re.match("^\+([0-9]+)$", linespec) - if (mo is not None): - matched = True - # print "Matched +<count>" - line_number = int(mo.group(1)) - line_entry = frame.GetLineEntry() - if not line_entry.IsValid(): - result.AppendMessage( - "Specified a line in the current file, but the current frame doesn't have line table information.") - return - breakpoint = target.BreakpointCreateByLocation( - line_entry.GetFileSpec(), (line_entry.GetLine() + line_number)) - - if (not matched): - mo = re.match("^\-([0-9]+)$", linespec) - if (mo is not None): - matched = True - # print "Matched -<count>" - line_number = int(mo.group(1)) - line_entry = frame.GetLineEntry() - if not line_entry.IsValid(): - result.AppendMessage( - "Specified a line in the current file, but the current frame doesn't have line table information.") - return - breakpoint = target.BreakpointCreateByLocation( - line_entry.GetFileSpec(), (line_entry.GetLine() - line_number)) - - if (not matched): - mo = re.match("^(.*):([0-9]+)$", linespec) - if (mo is not None): - matched = True - # print "Matched <filename>:<linenum>" - file_name = mo.group(1) - line_number = int(mo.group(2)) - breakpoint = target.BreakpointCreateByLocation( - file_name, line_number) - - if (not matched): - mo = re.match("\*((0x)?([0-9a-f]+))$", linespec) - if (mo is not None): - matched = True - # print "Matched <address-expression>" - address = long(mo.group(1), base=0) - breakpoint = target.BreakpointCreateByAddress(address) - - if (not matched): - # print "Trying <function-name>" - breakpoint = target.BreakpointCreateByName(linespec) - - num_locations = breakpoint.GetNumLocations() - - if (num_locations == 0): - result.AppendMessage( - "The line specification provided doesn't resolve to any addresses.") - - addr_list = [] - - for location_index in range(num_locations): - location = breakpoint.GetLocationAtIndex(location_index) - addr_list.append(location.GetAddress()) - - target.BreakpointDelete(breakpoint.GetID()) - - return addr_list - - -def usage_string(): - return """ Sets the program counter to a specific address. - -Syntax: jump <linespec> [<location-id>] - -Command Options Usage: - jump <linenum> - jump +<count> - jump -<count> - jump <filename>:<linenum> - jump <function-name> - jump *<address-expression> - -<location-id> serves to disambiguate when multiple locations could be meant.""" - - -def jump(debugger, command, result, internal_dict): - if (command == ""): - result.AppendMessage(usage_string()) - - args = command.split() - - if not debugger.IsValid(): - result.AppendMessage("Invalid debugger!") - return - - target = debugger.GetSelectedTarget() - if not target.IsValid(): - result.AppendMessage("jump requires a valid target.") - return - - process = target.GetProcess() - if not process.IsValid(): - result.AppendMessage("jump requires a valid process.") - return - - thread = process.GetSelectedThread() - if not thread.IsValid(): - result.AppendMessage("jump requires a valid thread.") - return - - frame = thread.GetSelectedFrame() - if not frame.IsValid(): - result.AppendMessage("jump requires a valid frame.") - return - - addresses = parse_linespec(args[0], frame, result) - - stream = lldb.SBStream() - - if len(addresses) == 0: - return - - desired_address = addresses[0] - - if len(addresses) > 1: - if len(args) == 2: - desired_index = int(args[1]) - if (desired_index >= 0) and (desired_index < len(addresses)): - desired_address = addresses[desired_index] - else: - result.AppendMessage( - "Desired index " + - args[1] + - " is not one of the options.") - return - else: - index = 0 - result.AppendMessage( - "The specified location resolves to multiple targets.") - for address in addresses: - stream.Clear() - address.GetDescription(stream) - result.AppendMessage( - " Location ID " + - str(index) + - ": " + - stream.GetData()) - index = index + 1 - result.AppendMessage( - "Please type 'jump " + - command + - " <location-id>' to choose one.") - return - - frame.SetPC(desired_address.GetLoadAddress(target)) - -if lldb.debugger: - # Module is being run inside the LLDB interpreter - jump.__doc__ = usage_string() - lldb.debugger.HandleCommand('command script add -f jump.jump jump') - print 'The "jump" command has been installed, type "help jump" or "jump <ENTER>" for detailed help.' diff --git a/examples/python/lldb_module_utils.py b/examples/python/lldb_module_utils.py deleted file mode 100644 index 006f232681f8..000000000000 --- a/examples/python/lldb_module_utils.py +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/python - -import lldb -import optparse -import shlex -import string -import sys - - -class DumpLineTables: - command_name = "dump-line-tables" - short_decription = "Dumps full paths to compile unit files and optionally all line table files." - 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.' - usage = "usage: %prog [options] MODULE1 [MODULE2 ...]" - def create_options(self): - self.parser = optparse.OptionParser( - description=self.description, - prog=self.command_name, - usage=self.usage) - - self.parser.add_option( - '-v', - '--verbose', - action='store_true', - dest='verbose', - help='Display verbose output.', - default=False) - - def get_short_help(self): - return self.short_decription - - def get_long_help(self): - return self.help_string - - def __init__(self, debugger, unused): - self.create_options() - self.help_string = self.parser.format_help() - - def __call__(self, debugger, command, exe_ctx, result): - # Use the Shell Lexer to properly parse up command options just like a - # shell would - command_args = shlex.split(command) - - try: - (options, args) = self.parser.parse_args(command_args) - except: - # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit - # (courtesy of OptParse dealing with argument errors by throwing SystemExit) - result.SetError("option parsing failed") - return - - # Always get program state from the SBExecutionContext passed in as exe_ctx - target = exe_ctx.GetTarget() - if not target.IsValid(): - result.SetError("invalid target") - return - - for module_path in args: - module = target.module[module_path] - if not module: - result.SetError('no module found that matches "%s".' % (module_path)) - return - num_cus = module.GetNumCompileUnits() - print >>result, 'Module: "%s"' % (module.file.fullpath), - if num_cus == 0: - print >>result, 'no debug info.' - continue - print >>result, 'has %u compile units:' % (num_cus) - for cu_idx in range(num_cus): - cu = module.GetCompileUnitAtIndex(cu_idx) - print >>result, ' Compile Unit: %s' % (cu.file.fullpath) - for line_idx in range(cu.GetNumLineEntries()): - line_entry = cu.GetLineEntryAtIndex(line_idx) - start_file_addr = line_entry.addr.file_addr - end_file_addr = line_entry.end_addr.file_addr - # If the two addresses are equal, this line table entry - # is a termination entry - if options.verbose: - if start_file_addr != end_file_addr: - result.PutCString( - ' [%#x - %#x): %s' % - (start_file_addr, end_file_addr, line_entry)) - else: - if start_file_addr == end_file_addr: - result.PutCString(' %#x: END' % - (start_file_addr)) - else: - result.PutCString( - ' %#x: %s' % - (start_file_addr, line_entry)) - if start_file_addr == end_file_addr: - result.PutCString("\n") - - -class DumpFiles: - command_name = "dump-files" - short_description = "Dumps full paths to compile unit files and optionally all line table files." - usage = "usage: %prog [options] MODULE1 [MODULE2 ...]" - description = '''This class adds a dump-files command to the LLDB interpreter. - -This command will dump all compile unit file paths found for each source file -for the binaries specified as arguments in the current target. Specify the ---support-files or -s option to see all file paths that a compile unit uses in -its lines tables. This is handy for troubleshooting why breakpoints aren't -working in IDEs that specify full paths to source files when setting file and -line breakpoints. Sometimes symlinks cause the debug info to contain the symlink -path and an IDE will resolve the path to the actual file and use the resolved -path when setting breakpoints. -''' - def create_options(self): - # Pass add_help_option = False, since this keeps the command in line with lldb commands, - # and we wire up "help command" to work by providing the long & short help methods below. - self.parser = optparse.OptionParser( - description = self.description, - prog = self.command_name, - usage = self.usage, - add_help_option = False) - - self.parser.add_option( - '-s', - '--support-files', - action = 'store_true', - dest = 'support_files', - help = 'Dumps full paths to all files used in a compile unit.', - default = False) - - def get_short_help(self): - return self.short_description - - def get_long_help(self): - return self.help_string - - def __init__(self, debugger, unused): - self.create_options() - self.help_string = self.parser.format_help() - - def __call__(self, debugger, command, exe_ctx, result): - # Use the Shell Lexer to properly parse up command options just like a - # shell would - command_args = shlex.split(command) - - try: - (options, args) = self.parser.parse_args(command_args) - except: - # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit - # (courtesy of OptParse dealing with argument errors by throwing SystemExit) - result.SetError("option parsing failed") - return - - # Always get program state from the SBExecutionContext passed in as exe_ctx - target = exe_ctx.GetTarget() - if not target.IsValid(): - result.SetError("invalid target") - return - - if len(args) == 0: - result.SetError("one or more executable paths must be specified") - return - - for module_path in args: - module = target.module[module_path] - if not module: - result.SetError('no module found that matches "%s".' % (module_path)) - return - num_cus = module.GetNumCompileUnits() - print >>result, 'Module: "%s"' % (module.file.fullpath), - if num_cus == 0: - print >>result, 'no debug info.' - continue - print >>result, 'has %u compile units:' % (num_cus) - for i in range(num_cus): - cu = module.GetCompileUnitAtIndex(i) - print >>result, ' Compile Unit: %s' % (cu.file.fullpath) - if options.support_files: - num_support_files = cu.GetNumSupportFiles() - for j in range(num_support_files): - path = cu.GetSupportFileAtIndex(j).fullpath - print >>result, ' file[%u]: %s' % (j, path) - - -def __lldb_init_module(debugger, dict): - # This initializer is being run from LLDB in the embedded command interpreter - - # Add any commands contained in this module to LLDB - debugger.HandleCommand( - 'command script add -c %s.DumpLineTables %s' % (__name__, - DumpLineTables.command_name)) - debugger.HandleCommand( - 'command script add -c %s.DumpFiles %s' % (__name__, DumpFiles.command_name)) - print 'The "%s" and "%s" commands have been installed.' % (DumpLineTables.command_name, - DumpFiles.command_name) diff --git a/examples/python/lldbtk.py b/examples/python/lldbtk.py deleted file mode 100644 index a978b9e07037..000000000000 --- a/examples/python/lldbtk.py +++ /dev/null @@ -1,613 +0,0 @@ -#!/usr/bin/python - -import lldb -import shlex -import sys -from Tkinter import * -import ttk - - -class ValueTreeItemDelegate(object): - - def __init__(self, value): - self.value = value - - def get_item_dictionary(self): - name = self.value.name - if name is None: - name = '' - typename = self.value.type - if typename is None: - typename = '' - value = self.value.value - if value is None: - value = '' - summary = self.value.summary - if summary is None: - summary = '' - has_children = self.value.MightHaveChildren() - return {'#0': name, - 'typename': typename, - 'value': value, - 'summary': summary, - 'children': has_children, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - for i in range(self.value.num_children): - item_delegate = ValueTreeItemDelegate( - self.value.GetChildAtIndex(i)) - item_dicts.append(item_delegate.get_item_dictionary()) - return item_dicts - - -class FrameTreeItemDelegate(object): - - def __init__(self, frame): - self.frame = frame - - def get_item_dictionary(self): - id = self.frame.GetFrameID() - name = 'frame #%u' % (id) - value = '0x%16.16x' % (self.frame.GetPC()) - stream = lldb.SBStream() - self.frame.GetDescription(stream) - summary = stream.GetData().split("`")[1] - return { - '#0': name, - 'value': value, - 'summary': summary, - 'children': self.frame.GetVariables( - True, - True, - True, - True).GetSize() > 0, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - variables = self.frame.GetVariables(True, True, True, True) - n = variables.GetSize() - for i in range(n): - item_delegate = ValueTreeItemDelegate(variables[i]) - item_dicts.append(item_delegate.get_item_dictionary()) - return item_dicts - - -class ThreadTreeItemDelegate(object): - - def __init__(self, thread): - self.thread = thread - - def get_item_dictionary(self): - num_frames = self.thread.GetNumFrames() - name = 'thread #%u' % (self.thread.GetIndexID()) - value = '0x%x' % (self.thread.GetThreadID()) - summary = '%u frames' % (num_frames) - return {'#0': name, - 'value': value, - 'summary': summary, - 'children': num_frames > 0, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - for frame in self.thread: - item_delegate = FrameTreeItemDelegate(frame) - item_dicts.append(item_delegate.get_item_dictionary()) - return item_dicts - - -class ProcessTreeItemDelegate(object): - - def __init__(self, process): - self.process = process - - def get_item_dictionary(self): - id = self.process.GetProcessID() - num_threads = self.process.GetNumThreads() - value = str(self.process.GetProcessID()) - summary = self.process.target.executable.fullpath - return {'#0': 'process', - 'value': value, - 'summary': summary, - 'children': num_threads > 0, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - for thread in self.process: - item_delegate = ThreadTreeItemDelegate(thread) - item_dicts.append(item_delegate.get_item_dictionary()) - return item_dicts - - -class TargetTreeItemDelegate(object): - - def __init__(self, target): - self.target = target - - def get_item_dictionary(self): - value = str(self.target.triple) - summary = self.target.executable.fullpath - return {'#0': 'target', - 'value': value, - 'summary': summary, - 'children': True, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - image_item_delegate = TargetImagesTreeItemDelegate(self.target) - item_dicts.append(image_item_delegate.get_item_dictionary()) - return item_dicts - - -class TargetImagesTreeItemDelegate(object): - - def __init__(self, target): - self.target = target - - def get_item_dictionary(self): - value = str(self.target.triple) - summary = self.target.executable.fullpath - num_modules = self.target.GetNumModules() - return {'#0': 'images', - 'value': '', - 'summary': '%u images' % num_modules, - 'children': num_modules > 0, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - for i in range(self.target.GetNumModules()): - module = self.target.GetModuleAtIndex(i) - image_item_delegate = ModuleTreeItemDelegate( - self.target, module, i) - item_dicts.append(image_item_delegate.get_item_dictionary()) - return item_dicts - - -class ModuleTreeItemDelegate(object): - - def __init__(self, target, module, index): - self.target = target - self.module = module - self.index = index - - def get_item_dictionary(self): - name = 'module %u' % (self.index) - value = self.module.file.basename - summary = self.module.file.dirname - return {'#0': name, - 'value': value, - 'summary': summary, - 'children': True, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - sections_item_delegate = ModuleSectionsTreeItemDelegate( - self.target, self.module) - item_dicts.append(sections_item_delegate.get_item_dictionary()) - - symbols_item_delegate = ModuleSymbolsTreeItemDelegate( - self.target, self.module) - item_dicts.append(symbols_item_delegate.get_item_dictionary()) - - comp_units_item_delegate = ModuleCompileUnitsTreeItemDelegate( - self.target, self.module) - item_dicts.append(comp_units_item_delegate.get_item_dictionary()) - return item_dicts - - -class ModuleSectionsTreeItemDelegate(object): - - def __init__(self, target, module): - self.target = target - self.module = module - - def get_item_dictionary(self): - name = 'sections' - value = '' - summary = '%u sections' % (self.module.GetNumSections()) - return {'#0': name, - 'value': value, - 'summary': summary, - 'children': True, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - num_sections = self.module.GetNumSections() - for i in range(num_sections): - section = self.module.GetSectionAtIndex(i) - image_item_delegate = SectionTreeItemDelegate(self.target, section) - item_dicts.append(image_item_delegate.get_item_dictionary()) - return item_dicts - - -class SectionTreeItemDelegate(object): - - def __init__(self, target, section): - self.target = target - self.section = section - - def get_item_dictionary(self): - name = self.section.name - section_load_addr = self.section.GetLoadAddress(self.target) - if section_load_addr != lldb.LLDB_INVALID_ADDRESS: - value = '0x%16.16x' % (section_load_addr) - else: - value = '0x%16.16x *' % (self.section.file_addr) - summary = '' - return {'#0': name, - 'value': value, - 'summary': summary, - 'children': self.section.GetNumSubSections() > 0, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - num_sections = self.section.GetNumSubSections() - for i in range(num_sections): - section = self.section.GetSubSectionAtIndex(i) - image_item_delegate = SectionTreeItemDelegate(self.target, section) - item_dicts.append(image_item_delegate.get_item_dictionary()) - return item_dicts - - -class ModuleCompileUnitsTreeItemDelegate(object): - - def __init__(self, target, module): - self.target = target - self.module = module - - def get_item_dictionary(self): - name = 'compile units' - value = '' - summary = '%u compile units' % (self.module.GetNumSections()) - return {'#0': name, - 'value': value, - 'summary': summary, - 'children': self.module.GetNumCompileUnits() > 0, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - num_cus = self.module.GetNumCompileUnits() - for i in range(num_cus): - cu = self.module.GetCompileUnitAtIndex(i) - image_item_delegate = CompileUnitTreeItemDelegate(self.target, cu) - item_dicts.append(image_item_delegate.get_item_dictionary()) - return item_dicts - - -class CompileUnitTreeItemDelegate(object): - - def __init__(self, target, cu): - self.target = target - self.cu = cu - - def get_item_dictionary(self): - name = self.cu.GetFileSpec().basename - value = '' - num_lines = self.cu.GetNumLineEntries() - summary = '' - return {'#0': name, - 'value': value, - 'summary': summary, - 'children': num_lines > 0, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - item_delegate = LineTableTreeItemDelegate(self.target, self.cu) - item_dicts.append(item_delegate.get_item_dictionary()) - return item_dicts - - -class LineTableTreeItemDelegate(object): - - def __init__(self, target, cu): - self.target = target - self.cu = cu - - def get_item_dictionary(self): - name = 'line table' - value = '' - num_lines = self.cu.GetNumLineEntries() - summary = '%u line entries' % (num_lines) - return {'#0': name, - 'value': value, - 'summary': summary, - 'children': num_lines > 0, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - num_lines = self.cu.GetNumLineEntries() - for i in range(num_lines): - line_entry = self.cu.GetLineEntryAtIndex(i) - item_delegate = LineEntryTreeItemDelegate( - self.target, line_entry, i) - item_dicts.append(item_delegate.get_item_dictionary()) - return item_dicts - - -class LineEntryTreeItemDelegate(object): - - def __init__(self, target, line_entry, index): - self.target = target - self.line_entry = line_entry - self.index = index - - def get_item_dictionary(self): - name = str(self.index) - address = self.line_entry.GetStartAddress() - load_addr = address.GetLoadAddress(self.target) - if load_addr != lldb.LLDB_INVALID_ADDRESS: - value = '0x%16.16x' % (load_addr) - else: - value = '0x%16.16x *' % (address.file_addr) - summary = self.line_entry.GetFileSpec().fullpath + ':' + \ - str(self.line_entry.line) - return {'#0': name, - 'value': value, - 'summary': summary, - 'children': False, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - return item_dicts - - -class InstructionTreeItemDelegate(object): - - def __init__(self, target, instr): - self.target = target - self.instr = instr - - def get_item_dictionary(self): - address = self.instr.GetAddress() - load_addr = address.GetLoadAddress(self.target) - if load_addr != lldb.LLDB_INVALID_ADDRESS: - name = '0x%16.16x' % (load_addr) - else: - name = '0x%16.16x *' % (address.file_addr) - value = self.instr.GetMnemonic( - self.target) + ' ' + self.instr.GetOperands(self.target) - summary = self.instr.GetComment(self.target) - return {'#0': name, - 'value': value, - 'summary': summary, - 'children': False, - 'tree-item-delegate': self} - - -class ModuleSymbolsTreeItemDelegate(object): - - def __init__(self, target, module): - self.target = target - self.module = module - - def get_item_dictionary(self): - name = 'symbols' - value = '' - summary = '%u symbols' % (self.module.GetNumSymbols()) - return {'#0': name, - 'value': value, - 'summary': summary, - 'children': True, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - num_symbols = self.module.GetNumSymbols() - for i in range(num_symbols): - symbol = self.module.GetSymbolAtIndex(i) - image_item_delegate = SymbolTreeItemDelegate( - self.target, symbol, i) - item_dicts.append(image_item_delegate.get_item_dictionary()) - return item_dicts - - -class SymbolTreeItemDelegate(object): - - def __init__(self, target, symbol, index): - self.target = target - self.symbol = symbol - self.index = index - - def get_item_dictionary(self): - address = self.symbol.GetStartAddress() - name = '[%u]' % self.index - symbol_load_addr = address.GetLoadAddress(self.target) - if symbol_load_addr != lldb.LLDB_INVALID_ADDRESS: - value = '0x%16.16x' % (symbol_load_addr) - else: - value = '0x%16.16x *' % (address.file_addr) - summary = self.symbol.name - return {'#0': name, - 'value': value, - 'summary': summary, - 'children': False, - 'tree-item-delegate': self} - - def get_child_item_dictionaries(self): - item_dicts = list() - return item_dicts - - -class DelegateTree(ttk.Frame): - - def __init__(self, column_dicts, delegate, title, name): - ttk.Frame.__init__(self, name=name) - self.pack(expand=Y, fill=BOTH) - self.master.title(title) - self.delegate = delegate - self.columns_dicts = column_dicts - self.item_id_to_item_dict = dict() - frame = Frame(self) - frame.pack(side=TOP, fill=BOTH, expand=Y) - self._create_treeview(frame) - self._populate_root() - - def _create_treeview(self, parent): - frame = ttk.Frame(parent) - frame.pack(side=TOP, fill=BOTH, expand=Y) - - column_ids = list() - for i in range(1, len(self.columns_dicts)): - column_ids.append(self.columns_dicts[i]['id']) - # create the tree and scrollbars - self.tree = ttk.Treeview(columns=column_ids) - - scroll_bar_v = ttk.Scrollbar(orient=VERTICAL, command=self.tree.yview) - scroll_bar_h = ttk.Scrollbar( - orient=HORIZONTAL, command=self.tree.xview) - self.tree['yscroll'] = scroll_bar_v.set - self.tree['xscroll'] = scroll_bar_h.set - - # setup column headings and columns properties - for columns_dict in self.columns_dicts: - self.tree.heading( - columns_dict['id'], - text=columns_dict['text'], - anchor=columns_dict['anchor']) - self.tree.column( - columns_dict['id'], - stretch=columns_dict['stretch']) - - # add tree and scrollbars to frame - self.tree.grid(in_=frame, row=0, column=0, sticky=NSEW) - scroll_bar_v.grid(in_=frame, row=0, column=1, sticky=NS) - scroll_bar_h.grid(in_=frame, row=1, column=0, sticky=EW) - - # set frame resizing priorities - frame.rowconfigure(0, weight=1) - frame.columnconfigure(0, weight=1) - - # action to perform when a node is expanded - self.tree.bind('<<TreeviewOpen>>', self._update_tree) - - def insert_items(self, parent_id, item_dicts): - for item_dict in item_dicts: - name = None - values = list() - first = True - for columns_dict in self.columns_dicts: - if first: - name = item_dict[columns_dict['id']] - first = False - else: - values.append(item_dict[columns_dict['id']]) - item_id = self.tree.insert(parent_id, # root item has an empty name - END, - text=name, - values=values) - self.item_id_to_item_dict[item_id] = item_dict - if item_dict['children']: - self.tree.insert(item_id, END, text='dummy') - - def _populate_root(self): - # use current directory as root node - self.insert_items('', self.delegate.get_child_item_dictionaries()) - - def _update_tree(self, event): - # user expanded a node - build the related directory - item_id = self.tree.focus() # the id of the expanded node - children = self.tree.get_children(item_id) - if len(children): - first_child = children[0] - # if the node only has a 'dummy' child, remove it and - # build new directory; skip if the node is already - # populated - if self.tree.item(first_child, option='text') == 'dummy': - self.tree.delete(first_child) - item_dict = self.item_id_to_item_dict[item_id] - item_dicts = item_dict[ - 'tree-item-delegate'].get_child_item_dictionaries() - self.insert_items(item_id, item_dicts) - - -@lldb.command("tk-variables") -def tk_variable_display(debugger, command, result, dict): - # needed for tree creation in TK library as it uses sys.argv... - sys.argv = ['tk-variables'] - target = debugger.GetSelectedTarget() - if not target: - print >>result, "invalid target" - return - process = target.GetProcess() - if not process: - print >>result, "invalid process" - return - thread = process.GetSelectedThread() - if not thread: - print >>result, "invalid thread" - return - frame = thread.GetSelectedFrame() - if not frame: - print >>result, "invalid frame" - return - # Parse command line args - command_args = shlex.split(command) - column_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0}, - {'id': 'typename', 'text': 'Type', 'anchor': W, 'stretch': 0}, - {'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0}, - {'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}] - tree = DelegateTree( - column_dicts, - FrameTreeItemDelegate(frame), - 'Variables', - 'lldb-tk-variables') - tree.mainloop() - - -@lldb.command("tk-process") -def tk_process_display(debugger, command, result, dict): - # needed for tree creation in TK library as it uses sys.argv... - sys.argv = ['tk-process'] - target = debugger.GetSelectedTarget() - if not target: - print >>result, "invalid target" - return - process = target.GetProcess() - if not process: - print >>result, "invalid process" - return - # Parse command line args - columnd_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0}, - {'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0}, - {'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}] - command_args = shlex.split(command) - tree = DelegateTree( - columnd_dicts, - ProcessTreeItemDelegate(process), - 'Process', - 'lldb-tk-process') - tree.mainloop() - - -@lldb.command("tk-target") -def tk_target_display(debugger, command, result, dict): - # needed for tree creation in TK library as it uses sys.argv... - sys.argv = ['tk-target'] - target = debugger.GetSelectedTarget() - if not target: - print >>result, "invalid target" - return - # Parse command line args - columnd_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0}, - {'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0}, - {'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}] - command_args = shlex.split(command) - tree = DelegateTree( - columnd_dicts, - TargetTreeItemDelegate(target), - 'Target', - 'lldb-tk-target') - tree.mainloop() diff --git a/examples/python/mach_o.py b/examples/python/mach_o.py deleted file mode 100755 index faa05ac83078..000000000000 --- a/examples/python/mach_o.py +++ /dev/null @@ -1,1845 +0,0 @@ -#!/usr/bin/python - -import cmd -import dict_utils -import file_extract -import optparse -import re -import struct -import string -import StringIO -import sys -import uuid - -# Mach header "magic" constants -MH_MAGIC = 0xfeedface -MH_CIGAM = 0xcefaedfe -MH_MAGIC_64 = 0xfeedfacf -MH_CIGAM_64 = 0xcffaedfe -FAT_MAGIC = 0xcafebabe -FAT_CIGAM = 0xbebafeca - -# Mach haeder "filetype" constants -MH_OBJECT = 0x00000001 -MH_EXECUTE = 0x00000002 -MH_FVMLIB = 0x00000003 -MH_CORE = 0x00000004 -MH_PRELOAD = 0x00000005 -MH_DYLIB = 0x00000006 -MH_DYLINKER = 0x00000007 -MH_BUNDLE = 0x00000008 -MH_DYLIB_STUB = 0x00000009 -MH_DSYM = 0x0000000a -MH_KEXT_BUNDLE = 0x0000000b - -# Mach haeder "flag" constant bits -MH_NOUNDEFS = 0x00000001 -MH_INCRLINK = 0x00000002 -MH_DYLDLINK = 0x00000004 -MH_BINDATLOAD = 0x00000008 -MH_PREBOUND = 0x00000010 -MH_SPLIT_SEGS = 0x00000020 -MH_LAZY_INIT = 0x00000040 -MH_TWOLEVEL = 0x00000080 -MH_FORCE_FLAT = 0x00000100 -MH_NOMULTIDEFS = 0x00000200 -MH_NOFIXPREBINDING = 0x00000400 -MH_PREBINDABLE = 0x00000800 -MH_ALLMODSBOUND = 0x00001000 -MH_SUBSECTIONS_VIA_SYMBOLS = 0x00002000 -MH_CANONICAL = 0x00004000 -MH_WEAK_DEFINES = 0x00008000 -MH_BINDS_TO_WEAK = 0x00010000 -MH_ALLOW_STACK_EXECUTION = 0x00020000 -MH_ROOT_SAFE = 0x00040000 -MH_SETUID_SAFE = 0x00080000 -MH_NO_REEXPORTED_DYLIBS = 0x00100000 -MH_PIE = 0x00200000 -MH_DEAD_STRIPPABLE_DYLIB = 0x00400000 -MH_HAS_TLV_DESCRIPTORS = 0x00800000 -MH_NO_HEAP_EXECUTION = 0x01000000 - -# Mach load command constants -LC_REQ_DYLD = 0x80000000 -LC_SEGMENT = 0x00000001 -LC_SYMTAB = 0x00000002 -LC_SYMSEG = 0x00000003 -LC_THREAD = 0x00000004 -LC_UNIXTHREAD = 0x00000005 -LC_LOADFVMLIB = 0x00000006 -LC_IDFVMLIB = 0x00000007 -LC_IDENT = 0x00000008 -LC_FVMFILE = 0x00000009 -LC_PREPAGE = 0x0000000a -LC_DYSYMTAB = 0x0000000b -LC_LOAD_DYLIB = 0x0000000c -LC_ID_DYLIB = 0x0000000d -LC_LOAD_DYLINKER = 0x0000000e -LC_ID_DYLINKER = 0x0000000f -LC_PREBOUND_DYLIB = 0x00000010 -LC_ROUTINES = 0x00000011 -LC_SUB_FRAMEWORK = 0x00000012 -LC_SUB_UMBRELLA = 0x00000013 -LC_SUB_CLIENT = 0x00000014 -LC_SUB_LIBRARY = 0x00000015 -LC_TWOLEVEL_HINTS = 0x00000016 -LC_PREBIND_CKSUM = 0x00000017 -LC_LOAD_WEAK_DYLIB = 0x00000018 | LC_REQ_DYLD -LC_SEGMENT_64 = 0x00000019 -LC_ROUTINES_64 = 0x0000001a -LC_UUID = 0x0000001b -LC_RPATH = 0x0000001c | LC_REQ_DYLD -LC_CODE_SIGNATURE = 0x0000001d -LC_SEGMENT_SPLIT_INFO = 0x0000001e -LC_REEXPORT_DYLIB = 0x0000001f | LC_REQ_DYLD -LC_LAZY_LOAD_DYLIB = 0x00000020 -LC_ENCRYPTION_INFO = 0x00000021 -LC_DYLD_INFO = 0x00000022 -LC_DYLD_INFO_ONLY = 0x00000022 | LC_REQ_DYLD -LC_LOAD_UPWARD_DYLIB = 0x00000023 | LC_REQ_DYLD -LC_VERSION_MIN_MACOSX = 0x00000024 -LC_VERSION_MIN_IPHONEOS = 0x00000025 -LC_FUNCTION_STARTS = 0x00000026 -LC_DYLD_ENVIRONMENT = 0x00000027 - -# Mach CPU constants -CPU_ARCH_MASK = 0xff000000 -CPU_ARCH_ABI64 = 0x01000000 -CPU_TYPE_ANY = 0xffffffff -CPU_TYPE_VAX = 1 -CPU_TYPE_MC680x0 = 6 -CPU_TYPE_I386 = 7 -CPU_TYPE_X86_64 = CPU_TYPE_I386 | CPU_ARCH_ABI64 -CPU_TYPE_MIPS = 8 -CPU_TYPE_MC98000 = 10 -CPU_TYPE_HPPA = 11 -CPU_TYPE_ARM = 12 -CPU_TYPE_MC88000 = 13 -CPU_TYPE_SPARC = 14 -CPU_TYPE_I860 = 15 -CPU_TYPE_ALPHA = 16 -CPU_TYPE_POWERPC = 18 -CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64 - -# VM protection constants -VM_PROT_READ = 1 -VM_PROT_WRITE = 2 -VM_PROT_EXECUTE = 4 - -# VM protection constants -N_STAB = 0xe0 -N_PEXT = 0x10 -N_TYPE = 0x0e -N_EXT = 0x01 - -# Values for nlist N_TYPE bits of the "Mach.NList.type" field. -N_UNDF = 0x0 -N_ABS = 0x2 -N_SECT = 0xe -N_PBUD = 0xc -N_INDR = 0xa - -# Section indexes for the "Mach.NList.sect_idx" fields -NO_SECT = 0 -MAX_SECT = 255 - -# Stab defines -N_GSYM = 0x20 -N_FNAME = 0x22 -N_FUN = 0x24 -N_STSYM = 0x26 -N_LCSYM = 0x28 -N_BNSYM = 0x2e -N_OPT = 0x3c -N_RSYM = 0x40 -N_SLINE = 0x44 -N_ENSYM = 0x4e -N_SSYM = 0x60 -N_SO = 0x64 -N_OSO = 0x66 -N_LSYM = 0x80 -N_BINCL = 0x82 -N_SOL = 0x84 -N_PARAMS = 0x86 -N_VERSION = 0x88 -N_OLEVEL = 0x8A -N_PSYM = 0xa0 -N_EINCL = 0xa2 -N_ENTRY = 0xa4 -N_LBRAC = 0xc0 -N_EXCL = 0xc2 -N_RBRAC = 0xe0 -N_BCOMM = 0xe2 -N_ECOMM = 0xe4 -N_ECOML = 0xe8 -N_LENG = 0xfe - -vm_prot_names = ['---', 'r--', '-w-', 'rw-', '--x', 'r-x', '-wx', 'rwx'] - - -def dump_memory(base_addr, data, hex_bytes_len, num_per_line): - hex_bytes = data.encode('hex') - if hex_bytes_len == -1: - hex_bytes_len = len(hex_bytes) - addr = base_addr - ascii_str = '' - i = 0 - while i < hex_bytes_len: - if ((i / 2) % num_per_line) == 0: - if i > 0: - print ' %s' % (ascii_str) - ascii_str = '' - print '0x%8.8x:' % (addr + i), - hex_byte = hex_bytes[i:i + 2] - print hex_byte, - int_byte = int(hex_byte, 16) - ascii_char = '%c' % (int_byte) - if int_byte >= 32 and int_byte < 127: - ascii_str += ascii_char - else: - ascii_str += '.' - i = i + 2 - if ascii_str: - if (i / 2) % num_per_line: - padding = num_per_line - ((i / 2) % num_per_line) - else: - padding = 0 - print '%*s%s' % (padding * 3 + 1, '', ascii_str) - print - - -class TerminalColors: - '''Simple terminal colors class''' - - def __init__(self, enabled=True): - # TODO: discover terminal type from "file" and disable if - # it can't handle the color codes - self.enabled = enabled - - def reset(self): - '''Reset all terminal colors and formatting.''' - if self.enabled: - return "\x1b[0m" - return '' - - def bold(self, on=True): - '''Enable or disable bold depending on the "on" parameter.''' - if self.enabled: - if on: - return "\x1b[1m" - else: - return "\x1b[22m" - return '' - - def italics(self, on=True): - '''Enable or disable italics depending on the "on" parameter.''' - if self.enabled: - if on: - return "\x1b[3m" - else: - return "\x1b[23m" - return '' - - def underline(self, on=True): - '''Enable or disable underline depending on the "on" parameter.''' - if self.enabled: - if on: - return "\x1b[4m" - else: - return "\x1b[24m" - return '' - - def inverse(self, on=True): - '''Enable or disable inverse depending on the "on" parameter.''' - if self.enabled: - if on: - return "\x1b[7m" - else: - return "\x1b[27m" - return '' - - def strike(self, on=True): - '''Enable or disable strike through depending on the "on" parameter.''' - if self.enabled: - if on: - return "\x1b[9m" - else: - return "\x1b[29m" - return '' - - def black(self, fg=True): - '''Set the foreground or background color to black. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[30m" - else: - return "\x1b[40m" - return '' - - def red(self, fg=True): - '''Set the foreground or background color to red. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[31m" - else: - return "\x1b[41m" - return '' - - def green(self, fg=True): - '''Set the foreground or background color to green. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[32m" - else: - return "\x1b[42m" - return '' - - def yellow(self, fg=True): - '''Set the foreground or background color to yellow. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[43m" - else: - return "\x1b[33m" - return '' - - def blue(self, fg=True): - '''Set the foreground or background color to blue. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[34m" - else: - return "\x1b[44m" - return '' - - def magenta(self, fg=True): - '''Set the foreground or background color to magenta. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[35m" - else: - return "\x1b[45m" - return '' - - def cyan(self, fg=True): - '''Set the foreground or background color to cyan. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[36m" - else: - return "\x1b[46m" - return '' - - def white(self, fg=True): - '''Set the foreground or background color to white. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[37m" - else: - return "\x1b[47m" - return '' - - def default(self, fg=True): - '''Set the foreground or background color to the default. - The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' - if self.enabled: - if fg: - return "\x1b[39m" - else: - return "\x1b[49m" - return '' - - -def swap_unpack_char(): - """Returns the unpack prefix that will for non-native endian-ness.""" - if struct.pack('H', 1).startswith("\x00"): - return '<' - return '>' - - -def dump_hex_bytes(addr, s, bytes_per_line=16): - i = 0 - line = '' - for ch in s: - if (i % bytes_per_line) == 0: - if line: - print line - line = '%#8.8x: ' % (addr + i) - line += "%02X " % ord(ch) - i += 1 - print line - - -def dump_hex_byte_string_diff(addr, a, b, bytes_per_line=16): - i = 0 - line = '' - a_len = len(a) - b_len = len(b) - if a_len < b_len: - max_len = b_len - else: - max_len = a_len - tty_colors = TerminalColors(True) - for i in range(max_len): - ch = None - if i < a_len: - ch_a = a[i] - ch = ch_a - else: - ch_a = None - if i < b_len: - ch_b = b[i] - if not ch: - ch = ch_b - else: - ch_b = None - mismatch = ch_a != ch_b - if (i % bytes_per_line) == 0: - if line: - print line - line = '%#8.8x: ' % (addr + i) - if mismatch: - line += tty_colors.red() - line += "%02X " % ord(ch) - if mismatch: - line += tty_colors.default() - i += 1 - - print line - - -class Mach: - """Class that does everything mach-o related""" - - class Arch: - """Class that implements mach-o architectures""" - - def __init__(self, c=0, s=0): - self.cpu = c - self.sub = s - - def set_cpu_type(self, c): - self.cpu = c - - def set_cpu_subtype(self, s): - self.sub = s - - def set_arch(self, c, s): - self.cpu = c - self.sub = s - - def is_64_bit(self): - return (self.cpu & CPU_ARCH_ABI64) != 0 - - cpu_infos = [ - ["arm", CPU_TYPE_ARM, CPU_TYPE_ANY], - ["arm", CPU_TYPE_ARM, 0], - ["armv4", CPU_TYPE_ARM, 5], - ["armv6", CPU_TYPE_ARM, 6], - ["armv5", CPU_TYPE_ARM, 7], - ["xscale", CPU_TYPE_ARM, 8], - ["armv7", CPU_TYPE_ARM, 9], - ["armv7f", CPU_TYPE_ARM, 10], - ["armv7s", CPU_TYPE_ARM, 11], - ["armv7k", CPU_TYPE_ARM, 12], - ["armv7m", CPU_TYPE_ARM, 15], - ["armv7em", CPU_TYPE_ARM, 16], - ["ppc", CPU_TYPE_POWERPC, CPU_TYPE_ANY], - ["ppc", CPU_TYPE_POWERPC, 0], - ["ppc601", CPU_TYPE_POWERPC, 1], - ["ppc602", CPU_TYPE_POWERPC, 2], - ["ppc603", CPU_TYPE_POWERPC, 3], - ["ppc603e", CPU_TYPE_POWERPC, 4], - ["ppc603ev", CPU_TYPE_POWERPC, 5], - ["ppc604", CPU_TYPE_POWERPC, 6], - ["ppc604e", CPU_TYPE_POWERPC, 7], - ["ppc620", CPU_TYPE_POWERPC, 8], - ["ppc750", CPU_TYPE_POWERPC, 9], - ["ppc7400", CPU_TYPE_POWERPC, 10], - ["ppc7450", CPU_TYPE_POWERPC, 11], - ["ppc970", CPU_TYPE_POWERPC, 100], - ["ppc64", CPU_TYPE_POWERPC64, 0], - ["ppc970-64", CPU_TYPE_POWERPC64, 100], - ["i386", CPU_TYPE_I386, 3], - ["i486", CPU_TYPE_I386, 4], - ["i486sx", CPU_TYPE_I386, 0x84], - ["i386", CPU_TYPE_I386, CPU_TYPE_ANY], - ["x86_64", CPU_TYPE_X86_64, 3], - ["x86_64", CPU_TYPE_X86_64, CPU_TYPE_ANY], - ] - - def __str__(self): - for info in self.cpu_infos: - if self.cpu == info[1] and (self.sub & 0x00ffffff) == info[2]: - return info[0] - return "{0}.{1}".format(self.cpu, self.sub) - - class Magic(dict_utils.Enum): - - enum = { - 'MH_MAGIC': MH_MAGIC, - 'MH_CIGAM': MH_CIGAM, - 'MH_MAGIC_64': MH_MAGIC_64, - 'MH_CIGAM_64': MH_CIGAM_64, - 'FAT_MAGIC': FAT_MAGIC, - 'FAT_CIGAM': FAT_CIGAM - } - - def __init__(self, initial_value=0): - dict_utils.Enum.__init__(self, initial_value, self.enum) - - def is_skinny_mach_file(self): - return self.value == MH_MAGIC or self.value == MH_CIGAM or self.value == MH_MAGIC_64 or self.value == MH_CIGAM_64 - - def is_universal_mach_file(self): - return self.value == FAT_MAGIC or self.value == FAT_CIGAM - - def unpack(self, data): - data.set_byte_order('native') - self.value = data.get_uint32() - - def get_byte_order(self): - if self.value == MH_CIGAM or self.value == MH_CIGAM_64 or self.value == FAT_CIGAM: - return swap_unpack_char() - else: - return '=' - - def is_64_bit(self): - return self.value == MH_MAGIC_64 or self.value == MH_CIGAM_64 - - def __init__(self): - self.magic = Mach.Magic() - self.content = None - self.path = None - - def extract(self, path, extractor): - self.path = path - self.unpack(extractor) - - def parse(self, path): - self.path = path - try: - f = open(self.path) - file_extractor = file_extract.FileExtract(f, '=') - self.unpack(file_extractor) - # f.close() - except IOError as xxx_todo_changeme: - (errno, strerror) = xxx_todo_changeme.args - print "I/O error({0}): {1}".format(errno, strerror) - except ValueError: - print "Could not convert data to an integer." - except: - print "Unexpected error:", sys.exc_info()[0] - raise - - def compare(self, rhs): - self.content.compare(rhs.content) - - def dump(self, options=None): - self.content.dump(options) - - def dump_header(self, dump_description=True, options=None): - self.content.dump_header(dump_description, options) - - def dump_load_commands(self, dump_description=True, options=None): - self.content.dump_load_commands(dump_description, options) - - def dump_sections(self, dump_description=True, options=None): - self.content.dump_sections(dump_description, options) - - def dump_section_contents(self, options): - self.content.dump_section_contents(options) - - def dump_symtab(self, dump_description=True, options=None): - self.content.dump_symtab(dump_description, options) - - def dump_symbol_names_matching_regex(self, regex, file=None): - self.content.dump_symbol_names_matching_regex(regex, file) - - def description(self): - return self.content.description() - - def unpack(self, data): - self.magic.unpack(data) - if self.magic.is_skinny_mach_file(): - self.content = Mach.Skinny(self.path) - elif self.magic.is_universal_mach_file(): - self.content = Mach.Universal(self.path) - else: - self.content = None - - if self.content is not None: - self.content.unpack(data, self.magic) - - def is_valid(self): - return self.content is not None - - class Universal: - - def __init__(self, path): - self.path = path - self.type = 'universal' - self.file_off = 0 - self.magic = None - self.nfat_arch = 0 - self.archs = list() - - def description(self): - s = '%#8.8x: %s (' % (self.file_off, self.path) - archs_string = '' - for arch in self.archs: - if len(archs_string): - archs_string += ', ' - archs_string += '%s' % arch.arch - s += archs_string - s += ')' - return s - - def unpack(self, data, magic=None): - self.file_off = data.tell() - if magic is None: - self.magic = Mach.Magic() - self.magic.unpack(data) - else: - self.magic = magic - self.file_off = self.file_off - 4 - # Universal headers are always in big endian - data.set_byte_order('big') - self.nfat_arch = data.get_uint32() - for i in range(self.nfat_arch): - self.archs.append(Mach.Universal.ArchInfo()) - self.archs[i].unpack(data) - for i in range(self.nfat_arch): - self.archs[i].mach = Mach.Skinny(self.path) - data.seek(self.archs[i].offset, 0) - skinny_magic = Mach.Magic() - skinny_magic.unpack(data) - self.archs[i].mach.unpack(data, skinny_magic) - - def compare(self, rhs): - print 'error: comparing two universal files is not supported yet' - return False - - def dump(self, options): - if options.dump_header: - print - print "Universal Mach File: magic = %s, nfat_arch = %u" % (self.magic, self.nfat_arch) - print - if self.nfat_arch > 0: - if options.dump_header: - self.archs[0].dump_header(True, options) - for i in range(self.nfat_arch): - self.archs[i].dump_flat(options) - if options.dump_header: - print - for i in range(self.nfat_arch): - self.archs[i].mach.dump(options) - - def dump_header(self, dump_description=True, options=None): - if dump_description: - print self.description() - for i in range(self.nfat_arch): - self.archs[i].mach.dump_header(True, options) - print - - def dump_load_commands(self, dump_description=True, options=None): - if dump_description: - print self.description() - for i in range(self.nfat_arch): - self.archs[i].mach.dump_load_commands(True, options) - print - - def dump_sections(self, dump_description=True, options=None): - if dump_description: - print self.description() - for i in range(self.nfat_arch): - self.archs[i].mach.dump_sections(True, options) - print - - def dump_section_contents(self, options): - for i in range(self.nfat_arch): - self.archs[i].mach.dump_section_contents(options) - print - - def dump_symtab(self, dump_description=True, options=None): - if dump_description: - print self.description() - for i in range(self.nfat_arch): - self.archs[i].mach.dump_symtab(True, options) - print - - def dump_symbol_names_matching_regex(self, regex, file=None): - for i in range(self.nfat_arch): - self.archs[i].mach.dump_symbol_names_matching_regex( - regex, file) - - class ArchInfo: - - def __init__(self): - self.arch = Mach.Arch(0, 0) - self.offset = 0 - self.size = 0 - self.align = 0 - self.mach = None - - def unpack(self, data): - # Universal headers are always in big endian - data.set_byte_order('big') - 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): - if options.verbose: - print "CPU SUBTYPE OFFSET SIZE ALIGN" - print "---------- ---------- ---------- ---------- ----------" - else: - print "ARCH FILEOFFSET FILESIZE ALIGN" - print "---------- ---------- ---------- ----------" - - def dump_flat(self, options): - 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) - else: - print "%-10s %#8.8x %#8.8x %#8.8x" % (self.arch, self.offset, self.size, self.align) - - def dump(self): - print " cputype: %#8.8x" % self.arch.cpu - print "cpusubtype: %#8.8x" % self.arch.sub - print " offset: %#8.8x" % self.offset - print " size: %#8.8x" % self.size - print " align: %#8.8x" % self.align - - 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) - - 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) - - class Flags: - - def __init__(self, b): - self.bits = b - - def __str__(self): - s = '' - if self.bits & MH_NOUNDEFS: - s += 'MH_NOUNDEFS | ' - if self.bits & MH_INCRLINK: - s += 'MH_INCRLINK | ' - if self.bits & MH_DYLDLINK: - s += 'MH_DYLDLINK | ' - if self.bits & MH_BINDATLOAD: - s += 'MH_BINDATLOAD | ' - if self.bits & MH_PREBOUND: - s += 'MH_PREBOUND | ' - if self.bits & MH_SPLIT_SEGS: - s += 'MH_SPLIT_SEGS | ' - if self.bits & MH_LAZY_INIT: - s += 'MH_LAZY_INIT | ' - if self.bits & MH_TWOLEVEL: - s += 'MH_TWOLEVEL | ' - if self.bits & MH_FORCE_FLAT: - s += 'MH_FORCE_FLAT | ' - if self.bits & MH_NOMULTIDEFS: - s += 'MH_NOMULTIDEFS | ' - if self.bits & MH_NOFIXPREBINDING: - s += 'MH_NOFIXPREBINDING | ' - if self.bits & MH_PREBINDABLE: - s += 'MH_PREBINDABLE | ' - if self.bits & MH_ALLMODSBOUND: - s += 'MH_ALLMODSBOUND | ' - if self.bits & MH_SUBSECTIONS_VIA_SYMBOLS: - s += 'MH_SUBSECTIONS_VIA_SYMBOLS | ' - if self.bits & MH_CANONICAL: - s += 'MH_CANONICAL | ' - if self.bits & MH_WEAK_DEFINES: - s += 'MH_WEAK_DEFINES | ' - if self.bits & MH_BINDS_TO_WEAK: - s += 'MH_BINDS_TO_WEAK | ' - if self.bits & MH_ALLOW_STACK_EXECUTION: - s += 'MH_ALLOW_STACK_EXECUTION | ' - if self.bits & MH_ROOT_SAFE: - s += 'MH_ROOT_SAFE | ' - if self.bits & MH_SETUID_SAFE: - s += 'MH_SETUID_SAFE | ' - if self.bits & MH_NO_REEXPORTED_DYLIBS: - s += 'MH_NO_REEXPORTED_DYLIBS | ' - if self.bits & MH_PIE: - s += 'MH_PIE | ' - if self.bits & MH_DEAD_STRIPPABLE_DYLIB: - s += 'MH_DEAD_STRIPPABLE_DYLIB | ' - if self.bits & MH_HAS_TLV_DESCRIPTORS: - s += 'MH_HAS_TLV_DESCRIPTORS | ' - if self.bits & MH_NO_HEAP_EXECUTION: - s += 'MH_NO_HEAP_EXECUTION | ' - # Strip the trailing " |" if we have any flags - if len(s) > 0: - s = s[0:-2] - return s - - class FileType(dict_utils.Enum): - - enum = { - 'MH_OBJECT': MH_OBJECT, - 'MH_EXECUTE': MH_EXECUTE, - 'MH_FVMLIB': MH_FVMLIB, - 'MH_CORE': MH_CORE, - 'MH_PRELOAD': MH_PRELOAD, - 'MH_DYLIB': MH_DYLIB, - 'MH_DYLINKER': MH_DYLINKER, - 'MH_BUNDLE': MH_BUNDLE, - 'MH_DYLIB_STUB': MH_DYLIB_STUB, - 'MH_DSYM': MH_DSYM, - 'MH_KEXT_BUNDLE': MH_KEXT_BUNDLE - } - - def __init__(self, initial_value=0): - dict_utils.Enum.__init__(self, initial_value, self.enum) - - class Skinny: - - def __init__(self, path): - self.path = path - self.type = 'skinny' - self.data = None - self.file_off = 0 - self.magic = 0 - self.arch = Mach.Arch(0, 0) - self.filetype = Mach.FileType(0) - self.ncmds = 0 - self.sizeofcmds = 0 - self.flags = Mach.Flags(0) - self.uuid = None - self.commands = list() - self.segments = list() - self.sections = list() - self.symbols = list() - self.sections.append(Mach.Section()) - - def description(self): - return '%#8.8x: %s (%s)' % (self.file_off, self.path, self.arch) - - def unpack(self, data, magic=None): - self.data = data - self.file_off = data.tell() - if magic is None: - self.magic = Mach.Magic() - self.magic.unpack(data) - else: - self.magic = magic - self.file_off = self.file_off - 4 - 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.flags.bits = bits - - if self.is_64_bit(): - data.get_uint32() # Skip reserved word in mach_header_64 - - for i in range(0, self.ncmds): - lc = self.unpack_load_command(data) - self.commands.append(lc) - - def get_data(self): - if self.data: - self.data.set_byte_order(self.magic.get_byte_order()) - return self.data - return None - - def unpack_load_command(self, data): - lc = Mach.LoadCommand() - lc.unpack(self, data) - lc_command = lc.command.get_enum_value() - if (lc_command == LC_SEGMENT or - lc_command == LC_SEGMENT_64): - lc = Mach.SegmentLoadCommand(lc) - lc.unpack(self, data) - elif (lc_command == LC_LOAD_DYLIB or - lc_command == LC_ID_DYLIB or - lc_command == LC_LOAD_WEAK_DYLIB or - lc_command == LC_REEXPORT_DYLIB): - lc = Mach.DylibLoadCommand(lc) - lc.unpack(self, data) - elif (lc_command == LC_LOAD_DYLINKER or - lc_command == LC_SUB_FRAMEWORK or - lc_command == LC_SUB_CLIENT or - lc_command == LC_SUB_UMBRELLA or - lc_command == LC_SUB_LIBRARY or - lc_command == LC_ID_DYLINKER or - lc_command == LC_RPATH): - lc = Mach.LoadDYLDLoadCommand(lc) - lc.unpack(self, data) - elif (lc_command == LC_DYLD_INFO_ONLY): - lc = Mach.DYLDInfoOnlyLoadCommand(lc) - lc.unpack(self, data) - elif (lc_command == LC_SYMTAB): - lc = Mach.SymtabLoadCommand(lc) - lc.unpack(self, data) - elif (lc_command == LC_DYSYMTAB): - lc = Mach.DYLDSymtabLoadCommand(lc) - lc.unpack(self, data) - elif (lc_command == LC_UUID): - lc = Mach.UUIDLoadCommand(lc) - lc.unpack(self, data) - elif (lc_command == LC_CODE_SIGNATURE or - lc_command == LC_SEGMENT_SPLIT_INFO or - lc_command == LC_FUNCTION_STARTS): - lc = Mach.DataBlobLoadCommand(lc) - lc.unpack(self, data) - elif (lc_command == LC_UNIXTHREAD): - lc = Mach.UnixThreadLoadCommand(lc) - lc.unpack(self, data) - elif (lc_command == LC_ENCRYPTION_INFO): - lc = Mach.EncryptionInfoLoadCommand(lc) - lc.unpack(self, data) - lc.skip(data) - return lc - - def compare(self, rhs): - print "\nComparing:" - print "a) %s %s" % (self.arch, self.path) - print "b) %s %s" % (rhs.arch, rhs.path) - result = True - if self.type == rhs.type: - for lhs_section in self.sections[1:]: - rhs_section = rhs.get_section_by_section(lhs_section) - if rhs_section: - print 'comparing %s.%s...' % (lhs_section.segname, lhs_section.sectname), - sys.stdout.flush() - lhs_data = lhs_section.get_contents(self) - rhs_data = rhs_section.get_contents(rhs) - if lhs_data and rhs_data: - if lhs_data == rhs_data: - print 'ok' - else: - lhs_data_len = len(lhs_data) - rhs_data_len = len(rhs_data) - # if lhs_data_len < rhs_data_len: - # if lhs_data == rhs_data[0:lhs_data_len]: - # print 'section data for %s matches the first %u bytes' % (lhs_section.sectname, lhs_data_len) - # else: - # # TODO: check padding - # result = False - # elif lhs_data_len > rhs_data_len: - # if lhs_data[0:rhs_data_len] == rhs_data: - # print 'section data for %s matches the first %u bytes' % (lhs_section.sectname, lhs_data_len) - # else: - # # TODO: check padding - # result = False - # else: - result = False - print 'error: sections differ' - # print 'a) %s' % (lhs_section) - # dump_hex_byte_string_diff(0, lhs_data, rhs_data) - # print 'b) %s' % (rhs_section) - # dump_hex_byte_string_diff(0, rhs_data, lhs_data) - elif lhs_data and not rhs_data: - print 'error: section data missing from b:' - print 'a) %s' % (lhs_section) - print 'b) %s' % (rhs_section) - result = False - elif not lhs_data and rhs_data: - print 'error: section data missing from a:' - print 'a) %s' % (lhs_section) - print 'b) %s' % (rhs_section) - result = False - elif lhs_section.offset or rhs_section.offset: - print 'error: section data missing for both a and b:' - print 'a) %s' % (lhs_section) - print 'b) %s' % (rhs_section) - result = False - else: - print 'ok' - else: - result = False - print 'error: section %s is missing in %s' % (lhs_section.sectname, rhs.path) - else: - print 'error: comaparing a %s mach-o file with a %s mach-o file is not supported' % (self.type, rhs.type) - result = False - if not result: - print 'error: mach files differ' - return result - - def dump_header(self, dump_description=True, options=None): - if options.verbose: - print "MAGIC CPU SUBTYPE FILETYPE NUM CMDS SIZE CMDS FLAGS" - print "---------- ---------- ---------- ---------- -------- ---------- ----------" - else: - print "MAGIC ARCH FILETYPE NUM CMDS SIZE CMDS FLAGS" - print "------------ ---------- -------------- -------- ---------- ----------" - - def dump_flat(self, options): - if options.verbose: - print "%#8.8x %#8.8x %#8.8x %#8.8x %#8u %#8.8x %#8.8x" % (self.magic, self.arch.cpu, self.arch.sub, self.filetype.value, self.ncmds, self.sizeofcmds, self.flags.bits) - else: - print "%-12s %-10s %-14s %#8u %#8.8x %s" % (self.magic, self.arch, self.filetype, self.ncmds, self.sizeofcmds, self.flags) - - def dump(self, options): - if options.dump_header: - self.dump_header(True, options) - if options.dump_load_commands: - self.dump_load_commands(False, options) - if options.dump_sections: - self.dump_sections(False, options) - if options.section_names: - self.dump_section_contents(options) - if options.dump_symtab: - self.get_symtab() - if len(self.symbols): - self.dump_sections(False, options) - else: - print "No symbols" - if options.find_mangled: - self.dump_symbol_names_matching_regex(re.compile('^_?_Z')) - - def dump_header(self, dump_description=True, options=None): - if dump_description: - print self.description() - print "Mach Header" - print " magic: %#8.8x %s" % (self.magic.value, self.magic) - print " cputype: %#8.8x %s" % (self.arch.cpu, self.arch) - print " cpusubtype: %#8.8x" % self.arch.sub - print " filetype: %#8.8x %s" % (self.filetype.get_enum_value(), self.filetype.get_enum_name()) - print " ncmds: %#8.8x %u" % (self.ncmds, self.ncmds) - print " sizeofcmds: %#8.8x" % self.sizeofcmds - print " flags: %#8.8x %s" % (self.flags.bits, self.flags) - - def dump_load_commands(self, dump_description=True, options=None): - if dump_description: - print self.description() - for lc in self.commands: - print lc - - def get_section_by_name(self, name): - for section in self.sections: - if section.sectname and section.sectname == name: - return section - return None - - def get_section_by_section(self, other_section): - for section in self.sections: - if section.sectname == other_section.sectname and section.segname == other_section.segname: - return section - return None - - def dump_sections(self, dump_description=True, options=None): - if dump_description: - print self.description() - num_sections = len(self.sections) - if num_sections > 1: - self.sections[1].dump_header() - for sect_idx in range(1, num_sections): - print "%s" % self.sections[sect_idx] - - def dump_section_contents(self, options): - saved_section_to_disk = False - for sectname in options.section_names: - section = self.get_section_by_name(sectname) - if section: - sect_bytes = section.get_contents(self) - if options.outfile: - if not saved_section_to_disk: - outfile = open(options.outfile, 'w') - if options.extract_modules: - # print "Extracting modules from mach file..." - data = file_extract.FileExtract( - StringIO.StringIO(sect_bytes), self.data.byte_order) - version = data.get_uint32() - num_modules = data.get_uint32() - # print "version = %u, num_modules = %u" % - # (version, num_modules) - for i in range(num_modules): - data_offset = data.get_uint64() - data_size = data.get_uint64() - name_offset = data.get_uint32() - language = data.get_uint32() - flags = data.get_uint32() - data.seek(name_offset) - 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) - data.seek(data_offset) - outfile.write(data.read_size(data_size)) - else: - print "Saving section %s to '%s'" % (sectname, options.outfile) - outfile.write(sect_bytes) - outfile.close() - saved_section_to_disk = True - else: - print "error: you can only save a single section to disk at a time, skipping section '%s'" % (sectname) - else: - print 'section %s:\n' % (sectname) - section.dump_header() - print '%s\n' % (section) - dump_memory(0, sect_bytes, options.max_count, 16) - else: - print 'error: no section named "%s" was found' % (sectname) - - def get_segment(self, segname): - if len(self.segments) == 1 and self.segments[0].segname == '': - return self.segments[0] - for segment in self.segments: - if segment.segname == segname: - return segment - return None - - def get_first_load_command(self, lc_enum_value): - for lc in self.commands: - if lc.command.value == lc_enum_value: - return lc - return None - - def get_symtab(self): - if self.data and not self.symbols: - lc_symtab = self.get_first_load_command(LC_SYMTAB) - if lc_symtab: - symtab_offset = self.file_off - if self.data.is_in_memory(): - linkedit_segment = self.get_segment('__LINKEDIT') - if linkedit_segment: - linkedit_vmaddr = linkedit_segment.vmaddr - linkedit_fileoff = linkedit_segment.fileoff - symtab_offset = linkedit_vmaddr + lc_symtab.symoff - linkedit_fileoff - symtab_offset = linkedit_vmaddr + lc_symtab.stroff - linkedit_fileoff - else: - symtab_offset += lc_symtab.symoff - - self.data.seek(symtab_offset) - is_64 = self.is_64_bit() - for i in range(lc_symtab.nsyms): - nlist = Mach.NList() - nlist.unpack(self, self.data, lc_symtab) - self.symbols.append(nlist) - else: - print "no LC_SYMTAB" - - def dump_symtab(self, dump_description=True, options=None): - self.get_symtab() - if dump_description: - print self.description() - for i, symbol in enumerate(self.symbols): - print '[%5u] %s' % (i, symbol) - - def dump_symbol_names_matching_regex(self, regex, file=None): - self.get_symtab() - for symbol in self.symbols: - if symbol.name and regex.search(symbol.name): - print symbol.name - if file: - file.write('%s\n' % (symbol.name)) - - def is_64_bit(self): - return self.magic.is_64_bit() - - class LoadCommand: - - class Command(dict_utils.Enum): - enum = { - 'LC_SEGMENT': LC_SEGMENT, - 'LC_SYMTAB': LC_SYMTAB, - 'LC_SYMSEG': LC_SYMSEG, - 'LC_THREAD': LC_THREAD, - 'LC_UNIXTHREAD': LC_UNIXTHREAD, - 'LC_LOADFVMLIB': LC_LOADFVMLIB, - 'LC_IDFVMLIB': LC_IDFVMLIB, - 'LC_IDENT': LC_IDENT, - 'LC_FVMFILE': LC_FVMFILE, - 'LC_PREPAGE': LC_PREPAGE, - 'LC_DYSYMTAB': LC_DYSYMTAB, - 'LC_LOAD_DYLIB': LC_LOAD_DYLIB, - 'LC_ID_DYLIB': LC_ID_DYLIB, - 'LC_LOAD_DYLINKER': LC_LOAD_DYLINKER, - 'LC_ID_DYLINKER': LC_ID_DYLINKER, - 'LC_PREBOUND_DYLIB': LC_PREBOUND_DYLIB, - 'LC_ROUTINES': LC_ROUTINES, - 'LC_SUB_FRAMEWORK': LC_SUB_FRAMEWORK, - 'LC_SUB_UMBRELLA': LC_SUB_UMBRELLA, - 'LC_SUB_CLIENT': LC_SUB_CLIENT, - 'LC_SUB_LIBRARY': LC_SUB_LIBRARY, - 'LC_TWOLEVEL_HINTS': LC_TWOLEVEL_HINTS, - 'LC_PREBIND_CKSUM': LC_PREBIND_CKSUM, - 'LC_LOAD_WEAK_DYLIB': LC_LOAD_WEAK_DYLIB, - 'LC_SEGMENT_64': LC_SEGMENT_64, - 'LC_ROUTINES_64': LC_ROUTINES_64, - 'LC_UUID': LC_UUID, - 'LC_RPATH': LC_RPATH, - 'LC_CODE_SIGNATURE': LC_CODE_SIGNATURE, - 'LC_SEGMENT_SPLIT_INFO': LC_SEGMENT_SPLIT_INFO, - 'LC_REEXPORT_DYLIB': LC_REEXPORT_DYLIB, - 'LC_LAZY_LOAD_DYLIB': LC_LAZY_LOAD_DYLIB, - 'LC_ENCRYPTION_INFO': LC_ENCRYPTION_INFO, - 'LC_DYLD_INFO': LC_DYLD_INFO, - 'LC_DYLD_INFO_ONLY': LC_DYLD_INFO_ONLY, - 'LC_LOAD_UPWARD_DYLIB': LC_LOAD_UPWARD_DYLIB, - 'LC_VERSION_MIN_MACOSX': LC_VERSION_MIN_MACOSX, - 'LC_VERSION_MIN_IPHONEOS': LC_VERSION_MIN_IPHONEOS, - 'LC_FUNCTION_STARTS': LC_FUNCTION_STARTS, - 'LC_DYLD_ENVIRONMENT': LC_DYLD_ENVIRONMENT - } - - def __init__(self, initial_value=0): - dict_utils.Enum.__init__(self, initial_value, self.enum) - - def __init__(self, c=None, l=0, o=0): - if c is not None: - self.command = c - else: - self.command = Mach.LoadCommand.Command(0) - self.length = l - self.file_off = o - - def unpack(self, mach_file, data): - self.file_off = data.tell() - self.command.value, self.length = data.get_n_uint32(2) - - def skip(self, data): - data.seek(self.file_off + self.length, 0) - - def __str__(self): - lc_name = self.command.get_enum_name() - return '%#8.8x: <%#4.4x> %-24s' % (self.file_off, - self.length, lc_name) - - class Section: - - def __init__(self): - self.index = 0 - self.is_64 = False - self.sectname = None - self.segname = None - self.addr = 0 - self.size = 0 - self.offset = 0 - self.align = 0 - self.reloff = 0 - self.nreloc = 0 - self.flags = 0 - self.reserved1 = 0 - self.reserved2 = 0 - self.reserved3 = 0 - - def unpack(self, is_64, data): - self.is_64 = is_64 - self.sectname = data.get_fixed_length_c_string(16, '', True) - self.segname = data.get_fixed_length_c_string(16, '', True) - if self.is_64: - 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) - else: - 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) - - def dump_header(self): - if self.is_64: - print "INDEX ADDRESS SIZE OFFSET ALIGN RELOFF NRELOC FLAGS RESERVED1 RESERVED2 RESERVED3 NAME" - print "===== ------------------ ------------------ ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------------" - else: - print "INDEX ADDRESS SIZE OFFSET ALIGN RELOFF NRELOC FLAGS RESERVED1 RESERVED2 NAME" - print "===== ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------------" - - def __str__(self): - 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) - 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) - - def get_contents(self, mach_file): - '''Get the section contents as a python string''' - if self.size > 0 and mach_file.get_segment( - self.segname).filesize > 0: - data = mach_file.get_data() - if data: - 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) - data.push_offset_and_seek(section_data_offset) - bytes = data.read_size(self.size) - data.pop_offset_and_seek() - return bytes - return None - - class DylibLoadCommand(LoadCommand): - - def __init__(self, lc): - Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) - self.name = None - self.timestamp = 0 - self.current_version = 0 - self.compatibility_version = 0 - - def unpack(self, mach_file, data): - byte_order_char = mach_file.magic.get_byte_order() - name_offset, self.timestamp, self.current_version, self.compatibility_version = data.get_n_uint32( - 4) - data.seek(self.file_off + name_offset, 0) - self.name = data.get_fixed_length_c_string(self.length - 24) - - def __str__(self): - s = Mach.LoadCommand.__str__(self) - s += "%#8.8x %#8.8x %#8.8x " % (self.timestamp, - self.current_version, - self.compatibility_version) - s += self.name - return s - - class LoadDYLDLoadCommand(LoadCommand): - - def __init__(self, lc): - Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) - self.name = None - - def unpack(self, mach_file, data): - data.get_uint32() - self.name = data.get_fixed_length_c_string(self.length - 12) - - def __str__(self): - s = Mach.LoadCommand.__str__(self) - s += "%s" % self.name - return s - - class UnixThreadLoadCommand(LoadCommand): - - class ThreadState: - - def __init__(self): - self.flavor = 0 - self.count = 0 - self.register_values = list() - - def unpack(self, data): - self.flavor, self.count = data.get_n_uint32(2) - self.register_values = data.get_n_uint32(self.count) - - def __str__(self): - s = "flavor = %u, count = %u, regs =" % ( - self.flavor, self.count) - i = 0 - for register_value in self.register_values: - if i % 8 == 0: - s += "\n " - s += " %#8.8x" % register_value - i += 1 - return s - - def __init__(self, lc): - Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) - self.reg_sets = list() - - def unpack(self, mach_file, data): - reg_set = Mach.UnixThreadLoadCommand.ThreadState() - reg_set.unpack(data) - self.reg_sets.append(reg_set) - - def __str__(self): - s = Mach.LoadCommand.__str__(self) - for reg_set in self.reg_sets: - s += "%s" % reg_set - return s - - class DYLDInfoOnlyLoadCommand(LoadCommand): - - def __init__(self, lc): - Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) - self.rebase_off = 0 - self.rebase_size = 0 - self.bind_off = 0 - self.bind_size = 0 - self.weak_bind_off = 0 - self.weak_bind_size = 0 - self.lazy_bind_off = 0 - self.lazy_bind_size = 0 - self.export_off = 0 - self.export_size = 0 - - def unpack(self, mach_file, data): - 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) - - def __str__(self): - s = Mach.LoadCommand.__str__(self) - s += "rebase_off = %#8.8x, rebase_size = %u, " % ( - self.rebase_off, self.rebase_size) - s += "bind_off = %#8.8x, bind_size = %u, " % ( - self.bind_off, self.bind_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 - - class DYLDSymtabLoadCommand(LoadCommand): - - def __init__(self, lc): - Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) - self.ilocalsym = 0 - self.nlocalsym = 0 - self.iextdefsym = 0 - self.nextdefsym = 0 - self.iundefsym = 0 - self.nundefsym = 0 - self.tocoff = 0 - self.ntoc = 0 - self.modtaboff = 0 - self.nmodtab = 0 - self.extrefsymoff = 0 - self.nextrefsyms = 0 - self.indirectsymoff = 0 - self.nindirectsyms = 0 - self.extreloff = 0 - self.nextrel = 0 - self.locreloff = 0 - self.nlocrel = 0 - - def unpack(self, mach_file, data): - 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) - - def __str__(self): - s = Mach.LoadCommand.__str__(self) - # s += "ilocalsym = %u, nlocalsym = %u, " % (self.ilocalsym, self.nlocalsym) - # s += "iextdefsym = %u, nextdefsym = %u, " % (self.iextdefsym, self.nextdefsym) - # s += "iundefsym %u, nundefsym = %u, " % (self.iundefsym, self.nundefsym) - # s += "tocoff = %#8.8x, ntoc = %u, " % (self.tocoff, self.ntoc) - # s += "modtaboff = %#8.8x, nmodtab = %u, " % (self.modtaboff, self.nmodtab) - # s += "extrefsymoff = %#8.8x, nextrefsyms = %u, " % (self.extrefsymoff, self.nextrefsyms) - # s += "indirectsymoff = %#8.8x, nindirectsyms = %u, " % (self.indirectsymoff, self.nindirectsyms) - # s += "extreloff = %#8.8x, nextrel = %u, " % (self.extreloff, self.nextrel) - # s += "locreloff = %#8.8x, nlocrel = %u" % (self.locreloff, - # self.nlocrel) - s += "ilocalsym = %-10u, nlocalsym = %u\n" % ( - self.ilocalsym, self.nlocalsym) - s += " iextdefsym = %-10u, nextdefsym = %u\n" % ( - self.iextdefsym, self.nextdefsym) - s += " iundefsym = %-10u, nundefsym = %u\n" % ( - self.iundefsym, self.nundefsym) - s += " tocoff = %#8.8x, ntoc = %u\n" % ( - 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 - - class SymtabLoadCommand(LoadCommand): - - def __init__(self, lc): - Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) - self.symoff = 0 - self.nsyms = 0 - self.stroff = 0 - self.strsize = 0 - - def unpack(self, mach_file, data): - byte_order_char = mach_file.magic.get_byte_order() - self.symoff, self.nsyms, self.stroff, self.strsize = data.get_n_uint32( - 4) - - def __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) - return s - - class UUIDLoadCommand(LoadCommand): - - def __init__(self, lc): - Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) - self.uuid = None - - def unpack(self, mach_file, data): - uuid_data = data.get_n_uint8(16) - uuid_str = '' - for byte in uuid_data: - uuid_str += '%2.2x' % byte - self.uuid = uuid.UUID(uuid_str) - mach_file.uuid = self.uuid - - def __str__(self): - s = Mach.LoadCommand.__str__(self) - s += self.uuid.__str__() - return s - - class DataBlobLoadCommand(LoadCommand): - - def __init__(self, lc): - Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) - self.dataoff = 0 - self.datasize = 0 - - def unpack(self, mach_file, data): - byte_order_char = mach_file.magic.get_byte_order() - self.dataoff, self.datasize = data.get_n_uint32(2) - - def __str__(self): - s = Mach.LoadCommand.__str__(self) - s += "dataoff = %#8.8x, datasize = %u" % ( - self.dataoff, self.datasize) - return s - - class EncryptionInfoLoadCommand(LoadCommand): - - def __init__(self, lc): - Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) - self.cryptoff = 0 - self.cryptsize = 0 - self.cryptid = 0 - - def unpack(self, mach_file, data): - byte_order_char = mach_file.magic.get_byte_order() - self.cryptoff, self.cryptsize, self.cryptid = data.get_n_uint32(3) - - def __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) - return s - - class SegmentLoadCommand(LoadCommand): - - def __init__(self, lc): - Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) - self.segname = None - self.vmaddr = 0 - self.vmsize = 0 - self.fileoff = 0 - self.filesize = 0 - self.maxprot = 0 - self.initprot = 0 - self.nsects = 0 - self.flags = 0 - - def unpack(self, mach_file, data): - is_64 = self.command.get_enum_value() == LC_SEGMENT_64 - self.segname = data.get_fixed_length_c_string(16, '', True) - if is_64: - self.vmaddr, self.vmsize, self.fileoff, self.filesize = data.get_n_uint64( - 4) - else: - self.vmaddr, self.vmsize, self.fileoff, self.filesize = data.get_n_uint32( - 4) - self.maxprot, self.initprot, self.nsects, self.flags = data.get_n_uint32( - 4) - mach_file.segments.append(self) - for i in range(self.nsects): - section = Mach.Section() - section.unpack(is_64, data) - section.index = len(mach_file.sections) - mach_file.sections.append(section) - - def __str__(self): - s = Mach.LoadCommand.__str__(self) - 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) - else: - s += "%#16.16x %#16.16x %#16.16x %#16.16x " % ( - 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 - return s - - class NList: - - class Type: - - class Stab(dict_utils.Enum): - enum = { - 'N_GSYM': N_GSYM, - 'N_FNAME': N_FNAME, - 'N_FUN': N_FUN, - 'N_STSYM': N_STSYM, - 'N_LCSYM': N_LCSYM, - 'N_BNSYM': N_BNSYM, - 'N_OPT': N_OPT, - 'N_RSYM': N_RSYM, - 'N_SLINE': N_SLINE, - 'N_ENSYM': N_ENSYM, - 'N_SSYM': N_SSYM, - 'N_SO': N_SO, - 'N_OSO': N_OSO, - 'N_LSYM': N_LSYM, - 'N_BINCL': N_BINCL, - 'N_SOL': N_SOL, - 'N_PARAMS': N_PARAMS, - 'N_VERSION': N_VERSION, - 'N_OLEVEL': N_OLEVEL, - 'N_PSYM': N_PSYM, - 'N_EINCL': N_EINCL, - 'N_ENTRY': N_ENTRY, - 'N_LBRAC': N_LBRAC, - 'N_EXCL': N_EXCL, - 'N_RBRAC': N_RBRAC, - 'N_BCOMM': N_BCOMM, - 'N_ECOMM': N_ECOMM, - 'N_ECOML': N_ECOML, - 'N_LENG': N_LENG - } - - def __init__(self, magic=0): - dict_utils.Enum.__init__(self, magic, self.enum) - - def __init__(self, t=0): - self.value = t - - def __str__(self): - n_type = self.value - if n_type & N_STAB: - stab = Mach.NList.Type.Stab(self.value) - return '%s' % stab - else: - type = self.value & N_TYPE - type_str = '' - if type == N_UNDF: - type_str = 'N_UNDF' - elif type == N_ABS: - type_str = 'N_ABS ' - elif type == N_SECT: - type_str = 'N_SECT' - elif type == N_PBUD: - type_str = 'N_PBUD' - elif type == N_INDR: - type_str = 'N_INDR' - else: - type_str = "??? (%#2.2x)" % type - if n_type & N_PEXT: - type_str += ' | PEXT' - if n_type & N_EXT: - type_str += ' | EXT ' - return type_str - - def __init__(self): - self.index = 0 - self.name_offset = 0 - self.name = 0 - self.type = Mach.NList.Type() - self.sect_idx = 0 - self.desc = 0 - self.value = 0 - - def unpack(self, mach_file, data, symtab_lc): - self.index = len(mach_file.symbols) - self.name_offset = data.get_uint32() - self.type.value, self.sect_idx = data.get_n_uint8(2) - self.desc = data.get_uint16() - if mach_file.is_64_bit(): - self.value = data.get_uint64() - else: - self.value = data.get_uint32() - data.push_offset_and_seek( - mach_file.file_off + - symtab_lc.stroff + - self.name_offset) - # print "get string for symbol[%u]" % self.index - self.name = data.get_c_string() - data.pop_offset_and_seek() - - def __str__(self): - name_display = '' - if len(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) - - class Interactive(cmd.Cmd): - '''Interactive command interpreter to mach-o files.''' - - def __init__(self, mach, options): - cmd.Cmd.__init__(self) - self.intro = 'Interactive mach-o command interpreter' - self.prompt = 'mach-o: %s %% ' % mach.path - self.mach = mach - self.options = options - - def default(self, line): - '''Catch all for unknown command, which will exit the interpreter.''' - print "uknown command: %s" % line - return True - - def do_q(self, line): - '''Quit command''' - return True - - def do_quit(self, line): - '''Quit command''' - return True - - def do_header(self, line): - '''Dump mach-o file headers''' - self.mach.dump_header(True, self.options) - return False - - def do_load(self, line): - '''Dump all mach-o load commands''' - self.mach.dump_load_commands(True, self.options) - return False - - def do_sections(self, line): - '''Dump all mach-o sections''' - self.mach.dump_sections(True, self.options) - return False - - def do_symtab(self, line): - '''Dump all mach-o symbols in the symbol table''' - self.mach.dump_symtab(True, self.options) - return False - -if __name__ == '__main__': - parser = optparse.OptionParser( - description='A script that parses skinny and universal mach-o files.') - parser.add_option( - '--arch', - '-a', - type='string', - metavar='arch', - dest='archs', - action='append', - help='specify one or more architectures by name') - parser.add_option( - '-v', - '--verbose', - 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() - if options.extract_modules: - if options.section_names: - print "error: can't use --section option with the --extract-modules option" - exit(1) - if not options.outfile: - print "error: the --output=FILE option must be specified with the --extract-modules option" - exit(1) - options.section_names.append("__apple_ast") - if options.compare: - if len(mach_files) == 2: - mach_a = Mach() - mach_b = Mach() - mach_a.parse(mach_files[0]) - mach_b.parse(mach_files[1]) - mach_a.compare(mach_b) - else: - print 'error: --compare takes two mach files as arguments' - else: - if not (options.dump_header or options.dump_load_commands or options.dump_symtab or options.dump_sections or options.find_mangled or options.section_names): - options.dump_header = True - options.dump_load_commands = True - if options.verbose: - print 'options', options - print 'mach_files', mach_files - for path in mach_files: - mach = Mach() - mach.parse(path) - if options.interactive: - interpreter = Mach.Interactive(mach, options) - interpreter.cmdloop() - else: - mach.dump(options) diff --git a/examples/python/memory.py b/examples/python/memory.py deleted file mode 100755 index 5e2f636dc3e6..000000000000 --- a/examples/python/memory.py +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/python - -#---------------------------------------------------------------------- -# Be sure to add the python path that points to the LLDB shared library. -# -# # To use this in the embedded python interpreter using "lldb" just -# import it with the full path using the "command script import" -# command -# (lldb) command script import /path/to/cmdtemplate.py -#---------------------------------------------------------------------- - -import commands -import platform -import os -import re -import sys - -try: - # Just try for LLDB in case PYTHONPATH is already correctly setup - import lldb -except ImportError: - lldb_python_dirs = list() - # lldb is not in the PYTHONPATH, try some defaults for the current platform - platform_system = platform.system() - if platform_system == 'Darwin': - # On Darwin, try the currently selected Xcode directory - xcode_dir = commands.getoutput("xcode-select --print-path") - if xcode_dir: - lldb_python_dirs.append( - os.path.realpath( - xcode_dir + - '/../SharedFrameworks/LLDB.framework/Resources/Python')) - lldb_python_dirs.append( - xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') - lldb_python_dirs.append( - '/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') - success = False - for lldb_python_dir in lldb_python_dirs: - if os.path.exists(lldb_python_dir): - if not (sys.path.__contains__(lldb_python_dir)): - sys.path.append(lldb_python_dir) - try: - import lldb - except ImportError: - pass - else: - print 'imported lldb from: "%s"' % (lldb_python_dir) - success = True - break - if not success: - print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly" - sys.exit(1) - -import commands -import optparse -import shlex -import string -import struct -import time - - -def append_data_callback(option, opt_str, value, parser): - if opt_str == "--uint8": - int8 = int(value, 0) - parser.values.data += struct.pack('1B', int8) - if opt_str == "--uint16": - int16 = int(value, 0) - parser.values.data += struct.pack('1H', int16) - if opt_str == "--uint32": - int32 = int(value, 0) - parser.values.data += struct.pack('1I', int32) - if opt_str == "--uint64": - int64 = int(value, 0) - parser.values.data += struct.pack('1Q', int64) - if opt_str == "--int8": - int8 = int(value, 0) - parser.values.data += struct.pack('1b', int8) - if opt_str == "--int16": - int16 = int(value, 0) - parser.values.data += struct.pack('1h', int16) - if opt_str == "--int32": - int32 = int(value, 0) - parser.values.data += struct.pack('1i', int32) - if opt_str == "--int64": - int64 = int(value, 0) - parser.values.data += struct.pack('1q', int64) - - -def create_memfind_options(): - usage = "usage: %prog [options] STARTADDR [ENDADDR]" - description = '''This command can find data in a specified address range. -Options are used to specify the data that is to be looked for and the options -can be specified multiple times to look for longer streams of data. -''' - parser = optparse.OptionParser( - description=description, - prog='memfind', - usage=usage) - parser.add_option( - '-s', - '--size', - type='int', - metavar='BYTESIZE', - dest='size', - help='Specify the byte size to search.', - default=0) - parser.add_option( - '--int8', - action="callback", - callback=append_data_callback, - type='string', - metavar='INT', - dest='data', - help='Specify a 8 bit signed integer value to search for in memory.', - default='') - parser.add_option( - '--int16', - action="callback", - callback=append_data_callback, - type='string', - metavar='INT', - dest='data', - help='Specify a 16 bit signed integer value to search for in memory.', - default='') - parser.add_option( - '--int32', - action="callback", - callback=append_data_callback, - type='string', - metavar='INT', - dest='data', - help='Specify a 32 bit signed integer value to search for in memory.', - default='') - parser.add_option( - '--int64', - action="callback", - callback=append_data_callback, - type='string', - metavar='INT', - dest='data', - help='Specify a 64 bit signed integer value to search for in memory.', - default='') - parser.add_option( - '--uint8', - action="callback", - callback=append_data_callback, - type='string', - metavar='INT', - dest='data', - help='Specify a 8 bit unsigned integer value to search for in memory.', - default='') - parser.add_option( - '--uint16', - action="callback", - callback=append_data_callback, - type='string', - metavar='INT', - dest='data', - help='Specify a 16 bit unsigned integer value to search for in memory.', - default='') - parser.add_option( - '--uint32', - action="callback", - callback=append_data_callback, - type='string', - metavar='INT', - dest='data', - help='Specify a 32 bit unsigned integer value to search for in memory.', - default='') - parser.add_option( - '--uint64', - action="callback", - callback=append_data_callback, - type='string', - metavar='INT', - dest='data', - help='Specify a 64 bit unsigned integer value to search for in memory.', - default='') - return parser - - -def memfind_command(debugger, command, result, dict): - # Use the Shell Lexer to properly parse up command options just like a - # shell would - command_args = shlex.split(command) - parser = create_memfind_options() - (options, args) = parser.parse_args(command_args) - # try: - # (options, args) = parser.parse_args(command_args) - # except: - # # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit - # # (courtesy of OptParse dealing with argument errors by throwing SystemExit) - # result.SetStatus (lldb.eReturnStatusFailed) - # print >>result, "error: option parsing failed" # returning a string is the same as returning an error whose description is the string - # return - memfind(debugger.GetSelectedTarget(), options, args, result) - - -def print_error(str, show_usage, result): - print >>result, str - if show_usage: - print >>result, create_memfind_options().format_help() - - -def memfind(target, options, args, result): - num_args = len(args) - start_addr = 0 - if num_args == 1: - if options.size > 0: - print_error( - "error: --size must be specified if there is no ENDADDR argument", - True, - result) - return - start_addr = int(args[0], 0) - elif num_args == 2: - if options.size != 0: - print_error( - "error: --size can't be specified with an ENDADDR argument", - True, - result) - return - start_addr = int(args[0], 0) - end_addr = int(args[1], 0) - if start_addr >= end_addr: - print_error( - "error: inavlid memory range [%#x - %#x)" % - (start_addr, end_addr), True, result) - return - options.size = end_addr - start_addr - else: - print_error("error: memfind takes 1 or 2 arguments", True, result) - return - - if not options.data: - print >>result, 'error: no data specified to search for' - return - - if not target: - print >>result, 'error: invalid target' - return - process = target.process - if not process: - print >>result, 'error: invalid process' - return - - error = lldb.SBError() - bytes = process.ReadMemory(start_addr, options.size, error) - if error.Success(): - num_matches = 0 - print >>result, "Searching memory range [%#x - %#x) for" % ( - start_addr, end_addr), - for byte in options.data: - print >>result, '%2.2x' % ord(byte), - print >>result - - match_index = string.find(bytes, options.data) - while match_index != -1: - num_matches = num_matches + 1 - print >>result, '%#x: %#x + %u' % (start_addr + - match_index, start_addr, match_index) - match_index = string.find(bytes, options.data, match_index + 1) - - if num_matches == 0: - print >>result, "error: no matches found" - else: - print >>result, 'error: %s' % (error.GetCString()) - - -if __name__ == '__main__': - print 'error: this script is designed to be used within the embedded script interpreter in LLDB' -elif getattr(lldb, 'debugger', None): - memfind_command.__doc__ = create_memfind_options().format_help() - lldb.debugger.HandleCommand( - 'command script add -f memory.memfind_command memfind') - print '"memfind" command installed, use the "--help" option for detailed help' diff --git a/examples/python/operating_system.py b/examples/python/operating_system.py deleted file mode 100644 index bfa13f0568ea..000000000000 --- a/examples/python/operating_system.py +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/python - -import lldb -import struct - - -class OperatingSystemPlugIn(object): - """Class that provides data for an instance of a LLDB 'OperatingSystemPython' plug-in class""" - - def __init__(self, process): - '''Initialization needs a valid.SBProcess object. - - This plug-in will get created after a live process is valid and has stopped for the - first time.''' - self.process = None - self.registers = None - self.threads = None - if isinstance(process, lldb.SBProcess) and process.IsValid(): - self.process = process - self.threads = None # Will be an dictionary containing info for each thread - - def get_target(self): - # NOTE: Don't use "lldb.target" when trying to get your target as the "lldb.target" - # tracks the current target in the LLDB command interpreter which isn't the - # correct thing to use for this plug-in. - return self.process.target - - def create_thread(self, tid, context): - if tid == 0x444444444: - thread_info = { - 'tid': tid, - 'name': 'four', - 'queue': 'queue4', - 'state': 'stopped', - 'stop_reason': 'none'} - self.threads.append(thread_info) - return thread_info - return None - - def get_thread_info(self): - if not self.threads: - # The sample dictionary below shows the values that can be returned for a thread - # tid => thread ID (mandatory) - # name => thread name (optional key/value pair) - # queue => thread dispatch queue name (optional key/value pair) - # state => thred state (mandatory, set to 'stopped' for now) - # stop_reason => thread stop reason. (mandatory, usually set to 'none') - # Possible values include: - # 'breakpoint' if the thread is stopped at a breakpoint - # 'none' thread is just stopped because the process is stopped - # 'trace' the thread just single stepped - # The usual value for this while threads are in memory is 'none' - # register_data_addr => the address of the register data in memory (optional key/value pair) - # Specifying this key/value pair for a thread will avoid a call to get_register_data() - # and can be used when your registers are in a thread context structure that is contiguous - # in memory. Don't specify this if your register layout in memory doesn't match the layout - # described by the dictionary returned from a call to the - # get_register_info() method. - self.threads = [{'tid': 0x111111111, - 'name': 'one', - 'queue': 'queue1', - 'state': 'stopped', - 'stop_reason': 'breakpoint'}, - {'tid': 0x222222222, - 'name': 'two', - 'queue': 'queue2', - 'state': 'stopped', - 'stop_reason': 'none'}, - {'tid': 0x333333333, - 'name': 'three', - 'queue': 'queue3', - 'state': 'stopped', - 'stop_reason': 'trace', - 'register_data_addr': 0x100000000}] - return self.threads - - def get_register_info(self): - if self.registers is None: - self.registers = dict() - triple = self.process.target.triple - if triple: - arch = triple.split('-')[0] - if arch == 'x86_64': - self.registers['sets'] = ['GPR', 'FPU', 'EXC'] - self.registers['registers'] = [ - {'name': 'rax', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0}, - {'name': 'rbx', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3}, - {'name': 'rcx', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg4', 'alt-name': 'arg4', }, - {'name': 'rdx', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg3', 'alt-name': 'arg3', }, - {'name': 'rdi', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg1', 'alt-name': 'arg1', }, - {'name': 'rsi', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg2', 'alt-name': 'arg2', }, - {'name': 'rbp', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'fp', 'alt-name': 'fp', }, - {'name': 'rsp', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'sp', 'alt-name': 'sp', }, - {'name': 'r8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8, 'generic': 'arg5', 'alt-name': 'arg5', }, - {'name': 'r9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9, 'generic': 'arg6', 'alt-name': 'arg6', }, - {'name': 'r10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10}, - {'name': 'r11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11}, - {'name': 'r12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12}, - {'name': 'r13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13}, - {'name': 'r14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14}, - {'name': 'r15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15}, - {'name': 'rip', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16, 'generic': 'pc', 'alt-name': 'pc'}, - {'name': 'rflags', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'generic': 'flags', 'alt-name': 'flags'}, - {'name': 'cs', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0}, - {'name': 'fs', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0}, - {'name': 'gs', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0}, - ] - return self.registers - - def get_register_data(self, tid): - if tid == 0x111111111: - return struct.pack( - '21Q', - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21) - 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) - 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) - 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) - 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 None diff --git a/examples/python/performance.py b/examples/python/performance.py deleted file mode 100755 index f1bc94f4b43a..000000000000 --- a/examples/python/performance.py +++ /dev/null @@ -1,392 +0,0 @@ -#!/usr/bin/python - -#---------------------------------------------------------------------- -# Be sure to add the python path that points to the LLDB shared library. -# On MacOSX csh, tcsh: -# setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python -# On MacOSX sh, bash: -# export PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python -#---------------------------------------------------------------------- - -import commands -import optparse -import os -import platform -import re -import resource -import sys -import time -import types - -#---------------------------------------------------------------------- -# Code that auto imports LLDB -#---------------------------------------------------------------------- -try: - # Just try for LLDB in case PYTHONPATH is already correctly setup - import lldb -except ImportError: - lldb_python_dirs = list() - # lldb is not in the PYTHONPATH, try some defaults for the current platform - platform_system = platform.system() - if platform_system == 'Darwin': - # On Darwin, try the currently selected Xcode directory - xcode_dir = commands.getoutput("xcode-select --print-path") - if xcode_dir: - lldb_python_dirs.append( - os.path.realpath( - xcode_dir + - '/../SharedFrameworks/LLDB.framework/Resources/Python')) - lldb_python_dirs.append( - xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') - lldb_python_dirs.append( - '/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') - success = False - for lldb_python_dir in lldb_python_dirs: - if os.path.exists(lldb_python_dir): - if not (sys.path.__contains__(lldb_python_dir)): - sys.path.append(lldb_python_dir) - try: - import lldb - except ImportError: - pass - else: - print 'imported lldb from: "%s"' % (lldb_python_dir) - success = True - break - if not success: - print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly" - sys.exit(1) - - -class Timer: - - def __enter__(self): - self.start = time.clock() - return self - - def __exit__(self, *args): - self.end = time.clock() - self.interval = self.end - self.start - - -class Action(object): - """Class that encapsulates actions to take when a thread stops for a reason.""" - - def __init__(self, callback=None, callback_owner=None): - self.callback = callback - self.callback_owner = callback_owner - - def ThreadStopped(self, thread): - assert False, "performance.Action.ThreadStopped(self, thread) must be overridden in a subclass" - - -class PlanCompleteAction (Action): - - def __init__(self, callback=None, callback_owner=None): - Action.__init__(self, callback, callback_owner) - - def ThreadStopped(self, thread): - if thread.GetStopReason() == lldb.eStopReasonPlanComplete: - if self.callback: - if self.callback_owner: - self.callback(self.callback_owner, thread) - else: - self.callback(thread) - return True - return False - - -class BreakpointAction (Action): - - def __init__( - self, - callback=None, - callback_owner=None, - name=None, - module=None, - file=None, - line=None, - breakpoint=None): - Action.__init__(self, callback, callback_owner) - self.modules = lldb.SBFileSpecList() - self.files = lldb.SBFileSpecList() - self.breakpoints = list() - # "module" can be a list or a string - if breakpoint: - self.breakpoints.append(breakpoint) - else: - if module: - if isinstance(module, types.ListType): - for module_path in module: - self.modules.Append( - lldb.SBFileSpec(module_path, False)) - elif isinstance(module, types.StringTypes): - self.modules.Append(lldb.SBFileSpec(module, False)) - if name: - # "file" can be a list or a string - if file: - if isinstance(file, types.ListType): - self.files = lldb.SBFileSpecList() - for f in file: - self.files.Append(lldb.SBFileSpec(f, False)) - elif isinstance(file, types.StringTypes): - self.files.Append(lldb.SBFileSpec(file, False)) - self.breakpoints.append( - self.target.BreakpointCreateByName( - name, self.modules, self.files)) - elif file and line: - self.breakpoints.append( - self.target.BreakpointCreateByLocation( - file, line)) - - def ThreadStopped(self, thread): - if thread.GetStopReason() == lldb.eStopReasonBreakpoint: - for bp in self.breakpoints: - if bp.GetID() == thread.GetStopReasonDataAtIndex(0): - if self.callback: - if self.callback_owner: - self.callback(self.callback_owner, thread) - else: - self.callback(thread) - return True - return False - - -class TestCase: - """Class that aids in running performance tests.""" - - def __init__(self): - self.verbose = False - self.debugger = lldb.SBDebugger.Create() - self.target = None - self.process = None - self.thread = None - self.launch_info = None - self.done = False - self.listener = self.debugger.GetListener() - self.user_actions = list() - self.builtin_actions = list() - self.bp_id_to_dict = dict() - - def Setup(self, args): - self.launch_info = lldb.SBLaunchInfo(args) - - def Run(self, args): - assert False, "performance.TestCase.Run(self, args) must be subclassed" - - def Launch(self): - if self.target: - error = lldb.SBError() - self.process = self.target.Launch(self.launch_info, error) - if not error.Success(): - print "error: %s" % error.GetCString() - if self.process: - self.process.GetBroadcaster().AddListener(self.listener, - lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitInterrupt) - return True - return False - - def WaitForNextProcessEvent(self): - event = None - if self.process: - while event is None: - process_event = lldb.SBEvent() - if self.listener.WaitForEvent(lldb.UINT32_MAX, process_event): - state = lldb.SBProcess.GetStateFromEvent(process_event) - if self.verbose: - print "event = %s" % (lldb.SBDebugger.StateAsCString(state)) - if lldb.SBProcess.GetRestartedFromEvent(process_event): - continue - if state == lldb.eStateInvalid or state == lldb.eStateDetached or state == lldb.eStateCrashed or state == lldb.eStateUnloaded or state == lldb.eStateExited: - event = process_event - self.done = True - elif state == lldb.eStateConnected or state == lldb.eStateAttaching or state == lldb.eStateLaunching or state == lldb.eStateRunning or state == lldb.eStateStepping or state == lldb.eStateSuspended: - continue - elif state == lldb.eStateStopped: - event = process_event - call_test_step = True - fatal = False - selected_thread = False - for thread in self.process: - frame = thread.GetFrameAtIndex(0) - select_thread = False - - stop_reason = thread.GetStopReason() - if self.verbose: - print "tid = %#x pc = %#x " % (thread.GetThreadID(), frame.GetPC()), - if stop_reason == lldb.eStopReasonNone: - if self.verbose: - print "none" - elif stop_reason == lldb.eStopReasonTrace: - select_thread = True - if self.verbose: - print "trace" - elif stop_reason == lldb.eStopReasonPlanComplete: - select_thread = True - if self.verbose: - print "plan complete" - elif stop_reason == lldb.eStopReasonThreadExiting: - if self.verbose: - print "thread exiting" - elif stop_reason == lldb.eStopReasonExec: - if self.verbose: - print "exec" - elif stop_reason == lldb.eStopReasonInvalid: - if self.verbose: - print "invalid" - elif stop_reason == lldb.eStopReasonException: - select_thread = True - if self.verbose: - print "exception" - fatal = True - elif stop_reason == lldb.eStopReasonBreakpoint: - select_thread = True - bp_id = thread.GetStopReasonDataAtIndex(0) - bp_loc_id = thread.GetStopReasonDataAtIndex(1) - if self.verbose: - print "breakpoint id = %d.%d" % (bp_id, bp_loc_id) - elif stop_reason == lldb.eStopReasonWatchpoint: - select_thread = True - if self.verbose: - print "watchpoint id = %d" % (thread.GetStopReasonDataAtIndex(0)) - elif stop_reason == lldb.eStopReasonSignal: - select_thread = True - if self.verbose: - print "signal %d" % (thread.GetStopReasonDataAtIndex(0)) - - if select_thread and not selected_thread: - self.thread = thread - selected_thread = self.process.SetSelectedThread( - thread) - - for action in self.user_actions: - action.ThreadStopped(thread) - - if fatal: - # if self.verbose: - # Xcode.RunCommand(self.debugger,"bt all",true) - sys.exit(1) - return event - - -class Measurement: - '''A class that encapsulates a measurement''' - - def __init__(self): - object.__init__(self) - - def Measure(self): - assert False, "performance.Measurement.Measure() must be subclassed" - - -class MemoryMeasurement(Measurement): - '''A class that can measure memory statistics for a process.''' - - def __init__(self, pid): - Measurement.__init__(self) - self.pid = pid - self.stats = [ - "rprvt", - "rshrd", - "rsize", - "vsize", - "vprvt", - "kprvt", - "kshrd", - "faults", - "cow", - "pageins"] - self.command = "top -l 1 -pid %u -stats %s" % ( - self.pid, ",".join(self.stats)) - self.value = dict() - - def Measure(self): - output = commands.getoutput(self.command).split("\n")[-1] - values = re.split('[-+\s]+', output) - for (idx, stat) in enumerate(values): - multiplier = 1 - if stat: - if stat[-1] == 'K': - multiplier = 1024 - stat = stat[:-1] - elif stat[-1] == 'M': - multiplier = 1024 * 1024 - stat = stat[:-1] - elif stat[-1] == 'G': - multiplier = 1024 * 1024 * 1024 - elif stat[-1] == 'T': - multiplier = 1024 * 1024 * 1024 * 1024 - stat = stat[:-1] - self.value[self.stats[idx]] = int(stat) * multiplier - - def __str__(self): - '''Dump the MemoryMeasurement current value''' - s = '' - for key in self.value.keys(): - if s: - s += "\n" - s += "%8s = %s" % (key, self.value[key]) - return s - - -class TesterTestCase(TestCase): - - def __init__(self): - TestCase.__init__(self) - self.verbose = True - self.num_steps = 5 - - def BreakpointHit(self, thread): - bp_id = thread.GetStopReasonDataAtIndex(0) - loc_id = thread.GetStopReasonDataAtIndex(1) - print "Breakpoint %i.%i hit: %s" % (bp_id, loc_id, thread.process.target.FindBreakpointByID(bp_id)) - thread.StepOver() - - def PlanComplete(self, thread): - if self.num_steps > 0: - thread.StepOver() - self.num_steps = self.num_steps - 1 - else: - thread.process.Kill() - - def Run(self, args): - self.Setup(args) - with Timer() as total_time: - self.target = self.debugger.CreateTarget(args[0]) - if self.target: - with Timer() as breakpoint_timer: - bp = self.target.BreakpointCreateByName("main") - print( - 'Breakpoint time = %.03f sec.' % - breakpoint_timer.interval) - - self.user_actions.append( - BreakpointAction( - breakpoint=bp, - callback=TesterTestCase.BreakpointHit, - callback_owner=self)) - self.user_actions.append( - PlanCompleteAction( - callback=TesterTestCase.PlanComplete, - callback_owner=self)) - - if self.Launch(): - while not self.done: - self.WaitForNextProcessEvent() - else: - print "error: failed to launch process" - else: - print "error: failed to create target with '%s'" % (args[0]) - print('Total time = %.03f sec.' % total_time.interval) - - -if __name__ == '__main__': - lldb.SBDebugger.Initialize() - test = TesterTestCase() - test.Run(sys.argv[1:]) - mem = MemoryMeasurement(os.getpid()) - mem.Measure() - print str(mem) - lldb.SBDebugger.Terminate() - # print "sleeeping for 100 seconds" - # time.sleep(100) diff --git a/examples/python/process_events.py b/examples/python/process_events.py deleted file mode 100755 index c93020a979f0..000000000000 --- a/examples/python/process_events.py +++ /dev/null @@ -1,417 +0,0 @@ -#!/usr/bin/python - -#---------------------------------------------------------------------- -# Be sure to add the python path that points to the LLDB shared library. -# On MacOSX csh, tcsh: -# setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python -# On MacOSX sh, bash: -# export PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python -#---------------------------------------------------------------------- - -import commands -import optparse -import os -import platform -import sys - -#---------------------------------------------------------------------- -# Code that auto imports LLDB -#---------------------------------------------------------------------- -try: - # Just try for LLDB in case PYTHONPATH is already correctly setup - import lldb -except ImportError: - lldb_python_dirs = list() - # lldb is not in the PYTHONPATH, try some defaults for the current platform - platform_system = platform.system() - if platform_system == 'Darwin': - # On Darwin, try the currently selected Xcode directory - xcode_dir = commands.getoutput("xcode-select --print-path") - if xcode_dir: - lldb_python_dirs.append( - os.path.realpath( - xcode_dir + - '/../SharedFrameworks/LLDB.framework/Resources/Python')) - lldb_python_dirs.append( - xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') - lldb_python_dirs.append( - '/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') - success = False - for lldb_python_dir in lldb_python_dirs: - if os.path.exists(lldb_python_dir): - if not (sys.path.__contains__(lldb_python_dir)): - sys.path.append(lldb_python_dir) - try: - import lldb - except ImportError: - pass - else: - print 'imported lldb from: "%s"' % (lldb_python_dir) - success = True - break - if not success: - print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly" - sys.exit(1) - - -def print_threads(process, options): - if options.show_threads: - for thread in process: - print '%s %s' % (thread, thread.GetFrameAtIndex(0)) - - -def run_commands(command_interpreter, commands): - return_obj = lldb.SBCommandReturnObject() - for command in commands: - command_interpreter.HandleCommand(command, return_obj) - if return_obj.Succeeded(): - print return_obj.GetOutput() - else: - print return_obj - if options.stop_on_error: - break - - -def main(argv): - description = '''Debugs a program using the LLDB python API and uses asynchronous broadcast events to watch for process state changes.''' - epilog = '''Examples: - -#---------------------------------------------------------------------- -# Run "/bin/ls" with the arguments "-lAF /tmp/", and set a breakpoint -# at "malloc" and backtrace and read all registers each time we stop -#---------------------------------------------------------------------- -% ./process_events.py --breakpoint malloc --stop-command bt --stop-command 'register read' -- /bin/ls -lAF /tmp/ - -''' - optparse.OptionParser.format_epilog = lambda self, formatter: self.epilog - parser = optparse.OptionParser( - description=description, - prog='process_events', - usage='usage: process_events [options] program [arg1 arg2]', - epilog=epilog) - parser.add_option( - '-v', - '--verbose', - action='store_true', - dest='verbose', - help="Enable verbose logging.", - default=False) - parser.add_option( - '-b', - '--breakpoint', - action='append', - type='string', - metavar='BPEXPR', - dest='breakpoints', - help='Breakpoint commands to create after the target has been created, the values will be sent to the "_regexp-break" command which supports breakpoints by name, file:line, and address.') - parser.add_option( - '-a', - '--arch', - type='string', - dest='arch', - help='The architecture to use when creating the debug target.', - default=None) - parser.add_option( - '--platform', - type='string', - metavar='platform', - dest='platform', - help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".', - default=None) - parser.add_option( - '-l', - '--launch-command', - action='append', - type='string', - metavar='CMD', - dest='launch_commands', - help='LLDB command interpreter commands to run once after the process has launched. This option can be specified more than once.', - default=[]) - parser.add_option( - '-s', - '--stop-command', - action='append', - type='string', - metavar='CMD', - dest='stop_commands', - help='LLDB command interpreter commands to run each time the process stops. This option can be specified more than once.', - default=[]) - parser.add_option( - '-c', - '--crash-command', - action='append', - type='string', - metavar='CMD', - dest='crash_commands', - help='LLDB command interpreter commands to run in case the process crashes. This option can be specified more than once.', - default=[]) - parser.add_option( - '-x', - '--exit-command', - action='append', - type='string', - metavar='CMD', - dest='exit_commands', - help='LLDB command interpreter commands to run once after the process has exited. This option can be specified more than once.', - default=[]) - parser.add_option( - '-T', - '--no-threads', - action='store_false', - dest='show_threads', - help="Don't show threads when process stops.", - default=True) - parser.add_option( - '--ignore-errors', - action='store_false', - dest='stop_on_error', - help="Don't stop executing LLDB commands if the command returns an error. This applies to all of the LLDB command interpreter commands that get run for launch, stop, crash and exit.", - default=True) - parser.add_option( - '-n', - '--run-count', - type='int', - dest='run_count', - metavar='N', - help='How many times to run the process in case the process exits.', - default=1) - parser.add_option( - '-t', - '--event-timeout', - type='int', - dest='event_timeout', - metavar='SEC', - help='Specify the timeout in seconds to wait for process state change events.', - default=lldb.UINT32_MAX) - parser.add_option( - '-e', - '--environment', - action='append', - type='string', - metavar='ENV', - dest='env_vars', - help='Environment variables to set in the inferior process when launching a process.') - parser.add_option( - '-d', - '--working-dir', - type='string', - metavar='DIR', - dest='working_dir', - help='The the current working directory when launching a process.', - default=None) - parser.add_option( - '-p', - '--attach-pid', - type='int', - dest='attach_pid', - metavar='PID', - help='Specify a process to attach to by process ID.', - default=-1) - parser.add_option( - '-P', - '--attach-name', - type='string', - dest='attach_name', - metavar='PROCESSNAME', - help='Specify a process to attach to by name.', - default=None) - parser.add_option( - '-w', - '--attach-wait', - action='store_true', - dest='attach_wait', - help='Wait for the next process to launch when attaching to a process by name.', - default=False) - try: - (options, args) = parser.parse_args(argv) - except: - return - - attach_info = None - launch_info = None - exe = None - if args: - exe = args.pop(0) - launch_info = lldb.SBLaunchInfo(args) - if options.env_vars: - launch_info.SetEnvironmentEntries(options.env_vars, True) - if options.working_dir: - launch_info.SetWorkingDirectory(options.working_dir) - elif options.attach_pid != -1: - if options.run_count == 1: - attach_info = lldb.SBAttachInfo(options.attach_pid) - else: - print "error: --run-count can't be used with the --attach-pid option" - sys.exit(1) - elif not options.attach_name is None: - if options.run_count == 1: - attach_info = lldb.SBAttachInfo( - options.attach_name, options.attach_wait) - else: - print "error: --run-count can't be used with the --attach-name option" - sys.exit(1) - else: - print 'error: a program path for a program to debug and its arguments are required' - sys.exit(1) - - # Create a new debugger instance - debugger = lldb.SBDebugger.Create() - debugger.SetAsync(True) - command_interpreter = debugger.GetCommandInterpreter() - # Create a target from a file and arch - - if exe: - print "Creating a target for '%s'" % exe - error = lldb.SBError() - target = debugger.CreateTarget( - exe, options.arch, options.platform, True, error) - - if target: - - # Set any breakpoints that were specified in the args if we are launching. We use the - # command line command to take advantage of the shorthand breakpoint - # creation - if launch_info and options.breakpoints: - for bp in options.breakpoints: - debugger.HandleCommand("_regexp-break %s" % (bp)) - run_commands(command_interpreter, ['breakpoint list']) - - for run_idx in range(options.run_count): - # Launch the process. Since we specified synchronous mode, we won't return - # from this function until we hit the breakpoint at main - error = lldb.SBError() - - if launch_info: - if options.run_count == 1: - print 'Launching "%s"...' % (exe) - else: - print 'Launching "%s"... (launch %u of %u)' % (exe, run_idx + 1, options.run_count) - - process = target.Launch(launch_info, error) - else: - if options.attach_pid != -1: - print 'Attaching to process %i...' % (options.attach_pid) - else: - if options.attach_wait: - print 'Waiting for next to process named "%s" to launch...' % (options.attach_name) - else: - print 'Attaching to existing process named "%s"...' % (options.attach_name) - process = target.Attach(attach_info, error) - - # Make sure the launch went ok - if process and process.GetProcessID() != lldb.LLDB_INVALID_PROCESS_ID: - - pid = process.GetProcessID() - print 'Process is %i' % (pid) - if attach_info: - # continue process if we attached as we won't get an - # initial event - process.Continue() - - listener = debugger.GetListener() - # sign up for process state change events - stop_idx = 0 - done = False - while not done: - event = lldb.SBEvent() - if listener.WaitForEvent(options.event_timeout, event): - if lldb.SBProcess.EventIsProcessEvent(event): - state = lldb.SBProcess.GetStateFromEvent(event) - if state == lldb.eStateInvalid: - # Not a state event - print 'process event = %s' % (event) - else: - print "process state changed event: %s" % (lldb.SBDebugger.StateAsCString(state)) - if state == lldb.eStateStopped: - if stop_idx == 0: - if launch_info: - print "process %u launched" % (pid) - run_commands( - command_interpreter, ['breakpoint list']) - else: - print "attached to process %u" % (pid) - for m in target.modules: - print m - if options.breakpoints: - for bp in options.breakpoints: - debugger.HandleCommand( - "_regexp-break %s" % (bp)) - run_commands( - command_interpreter, ['breakpoint list']) - run_commands( - command_interpreter, options.launch_commands) - else: - if options.verbose: - print "process %u stopped" % (pid) - run_commands( - command_interpreter, options.stop_commands) - stop_idx += 1 - print_threads(process, options) - print "continuing process %u" % (pid) - process.Continue() - elif state == lldb.eStateExited: - exit_desc = process.GetExitDescription() - if exit_desc: - print "process %u exited with status %u: %s" % (pid, process.GetExitStatus(), exit_desc) - else: - print "process %u exited with status %u" % (pid, process.GetExitStatus()) - run_commands( - command_interpreter, options.exit_commands) - done = True - elif state == lldb.eStateCrashed: - print "process %u crashed" % (pid) - print_threads(process, options) - run_commands( - command_interpreter, options.crash_commands) - done = True - elif state == lldb.eStateDetached: - print "process %u detached" % (pid) - done = True - elif state == lldb.eStateRunning: - # process is running, don't say anything, - # we will always get one of these after - # resuming - if options.verbose: - print "process %u resumed" % (pid) - elif state == lldb.eStateUnloaded: - print "process %u unloaded, this shouldn't happen" % (pid) - done = True - elif state == lldb.eStateConnected: - print "process connected" - elif state == lldb.eStateAttaching: - print "process attaching" - elif state == lldb.eStateLaunching: - print "process launching" - else: - print 'event = %s' % (event) - else: - # timeout waiting for an event - print "no process event for %u seconds, killing the process..." % (options.event_timeout) - done = True - # Now that we are done dump the stdout and stderr - process_stdout = process.GetSTDOUT(1024) - if process_stdout: - print "Process STDOUT:\n%s" % (process_stdout) - while process_stdout: - process_stdout = process.GetSTDOUT(1024) - print process_stdout - process_stderr = process.GetSTDERR(1024) - if process_stderr: - print "Process STDERR:\n%s" % (process_stderr) - while process_stderr: - process_stderr = process.GetSTDERR(1024) - print process_stderr - process.Kill() # kill the process - else: - if error: - print error - else: - if launch_info: - print 'error: launch failed' - else: - print 'error: attach failed' - - lldb.SBDebugger.Terminate() - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/examples/python/pytracer.py b/examples/python/pytracer.py deleted file mode 100644 index a166f21e9839..000000000000 --- a/examples/python/pytracer.py +++ /dev/null @@ -1,360 +0,0 @@ -import sys -import inspect -from collections import OrderedDict - - -class TracebackFancy: - - def __init__(self, traceback): - self.t = traceback - - def getFrame(self): - return FrameFancy(self.t.tb_frame) - - def getLineNumber(self): - return self.t.tb_lineno if self.t is not None else None - - def getNext(self): - return TracebackFancy(self.t.tb_next) - - def __str__(self): - if self.t is None: - return "" - str_self = "%s @ %s" % ( - self.getFrame().getName(), self.getLineNumber()) - return str_self + "\n" + self.getNext().__str__() - - -class ExceptionFancy: - - def __init__(self, frame): - self.etraceback = frame.f_exc_traceback - self.etype = frame.exc_type - self.evalue = frame.f_exc_value - - def __init__(self, tb, ty, va): - self.etraceback = tb - self.etype = ty - self.evalue = va - - def getTraceback(self): - return TracebackFancy(self.etraceback) - - def __nonzero__(self): - return self.etraceback is not None or self.etype is not None or self.evalue is not None - - def getType(self): - return str(self.etype) - - def getValue(self): - return self.evalue - - -class CodeFancy: - - def __init__(self, code): - self.c = code - - def getArgCount(self): - return self.c.co_argcount if self.c is not None else 0 - - def getFilename(self): - return self.c.co_filename if self.c is not None else "" - - def getVariables(self): - return self.c.co_varnames if self.c is not None else [] - - def getName(self): - return self.c.co_name if self.c is not None else "" - - def getFileName(self): - return self.c.co_filename if self.c is not None else "" - - -class ArgsFancy: - - def __init__(self, frame, arginfo): - self.f = frame - self.a = arginfo - - def __str__(self): - args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs() - ret = "" - count = 0 - size = len(args) - for arg in args: - ret = ret + ("%s = %s" % (arg, args[arg])) - count = count + 1 - if count < size: - ret = ret + ", " - if varargs: - if size > 0: - ret = ret + " " - ret = ret + "varargs are " + str(varargs) - if kwargs: - if size > 0: - ret = ret + " " - ret = ret + "kwargs are " + str(kwargs) - return ret - - def getNumArgs(wantVarargs=False, wantKWArgs=False): - args, varargs, keywords, values = self.a - size = len(args) - if varargs and wantVarargs: - size = size + len(self.getVarArgs()) - if keywords and wantKWArgs: - size = size + len(self.getKWArgs()) - return size - - def getArgs(self): - args, _, _, values = self.a - argWValues = OrderedDict() - for arg in args: - argWValues[arg] = values[arg] - return argWValues - - def getVarArgs(self): - _, vargs, _, _ = self.a - if vargs: - return self.f.f_locals[vargs] - return () - - def getKWArgs(self): - _, _, kwargs, _ = self.a - if kwargs: - return self.f.f_locals[kwargs] - return {} - - -class FrameFancy: - - def __init__(self, frame): - self.f = frame - - def getCaller(self): - return FrameFancy(self.f.f_back) - - def getLineNumber(self): - return self.f.f_lineno if self.f is not None else 0 - - def getCodeInformation(self): - return CodeFancy(self.f.f_code) if self.f is not None else None - - def getExceptionInfo(self): - return ExceptionFancy(self.f) if self.f is not None else None - - def getName(self): - return self.getCodeInformation().getName() if self.f is not None else "" - - def getFileName(self): - return self.getCodeInformation().getFileName() if self.f is not None else "" - - def getLocals(self): - return self.f.f_locals if self.f is not None else {} - - def getArgumentInfo(self): - return ArgsFancy( - self.f, inspect.getargvalues( - self.f)) if self.f is not None else None - - -class TracerClass: - - def callEvent(self, frame): - pass - - def lineEvent(self, frame): - pass - - def returnEvent(self, frame, retval): - pass - - def exceptionEvent(self, frame, exception, value, traceback): - pass - - def cCallEvent(self, frame, cfunct): - pass - - def cReturnEvent(self, frame, cfunct): - pass - - def cExceptionEvent(self, frame, cfunct): - pass - -tracer_impl = TracerClass() - - -def the_tracer_entrypoint(frame, event, args): - if tracer_impl is None: - return None - if event == "call": - call_retval = tracer_impl.callEvent(FrameFancy(frame)) - if not call_retval: - return None - return the_tracer_entrypoint - elif event == "line": - line_retval = tracer_impl.lineEvent(FrameFancy(frame)) - if not line_retval: - return None - return the_tracer_entrypoint - elif event == "return": - tracer_impl.returnEvent(FrameFancy(frame), args) - elif event == "exception": - exty, exva, extb = args - exception_retval = tracer_impl.exceptionEvent( - FrameFancy(frame), ExceptionFancy(extb, exty, exva)) - if not exception_retval: - return None - return the_tracer_entrypoint - elif event == "c_call": - tracer_impl.cCallEvent(FrameFancy(frame), args) - elif event == "c_return": - tracer_impl.cReturnEvent(FrameFancy(frame), args) - elif event == "c_exception": - tracer_impl.cExceptionEvent(FrameFancy(frame), args) - return None - - -def enable(t=None): - global tracer_impl - if t: - tracer_impl = t - sys.settrace(the_tracer_entrypoint) - - -def disable(): - sys.settrace(None) - - -class LoggingTracer: - - def callEvent(self, frame): - print "call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo()) - - def lineEvent(self, frame): - print "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals()) + " in " + frame.getFileName() - - def returnEvent(self, frame, retval): - print "return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals()) - - def exceptionEvent(self, frame, exception): - print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber()) - print "tb: " + str(exception.getTraceback()) - -# the same functionality as LoggingTracer, but with a little more -# lldb-specific smarts - - -class LLDBAwareTracer: - - def callEvent(self, frame): - if frame.getName() == "<module>": - return - if frame.getName() == "run_one_line": - print "call run_one_line(%s)" % (frame.getArgumentInfo().getArgs()["input_string"]) - return - if "Python.framework" in frame.getFileName(): - print "call into Python at " + frame.getName() - return - if frame.getName() == "__init__" and frame.getCaller().getName( - ) == "run_one_line" and frame.getCaller().getLineNumber() == 101: - return False - strout = "call " + frame.getName() - if (frame.getCaller().getFileName() == ""): - strout += " from LLDB - args are " - args = frame.getArgumentInfo().getArgs() - for arg in args: - if arg == "dict" or arg == "internal_dict": - continue - strout = strout + ("%s = %s " % (arg, args[arg])) - else: - strout += " from " + frame.getCaller().getName() + " @ " + \ - str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo()) - print strout - - def lineEvent(self, frame): - if frame.getName() == "<module>": - return - if frame.getName() == "run_one_line": - print "running run_one_line(%s) @ %s" % (frame.getArgumentInfo().getArgs()["input_string"], frame.getLineNumber()) - return - if "Python.framework" in frame.getFileName(): - print "running into Python at " + frame.getName() + " @ " + str(frame.getLineNumber()) - return - strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + \ - " locals are " - if (frame.getCaller().getFileName() == ""): - locals = frame.getLocals() - for local in locals: - if local == "dict" or local == "internal_dict": - continue - strout = strout + ("%s = %s " % (local, locals[local])) - else: - strout = strout + str(frame.getLocals()) - strout = strout + " in " + frame.getFileName() - print strout - - def returnEvent(self, frame, retval): - if frame.getName() == "<module>": - return - if frame.getName() == "run_one_line": - print "return from run_one_line(%s) return value is %s" % (frame.getArgumentInfo().getArgs()["input_string"], retval) - return - if "Python.framework" in frame.getFileName(): - print "return from Python at " + frame.getName() + " return value is " + str(retval) - return - strout = "return from " + frame.getName() + " return value is " + \ - str(retval) + " locals are " - if (frame.getCaller().getFileName() == ""): - locals = frame.getLocals() - for local in locals: - if local == "dict" or local == "internal_dict": - continue - strout = strout + ("%s = %s " % (local, locals[local])) - else: - strout = strout + str(frame.getLocals()) - strout = strout + " in " + frame.getFileName() - print strout - - def exceptionEvent(self, frame, exception): - if frame.getName() == "<module>": - return - print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber()) - print "tb: " + str(exception.getTraceback()) - - -def f(x, y=None): - if x > 0: - return 2 + f(x - 2) - return 35 - - -def g(x): - return 1.134 / x - - -def print_keyword_args(**kwargs): - # kwargs is a dict of the keyword args passed to the function - for key, value in kwargs.iteritems(): - print "%s = %s" % (key, value) - - -def total(initial=5, *numbers, **keywords): - count = initial - for number in numbers: - count += number - for key in keywords: - count += keywords[key] - return count - -if __name__ == "__main__": - enable(LoggingTracer()) - f(5) - f(5, 1) - print_keyword_args(first_name="John", last_name="Doe") - total(10, 1, 2, 3, vegetables=50, fruits=100) - try: - g(0) - except: - pass - disable() diff --git a/examples/python/sbvalue.py b/examples/python/sbvalue.py deleted file mode 100755 index 6e512998da2f..000000000000 --- a/examples/python/sbvalue.py +++ /dev/null @@ -1,268 +0,0 @@ -#!/usr/bin/python - -import lldb - - -class value(object): - '''A class that wraps an lldb.SBValue object and returns an object that - can be used as an object with attribytes:\n - argv = a.value(lldb.frame.FindVariable('argv'))\n - argv.name - return the name of the value that this object contains\n - argv.type - return the lldb.SBType for this value - argv.type_name - return the name of the type - argv.size - return the byte size of this value - argv.is_in_scope - return true if this value is currently in scope - argv.is_pointer - return true if this value is a pointer - argv.format - return the current format for this value - argv.value - return the value's value as a string - argv.summary - return a summary of this value's value - argv.description - return the runtime description for this value - argv.location - return a string that represents the values location (address, register, etc) - argv.target - return the lldb.SBTarget for this value - argv.process - return the lldb.SBProcess for this value - argv.thread - return the lldb.SBThread for this value - argv.frame - return the lldb.SBFrame for this value - argv.num_children - return the number of children this value has - argv.children - return a list of sbvalue objects that represents all of the children of this value - ''' - - def __init__(self, sbvalue): - self.sbvalue = sbvalue - - def __nonzero__(self): - return self.sbvalue.__nonzero__() - - def __repr__(self): - return self.sbvalue.__repr__() - - def __str__(self): - return self.sbvalue.__str__() - - def __getitem__(self, key): - if isinstance(key, int): - return value( - self.sbvalue.GetChildAtIndex( - key, lldb.eNoDynamicValues, True)) - raise TypeError - - def __getattr__(self, name): - if name == 'name': - return self.sbvalue.GetName() - if name == 'type': - return self.sbvalue.GetType() - if name == 'type_name': - return self.sbvalue.GetTypeName() - if name == 'size': - return self.sbvalue.GetByteSize() - if name == 'is_in_scope': - return self.sbvalue.IsInScope() - if name == 'is_pointer': - return self.sbvalue.TypeIsPointerType() - if name == 'format': - return self.sbvalue.GetFormat() - if name == 'value': - return self.sbvalue.GetValue() - if name == 'summary': - return self.sbvalue.GetSummary() - if name == 'description': - return self.sbvalue.GetObjectDescription() - if name == 'location': - return self.sbvalue.GetLocation() - if name == 'target': - return self.sbvalue.GetTarget() - if name == 'process': - return self.sbvalue.GetProcess() - if name == 'thread': - return self.sbvalue.GetThread() - if name == 'frame': - return self.sbvalue.GetFrame() - if name == 'num_children': - return self.sbvalue.GetNumChildren() - if name == 'children': - # Returns an array of sbvalue objects, one for each child of - # the value for the lldb.SBValue - children = [] - for i in range(self.sbvalue.GetNumChildren()): - children.append( - value( - self.sbvalue.GetChildAtIndex( - i, - lldb.eNoDynamicValues, - True))) - return children - raise AttributeError - - -class variable(object): - '''A class that treats a lldb.SBValue and allows it to be used just as - a variable would be in code. So if you have a Point structure variable - in your code, you would be able to do: "pt.x + pt.y"''' - - def __init__(self, sbvalue): - self.sbvalue = sbvalue - - def __nonzero__(self): - return self.sbvalue.__nonzero__() - - def __repr__(self): - return self.sbvalue.__repr__() - - def __str__(self): - return self.sbvalue.__str__() - - def __getitem__(self, key): - # Allow array access if this value has children... - if isinstance(key, int): - return variable( - self.sbvalue.GetValueForExpressionPath( - "[%i]" % - key)) - raise TypeError - - def __getattr__(self, name): - child_sbvalue = self.sbvalue.GetChildMemberWithName(name) - if child_sbvalue: - return variable(child_sbvalue) - raise AttributeError - - def __add__(self, other): - return int(self) + int(other) - - def __sub__(self, other): - return int(self) - int(other) - - def __mul__(self, other): - return int(self) * int(other) - - def __floordiv__(self, other): - return int(self) // int(other) - - def __mod__(self, other): - return int(self) % int(other) - - def __divmod__(self, other): - return int(self) % int(other) - - def __pow__(self, other): - return int(self) ** int(other) - - def __lshift__(self, other): - return int(self) << int(other) - - def __rshift__(self, other): - return int(self) >> int(other) - - def __and__(self, other): - return int(self) & int(other) - - def __xor__(self, other): - return int(self) ^ int(other) - - def __or__(self, other): - return int(self) | int(other) - - def __div__(self, other): - return int(self) / int(other) - - def __truediv__(self, other): - return int(self) / int(other) - - def __iadd__(self, other): - result = self.__add__(other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __isub__(self, other): - result = self.__sub__(other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __imul__(self, other): - result = self.__mul__(other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __idiv__(self, other): - result = self.__div__(other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __itruediv__(self, other): - result = self.__truediv__(other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __ifloordiv__(self, other): - result = self.__floordiv__(self, other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __imod__(self, other): - result = self.__and__(self, other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __ipow__(self, other): - result = self.__pow__(self, other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __ipow__(self, other, modulo): - result = self.__pow__(self, other, modulo) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __ilshift__(self, other): - result = self.__lshift__(self, other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __irshift__(self, other): - result = self.__rshift__(self, other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __iand__(self, other): - result = self.__and__(self, other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __ixor__(self, other): - result = self.__xor__(self, other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __ior__(self, other): - result = self.__ior__(self, other) - self.sbvalue.SetValueFromCString(str(result)) - return result - - def __neg__(self): - return -int(self) - - def __pos__(self): - return +int(self) - - def __abs__(self): - return abs(int(self)) - - def __invert__(self): - return ~int(self) - - def __complex__(self): - return complex(int(self)) - - def __int__(self): - return self.sbvalue.GetValueAsSigned() - - def __long__(self): - return self.sbvalue.GetValueAsSigned() - - def __float__(self): - return float(self.sbvalue.GetValueAsSigned()) - - def __oct__(self): - return '0%o' % self.sbvalue.GetValueAsSigned() - - def __hex__(self): - return '0x%x' % self.sbvalue.GetValueAsSigned() diff --git a/examples/python/scripted_step.py b/examples/python/scripted_step.py deleted file mode 100644 index 453b5e229fb4..000000000000 --- a/examples/python/scripted_step.py +++ /dev/null @@ -1,244 +0,0 @@ -############################################################################# -# This script contains two trivial examples of simple "scripted step" classes. -# To fully understand how the lldb "Thread Plan" architecture works, read the -# comments at the beginning of ThreadPlan.h in the lldb sources. The python -# interface is a reduced version of the full internal mechanism, but captures -# most of the power with a much simpler interface. -# -# But I'll attempt a brief summary here. -# Stepping in lldb is done independently for each thread. Moreover, the stepping -# operations are stackable. So for instance if you did a "step over", and in -# the course of stepping over you hit a breakpoint, stopped and stepped again, -# the first "step-over" would be suspended, and the new step operation would -# be enqueued. Then if that step over caused the program to hit another breakpoint, -# lldb would again suspend the second step and return control to the user, so -# now there are two pending step overs. Etc. with all the other stepping -# operations. Then if you hit "continue" the bottom-most step-over would complete, -# and another continue would complete the first "step-over". -# -# lldb represents this system with a stack of "Thread Plans". Each time a new -# stepping operation is requested, a new plan is pushed on the stack. When the -# operation completes, it is pushed off the stack. -# -# The bottom-most plan in the stack is the immediate controller of stepping, -# most importantly, when the process resumes, the bottom most plan will get -# asked whether to set the program running freely, or to instruction-single-step -# the current thread. In the scripted interface, you indicate this by returning -# False or True respectively from the should_step method. -# -# Each time the process stops the thread plan stack for each thread that stopped -# "for a reason", Ii.e. a single-step completed on that thread, or a breakpoint -# was hit), is queried to determine how to proceed, starting from the most -# recently pushed plan, in two stages: -# -# 1) Each plan is asked if it "explains" the stop. The first plan to claim the -# stop wins. In scripted Thread Plans, this is done by returning True from -# the "explains_stop method. This is how, for instance, control is returned -# to the User when the "step-over" plan hits a breakpoint. The step-over -# plan doesn't explain the breakpoint stop, so it returns false, and the -# breakpoint hit is propagated up the stack to the "base" thread plan, which -# is the one that handles random breakpoint hits. -# -# 2) Then the plan that won the first round is asked if the process should stop. -# This is done in the "should_stop" method. The scripted plans actually do -# three jobs in should_stop: -# a) They determine if they have completed their job or not. If they have -# they indicate that by calling SetPlanComplete on their thread plan. -# b) They decide whether they want to return control to the user or not. -# They do this by returning True or False respectively. -# c) If they are not done, they set up whatever machinery they will use -# the next time the thread continues. -# -# Note that deciding to return control to the user, and deciding your plan -# is done, are orthgonal operations. You could set up the next phase of -# stepping, and then return True from should_stop, and when the user next -# "continued" the process your plan would resume control. Of course, the -# user might also "step-over" or some other operation that would push a -# different plan, which would take control till it was done. -# -# One other detail you should be aware of, if the plan below you on the -# stack was done, then it will be popped and the next plan will take control -# and its "should_stop" will be called. -# -# Note also, there should be another method called when your plan is popped, -# to allow you to do whatever cleanup is required. I haven't gotten to that -# yet. For now you should do that at the same time you mark your plan complete. -# -# 3) After the round of negotiation over whether to stop or not is done, all the -# plans get asked if they are "stale". If they are say they are stale -# then they will get popped. This question is asked with the "is_stale" method. -# -# This is useful, for instance, in the FinishPrintAndContinue plan. What might -# happen here is that after continuing but before the finish is done, the program -# could hit another breakpoint and stop. Then the user could use the step -# command repeatedly until they leave the frame of interest by stepping. -# In that case, the step plan is the one that will be responsible for stopping, -# and the finish plan won't be asked should_stop, it will just be asked if it -# is stale. In this case, if the step_out plan that the FinishPrintAndContinue -# plan is driving is stale, so is ours, and it is time to do our printing. -# -# Both examples show stepping through an address range for 20 bytes from the -# current PC. The first one does it by single stepping and checking a condition. -# It doesn't, however handle the case where you step into another frame while -# still in the current range in the starting frame. -# -# That is better handled in the second example by using the built-in StepOverRange -# thread plan. -# -# To use these stepping modes, you would do: -# -# (lldb) command script import scripted_step.py -# (lldb) thread step-scripted -C scripted_step.SimpleStep -# or -# -# (lldb) thread step-scripted -C scripted_step.StepWithPlan - -import lldb - - -class SimpleStep: - - def __init__(self, thread_plan, dict): - self.thread_plan = thread_plan - self.start_address = thread_plan.GetThread().GetFrameAtIndex(0).GetPC() - - def explains_stop(self, event): - # We are stepping, so if we stop for any other reason, it isn't - # because of us. - if self.thread_plan.GetThread().GetStopReason() == lldb.eStopReasonTrace: - return True - else: - return False - - def should_stop(self, event): - cur_pc = self.thread_plan.GetThread().GetFrameAtIndex(0).GetPC() - - if cur_pc < self.start_address or cur_pc >= self.start_address + 20: - self.thread_plan.SetPlanComplete(True) - return True - else: - return False - - def should_step(self): - return True - - -class StepWithPlan: - - def __init__(self, thread_plan, dict): - self.thread_plan = thread_plan - self.start_address = thread_plan.GetThread().GetFrameAtIndex(0).GetPCAddress() - self.step_thread_plan = thread_plan.QueueThreadPlanForStepOverRange( - self.start_address, 20) - - def explains_stop(self, event): - # Since all I'm doing is running a plan, I will only ever get askedthis - # if myplan doesn't explain the stop, and in that caseI don'teither. - return False - - def should_stop(self, event): - if self.step_thread_plan.IsPlanComplete(): - self.thread_plan.SetPlanComplete(True) - return True - else: - return False - - def should_step(self): - return False - -# Here's another example which does "step over" through the current function, -# and when it stops at each line, it checks some condition (in this example the -# value of a variable) and stops if that condition is true. - - -class StepCheckingCondition: - - def __init__(self, thread_plan, dict): - self.thread_plan = thread_plan - self.start_frame = thread_plan.GetThread().GetFrameAtIndex(0) - self.queue_next_plan() - - def queue_next_plan(self): - cur_frame = self.thread_plan.GetThread().GetFrameAtIndex(0) - cur_line_entry = cur_frame.GetLineEntry() - start_address = cur_line_entry.GetStartAddress() - end_address = cur_line_entry.GetEndAddress() - line_range = end_address.GetFileAddress() - start_address.GetFileAddress() - self.step_thread_plan = self.thread_plan.QueueThreadPlanForStepOverRange( - start_address, line_range) - - def explains_stop(self, event): - # We are stepping, so if we stop for any other reason, it isn't - # because of us. - return False - - def should_stop(self, event): - if not self.step_thread_plan.IsPlanComplete(): - return False - - frame = self.thread_plan.GetThread().GetFrameAtIndex(0) - if not self.start_frame.IsEqual(frame): - self.thread_plan.SetPlanComplete(True) - return True - - # This part checks the condition. In this case we are expecting - # some integer variable called "a", and will stop when it is 20. - a_var = frame.FindVariable("a") - - if not a_var.IsValid(): - print "A was not valid." - return True - - error = lldb.SBError() - a_value = a_var.GetValueAsSigned(error) - if not error.Success(): - print "A value was not good." - return True - - if a_value == 20: - self.thread_plan.SetPlanComplete(True) - return True - else: - self.queue_next_plan() - return False - - def should_step(self): - return True - -# Here's an example that steps out of the current frame, gathers some information -# and then continues. The information in this case is rax. Currently the thread -# plans are not a safe place to call lldb command-line commands, so the information -# is gathered through SB API calls. - - -class FinishPrintAndContinue: - - def __init__(self, thread_plan, dict): - self.thread_plan = thread_plan - self.step_out_thread_plan = thread_plan.QueueThreadPlanForStepOut( - 0, True) - self.thread = self.thread_plan.GetThread() - - def is_stale(self): - if self.step_out_thread_plan.IsPlanStale(): - self.do_print() - return True - else: - return False - - def explains_stop(self, event): - return False - - def should_stop(self, event): - if self.step_out_thread_plan.IsPlanComplete(): - self.do_print() - self.thread_plan.SetPlanComplete(True) - return False - - def do_print(self): - frame_0 = self.thread.frames[0] - rax_value = frame_0.FindRegister("rax") - if rax_value.GetError().Success(): - print "RAX on exit: ", rax_value.GetValue() - else: - print "Couldn't get rax value:", rax_value.GetError().GetCString() diff --git a/examples/python/shadow.py b/examples/python/shadow.py deleted file mode 100644 index 0556cfc553ce..000000000000 --- a/examples/python/shadow.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/python - -import lldb -import shlex - - -@lldb.command("shadow") -def check_shadow_command(debugger, command, exe_ctx, result, dict): - '''Check the currently selected stack frame for shadowed variables''' - process = exe_ctx.GetProcess() - state = process.GetState() - if state != lldb.eStateStopped: - print >>result, "process must be stopped, state is %s" % lldb.SBDebugger.StateAsCString( - state) - return - frame = exe_ctx.GetFrame() - if not frame: - print >>result, "invalid frame" - return - # Parse command line args - command_args = shlex.split(command) - # TODO: add support for using arguments that are passed to this command... - - # Make a dictionary of variable name to "SBBlock and SBValue" - shadow_dict = {} - - num_shadowed_variables = 0 - # Get the deepest most block from the current frame - block = frame.GetBlock() - # Iterate through the block and all of its parents - while block.IsValid(): - # Get block variables from the current block only - block_vars = block.GetVariables(frame, True, True, True, 0) - # Iterate through all variables in the current block - for block_var in block_vars: - # Since we can have multiple shadowed variables, we our variable - # name dictionary to have an array or "block + variable" pairs so - # We can correctly print out all shadowed variables and whow which - # blocks they come from - block_var_name = block_var.GetName() - if block_var_name in shadow_dict: - shadow_dict[block_var_name].append(block_var) - else: - shadow_dict[block_var_name] = [block_var] - # Get the parent block and continue - block = block.GetParent() - - num_shadowed_variables = 0 - if shadow_dict: - for name in shadow_dict.keys(): - shadow_vars = shadow_dict[name] - if len(shadow_vars) > 1: - print '"%s" is shadowed by the following declarations:' % (name) - num_shadowed_variables += 1 - for shadow_var in shadow_vars: - print >>result, str(shadow_var.GetDeclaration()) - if num_shadowed_variables == 0: - print >>result, 'no variables are shadowed' diff --git a/examples/python/sources.py b/examples/python/sources.py deleted file mode 100644 index b912f43f72c3..000000000000 --- a/examples/python/sources.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/python - -import lldb -import shlex - - -def dump_module_sources(module, result): - if module: - print >> result, "Module: %s" % (module.file) - for compile_unit in module.compile_units: - if compile_unit.file: - print >> result, " %s" % (compile_unit.file) - - -def info_sources(debugger, command, result, dict): - description = '''This command will dump all compile units in any modules that are listed as arguments, or for all modules if no arguments are supplied.''' - module_names = shlex.split(command) - target = debugger.GetSelectedTarget() - if module_names: - for module_name in module_names: - dump_module_sources(target.module[module_name], result) - else: - for module in target.modules: - dump_module_sources(module, result) - - -def __lldb_init_module(debugger, dict): - # Add any commands contained in this module to LLDB - debugger.HandleCommand( - 'command script add -f sources.info_sources info_sources') - print 'The "info_sources" command has been installed, type "help info_sources" or "info_sources --help" for detailed help.' diff --git a/examples/python/stacks.py b/examples/python/stacks.py deleted file mode 100755 index fec879993d96..000000000000 --- a/examples/python/stacks.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/python - -import lldb -import commands -import optparse -import shlex - - -def stack_frames(debugger, command, result, dict): - command_args = shlex.split(command) - usage = "usage: %prog [options] <PATH> [PATH ...]" - description = '''This command will enumerate all stack frames, print the stack size for each, and print an aggregation of which functions have the largest stack frame sizes at the end.''' - parser = optparse.OptionParser( - description=description, prog='ls', usage=usage) - parser.add_option( - '-v', - '--verbose', - action='store_true', - dest='verbose', - help='display verbose debug info', - default=False) - try: - (options, args) = parser.parse_args(command_args) - except: - return - - target = debugger.GetSelectedTarget() - process = target.GetProcess() - - frame_info = {} - for thread in process: - last_frame = None - print "thread %u" % (thread.id) - for frame in thread.frames: - if last_frame: - frame_size = 0 - if frame.idx == 1: - if frame.fp == last_frame.fp: - # No frame one the first frame (might be right at the - # entry point) - first_frame_size = 0 - frame_size = frame.fp - frame.sp - else: - # First frame that has a valid size - first_frame_size = last_frame.fp - last_frame.sp - print "<%#7x> %s" % (first_frame_size, last_frame) - if first_frame_size: - name = last_frame.name - if name not in frame_info: - frame_info[name] = first_frame_size - else: - frame_info[name] += first_frame_size - else: - # Second or higher frame - frame_size = frame.fp - last_frame.fp - print "<%#7x> %s" % (frame_size, frame) - if frame_size > 0: - name = frame.name - if name not in frame_info: - frame_info[name] = frame_size - else: - frame_info[name] += frame_size - last_frame = frame - print frame_info - - -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." diff --git a/examples/python/step_and_print.py b/examples/python/step_and_print.py deleted file mode 100644 index 41364ef97ba8..000000000000 --- a/examples/python/step_and_print.py +++ /dev/null @@ -1,24 +0,0 @@ -""" Does a step-over then prints the local variables or only the ones passed in """ -import lldb - -class StepAndPrint: - def __init__(self, debugger, unused): - return - - def __call__(self, debugger, command, exe_ctx, result): - # Set the command to synchronous so the step will complete - # before we try to run the frame variable. - old_async = debugger.GetAsync() - debugger.SetAsync(False) - - debugger.HandleCommand("thread step-over") - print("---------- Values: -------------------\n") - debugger.HandleCommand("frame variable %s"%(command)) - - debugger.SetAsync(old_async) - - def get_short_help(self): - return "Does a step-over then runs frame variable passing the command args to it\n" - -def __lldb_init_module(debugger, unused): - debugger.HandleCommand("command script add -c step_and_print.StepAndPrint sap") diff --git a/examples/python/symbolication.py b/examples/python/symbolication.py deleted file mode 100755 index b655ad0d179d..000000000000 --- a/examples/python/symbolication.py +++ /dev/null @@ -1,727 +0,0 @@ -#!/usr/bin/python - -#---------------------------------------------------------------------- -# Be sure to add the python path that points to the LLDB shared library. -# -# To use this in the embedded python interpreter using "lldb": -# -# cd /path/containing/crashlog.py -# lldb -# (lldb) script import crashlog -# "crashlog" command installed, type "crashlog --help" for detailed help -# (lldb) crashlog ~/Library/Logs/DiagnosticReports/a.crash -# -# The benefit of running the crashlog command inside lldb in the -# embedded python interpreter is when the command completes, there -# will be a target with all of the files loaded at the locations -# described in the crash log. Only the files that have stack frames -# in the backtrace will be loaded unless the "--load-all" option -# has been specified. This allows users to explore the program in the -# state it was in right at crash time. -# -# On MacOSX csh, tcsh: -# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash ) -# -# On MacOSX sh, bash: -# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash -#---------------------------------------------------------------------- - -import lldb -import commands -import optparse -import os -import plistlib -import re -import shlex -import sys -import time -import uuid - - -class Address: - """Class that represents an address that will be symbolicated""" - - def __init__(self, target, load_addr): - self.target = target - self.load_addr = load_addr # The load address that this object represents - # the resolved lldb.SBAddress (if any), named so_addr for - # section/offset address - self.so_addr = None - self.sym_ctx = None # The cached symbol context for this address - # Any original textual description of this address to be used as a - # backup in case symbolication fails - self.description = None - self.symbolication = None # The cached symbolicated string that describes this address - self.inlined = False - - def __str__(self): - s = "%#16.16x" % (self.load_addr) - if self.symbolication: - s += " %s" % (self.symbolication) - elif self.description: - s += " %s" % (self.description) - elif self.so_addr: - s += " %s" % (self.so_addr) - return s - - def resolve_addr(self): - if self.so_addr is None: - self.so_addr = self.target.ResolveLoadAddress(self.load_addr) - return self.so_addr - - def is_inlined(self): - return self.inlined - - def get_symbol_context(self): - if self.sym_ctx is None: - sb_addr = self.resolve_addr() - if sb_addr: - self.sym_ctx = self.target.ResolveSymbolContextForAddress( - sb_addr, lldb.eSymbolContextEverything) - else: - self.sym_ctx = lldb.SBSymbolContext() - return self.sym_ctx - - def get_instructions(self): - sym_ctx = self.get_symbol_context() - if sym_ctx: - function = sym_ctx.GetFunction() - if function: - return function.GetInstructions(self.target) - return sym_ctx.GetSymbol().GetInstructions(self.target) - return None - - def symbolicate(self, verbose=False): - if self.symbolication is None: - self.symbolication = '' - self.inlined = False - sym_ctx = self.get_symbol_context() - if sym_ctx: - module = sym_ctx.GetModule() - if module: - # Print full source file path in verbose mode - if verbose: - self.symbolication += str(module.GetFileSpec()) + '`' - else: - self.symbolication += module.GetFileSpec().GetFilename() + '`' - function_start_load_addr = -1 - function = sym_ctx.GetFunction() - block = sym_ctx.GetBlock() - line_entry = sym_ctx.GetLineEntry() - symbol = sym_ctx.GetSymbol() - inlined_block = block.GetContainingInlinedBlock() - if function: - self.symbolication += function.GetName() - - if inlined_block: - self.inlined = True - self.symbolication += ' [inlined] ' + \ - inlined_block.GetInlinedName() - block_range_idx = inlined_block.GetRangeIndexForBlockAddress( - self.so_addr) - if block_range_idx < lldb.UINT32_MAX: - block_range_start_addr = inlined_block.GetRangeStartAddress( - block_range_idx) - function_start_load_addr = block_range_start_addr.GetLoadAddress( - self.target) - if function_start_load_addr == -1: - function_start_load_addr = function.GetStartAddress().GetLoadAddress(self.target) - elif symbol: - self.symbolication += symbol.GetName() - function_start_load_addr = symbol.GetStartAddress().GetLoadAddress(self.target) - else: - self.symbolication = '' - return False - - # Dump the offset from the current function or symbol if it - # is non zero - function_offset = self.load_addr - function_start_load_addr - if function_offset > 0: - self.symbolication += " + %u" % (function_offset) - elif function_offset < 0: - self.symbolication += " %i (invalid negative offset, file a bug) " % function_offset - - # Print out any line information if any is available - if line_entry.GetFileSpec(): - # Print full source file path in verbose mode - if verbose: - self.symbolication += ' at %s' % line_entry.GetFileSpec() - else: - self.symbolication += ' at %s' % line_entry.GetFileSpec().GetFilename() - self.symbolication += ':%u' % line_entry.GetLine() - column = line_entry.GetColumn() - if column > 0: - self.symbolication += ':%u' % column - return True - return False - - -class Section: - """Class that represents an load address range""" - sect_info_regex = re.compile('(?P<name>[^=]+)=(?P<range>.*)') - addr_regex = re.compile('^\s*(?P<start>0x[0-9A-Fa-f]+)\s*$') - range_regex = re.compile( - '^\s*(?P<start>0x[0-9A-Fa-f]+)\s*(?P<op>[-+])\s*(?P<end>0x[0-9A-Fa-f]+)\s*$') - - def __init__(self, start_addr=None, end_addr=None, name=None): - self.start_addr = start_addr - self.end_addr = end_addr - self.name = name - - @classmethod - def InitWithSBTargetAndSBSection(cls, target, section): - sect_load_addr = section.GetLoadAddress(target) - if sect_load_addr != lldb.LLDB_INVALID_ADDRESS: - obj = cls( - sect_load_addr, - sect_load_addr + - section.size, - section.name) - return obj - else: - return None - - def contains(self, addr): - return self.start_addr <= addr and addr < self.end_addr - - def set_from_string(self, s): - match = self.sect_info_regex.match(s) - if match: - self.name = match.group('name') - range_str = match.group('range') - addr_match = self.addr_regex.match(range_str) - if addr_match: - self.start_addr = int(addr_match.group('start'), 16) - self.end_addr = None - return True - - range_match = self.range_regex.match(range_str) - if range_match: - self.start_addr = int(range_match.group('start'), 16) - self.end_addr = int(range_match.group('end'), 16) - op = range_match.group('op') - if op == '+': - self.end_addr += self.start_addr - return True - print 'error: invalid section info string "%s"' % s - print 'Valid section info formats are:' - print 'Format Example Description' - print '--------------------- -----------------------------------------------' - print '<name>=<base> __TEXT=0x123000 Section from base address only' - print '<name>=<base>-<end> __TEXT=0x123000-0x124000 Section from base address and end address' - print '<name>=<base>+<size> __TEXT=0x123000+0x1000 Section from base address and size' - return False - - def __str__(self): - if self.name: - if self.end_addr is not None: - if self.start_addr is not None: - return "%s=[0x%16.16x - 0x%16.16x)" % ( - self.name, self.start_addr, self.end_addr) - else: - if self.start_addr is not None: - return "%s=0x%16.16x" % (self.name, self.start_addr) - return self.name - return "<invalid>" - - -class Image: - """A class that represents an executable image and any associated data""" - - def __init__(self, path, uuid=None): - self.path = path - self.resolved_path = None - self.resolved = False - self.unavailable = False - self.uuid = uuid - self.section_infos = list() - self.identifier = None - self.version = None - self.arch = None - self.module = None - self.symfile = None - self.slide = None - - @classmethod - def InitWithSBTargetAndSBModule(cls, target, module): - '''Initialize this Image object with a module from a target.''' - obj = cls(module.file.fullpath, module.uuid) - obj.resolved_path = module.platform_file.fullpath - obj.resolved = True - obj.arch = module.triple - for section in module.sections: - symb_section = Section.InitWithSBTargetAndSBSection( - target, section) - if symb_section: - obj.section_infos.append(symb_section) - obj.arch = module.triple - obj.module = module - obj.symfile = None - obj.slide = None - return obj - - def dump(self, prefix): - print "%s%s" % (prefix, self) - - def debug_dump(self): - print 'path = "%s"' % (self.path) - print 'resolved_path = "%s"' % (self.resolved_path) - print 'resolved = %i' % (self.resolved) - print 'unavailable = %i' % (self.unavailable) - print 'uuid = %s' % (self.uuid) - print 'section_infos = %s' % (self.section_infos) - print 'identifier = "%s"' % (self.identifier) - print 'version = %s' % (self.version) - print 'arch = %s' % (self.arch) - print 'module = %s' % (self.module) - print 'symfile = "%s"' % (self.symfile) - print 'slide = %i (0x%x)' % (self.slide, self.slide) - - def __str__(self): - s = '' - if self.uuid: - s += "%s " % (self.get_uuid()) - if self.arch: - s += "%s " % (self.arch) - if self.version: - s += "%s " % (self.version) - resolved_path = self.get_resolved_path() - if resolved_path: - s += "%s " % (resolved_path) - for section_info in self.section_infos: - s += ", %s" % (section_info) - if self.slide is not None: - s += ', slide = 0x%16.16x' % self.slide - return s - - def add_section(self, section): - # print "added '%s' to '%s'" % (section, self.path) - self.section_infos.append(section) - - def get_section_containing_load_addr(self, load_addr): - for section_info in self.section_infos: - if section_info.contains(load_addr): - return section_info - return None - - def get_resolved_path(self): - if self.resolved_path: - return self.resolved_path - elif self.path: - return self.path - return None - - def get_resolved_path_basename(self): - path = self.get_resolved_path() - if path: - return os.path.basename(path) - return None - - def symfile_basename(self): - if self.symfile: - return os.path.basename(self.symfile) - return None - - def has_section_load_info(self): - return self.section_infos or self.slide is not None - - def load_module(self, target): - if self.unavailable: - return None # We already warned that we couldn't find this module, so don't return an error string - # Load this module into "target" using the section infos to - # set the section load addresses - if self.has_section_load_info(): - if target: - if self.module: - if self.section_infos: - num_sections_loaded = 0 - for section_info in self.section_infos: - if section_info.name: - section = self.module.FindSection( - section_info.name) - if section: - error = target.SetSectionLoadAddress( - section, section_info.start_addr) - if error.Success(): - num_sections_loaded += 1 - else: - return 'error: %s' % error.GetCString() - else: - return 'error: unable to find the section named "%s"' % section_info.name - else: - return 'error: unable to find "%s" section in "%s"' % ( - range.name, self.get_resolved_path()) - if num_sections_loaded == 0: - return 'error: no sections were successfully loaded' - else: - err = target.SetModuleLoadAddress( - self.module, self.slide) - if err.Fail(): - return err.GetCString() - return None - else: - return 'error: invalid module' - else: - return 'error: invalid target' - else: - return 'error: no section infos' - - def add_module(self, target): - '''Add the Image described in this object to "target" and load the sections if "load" is True.''' - if target: - # Try and find using UUID only first so that paths need not match - # up - uuid_str = self.get_normalized_uuid_string() - if uuid_str: - self.module = target.AddModule(None, None, uuid_str) - if not self.module: - self.locate_module_and_debug_symbols() - if self.unavailable: - return None - resolved_path = self.get_resolved_path() - self.module = target.AddModule( - resolved_path, self.arch, uuid_str, self.symfile) - if not self.module: - return 'error: unable to get module for (%s) "%s"' % ( - self.arch, self.get_resolved_path()) - if self.has_section_load_info(): - return self.load_module(target) - else: - return None # No sections, the module was added to the target, so success - else: - return 'error: invalid target' - - def locate_module_and_debug_symbols(self): - # By default, just use the paths that were supplied in: - # self.path - # self.resolved_path - # self.module - # self.symfile - # Subclasses can inherit from this class and override this function - self.resolved = True - return True - - def get_uuid(self): - if not self.uuid and self.module: - self.uuid = uuid.UUID(self.module.GetUUIDString()) - return self.uuid - - def get_normalized_uuid_string(self): - if self.uuid: - return str(self.uuid).upper() - return None - - def create_target(self): - '''Create a target using the information in this Image object.''' - if self.unavailable: - return None - - if self.locate_module_and_debug_symbols(): - resolved_path = self.get_resolved_path() - path_spec = lldb.SBFileSpec(resolved_path) - #result.PutCString ('plist[%s] = %s' % (uuid, self.plist)) - error = lldb.SBError() - target = lldb.debugger.CreateTarget( - resolved_path, self.arch, None, False, error) - if target: - self.module = target.FindModule(path_spec) - if self.has_section_load_info(): - err = self.load_module(target) - if err: - print 'ERROR: ', err - return target - else: - print 'error: unable to create a valid target for (%s) "%s"' % (self.arch, self.path) - else: - print 'error: unable to locate main executable (%s) "%s"' % (self.arch, self.path) - return None - - -class Symbolicator: - - def __init__(self): - """A class the represents the information needed to symbolicate addresses in a program""" - self.target = None - self.images = list() # a list of images to be used when symbolicating - self.addr_mask = 0xffffffffffffffff - - @classmethod - def InitWithSBTarget(cls, target): - obj = cls() - obj.target = target - obj.images = list() - triple = target.triple - if triple: - arch = triple.split('-')[0] - if "arm" in arch: - obj.addr_mask = 0xfffffffffffffffe - - for module in target.modules: - image = Image.InitWithSBTargetAndSBModule(target, module) - obj.images.append(image) - return obj - - def __str__(self): - s = "Symbolicator:\n" - if self.target: - s += "Target = '%s'\n" % (self.target) - s += "Target modules:\n" - for m in self.target.modules: - s += str(m) + "\n" - s += "Images:\n" - for image in self.images: - s += ' %s\n' % (image) - return s - - def find_images_with_identifier(self, identifier): - images = list() - for image in self.images: - if image.identifier == identifier: - images.append(image) - if len(images) == 0: - regex_text = '^.*\.%s$' % (re.escape(identifier)) - regex = re.compile(regex_text) - for image in self.images: - if regex.match(image.identifier): - images.append(image) - return images - - def find_image_containing_load_addr(self, load_addr): - for image in self.images: - if image.get_section_containing_load_addr(load_addr): - return image - return None - - def create_target(self): - if self.target: - return self.target - - if self.images: - for image in self.images: - self.target = image.create_target() - if self.target: - if self.target.GetAddressByteSize() == 4: - triple = self.target.triple - if triple: - arch = triple.split('-')[0] - if "arm" in arch: - self.addr_mask = 0xfffffffffffffffe - return self.target - return None - - def symbolicate(self, load_addr, verbose=False): - if not self.target: - self.create_target() - if self.target: - live_process = False - process = self.target.process - if process: - state = process.state - if state > lldb.eStateUnloaded and state < lldb.eStateDetached: - live_process = True - # If we don't have a live process, we can attempt to find the image - # that a load address belongs to and lazily load its module in the - # target, but we shouldn't do any of this if we have a live process - if not live_process: - image = self.find_image_containing_load_addr(load_addr) - if image: - image.add_module(self.target) - symbolicated_address = Address(self.target, load_addr) - if symbolicated_address.symbolicate(verbose): - if symbolicated_address.so_addr: - symbolicated_addresses = list() - symbolicated_addresses.append(symbolicated_address) - # See if we were able to reconstruct anything? - while True: - inlined_parent_so_addr = lldb.SBAddress() - inlined_parent_sym_ctx = symbolicated_address.sym_ctx.GetParentOfInlinedScope( - symbolicated_address.so_addr, inlined_parent_so_addr) - if not inlined_parent_sym_ctx: - break - if not inlined_parent_so_addr: - break - - symbolicated_address = Address( - self.target, inlined_parent_so_addr.GetLoadAddress( - self.target)) - symbolicated_address.sym_ctx = inlined_parent_sym_ctx - symbolicated_address.so_addr = inlined_parent_so_addr - symbolicated_address.symbolicate(verbose) - - # push the new frame onto the new frame stack - symbolicated_addresses.append(symbolicated_address) - - if symbolicated_addresses: - return symbolicated_addresses - else: - print 'error: no target in Symbolicator' - return None - - -def disassemble_instructions( - target, - instructions, - pc, - insts_before_pc, - insts_after_pc, - non_zeroeth_frame): - lines = list() - pc_index = -1 - comment_column = 50 - for inst_idx, inst in enumerate(instructions): - inst_pc = inst.GetAddress().GetLoadAddress(target) - if pc == inst_pc: - pc_index = inst_idx - mnemonic = inst.GetMnemonic(target) - operands = inst.GetOperands(target) - comment = inst.GetComment(target) - #data = inst.GetData (target) - lines.append("%#16.16x: %8s %s" % (inst_pc, mnemonic, operands)) - if comment: - line_len = len(lines[-1]) - if line_len < comment_column: - lines[-1] += ' ' * (comment_column - line_len) - lines[-1] += "; %s" % comment - - if pc_index >= 0: - # If we are disassembling the non-zeroeth frame, we need to backup the - # PC by 1 - if non_zeroeth_frame and pc_index > 0: - pc_index = pc_index - 1 - if insts_before_pc == -1: - start_idx = 0 - else: - start_idx = pc_index - insts_before_pc - if start_idx < 0: - start_idx = 0 - if insts_before_pc == -1: - end_idx = inst_idx - else: - end_idx = pc_index + insts_after_pc - if end_idx > inst_idx: - end_idx = inst_idx - for i in range(start_idx, end_idx + 1): - if i == pc_index: - print ' -> ', lines[i] - else: - print ' ', lines[i] - - -def print_module_section_data(section): - print section - section_data = section.GetSectionData() - if section_data: - ostream = lldb.SBStream() - section_data.GetDescription(ostream, section.GetFileAddress()) - print ostream.GetData() - - -def print_module_section(section, depth): - print section - if depth > 0: - num_sub_sections = section.GetNumSubSections() - for sect_idx in range(num_sub_sections): - print_module_section( - section.GetSubSectionAtIndex(sect_idx), depth - 1) - - -def print_module_sections(module, depth): - for sect in module.section_iter(): - print_module_section(sect, depth) - - -def print_module_symbols(module): - for sym in module: - print sym - - -def Symbolicate(command_args): - - usage = "usage: %prog [options] <addr1> [addr2 ...]" - description = '''Symbolicate one or more addresses using LLDB's python scripting API..''' - parser = optparse.OptionParser( - description=description, - prog='crashlog.py', - usage=usage) - parser.add_option( - '-v', - '--verbose', - action='store_true', - dest='verbose', - help='display verbose debug info', - default=False) - parser.add_option( - '-p', - '--platform', - type='string', - metavar='platform', - dest='platform', - help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".') - parser.add_option( - '-f', - '--file', - type='string', - metavar='file', - dest='file', - help='Specify a file to use when symbolicating') - parser.add_option( - '-a', - '--arch', - type='string', - metavar='arch', - dest='arch', - help='Specify a architecture to use when symbolicating') - parser.add_option( - '-s', - '--slide', - type='int', - metavar='slide', - dest='slide', - help='Specify the slide to use on the file specified with the --file option', - default=None) - parser.add_option( - '--section', - type='string', - action='append', - dest='section_strings', - help='specify <sect-name>=<start-addr> or <sect-name>=<start-addr>-<end-addr>') - try: - (options, args) = parser.parse_args(command_args) - except: - return - symbolicator = Symbolicator() - images = list() - if options.file: - image = Image(options.file) - image.arch = options.arch - # Add any sections that were specified with one or more --section - # options - if options.section_strings: - for section_str in options.section_strings: - section = Section() - if section.set_from_string(section_str): - image.add_section(section) - else: - sys.exit(1) - if options.slide is not None: - image.slide = options.slide - symbolicator.images.append(image) - - target = symbolicator.create_target() - if options.verbose: - print symbolicator - if target: - for addr_str in args: - addr = int(addr_str, 0) - symbolicated_addrs = symbolicator.symbolicate( - addr, options.verbose) - for symbolicated_addr in symbolicated_addrs: - print symbolicated_addr - print - else: - print 'error: no target for %s' % (symbolicator) - -if __name__ == '__main__': - # Create a new debugger instance - lldb.debugger = lldb.SBDebugger.Create() - Symbolicate(sys.argv[1:]) diff --git a/examples/python/types.py b/examples/python/types.py deleted file mode 100755 index a8aac24f4a07..000000000000 --- a/examples/python/types.py +++ /dev/null @@ -1,356 +0,0 @@ -#!/usr/bin/python - -#---------------------------------------------------------------------- -# Be sure to add the python path that points to the LLDB shared library. -# -# # To use this in the embedded python interpreter using "lldb" just -# import it with the full path using the "command script import" -# command -# (lldb) command script import /path/to/cmdtemplate.py -#---------------------------------------------------------------------- - -import commands -import platform -import os -import re -import signal -import sys - -try: - # Just try for LLDB in case PYTHONPATH is already correctly setup - import lldb -except ImportError: - lldb_python_dirs = list() - # lldb is not in the PYTHONPATH, try some defaults for the current platform - platform_system = platform.system() - if platform_system == 'Darwin': - # On Darwin, try the currently selected Xcode directory - xcode_dir = commands.getoutput("xcode-select --print-path") - if xcode_dir: - lldb_python_dirs.append( - os.path.realpath( - xcode_dir + - '/../SharedFrameworks/LLDB.framework/Resources/Python')) - lldb_python_dirs.append( - xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python') - lldb_python_dirs.append( - '/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') - success = False - for lldb_python_dir in lldb_python_dirs: - if os.path.exists(lldb_python_dir): - if not (sys.path.__contains__(lldb_python_dir)): - sys.path.append(lldb_python_dir) - try: - import lldb - except ImportError: - pass - else: - print 'imported lldb from: "%s"' % (lldb_python_dir) - success = True - break - if not success: - print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly" - sys.exit(1) - -import commands -import optparse -import shlex -import time - - -def regex_option_callback(option, opt_str, value, parser): - if opt_str == "--std": - value = '^std::' - regex = re.compile(value) - parser.values.skip_type_regexes.append(regex) - - -def create_types_options(for_lldb_command): - if for_lldb_command: - usage = "usage: %prog [options]" - description = '''This command will help check for padding in between -base classes and members in structs and classes. It will summarize the types -and how much padding was found. If no types are specified with the --types TYPENAME -option, all structure and class types will be verified. If no modules are -specified with the --module option, only the target's main executable will be -searched. -''' - else: - usage = "usage: %prog [options] EXEPATH [EXEPATH ...]" - description = '''This command will help check for padding in between -base classes and members in structures and classes. It will summarize the types -and how much padding was found. One or more paths to executable files must be -specified and targets will be created with these modules. If no types are -specified with the --types TYPENAME option, all structure and class types will -be verified in all specified modules. -''' - parser = optparse.OptionParser( - description=description, - prog='framestats', - usage=usage) - if not for_lldb_command: - parser.add_option( - '-a', - '--arch', - type='string', - dest='arch', - help='The architecture to use when creating the debug target.', - default=None) - parser.add_option( - '-p', - '--platform', - type='string', - metavar='platform', - dest='platform', - help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".') - parser.add_option( - '-m', - '--module', - action='append', - type='string', - metavar='MODULE', - dest='modules', - help='Specify one or more modules which will be used to verify the types.', - default=[]) - parser.add_option( - '-d', - '--debug', - action='store_true', - dest='debug', - help='Pause 10 seconds to wait for a debugger to attach.', - default=False) - parser.add_option( - '-t', - '--type', - action='append', - type='string', - metavar='TYPENAME', - dest='typenames', - help='Specify one or more type names which should be verified. If no type names are specified, all class and struct types will be verified.', - default=[]) - parser.add_option( - '-v', - '--verbose', - action='store_true', - dest='verbose', - help='Enable verbose logging and information.', - default=False) - parser.add_option( - '-s', - '--skip-type-regex', - action="callback", - callback=regex_option_callback, - type='string', - metavar='REGEX', - dest='skip_type_regexes', - help='Regular expressions that, if they match the current member typename, will cause the type to no be recursively displayed.', - default=[]) - parser.add_option( - '--std', - action="callback", - callback=regex_option_callback, - metavar='REGEX', - dest='skip_type_regexes', - help="Don't' recurse into types in the std namespace.", - default=[]) - return parser - - -def verify_type(target, options, type): - print type - typename = type.GetName() - # print 'type: %s' % (typename) - (end_offset, padding) = verify_type_recursive( - target, options, type, None, 0, 0, 0) - byte_size = type.GetByteSize() - # if end_offset < byte_size: - # last_member_padding = byte_size - end_offset - # print '%+4u <%u> padding' % (end_offset, last_member_padding) - # padding += last_member_padding - print 'Total byte size: %u' % (byte_size) - print 'Total pad bytes: %u' % (padding) - if padding > 0: - print 'Padding percentage: %2.2f %%' % ((float(padding) / float(byte_size)) * 100.0) - print - - -def verify_type_recursive( - target, - options, - type, - member_name, - depth, - base_offset, - padding): - prev_end_offset = base_offset - typename = type.GetName() - byte_size = type.GetByteSize() - if member_name and member_name != typename: - print '%+4u <%3u> %s%s %s;' % (base_offset, byte_size, ' ' * depth, typename, member_name) - else: - print '%+4u {%3u} %s%s' % (base_offset, byte_size, ' ' * depth, typename) - - for type_regex in options.skip_type_regexes: - match = type_regex.match(typename) - if match: - return (base_offset + byte_size, padding) - - members = type.members - if members: - for member_idx, member in enumerate(members): - member_type = member.GetType() - member_canonical_type = member_type.GetCanonicalType() - member_type_class = member_canonical_type.GetTypeClass() - member_name = member.GetName() - member_offset = member.GetOffsetInBytes() - member_total_offset = member_offset + base_offset - member_byte_size = member_type.GetByteSize() - member_is_class_or_struct = False - if member_type_class == lldb.eTypeClassStruct or member_type_class == lldb.eTypeClassClass: - member_is_class_or_struct = True - if member_idx == 0 and member_offset == target.GetAddressByteSize( - ) and type.IsPolymorphicClass(): - ptr_size = target.GetAddressByteSize() - print '%+4u <%3u> %s__vtbl_ptr_type * _vptr;' % (prev_end_offset, ptr_size, ' ' * (depth + 1)) - prev_end_offset = ptr_size - else: - if prev_end_offset < member_total_offset: - member_padding = member_total_offset - prev_end_offset - padding = padding + member_padding - print '%+4u <%3u> %s<PADDING>' % (prev_end_offset, member_padding, ' ' * (depth + 1)) - - if member_is_class_or_struct: - (prev_end_offset, - padding) = verify_type_recursive(target, - options, - member_canonical_type, - member_name, - depth + 1, - member_total_offset, - padding) - else: - prev_end_offset = member_total_offset + member_byte_size - member_typename = member_type.GetName() - if member.IsBitfield(): - print '%+4u <%3u> %s%s:%u %s;' % (member_total_offset, member_byte_size, ' ' * (depth + 1), member_typename, member.GetBitfieldSizeInBits(), member_name) - else: - print '%+4u <%3u> %s%s %s;' % (member_total_offset, member_byte_size, ' ' * (depth + 1), member_typename, member_name) - - if prev_end_offset < byte_size: - last_member_padding = byte_size - prev_end_offset - print '%+4u <%3u> %s<PADDING>' % (prev_end_offset, last_member_padding, ' ' * (depth + 1)) - padding += last_member_padding - else: - if type.IsPolymorphicClass(): - ptr_size = target.GetAddressByteSize() - print '%+4u <%3u> %s__vtbl_ptr_type * _vptr;' % (prev_end_offset, ptr_size, ' ' * (depth + 1)) - prev_end_offset = ptr_size - prev_end_offset = base_offset + byte_size - - return (prev_end_offset, padding) - - -def check_padding_command(debugger, command, result, dict): - # Use the Shell Lexer to properly parse up command options just like a - # shell would - command_args = shlex.split(command) - parser = create_types_options(True) - try: - (options, args) = parser.parse_args(command_args) - except: - # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit - # (courtesy of OptParse dealing with argument errors by throwing SystemExit) - result.SetStatus(lldb.eReturnStatusFailed) - # returning a string is the same as returning an error whose - # description is the string - return "option parsing failed" - verify_types(debugger.GetSelectedTarget(), options) - - -@lldb.command("parse_all_struct_class_types") -def parse_all_struct_class_types(debugger, command, result, dict): - command_args = shlex.split(command) - for f in command_args: - error = lldb.SBError() - target = debugger.CreateTarget(f, None, None, False, error) - module = target.GetModuleAtIndex(0) - print "Parsing all types in '%s'" % (module) - types = module.GetTypes(lldb.eTypeClassClass | lldb.eTypeClassStruct) - for t in types: - print t - print "" - - -def verify_types(target, options): - - if not target: - print 'error: invalid target' - return - - modules = list() - if len(options.modules) == 0: - # Append just the main executable if nothing was specified - module = target.modules[0] - if module: - modules.append(module) - else: - for module_name in options.modules: - module = lldb.target.module[module_name] - if module: - modules.append(module) - - if modules: - for module in modules: - print 'module: %s' % (module.file) - if options.typenames: - for typename in options.typenames: - types = module.FindTypes(typename) - if types.GetSize(): - print 'Found %u types matching "%s" in "%s"' % (len(types), typename, module.file) - for type in types: - verify_type(target, options, type) - else: - print 'error: no type matches "%s" in "%s"' % (typename, module.file) - else: - types = module.GetTypes( - lldb.eTypeClassClass | lldb.eTypeClassStruct) - print 'Found %u types in "%s"' % (len(types), module.file) - for type in types: - verify_type(target, options, type) - else: - print 'error: no modules' - -if __name__ == '__main__': - debugger = lldb.SBDebugger.Create() - parser = create_types_options(False) - - # try: - (options, args) = parser.parse_args(sys.argv[1:]) - # except: - # print "error: option parsing failed" - # sys.exit(1) - - if options.debug: - print "Waiting for debugger to attach to process %d" % os.getpid() - os.kill(os.getpid(), signal.SIGSTOP) - - for path in args: - # in a command - the lldb.* convenience variables are not to be used - # and their values (if any) are undefined - # this is the best practice to access those objects from within a - # command - error = lldb.SBError() - target = debugger.CreateTarget(path, - options.arch, - options.platform, - True, - error) - if error.Fail(): - print error.GetCString() - continue - verify_types(target, options) - -elif getattr(lldb, 'debugger', None): - 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' diff --git a/examples/python/x86_64_linux_target_definition.py b/examples/python/x86_64_linux_target_definition.py deleted file mode 100644 index 9417b21abd66..000000000000 --- a/examples/python/x86_64_linux_target_definition.py +++ /dev/null @@ -1,775 +0,0 @@ -#!/usr/bin/python -#===-- x86_64_linux_target_definition.py -----------------------------*- C++ -*-===// -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===----------------------------------------------------------------------===// - -#---------------------------------------------------------------------- -# DESCRIPTION -# -# This file can be used with the following setting: -# plugin.process.gdb-remote.target-definition-file -# This setting should be used when you are trying to connect to a -# remote GDB server that doesn't support any of the register discovery -# packets that LLDB normally uses. -# -# Why is this necessary? LLDB doesn't require a new build of LLDB that -# targets each new architecture you will debug with. Instead, all -# architectures are supported and LLDB relies on extra GDB server -# packets to discover the target we are connecting to so that is can -# show the right registers for each target. This allows the GDB server -# to change and add new registers without requiring a new LLDB build -# just so we can see new registers. -# -# This file implements the x86_64 registers for the darwin version of -# GDB and allows you to connect to servers that use this register set. -# -# USAGE -# -# (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/x86_64_linux_target_definition.py -# (lldb) gdb-remote other.baz.com:1234 -# -# The target definition file will get used if and only if the -# qRegisterInfo packets are not supported when connecting to a remote -# GDB server. -#---------------------------------------------------------------------- -from lldb import * - -# Compiler and DWARF register numbers -name_to_gcc_dwarf_regnum = { - 'rax': 0, - 'rdx': 1, - 'rcx': 2, - 'rbx': 3, - 'rsi': 4, - 'rdi': 5, - 'rbp': 6, - 'rsp': 7, - 'r8': 8, - 'r9': 9, - 'r10': 10, - 'r11': 11, - 'r12': 12, - 'r13': 13, - 'r14': 14, - 'r15': 15, - 'rip': 16, - 'xmm0': 17, - 'xmm1': 18, - 'xmm2': 19, - 'xmm3': 20, - 'xmm4': 21, - 'xmm5': 22, - 'xmm6': 23, - 'xmm7': 24, - 'xmm8': 25, - 'xmm9': 26, - 'xmm10': 27, - 'xmm11': 28, - 'xmm12': 29, - 'xmm13': 30, - 'xmm14': 31, - 'xmm15': 32, - 'stmm0': 33, - 'stmm1': 34, - 'stmm2': 35, - 'stmm3': 36, - 'stmm4': 37, - 'stmm5': 38, - 'stmm6': 39, - 'stmm7': 30, - 'ymm0': 41, - 'ymm1': 42, - 'ymm2': 43, - 'ymm3': 44, - 'ymm4': 45, - 'ymm5': 46, - 'ymm6': 47, - 'ymm7': 48, - 'ymm8': 49, - 'ymm9': 40, - 'ymm10': 41, - 'ymm11': 42, - 'ymm12': 43, - 'ymm13': 44, - 'ymm14': 45, - 'ymm15': 46 -} - -name_to_gdb_regnum = { - 'rax': 0, - 'rbx': 1, - 'rcx': 2, - 'rdx': 3, - 'rsi': 4, - 'rdi': 5, - 'rbp': 6, - 'rsp': 7, - 'r8': 8, - 'r9': 9, - 'r10': 10, - 'r11': 11, - 'r12': 12, - 'r13': 13, - 'r14': 14, - 'r15': 15, - 'rip': 16, - 'rflags': 17, - 'cs': 18, - 'ss': 19, - 'ds': 20, - 'es': 21, - 'fs': 22, - 'gs': 23, - 'stmm0': 24, - 'stmm1': 25, - 'stmm2': 26, - 'stmm3': 27, - 'stmm4': 28, - 'stmm5': 29, - 'stmm6': 30, - 'stmm7': 31, - 'fctrl': 32, - 'fstat': 33, - 'ftag': 34, - 'fiseg': 35, - 'fioff': 36, - 'foseg': 37, - 'fooff': 38, - 'fop': 39, - 'xmm0': 40, - 'xmm1': 41, - 'xmm2': 42, - 'xmm3': 43, - 'xmm4': 44, - 'xmm5': 45, - 'xmm6': 46, - 'xmm7': 47, - 'xmm8': 48, - 'xmm9': 49, - 'xmm10': 50, - 'xmm11': 51, - 'xmm12': 52, - 'xmm13': 53, - 'xmm14': 54, - 'xmm15': 55, - 'mxcsr': 56, - 'ymm0': 57, - 'ymm1': 58, - 'ymm2': 59, - 'ymm3': 60, - 'ymm4': 61, - 'ymm5': 62, - 'ymm6': 63, - 'ymm7': 64, - 'ymm8': 65, - 'ymm9': 66, - 'ymm10': 67, - 'ymm11': 68, - 'ymm12': 69, - 'ymm13': 70, - 'ymm14': 71, - 'ymm15': 72 -} - -name_to_generic_regnum = { - 'rip': LLDB_REGNUM_GENERIC_PC, - 'rsp': LLDB_REGNUM_GENERIC_SP, - 'rbp': LLDB_REGNUM_GENERIC_FP, - 'rdi': LLDB_REGNUM_GENERIC_ARG1, - 'rsi': LLDB_REGNUM_GENERIC_ARG2, - 'rdx': LLDB_REGNUM_GENERIC_ARG3, - 'rcx': LLDB_REGNUM_GENERIC_ARG4, - 'r8': LLDB_REGNUM_GENERIC_ARG5, - 'r9': LLDB_REGNUM_GENERIC_ARG6 -} - - -def get_reg_num(reg_num_dict, reg_name): - if reg_name in reg_num_dict: - return reg_num_dict[reg_name] - return LLDB_INVALID_REGNUM - -x86_64_register_infos = [ - {'name': 'rax', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'rbx', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'rcx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg4'}, - {'name': 'rdx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg3'}, - {'name': 'rsi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg2'}, - {'name': 'rdi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg1'}, - {'name': 'rbp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'fp'}, - {'name': 'rsp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'sp'}, - {'name': 'r8', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg5'}, - {'name': 'r9', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg6'}, - {'name': 'r10', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r11', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r12', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r13', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r14', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r15', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'rip', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'pc'}, - {'name': 'rflags', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'cs', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'ss', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'ds', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'es', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fs', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'gs', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'stmm0', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm1', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm2', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm3', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm4', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm5', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm6', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm7', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'fctrl', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fstat', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'ftag', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fiseg', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fioff', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'foseg', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fooff', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fop', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'xmm0', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm1', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm2', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm3', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm4', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm5', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm6', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm7', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm8', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm9', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm10', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm11', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm12', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm13', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm14', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm15', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'mxcsr', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'orig_rax', 'set': 1, 'bitsize': 64, - 'encoding': eEncodingUint, 'format': eFormatHex}, - # Registers that are contained in or composed of one of more other - # registers - {'name': 'eax', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[31:0]'}, - {'name': 'ebx', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[31:0]'}, - {'name': 'ecx', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[31:0]'}, - {'name': 'edx', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[31:0]'}, - {'name': 'edi', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdi[31:0]'}, - {'name': 'esi', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsi[31:0]'}, - {'name': 'ebp', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbp[31:0]'}, - {'name': 'esp', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsp[31:0]'}, - {'name': 'r8d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r8[31:0]'}, - {'name': 'r9d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r9[31:0]'}, - {'name': 'r10d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r10[31:0]'}, - {'name': 'r11d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r11[31:0]'}, - {'name': 'r12d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r12[31:0]'}, - {'name': 'r13d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r13[31:0]'}, - {'name': 'r14d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r14[31:0]'}, - {'name': 'r15d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r15[31:0]'}, - - {'name': 'ax', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[15:0]'}, - {'name': 'bx', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[15:0]'}, - {'name': 'cx', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[15:0]'}, - {'name': 'dx', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[15:0]'}, - {'name': 'di', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdi[15:0]'}, - {'name': 'si', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsi[15:0]'}, - {'name': 'bp', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbp[15:0]'}, - {'name': 'sp', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsp[15:0]'}, - {'name': 'r8w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r8[15:0]'}, - {'name': 'r9w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r9[15:0]'}, - {'name': 'r10w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r10[15:0]'}, - {'name': 'r11w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r11[15:0]'}, - {'name': 'r12w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r12[15:0]'}, - {'name': 'r13w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r13[15:0]'}, - {'name': 'r14w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r14[15:0]'}, - {'name': 'r15w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r15[15:0]'}, - - {'name': 'ah', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[15:8]'}, - {'name': 'bh', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[15:8]'}, - {'name': 'ch', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[15:8]'}, - {'name': 'dh', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[15:8]'}, - - {'name': 'al', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[7:0]'}, - {'name': 'bl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[7:0]'}, - {'name': 'cl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[7:0]'}, - {'name': 'dl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[7:0]'}, - {'name': 'dil', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdi[7:0]'}, - {'name': 'sil', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsi[7:0]'}, - {'name': 'bpl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbp[7:0]'}, - {'name': 'spl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsp[7:0]'}, - {'name': 'r8l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r8[7:0]'}, - {'name': 'r9l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r9[7:0]'}, - {'name': 'r10l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r10[7:0]'}, - {'name': 'r11l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r11[7:0]'}, - {'name': 'r12l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r12[7:0]'}, - {'name': 'r13l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r13[7:0]'}, - {'name': 'r14l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r14[7:0]'}, - {'name': 'r15l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r15[7:0]'}, -] - -g_target_definition = None - - -def get_target_definition(): - global g_target_definition - if g_target_definition is None: - g_target_definition = {} - offset = 0 - for reg_info in x86_64_register_infos: - reg_name = reg_info['name'] - - # Only fill in the offset if there is no 'slice' in the register - # info - if 'slice' not in reg_info and 'composite' not in reg_info: - reg_info['offset'] = offset - offset += reg_info['bitsize'] / 8 - - # Set the GCC/DWARF register number for this register if it has one - reg_num = get_reg_num(name_to_gcc_dwarf_regnum, reg_name) - if reg_num != LLDB_INVALID_REGNUM: - reg_info['gcc'] = reg_num - reg_info['dwarf'] = reg_num - - # Set the generic register number for this register if it has one - reg_num = get_reg_num(name_to_generic_regnum, reg_name) - if reg_num != LLDB_INVALID_REGNUM: - reg_info['generic'] = reg_num - - # Set the GDB register number for this register if it has one - reg_num = get_reg_num(name_to_gdb_regnum, reg_name) - if reg_num != LLDB_INVALID_REGNUM: - reg_info['gdb'] = reg_num - - g_target_definition['sets'] = [ - 'General Purpose Registers', - 'Floating Point Registers'] - g_target_definition['registers'] = x86_64_register_infos - g_target_definition[ - 'host-info'] = {'triple': 'x86_64-*-linux', 'endian': eByteOrderLittle} - g_target_definition['g-packet-size'] = offset - g_target_definition['breakpoint-pc-offset'] = -1 - return g_target_definition - - -def get_dynamic_setting(target, setting_name): - if setting_name == 'gdb-server-target-definition': - return get_target_definition() diff --git a/examples/python/x86_64_qemu_target_definition.py b/examples/python/x86_64_qemu_target_definition.py deleted file mode 100644 index 5b4ea480ccf3..000000000000 --- a/examples/python/x86_64_qemu_target_definition.py +++ /dev/null @@ -1,773 +0,0 @@ -#!/usr/bin/python -#===-- x86_64_qemu_target_definition.py -----------------------------*- C++ -*-===// -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===----------------------------------------------------------------------===// - -#---------------------------------------------------------------------- -# DESCRIPTION -# -# This file can be used with the following setting: -# plugin.process.gdb-remote.target-definition-file -# This setting should be used when you are trying to connect to a -# remote GDB server that doesn't support any of the register discovery -# packets that LLDB normally uses. -# -# Why is this necessary? LLDB doesn't require a new build of LLDB that -# targets each new architecture you will debug with. Instead, all -# architectures are supported and LLDB relies on extra GDB server -# packets to discover the target we are connecting to so that is can -# show the right registers for each target. This allows the remote stub -# to change and add new registers without requiring a new LLDB build -# just so we can see new registers. -# -# This file implements the x86_64 registers for the user mode qemu on linux. -# The only difference with the Linux file is the absense of orig_rax register. -# -# USAGE -# -# (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/x86_64_qemu_target_definition.py -# (lldb) gdb-remote other.baz.com:1234 -# -# The target definition file will get used if and only if the -# qRegisterInfo packets are not supported when connecting to a remote -# GDB stub. -#---------------------------------------------------------------------- -from lldb import * - -# Compiler and DWARF register numbers -name_to_gcc_dwarf_regnum = { - 'rax': 0, - 'rdx': 1, - 'rcx': 2, - 'rbx': 3, - 'rsi': 4, - 'rdi': 5, - 'rbp': 6, - 'rsp': 7, - 'r8': 8, - 'r9': 9, - 'r10': 10, - 'r11': 11, - 'r12': 12, - 'r13': 13, - 'r14': 14, - 'r15': 15, - 'rip': 16, - 'xmm0': 17, - 'xmm1': 18, - 'xmm2': 19, - 'xmm3': 20, - 'xmm4': 21, - 'xmm5': 22, - 'xmm6': 23, - 'xmm7': 24, - 'xmm8': 25, - 'xmm9': 26, - 'xmm10': 27, - 'xmm11': 28, - 'xmm12': 29, - 'xmm13': 30, - 'xmm14': 31, - 'xmm15': 32, - 'stmm0': 33, - 'stmm1': 34, - 'stmm2': 35, - 'stmm3': 36, - 'stmm4': 37, - 'stmm5': 38, - 'stmm6': 39, - 'stmm7': 30, - 'ymm0': 41, - 'ymm1': 42, - 'ymm2': 43, - 'ymm3': 44, - 'ymm4': 45, - 'ymm5': 46, - 'ymm6': 47, - 'ymm7': 48, - 'ymm8': 49, - 'ymm9': 40, - 'ymm10': 41, - 'ymm11': 42, - 'ymm12': 43, - 'ymm13': 44, - 'ymm14': 45, - 'ymm15': 46 -} - -name_to_gdb_regnum = { - 'rax': 0, - 'rbx': 1, - 'rcx': 2, - 'rdx': 3, - 'rsi': 4, - 'rdi': 5, - 'rbp': 6, - 'rsp': 7, - 'r8': 8, - 'r9': 9, - 'r10': 10, - 'r11': 11, - 'r12': 12, - 'r13': 13, - 'r14': 14, - 'r15': 15, - 'rip': 16, - 'rflags': 17, - 'cs': 18, - 'ss': 19, - 'ds': 20, - 'es': 21, - 'fs': 22, - 'gs': 23, - 'stmm0': 24, - 'stmm1': 25, - 'stmm2': 26, - 'stmm3': 27, - 'stmm4': 28, - 'stmm5': 29, - 'stmm6': 30, - 'stmm7': 31, - 'fctrl': 32, - 'fstat': 33, - 'ftag': 34, - 'fiseg': 35, - 'fioff': 36, - 'foseg': 37, - 'fooff': 38, - 'fop': 39, - 'xmm0': 40, - 'xmm1': 41, - 'xmm2': 42, - 'xmm3': 43, - 'xmm4': 44, - 'xmm5': 45, - 'xmm6': 46, - 'xmm7': 47, - 'xmm8': 48, - 'xmm9': 49, - 'xmm10': 50, - 'xmm11': 51, - 'xmm12': 52, - 'xmm13': 53, - 'xmm14': 54, - 'xmm15': 55, - 'mxcsr': 56, - 'ymm0': 57, - 'ymm1': 58, - 'ymm2': 59, - 'ymm3': 60, - 'ymm4': 61, - 'ymm5': 62, - 'ymm6': 63, - 'ymm7': 64, - 'ymm8': 65, - 'ymm9': 66, - 'ymm10': 67, - 'ymm11': 68, - 'ymm12': 69, - 'ymm13': 70, - 'ymm14': 71, - 'ymm15': 72 -} - -name_to_generic_regnum = { - 'rip': LLDB_REGNUM_GENERIC_PC, - 'rsp': LLDB_REGNUM_GENERIC_SP, - 'rbp': LLDB_REGNUM_GENERIC_FP, - 'rdi': LLDB_REGNUM_GENERIC_ARG1, - 'rsi': LLDB_REGNUM_GENERIC_ARG2, - 'rdx': LLDB_REGNUM_GENERIC_ARG3, - 'rcx': LLDB_REGNUM_GENERIC_ARG4, - 'r8': LLDB_REGNUM_GENERIC_ARG5, - 'r9': LLDB_REGNUM_GENERIC_ARG6 -} - - -def get_reg_num(reg_num_dict, reg_name): - if reg_name in reg_num_dict: - return reg_num_dict[reg_name] - return LLDB_INVALID_REGNUM - -x86_64_register_infos = [ - {'name': 'rax', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'rbx', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'rcx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg4'}, - {'name': 'rdx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg3'}, - {'name': 'rsi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg2'}, - {'name': 'rdi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg1'}, - {'name': 'rbp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'fp'}, - {'name': 'rsp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'sp'}, - {'name': 'r8', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg5'}, - {'name': 'r9', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg6'}, - {'name': 'r10', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r11', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r12', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r13', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r14', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r15', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'rip', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'pc'}, - {'name': 'rflags', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'cs', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'ss', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'ds', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'es', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fs', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'gs', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'stmm0', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm1', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm2', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm3', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm4', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm5', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm6', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm7', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'fctrl', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fstat', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'ftag', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fiseg', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fioff', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'foseg', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fooff', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fop', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'xmm0', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm1', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm2', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm3', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm4', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm5', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm6', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm7', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm8', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm9', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm10', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm11', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm12', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm13', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm14', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm15', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'mxcsr', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - # Registers that are contained in or composed of one of more other - # registers - {'name': 'eax', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[31:0]'}, - {'name': 'ebx', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[31:0]'}, - {'name': 'ecx', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[31:0]'}, - {'name': 'edx', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[31:0]'}, - {'name': 'edi', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdi[31:0]'}, - {'name': 'esi', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsi[31:0]'}, - {'name': 'ebp', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbp[31:0]'}, - {'name': 'esp', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsp[31:0]'}, - {'name': 'r8d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r8[31:0]'}, - {'name': 'r9d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r9[31:0]'}, - {'name': 'r10d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r10[31:0]'}, - {'name': 'r11d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r11[31:0]'}, - {'name': 'r12d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r12[31:0]'}, - {'name': 'r13d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r13[31:0]'}, - {'name': 'r14d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r14[31:0]'}, - {'name': 'r15d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r15[31:0]'}, - - {'name': 'ax', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[15:0]'}, - {'name': 'bx', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[15:0]'}, - {'name': 'cx', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[15:0]'}, - {'name': 'dx', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[15:0]'}, - {'name': 'di', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdi[15:0]'}, - {'name': 'si', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsi[15:0]'}, - {'name': 'bp', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbp[15:0]'}, - {'name': 'sp', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsp[15:0]'}, - {'name': 'r8w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r8[15:0]'}, - {'name': 'r9w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r9[15:0]'}, - {'name': 'r10w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r10[15:0]'}, - {'name': 'r11w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r11[15:0]'}, - {'name': 'r12w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r12[15:0]'}, - {'name': 'r13w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r13[15:0]'}, - {'name': 'r14w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r14[15:0]'}, - {'name': 'r15w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r15[15:0]'}, - - {'name': 'ah', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[15:8]'}, - {'name': 'bh', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[15:8]'}, - {'name': 'ch', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[15:8]'}, - {'name': 'dh', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[15:8]'}, - - {'name': 'al', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[7:0]'}, - {'name': 'bl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[7:0]'}, - {'name': 'cl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[7:0]'}, - {'name': 'dl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[7:0]'}, - {'name': 'dil', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdi[7:0]'}, - {'name': 'sil', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsi[7:0]'}, - {'name': 'bpl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbp[7:0]'}, - {'name': 'spl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsp[7:0]'}, - {'name': 'r8l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r8[7:0]'}, - {'name': 'r9l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r9[7:0]'}, - {'name': 'r10l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r10[7:0]'}, - {'name': 'r11l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r11[7:0]'}, - {'name': 'r12l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r12[7:0]'}, - {'name': 'r13l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r13[7:0]'}, - {'name': 'r14l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r14[7:0]'}, - {'name': 'r15l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r15[7:0]'}, -] - -g_target_definition = None - - -def get_target_definition(): - global g_target_definition - if g_target_definition is None: - g_target_definition = {} - offset = 0 - for reg_info in x86_64_register_infos: - reg_name = reg_info['name'] - - # Only fill in the offset if there is no 'slice' in the register - # info - if 'slice' not in reg_info and 'composite' not in reg_info: - reg_info['offset'] = offset - offset += reg_info['bitsize'] / 8 - - # Set the GCC/DWARF register number for this register if it has one - reg_num = get_reg_num(name_to_gcc_dwarf_regnum, reg_name) - if reg_num != LLDB_INVALID_REGNUM: - reg_info['gcc'] = reg_num - reg_info['dwarf'] = reg_num - - # Set the generic register number for this register if it has one - reg_num = get_reg_num(name_to_generic_regnum, reg_name) - if reg_num != LLDB_INVALID_REGNUM: - reg_info['generic'] = reg_num - - # Set the GDB register number for this register if it has one - reg_num = get_reg_num(name_to_gdb_regnum, reg_name) - if reg_num != LLDB_INVALID_REGNUM: - reg_info['gdb'] = reg_num - - g_target_definition['sets'] = [ - 'General Purpose Registers', - 'Floating Point Registers'] - g_target_definition['registers'] = x86_64_register_infos - g_target_definition[ - 'host-info'] = {'triple': 'x86_64-*-linux', 'endian': eByteOrderLittle} - g_target_definition['g-packet-size'] = offset - g_target_definition['breakpoint-pc-offset'] = -1 - return g_target_definition - - -def get_dynamic_setting(target, setting_name): - if setting_name == 'gdb-server-target-definition': - return get_target_definition() diff --git a/examples/python/x86_64_target_definition.py b/examples/python/x86_64_target_definition.py deleted file mode 100644 index 03411cf07c20..000000000000 --- a/examples/python/x86_64_target_definition.py +++ /dev/null @@ -1,778 +0,0 @@ -#!/usr/bin/python -#===-- x86_64_target_definition.py -----------------------------*- C++ -*-===// -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===----------------------------------------------------------------------===// - -#---------------------------------------------------------------------- -# DESCRIPTION -# -# This file can be used with the following setting: -# plugin.process.gdb-remote.target-definition-file -# This setting should be used when you are trying to connect to a -# remote GDB server that doesn't support any of the register discovery -# packets that LLDB normally uses. -# -# Why is this necessary? LLDB doesn't require a new build of LLDB that -# targets each new architecture you will debug with. Instead, all -# architectures are supported and LLDB relies on extra GDB server -# packets to discover the target we are connecting to so that is can -# show the right registers for each target. This allows the GDB server -# to change and add new registers without requiring a new LLDB build -# just so we can see new registers. -# -# This file implements the x86_64 registers for the darwin version of -# GDB and allows you to connect to servers that use this register set. -# -# USAGE -# -# (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/x86_64_target_definition.py -# (lldb) gdb-remote other.baz.com:1234 -# -# The target definition file will get used if and only if the -# qRegisterInfo packets are not supported when connecting to a remote -# GDB server. -#---------------------------------------------------------------------- -from lldb import * - -# Compiler and DWARF register numbers -name_to_gcc_dwarf_regnum = { - 'rax': 0, - 'rdx': 1, - 'rcx': 2, - 'rbx': 3, - 'rsi': 4, - 'rdi': 5, - 'rbp': 6, - 'rsp': 7, - 'r8': 8, - 'r9': 9, - 'r10': 10, - 'r11': 11, - 'r12': 12, - 'r13': 13, - 'r14': 14, - 'r15': 15, - 'rip': 16, - 'xmm0': 17, - 'xmm1': 18, - 'xmm2': 19, - 'xmm3': 20, - 'xmm4': 21, - 'xmm5': 22, - 'xmm6': 23, - 'xmm7': 24, - 'xmm8': 25, - 'xmm9': 26, - 'xmm10': 27, - 'xmm11': 28, - 'xmm12': 29, - 'xmm13': 30, - 'xmm14': 31, - 'xmm15': 32, - 'stmm0': 33, - 'stmm1': 34, - 'stmm2': 35, - 'stmm3': 36, - 'stmm4': 37, - 'stmm5': 38, - 'stmm6': 39, - 'stmm7': 30, - 'ymm0': 41, - 'ymm1': 42, - 'ymm2': 43, - 'ymm3': 44, - 'ymm4': 45, - 'ymm5': 46, - 'ymm6': 47, - 'ymm7': 48, - 'ymm8': 49, - 'ymm9': 40, - 'ymm10': 41, - 'ymm11': 42, - 'ymm12': 43, - 'ymm13': 44, - 'ymm14': 45, - 'ymm15': 46 -} - -name_to_gdb_regnum = { - 'rax': 0, - 'rbx': 1, - 'rcx': 2, - 'rdx': 3, - 'rsi': 4, - 'rdi': 5, - 'rbp': 6, - 'rsp': 7, - 'r8': 8, - 'r9': 9, - 'r10': 10, - 'r11': 11, - 'r12': 12, - 'r13': 13, - 'r14': 14, - 'r15': 15, - 'rip': 16, - 'rflags': 17, - 'cs': 18, - 'ss': 19, - 'ds': 20, - 'es': 21, - 'fs': 22, - 'gs': 23, - 'stmm0': 24, - 'stmm1': 25, - 'stmm2': 26, - 'stmm3': 27, - 'stmm4': 28, - 'stmm5': 29, - 'stmm6': 30, - 'stmm7': 31, - 'fctrl': 32, - 'fstat': 33, - 'ftag': 34, - 'fiseg': 35, - 'fioff': 36, - 'foseg': 37, - 'fooff': 38, - 'fop': 39, - 'xmm0': 40, - 'xmm1': 41, - 'xmm2': 42, - 'xmm3': 43, - 'xmm4': 44, - 'xmm5': 45, - 'xmm6': 46, - 'xmm7': 47, - 'xmm8': 48, - 'xmm9': 49, - 'xmm10': 50, - 'xmm11': 51, - 'xmm12': 52, - 'xmm13': 53, - 'xmm14': 54, - 'xmm15': 55, - 'mxcsr': 56, - 'ymm0': 57, - 'ymm1': 58, - 'ymm2': 59, - 'ymm3': 60, - 'ymm4': 61, - 'ymm5': 62, - 'ymm6': 63, - 'ymm7': 64, - 'ymm8': 65, - 'ymm9': 66, - 'ymm10': 67, - 'ymm11': 68, - 'ymm12': 69, - 'ymm13': 70, - 'ymm14': 71, - 'ymm15': 72 -} - -name_to_generic_regnum = { - 'rip': LLDB_REGNUM_GENERIC_PC, - 'rsp': LLDB_REGNUM_GENERIC_SP, - 'rbp': LLDB_REGNUM_GENERIC_FP, - 'rdi': LLDB_REGNUM_GENERIC_ARG1, - 'rsi': LLDB_REGNUM_GENERIC_ARG2, - 'rdx': LLDB_REGNUM_GENERIC_ARG3, - 'rcx': LLDB_REGNUM_GENERIC_ARG4, - 'r8': LLDB_REGNUM_GENERIC_ARG5, - 'r9': LLDB_REGNUM_GENERIC_ARG6 -} - - -def get_reg_num(reg_num_dict, reg_name): - if reg_name in reg_num_dict: - return reg_num_dict[reg_name] - return LLDB_INVALID_REGNUM - - -def get_reg_num(reg_num_dict, reg_name): - if reg_name in reg_num_dict: - return reg_num_dict[reg_name] - return LLDB_INVALID_REGNUM - -x86_64_register_infos = [ - {'name': 'rax', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'rbx', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'rcx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg4'}, - {'name': 'rdx', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg3'}, - {'name': 'rsi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg2'}, - {'name': 'rdi', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg1'}, - {'name': 'rbp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'fp'}, - {'name': 'rsp', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'sp'}, - {'name': 'r8', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg5'}, - {'name': 'r9', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'arg6'}, - {'name': 'r10', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r11', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r12', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r13', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r14', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'r15', - 'set': 0, - 'bitsize': 64, - 'encoding': eEncodingUint, - 'format': eFormatAddressInfo}, - {'name': 'rip', 'set': 0, 'bitsize': 64, 'encoding': eEncodingUint, - 'format': eFormatAddressInfo, 'alt-name': 'pc'}, - {'name': 'rflags', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'cs', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'ss', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'ds', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'es', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fs', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'gs', 'set': 0, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'stmm0', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm1', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm2', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm3', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm4', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm5', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm6', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'stmm7', - 'set': 1, - 'bitsize': 80, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'fctrl', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fstat', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'ftag', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fiseg', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fioff', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'foseg', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fooff', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'fop', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - {'name': 'xmm0', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm1', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm2', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm3', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm4', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm5', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm6', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm7', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm8', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm9', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm10', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm11', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm12', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm13', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm14', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'xmm15', - 'set': 1, - 'bitsize': 128, - 'encoding': eEncodingVector, - 'format': eFormatVectorOfUInt8}, - {'name': 'mxcsr', 'set': 1, 'bitsize': 32, - 'encoding': eEncodingUint, 'format': eFormatHex}, - # Registers that are contained in or composed of one of more other - # registers - {'name': 'eax', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[31:0]'}, - {'name': 'ebx', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[31:0]'}, - {'name': 'ecx', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[31:0]'}, - {'name': 'edx', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[31:0]'}, - {'name': 'edi', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdi[31:0]'}, - {'name': 'esi', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsi[31:0]'}, - {'name': 'ebp', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbp[31:0]'}, - {'name': 'esp', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsp[31:0]'}, - {'name': 'r8d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r8[31:0]'}, - {'name': 'r9d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r9[31:0]'}, - {'name': 'r10d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r10[31:0]'}, - {'name': 'r11d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r11[31:0]'}, - {'name': 'r12d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r12[31:0]'}, - {'name': 'r13d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r13[31:0]'}, - {'name': 'r14d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r14[31:0]'}, - {'name': 'r15d', - 'set': 0, - 'bitsize': 32, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r15[31:0]'}, - - {'name': 'ax', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[15:0]'}, - {'name': 'bx', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[15:0]'}, - {'name': 'cx', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[15:0]'}, - {'name': 'dx', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[15:0]'}, - {'name': 'di', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdi[15:0]'}, - {'name': 'si', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsi[15:0]'}, - {'name': 'bp', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbp[15:0]'}, - {'name': 'sp', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsp[15:0]'}, - {'name': 'r8w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r8[15:0]'}, - {'name': 'r9w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r9[15:0]'}, - {'name': 'r10w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r10[15:0]'}, - {'name': 'r11w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r11[15:0]'}, - {'name': 'r12w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r12[15:0]'}, - {'name': 'r13w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r13[15:0]'}, - {'name': 'r14w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r14[15:0]'}, - {'name': 'r15w', - 'set': 0, - 'bitsize': 16, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r15[15:0]'}, - - {'name': 'ah', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[15:8]'}, - {'name': 'bh', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[15:8]'}, - {'name': 'ch', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[15:8]'}, - {'name': 'dh', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[15:8]'}, - - {'name': 'al', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rax[7:0]'}, - {'name': 'bl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbx[7:0]'}, - {'name': 'cl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rcx[7:0]'}, - {'name': 'dl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdx[7:0]'}, - {'name': 'dil', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rdi[7:0]'}, - {'name': 'sil', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsi[7:0]'}, - {'name': 'bpl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rbp[7:0]'}, - {'name': 'spl', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'rsp[7:0]'}, - {'name': 'r8l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r8[7:0]'}, - {'name': 'r9l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r9[7:0]'}, - {'name': 'r10l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r10[7:0]'}, - {'name': 'r11l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r11[7:0]'}, - {'name': 'r12l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r12[7:0]'}, - {'name': 'r13l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r13[7:0]'}, - {'name': 'r14l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r14[7:0]'}, - {'name': 'r15l', - 'set': 0, - 'bitsize': 8, - 'encoding': eEncodingUint, - 'format': eFormatHex, - 'slice': 'r15[7:0]'}, -] - -g_target_definition = None - - -def get_target_definition(): - global g_target_definition - if g_target_definition is None: - g_target_definition = {} - offset = 0 - for reg_info in x86_64_register_infos: - reg_name = reg_info['name'] - - # Only fill in the offset if there is no 'slice' in the register - # info - if 'slice' not in reg_info and 'composite' not in reg_info: - reg_info['offset'] = offset - offset += reg_info['bitsize'] / 8 - - # Set the GCC/DWARF register number for this register if it has one - reg_num = get_reg_num(name_to_gcc_dwarf_regnum, reg_name) - if reg_num != LLDB_INVALID_REGNUM: - reg_info['gcc'] = reg_num - reg_info['dwarf'] = reg_num - - # Set the generic register number for this register if it has one - reg_num = get_reg_num(name_to_generic_regnum, reg_name) - if reg_num != LLDB_INVALID_REGNUM: - reg_info['generic'] = reg_num - - # Set the GDB register number for this register if it has one - reg_num = get_reg_num(name_to_gdb_regnum, reg_name) - if reg_num != LLDB_INVALID_REGNUM: - reg_info['gdb'] = reg_num - - g_target_definition['sets'] = [ - 'General Purpose Registers', - 'Floating Point Registers'] - g_target_definition['registers'] = x86_64_register_infos - g_target_definition[ - 'host-info'] = {'triple': 'x86_64-apple-macosx', 'endian': eByteOrderLittle} - g_target_definition['g-packet-size'] = offset - return g_target_definition - - -def get_dynamic_setting(target, setting_name): - if setting_name == 'gdb-server-target-definition': - return get_target_definition() |