@@ -537,21 +537,21 @@ class InteractiveCrashLogException(Exception):
537
537
538
538
class CrashLogParser :
539
539
@staticmethod
540
- def create (debugger , path , verbose ):
540
+ def create (debugger , path , options ):
541
541
data = JSONCrashLogParser .is_valid_json (path )
542
542
if data :
543
- parser = JSONCrashLogParser (debugger , path , verbose )
543
+ parser = JSONCrashLogParser (debugger , path , options )
544
544
parser .data = data
545
545
return parser
546
546
else :
547
- return TextCrashLogParser (debugger , path , verbose )
547
+ return TextCrashLogParser (debugger , path , options )
548
548
549
- def __init__ (self , debugger , path , verbose ):
549
+ def __init__ (self , debugger , path , options ):
550
550
self .path = os .path .expanduser (path )
551
- self .verbose = verbose
551
+ self .options = options
552
552
# List of DarwinImages sorted by their index.
553
553
self .images = list ()
554
- self .crashlog = CrashLog (debugger , self .path , self .verbose )
554
+ self .crashlog = CrashLog (debugger , self .path , self .options . verbose )
555
555
556
556
@abc .abstractmethod
557
557
def parse (self ):
@@ -577,8 +577,8 @@ def parse_json(buffer):
577
577
except :
578
578
return None
579
579
580
- def __init__ (self , debugger , path , verbose ):
581
- super ().__init__ (debugger , path , verbose )
580
+ def __init__ (self , debugger , path , options ):
581
+ super ().__init__ (debugger , path , options )
582
582
583
583
def parse (self ):
584
584
try :
@@ -639,7 +639,7 @@ def parse_images(self, json_images):
639
639
path = json_image ["path" ] if "path" in json_image else ""
640
640
version = ""
641
641
darwin_image = self .crashlog .DarwinImage (
642
- low , high , name , version , img_uuid , path , self .verbose
642
+ low , high , name , version , img_uuid , path , self .options . verbose
643
643
)
644
644
if "arch" in json_image :
645
645
darwin_image .arch = json_image ["arch" ]
@@ -898,8 +898,8 @@ def get(cls):
898
898
)
899
899
exception_extra_regex = re .compile (r"^Exception\s+.*:\s+(.*)" )
900
900
901
- def __init__ (self , debugger , path , verbose ):
902
- super ().__init__ (debugger , path , verbose )
901
+ def __init__ (self , debugger , path , options ):
902
+ super ().__init__ (debugger , path , options )
903
903
self .thread = None
904
904
self .app_specific_backtrace = False
905
905
self .parse_mode = CrashLogParseMode .NORMAL
@@ -917,8 +917,15 @@ def parse(self):
917
917
with open (self .path , "r" , encoding = "utf-8" ) as f :
918
918
lines = f .read ().splitlines ()
919
919
920
- for line in lines :
920
+ idx = 0
921
+ lines_count = len (lines )
922
+ while True :
923
+ if idx >= lines_count :
924
+ break
925
+
926
+ line = lines [idx ]
921
927
line_len = len (line )
928
+
922
929
if line_len == 0 :
923
930
if self .thread :
924
931
if self .parse_mode == CrashLogParseMode .THREAD :
@@ -935,22 +942,36 @@ def parse(self):
935
942
else :
936
943
self .crashlog .threads .append (self .thread )
937
944
self .thread = None
938
- else :
939
- # only append an extra empty line if the previous line
940
- # in the info_lines wasn't empty
941
- if len (self .crashlog .info_lines ) > 0 and len (
942
- self .crashlog .info_lines [- 1 ]
943
- ):
944
- self .crashlog .info_lines .append (line )
945
+
946
+ empty_lines = 1
947
+ while (
948
+ idx + empty_lines < lines_count
949
+ and len (lines [idx + empty_lines ]) == 0
950
+ ):
951
+ empty_lines = empty_lines + 1
952
+
953
+ if (
954
+ empty_lines == 1
955
+ and idx + empty_lines < lines_count - 1
956
+ and self .parse_mode != CrashLogParseMode .NORMAL
957
+ ):
958
+ # check if next line can be parsed with the current parse mode
959
+ next_line_idx = idx + empty_lines
960
+ if self .parsers [self .parse_mode ](lines [next_line_idx ]):
961
+ # If that suceeded, skip the empty line and the next line.
962
+ idx = next_line_idx + 1
963
+ continue
945
964
self .parse_mode = CrashLogParseMode .NORMAL
946
- else :
947
- self .parsers [self .parse_mode ](line )
965
+
966
+ self .parsers [self .parse_mode ](line )
967
+
968
+ idx = idx + 1
948
969
949
970
return self .crashlog
950
971
951
972
def parse_exception (self , line ):
952
973
if not line .startswith ("Exception" ):
953
- return
974
+ return False
954
975
if line .startswith ("Exception Type:" ):
955
976
self .crashlog .thread_exception = line [15 :].strip ()
956
977
exception_type_match = self .exception_type_regex .search (line )
@@ -968,7 +989,7 @@ def parse_exception(self, line):
968
989
elif line .startswith ("Exception Codes:" ):
969
990
self .crashlog .thread_exception_data = line [16 :].strip ()
970
991
if "type" not in self .crashlog .exception :
971
- return
992
+ return False
972
993
exception_codes_match = self .exception_codes_regex .search (line )
973
994
if exception_codes_match :
974
995
self .crashlog .exception ["codes" ] = self .crashlog .thread_exception_data
@@ -979,10 +1000,11 @@ def parse_exception(self, line):
979
1000
]
980
1001
else :
981
1002
if "type" not in self .crashlog .exception :
982
- return
1003
+ return False
983
1004
exception_extra_match = self .exception_extra_regex .search (line )
984
1005
if exception_extra_match :
985
1006
self .crashlog .exception ["message" ] = exception_extra_match .group (1 )
1007
+ return True
986
1008
987
1009
def parse_normal (self , line ):
988
1010
if line .startswith ("Process:" ):
@@ -1081,14 +1103,14 @@ def parse_normal(self, line):
1081
1103
1082
1104
def parse_thread (self , line ):
1083
1105
if line .startswith ("Thread" ):
1084
- return
1106
+ return False
1085
1107
if self .null_frame_regex .search (line ):
1086
1108
print ('warning: thread parser ignored null-frame: "%s"' % line )
1087
- return
1109
+ return False
1088
1110
frame_match = self .frame_regex .search (line )
1089
1111
if not frame_match :
1090
1112
print ('error: frame regex failed for line: "%s"' % line )
1091
- return
1113
+ return False
1092
1114
1093
1115
frame_id = (
1094
1116
frame_img_name
@@ -1155,6 +1177,8 @@ def parse_thread(self, line):
1155
1177
self .crashlog .Frame (int (frame_id ), int (frame_addr , 0 ), description )
1156
1178
)
1157
1179
1180
+ return True
1181
+
1158
1182
def parse_images (self , line ):
1159
1183
image_match = self .image_regex_uuid .search (line )
1160
1184
if image_match :
@@ -1174,7 +1198,7 @@ def parse_images(self, line):
1174
1198
img_version .strip () if img_version else "" ,
1175
1199
uuid .UUID (img_uuid ),
1176
1200
img_path ,
1177
- self .verbose ,
1201
+ self .options . verbose ,
1178
1202
)
1179
1203
unqualified_img_name = os .path .basename (img_path )
1180
1204
if unqualified_img_name in self .symbols :
@@ -1188,17 +1212,22 @@ def parse_images(self, line):
1188
1212
1189
1213
self .images .append (image )
1190
1214
self .crashlog .images .append (image )
1215
+ return True
1191
1216
else :
1192
- print ("error: image regex failed for: %s" % line )
1217
+ if self .options .debug :
1218
+ print ("error: image regex failed for: %s" % line )
1219
+ return False
1193
1220
1194
1221
def parse_thread_registers (self , line ):
1195
1222
# "r12: 0x00007fff6b5939c8 r13: 0x0000000007000006 r14: 0x0000000000002a03 r15: 0x0000000000000c00"
1196
1223
reg_values = re .findall ("([a-z0-9]+): (0x[0-9a-f]+)" , line , re .I )
1197
1224
for reg , value in reg_values :
1198
1225
self .thread .registers [reg ] = int (value , 16 )
1226
+ return len (reg_values ) != 0
1199
1227
1200
1228
def parse_system (self , line ):
1201
1229
self .crashlog .system_profile .append (line )
1230
+ return True
1202
1231
1203
1232
def parse_instructions (self , line ):
1204
1233
pass
@@ -1412,7 +1441,7 @@ def add_module(image, target, obj_dir):
1412
1441
1413
1442
1414
1443
def load_crashlog_in_scripted_process (debugger , crashlog_path , options , result ):
1415
- crashlog = CrashLogParser .create (debugger , crashlog_path , False ).parse ()
1444
+ crashlog = CrashLogParser .create (debugger , crashlog_path , options ).parse ()
1416
1445
1417
1446
target = lldb .SBTarget ()
1418
1447
# 1. Try to use the user-provided target
@@ -1735,7 +1764,7 @@ def should_run_in_interactive_mode(options, ci):
1735
1764
result .SetError (str (e ))
1736
1765
else :
1737
1766
crash_log = CrashLogParser .create (
1738
- debugger , crashlog_path , options . verbose
1767
+ debugger , crashlog_path , options
1739
1768
).parse ()
1740
1769
SymbolicateCrashLog (crash_log , options )
1741
1770
0 commit comments