JDevlieghere created this revision.
JDevlieghere added a reviewer: clayborg.
JDevlieghere requested review of this revision.

The `lldb.debugger` et al convenience variables are only available from the 
interactive script interpreter. In all other scenarios, they are `None` (since 
fc1fd6bf9fcfac412b10b4193805ec5de0e8df57) 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.


https://reviews.llvm.org/D90706

Files:
  lldb/examples/python/crashlog.py
  lldb/examples/python/symbolication.py

Index: lldb/examples/python/symbolication.py
===================================================================
--- lldb/examples/python/symbolication.py
+++ lldb/examples/python/symbolication.py
@@ -419,7 +419,7 @@
             resolved_path = self.get_resolved_path()
             path_spec = lldb.SBFileSpec(resolved_path)
             error = lldb.SBError()
-            target = lldb.debugger.CreateTarget(
+            target = self.debugger.CreateTarget(
                 resolved_path, self.arch, None, False, error)
             if target:
                 self.module = target.FindModule(path_spec)
@@ -437,8 +437,9 @@
 
 class Symbolicator:
 
-    def __init__(self):
+    def __init__(self, debugger):
         """A class the represents the information needed to symbolicate addresses in a program"""
+        self.debugger = debugger
         self.target = None
         self.images = list()  # a list of images to be used when symbolicating
         self.addr_mask = 0xffffffffffffffff
@@ -632,7 +633,7 @@
         print(sym)
 
 
-def Symbolicate(command_args):
+def Symbolicate(debugger, command_args):
 
     usage = "usage: %prog [options] <addr1> [addr2 ...]"
     description = '''Symbolicate one or more addresses using LLDB's python scripting API..'''
@@ -686,7 +687,7 @@
         (options, args) = parser.parse_args(command_args)
     except:
         return
-    symbolicator = Symbolicator()
+    symbolicator = Symbolicator(debugger)
     images = list()
     if options.file:
         image = Image(options.file)
@@ -720,5 +721,6 @@
 
 if __name__ == '__main__':
     # Create a new debugger instance
-    lldb.debugger = lldb.SBDebugger.Create()
-    Symbolicate(sys.argv[1:])
+    debugger = lldb.SBDebugger.Create()
+    Symbolicate(debugger, sys.argv[1:])
+    SBDebugger.Destroy(debugger)
Index: lldb/examples/python/crashlog.py
===================================================================
--- lldb/examples/python/crashlog.py
+++ lldb/examples/python/crashlog.py
@@ -131,7 +131,7 @@
                             if line_entry.IsValid():
                                 strm = lldb.SBStream()
                                 if line_entry:
-                                    lldb.debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers(
+                                    crash_log.debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers(
                                         line_entry.file, line_entry.line, source_context, source_context, "->", strm)
                                 source_text = strm.GetData()
                                 if source_text:
@@ -310,9 +310,9 @@
                 self.unavailable = True
             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"""
-        symbolication.Symbolicator.__init__(self)
+        symbolication.Symbolicator.__init__(self, debugger)
         self.path = os.path.expanduser(path)
         self.info_lines = list()
         self.system_profile = list()
@@ -411,12 +411,12 @@
                                  )
 
 
-    def __init__(self, path, verbose):
+    def __init__(self, debugger, path, verbose):
         self.path = os.path.expanduser(path)
         self.verbose = verbose
         self.thread = None
         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.parsers = {
             CrashLogParseMode.NORMAL : self.parse_normal,
@@ -711,7 +711,7 @@
         return False
 
 
-def interactive_crashlogs(options, args):
+def interactive_crashlogs(debugger, options, args):
     crash_log_files = list()
     for arg in args:
         for resolved_path in glob.glob(arg):
@@ -720,7 +720,7 @@
     crash_logs = list()
     for crash_log_file in crash_log_files:
         try:
-            crash_log = CrashLogParser(crash_log_file, options.verbose).parse()
+            crash_log = CrashLogParser(debugger, crash_log_file, options.verbose).parse()
         except Exception as e:
             print(e)
             continue
@@ -848,7 +848,9 @@
 
 def Symbolicate(debugger, command, result, dict):
     try:
-        SymbolicateCrashLogs(shlex.split(command))
+        # This is only called from LLDB's interactive script interpreter so we
+        # can rely on lldb.debugger being set.
+        SymbolicateCrashLogs(lldb.debugger, shlex.split(command))
     except Exception as e:
         result.PutCString("error: python exception: %s" % e)
 
@@ -1024,7 +1026,7 @@
     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,
 inlined stack frames back to the concrete functions, and disassemble the location of the crash
 for the first frame of the crashed thread.
@@ -1052,17 +1054,17 @@
 
     if args:
         if options.interactive:
-            interactive_crashlogs(options, args)
+            interactive_crashlogs(debugger, options, args)
         else:
             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()
                 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)
+    debugger = lldb.SBDebugger.Create()
+    SymbolicateCrashLogs(debugger, sys.argv[1:])
+    lldb.SBDebugger.Destroy(debugger)
 elif getattr(lldb, 'debugger', None):
     lldb.debugger.HandleCommand(
         'command script add -f lldb.macosx.crashlog.Symbolicate crashlog')
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to