Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(490)

Side by Side Diff: appengine/findit/crash/callstack_detectors.py

Issue 2607813002: [Predator] Make ``CallStackDetector`` return a namedtuple. (Closed)
Patch Set: Fix nit. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2016 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 from collections import namedtuple
5 import re 6 import re
6 7
7 from crash.type_enums import CallStackFormatType 8 from crash.type_enums import CallStackFormatType
8 from crash.type_enums import LanguageType 9 from crash.type_enums import LanguageType
9 from crash.type_enums import SanitizerType 10 from crash.type_enums import SanitizerType
10 11
11 12
13 class StartOfCallStack(
14 namedtuple('StartOfCallStack',
wrengr 2016/12/29 20:13:02 I'd put this on the previous line, to match the st
Sharu Jiang 2016/12/29 21:40:14 Actually that's a wrong indentation. Didn't notice
15 ['priority', 'format_type', 'language_type', 'metadata'])):
16 """Represents the start of a new callstack.
17
wrengr 2016/12/29 20:13:02 Shouldn't there be a header word here? like "Prope
Sharu Jiang 2016/12/29 21:40:14 Done.
18 priority (int): Priority of the new callstack.
19 format_type (CallStackFormatType): The format of the new callstack.
20 language_type (LanguageType): The language of the new callstack.
21 metadata (dict): Dict of metadata for the new callstack, e.g. pid of the
22 stack.
23 """
24 __slots__ = ()
25
wrengr 2016/12/29 20:13:02 Maybe add a __new__ constructor, so that the metat
Sharu Jiang 2016/12/29 21:40:14 Done.
26 def __str__(self): # pragma: no cover
27 return ('StartOfCallStack(priority = %d, format_type = %d, '
wrengr 2016/12/29 20:13:02 Use '%s' and self.__class__.__name__ instead of re
Sharu Jiang 2016/12/29 21:40:14 Done.
28 'language_type = %d, metadata = %s)' % (self.priority,
29 self.format_type,
30 self.language_type,
31 self.metadata))
32
33
12 class CallStackDetector(object): 34 class CallStackDetector(object):
13 """Class for detecting the start of a particular sort of CallStack.""" 35 """Class for detecting the start of a particular sort of CallStack."""
14 36
15 # TODO(crbug.com/677321) Make the return to be a namedtuple. 37 # TODO(crbug.com/677321) Make the return to be a namedtuple.
wrengr 2016/12/29 20:13:02 the todo is redundant now
Sharu Jiang 2016/12/29 21:40:14 Oops, should have cleaned this.
16 def IsStartOfNewCallStack(self, line, flags=None): 38 def __call__(self, line, flags=None):
wrengr 2016/12/29 20:13:02 +1 to using __call__ :)
17 """Determines whether a line is the start of a new callstack or not. 39 """Determines whether a line is the start of a new callstack or not.
18 40
19 Args: 41 Args:
20 line (str): The line to be checked. 42 line (str): The line to be checked.
21 flags (FlagManager): manager for keeping track of parsing flags. 43 flags (FlagManager): manager for keeping track of parsing flags.
22 44
23 Returns: 45 Returns:
24 A tuple - 46 A ``StartOfCallStack`` or None if no callstack found.
25 (is_new_callstack, priority, format_type, language_type, metadata)
26 is_new_callstack (bool): Boolean indicating whether this is the start of
27 a new callstack.
28 priority (int): Priority of a callstack.
29 format_type (CallStackFormatType): The format of the new callstack, or
30 None if there is no new callstack.
31 language_type (LanguageType): The language of the new callstack, or None
32 if there is no new callstack.
33 metadata (dict): Dict of metadata for the new callstack, e.g. pid of
34 the stack.
35 """ 47 """
36 raise NotImplementedError() 48 raise NotImplementedError()
37 49
38 50
39 class AndroidJobDetector(CallStackDetector): 51 class AndroidJobDetector(CallStackDetector):
40 """Detects the start of an android job callstack.""" 52 """Detects the start of an android job callstack."""
41 JAVA_LANG_CALLSTACK_START_PATTERN = r'^java\.[A-Za-z0-9$._]+' 53 JAVA_LANG_CALLSTACK_START_PATTERN = r'^java\.[A-Za-z0-9$._]+'
42 JAVA_ORG_GHROMIUM_CALLSTACK_START_PATTERN = r'^org\.chromium\.[A-Za-z0-9$._]+' 54 JAVA_ORG_GHROMIUM_CALLSTACK_START_PATTERN = r'^org\.chromium\.[A-Za-z0-9$._]+'
43 JAVA_CAUSED_BY_CALLSTACK_START_PATTERN = r'^Caused by:' 55 JAVA_CAUSED_BY_CALLSTACK_START_PATTERN = r'^Caused by:'
44 JAVA_ANDROID_CALLSTACK_START_PATTERN = ( 56 JAVA_ANDROID_CALLSTACK_START_PATTERN = (
45 r'^(com\.google\.)?android\.[A-Za-z0-9$._]+') 57 r'^(com\.google\.)?android\.[A-Za-z0-9$._]+')
46 58
47 JAVA_CALLSTACK_START_REGEX = re.compile( 59 JAVA_CALLSTACK_START_REGEX = re.compile(
48 '|'.join([JAVA_LANG_CALLSTACK_START_PATTERN, 60 '|'.join([JAVA_LANG_CALLSTACK_START_PATTERN,
49 JAVA_ORG_GHROMIUM_CALLSTACK_START_PATTERN, 61 JAVA_ORG_GHROMIUM_CALLSTACK_START_PATTERN,
50 JAVA_CAUSED_BY_CALLSTACK_START_PATTERN, 62 JAVA_CAUSED_BY_CALLSTACK_START_PATTERN,
51 JAVA_ANDROID_CALLSTACK_START_PATTERN])) 63 JAVA_ANDROID_CALLSTACK_START_PATTERN]))
52 64
53 def IsStartOfNewCallStack(self, line, flags=None): 65 def __call__(self, line, flags=None):
54 if AndroidJobDetector.JAVA_CALLSTACK_START_REGEX.match(line): 66 if AndroidJobDetector.JAVA_CALLSTACK_START_REGEX.match(line):
55 # Only assign the highest priority to fatal exception stack or segv 67 # Only assign the highest priority to fatal exception stack or segv
56 # stack. 68 # stack.
57 if flags and flags.Get('java_main_stack_flag'): 69 if flags and flags.Get('java_main_stack_flag'):
58 flags.TurnOff('java_main_stack_flag') 70 flags.TurnOff('java_main_stack_flag')
59 return True, 0, CallStackFormatType.JAVA, LanguageType.JAVA, {} 71 return StartOfCallStack(0, CallStackFormatType.JAVA,
72 LanguageType.JAVA, {})
60 73
61 return True, 1, CallStackFormatType.JAVA, LanguageType.JAVA, {} 74 return StartOfCallStack(1, CallStackFormatType.JAVA,
75 LanguageType.JAVA, {})
62 76
63 return False, None, None, None, None 77 return None
64 78
65 79
66 class SyzyasanDetector(CallStackDetector): 80 class SyzyasanDetector(CallStackDetector):
67 """Detects the start of a syzyasn callstack.""" 81 """Detects the start of a syzyasn callstack."""
68 SYZYASAN_CRASH_CALLSTACK_START_REGEX = re.compile(r'^Crash stack:$') 82 SYZYASAN_CRASH_CALLSTACK_START_REGEX = re.compile(r'^Crash stack:$')
69 SYZYASAN_NON_CRASH_CALLSTACK_START_REGEX = re.compile(r'^(?!Crash).* stack:$') 83 SYZYASAN_NON_CRASH_CALLSTACK_START_REGEX = re.compile(r'^(?!Crash).* stack:$')
70 84
71 def IsStartOfNewCallStack(self, line, flags=None): 85 def __call__(self, line, flags=None):
72 # In syzyasan build, new stack starts with 'crash stack:', 86 # In syzyasan build, new stack starts with 'crash stack:',
73 # 'freed stack:', etc. 87 # 'freed stack:', etc.
74 if SyzyasanDetector.SYZYASAN_CRASH_CALLSTACK_START_REGEX.match(line): 88 if SyzyasanDetector.SYZYASAN_CRASH_CALLSTACK_START_REGEX.match(line):
75 return True, 0, CallStackFormatType.SYZYASAN, LanguageType.CPP, {} 89 return StartOfCallStack(0, CallStackFormatType.SYZYASAN,
90 LanguageType.CPP, {})
76 # Other callstacks all get priority 1. 91 # Other callstacks all get priority 1.
77 if SyzyasanDetector.SYZYASAN_NON_CRASH_CALLSTACK_START_REGEX.match(line): 92 if SyzyasanDetector.SYZYASAN_NON_CRASH_CALLSTACK_START_REGEX.match(line):
78 return True, 1, CallStackFormatType.SYZYASAN, LanguageType.CPP, {} 93 return StartOfCallStack(1, CallStackFormatType.SYZYASAN,
94 LanguageType.CPP, {})
79 95
80 return False, None, None, None, None 96 return None
81 97
82 98
83 class TsanDetector(CallStackDetector): 99 class TsanDetector(CallStackDetector):
84 """Detects the start of a thread sanitizer callstack.""" 100 """Detects the start of a thread sanitizer callstack."""
85 TSAN_CRASH_CALLSTACK_START_PATTERN1 = r'^(Read|Write) of size \d+' 101 TSAN_CRASH_CALLSTACK_START_PATTERN1 = r'^(Read|Write) of size \d+'
86 TSAN_CRASH_CALLSTACK_START_PATTERN2 = r'^[A-Z]+: ThreadSanitizer' 102 TSAN_CRASH_CALLSTACK_START_PATTERN2 = r'^[A-Z]+: ThreadSanitizer'
87 TSAN_ALLOCATION_CALLSTACK_START_PATTERN = ( 103 TSAN_ALLOCATION_CALLSTACK_START_PATTERN = (
88 r'^Previous (write|read) of size \d+') 104 r'^Previous (write|read) of size \d+')
89 TSAN_LOCATION_CALLSTACK_START_PATTERN = ( 105 TSAN_LOCATION_CALLSTACK_START_PATTERN = (
90 r'^Location is heap block of size \d+') 106 r'^Location is heap block of size \d+')
91 107
92 TSAN_CRASH_CALLSTACK_START_REGEX = re.compile( 108 TSAN_CRASH_CALLSTACK_START_REGEX = re.compile(
93 '|'.join([TSAN_CRASH_CALLSTACK_START_PATTERN1, 109 '|'.join([TSAN_CRASH_CALLSTACK_START_PATTERN1,
94 TSAN_CRASH_CALLSTACK_START_PATTERN2])) 110 TSAN_CRASH_CALLSTACK_START_PATTERN2]))
95 111
96 TSAN_NON_CRASH_CALLSTACK_START_REGEX = re.compile( 112 TSAN_NON_CRASH_CALLSTACK_START_REGEX = re.compile(
97 '|'.join([TSAN_ALLOCATION_CALLSTACK_START_PATTERN, 113 '|'.join([TSAN_ALLOCATION_CALLSTACK_START_PATTERN,
98 TSAN_LOCATION_CALLSTACK_START_PATTERN])) 114 TSAN_LOCATION_CALLSTACK_START_PATTERN]))
99 115
100 def IsStartOfNewCallStack(self, line, flags=None): 116 def __call__(self, line, flags=None):
101 # Crash stack gets priority 0. 117 # Crash stack gets priority 0.
102 if TsanDetector.TSAN_CRASH_CALLSTACK_START_REGEX.match(line): 118 if TsanDetector.TSAN_CRASH_CALLSTACK_START_REGEX.match(line):
103 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {} 119 return StartOfCallStack(0, CallStackFormatType.DEFAULT,
120 LanguageType.CPP, {})
104 121
105 # All other stacks get priority 1. 122 # All other stacks get priority 1.
106 if TsanDetector.TSAN_NON_CRASH_CALLSTACK_START_REGEX.match(line): 123 if TsanDetector.TSAN_NON_CRASH_CALLSTACK_START_REGEX.match(line):
107 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, {} 124 return StartOfCallStack(1, CallStackFormatType.DEFAULT,
125 LanguageType.CPP, {})
108 126
109 return False, None, None, None, None 127 return None
110 128
111 129
112 class UbsanDetector(CallStackDetector): 130 class UbsanDetector(CallStackDetector):
113 """Detects the start of an undefined-behavior callstack.""" 131 """Detects the start of an undefined-behavior callstack."""
114 UBSAN_CALLSTACK_START_REGEX = re.compile(r'^.*: runtime error: .*$') 132 UBSAN_CALLSTACK_START_REGEX = re.compile(r'^.*: runtime error: .*$')
115 133
116 def IsStartOfNewCallStack(self, line, flags=None): 134 def __call__(self, line, flags=None):
117 if UbsanDetector.UBSAN_CALLSTACK_START_REGEX.match(line): 135 if UbsanDetector.UBSAN_CALLSTACK_START_REGEX.match(line):
118 if flags and flags.Get('is_first_stack_flag'): 136 if flags and flags.Get('is_first_stack_flag'):
119 flags.TurnOff('is_first_stack_flag') 137 flags.TurnOff('is_first_stack_flag')
120 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {} 138 return StartOfCallStack(0, CallStackFormatType.DEFAULT,
139 LanguageType.CPP, {})
121 140
122 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, {} 141 return StartOfCallStack(1, CallStackFormatType.DEFAULT,
142 LanguageType.CPP, {})
123 143
124 return False, None, None, None, None 144 return None
125 145
126 146
127 class MsanDetector(CallStackDetector): 147 class MsanDetector(CallStackDetector):
128 """Detects the start of a memory sanitizer callstack.""" 148 """Detects the start of a memory sanitizer callstack."""
129 MSAN_CALLSTACK_START_REGEX = re.compile(r'^==(\d+)== ?([A-Z]+:|\w+Sanitizer)') 149 MSAN_CALLSTACK_START_REGEX = re.compile(r'^==(\d+)== ?([A-Z]+:|\w+Sanitizer)')
130 MSAN_CREATION_CALLSTACK_START_MARKER = 'Uninitialized value was created by' 150 MSAN_CREATION_CALLSTACK_START_MARKER = 'Uninitialized value was created by'
131 MSAN_STORAGE_CALLSTACK_START_MARKER = 'Uninitialized value was stored to' 151 MSAN_STORAGE_CALLSTACK_START_MARKER = 'Uninitialized value was stored to'
132 152
133 def IsStartOfNewCallStack(self, line, flags=None): 153 def __call__(self, line, flags=None):
134 # Assign the only msan stack priority 0. 154 # Assign the only msan stack priority 0.
135 if MsanDetector.MSAN_CREATION_CALLSTACK_START_MARKER in line: 155 if MsanDetector.MSAN_CREATION_CALLSTACK_START_MARKER in line:
136 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {} 156 return StartOfCallStack(0, CallStackFormatType.DEFAULT,
157 LanguageType.CPP, {})
137 if MsanDetector.MSAN_STORAGE_CALLSTACK_START_MARKER in line: 158 if MsanDetector.MSAN_STORAGE_CALLSTACK_START_MARKER in line:
138 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, {} 159 return StartOfCallStack(1, CallStackFormatType.DEFAULT,
160 LanguageType.CPP, {})
139 msan_callstack_start_regex = ( 161 msan_callstack_start_regex = (
140 MsanDetector.MSAN_CALLSTACK_START_REGEX.match(line)) 162 MsanDetector.MSAN_CALLSTACK_START_REGEX.match(line))
141 if msan_callstack_start_regex: 163 if msan_callstack_start_regex:
142 return (True, 2, CallStackFormatType.DEFAULT, LanguageType.CPP, 164 return StartOfCallStack(
143 {'pid': int(msan_callstack_start_regex.group(1).strip())}) 165 2, CallStackFormatType.DEFAULT, LanguageType.CPP,
166 {'pid': int(msan_callstack_start_regex.group(1).strip())})
144 167
145 return False, None, None, None, None 168 return None
146 169
147 170
148 class AsanDetector(CallStackDetector): 171 class AsanDetector(CallStackDetector):
149 """Detects the start of an address sanitizer callstack.""" 172 """Detects the start of an address sanitizer callstack."""
150 ASAN_CRASH_CALLSTACK_START_REGEX1 = re.compile( 173 ASAN_CRASH_CALLSTACK_START_REGEX1 = re.compile(
151 r'^==(\d+)== ?([A-Z]+:|\w+Sanitizer)') 174 r'^==(\d+)== ?([A-Z]+:|\w+Sanitizer)')
152 ASAN_CRASH_CALLSTACK_START_REGEX2 = re.compile( 175 ASAN_CRASH_CALLSTACK_START_REGEX2 = re.compile(
153 r'^(READ|WRITE) of size \d+ at|^backtrace:') 176 r'^(READ|WRITE) of size \d+ at|^backtrace:')
154 177
155 ASAN_FREED_CALLSTACK_START_PATTERN = ( 178 ASAN_FREED_CALLSTACK_START_PATTERN = (
156 r'^freed by thread T\d+ (.* )?here:') 179 r'^freed by thread T\d+ (.* )?here:')
157 ASAN_ALLOCATION_CALLSTACK_START_PATTERN = ( 180 ASAN_ALLOCATION_CALLSTACK_START_PATTERN = (
158 r'^(previously )?allocated by thread T\d+ (.* )?here:') 181 r'^(previously )?allocated by thread T\d+ (.* )?here:')
159 ASAN_OTHER_CALLSTACK_START_PATTERN = ( 182 ASAN_OTHER_CALLSTACK_START_PATTERN = (
160 r'^Thread T\d+ (.* )?created by') 183 r'^Thread T\d+ (.* )?created by')
161 184
162 ASAN_NON_CRASH_CALLSTACK_START_PATTERN = re.compile( 185 ASAN_NON_CRASH_CALLSTACK_START_PATTERN = re.compile(
163 '|'.join([ASAN_FREED_CALLSTACK_START_PATTERN, 186 '|'.join([ASAN_FREED_CALLSTACK_START_PATTERN,
164 ASAN_ALLOCATION_CALLSTACK_START_PATTERN, 187 ASAN_ALLOCATION_CALLSTACK_START_PATTERN,
165 ASAN_OTHER_CALLSTACK_START_PATTERN])) 188 ASAN_OTHER_CALLSTACK_START_PATTERN]))
166 189
167 def IsStartOfNewCallStack(self, line, flags=None): 190 def __call__(self, line, flags=None):
168 asan_crash_callstack_start_regex1_match = ( 191 asan_crash_callstack_start_regex1_match = (
169 AsanDetector.ASAN_CRASH_CALLSTACK_START_REGEX1.match(line)) 192 AsanDetector.ASAN_CRASH_CALLSTACK_START_REGEX1.match(line))
170 if asan_crash_callstack_start_regex1_match: 193 if asan_crash_callstack_start_regex1_match:
171 return (True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, 194 return StartOfCallStack(
172 {'pid': int( 195 0, CallStackFormatType.DEFAULT, LanguageType.CPP,
173 asan_crash_callstack_start_regex1_match.group(1).strip())}) 196 {'pid': int(
197 asan_crash_callstack_start_regex1_match.group(1).strip())})
174 198
175 # Crash stack gets priority 0. 199 # Crash stack gets priority 0.
176 if AsanDetector.ASAN_CRASH_CALLSTACK_START_REGEX2.match(line): 200 if AsanDetector.ASAN_CRASH_CALLSTACK_START_REGEX2.match(line):
177 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {} 201 return StartOfCallStack(0, CallStackFormatType.DEFAULT,
202 LanguageType.CPP, {})
178 203
179 # All other callstack gets priority 1. 204 # All other callstack gets priority 1.
180 if AsanDetector.ASAN_NON_CRASH_CALLSTACK_START_PATTERN.match(line): 205 if AsanDetector.ASAN_NON_CRASH_CALLSTACK_START_PATTERN.match(line):
181 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, {} 206 return StartOfCallStack(1, CallStackFormatType.DEFAULT,
207 LanguageType.CPP, {})
182 208
183 return False, None, None, None, None 209 return None
184 210
185 211
186 class ChromeCrashStackDetector(CallStackDetector): 212 class ChromeCrashStackDetector(CallStackDetector):
187 """Detects the start of an chromecrash(Fracas/Cracas) callstack.""" 213 """Detects the start of an chromecrash(Fracas/Cracas) callstack."""
188 CHROME_CRASH_CALLSTACK_START_REGEX = re.compile(r'CRASHED \[(.*) @ 0x(.*)\]') 214 CHROME_CRASH_CALLSTACK_START_REGEX = re.compile(r'CRASHED \[(.*) @ 0x(.*)\]')
189 JAVA_CALLSTACK_START_REGEX = re.compile(r'\(JAVA\) CRASHED \[(.*) @ 0x(.*)\]') 215 JAVA_CALLSTACK_START_REGEX = re.compile(r'\(JAVA\) CRASHED \[(.*) @ 0x(.*)\]')
190 216
191 def IsStartOfNewCallStack(self, line, flags=None): 217 def __call__(self, line, flags=None):
192 if ChromeCrashStackDetector.CHROME_CRASH_CALLSTACK_START_REGEX.match(line): 218 if ChromeCrashStackDetector.CHROME_CRASH_CALLSTACK_START_REGEX.match(line):
193 # Fracas only provide magic signature stack (crash stack). 219 # Fracas only provide magic signature stack (crash stack).
194 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {} 220 return StartOfCallStack(0, CallStackFormatType.DEFAULT,
221 LanguageType.CPP, {})
195 222
196 if ChromeCrashStackDetector.JAVA_CALLSTACK_START_REGEX.match(line): 223 if ChromeCrashStackDetector.JAVA_CALLSTACK_START_REGEX.match(line):
197 return True, 0, CallStackFormatType.DEFAULT, LanguageType.JAVA, {} 224 return StartOfCallStack(0, CallStackFormatType.DEFAULT,
225 LanguageType.JAVA, {})
198 226
199 return False, None, None, None, None 227 return None
OLDNEW
« no previous file with comments | « no previous file | appengine/findit/crash/chromecrash_parser.py » ('j') | appengine/findit/crash/chromecrash_parser.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698