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

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

Issue 2593593003: [Predator] Add Clusterfuzz stacktrace parser. (Closed)
Patch Set: Rebase and 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
« no previous file with comments | « no previous file | appengine/findit/crash/chromecrash_parser.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 """Class for detecting the start of a particular sort of CallStack."""
14
15 # TODO(crbug.com/677321) Make the return to be a namedtuple.
16 def IsStartOfNewCallStack(self, line, flags=None):
17 """Determines whether a line is the start of a new callstack or not.
18
19 Args:
20 line (str): The line to be checked.
21 flags (FlagManager): manager for keeping track of parsing flags.
22
23 Returns:
24 A tuple -
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 """
36 raise NotImplementedError()
37
38
39 class AndroidJobDetector(CallStackDetector):
40 """Detects the start of an android job callstack."""
41 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$._]+'
43 JAVA_CAUSED_BY_CALLSTACK_START_PATTERN = r'^Caused by:'
44 JAVA_ANDROID_CALLSTACK_START_PATTERN = (
45 r'^(com\.google\.)?android\.[A-Za-z0-9$._]+')
46
47 JAVA_CALLSTACK_START_REGEX = re.compile(
48 '|'.join([JAVA_LANG_CALLSTACK_START_PATTERN,
49 JAVA_ORG_GHROMIUM_CALLSTACK_START_PATTERN,
50 JAVA_CAUSED_BY_CALLSTACK_START_PATTERN,
51 JAVA_ANDROID_CALLSTACK_START_PATTERN]))
52
53 def IsStartOfNewCallStack(self, line, flags=None):
54 if AndroidJobDetector.JAVA_CALLSTACK_START_REGEX.match(line):
55 # Only assign the highest priority to fatal exception stack or segv
56 # stack.
57 if flags and flags.Get('java_main_stack_flag'):
58 flags.TurnOff('java_main_stack_flag')
59 return True, 0, CallStackFormatType.JAVA, LanguageType.JAVA, {}
60
61 return True, 1, CallStackFormatType.JAVA, LanguageType.JAVA, {}
62
63 return False, None, None, None, None
64
65
66 class SyzyasanDetector(CallStackDetector):
67 """Detects the start of a syzyasn callstack."""
68 SYZYASAN_CRASH_CALLSTACK_START_REGEX = re.compile(r'^Crash stack:$')
69 SYZYASAN_NON_CRASH_CALLSTACK_START_REGEX = re.compile(r'^(?!Crash).* stack:$')
70
71 def IsStartOfNewCallStack(self, line, flags=None):
72 # In syzyasan build, new stack starts with 'crash stack:',
73 # 'freed stack:', etc.
74 if SyzyasanDetector.SYZYASAN_CRASH_CALLSTACK_START_REGEX.match(line):
75 return True, 0, CallStackFormatType.SYZYASAN, LanguageType.CPP, {}
76 # Other callstacks all get priority 1.
77 if SyzyasanDetector.SYZYASAN_NON_CRASH_CALLSTACK_START_REGEX.match(line):
78 return True, 1, CallStackFormatType.SYZYASAN, LanguageType.CPP, {}
79
80 return False, None, None, None, None
81
82
83 class TsanDetector(CallStackDetector):
84 """Detects the start of a thread sanitizer callstack."""
85 TSAN_CRASH_CALLSTACK_START_PATTERN1 = r'^(Read|Write) of size \d+'
86 TSAN_CRASH_CALLSTACK_START_PATTERN2 = r'^[A-Z]+: ThreadSanitizer'
87 TSAN_ALLOCATION_CALLSTACK_START_PATTERN = (
88 r'^Previous (write|read) of size \d+')
89 TSAN_LOCATION_CALLSTACK_START_PATTERN = (
90 r'^Location is heap block of size \d+')
91
92 TSAN_CRASH_CALLSTACK_START_REGEX = re.compile(
93 '|'.join([TSAN_CRASH_CALLSTACK_START_PATTERN1,
94 TSAN_CRASH_CALLSTACK_START_PATTERN2]))
95
96 TSAN_NON_CRASH_CALLSTACK_START_REGEX = re.compile(
97 '|'.join([TSAN_ALLOCATION_CALLSTACK_START_PATTERN,
98 TSAN_LOCATION_CALLSTACK_START_PATTERN]))
99
100 def IsStartOfNewCallStack(self, line, flags=None):
101 # Crash stack gets priority 0.
102 if TsanDetector.TSAN_CRASH_CALLSTACK_START_REGEX.match(line):
103 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {}
104
105 # All other stacks get priority 1.
106 if TsanDetector.TSAN_NON_CRASH_CALLSTACK_START_REGEX.match(line):
107 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, {}
108
109 return False, None, None, None, None
110
111
112 class UbsanDetector(CallStackDetector):
113 """Detects the start of an undefined-behavior callstack."""
114 UBSAN_CALLSTACK_START_REGEX = re.compile(r'^.*: runtime error: .*$')
115
116 def IsStartOfNewCallStack(self, line, flags=None):
117 if UbsanDetector.UBSAN_CALLSTACK_START_REGEX.match(line):
118 if flags and flags.Get('is_first_stack_flag'):
119 flags.TurnOff('is_first_stack_flag')
120 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {}
121
122 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, {}
123
124 return False, None, None, None, None
125
126
127 class MsanDetector(CallStackDetector):
128 """Detects the start of a memory sanitizer callstack."""
129 MSAN_CALLSTACK_START_REGEX = re.compile(r'^==(\d+)== ?([A-Z]+:|\w+Sanitizer)')
130 MSAN_CREATION_CALLSTACK_START_MARKER = 'Uninitialized value was created by'
131 MSAN_STORAGE_CALLSTACK_START_MARKER = 'Uninitialized value was stored to'
132
133 def IsStartOfNewCallStack(self, line, flags=None):
134 # Assign the only msan stack priority 0.
135 if MsanDetector.MSAN_CREATION_CALLSTACK_START_MARKER in line:
136 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {}
137 if MsanDetector.MSAN_STORAGE_CALLSTACK_START_MARKER in line:
138 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, {}
139 msan_callstack_start_regex = (
140 MsanDetector.MSAN_CALLSTACK_START_REGEX.match(line))
141 if msan_callstack_start_regex:
142 return (True, 2, CallStackFormatType.DEFAULT, LanguageType.CPP,
143 {'pid': int(msan_callstack_start_regex.group(1).strip())})
144
145 return False, None, None, None, None
146
147
148 class AsanDetector(CallStackDetector):
149 """Detects the start of an address sanitizer callstack."""
150 ASAN_CRASH_CALLSTACK_START_REGEX1 = re.compile(
151 r'^==(\d+)== ?([A-Z]+:|\w+Sanitizer)')
152 ASAN_CRASH_CALLSTACK_START_REGEX2 = re.compile(
153 r'^(READ|WRITE) of size \d+ at|^backtrace:')
154
155 ASAN_FREED_CALLSTACK_START_PATTERN = (
156 r'^freed by thread T\d+ (.* )?here:')
157 ASAN_ALLOCATION_CALLSTACK_START_PATTERN = (
158 r'^(previously )?allocated by thread T\d+ (.* )?here:')
159 ASAN_OTHER_CALLSTACK_START_PATTERN = (
160 r'^Thread T\d+ (.* )?created by')
161
162 ASAN_NON_CRASH_CALLSTACK_START_PATTERN = re.compile(
163 '|'.join([ASAN_FREED_CALLSTACK_START_PATTERN,
164 ASAN_ALLOCATION_CALLSTACK_START_PATTERN,
165 ASAN_OTHER_CALLSTACK_START_PATTERN]))
166
167 def IsStartOfNewCallStack(self, line, flags=None):
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 return (True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP,
172 {'pid': int(
173 asan_crash_callstack_start_regex1_match.group(1).strip())})
174
175 # Crash stack gets priority 0.
176 if AsanDetector.ASAN_CRASH_CALLSTACK_START_REGEX2.match(line):
177 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {}
178
179 # All other callstack gets priority 1.
180 if AsanDetector.ASAN_NON_CRASH_CALLSTACK_START_PATTERN.match(line):
181 return True, 1, CallStackFormatType.DEFAULT, LanguageType.CPP, {}
182
183 return False, None, None, None, None
184
185
186 class ChromeCrashStackDetector(CallStackDetector):
187 """Detects the start of an chromecrash(Fracas/Cracas) callstack."""
188 CHROME_CRASH_CALLSTACK_START_REGEX = re.compile(r'CRASHED \[(.*) @ 0x(.*)\]')
189 JAVA_CALLSTACK_START_REGEX = re.compile(r'\(JAVA\) CRASHED \[(.*) @ 0x(.*)\]')
190
191 def IsStartOfNewCallStack(self, line, flags=None):
192 if ChromeCrashStackDetector.CHROME_CRASH_CALLSTACK_START_REGEX.match(line):
193 # Fracas only provide magic signature stack (crash stack).
194 return True, 0, CallStackFormatType.DEFAULT, LanguageType.CPP, {}
195
196 if ChromeCrashStackDetector.JAVA_CALLSTACK_START_REGEX.match(line):
197 return True, 0, CallStackFormatType.DEFAULT, LanguageType.JAVA, {}
198
199 return False, None, None, None, None
OLDNEW
« no previous file with comments | « no previous file | appengine/findit/crash/chromecrash_parser.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698