diff --git a/lldb/examples/python/crashlog.py b/lldb/examples/python/crashlog.py --- a/lldb/examples/python/crashlog.py +++ b/lldb/examples/python/crashlog.py @@ -537,21 +537,21 @@ class CrashLogParser: @staticmethod - def create(debugger, path, verbose): + def create(debugger, path, options): data = JSONCrashLogParser.is_valid_json(path) if data: - parser = JSONCrashLogParser(debugger, path, verbose) + parser = JSONCrashLogParser(debugger, path, options) parser.data = data return parser else: - return TextCrashLogParser(debugger, path, verbose) + return TextCrashLogParser(debugger, path, options) - def __init__(self, debugger, path, verbose): + def __init__(self, debugger, path, options): self.path = os.path.expanduser(path) - self.verbose = verbose + self.options = options # List of DarwinImages sorted by their index. self.images = list() - self.crashlog = CrashLog(debugger, self.path, self.verbose) + self.crashlog = CrashLog(debugger, self.path, self.options.verbose) @abc.abstractmethod def parse(self): @@ -577,8 +577,8 @@ except: return None - def __init__(self, debugger, path, verbose): - super().__init__(debugger, path, verbose) + def __init__(self, debugger, path, options): + super().__init__(debugger, path, options) def parse(self): try: @@ -639,7 +639,7 @@ path = json_image["path"] if "path" in json_image else "" version = "" darwin_image = self.crashlog.DarwinImage( - low, high, name, version, img_uuid, path, self.verbose + low, high, name, version, img_uuid, path, self.options.verbose ) if "arch" in json_image: darwin_image.arch = json_image["arch"] @@ -898,8 +898,8 @@ ) exception_extra_regex = re.compile(r"^Exception\s+.*:\s+(.*)") - def __init__(self, debugger, path, verbose): - super().__init__(debugger, path, verbose) + def __init__(self, debugger, path, options): + super().__init__(debugger, path, options) self.thread = None self.app_specific_backtrace = False self.parse_mode = CrashLogParseMode.NORMAL @@ -917,8 +917,15 @@ with open(self.path, "r", encoding="utf-8") as f: lines = f.read().splitlines() - for line in lines: + idx = 0 + lines_count = len(lines) + while True: + if idx >= lines_count: + break + + line = lines[idx] line_len = len(line) + if line_len == 0: if self.thread: if self.parse_mode == CrashLogParseMode.THREAD: @@ -935,22 +942,36 @@ else: 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.crashlog.info_lines) > 0 and len( - self.crashlog.info_lines[-1] - ): - self.crashlog.info_lines.append(line) + + empty_lines = 1 + while ( + idx + empty_lines < lines_count + and len(lines[idx + empty_lines]) == 0 + ): + empty_lines = empty_lines + 1 + + if ( + empty_lines == 1 + and idx + empty_lines < lines_count - 1 + and self.parse_mode != CrashLogParseMode.NORMAL + ): + # check if next line can be parsed with the current parse mode + next_line_idx = idx + empty_lines + if self.parsers[self.parse_mode](lines[next_line_idx]): + # If that suceeded, skip the empty line and the next line. + idx = next_line_idx + 1 + continue self.parse_mode = CrashLogParseMode.NORMAL - else: - self.parsers[self.parse_mode](line) + + self.parsers[self.parse_mode](line) + + idx = idx + 1 return self.crashlog def parse_exception(self, line): if not line.startswith("Exception"): - return + return False if line.startswith("Exception Type:"): self.crashlog.thread_exception = line[15:].strip() exception_type_match = self.exception_type_regex.search(line) @@ -968,7 +989,7 @@ elif line.startswith("Exception Codes:"): self.crashlog.thread_exception_data = line[16:].strip() if "type" not in self.crashlog.exception: - return + return False exception_codes_match = self.exception_codes_regex.search(line) if exception_codes_match: self.crashlog.exception["codes"] = self.crashlog.thread_exception_data @@ -979,10 +1000,11 @@ ] else: if "type" not in self.crashlog.exception: - return + return False exception_extra_match = self.exception_extra_regex.search(line) if exception_extra_match: self.crashlog.exception["message"] = exception_extra_match.group(1) + return True def parse_normal(self, line): if line.startswith("Process:"): @@ -1081,14 +1103,14 @@ def parse_thread(self, line): if line.startswith("Thread"): - return + return False if self.null_frame_regex.search(line): print('warning: thread parser ignored null-frame: "%s"' % line) - return + return False frame_match = self.frame_regex.search(line) if not frame_match: print('error: frame regex failed for line: "%s"' % line) - return + return False frame_id = ( frame_img_name @@ -1155,6 +1177,8 @@ self.crashlog.Frame(int(frame_id), int(frame_addr, 0), description) ) + return True + def parse_images(self, line): image_match = self.image_regex_uuid.search(line) if image_match: @@ -1174,7 +1198,7 @@ img_version.strip() if img_version else "", uuid.UUID(img_uuid), img_path, - self.verbose, + self.options.verbose, ) unqualified_img_name = os.path.basename(img_path) if unqualified_img_name in self.symbols: @@ -1188,17 +1212,22 @@ self.images.append(image) self.crashlog.images.append(image) + return True else: - print("error: image regex failed for: %s" % line) + if self.options.debug: + print("error: image regex failed for: %s" % line) + return False def parse_thread_registers(self, line): # "r12: 0x00007fff6b5939c8 r13: 0x0000000007000006 r14: 0x0000000000002a03 r15: 0x0000000000000c00" reg_values = re.findall("([a-z0-9]+): (0x[0-9a-f]+)", line, re.I) for reg, value in reg_values: self.thread.registers[reg] = int(value, 16) + return len(reg_values) != 0 def parse_system(self, line): self.crashlog.system_profile.append(line) + return True def parse_instructions(self, line): pass @@ -1412,7 +1441,7 @@ def load_crashlog_in_scripted_process(debugger, crashlog_path, options, result): - crashlog = CrashLogParser.create(debugger, crashlog_path, False).parse() + crashlog = CrashLogParser.create(debugger, crashlog_path, options).parse() target = lldb.SBTarget() # 1. Try to use the user-provided target @@ -1735,7 +1764,7 @@ result.SetError(str(e)) else: crash_log = CrashLogParser.create( - debugger, crashlog_path, options.verbose + debugger, crashlog_path, options ).parse() SymbolicateCrashLog(crash_log, options)