Initial import of lldb
Change-Id: Ib244e837bee349effa12b2ff6ffffbe3d730e929
This commit is contained in:
76
external/bsd/llvm/dist/lldb/examples/python/cmdtemplate.py
vendored
Normal file
76
external/bsd/llvm/dist/lldb/examples/python/cmdtemplate.py
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/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 lldb
|
||||
import commands
|
||||
import optparse
|
||||
import shlex
|
||||
|
||||
def create_framestats_options():
|
||||
usage = "usage: %prog [options]"
|
||||
description='''This command is meant to be an example of how to make an LLDB command that
|
||||
does something useful, follows best practices, and exploits the SB API.
|
||||
Specifically, this command computes the aggregate and average size of the variables in the current frame
|
||||
and allows you to tweak exactly which variables are to be accounted in the computation.
|
||||
'''
|
||||
parser = optparse.OptionParser(description=description, prog='framestats',usage=usage)
|
||||
parser.add_option('-i', '--in-scope', action='store_true', dest='inscope', help='in_scope_only = True', default=False)
|
||||
parser.add_option('-a', '--arguments', action='store_true', dest='arguments', help='arguments = True', default=False)
|
||||
parser.add_option('-l', '--locals', action='store_true', dest='locals', help='locals = True', default=False)
|
||||
parser.add_option('-s', '--statics', action='store_true', dest='statics', help='statics = True', default=False)
|
||||
return parser
|
||||
|
||||
def the_framestats_command(debugger, command, result, dict):
|
||||
# Use the Shell Lexer to properly parse up command options just like a
|
||||
# shell would
|
||||
command_args = shlex.split(command)
|
||||
parser = create_framestats_options()
|
||||
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.SetError ("option parsing failed")
|
||||
return
|
||||
|
||||
# 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
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
thread = process.GetSelectedThread()
|
||||
frame = thread.GetSelectedFrame()
|
||||
if not frame.IsValid():
|
||||
return "no frame here"
|
||||
# from now on, replace lldb.<thing>.whatever with <thing>.whatever
|
||||
variables_list = frame.GetVariables(options.arguments, options.locals, options.statics, options.inscope)
|
||||
variables_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):
|
||||
# This initializer is being run from LLDB in the embedded command interpreter
|
||||
# Make the options so we can generate the help text for the new LLDB
|
||||
# command line command prior to registering it with LLDB below
|
||||
parser = create_framestats_options()
|
||||
the_framestats_command.__doc__ = parser.format_help()
|
||||
# Add any commands contained in this module to LLDB
|
||||
debugger.HandleCommand('command script add -f cmdtemplate.the_framestats_command framestats')
|
||||
print 'The "framestats" command has been installed, type "help framestats" or "framestats --help" for detailed help.'
|
||||
782
external/bsd/llvm/dist/lldb/examples/python/crashlog.py
vendored
Executable file
782
external/bsd/llvm/dist/lldb/examples/python/crashlog.py
vendored
Executable file
@@ -0,0 +1,782 @@
|
||||
#!/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]+)([^:]*):(.*)')
|
||||
frame_regex = re.compile('^([0-9]+) +([^ ]+) *\t?(0x[0-9a-fA-F]+) +(.*)')
|
||||
image_regex_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^<]+)<([-0-9a-fA-F]+)> (.*)');
|
||||
image_regex_no_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^/]+)/(.*)');
|
||||
empty_line_regex = re.compile('^$')
|
||||
|
||||
class Thread:
|
||||
"""Class that represents a thread in a darwin crash log"""
|
||||
def __init__(self, index):
|
||||
self.index = index
|
||||
self.frames = list()
|
||||
self.idents = list()
|
||||
self.registers = dict()
|
||||
self.reason = None
|
||||
self.queue = None
|
||||
|
||||
def dump(self, prefix):
|
||||
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 add_ident(self, ident):
|
||||
if not ident in self.idents:
|
||||
self.idents.append(ident)
|
||||
|
||||
def did_crash(self):
|
||||
return self.reason != None
|
||||
|
||||
def __str__(self):
|
||||
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 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:
|
||||
plist_root = plistlib.readPlistFromString (s)
|
||||
if plist_root:
|
||||
plist = plist_root[uuid_str]
|
||||
if plist:
|
||||
if 'DBGArchitecture' in plist:
|
||||
self.arch = plist['DBGArchitecture']
|
||||
if 'DBGDSYMPath' in plist:
|
||||
self.symfile = os.path.realpath(plist['DBGDSYMPath'])
|
||||
if 'DBGSymbolRichExecutable' in plist:
|
||||
self.resolved_path = os.path.expanduser (plist['DBGSymbolRichExecutable'])
|
||||
if not self.resolved_path and os.path.exists(self.path):
|
||||
dwarfdump_cmd_output = commands.getoutput('dwarfdump --uuid "%s"' % self.path)
|
||||
self_uuid = self.get_uuid()
|
||||
for line in dwarfdump_cmd_output.splitlines():
|
||||
match = self.dwarfdump_uuid_regex.search (line)
|
||||
if match:
|
||||
dwarf_uuid_str = match.group(1)
|
||||
dwarf_uuid = uuid.UUID(dwarf_uuid_str)
|
||||
if self_uuid == dwarf_uuid:
|
||||
self.resolved_path = self.path
|
||||
self.arch = match.group(2)
|
||||
break;
|
||||
if not self.resolved_path:
|
||||
self.unavailable = True
|
||||
print "error\n error: unable to locate '%s' with UUID %s" % (self.path, uuid_str)
|
||||
return False
|
||||
if (self.resolved_path and os.path.exists(self.resolved_path)) or (self.path and os.path.exists(self.path)):
|
||||
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.idents = list() # A list of the required identifiers for doing all stack backtraces
|
||||
self.crashed_thread_idx = -1
|
||||
self.version = -1
|
||||
self.error = 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
|
||||
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
|
||||
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 ('Crashed Thread:'):
|
||||
self.crashed_thread_idx = int(line[15:].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:
|
||||
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:
|
||||
# print 'PARSE_MODE_THREAD'
|
||||
parse_mode = PARSE_MODE_THREAD
|
||||
thread_idx = int(thread_match.group(1))
|
||||
thread = CrashLog.Thread(thread_idx)
|
||||
continue
|
||||
elif line.startswith ('Binary Images:'):
|
||||
parse_mode = PARSE_MODE_IMAGES
|
||||
continue
|
||||
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 not ident 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:
|
||||
image = CrashLog.DarwinImage (int(image_match.group(1),0),
|
||||
int(image_match.group(2),0),
|
||||
image_match.group(3).strip(),
|
||||
image_match.group(4).strip(),
|
||||
uuid.UUID(image_match.group(5)),
|
||||
image_match.group(6))
|
||||
self.images.append (image)
|
||||
else:
|
||||
image_match = self.image_regex_no_uuid.search (line)
|
||||
if image_match:
|
||||
image = CrashLog.DarwinImage (int(image_match.group(1),0),
|
||||
int(image_match.group(2),0),
|
||||
image_match.group(3).strip(),
|
||||
image_match.group(4).strip(),
|
||||
None,
|
||||
image_match.group(5))
|
||||
self.images.append (image)
|
||||
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)
|
||||
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
|
||||
return None
|
||||
|
||||
def create_target(self):
|
||||
#print 'crashlog.create_target()...'
|
||||
target = symbolication.Symbolicator.create_target(self)
|
||||
if target:
|
||||
return 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:
|
||||
target = image.create_target ()
|
||||
if target:
|
||||
return target # success
|
||||
print 'crashlog.create_target()...3'
|
||||
for image in self.images:
|
||||
target = image.create_target ()
|
||||
if target:
|
||||
return target # success
|
||||
print 'crashlog.create_target()...4'
|
||||
print 'error: unable to locate any executables from the crash log'
|
||||
return None
|
||||
|
||||
|
||||
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, 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
|
||||
if lldb.target:
|
||||
identifier = lldb.target.executable.basename
|
||||
if lldb.process:
|
||||
pid = lldb.process.id
|
||||
if pid != lldb.LLDB_INVALID_PROCESS_ID:
|
||||
out_file.write('Process: %s [%u]\n' % (identifier, pid))
|
||||
out_file.write('Path: %s\n' % (lldb.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(lldb.process.num_threads):
|
||||
thread = lldb.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 lldb.target.modules:
|
||||
text_segment = module.section['__TEXT']
|
||||
if text_segment:
|
||||
text_segment_load_addr = text_segment.GetLoadAddress(lldb.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 in loaded_images:
|
||||
print "warning: skipping %s loaded at %#16.16x duplicate entry (probably commpage)" % (image.path, image.text_addr_lo)
|
||||
else:
|
||||
err = image.add_module (target)
|
||||
if err:
|
||||
print err
|
||||
else:
|
||||
#print 'loaded %s' % image
|
||||
loaded_images.append(image)
|
||||
|
||||
for thread in crash_log.threads:
|
||||
this_thread_crashed = thread.did_crash()
|
||||
if options.crashed_only and this_thread_crashed == False:
|
||||
continue
|
||||
print "%s" % thread
|
||||
#prev_frame_index = -1
|
||||
display_frame_idx = -1
|
||||
for frame_idx, frame in enumerate(thread.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 thread.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 (target,
|
||||
instructions,
|
||||
frame.pc,
|
||||
options.disassemble_before,
|
||||
options.disassemble_after, frame.index > 0)
|
||||
print
|
||||
symbolicated_frame_address_idx += 1
|
||||
else:
|
||||
print frame
|
||||
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:])
|
||||
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'
|
||||
|
||||
115
external/bsd/llvm/dist/lldb/examples/python/delta.py
vendored
Executable file
115
external/bsd/llvm/dist/lldb/examples/python/delta.py
vendored
Executable file
@@ -0,0 +1,115 @@
|
||||
#!/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 fucntion 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'
|
||||
171
external/bsd/llvm/dist/lldb/examples/python/diagnose_nsstring.py
vendored
Normal file
171
external/bsd/llvm/dist/lldb/examples/python/diagnose_nsstring.py
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
# 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
|
||||
270
external/bsd/llvm/dist/lldb/examples/python/diagnose_unwind.py
vendored
Normal file
270
external/bsd/llvm/dist/lldb/examples/python/diagnose_unwind.py
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
# 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 == None:
|
||||
module_uuid_str = ""
|
||||
if sbaddr.GetModule().GetFileSpec():
|
||||
module_filename = sbaddr.GetModule().GetFileSpec().GetFilename()
|
||||
if module_filename == None:
|
||||
module_filename = ""
|
||||
if module_uuid_str != "" or module_filename != "":
|
||||
module_description = '%s %s' % (module_filename, module_uuid_str)
|
||||
except Exception:
|
||||
print '%2d: pc==0x%-*x fp==0x%-*x' % (frame_num, addr_width, addr_for_printing, addr_width, fp)
|
||||
return
|
||||
|
||||
sym_ctx = target.ResolveSymbolContextForAddress(sbaddr, lldb.eSymbolContextEverything)
|
||||
if sym_ctx.IsValid() and sym_ctx.GetSymbol().IsValid():
|
||||
function_start = sym_ctx.GetSymbol().GetStartAddress().GetLoadAddress(target)
|
||||
offset = addr - function_start
|
||||
print '%2d: pc==0x%-*x fp==0x%-*x %s %s + %d' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description, sym_ctx.GetSymbol().GetName(), offset)
|
||||
else:
|
||||
print '%2d: pc==0x%-*x fp==0x%-*x %s' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description)
|
||||
return sbaddr.GetModule()
|
||||
|
||||
# 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 != 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 != None:
|
||||
module_list.append (this_module)
|
||||
frame_num = frame_num + 1
|
||||
next_pc = 0
|
||||
next_fp = 0
|
||||
if target.triple[0:6] == "x86_64" or target.triple[0:4] == "i386" or target.triple[0:3] == "arm":
|
||||
error = lldb.SBError()
|
||||
next_pc = process.ReadPointerFromMemory(cur_fp + process.GetAddressByteSize(), error)
|
||||
if not error.Success():
|
||||
next_pc = 0
|
||||
next_fp = process.ReadPointerFromMemory(cur_fp, error)
|
||||
if not error.Success():
|
||||
next_fp = 0
|
||||
# Clear the 0th bit for arm frames - this indicates it is a thumb frame
|
||||
if target.triple[0:3] == "arm" and (next_pc & 1) == 1:
|
||||
next_pc = next_pc & ~1
|
||||
cur_pc = next_pc
|
||||
cur_fp = next_fp
|
||||
this_module = backtrace_print_frame (target, frame_num, cur_pc, cur_fp)
|
||||
print_stack_frame (process, cur_fp)
|
||||
print ""
|
||||
if this_module != None:
|
||||
module_list.append (this_module)
|
||||
return [module_list, address_list]
|
||||
|
||||
def print_stack_frame(process, fp):
|
||||
if fp == 0 or fp == lldb.LLDB_INVALID_ADDRESS or fp == 1:
|
||||
return
|
||||
addr_size = process.GetAddressByteSize()
|
||||
addr = fp - (2 * addr_size)
|
||||
i = 0
|
||||
outline = "Stack frame from $fp-%d: " % (2 * addr_size)
|
||||
error = lldb.SBError()
|
||||
try:
|
||||
while i < 5 and error.Success():
|
||||
address = process.ReadPointerFromMemory(addr + (i * addr_size), error)
|
||||
outline += " 0x%x" % address
|
||||
i += 1
|
||||
print outline
|
||||
except Exception:
|
||||
return
|
||||
|
||||
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 != None:
|
||||
modules_seen.append (this_module)
|
||||
addresses_seen.append (frame.GetPC())
|
||||
frame_num = frame_num + 1
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "Simple stack walk algorithm:"
|
||||
print ""
|
||||
(module_list, address_list) = simple_backtrace(debugger)
|
||||
if module_list and module_list != None:
|
||||
modules_seen += module_list
|
||||
if address_list and address_list != None:
|
||||
addresses_seen = set(addresses_seen)
|
||||
addresses_seen.update(set(address_list))
|
||||
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "Modules seen in stack walks:"
|
||||
print ""
|
||||
modules_already_seen = set()
|
||||
for module in modules_seen:
|
||||
if module != None and module.GetFileSpec().GetFilename() != None:
|
||||
if not module.GetFileSpec().GetFilename() in modules_already_seen:
|
||||
debugger.HandleCommand('image list %s' % module.GetFileSpec().GetFilename())
|
||||
modules_already_seen.add(module.GetFileSpec().GetFilename())
|
||||
|
||||
print ""
|
||||
print "============================================================================================="
|
||||
print ""
|
||||
print "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.'
|
||||
61
external/bsd/llvm/dist/lldb/examples/python/dict_utils.py
vendored
Executable file
61
external/bsd/llvm/dist/lldb/examples/python/dict_utils.py
vendored
Executable file
@@ -0,0 +1,61 @@
|
||||
|
||||
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 == None:
|
||||
s = "%#8.8x" % self.value
|
||||
return s
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
168
external/bsd/llvm/dist/lldb/examples/python/disasm-stress-test.py
vendored
Executable file
168
external/bsd/llvm/dist/lldb/examples/python/disasm-stress-test.py
vendored
Executable file
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import argparse, datetime, re, subprocess, sys, 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 == None:
|
||||
return None
|
||||
xcode_contents_path = re_result.group(1)
|
||||
return xcode_contents_path + "/SharedFrameworks/LLDB.framework"
|
||||
|
||||
lldb_framework_path = GetLLDBFrameworkPath()
|
||||
|
||||
if lldb_framework_path == None:
|
||||
print "Couldn't find LLDB.framework"
|
||||
sys.exit(-1)
|
||||
|
||||
sys.path.append(lldb_framework_path + "/Resources/Python")
|
||||
|
||||
if arg_ns.lldb == 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 == None:
|
||||
raise StopIteration
|
||||
return ret
|
||||
|
||||
class RandomInstructionProvider:
|
||||
def __init__(self, byte_width, log_file):
|
||||
self.m_byte_width = byte_width
|
||||
self.m_log_file = log_file
|
||||
self.m_random_file = open("/dev/random", 'r')
|
||||
def PrintCurrentState(self, ret):
|
||||
ResetLogFile(self.m_log_file)
|
||||
PrintByteArray(self.m_log_file, ret)
|
||||
def GetNextInstruction(self):
|
||||
ret = bytearray(self.m_byte_width)
|
||||
for i in range(self.m_byte_width):
|
||||
ret[i] = self.m_random_file.read(1)
|
||||
self.PrintCurrentState(ret)
|
||||
return ret
|
||||
def __iter__(self):
|
||||
return self
|
||||
def next(self):
|
||||
ret = self.GetNextInstruction()
|
||||
if ret == None:
|
||||
raise StopIteration
|
||||
return ret
|
||||
|
||||
log_file = None
|
||||
|
||||
def GetProviderWithArguments(args):
|
||||
global log_file
|
||||
if args.log != None:
|
||||
log_file = open(args.log, 'w')
|
||||
else:
|
||||
log_file = sys.stdout
|
||||
instruction_provider = None
|
||||
if args.random == True:
|
||||
instruction_provider = RandomInstructionProvider(args.bytes, log_file)
|
||||
else:
|
||||
start = 0
|
||||
skip = 1
|
||||
if args.start != None:
|
||||
start = args.start
|
||||
if args.skip != 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()
|
||||
119
external/bsd/llvm/dist/lldb/examples/python/disasm.py
vendored
Executable file
119
external/bsd/llvm/dist/lldb/examples/python/disasm.py
vendored
Executable file
@@ -0,0 +1,119 @@
|
||||
#!/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()
|
||||
221
external/bsd/llvm/dist/lldb/examples/python/file_extract.py
vendored
Executable file
221
external/bsd/llvm/dist/lldb/examples/python/file_extract.py
vendored
Executable file
@@ -0,0 +1,221 @@
|
||||
#! /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
|
||||
24
external/bsd/llvm/dist/lldb/examples/python/gdb_disassemble.py
vendored
Executable file
24
external/bsd/llvm/dist/lldb/examples/python/gdb_disassemble.py
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
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'
|
||||
1042
external/bsd/llvm/dist/lldb/examples/python/gdbremote.py
vendored
Executable file
1042
external/bsd/llvm/dist/lldb/examples/python/gdbremote.py
vendored
Executable file
File diff suppressed because it is too large
Load Diff
72
external/bsd/llvm/dist/lldb/examples/python/globals.py
vendored
Executable file
72
external/bsd/llvm/dist/lldb/examples/python/globals.py
vendored
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/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:
|
||||
print 'name = %s' % global_variable.name # returns the global variable name as a string
|
||||
print 'value = %s' % global_variable.value # Returns the variable value as a string
|
||||
print 'type = %s' % global_variable.type # Returns an lldb.SBType object
|
||||
print 'addr = %s' % global_variable.addr # Returns an lldb.SBAddress (section offset address) for this global
|
||||
print 'file_addr = 0x%x' % global_variable.addr.file_addr # Returns the file virtual address for this global
|
||||
print 'location = %s' % global_variable.location # returns the global variable value as a string
|
||||
print 'size = %s' % global_variable.size # Returns the size in bytes of this global variable
|
||||
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:])
|
||||
|
||||
173
external/bsd/llvm/dist/lldb/examples/python/jump.py
vendored
Normal file
173
external/bsd/llvm/dist/lldb/examples/python/jump.py
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
import lldb, 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 != 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 != 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 != 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 != 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 != 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.'
|
||||
59
external/bsd/llvm/dist/lldb/examples/python/lldb_module_utils.py
vendored
Normal file
59
external/bsd/llvm/dist/lldb/examples/python/lldb_module_utils.py
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import lldb
|
||||
import optparse
|
||||
import shlex
|
||||
import string
|
||||
import sys
|
||||
|
||||
def create_dump_module_line_tables_options ():
|
||||
usage = "usage: dump_module_line_tables [options] MODULE1 [MODULE2 ...]"
|
||||
description='''Dumps all line tables from all compile units for any modules specified as arguments. Specifying the --verbose flag will output address ranges for each line entry.'''
|
||||
parser = optparse.OptionParser(description=description, prog='start_gdb_log',usage=usage)
|
||||
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='Display verbose output.', default=False)
|
||||
return parser
|
||||
|
||||
def dump_module_line_tables(debugger, command, result, dict):
|
||||
'''Dumps all line tables from all compile units for any modules specified as arguments.'''
|
||||
command_args = shlex.split(command)
|
||||
|
||||
parser = create_dump_module_line_tables_options ()
|
||||
try:
|
||||
(options, args) = parser.parse_args(command_args)
|
||||
except:
|
||||
return
|
||||
if command_args:
|
||||
target = debugger.GetSelectedTarget()
|
||||
lldb.target = target
|
||||
for module_name in command_args:
|
||||
result.PutCString('Searching for module "%s"' % (module_name,))
|
||||
module_fspec = lldb.SBFileSpec (module_name, False)
|
||||
module = target.FindModule (module_fspec);
|
||||
if module:
|
||||
for cu_idx in range (module.GetNumCompileUnits()):
|
||||
cu = module.GetCompileUnitAtIndex(cu_idx)
|
||||
result.PutCString("\n%s:" % (cu.file))
|
||||
for line_idx in range(cu.GetNumLineEntries()):
|
||||
line_entry = cu.GetLineEntryAtIndex(line_idx)
|
||||
start_file_addr = line_entry.addr.file_addr
|
||||
end_file_addr = line_entry.end_addr.file_addr
|
||||
# If the two addresses are equal, this line table entry is a termination entry
|
||||
if 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.Printf("\n")
|
||||
else:
|
||||
result.PutCString ("no module for '%s'" % module)
|
||||
else:
|
||||
result.PutCString ("error: invalid target")
|
||||
|
||||
parser = create_dump_module_line_tables_options ()
|
||||
dump_module_line_tables.__doc__ = parser.format_help()
|
||||
lldb.debugger.HandleCommand('command script add -f %s.dump_module_line_tables dump_module_line_tables' % __name__)
|
||||
print 'Installed "dump_module_line_tables" command'
|
||||
1687
external/bsd/llvm/dist/lldb/examples/python/mach_o.py
vendored
Executable file
1687
external/bsd/llvm/dist/lldb/examples/python/mach_o.py
vendored
Executable file
File diff suppressed because it is too large
Load Diff
181
external/bsd/llvm/dist/lldb/examples/python/memory.py
vendored
Executable file
181
external/bsd/llvm/dist/lldb/examples/python/memory.py
vendored
Executable file
@@ -0,0 +1,181 @@
|
||||
#!/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'
|
||||
104
external/bsd/llvm/dist/lldb/examples/python/operating_system.py
vendored
Normal file
104
external/bsd/llvm/dist/lldb/examples/python/operating_system.py
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
#!/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 type(process) is 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 == 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
|
||||
|
||||
335
external/bsd/llvm/dist/lldb/examples/python/performance.py
vendored
Executable file
335
external/bsd/llvm/dist/lldb/examples/python/performance.py
vendored
Executable file
@@ -0,0 +1,335 @@
|
||||
#!/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)
|
||||
272
external/bsd/llvm/dist/lldb/examples/python/process_events.py
vendored
Executable file
272
external/bsd/llvm/dist/lldb/examples/python/process_events.py
vendored
Executable file
@@ -0,0 +1,272 @@
|
||||
#!/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()
|
||||
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:])
|
||||
328
external/bsd/llvm/dist/lldb/examples/python/pytracer.py
vendored
Normal file
328
external/bsd/llvm/dist/lldb/examples/python/pytracer.py
vendored
Normal file
@@ -0,0 +1,328 @@
|
||||
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 != None else None
|
||||
|
||||
def getNext(self):
|
||||
return TracebackFancy(self.t.tb_next)
|
||||
|
||||
def __str__(self):
|
||||
if self.t == None:
|
||||
return ""
|
||||
str_self = "%s @ %s" % (self.getFrame().getName(), self.getLineNumber())
|
||||
return str_self + "\n" + self.getNext().__str__()
|
||||
|
||||
class ExceptionFancy:
|
||||
def __init__(self,frame):
|
||||
self.etraceback = frame.f_exc_traceback
|
||||
self.etype = frame.exc_type
|
||||
self.evalue = frame.f_exc_value
|
||||
|
||||
def __init__(self,tb,ty,va):
|
||||
self.etraceback = tb
|
||||
self.etype = ty
|
||||
self.evalue = va
|
||||
|
||||
def getTraceback(self):
|
||||
return TracebackFancy(self.etraceback)
|
||||
|
||||
def __nonzero__(self):
|
||||
return self.etraceback != None or self.etype != None or self.evalue != 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 != None else 0
|
||||
|
||||
def getFilename(self):
|
||||
return self.c.co_filename if self.c != None else ""
|
||||
|
||||
def getVariables(self):
|
||||
return self.c.co_varnames if self.c != None else []
|
||||
|
||||
def getName(self):
|
||||
return self.c.co_name if self.c != None else ""
|
||||
|
||||
def getFileName(self):
|
||||
return self.c.co_filename if self.c != None else ""
|
||||
|
||||
class ArgsFancy:
|
||||
def __init__(self,frame,arginfo):
|
||||
self.f = frame
|
||||
self.a = arginfo
|
||||
|
||||
def __str__(self):
|
||||
args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs()
|
||||
ret = ""
|
||||
count = 0
|
||||
size = len(args)
|
||||
for arg in args:
|
||||
ret = ret + ("%s = %s" % (arg, args[arg]))
|
||||
count = count + 1
|
||||
if count < size:
|
||||
ret = ret + ", "
|
||||
if varargs:
|
||||
if size > 0:
|
||||
ret = ret + " "
|
||||
ret = ret + "varargs are " + str(varargs)
|
||||
if kwargs:
|
||||
if size > 0:
|
||||
ret = ret + " "
|
||||
ret = ret + "kwargs are " + str(kwargs)
|
||||
return ret
|
||||
|
||||
def 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 != None else 0
|
||||
|
||||
def getCodeInformation(self):
|
||||
return CodeFancy(self.f.f_code) if self.f != None else None
|
||||
|
||||
def getExceptionInfo(self):
|
||||
return ExceptionFancy(self.f) if self.f != None else None
|
||||
|
||||
def getName(self):
|
||||
return self.getCodeInformation().getName() if self.f != None else ""
|
||||
|
||||
def getFileName(self):
|
||||
return self.getCodeInformation().getFileName() if self.f != None else ""
|
||||
|
||||
def getLocals(self):
|
||||
return self.f.f_locals if self.f != None else {}
|
||||
|
||||
def getArgumentInfo(self):
|
||||
return ArgsFancy(self.f,inspect.getargvalues(self.f)) if self.f != None else None
|
||||
|
||||
class TracerClass:
|
||||
def callEvent(self,frame):
|
||||
pass
|
||||
|
||||
def lineEvent(self,frame):
|
||||
pass
|
||||
|
||||
def 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 == None:
|
||||
return None
|
||||
if event == "call":
|
||||
call_retval = tracer_impl.callEvent(FrameFancy(frame))
|
||||
if call_retval == False:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "line":
|
||||
line_retval = tracer_impl.lineEvent(FrameFancy(frame))
|
||||
if line_retval == False:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "return":
|
||||
tracer_impl.returnEvent(FrameFancy(frame),args)
|
||||
elif event == "exception":
|
||||
exty,exva,extb = args
|
||||
exception_retval = tracer_impl.exceptionEvent(FrameFancy(frame),ExceptionFancy(extb,exty,exva))
|
||||
if exception_retval == False:
|
||||
return None
|
||||
return the_tracer_entrypoint
|
||||
elif event == "c_call":
|
||||
tracer_impl.cCallEvent(FrameFancy(frame),args)
|
||||
elif event == "c_return":
|
||||
tracer_impl.cReturnEvent(FrameFancy(frame),args)
|
||||
elif event == "c_exception":
|
||||
tracer_impl.cExceptionEvent(FrameFancy(frame),args)
|
||||
return None
|
||||
|
||||
def 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()
|
||||
255
external/bsd/llvm/dist/lldb/examples/python/sbvalue.py
vendored
Executable file
255
external/bsd/llvm/dist/lldb/examples/python/sbvalue.py
vendored
Executable file
@@ -0,0 +1,255 @@
|
||||
#!/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 type(key) is 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 type(key) is 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()
|
||||
|
||||
28
external/bsd/llvm/dist/lldb/examples/python/sources.py
vendored
Normal file
28
external/bsd/llvm/dist/lldb/examples/python/sources.py
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/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.'
|
||||
56
external/bsd/llvm/dist/lldb/examples/python/stacks.py
vendored
Executable file
56
external/bsd/llvm/dist/lldb/examples/python/stacks.py
vendored
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/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
|
||||
|
||||
frame_info = {}
|
||||
for thread in lldb.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."
|
||||
583
external/bsd/llvm/dist/lldb/examples/python/symbolication.py
vendored
Executable file
583
external/bsd/llvm/dist/lldb/examples/python/symbolication.py
vendored
Executable file
@@ -0,0 +1,583 @@
|
||||
#!/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
|
||||
self.so_addr = None # the resolved lldb.SBAddress (if any), named so_addr for section/offset address
|
||||
self.sym_ctx = None # The cached symbol context for this address
|
||||
self.description = None # Any original textual description of this address to be used as a backup in case symbolication fails
|
||||
self.symbolication = None # The cached symbolicated string that describes this address
|
||||
self.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 == None:
|
||||
self.so_addr = self.target.ResolveLoadAddress (self.load_addr)
|
||||
return self.so_addr
|
||||
|
||||
def is_inlined(self):
|
||||
return self.inlined
|
||||
|
||||
def get_symbol_context(self):
|
||||
if self.sym_ctx == None:
|
||||
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 == 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
|
||||
|
||||
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 != None:
|
||||
if self.start_addr != None:
|
||||
return "%s=[0x%16.16x - 0x%16.16x)" % (self.name, self.start_addr, self.end_addr)
|
||||
else:
|
||||
if self.start_addr != 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
|
||||
|
||||
|
||||
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 = "%s %s %s" % (self.get_uuid(), self.version, self.get_resolved_path())
|
||||
for section_info in self.section_infos:
|
||||
s += ", %s" % (section_info)
|
||||
if self.slide != 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 != 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
|
||||
|
||||
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:
|
||||
print m
|
||||
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)
|
||||
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 1:
|
||||
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 != 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:])
|
||||
252
external/bsd/llvm/dist/lldb/examples/python/types.py
vendored
Executable file
252
external/bsd/llvm/dist/lldb/examples/python/types.py
vendored
Executable file
@@ -0,0 +1,252 @@
|
||||
#!/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)
|
||||
return "option parsing failed" # returning a string is the same as returning an error whose description is the string
|
||||
verify_types(options, debugger.GetSelectedTarget(), command_args)
|
||||
|
||||
|
||||
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'
|
||||
353
external/bsd/llvm/dist/lldb/examples/python/x86_64_linux_target_definition.py
vendored
Normal file
353
external/bsd/llvm/dist/lldb/examples/python/x86_64_linux_target_definition.py
vendored
Normal file
@@ -0,0 +1,353 @@
|
||||
#!/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 == 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()
|
||||
357
external/bsd/llvm/dist/lldb/examples/python/x86_64_target_definition.py
vendored
Normal file
357
external/bsd/llvm/dist/lldb/examples/python/x86_64_target_definition.py
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
#!/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 == 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
|
||||
|
||||
# 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
|
||||
|
||||
offset += reg_info['bitsize']/8
|
||||
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()
|
||||
Reference in New Issue
Block a user