[Lldb-commits] [lldb] r255697 - First pass at LLDBRPC.framework
Zachary Turner via lldb-commits
lldb-commits at lists.llvm.org
Tue Dec 15 15:09:47 PST 2015
Can you explain this? Why are we upstreaming a second copy of SB headers
and clang headers? This looks like something that should be out of tree
On Tue, Dec 15, 2015 at 3:06 PM Greg Clayton via lldb-commits <
lldb-commits at lists.llvm.org> wrote:
> Added:
> lldb/trunk/build/Debug/LLDB.framework/Versions/A/Resources/Python/lldb/macosx/crashlog.py
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/build/Debug/LLDB.framework/Versions/A/Resources/Python/lldb/macosx/crashlog.py?rev=255697&view=auto
>
> ==============================================================================
> ---
> lldb/trunk/build/Debug/LLDB.framework/Versions/A/Resources/Python/lldb/macosx/crashlog.py
> (added)
> +++
> lldb/trunk/build/Debug/LLDB.framework/Versions/A/Resources/Python/lldb/macosx/crashlog.py
> Tue Dec 15 17:03:22 2015
> @@ -0,0 +1,829 @@
> +#!/usr/bin/python
> +
> +#----------------------------------------------------------------------
> +# Be sure to add the python path that points to the LLDB shared library.
> +#
> +# To use this in the embedded python interpreter using "lldb":
> +#
> +# cd /path/containing/crashlog.py
> +# lldb
> +# (lldb) script import crashlog
> +# "crashlog" command installed, type "crashlog --help" for detailed help
> +# (lldb) crashlog ~/Library/Logs/DiagnosticReports/a.crash
> +#
> +# The benefit of running the crashlog command inside lldb in the
> +# embedded python interpreter is when the command completes, there
> +# will be a target with all of the files loaded at the locations
> +# described in the crash log. Only the files that have stack frames
> +# in the backtrace will be loaded unless the "--load-all" option
> +# has been specified. This allows users to explore the program in the
> +# state it was in right at crash time.
> +#
> +# On MacOSX csh, tcsh:
> +# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ;
> ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash )
> +#
> +# On MacOSX sh, bash:
> +# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./crashlog.py
> ~/Library/Logs/DiagnosticReports/a.crash
> +#----------------------------------------------------------------------
> +
> +import commands
> +import cmd
> +import datetime
> +import glob
> +import optparse
> +import os
> +import platform
> +import plistlib
> +import pprint # pp = pprint.PrettyPrinter(indent=4);
> pp.pprint(command_args)
> +import re
> +import shlex
> +import string
> +import sys
> +import time
> +import uuid
> +
> +try:
> + # Just try for LLDB in case PYTHONPATH is already correctly setup
> + import lldb
> +except ImportError:
> + lldb_python_dirs = list()
> + # lldb is not in the PYTHONPATH, try some defaults for the current
> platform
> + platform_system = platform.system()
> + if platform_system == 'Darwin':
> + # On Darwin, try the currently selected Xcode directory
> + xcode_dir = commands.getoutput("xcode-select --print-path")
> + if xcode_dir:
> + lldb_python_dirs.append(os.path.realpath(xcode_dir +
> '/../SharedFrameworks/LLDB.framework/Resources/Python'))
> + lldb_python_dirs.append(xcode_dir +
> '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
> +
> lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
> + success = False
> + for lldb_python_dir in lldb_python_dirs:
> + if os.path.exists(lldb_python_dir):
> + if not (sys.path.__contains__(lldb_python_dir)):
> + sys.path.append(lldb_python_dir)
> + try:
> + import lldb
> + except ImportError:
> + pass
> + else:
> + print 'imported lldb from: "%s"' % (lldb_python_dir)
> + success = True
> + break
> + if not success:
> + print "error: couldn't locate the 'lldb' module, please set
> PYTHONPATH correctly"
> + sys.exit(1)
> +
> +from lldb.utils import symbolication
> +
> +PARSE_MODE_NORMAL = 0
> +PARSE_MODE_THREAD = 1
> +PARSE_MODE_IMAGES = 2
> +PARSE_MODE_THREGS = 3
> +PARSE_MODE_SYSTEM = 4
> +
> +class CrashLog(symbolication.Symbolicator):
> + """Class that does parses darwin crash logs"""
> + parent_process_regex = re.compile('^Parent Process:\s*(.*)\[(\d+)\]');
> + thread_state_regex = re.compile('^Thread ([0-9]+) crashed with')
> + thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)')
> + app_backtrace_regex = re.compile('^Application Specific Backtrace
> ([0-9]+)([^:]*):(.*)')
> + frame_regex = re.compile('^([0-9]+)\s+([^ ]+)\s+(0x[0-9a-fA-F]+)
> +(.*)')
> + image_regex_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+)
> +[+]?([^ ]+) +([^<]+)<([-0-9a-fA-F]+)> (.*)');
> + image_regex_no_uuid = re.compile('(0x[0-9a-fA-F]+)[-
> ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^/]+)/(.*)');
> + empty_line_regex = re.compile('^$')
> +
> + class Thread:
> + """Class that represents a thread in a darwin crash log"""
> + def __init__(self, index, app_specific_backtrace):
> + self.index = index
> + self.frames = list()
> + self.idents = list()
> + self.registers = dict()
> + self.reason = None
> + self.queue = None
> + self.app_specific_backtrace = app_specific_backtrace
> +
> + def dump(self, prefix):
> + if self.app_specific_backtrace:
> + print "%Application Specific Backtrace[%u] %s" % (prefix,
> self.index, self.reason)
> + else:
> + print "%sThread[%u] %s" % (prefix, self.index,
> self.reason)
> + if self.frames:
> + print "%s Frames:" % (prefix)
> + for frame in self.frames:
> + frame.dump(prefix + ' ')
> + if self.registers:
> + print "%s Registers:" % (prefix)
> + for reg in self.registers.keys():
> + print "%s %-5s = %#16.16x" % (prefix, reg,
> self.registers[reg])
> +
> + def dump_symbolicated (self, crash_log, options):
> + this_thread_crashed = self.app_specific_backtrace
> + if not this_thread_crashed:
> + this_thread_crashed = self.did_crash()
> + if options.crashed_only and this_thread_crashed == False:
> + return
> +
> + print "%s" % self
> + #prev_frame_index = -1
> + display_frame_idx = -1
> + for frame_idx, frame in enumerate(self.frames):
> + disassemble = (this_thread_crashed or
> options.disassemble_all_threads) and frame_idx < options.disassemble_depth;
> + if frame_idx == 0:
> + symbolicated_frame_addresses = crash_log.symbolicate
> (frame.pc & crash_log.addr_mask, options.verbose)
> + else:
> + # Any frame above frame zero and we have to subtract
> one to get the previous line entry
> + symbolicated_frame_addresses = crash_log.symbolicate
> ((frame.pc & crash_log.addr_mask) - 1, options.verbose)
> +
> + if symbolicated_frame_addresses:
> + symbolicated_frame_address_idx = 0
> + for symbolicated_frame_address in
> symbolicated_frame_addresses:
> + display_frame_idx += 1
> + print '[%3u] %s' % (frame_idx,
> symbolicated_frame_address)
> + if (options.source_all or self.did_crash()) and
> display_frame_idx < options.source_frames and options.source_context:
> + source_context = options.source_context
> + line_entry =
> symbolicated_frame_address.get_symbol_context().line_entry
> + if line_entry.IsValid():
> + strm = lldb.SBStream()
> + if line_entry:
> +
> lldb.debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers(line_entry.file,
> line_entry.line, source_context, source_context, "->", strm)
> + source_text = strm.GetData()
> + if source_text:
> + # Indent the source a bit
> + indent_str = ' '
> + join_str = '\n' + indent_str
> + print '%s%s' % (indent_str,
> join_str.join(source_text.split('\n')))
> + if symbolicated_frame_address_idx == 0:
> + if disassemble:
> + instructions =
> symbolicated_frame_address.get_instructions()
> + if instructions:
> + print
> +
> symbolication.disassemble_instructions (crash_log.get_target(),
> +
> instructions,
> +
> frame.pc,
> +
> options.disassemble_before,
> +
> options.disassemble_after, frame.index > 0)
> + print
> + symbolicated_frame_address_idx += 1
> + else:
> + print frame
> +
> + def add_ident(self, ident):
> + if not ident in self.idents:
> + self.idents.append(ident)
> +
> + def did_crash(self):
> + return self.reason != None
> +
> + def __str__(self):
> + if self.app_specific_backtrace:
> + s = "Application Specific Backtrace[%u]" % self.index
> + else:
> + s = "Thread[%u]" % self.index
> + if self.reason:
> + s += ' %s' % self.reason
> + return s
> +
> +
> + class Frame:
> + """Class that represents a stack frame in a thread in a darwin
> crash log"""
> + def __init__(self, index, pc, description):
> + self.pc = pc
> + self.description = description
> + self.index = index
> +
> + def __str__(self):
> + if self.description:
> + return "[%3u] 0x%16.16x %s" % (self.index, self.pc,
> self.description)
> + else:
> + return "[%3u] 0x%16.16x" % (self.index, self.pc)
> +
> + def dump(self, prefix):
> + print "%s%s" % (prefix, str(self))
> +
> + class DarwinImage(symbolication.Image):
> + """Class that represents a binary images in a darwin crash log"""
> + dsymForUUIDBinary = os.path.expanduser('~rc/bin/dsymForUUID')
> + if not os.path.exists(dsymForUUIDBinary):
> + dsymForUUIDBinary = commands.getoutput('which dsymForUUID')
> +
> + dwarfdump_uuid_regex = re.compile('UUID: ([-0-9a-fA-F]+)
> \(([^\(]+)\) .*')
> +
> + def __init__(self, text_addr_lo, text_addr_hi, identifier,
> version, uuid, path):
> + symbolication.Image.__init__(self, path, uuid);
> + self.add_section (symbolication.Section(text_addr_lo,
> text_addr_hi, "__TEXT"))
> + self.identifier = identifier
> + self.version = version
> +
> + def 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.path = os.path.expanduser
> (plist['DBGSymbolRichExecutable'])
> + self.resolved_path = self.path
> + if not self.resolved_path and os.path.exists(self.path):
> + dwarfdump_cmd_output = commands.getoutput('dwarfdump
> --uuid "%s"' % self.path)
> + 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.backtraces = list() # For application specific backtraces
> + self.idents = list() # A list of the required identifiers for
> doing all stack backtraces
> + self.crashed_thread_idx = -1
> + self.version = -1
> + self.error = None
> + self.target = None
> + # With possible initial component of ~ or ~user replaced by that
> user's home directory.
> + try:
> + f = open(self.path)
> + except IOError:
> + self.error = 'error: cannot open "%s"' % self.path
> + return
> +
> + self.file_lines = f.read().splitlines()
> + parse_mode = PARSE_MODE_NORMAL
> + thread = None
> + app_specific_backtrace = False
> + for line in self.file_lines:
> + # print line
> + line_len = len(line)
> + if line_len == 0:
> + if thread:
> + if parse_mode == PARSE_MODE_THREAD:
> + if thread.index == self.crashed_thread_idx:
> + thread.reason = ''
> + if self.thread_exception:
> + thread.reason += self.thread_exception
> + if self.thread_exception_data:
> + thread.reason += " (%s)" %
> self.thread_exception_data
> + if app_specific_backtrace:
> + self.backtraces.append(thread)
> + else:
> + self.threads.append(thread)
> + thread = None
> + else:
> + # only append an extra empty line if the previous line
> + # in the info_lines wasn't empty
> + if len(self.info_lines) > 0 and
> len(self.info_lines[-1]):
> + self.info_lines.append(line)
> + parse_mode = PARSE_MODE_NORMAL
> + # print 'PARSE_MODE_NORMAL'
> + elif parse_mode == PARSE_MODE_NORMAL:
> + if line.startswith ('Process:'):
> + (self.process_name, pid_with_brackets) =
> line[8:].strip().split(' [')
> + self.process_id = pid_with_brackets.strip('[]')
> + elif line.startswith ('Path:'):
> + self.process_path = line[5:].strip()
> + elif line.startswith ('Identifier:'):
> + self.process_identifier = line[11:].strip()
> + elif line.startswith ('Version:'):
> + version_string = line[8:].strip()
> + matched_pair = re.search("(.+)\((.+)\)",
> version_string)
> + if matched_pair:
> + self.process_version = matched_pair.group(1)
> + self.process_compatability_version =
> matched_pair.group(2)
> + else:
> + self.process = version_string
> + self.process_compatability_version =
> version_string
> + elif self.parent_process_regex.search(line):
> + parent_process_match =
> self.parent_process_regex.search(line)
> + self.parent_process_name =
> parent_process_match.group(1)
> + self.parent_process_id = parent_process_match.group(2)
> + elif line.startswith ('Exception Type:'):
> + self.thread_exception = line[15:].strip()
> + continue
> + elif line.startswith ('Exception Codes:'):
> + self.thread_exception_data = line[16:].strip()
> + continue
> + elif line.startswith ('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:
> + app_specific_backtrace = False
> + thread_state_match = self.thread_regex.search
> (line)
> + thread_idx = int(thread_state_match.group(1))
> + parse_mode = PARSE_MODE_THREGS
> + thread = self.threads[thread_idx]
> + else:
> + thread_match = self.thread_regex.search (line)
> + if thread_match:
> + app_specific_backtrace = False
> + parse_mode = PARSE_MODE_THREAD
> + thread_idx = int(thread_match.group(1))
> + thread = CrashLog.Thread(thread_idx, False)
> + continue
> + elif line.startswith ('Binary Images:'):
> + parse_mode = PARSE_MODE_IMAGES
> + continue
> + elif line.startswith ('Application Specific Backtrace'):
> + app_backtrace_match = self.app_backtrace_regex.search
> (line)
> + if app_backtrace_match:
> + parse_mode = PARSE_MODE_THREAD
> + app_specific_backtrace = True
> + idx = int(app_backtrace_match.group(1))
> + thread = CrashLog.Thread(idx, True)
> + 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)
> + if self.backtraces:
> + print "\nApplication Specific Backtraces:"
> + for thread in self.backtraces:
> + thread.dump(' ')
> + print "\nThreads:"
> + for thread in self.threads:
> + thread.dump(' ')
> + print "\nImages:"
> + for image in self.images:
> + image.dump(' ')
> +
> + def find_image_with_identifier(self, identifier):
> + for image in self.images:
> + if image.identifier == identifier:
> + return image
> + regex_text = '^.*\.%s$' % (identifier)
> + regex = re.compile(regex_text)
> + for image in self.images:
> + if regex.match(image.identifier):
> + return image
> + return None
> +
> + def create_target(self):
> + #print 'crashlog.create_target()...'
> + if self.target is None:
> + self.target = symbolication.Symbolicator.create_target(self)
> + if self.target:
> + return self.target
> + # We weren't able to open the main executable as, but we can
> still symbolicate
> + print 'crashlog.create_target()...2'
> + if self.idents:
> + for ident in self.idents:
> + image = self.find_image_with_identifier (ident)
> + if image:
> + self.target = image.create_target ()
> + if self.target:
> + return self.target # success
> + print 'crashlog.create_target()...3'
> + for image in self.images:
> + self.target = image.create_target ()
> + if self.target:
> + return self.target # success
> + print 'crashlog.create_target()...4'
> + print 'error: unable to locate any executables from the crash
> log'
> + return self.target
> +
> + def get_target(self):
> + return self.target
> +
> +def usage():
> + print "Usage: lldb-symbolicate.py [-n name] executable-image"
> + sys.exit(0)
> +
> +class Interactive(cmd.Cmd):
> + '''Interactive prompt for analyzing one or more Darwin crash logs,
> type "help" to see a list of supported commands.'''
> + image_option_parser = None
> +
> + def __init__(self, crash_logs):
> + cmd.Cmd.__init__(self)
> + self.use_rawinput = False
> + self.intro = 'Interactive crashlogs prompt, type "help" to see a
> list of supported commands.'
> + self.crash_logs = crash_logs
> + self.prompt = '% '
> +
> + def default(self, line):
> + '''Catch all for unknown command, which will exit the
> interpreter.'''
> + print "uknown command: %s" % line
> + return True
> +
> + def do_q(self, line):
> + '''Quit command'''
> + return True
> +
> + def do_quit(self, line):
> + '''Quit command'''
> + return True
> +
> + def do_symbolicate(self, line):
> + description='''Symbolicate one or more darwin crash log files by
> index to provide source file and line information,
> + inlined stack frames back to the concrete functions, and
> disassemble the location of the crash
> + for the first frame of the crashed thread.'''
> + option_parser = CreateSymbolicateCrashLogOptions ('symbolicate',
> description, False)
> + command_args = shlex.split(line)
> + try:
> + (options, args) = option_parser.parse_args(command_args)
> + except:
> + return
> +
> + if args:
> + # We have arguments, they must valid be crash log file indexes
> + for idx_str in args:
> + idx = int(idx_str)
> + if idx < len(self.crash_logs):
> + SymbolicateCrashLog (self.crash_logs[idx], options)
> + else:
> + print 'error: crash log index %u is out of range' %
> (idx)
> + else:
> + # No arguments, symbolicate all crash logs using the options
> provided
> + for idx in range(len(self.crash_logs)):
> + SymbolicateCrashLog (self.crash_logs[idx], options)
> +
> + def do_list(self, line=None):
> + '''Dump a list of all crash logs that are currently loaded.
> +
> + USAGE: list'''
> + print '%u crash logs are loaded:' % len(self.crash_logs)
> + for (crash_log_idx, crash_log) in enumerate(self.crash_logs):
> + print '[%u] = %s' % (crash_log_idx, crash_log.path)
> +
> + def do_image(self, line):
> + '''Dump information about one or more binary images in the crash
> log given an image basename, or all images if no arguments are provided.'''
> + usage = "usage: %prog [options] <PATH> [PATH ...]"
> + description='''Dump information about one or more images in all
> crash logs. The <PATH> can be a full path, image basename, or partial path.
> Searches are done in this order.'''
> + command_args = shlex.split(line)
> + if not self.image_option_parser:
> + self.image_option_parser =
> optparse.OptionParser(description=description, prog='image',usage=usage)
> + self.image_option_parser.add_option('-a', '--all',
> action='store_true', help='show all images', default=False)
> + try:
> + (options, args) =
> self.image_option_parser.parse_args(command_args)
> + except:
> + return
> +
> + if args:
> + for image_path in args:
> + fullpath_search = image_path[0] == '/'
> + for (crash_log_idx, crash_log) in
> enumerate(self.crash_logs):
> + matches_found = 0
> + for (image_idx, image) in enumerate(crash_log.images):
> + if fullpath_search:
> + if image.get_resolved_path() == image_path:
> + matches_found += 1
> + print '[%u] ' % (crash_log_idx), image
> + else:
> + image_basename =
> image.get_resolved_path_basename()
> + if image_basename == image_path:
> + matches_found += 1
> + print '[%u] ' % (crash_log_idx), image
> + if matches_found == 0:
> + for (image_idx, image) in
> enumerate(crash_log.images):
> + resolved_image_path =
> image.get_resolved_path()
> + if resolved_image_path and
> string.find(image.get_resolved_path(), image_path) >= 0:
> + print '[%u] ' % (crash_log_idx), image
> + else:
> + for crash_log in self.crash_logs:
> + for (image_idx, image) in enumerate(crash_log.images):
> + print '[%u] %s' % (image_idx, image)
> + return False
> +
> +
> +def interactive_crashlogs(options, args):
> + crash_log_files = list()
> + for arg in args:
> + for resolved_path in glob.glob(arg):
> + crash_log_files.append(resolved_path)
> +
> + crash_logs = list();
> + for crash_log_file in crash_log_files:
> + #print 'crash_log_file = "%s"' % crash_log_file
> + crash_log = CrashLog(crash_log_file)
> + if crash_log.error:
> + print crash_log.error
> + continue
> + if options.debug:
> + crash_log.dump()
> + if not crash_log.images:
> + print 'error: no images in crash log "%s"' % (crash_log)
> + continue
> + else:
> + crash_logs.append(crash_log)
> +
> + interpreter = Interactive(crash_logs)
> + # List all crash logs that were imported
> + interpreter.do_list()
> + interpreter.cmdloop()
> +
> +
> +def save_crashlog(debugger, command, result, dict):
> + usage = "usage: %prog [options] <output-path>"
> + description='''Export the state of current target into a crashlog
> file'''
> + parser = optparse.OptionParser(description=description,
> prog='save_crashlog',usage=usage)
> + parser.add_option('-v', '--verbose', action='store_true',
> dest='verbose', help='display verbose debug info', default=False)
> + try:
> + (options, args) = parser.parse_args(shlex.split(command))
> + except:
> + result.PutCString ("error: invalid options");
> + return
> + if len(args) != 1:
> + result.PutCString ("error: invalid arguments, a single output
> file is the only valid argument")
> + return
> + out_file = open(args[0], 'w')
> + if not out_file:
> + result.PutCString ("error: failed to open file '%s' for
> writing...", args[0]);
> + return
> + target = debugger.GetSelectedTarget()
> + if target:
> + identifier = 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' %
> (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 target.modules:
> + text_segment = module.section['__TEXT']
> + if text_segment:
> + text_segment_load_addr =
> text_segment.GetLoadAddress(target)
> + if text_segment_load_addr != lldb.LLDB_INVALID_ADDRESS:
> + text_segment_end_load_addr = text_segment_load_addr +
> text_segment.size
> + identifier = module.file.basename
> + module_version = '???'
> + module_version_array = module.GetVersion()
> + if module_version_array:
> + module_version =
> '.'.join(map(str,module_version_array))
> + out_file.write (' 0x%16.16x - 0x%16.16x %s (%s -
> ???) <%s> %s\n' % (text_segment_load_addr, text_segment_end_load_addr,
> identifier, module_version, module.GetUUIDString(), module.file.fullpath))
> + out_file.close()
> + else:
> + result.PutCString ("error: invalid target");
> +
> +
> +def Symbolicate(debugger, command, result, dict):
> + try:
> + SymbolicateCrashLogs (shlex.split(command))
> + except:
> + result.PutCString ("error: python exception %s" %
> sys.exc_info()[0])
> +
> +def SymbolicateCrashLog(crash_log, options):
> + if crash_log.error:
> + print crash_log.error
> + return
> + if options.debug:
> + crash_log.dump()
> + if not crash_log.images:
> + print 'error: no images in crash log'
> + return
> +
> + if options.dump_image_list:
> + print "Binary Images:"
> + for image in crash_log.images:
> + if options.verbose:
> + print image.debug_dump()
> + else:
> + print image
> +
> + target = crash_log.create_target ()
> + if not target:
> + return
> + exe_module = target.GetModuleAtIndex(0)
> + images_to_load = list()
> + loaded_images = list()
> + if options.load_all_images:
> + # --load-all option was specified, load everything up
> + for image in crash_log.images:
> + images_to_load.append(image)
> + else:
> + # Only load the images found in stack frames for the crashed
> threads
> + if options.crashed_only:
> + for thread in crash_log.threads:
> + if thread.did_crash():
> + for ident in thread.idents:
> + images = crash_log.find_images_with_identifier
> (ident)
> + if images:
> + for image in images:
> + images_to_load.append(image)
> + else:
> + print 'error: can\'t find image for
> identifier "%s"' % ident
> + else:
> + for ident in crash_log.idents:
> + images = crash_log.find_images_with_identifier (ident)
> + if images:
> + for image in images:
> + images_to_load.append(image)
> + else:
> + print 'error: can\'t find image for identifier "%s"'
> % ident
> +
> + for image in images_to_load:
> + if not image in loaded_images:
> + err = image.add_module (target)
> + if err:
> + print err
> + else:
> + #print 'loaded %s' % image
> + loaded_images.append(image)
> +
> + if crash_log.backtraces:
> + for thread in crash_log.backtraces:
> + thread.dump_symbolicated (crash_log, options)
> + print
> +
> + for thread in crash_log.threads:
> + thread.dump_symbolicated (crash_log, options)
> + print
> +
> +
> +def CreateSymbolicateCrashLogOptions(command_name, description,
> add_interactive_options):
> + usage = "usage: %prog [options] <FILE> [FILE ...]"
> + option_parser = optparse.OptionParser(description=description,
> prog='crashlog',usage=usage)
> + option_parser.add_option('--verbose' , '-v',
> action='store_true', dest='verbose', help='display verbose debug info',
> default=False)
> + option_parser.add_option('--debug' , '-g',
> action='store_true', dest='debug', help='display verbose debug logging',
> default=False)
> + option_parser.add_option('--load-all' , '-a',
> action='store_true', dest='load_all_images', help='load all executable
> images, not just the images found in the crashed stack frames',
> default=False)
> + option_parser.add_option('--images' ,
> action='store_true', dest='dump_image_list', help='show image list',
> default=False)
> + option_parser.add_option('--debug-delay' , type='int',
> dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for
> debugger', default=0)
> + option_parser.add_option('--crashed-only' , '-c',
> action='store_true', dest='crashed_only', help='only symbolicate the
> crashed thread', default=False)
> + option_parser.add_option('--disasm-depth' , '-d', type='int',
> dest='disassemble_depth', help='set the depth in stack frames that should
> be disassembled (default is 1)', default=1)
> + option_parser.add_option('--disasm-all' , '-D',
> action='store_true', dest='disassemble_all_threads', help='enabled
> disassembly of frames on all threads (not just the crashed thread)',
> default=False)
> + option_parser.add_option('--disasm-before' , '-B', type='int',
> dest='disassemble_before', help='the number of instructions to disassemble
> before the frame PC', default=4)
> + option_parser.add_option('--disasm-after' , '-A', type='int',
> dest='disassemble_after', help='the number of instructions to disassemble
> after the frame PC', default=4)
> + option_parser.add_option('--source-context', '-C', type='int',
> metavar='NLINES', dest='source_context', help='show NLINES source lines of
> source context (default = 4)', default=4)
> + option_parser.add_option('--source-frames' , type='int',
> metavar='NFRAMES', dest='source_frames', help='show source for NFRAMES
> (default = 4)', default=4)
> + option_parser.add_option('--source-all' ,
> action='store_true', dest='source_all', help='show source for all threads,
> not just the crashed thread', default=False)
> + if add_interactive_options:
> + option_parser.add_option('-i', '--interactive',
> action='store_true', help='parse all crash logs and enter interactive
> mode', default=False)
> + return option_parser
> +
> +def SymbolicateCrashLogs(command_args):
> + description='''Symbolicate one or more darwin crash log files to
> provide source file and line information,
> +inlined stack frames back to the concrete functions, and disassemble the
> location of the crash
> +for the first frame of the crashed thread.
> +If this script is imported into the LLDB command interpreter, a
> "crashlog" command will be added to the interpreter
> +for use at the LLDB command line. After a crash log has been parsed and
> symbolicated, a target will have been
> +created that has all of the shared libraries loaded at the load addresses
> found in the crash log file. This allows
> +you to explore the program as if it were stopped at the locations
> described in the crash log and functions can
> +be disassembled and lookups can be performed using the addresses found in
> the crash log.'''
> + option_parser = CreateSymbolicateCrashLogOptions ('crashlog',
> description, True)
> + try:
> + (options, args) = option_parser.parse_args(command_args)
> + except:
> + return
> +
> + if options.debug:
> + print 'command_args = %s' % command_args
> + print 'options', options
> + print 'args', args
> +
> + if options.debug_delay > 0:
> + print "Waiting %u seconds for debugger to attach..." %
> options.debug_delay
> + time.sleep(options.debug_delay)
> + error = lldb.SBError()
> +
> + if args:
> + if options.interactive:
> + interactive_crashlogs(options, args)
> + else:
> + for crash_log_file in args:
> + crash_log = CrashLog(crash_log_file)
> + SymbolicateCrashLog (crash_log, options)
> +if __name__ == '__main__':
> + # Create a new debugger instance
> + lldb.debugger = lldb.SBDebugger.Create()
> + SymbolicateCrashLogs (sys.argv[1:])
> + lldb.SBDebugger.Destroy (lldb.debugger)
> +elif getattr(lldb, 'debugger', None):
> + lldb.debugger.HandleCommand('command script add -f
> lldb.macosx.crashlog.Symbolicate crashlog')
> + lldb.debugger.HandleCommand('command script add -f
> lldb.macosx.crashlog.save_crashlog save_crashlog')
> + print '"crashlog" and "save_crashlog" command installed, use the
> "--help" option for detailed help'
> +
>
> Propchange:
> lldb/trunk/build/Debug/LLDB.framework/Versions/A/Resources/Python/lldb/macosx/crashlog.py
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added:
> lldb/trunk/build/Debug/LLDB.framework/Versions/A/Resources/Python/lldb/macosx/heap.py
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/build/Debug/LLDB.framework/Versions/A/Resources/Python/lldb/macosx/heap.py?rev=255697&view=auto
>
> ==============================================================================
> ---
> lldb/trunk/build/Debug/LLDB.framework/Versions/A/Resources/Python/lldb/macosx/heap.py
> (added)
> +++
> lldb/trunk/build/Debug/LLDB.framework/Versions/A/Resources/Python/lldb/macosx/heap.py
> Tue Dec 15 17:03:22 2015
> @@ -0,0 +1,1244 @@
> +#!/usr/bin/python
> +
> +#----------------------------------------------------------------------
> +# This module is designed to live inside the "lldb" python package
> +# in the "lldb.macosx" package. To use this in the embedded python
> +# interpreter using "lldb" just import it:
> +#
> +# (lldb) script import lldb.macosx.heap
> +#----------------------------------------------------------------------
> +
> +import lldb
> +import commands
> +import optparse
> +import os
> +import os.path
> +import re
> +import shlex
> +import string
> +import sys
> +import tempfile
> +import lldb.utils.symbolication
> +
> +g_libheap_dylib_dir = None
> +g_libheap_dylib_dict = dict()
> +
> +def get_iterate_memory_expr(options, process, user_init_code,
> user_return_code):
> + expr = '''
> +typedef unsigned natural_t;
> +typedef uintptr_t vm_size_t;
> +typedef uintptr_t vm_address_t;
> +typedef natural_t task_t;
> +typedef int kern_return_t;
> +#define KERN_SUCCESS 0
> +typedef void (*range_callback_t)(task_t task, void *baton, unsigned type,
> uintptr_t ptr_addr, uintptr_t ptr_size);
> +''';
> + if options.search_vm_regions:
> + expr += '''
> +typedef int vm_prot_t;
> +typedef unsigned int vm_inherit_t;
> +typedef unsigned long long memory_object_offset_t;
> +typedef unsigned int boolean_t;
> +typedef int vm_behavior_t;
> +typedef uint32_t vm32_object_id_t;
> +typedef natural_t mach_msg_type_number_t;
> +typedef uint64_t mach_vm_address_t;
> +typedef uint64_t mach_vm_offset_t;
> +typedef uint64_t mach_vm_size_t;
> +typedef uint64_t vm_map_offset_t;
> +typedef uint64_t vm_map_address_t;
> +typedef uint64_t vm_map_size_t;
> +#define VM_PROT_NONE ((vm_prot_t) 0x00)
> +#define VM_PROT_READ ((vm_prot_t) 0x01)
> +#define VM_PROT_WRITE ((vm_prot_t) 0x02)
> +#define VM_PROT_EXECUTE ((vm_prot_t) 0x04)
> +typedef struct vm_region_submap_short_info_data_64_t {
> + vm_prot_t protection;
> + vm_prot_t max_protection;
> + vm_inherit_t inheritance;
> + memory_object_offset_t offset; // offset into object/map
> + unsigned int user_tag; // user tag on map entry
> + unsigned int ref_count; // obj/map mappers, etc
> + unsigned short shadow_depth; // only for obj
> + unsigned char external_pager; // only for obj
> + unsigned char share_mode; // see enumeration
> + boolean_t is_submap; // submap vs obj
> + vm_behavior_t behavior; // access behavior hint
> + vm32_object_id_t object_id; // obj/map name, not a handle
> + unsigned short user_wired_count;
> +} vm_region_submap_short_info_data_64_t;
> +#define VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
> ((mach_msg_type_number_t)(sizeof(vm_region_submap_short_info_data_64_t)/sizeof(int)))''';
> + if user_init_code:
> + expr += user_init_code;
> + expr += '''
> +task_t task = (task_t)mach_task_self();
> +mach_vm_address_t vm_region_base_addr;
> +mach_vm_size_t vm_region_size;
> +natural_t vm_region_depth;
> +vm_region_submap_short_info_data_64_t vm_region_info;
> +kern_return_t err;
> +for (vm_region_base_addr = 0, vm_region_size = 1; vm_region_size != 0;
> vm_region_base_addr += vm_region_size)
> +{
> + mach_msg_type_number_t vm_region_info_size =
> VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
> + err = (kern_return_t)mach_vm_region_recurse (task,
> + &vm_region_base_addr,
> + &vm_region_size,
> + &vm_region_depth,
> + &vm_region_info,
> + &vm_region_info_size);
> + if (err)
> + break;
> + // Check all read + write regions. This will cover the thread stacks
> + // and any regions of memory like __DATA segments, that might contain
> + // data we are looking for
> + if (vm_region_info.protection & VM_PROT_WRITE &&
> + vm_region_info.protection & VM_PROT_READ)
> + {
> + baton.callback (task,
> + &baton,
> + 64,
> + vm_region_base_addr,
> + vm_region_size);
> + }
> +}'''
> + else:
> + if options.search_stack:
> + expr += get_thread_stack_ranges_struct (process)
> + if options.search_segments:
> + expr += get_sections_ranges_struct (process)
> + if user_init_code:
> + expr += user_init_code
> + if options.search_heap:
> + expr += '''
> +#define MALLOC_PTR_IN_USE_RANGE_TYPE 1
> +typedef struct vm_range_t {
> + vm_address_t address;
> + vm_size_t size;
> +} vm_range_t;
> +typedef kern_return_t (*memory_reader_t)(task_t task, vm_address_t
> remote_address, vm_size_t size, void **local_memory);
> +typedef void (*vm_range_recorder_t)(task_t task, void *baton, unsigned
> type, vm_range_t *range, unsigned size);
> +typedef struct malloc_introspection_t {
> + kern_return_t (*enumerator)(task_t task, void *, unsigned type_mask,
> vm_address_t zone_address, memory_reader_t reader, vm_range_recorder_t
> recorder); /* enumerates all the malloc pointers in use */
> +} malloc_introspection_t;
> +typedef struct malloc_zone_t {
> + void *reserved1[12];
> + struct malloc_introspection_t *introspect;
> +} malloc_zone_t;
> +memory_reader_t task_peek = [](task_t task, vm_address_t remote_address,
> vm_size_t size, void **local_memory) -> kern_return_t {
> + *local_memory = (void*) remote_address;
> + return KERN_SUCCESS;
> +};
> +vm_address_t *zones = 0;
> +unsigned int num_zones = 0;task_t task = 0;
> +kern_return_t err = (kern_return_t)malloc_get_all_zones (task, task_peek,
> &zones, &num_zones);
> +if (KERN_SUCCESS == err)
> +{
> + for (unsigned int i=0; i<num_zones; ++i)
> + {
> + const malloc_zone_t *zone = (const malloc_zone_t *)zones[i];
> + if (zone && zone->introspect)
> + zone->introspect->enumerator (task,
> + &baton,
> + MALLOC_PTR_IN_USE_RANGE_TYPE,
> + (vm_address_t)zone,
> + task_peek,
> + [] (task_t task, void *baton,
> unsigned type, vm_range_t *ranges, unsigned size) -> void
> + {
> + range_callback_t callback =
> ((callback_baton_t *)baton)->callback;
> + for (unsigned i=0; i<size;
> ++i)
> + {
> + callback (task, baton,
> type, ranges[i].address, ranges[i].size);
> + }
> + });
> + }
> +}'''
> +
> + if options.search_stack:
> + expr += '''
> +#ifdef NUM_STACKS
> +// Call the callback for the thread stack ranges
> +for (uint32_t i=0; i<NUM_STACKS; ++i) {
> + range_callback(task, &baton, 8, stacks[i].base, stacks[i].size);
> + if (STACK_RED_ZONE_SIZE > 0) {
> + range_callback(task, &baton, 16, stacks[i].base -
> STACK_RED_ZONE_SIZE, STACK_RED_ZONE_SIZE);
> + }
> +}
> +#endif'''
> +
> + if options.search_segments:
> + expr += '''
> +#ifdef NUM_SEGMENTS
> +// Call the callback for all segments
> +for (uint32_t i=0; i<NUM_SEGMENTS; ++i)
> + range_callback(task, &baton, 32, segments[i].base, segments[i].size);
> +#endif'''
> +
> + if user_return_code:
> + expr += "\n%s" % (user_return_code,)
> +
> + return expr
> +
> +def get_member_types_for_offset(value_type, offset, member_list):
> + member = value_type.GetFieldAtIndex(0)
> + search_bases = False
> + if member:
> + if member.GetOffsetInBytes() <= offset:
> + for field_idx in range (value_type.GetNumberOfFields()):
> + member = value_type.GetFieldAtIndex(field_idx)
> + member_byte_offset = member.GetOffsetInBytes()
> + member_end_byte_offset = member_byte_offset +
> member.type.size
> + if member_byte_offset <= offset and offset <
> member_end_byte_offset:
> + member_list.append(member)
> + get_member_types_for_offset (member.type, offset -
> member_byte_offset, member_list)
> + return
> + else:
> + search_bases = True
> + else:
> + search_bases = True
> + if search_bases:
> + for field_idx in range
> (value_type.GetNumberOfDirectBaseClasses()):
> + member = value_type.GetDirectBaseClassAtIndex(field_idx)
> + member_byte_offset = member.GetOffsetInBytes()
> + member_end_byte_offset = member_byte_offset + member.type.size
> + if member_byte_offset <= offset and offset <
> member_end_byte_offset:
> + member_list.append(member)
> + get_member_types_for_offset (member.type, offset -
> member_byte_offset, member_list)
> + return
> + for field_idx in range
> (value_type.GetNumberOfVirtualBaseClasses()):
> + member = value_type.GetVirtualBaseClassAtIndex(field_idx)
> + member_byte_offset = member.GetOffsetInBytes()
> + member_end_byte_offset = member_byte_offset + member.type.size
> + if member_byte_offset <= offset and offset <
> member_end_byte_offset:
> + member_list.append(member)
> + get_member_types_for_offset (member.type, offset -
> member_byte_offset, member_list)
> + return
> +
> +def append_regex_callback(option, opt, value, parser):
> + try:
> + ivar_regex = re.compile(value)
> + parser.values.ivar_regex_blacklist.append(ivar_regex)
> + except:
> + print 'error: an exception was thrown when compiling the ivar
> regular expression for "%s"' % value
> +
> +def add_common_options(parser):
> + parser.add_option('-v', '--verbose', action='store_true',
> dest='verbose', help='display verbose debug info', default=False)
> + parser.add_option('-t', '--type', action='store_true',
> dest='print_type', help='print the full value of the type for each matching
> malloc block', default=False)
> + parser.add_option('-o', '--po', action='store_true',
> dest='print_object_description', help='print the object descriptions for
> any matches', default=False)
> + parser.add_option('-z', '--size', action='store_true',
> dest='show_size', help='print the allocation size in bytes', default=False)
> + parser.add_option('-r', '--range', action='store_true',
> dest='show_range', help='print the allocation address range instead of just
> the allocation base address', default=False)
> + parser.add_option('-m', '--memory', action='store_true',
> dest='memory', help='dump the memory for each matching block',
> default=False)
> + parser.add_option('-f', '--format', type='string', dest='format',
> help='the format to use when dumping memory if --memory is specified',
> default=None)
> + parser.add_option('-I', '--omit-ivar-regex', type='string',
> action='callback', callback=append_regex_callback,
> dest='ivar_regex_blacklist', default=[], help='specify one or more regular
> expressions used to backlist any matches that are in ivars')
> + parser.add_option('-s', '--stack', action='store_true', dest='stack',
> help='gets the stack that allocated each malloc block if MallocStackLogging
> is enabled', default=False)
> + parser.add_option('-S', '--stack-history', action='store_true',
> dest='stack_history', help='gets the stack history for all allocations
> whose start address matches each malloc block if MallocStackLogging is
> enabled', default=False)
> + parser.add_option('-F', '--max-frames', type='int',
> dest='max_frames', help='the maximum number of stack frames to print when
> using the --stack or --stack-history options (default=128)', default=128)
> + parser.add_option('-H', '--max-history', type='int',
> dest='max_history', help='the maximum number of stack history backtraces to
> print for each allocation when using the --stack-history option
> (default=16)', default=16)
> + parser.add_option('-M', '--max-matches', type='int',
> dest='max_matches', help='the maximum number of matches to print',
> default=32)
> + parser.add_option('-O', '--offset', type='int', dest='offset',
> help='the matching data must be at this offset', default=-1)
> + parser.add_option('--ignore-stack', action='store_false',
> dest='search_stack', help="Don't search the stack when enumerating memory",
> default=True)
> + parser.add_option('--ignore-heap', action='store_false',
> dest='search_heap', help="Don't search the heap allocations when
> enumerating memory", default=True)
> + parser.add_option('--ignore-segments', action='store_false',
> dest='search_segments', help="Don't search readable executable segments
> enumerating memory", default=True)
> + parser.add_option('-V', '--vm-regions', action='store_true',
> dest='search_vm_regions', help='Check all VM regions instead of searching
> the heap, stack and segments', default=False)
> +
> +def type_flags_to_string(type_flags):
> + if type_flags == 0:
> + type_str = 'free'
> + elif type_flags & 2:
> + type_str = 'malloc'
> + elif type_flags & 4:
> + type_str = 'free'
> + elif type_flags & 1:
> + type_str = 'generic'
> + elif type_flags & 8:
> + type_str = 'stack'
> + elif type_flags & 16:
> + type_str = 'stack (red zone)'
> + elif type_flags & 32:
> + type_str = 'segment'
> + elif type_flags & 64:
> + type_str = 'vm_region'
> + else:
> + type_str = hex(type_flags)
> + return type_str
> +
> +def find_variable_containing_address(verbose, frame, match_addr):
> + variables = frame.GetVariables(True,True,True,True)
> + matching_var = None
> + for var in variables:
> + var_addr = var.GetLoadAddress()
> + if var_addr != lldb.LLDB_INVALID_ADDRESS:
> + byte_size = var.GetType().GetByteSize()
> + if verbose:
> + print 'frame #%u: [%#x - %#x) %s' % (frame.GetFrameID(),
> var.load_addr, var.load_addr + byte_size, var.name)
> + if var_addr == match_addr:
> + if verbose:
> + print 'match'
> + return var
> + else:
> + if byte_size > 0 and var_addr <= match_addr and
> match_addr < (var_addr + byte_size):
> + if verbose:
> + print 'match'
> + return var
> + return None
> +
> +def find_frame_for_stack_address(process, addr):
> + closest_delta = sys.maxint
> + closest_frame = None
> + #print 'find_frame_for_stack_address(%#x)' % (addr)
> + for thread in process:
> + prev_sp = lldb.LLDB_INVALID_ADDRESS
> + for frame in thread:
> + cfa = frame.GetCFA()
> + #print 'frame #%u: cfa = %#x' % (frame.GetFrameID(), cfa)
> + if addr < cfa:
> + delta = cfa - addr
> + #print '%#x < %#x, delta = %
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20151215/172b533d/attachment-0001.html>
More information about the lldb-commits
mailing list