forked from OSchip/llvm-project
[crashlog] Pass the debugger around instead of relying on lldb.debugger
The lldb.debugger et al convenience variables are only available from
the interactive script interpreter. In all other scenarios, they are
None (since fc1fd6bf9f
) before that they
were default initialized.
The crashlog script was hacking around that by setting the lldb.debugger
to a newly created debugger instance when running outside of the script
interpreter, which works fine until lldb creates a script interpreter
instance under the hood and clears the variables. This was resulting in
an AttributeError when invoking the script directly (from outside of
lldb):
AttributeError: 'NoneType' object has no attribute 'GetSourceManager'
This patch fixes that by passing around the debugger instance.
rdar://64775776
Differential revision: https://reviews.llvm.org/D90706
This commit is contained in:
parent
b45ea4451a
commit
c29c24be63
|
@ -131,7 +131,7 @@ class CrashLog(symbolication.Symbolicator):
|
||||||
if line_entry.IsValid():
|
if line_entry.IsValid():
|
||||||
strm = lldb.SBStream()
|
strm = lldb.SBStream()
|
||||||
if line_entry:
|
if line_entry:
|
||||||
lldb.debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers(
|
crash_log.debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers(
|
||||||
line_entry.file, line_entry.line, source_context, source_context, "->", strm)
|
line_entry.file, line_entry.line, source_context, source_context, "->", strm)
|
||||||
source_text = strm.GetData()
|
source_text = strm.GetData()
|
||||||
if source_text:
|
if source_text:
|
||||||
|
@ -310,9 +310,9 @@ class CrashLog(symbolication.Symbolicator):
|
||||||
self.unavailable = True
|
self.unavailable = True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __init__(self, path, verbose):
|
def __init__(self, debugger, path, verbose):
|
||||||
"""CrashLog constructor that take a path to a darwin crash log file"""
|
"""CrashLog constructor that take a path to a darwin crash log file"""
|
||||||
symbolication.Symbolicator.__init__(self)
|
symbolication.Symbolicator.__init__(self, debugger)
|
||||||
self.path = os.path.expanduser(path)
|
self.path = os.path.expanduser(path)
|
||||||
self.info_lines = list()
|
self.info_lines = list()
|
||||||
self.system_profile = list()
|
self.system_profile = list()
|
||||||
|
@ -360,12 +360,12 @@ class CrashLog(symbolication.Symbolicator):
|
||||||
for ident in self.idents:
|
for ident in self.idents:
|
||||||
image = self.find_image_with_identifier(ident)
|
image = self.find_image_with_identifier(ident)
|
||||||
if image:
|
if image:
|
||||||
self.target = image.create_target()
|
self.target = image.create_target(self.debugger)
|
||||||
if self.target:
|
if self.target:
|
||||||
return self.target # success
|
return self.target # success
|
||||||
print('crashlog.create_target()...3')
|
print('crashlog.create_target()...3')
|
||||||
for image in self.images:
|
for image in self.images:
|
||||||
self.target = image.create_target()
|
self.target = image.create_target(self.debugger)
|
||||||
if self.target:
|
if self.target:
|
||||||
return self.target # success
|
return self.target # success
|
||||||
print('crashlog.create_target()...4')
|
print('crashlog.create_target()...4')
|
||||||
|
@ -411,12 +411,12 @@ class CrashLogParser:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, path, verbose):
|
def __init__(self, debugger, path, verbose):
|
||||||
self.path = os.path.expanduser(path)
|
self.path = os.path.expanduser(path)
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
self.thread = None
|
self.thread = None
|
||||||
self.app_specific_backtrace = False
|
self.app_specific_backtrace = False
|
||||||
self.crashlog = CrashLog(self.path, self.verbose)
|
self.crashlog = CrashLog(debugger, self.path, self.verbose)
|
||||||
self.parse_mode = CrashLogParseMode.NORMAL
|
self.parse_mode = CrashLogParseMode.NORMAL
|
||||||
self.parsers = {
|
self.parsers = {
|
||||||
CrashLogParseMode.NORMAL : self.parse_normal,
|
CrashLogParseMode.NORMAL : self.parse_normal,
|
||||||
|
@ -711,7 +711,7 @@ class Interactive(cmd.Cmd):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def interactive_crashlogs(options, args):
|
def interactive_crashlogs(debugger, options, args):
|
||||||
crash_log_files = list()
|
crash_log_files = list()
|
||||||
for arg in args:
|
for arg in args:
|
||||||
for resolved_path in glob.glob(arg):
|
for resolved_path in glob.glob(arg):
|
||||||
|
@ -720,7 +720,7 @@ def interactive_crashlogs(options, args):
|
||||||
crash_logs = list()
|
crash_logs = list()
|
||||||
for crash_log_file in crash_log_files:
|
for crash_log_file in crash_log_files:
|
||||||
try:
|
try:
|
||||||
crash_log = CrashLogParser(crash_log_file, options.verbose).parse()
|
crash_log = CrashLogParser(debugger, crash_log_file, options.verbose).parse()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
continue
|
continue
|
||||||
|
@ -848,7 +848,7 @@ def save_crashlog(debugger, command, exe_ctx, result, dict):
|
||||||
|
|
||||||
def Symbolicate(debugger, command, result, dict):
|
def Symbolicate(debugger, command, result, dict):
|
||||||
try:
|
try:
|
||||||
SymbolicateCrashLogs(shlex.split(command))
|
SymbolicateCrashLogs(debugger, shlex.split(command))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result.PutCString("error: python exception: %s" % e)
|
result.PutCString("error: python exception: %s" % e)
|
||||||
|
|
||||||
|
@ -1024,7 +1024,7 @@ def CreateSymbolicateCrashLogOptions(
|
||||||
return option_parser
|
return option_parser
|
||||||
|
|
||||||
|
|
||||||
def SymbolicateCrashLogs(command_args):
|
def SymbolicateCrashLogs(debugger, command_args):
|
||||||
description = '''Symbolicate one or more darwin crash log files to provide source file and line information,
|
description = '''Symbolicate one or more darwin crash log files to provide source file and line information,
|
||||||
inlined stack frames back to the concrete functions, and disassemble the location of the crash
|
inlined stack frames back to the concrete functions, and disassemble the location of the crash
|
||||||
for the first frame of the crashed thread.
|
for the first frame of the crashed thread.
|
||||||
|
@ -1052,17 +1052,17 @@ be disassembled and lookups can be performed using the addresses found in the cr
|
||||||
|
|
||||||
if args:
|
if args:
|
||||||
if options.interactive:
|
if options.interactive:
|
||||||
interactive_crashlogs(options, args)
|
interactive_crashlogs(debugger, options, args)
|
||||||
else:
|
else:
|
||||||
for crash_log_file in args:
|
for crash_log_file in args:
|
||||||
crash_log_parser = CrashLogParser(crash_log_file, options.verbose)
|
crash_log_parser = CrashLogParser(debugger, crash_log_file, options.verbose)
|
||||||
crash_log = crash_log_parser.parse()
|
crash_log = crash_log_parser.parse()
|
||||||
SymbolicateCrashLog(crash_log, options)
|
SymbolicateCrashLog(crash_log, options)
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Create a new debugger instance
|
# Create a new debugger instance
|
||||||
lldb.debugger = lldb.SBDebugger.Create()
|
debugger = lldb.SBDebugger.Create()
|
||||||
SymbolicateCrashLogs(sys.argv[1:])
|
SymbolicateCrashLogs(debugger, sys.argv[1:])
|
||||||
lldb.SBDebugger.Destroy(lldb.debugger)
|
lldb.SBDebugger.Destroy(debugger)
|
||||||
elif getattr(lldb, 'debugger', None):
|
elif getattr(lldb, 'debugger', None):
|
||||||
lldb.debugger.HandleCommand(
|
lldb.debugger.HandleCommand(
|
||||||
'command script add -f lldb.macosx.crashlog.Symbolicate crashlog')
|
'command script add -f lldb.macosx.crashlog.Symbolicate crashlog')
|
||||||
|
|
|
@ -410,7 +410,7 @@ class Image:
|
||||||
return str(self.uuid).upper()
|
return str(self.uuid).upper()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def create_target(self):
|
def create_target(self, debugger):
|
||||||
'''Create a target using the information in this Image object.'''
|
'''Create a target using the information in this Image object.'''
|
||||||
if self.unavailable:
|
if self.unavailable:
|
||||||
return None
|
return None
|
||||||
|
@ -419,7 +419,7 @@ class Image:
|
||||||
resolved_path = self.get_resolved_path()
|
resolved_path = self.get_resolved_path()
|
||||||
path_spec = lldb.SBFileSpec(resolved_path)
|
path_spec = lldb.SBFileSpec(resolved_path)
|
||||||
error = lldb.SBError()
|
error = lldb.SBError()
|
||||||
target = lldb.debugger.CreateTarget(
|
target = debugger.CreateTarget(
|
||||||
resolved_path, self.arch, None, False, error)
|
resolved_path, self.arch, None, False, error)
|
||||||
if target:
|
if target:
|
||||||
self.module = target.FindModule(path_spec)
|
self.module = target.FindModule(path_spec)
|
||||||
|
@ -437,8 +437,9 @@ class Image:
|
||||||
|
|
||||||
class Symbolicator:
|
class Symbolicator:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, debugger):
|
||||||
"""A class the represents the information needed to symbolicate addresses in a program"""
|
"""A class the represents the information needed to symbolicate addresses in a program"""
|
||||||
|
self.debugger = debugger
|
||||||
self.target = None
|
self.target = None
|
||||||
self.images = list() # a list of images to be used when symbolicating
|
self.images = list() # a list of images to be used when symbolicating
|
||||||
self.addr_mask = 0xffffffffffffffff
|
self.addr_mask = 0xffffffffffffffff
|
||||||
|
@ -496,7 +497,7 @@ class Symbolicator:
|
||||||
|
|
||||||
if self.images:
|
if self.images:
|
||||||
for image in self.images:
|
for image in self.images:
|
||||||
self.target = image.create_target()
|
self.target = image.create_target(self.debugger)
|
||||||
if self.target:
|
if self.target:
|
||||||
if self.target.GetAddressByteSize() == 4:
|
if self.target.GetAddressByteSize() == 4:
|
||||||
triple = self.target.triple
|
triple = self.target.triple
|
||||||
|
@ -632,7 +633,7 @@ def print_module_symbols(module):
|
||||||
print(sym)
|
print(sym)
|
||||||
|
|
||||||
|
|
||||||
def Symbolicate(command_args):
|
def Symbolicate(debugger, command_args):
|
||||||
|
|
||||||
usage = "usage: %prog [options] <addr1> [addr2 ...]"
|
usage = "usage: %prog [options] <addr1> [addr2 ...]"
|
||||||
description = '''Symbolicate one or more addresses using LLDB's python scripting API..'''
|
description = '''Symbolicate one or more addresses using LLDB's python scripting API..'''
|
||||||
|
@ -686,7 +687,7 @@ def Symbolicate(command_args):
|
||||||
(options, args) = parser.parse_args(command_args)
|
(options, args) = parser.parse_args(command_args)
|
||||||
except:
|
except:
|
||||||
return
|
return
|
||||||
symbolicator = Symbolicator()
|
symbolicator = Symbolicator(debugger)
|
||||||
images = list()
|
images = list()
|
||||||
if options.file:
|
if options.file:
|
||||||
image = Image(options.file)
|
image = Image(options.file)
|
||||||
|
@ -720,5 +721,6 @@ def Symbolicate(command_args):
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Create a new debugger instance
|
# Create a new debugger instance
|
||||||
lldb.debugger = lldb.SBDebugger.Create()
|
debugger = lldb.SBDebugger.Create()
|
||||||
Symbolicate(sys.argv[1:])
|
Symbolicate(debugger, sys.argv[1:])
|
||||||
|
SBDebugger.Destroy(debugger)
|
||||||
|
|
Loading…
Reference in New Issue