[Lldb-commits] [lldb] 4b84682 - [crashlog] Move crash log parsing into its own class

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Tue Nov 3 09:04:42 PST 2020


Author: Jonas Devlieghere
Date: 2020-11-03T09:04:35-08:00
New Revision: 4b846820445ef33a099a19b5df983ed2f9d6e067

URL: https://github.com/llvm/llvm-project/commit/4b846820445ef33a099a19b5df983ed2f9d6e067
DIFF: https://github.com/llvm/llvm-project/commit/4b846820445ef33a099a19b5df983ed2f9d6e067.diff

LOG: [crashlog] Move crash log parsing into its own class

Move crash log parsing out of the CrashLog class and into its own class
and add more tests.

Differential revision: https://reviews.llvm.org/D90664

Added: 
    lldb/test/Shell/ScriptInterpreter/Python/Crashlog/crashlog.test
    lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive.test
    lldb/test/Shell/ScriptInterpreter/Python/Crashlog/lit.local.cfg

Modified: 
    lldb/examples/python/crashlog.py

Removed: 
    lldb/test/Shell/ScriptInterpreter/Python/crashlog.test


################################################################################
diff  --git a/lldb/examples/python/crashlog.py b/lldb/examples/python/crashlog.py
index 85387756ce18..373065f165ca 100755
--- a/lldb/examples/python/crashlog.py
+++ b/lldb/examples/python/crashlog.py
@@ -71,41 +71,7 @@ def read_plist(s):
     else:
         return plistlib.readPlistFromString(s)
 
-class CrashLogParseMode:
-    NORMAL = 0
-    THREAD = 1
-    IMAGES = 2
-    THREGS = 3
-    SYSTEM = 4
-    INSTRS = 5
-
-
 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_instrs_regex = re.compile('^Thread ([0-9]+) instruction stream')
-    thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)')
-    app_backtrace_regex = re.compile(
-        '^Application Specific Backtrace ([0-9]+)([^:]*):(.*)')
-    version = r'(\(.+\)|(arm|x86_)[0-9a-z]+)\s+'
-    frame_regex = re.compile(r'^([0-9]+)' r'\s'                # id
-                             r'+(.+?)'    r'\s+'               # img_name
-                             r'(' +version+ r')?'              # img_version
-                             r'(0x[0-9a-fA-F]{7}[0-9a-fA-F]+)' # addr
-                             r' +(.*)'                         # offs
-                            )
-    null_frame_regex = re.compile(r'^([0-9]+)\s+\?\?\?\s+(0{7}0+) +(.*)')
-    image_regex_uuid = re.compile(r'(0x[0-9a-fA-F]+)'            # img_lo
-                                  r'\s+' '-' r'\s+'              #   -
-                                  r'(0x[0-9a-fA-F]+)'     r'\s+' # img_hi
-                                  r'[+]?(.+?)'            r'\s+' # img_name
-                                  r'(' +version+ ')?'            # img_version
-                                  r'(<([-0-9a-fA-F]+)>\s+)?'     # img_uuid
-                                  r'(/.*)'                       # img_path
-                                 )
-    empty_line_regex = re.compile('^$')
-
     class Thread:
         """Class that represents a thread in a darwin crash log"""
 
@@ -355,88 +321,174 @@ def __init__(self, path, verbose):
         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
         self.verbose = verbose
-        # 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 = CrashLogParseMode.NORMAL
-        thread = None
-        app_specific_backtrace = False
-        for line in self.file_lines:
-            # print line
+    def dump(self):
+        print("Crash Log File: %s" % (self.path))
+        if self.backtraces:
+            print("\nApplication Specific Backtraces:")
+            for thread in self.backtraces:
+                thread.dump('  ')
+        print("\nThreads:")
+        for thread in self.threads:
+            thread.dump('  ')
+        print("\nImages:")
+        for image in self.images:
+            image.dump('  ')
+
+    def find_image_with_identifier(self, identifier):
+        for image in self.images:
+            if image.identifier == identifier:
+                return image
+        regex_text = '^.*\.%s$' % (re.escape(identifier))
+        regex = re.compile(regex_text)
+        for image in self.images:
+            if regex.match(image.identifier):
+                return image
+        return None
+
+    def create_target(self):
+        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.')
+            print('       Try loading the executable into lldb before running crashlog')
+            print('       and/or make sure the .dSYM bundles can be found by Spotlight.')
+        return self.target
+
+    def get_target(self):
+        return self.target
+
+
+class CrashLogParseMode:
+    NORMAL = 0
+    THREAD = 1
+    IMAGES = 2
+    THREGS = 3
+    SYSTEM = 4
+    INSTRS = 5
+
+
+class CrashLogParser:
+    parent_process_regex = re.compile('^Parent Process:\s*(.*)\[(\d+)\]')
+    thread_state_regex = re.compile('^Thread ([0-9]+) crashed with')
+    thread_instrs_regex = re.compile('^Thread ([0-9]+) instruction stream')
+    thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)')
+    app_backtrace_regex = re.compile('^Application Specific Backtrace ([0-9]+)([^:]*):(.*)')
+    version = r'(\(.+\)|(arm|x86_)[0-9a-z]+)\s+'
+    frame_regex = re.compile(r'^([0-9]+)' r'\s'                # id
+                             r'+(.+?)'    r'\s+'               # img_name
+                             r'(' +version+ r')?'              # img_version
+                             r'(0x[0-9a-fA-F]{7}[0-9a-fA-F]+)' # addr
+                             r' +(.*)'                         # offs
+                            )
+    null_frame_regex = re.compile(r'^([0-9]+)\s+\?\?\?\s+(0{7}0+) +(.*)')
+    image_regex_uuid = re.compile(r'(0x[0-9a-fA-F]+)'            # img_lo
+                                  r'\s+' '-' r'\s+'              #   -
+                                  r'(0x[0-9a-fA-F]+)'     r'\s+' # img_hi
+                                  r'[+]?(.+?)'            r'\s+' # img_name
+                                  r'(' +version+ ')?'            # img_version
+                                  r'(<([-0-9a-fA-F]+)>\s+)?'     # img_uuid
+                                  r'(/.*)'                       # img_path
+                                 )
+
+
+    def __init__(self, path, verbose):
+        self.path = os.path.expanduser(path)
+        self.verbose = verbose
+        self.parse_mode = CrashLogParseMode.NORMAL
+        self.thread = None
+        self.app_specific_backtrace = False
+        self.crashlog = CrashLog(self.path, self.verbose)
+
+    def parse(self):
+        with open(self.path,'r') as f:
+            lines = f.read().splitlines()
+
+        for line in lines:
             line_len = len(line)
             if line_len == 0:
-                if thread:
-                    if parse_mode == CrashLogParseMode.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)
+                if self.thread:
+                    if self.parse_mode == CrashLogParseMode.THREAD:
+                        if self.thread.index == self.crashlog.crashed_thread_idx:
+                            self.thread.reason = ''
+                            if self.crashlog.thread_exception:
+                                self.thread.reason += self.crashlog.thread_exception
+                            if self.crashlog.thread_exception_data:
+                                self.thread.reason += " (%s)" % self.crashlog.thread_exception_data
+                        if self.app_specific_backtrace:
+                            self.crashlog.backtraces.append(self.thread)
                         else:
-                            self.threads.append(thread)
-                    thread = None
+                            self.crashlog.threads.append(self.thread)
+                    self.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 = CrashLogParseMode.NORMAL
-            elif parse_mode == CrashLogParseMode.NORMAL:
+                    if len(self.crashlog.info_lines) > 0 and len(self.crashlog.info_lines[-1]):
+                        self.crashlog.info_lines.append(line)
+                self.parse_mode = CrashLogParseMode.NORMAL
+            elif self.parse_mode == CrashLogParseMode.NORMAL:
                 if line.startswith('Process:'):
-                    (self.process_name, pid_with_brackets) = line[
+                    (self.crashlog.process_name, pid_with_brackets) = line[
                         8:].strip().split(' [')
-                    self.process_id = pid_with_brackets.strip('[]')
+                    self.crashlog.process_id = pid_with_brackets.strip('[]')
                 elif line.startswith('Path:'):
-                    self.process_path = line[5:].strip()
+                    self.crashlog.process_path = line[5:].strip()
                 elif line.startswith('Identifier:'):
-                    self.process_identifier = line[11:].strip()
+                    self.crashlog.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(
+                        self.crashlog.process_version = matched_pair.group(1)
+                        self.crashlog.process_compatability_version = matched_pair.group(
                             2)
                     else:
-                        self.process = version_string
-                        self.process_compatability_version = version_string
+                        self.crashlog.process = version_string
+                        self.crashlog.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)
+                    self.crashlog.parent_process_name = parent_process_match.group(1)
+                    self.crashlog.parent_process_id = parent_process_match.group(2)
                 elif line.startswith('Exception Type:'):
-                    self.thread_exception = line[15:].strip()
+                    self.crashlog.thread_exception = line[15:].strip()
                     continue
                 elif line.startswith('Exception Codes:'):
-                    self.thread_exception_data = line[16:].strip()
+                    self.crashlog.thread_exception_data = line[16:].strip()
                     continue
                 elif line.startswith('Exception Subtype:'): # iOS
-                    self.thread_exception_data = line[18:].strip()
+                    self.crashlog.thread_exception_data = line[18:].strip()
                     continue
                 elif line.startswith('Crashed Thread:'):
-                    self.crashed_thread_idx = int(line[15:].strip().split()[0])
+                    self.crashlog.crashed_thread_idx = int(line[15:].strip().split()[0])
                     continue
                 elif line.startswith('Triggered by Thread:'): # iOS
-                    self.crashed_thread_idx = int(line[20:].strip().split()[0])
+                    self.crashlog.crashed_thread_idx = int(line[20:].strip().split()[0])
                     continue
                 elif line.startswith('Report Version:'):
-                    self.version = int(line[15:].strip())
+                    self.crashlog.version = int(line[15:].strip())
                     continue
                 elif line.startswith('System Profile:'):
-                    parse_mode = CrashLogParseMode.SYSTEM
+                    self.parse_mode = CrashLogParseMode.SYSTEM
                     continue
                 elif (line.startswith('Interval Since Last Report:') or
                       line.startswith('Crashes Since Last Report:') or
@@ -449,41 +501,41 @@ def __init__(self, path, verbose):
                 elif line.startswith('Thread'):
                     thread_state_match = self.thread_state_regex.search(line)
                     if thread_state_match:
-                        app_specific_backtrace = False
+                        self.app_specific_backtrace = False
                         thread_state_match = self.thread_regex.search(line)
                         thread_idx = int(thread_state_match.group(1))
-                        parse_mode = CrashLogParseMode.THREGS
-                        thread = self.threads[thread_idx]
+                        self.parse_mode = CrashLogParseMode.THREGS
+                        self.thread = self.crashlog.threads[thread_idx]
                         continue
                     thread_insts_match  = self.thread_instrs_regex.search(line)
                     if thread_insts_match:
-                        parse_mode = CrashLogParseMode.INSTRS
+                        self.parse_mode = CrashLogParseMode.INSTRS
                         continue
                     thread_match = self.thread_regex.search(line)
                     if thread_match:
-                        app_specific_backtrace = False
-                        parse_mode = CrashLogParseMode.THREAD
+                        self.app_specific_backtrace = False
+                        self.parse_mode = CrashLogParseMode.THREAD
                         thread_idx = int(thread_match.group(1))
-                        thread = CrashLog.Thread(thread_idx, False)
+                        self.thread = self.crashlog.Thread(thread_idx, False)
                         continue
                     continue
                 elif line.startswith('Binary Images:'):
-                    parse_mode = CrashLogParseMode.IMAGES
+                    self.parse_mode = CrashLogParseMode.IMAGES
                     continue
                 elif line.startswith('Application Specific Backtrace'):
                     app_backtrace_match = self.app_backtrace_regex.search(line)
                     if app_backtrace_match:
-                        parse_mode = CrashLogParseMode.THREAD
-                        app_specific_backtrace = True
+                        self.parse_mode = CrashLogParseMode.THREAD
+                        self.app_specific_backtrace = True
                         idx = int(app_backtrace_match.group(1))
-                        thread = CrashLog.Thread(idx, True)
+                        self.thread = self.crashlog.Thread(idx, True)
                 elif line.startswith('Last Exception Backtrace:'): # iOS
-                    parse_mode = CrashLogParseMode.THREAD
-                    app_specific_backtrace = True
+                    self.parse_mode = CrashLogParseMode.THREAD
+                    self.app_specific_backtrace = True
                     idx = 1
-                    thread = CrashLog.Thread(idx, True)
-                self.info_lines.append(line.strip())
-            elif parse_mode == CrashLogParseMode.THREAD:
+                    self.thread = self.crashlog.Thread(idx, True)
+                self.crashlog.info_lines.append(line.strip())
+            elif self.parse_mode == CrashLogParseMode.THREAD:
                 if line.startswith('Thread'):
                     continue
                 if self.null_frame_regex.search(line):
@@ -494,94 +546,43 @@ def __init__(self, path, verbose):
                     (frame_id, frame_img_name, _, frame_img_version, _,
                      frame_addr, frame_ofs) = frame_match.groups()
                     ident = frame_img_name
-                    thread.add_ident(ident)
-                    if ident not in self.idents:
-                        self.idents.append(ident)
-                    thread.frames.append(CrashLog.Frame(int(frame_id), int(
+                    self.thread.add_ident(ident)
+                    if ident not in self.crashlog.idents:
+                        self.crashlog.idents.append(ident)
+                    self.thread.frames.append(self.crashlog.Frame(int(frame_id), int(
                         frame_addr, 0), frame_ofs))
                 else:
                     print('error: frame regex failed for line: "%s"' % line)
-            elif parse_mode == CrashLogParseMode.IMAGES:
+            elif self.parse_mode == CrashLogParseMode.IMAGES:
                 image_match = self.image_regex_uuid.search(line)
                 if image_match:
                     (img_lo, img_hi, img_name, _, img_version, _,
                      _, img_uuid, img_path) = image_match.groups()
-                    image = CrashLog.DarwinImage(int(img_lo, 0), int(img_hi, 0),
+                    image = self.crashlog.DarwinImage(int(img_lo, 0), int(img_hi, 0),
                                                  img_name.strip(),
                                                  img_version.strip()
                                                  if img_version else "",
                                                  uuid.UUID(img_uuid), img_path,
                                                  self.verbose)
-                    self.images.append(image)
+                    self.crashlog.images.append(image)
                 else:
                     print("error: image regex failed for: %s" % line)
 
-            elif parse_mode == CrashLogParseMode.THREGS:
+            elif self.parse_mode == CrashLogParseMode.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:
                     (reg, value) = reg_value.split(': ')
-                    thread.registers[reg.strip()] = int(value, 0)
-            elif parse_mode == CrashLogParseMode.SYSTEM:
-                self.system_profile.append(line)
-            elif parse_mode == CrashLogParseMode.INSTRS:
+                    self.thread.registers[reg.strip()] = int(value, 0)
+            elif self.parse_mode == CrashLogParseMode.SYSTEM:
+                self.crashlog.system_profile.append(line)
+            elif self.parse_mode == CrashLogParseMode.INSTRS:
                 pass
-        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('  ')
+        return self.crashlog
 
-    def find_image_with_identifier(self, identifier):
-        for image in self.images:
-            if image.identifier == identifier:
-                return image
-        regex_text = '^.*\.%s$' % (re.escape(identifier))
-        regex = re.compile(regex_text)
-        for image in self.images:
-            if regex.match(image.identifier):
-                return image
-        return None
-
-    def create_target(self):
-        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.')
-            print('       Try loading the executable into lldb before running crashlog')
-            print('       and/or make sure the .dSYM bundles can be found by Spotlight.')
-        return self.target
-
-    def get_target(self):
-        return self.target
 
 
 def usage():
@@ -702,9 +703,10 @@ def interactive_crashlogs(options, args):
 
     crash_logs = list()
     for crash_log_file in crash_log_files:
-        crash_log = CrashLog(crash_log_file, options.verbose)
-        if crash_log.error:
-            print(crash_log.error)
+        try:
+            crash_log = CrashLogParser(crash_log_file, options.verbose).parse()
+        except Exception as e:
+            print(e)
             continue
         if options.debug:
             crash_log.dump()
@@ -836,9 +838,6 @@ def Symbolicate(debugger, command, result, dict):
 
 
 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:
@@ -1040,7 +1039,8 @@ def SymbolicateCrashLogs(command_args):
             interactive_crashlogs(options, args)
         else:
             for crash_log_file in args:
-                crash_log = CrashLog(crash_log_file, options.verbose)
+                crash_log_parser = CrashLogParser(crash_log_file, options.verbose)
+                crash_log = crash_log_parser.parse()
                 SymbolicateCrashLog(crash_log, options)
 if __name__ == '__main__':
     # Create a new debugger instance
@@ -1052,4 +1052,3 @@ def SymbolicateCrashLogs(command_args):
         'command script add -f lldb.macosx.crashlog.Symbolicate crashlog')
     lldb.debugger.HandleCommand(
         'command script add -f lldb.macosx.crashlog.save_crashlog save_crashlog')
-    print('"crashlog" and "save_crashlog" command installed, use the "--help" option for detailed help')

diff  --git a/lldb/test/Shell/ScriptInterpreter/Python/crashlog.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/crashlog.test
similarity index 91%
rename from lldb/test/Shell/ScriptInterpreter/Python/crashlog.test
rename to lldb/test/Shell/ScriptInterpreter/Python/Crashlog/crashlog.test
index 293d34514fdc..6ac9392c87c1 100644
--- a/lldb/test/Shell/ScriptInterpreter/Python/crashlog.test
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/crashlog.test
@@ -1,12 +1,11 @@
 #                                                                 -*- python -*-
-# REQUIRES: system-darwin
-# UNSUPPORTED: lldb-repro
-# DEBUG: cd %S/../../../../examples/python && cat %s | %lldb && false
-# RUN: cd %S/../../../../examples/python && cat %s | %lldb | FileCheck %s
+# DEBUG: cd %S/../../../../../examples/python && cat %s | %lldb && false
+# RUN: cd %S/../../../../../examples/python && cat %s | %lldb | FileCheck %s
 # CHECK-LABEL: {{S}}KIP BEYOND CHECKS
 script
 import crashlog
-cl = crashlog.CrashLog
+crash_log_parser = crashlog.CrashLogParser
+crash_log = crashlog.CrashLog
 images = [
 "0x10b60b000 - 0x10f707fff com.apple.LLDB.framework (1.1000.11.38.2 - 1000.11.38.2) <96E36F5C-1A83-39A1-8713-5FDD9701C3F1> /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/LLDB",
 # CHECK: 0x10b60b000
@@ -120,7 +119,7 @@ print("SKIP BEYOND CHECKS")
 for image in images:
     print('"%s"'%image)
     print("--------------")
-    match = cl.image_regex_uuid.search(image)
+    match = crash_log_parser.image_regex_uuid.search(image)
     for group in match.groups():
         print(group)
 
@@ -128,7 +127,7 @@ print("FRAMES")
 for frame in frames:
     print('"%s"'%frame)
     print("--------------")
-    match = cl.frame_regex.search(frame)
+    match = crash_log_parser.frame_regex.search(frame)
     for group in match.groups():
         print(group)
 

diff  --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive.test
new file mode 100644
index 000000000000..2690b7fa2122
--- /dev/null
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive.test
@@ -0,0 +1,8 @@
+# RUN: echo "quit" | %S/../../../../../examples/python/crashlog.py -i %s 2>&1 | FileCheck %s
+# CHECK: 1 crash logs are loaded:
+# CHECK: [0] = {{.*}}interactive.test
+# CHECK: Interactive crashlogs prompt, type "help" to see a list of supported commands.
+
+Binary Images:
+       0x10ab87000 -        0x10abdafff +lldb (10.0.0) <87BD1384-BAE9-3625-A838-9D241CBAEF87> /Volumes/VOLUME/*/lldb
+       0x10ac45000 -        0x10ae94fff  com.apple.python3 (3.8.2 - 3.8.2) <20BC3FC4-CAAD-3002-ACDF-423A3188F24C> /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/Python3

diff  --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/lit.local.cfg b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/lit.local.cfg
new file mode 100644
index 000000000000..417069653d68
--- /dev/null
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/lit.local.cfg
@@ -0,0 +1,5 @@
+if 'system-darwin' not in config.available_features:
+  config.unsupported = True
+
+if 'lldb-repro' in config.available_features:
+  config.unsupported = True


        


More information about the lldb-commits mailing list