[Lldb-commits] [lldb] 16dd693 - [crashlog] Modularize parser

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Tue Nov 3 10:21:29 PST 2020


Author: Jonas Devlieghere
Date: 2020-11-03T10:21:21-08:00
New Revision: 16dd69347dfc80ec52f656b971102c31ccf78449

URL: https://github.com/llvm/llvm-project/commit/16dd69347dfc80ec52f656b971102c31ccf78449
DIFF: https://github.com/llvm/llvm-project/commit/16dd69347dfc80ec52f656b971102c31ccf78449.diff

LOG: [crashlog] Modularize parser

Instead of parsing the crashlog in one big loop, use methods that
correspond to the different parsing modes.

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

Added: 
    

Modified: 
    lldb/examples/python/crashlog.py

Removed: 
    


################################################################################
diff  --git a/lldb/examples/python/crashlog.py b/lldb/examples/python/crashlog.py
index 373065f165ca..76538715f17e 100755
--- a/lldb/examples/python/crashlog.py
+++ b/lldb/examples/python/crashlog.py
@@ -414,10 +414,18 @@ class CrashLogParser:
     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)
+        self.parse_mode = CrashLogParseMode.NORMAL
+        self.parsers = {
+            CrashLogParseMode.NORMAL : self.parse_normal,
+            CrashLogParseMode.THREAD : self.parse_thread,
+            CrashLogParseMode.IMAGES : self.parse_images,
+            CrashLogParseMode.THREGS : self.parse_thread_registers,
+            CrashLogParseMode.SYSTEM : self.parse_system,
+            CrashLogParseMode.INSTRS : self.parse_instructions,
+        }
 
     def parse(self):
         with open(self.path,'r') as f:
@@ -445,145 +453,153 @@ def parse(self):
                     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.crashlog.process_name, pid_with_brackets) = line[
-                        8:].strip().split(' [')
-                    self.crashlog.process_id = pid_with_brackets.strip('[]')
-                elif line.startswith('Path:'):
-                    self.crashlog.process_path = line[5:].strip()
-                elif line.startswith('Identifier:'):
-                    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.crashlog.process_version = matched_pair.group(1)
-                        self.crashlog.process_compatability_version = matched_pair.group(
-                            2)
-                    else:
-                        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.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.crashlog.thread_exception = line[15:].strip()
-                    continue
-                elif line.startswith('Exception Codes:'):
-                    self.crashlog.thread_exception_data = line[16:].strip()
-                    continue
-                elif line.startswith('Exception Subtype:'): # iOS
-                    self.crashlog.thread_exception_data = line[18:].strip()
-                    continue
-                elif line.startswith('Crashed Thread:'):
-                    self.crashlog.crashed_thread_idx = int(line[15:].strip().split()[0])
-                    continue
-                elif line.startswith('Triggered by Thread:'): # iOS
-                    self.crashlog.crashed_thread_idx = int(line[20:].strip().split()[0])
-                    continue
-                elif line.startswith('Report Version:'):
-                    self.crashlog.version = int(line[15:].strip())
-                    continue
-                elif line.startswith('System Profile:'):
-                    self.parse_mode = CrashLogParseMode.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:
-                        self.app_specific_backtrace = False
-                        thread_state_match = self.thread_regex.search(line)
-                        thread_idx = int(thread_state_match.group(1))
-                        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:
-                        self.parse_mode = CrashLogParseMode.INSTRS
-                        continue
-                    thread_match = self.thread_regex.search(line)
-                    if thread_match:
-                        self.app_specific_backtrace = False
-                        self.parse_mode = CrashLogParseMode.THREAD
-                        thread_idx = int(thread_match.group(1))
-                        self.thread = self.crashlog.Thread(thread_idx, False)
-                        continue
-                    continue
-                elif line.startswith('Binary 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:
-                        self.parse_mode = CrashLogParseMode.THREAD
-                        self.app_specific_backtrace = True
-                        idx = int(app_backtrace_match.group(1))
-                        self.thread = self.crashlog.Thread(idx, True)
-                elif line.startswith('Last Exception Backtrace:'): # iOS
-                    self.parse_mode = CrashLogParseMode.THREAD
-                    self.app_specific_backtrace = True
-                    idx = 1
-                    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):
-                    print('warning: thread parser ignored null-frame: "%s"' % line)
-                    continue
-                frame_match = self.frame_regex.search(line)
-                if frame_match:
-                    (frame_id, frame_img_name, _, frame_img_version, _,
-                     frame_addr, frame_ofs) = frame_match.groups()
-                    ident = frame_img_name
-                    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 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 = 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.crashlog.images.append(image)
-                else:
-                    print("error: image regex failed for: %s" % line)
-
-            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(': ')
-                    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
+            else:
+                self.parsers[self.parse_mode](line)
 
         return self.crashlog
 
 
+    def parse_normal(self, line):
+        if line.startswith('Process:'):
+            (self.crashlog.process_name, pid_with_brackets) = line[
+                8:].strip().split(' [')
+            self.crashlog.process_id = pid_with_brackets.strip('[]')
+        elif line.startswith('Path:'):
+            self.crashlog.process_path = line[5:].strip()
+        elif line.startswith('Identifier:'):
+            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.crashlog.process_version = matched_pair.group(1)
+                self.crashlog.process_compatability_version = matched_pair.group(
+                    2)
+            else:
+                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.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.crashlog.thread_exception = line[15:].strip()
+            return
+        elif line.startswith('Exception Codes:'):
+            self.crashlog.thread_exception_data = line[16:].strip()
+            return
+        elif line.startswith('Exception Subtype:'): # iOS
+            self.crashlog.thread_exception_data = line[18:].strip()
+            return
+        elif line.startswith('Crashed Thread:'):
+            self.crashlog.crashed_thread_idx = int(line[15:].strip().split()[0])
+            return
+        elif line.startswith('Triggered by Thread:'): # iOS
+            self.crashlog.crashed_thread_idx = int(line[20:].strip().split()[0])
+            return
+        elif line.startswith('Report Version:'):
+            self.crashlog.version = int(line[15:].strip())
+            return
+        elif line.startswith('System Profile:'):
+            self.parse_mode = CrashLogParseMode.SYSTEM
+            return
+        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
+            return
+        elif line.startswith('Thread'):
+            thread_state_match = self.thread_state_regex.search(line)
+            if thread_state_match:
+                self.app_specific_backtrace = False
+                thread_state_match = self.thread_regex.search(line)
+                thread_idx = int(thread_state_match.group(1))
+                self.parse_mode = CrashLogParseMode.THREGS
+                self.thread = self.crashlog.threads[thread_idx]
+                return
+            thread_insts_match  = self.thread_instrs_regex.search(line)
+            if thread_insts_match:
+                self.parse_mode = CrashLogParseMode.INSTRS
+                return
+            thread_match = self.thread_regex.search(line)
+            if thread_match:
+                self.app_specific_backtrace = False
+                self.parse_mode = CrashLogParseMode.THREAD
+                thread_idx = int(thread_match.group(1))
+                self.thread = self.crashlog.Thread(thread_idx, False)
+                return
+            return
+        elif line.startswith('Binary Images:'):
+            self.parse_mode = CrashLogParseMode.IMAGES
+            return
+        elif line.startswith('Application Specific Backtrace'):
+            app_backtrace_match = self.app_backtrace_regex.search(line)
+            if app_backtrace_match:
+                self.parse_mode = CrashLogParseMode.THREAD
+                self.app_specific_backtrace = True
+                idx = int(app_backtrace_match.group(1))
+                self.thread = self.crashlog.Thread(idx, True)
+        elif line.startswith('Last Exception Backtrace:'): # iOS
+            self.parse_mode = CrashLogParseMode.THREAD
+            self.app_specific_backtrace = True
+            idx = 1
+            self.thread = self.crashlog.Thread(idx, True)
+        self.crashlog.info_lines.append(line.strip())
+
+    def parse_thread(self, line):
+        if line.startswith('Thread'):
+            return
+        if self.null_frame_regex.search(line):
+            print('warning: thread parser ignored null-frame: "%s"' % line)
+            return
+        frame_match = self.frame_regex.search(line)
+        if frame_match:
+            (frame_id, frame_img_name, _, frame_img_version, _,
+                frame_addr, frame_ofs) = frame_match.groups()
+            ident = frame_img_name
+            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)
+
+    def parse_images(self, line):
+        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 = 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.crashlog.images.append(image)
+        else:
+            print("error: image regex failed for: %s" % line)
+
+
+    def parse_thread_registers(self, line):
+        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(': ')
+            self.thread.registers[reg.strip()] = int(value, 0)
+
+    def parse_system(self, line):
+        self.crashlog.system_profile.append(line)
+
+    def parse_instructions(self, line):
+        pass
+
 
 def usage():
     print("Usage: lldb-symbolicate.py [-n name] executable-image")


        


More information about the lldb-commits mailing list