Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 import re | |
| 6 | |
| 7 from crash.type_enums import CallStackFormatType | |
| 8 from crash.type_enums import LanguageType | |
| 9 from crash.type_enums import SanitizerType | |
| 10 | |
| 11 | |
| 12 class CallStackDetector(object): | |
| 13 """Detector to detect the start of a CallStack.""" | |
|
wrengr
2016/12/22 23:28:36
"detector to detect" is awkward. Try something lik
Sharu Jiang
2016/12/28 20:16:46
good point. Done.
| |
| 14 | |
| 15 def IsStartOfNewCallStack(self, line, flags=None): | |
| 16 """Determines whether a line is the start of a new callstack or not. | |
| 17 | |
| 18 Args: | |
| 19 line (str): The line to be checked whether it is a start of new callstack | |
|
wrengr
2016/12/22 23:28:36
I'd drop the "whether..." part.
If retained, then
Sharu Jiang
2016/12/28 20:16:46
Done.
| |
| 20 or not. | |
| 21 flags (FlagManager): flag manager to manage flags needed to determine | |
|
wrengr
2016/12/22 23:28:35
"flag manager to manage flags" is awkward. Just sa
Sharu Jiang
2016/12/28 20:16:46
Done.
| |
| 22 whether a line is the start of a new callstack. | |
| 23 | |
| 24 Returns: | |
| 25 A tuple - | |
| 26 (is_new_callstack, priority, format_type, language_type, metadata) | |
|
wrengr
2016/12/22 23:28:36
It'd help clarify things to break this out as a na
Sharu Jiang
2016/12/28 20:16:46
Added a todo.
| |
| 27 is_new_callstack (bool): Boolean indicating whether this is the start of | |
| 28 a new callstack. | |
| 29 priority (int): Priority of a callstack. | |
| 30 format_type (CallStackFormatType): Format type of new callstack. | |
|
wrengr
2016/12/22 23:28:35
-> "the format of the new callstack (or None if th
Sharu Jiang
2016/12/28 20:16:46
Done.
| |
| 31 language_type (LanguageType): Language type of new callstack. | |
|
wrengr
2016/12/22 23:28:35
-> "the language of the new callstack (or None if
Sharu Jiang
2016/12/28 20:16:46
Done.
| |
| 32 metadata (dict): Dict of metadata of new callstack, | |
|
wrengr
2016/12/22 23:28:35
"metadata of" -> "metadata for the"
Sharu Jiang
2016/12/28 20:16:46
Done.
| |
| 33 e.g. pid, top_frame_has_no_symbols. | |
| 34 """ | |
| 35 raise NotImplementedError() | |
| 36 | |
| 37 | |
| 38 class AndroidJobDetector(CallStackDetector): | |
| 39 """Detects the start of an android job callstack.""" | |
| 40 JAVA_LANG_CALLSTACK_START_PATTERN = r'^java\.[A-Za-z0-9$._]+' | |
| 41 JAVA_ORG_GHROMIUM_CALLSTACK_START_PATTERN = r'^org\.chromium\.[A-Za-z0-9$._]+' | |
| 42 JAVA_CAUSED_BY_CALLSTACK_START_PATTERN = r'^Caused by:' | |
| 43 JAVA_ANDROID_CALLSTACK_START_PATTERN = ( | |
| 44 r'^(com\.google\.)?android\.[A-Za-z0-9$._]+') | |
| 45 | |
| 46 JAVA_CALLSTACK_START_REGEX = re.compile( | |
| 47 '|'.join([JAVA_LANG_CALLSTACK_START_PATTERN, | |
| 48 JAVA_ORG_GHROMIUM_CALLSTACK_START_PATTERN, | |
| 49 JAVA_CAUSED_BY_CALLSTACK_START_PATTERN, | |
| 50 JAVA_ANDROID_CALLSTACK_START_PATTERN])) | |
| 51 | |
| 52 def IsStartOfNewCallStack(self, line, flags=None): | |
| 53 if AndroidJobDetector.JAVA_CALLSTACK_START_REGEX.match(line): | |
| 54 # Only assign the highest priority to fatal exception stack or segv | |
| 55 # stack. | |
| 56 if flags and flags.Get('java_main_stack_flag'): | |
| 57 flags.Set('java_main_stack_flag', False) | |
| 58 return True, 0, CallStackFormatType.JAVA, LanguageType.JAVA, {} | |
| 59 | |
| 60 return True, 1, CallStackFormatType.JAVA, LanguageType.JAVA, {} | |
| 61 | |
| 62 return False, None, None, None, None | |
| 63 | |
| 64 | |
| 65 class SyzyasanDetector(CallStackDetector): | |
| 66 """Detects the start of a syzyasn callstack.""" | |
| 67 SYZYASAN_CRASH_CALLSTACK_START_REGEX = re.compile(r'^Crash stack:$') | |
| 68 SYZYASAN_NON_CRASH_CALLSTACK_START_REGEX = re.compile(r'^(?!Crash).* stack:$') | |
| 69 | |
| 70 def IsStartOfNewCallStack(self, line, flags=None): | |
| 71 # In syzyasan build, new stack starts with 'crash stack:', | |
| 72 # 'freed stack:', etc. | |
| 73 if SyzyasanDetector.SYZYASAN_CRASH_CALLSTACK_START_REGEX.match(line): | |
| 74 return True, 0, CallStackFormatType.SYZYASAN, LanguageType.CPP, {} | |
| 75 # Other callstacks all get priority 1. | |
| 76 if SyzyasanDetector.SYZYASAN_NON_CRASH_CALLSTACK_START_REGEX.match(line): | |
| 77 return True, 1, CallStackFormatType.SYZYASAN, LanguageType.CPP, {} | |
| 78 | |
| 79 return False, None, None, None, None | |
| 80 | |
| 81 | |
| 82 class TsanDetector(CallStackDetector): | |
| 83 """Detects the start of a thread sanitizer callstack.""" | |
| 84 TSAN_CRASH_CALLSTACK_START_PATTERN1 = r'^(Read|Write) of size \d+' | |
| 85 TSAN_CRASH_CALLSTACK_START_PATTERN2 = r'^[A-Z]+: ThreadSanitizer' | |
| 86 TSAN_ALLOCATION_CALLSTACK_START_PATTERN = ( | |
| 87 r'^Previous (write|read) of size \d+') | |
| 88 TSAN_LOCATION_CALLSTACK_START_PATTERN = ( | |
| 89 r'^Location is heap block of size \d+') | |
| 90 | |
| 91 TSAN_CRASH_CALLSTACK_START_REGEX = re.compile( | |
| 92 '|'.join([TSAN_CRASH_CALLSTACK_START_PATTERN1, | |
| 93 TSAN_CRASH_CALLSTACK_START_PATTERN2])) | |
| 94 | |
| 95 TSAN_NON_CRASH_CALLSTACK_START_REGEX = re.compile( | |
| 96 '|'.join([TSAN_ALLOCATION_CALLSTACK_START_PATTERN, | |
| 97 TSAN_LOCATION_CALLSTACK_START_PATTERN])) | |
| 98 | |
| 99 def IsStartOfNewCallStack(self, line, flags=None): | |
| 100 # Crash stack gets priority 0. | |
| 101 if TsanDetector.TSAN_CRASH_CALLSTACK_START_REGEX.match(line): | |
| 102 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {} | |
| 103 | |
| 104 # All other stacks get priority 1. | |
| 105 if TsanDetector.TSAN_NON_CRASH_CALLSTACK_START_REGEX.match(line): | |
| 106 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, {} | |
| 107 | |
| 108 return False, None, None, None, None | |
| 109 | |
| 110 | |
| 111 class UbsanDetector(CallStackDetector): | |
| 112 """Detects the start of a ubsan callstack.""" | |
|
wrengr
2016/12/22 23:28:36
"a ubsan" -> "an undefined-behavior sanitizer"
Sharu Jiang
2016/12/28 20:16:46
Done.
| |
| 113 UBSAN_CALLSTACK_START_REGEX = re.compile(r'^.*: runtime error: .*$') | |
| 114 | |
| 115 def IsStartOfNewCallStack(self, line, flags=None): | |
| 116 if UbsanDetector.UBSAN_CALLSTACK_START_REGEX.match(line): | |
| 117 if flags and flags.Get('is_first_stack_flag'): | |
| 118 flags.Set('is_first_stack_flag', False) | |
| 119 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {} | |
| 120 | |
| 121 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, {} | |
| 122 | |
| 123 return False, None, None, None, None | |
| 124 | |
| 125 | |
| 126 class MsanDetector(CallStackDetector): | |
| 127 """Detects the start of a memory sanitizer callstack.""" | |
| 128 MSAN_CALLSTACK_START_REGEX = re.compile(r'^==(\d+)== ?([A-Z]+:|\w+Sanitizer)') | |
| 129 MSAN_CREATION_CALLSTACK_START_MARKER = 'Uninitialized value was created by' | |
| 130 MSAN_STORAGE_CALLSTACK_START_MARKER = 'Uninitialized value was stored to' | |
| 131 | |
| 132 def IsStartOfNewCallStack(self, line, flags=None): | |
| 133 # Assign the only msan stack priority 0. | |
| 134 if MsanDetector.MSAN_CREATION_CALLSTACK_START_MARKER in line: | |
| 135 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {} | |
| 136 if MsanDetector.MSAN_STORAGE_CALLSTACK_START_MARKER in line: | |
| 137 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, {} | |
| 138 msan_callstack_start_regex = ( | |
| 139 MsanDetector.MSAN_CALLSTACK_START_REGEX.match(line)) | |
| 140 if msan_callstack_start_regex: | |
| 141 return (True, 2, CallStackFormatType.DEFAULT, LanguageType.CPP, | |
| 142 {'pid': int(msan_callstack_start_regex.group(1).strip())}) | |
| 143 | |
| 144 return False, None, None, None, None | |
| 145 | |
| 146 | |
| 147 class AsanDetector(CallStackDetector): | |
| 148 """Detects the start of an address sanitizer callstack.""" | |
| 149 ASAN_CRASH_CALLSTACK_START_REGEX1 = re.compile( | |
| 150 r'^==(\d+)== ?([A-Z]+:|\w+Sanitizer)') | |
| 151 ASAN_CRASH_CALLSTACK_START_REGEX2 = re.compile( | |
| 152 r'^(READ|WRITE) of size \d+ at|^backtrace:') | |
| 153 | |
| 154 ASAN_FREED_CALLSTACK_START_PATTERN = ( | |
| 155 r'^freed by thread T\d+ (.* )?here:') | |
| 156 ASAN_ALLOCATION_CALLSTACK_START_PATTERN = ( | |
| 157 r'^(previously )?allocated by thread T\d+ (.* )?here:') | |
| 158 ASAN_OTHER_CALLSTACK_START_PATTERN = ( | |
| 159 r'^Thread T\d+ (.* )?created by') | |
| 160 | |
| 161 ASAN_NON_CRASH_CALLSTACK_START_PATTERN = re.compile( | |
| 162 '|'.join([ASAN_FREED_CALLSTACK_START_PATTERN, | |
| 163 ASAN_ALLOCATION_CALLSTACK_START_PATTERN, | |
| 164 ASAN_OTHER_CALLSTACK_START_PATTERN])) | |
| 165 | |
| 166 def IsStartOfNewCallStack(self, line, flags=None): | |
| 167 metadata = {} | |
| 168 asan_crash_callstack_start_regex1_match = ( | |
| 169 AsanDetector.ASAN_CRASH_CALLSTACK_START_REGEX1.match(line)) | |
| 170 if asan_crash_callstack_start_regex1_match: | |
| 171 metadata['pid'] = int( | |
| 172 asan_crash_callstack_start_regex1_match.group(1).strip()) | |
|
wrengr
2016/12/22 23:28:36
I think it'd be clearer to return (True, 0, DEFAUL
Sharu Jiang
2016/12/28 20:16:46
Done.
| |
| 173 # Crash stack gets priority 0. | |
| 174 if (asan_crash_callstack_start_regex1_match or | |
| 175 AsanDetector.ASAN_CRASH_CALLSTACK_START_REGEX2.match(line)): | |
| 176 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, metadata | |
| 177 | |
| 178 # All other callstack gets priority 1. | |
| 179 if AsanDetector.ASAN_NON_CRASH_CALLSTACK_START_PATTERN.match(line): | |
| 180 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, metadata | |
| 181 | |
| 182 return False, None, None, None, None | |
| 183 | |
| 184 | |
| 185 class ChromeCrashStackDetector(CallStackDetector): | |
| 186 """Detects the start of an chromecrash(Fracas/Cracas) callstack.""" | |
| 187 CHROME_CRASH_CALLSTACK_START_REGEX = re.compile(r'CRASHED \[(.*) @ 0x(.*)\]') | |
| 188 JAVA_CALLSTACK_START_REGEX = re.compile(r'\(JAVA\) CRASHED \[(.*) @ 0x(.*)\]') | |
| 189 | |
| 190 def IsStartOfNewCallStack(self, line, flags=None): | |
| 191 if ChromeCrashStackDetector.CHROME_CRASH_CALLSTACK_START_REGEX.match(line): | |
| 192 # Fracas only provide magic signature stack (crash stack). | |
| 193 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {} | |
| 194 | |
| 195 if ChromeCrashStackDetector.JAVA_CALLSTACK_START_REGEX.match(line): | |
| 196 return True, 0, CallStackFormatType.DEFAULT, LanguageType.JAVA, {} | |
| 197 | |
| 198 return False, None, None, None, None | |
| OLD | NEW |