OLD | NEW |
---|---|
(Empty) | |
1 # Copyright (c) 2014 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 import os | |
5 import re | |
6 import findit_for_crash_utils as findit_utils | |
stgao
2014/07/31 01:52:24
How about adding a file crash_utils.py? And includ
jeun
2014/07/31 18:41:15
Done.
| |
7 | |
8 | |
9 class Stacktrace(object): | |
stgao
2014/07/31 01:52:24
Rename to |StacktraceInfo|? Because it contains mu
jeun
2014/07/31 18:41:14
I named it stacktrace because this object exists o
stgao
2014/07/31 19:48:58
Sound good.
In that case, the comment "Contains re
| |
10 """Represents Stacktrace object. | |
11 | |
12 Contains release build stacktrace and debug build stacktrace. | |
13 """ | |
14 | |
15 def __init__(self, stacktrace, chrome_build): | |
16 self.stack_list = [] | |
17 self.ParseStacktrace(stacktrace, chrome_build) | |
18 | |
19 def ParseStacktrace(self, stacktrace, chrome_build): | |
20 """Parses stacktrace and returns normalized stacktrace. | |
stgao
2014/07/31 01:52:24
We do not return anything within this function act
jeun
2014/07/31 18:41:15
Done.
| |
21 | |
22 If there are multiple stack frames within the stacktrace, | |
stgao
2014/07/31 01:52:24
What's the 'stack frame' here? Does it refer to a
jeun
2014/07/31 18:41:15
changed the description
| |
23 it will parse each frame separately. | |
24 | |
25 Args: | |
26 stacktrace: a string containing stacktrace | |
27 chrome_build: a string containing the job type of the crash | |
28 | |
29 Returns: | |
30 A stack dictionary, where key 'release' containing the result of parsing | |
31 release build stacktrace and 'debug' containing the result from debug | |
32 build stacktrace. Parsed result from each stacktrace contains a list | |
33 of parsed result for each stack within the stacktrace, where a | |
34 parsed result is a list of stacktraceline objects. | |
35 """ | |
36 # If the passed in string is empty, the object does not represent anything | |
37 if not stacktrace: | |
38 self.stack_list = None | |
39 return | |
40 | |
41 stack_frame_index_pattern = re.compile(r'#\d+') | |
42 | |
43 # Reset the stack list, and assume we start from main thread | |
stgao
2014/07/31 01:52:24
# Comments end with a period like this.
Please al
jeun
2014/07/31 18:41:15
Done.
| |
44 self.stack_list = [] | |
45 stack_priority = 0 | |
46 seen_zero = False | |
47 current_stack = CallStack(stack_priority) | |
48 | |
49 for line in stacktrace: | |
50 | |
51 # If this line does not represent the crashing information, continue | |
52 if not stack_frame_index_pattern.match(line): | |
53 continue | |
54 | |
55 # Get the frame index from the line | |
56 parts = line.split() | |
57 stack_frame_index = int(parts[0][1:]) | |
stgao
2014/07/31 01:52:25
Use regex to get the stack_frame_index instead of
jeun
2014/07/31 18:41:15
Done.
| |
58 | |
59 # If it is 0, we need to check if this is from freed or prev-alloc, or | |
60 # is from main thead | |
61 if stack_frame_index == 0: | |
62 | |
63 # If this frame is from main thread | |
stgao
2014/07/31 01:52:24
frame?
jeun
2014/07/31 18:41:15
Done.
| |
64 if not seen_zero: | |
stgao
2014/07/31 01:52:24
Could |seen_zero| be renamed to |seen_main_thread|
jeun
2014/07/31 18:41:15
Done.
| |
65 seen_zero = True | |
66 | |
67 # If this is from freed or prev-alloc, add the callstack we have | |
68 # to the list of callstacks, and increment the stack priority | |
69 else: | |
70 self.stack_list.append(current_stack) | |
71 stack_priority += 1 | |
72 current_stack = CallStack(stack_priority) | |
73 | |
74 # Parse function name, file path and line number from the line | |
75 parsed_stack_frame_line = self.ExtractFromStacktraceLine( | |
76 parts, chrome_build) | |
77 | |
78 # If the line is malformed, ignore this line. Else, get the info | |
79 if not parsed_stack_frame_line: | |
80 continue | |
81 (function, file_path, crashed_line) = parsed_stack_frame_line | |
82 | |
83 # Normalize the file path so that it can be compared to repository path | |
84 file_name = os.path.basename(file_path) | |
85 (component, file_path) = findit_utils.NormalizePathLinux(file_path) | |
86 | |
87 # Currently supports only blink and chromium | |
88 if component == 'blink' or component == 'chromium': | |
89 current_stack.Add( | |
90 StacktraceLine(stack_frame_index, component, file_name, | |
91 function, file_path, crashed_line)) | |
92 | |
93 self.stack_list.append(current_stack) | |
stgao
2014/07/31 01:52:24
I think different builds (asan, lsan, tsan, msan)
jeun
2014/07/31 18:41:14
I agree that something needs to be done about this
| |
94 | |
95 def ExtractFromStacktraceLine(self, parts, chrome_build): | |
96 """Extracts information from stacktrace. | |
stgao
2014/07/31 01:52:25
stacktrace seems misused here. Should be stack fra
jeun
2014/07/31 18:41:15
Done.
| |
97 | |
98 Args: | |
99 parts: a list, stacktrace.split() | |
100 chrome_build: a string containing the job type | |
101 of this crash (e.g. linux_asan_chrome_mp) | |
102 | |
103 Returns: | |
104 A triple containing the name of the function, the path of the file and | |
105 the line of crash | |
106 """ | |
107 try: | |
108 # tsan has different stack frame style from other builds | |
109 if chrome_build.startswith('linux_tsan'): | |
110 crash_component = parts[-2] | |
stgao
2014/07/31 01:52:24
The way we guess |crash_component| here is hacky.
jeun
2014/07/31 18:41:15
This is just a totally mis named variable. changed
| |
111 function = ' '.join(parts[1:-2]) | |
112 | |
113 else: | |
114 crash_component = parts[-1] | |
115 function = ' '.join(parts[3:-1]) | |
116 | |
117 # Get file path and line info from the line | |
118 file_and_line = crash_component.split(':') | |
119 file_path = file_and_line[0] | |
120 crashed_line = int(file_and_line[1]) | |
121 return (function, file_path, crashed_line) | |
122 | |
123 # Return None if the line is malformed | |
124 except IndexError: | |
125 return None | |
126 except ValueError: | |
127 return None | |
128 | |
129 def __getitem__(self, index): | |
130 return self.stack_list[index] | |
131 | |
132 def GetStackFromMainThread(self): | |
133 return self.stack_list[0] | |
134 | |
135 | |
136 class CallStack(object): | |
137 """Represents a call stack within a stacktrace. | |
138 | |
139 It is a list of stacktraceline object, and the stack represented by | |
140 this object is from main thread, freed thread or previously-allocated thread. | |
141 """ | |
142 | |
143 def __init__(self, stack_priority): | |
144 self.line_list = [] | |
stgao
2014/07/31 01:52:25
|line_list| -> |frames| or |frame_list|?
jeun
2014/07/31 18:41:15
Done.
| |
145 self.priority = stack_priority | |
146 | |
147 def Add(self, stacktrace_line): | |
148 self.line_list.append(stacktrace_line) | |
149 | |
150 def GetFirstN(self, n): | |
stgao
2014/07/31 01:52:24
check out of boundary?
jeun
2014/07/31 18:41:15
Python automatically checks for boundary when usin
| |
151 return self.line_list[:n] | |
152 | |
153 | |
154 class StacktraceLine(object): | |
155 """Represents a line in stacktrace. | |
stgao
2014/07/31 01:52:25
We refer this as stack frames. Maybe renaming it t
jeun
2014/07/31 18:41:15
Done.
| |
156 | |
157 Attributes: | |
158 stack_frame_index: index in the stacktrace | |
159 component: a component this line represents, such as blink, chrome, etc. | |
160 file_name: name of the file that crashed | |
stgao
2014/07/31 01:52:24
|file_name| could be derived from |file_path|. Cou
jeun
2014/07/31 18:41:15
Same as the comment in component_dictionary file.
| |
161 function: function that caused the crash | |
162 file_path: path of the crashed file | |
163 crashed_line: line of the file that caused the crash | |
stgao
2014/07/31 01:52:25
Will |line_number| be more clear?
jeun
2014/07/31 18:41:15
changed to crashed_line_number
| |
164 """ | |
165 | |
166 def __init__(self, stack_frame_index, component, file_name, | |
167 function, file_path, crashed_line): | |
168 self.stack_frame_index = stack_frame_index | |
169 self.component = component | |
170 self.file_name = file_name | |
171 self.function = function | |
172 self.file_path = file_path | |
173 self.crashed_line = crashed_line | |
OLD | NEW |