Index: tools/findit/component_dictionary.py |
diff --git a/tools/findit/component_dictionary.py b/tools/findit/component_dictionary.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..54275d994fd33359643b3e26a446736f7b29b94d |
--- /dev/null |
+++ b/tools/findit/component_dictionary.py |
@@ -0,0 +1,136 @@ |
+# Copyright (c) 2014 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+import os |
+ |
+ |
+class FileDictionary(object): |
+ """Maps file in a stacktrace to its crash information. |
+ |
+ It maps file to another dictionary, which maps the file's path to crashed |
+ lines, stack frame indices and crashed functions. |
+ """ |
+ |
+ def __init__(self): |
+ """Initializes the file dictionary.""" |
+ self.file_dict = {} |
+ |
+ def AddFile(self, file_name, file_path, crashed_line_number, |
+ stack_frame_index, function): |
+ """Adds file and its crash information to the map. |
+ |
+ Args: |
+ file_name: The name of the crashed file. |
+ file_path: The path of the crashed file. |
+ crashed_line_number: The crashed line of the file. |
+ stack_frame_index: The file's position in the callstack. |
+ function: The name of the crashed function. |
+ """ |
+ # Populate the dictionary if this file/path has not been added before. |
+ if file_name not in self.file_dict: |
+ self.file_dict[file_name] = {} |
+ |
+ if file_path not in self.file_dict[file_name]: |
+ self.file_dict[file_name][file_path] = {} |
+ self.file_dict[file_name][file_path]['line_numbers'] = [] |
+ self.file_dict[file_name][file_path]['stack_frame_indices'] = [] |
+ self.file_dict[file_name][file_path]['function'] = [] |
+ |
+ # Add the crashed line, frame index and function name. |
+ self.file_dict[file_name][file_path]['line_numbers'].append( |
+ crashed_line_number) |
+ self.file_dict[file_name][file_path]['stack_frame_indices'].append( |
+ stack_frame_index) |
+ self.file_dict[file_name][file_path]['function'].append(function) |
+ |
+ def GetPathDic(self, file_name): |
+ """Returns file's path and crash information.""" |
+ return self.file_dict[file_name] |
+ |
+ def GetCrashedLineNumbers(self, file_path): |
+ """Returns crashed line numbers given a file path.""" |
+ file_name = os.path.basename(file_path) |
+ return self.file_dict[file_name][file_path]['line_numbers'] |
+ |
+ def GetCrashStackFrameindex(self, file_path): |
+ """Returns stack frame indices given a file path.""" |
+ file_name = os.path.basename(file_path) |
+ return self.file_dict[file_name][file_path]['stack_frame_indices'] |
+ |
+ def GetCrashFunction(self, file_path): |
+ """Returns list of crashed functions given a file path.""" |
+ file_name = os.path.basename(file_path) |
+ return self.file_dict[file_name][file_path]['function'] |
+ |
+ def __iter__(self): |
+ return iter(self.file_dict) |
+ |
+ |
+class ComponentDictionary(object): |
+ """Represents a file dictionary. |
+ |
+ It maps each component path to a file dictionary. |
+ """ |
+ |
+ def __init__(self, callstack, components): |
+ """Initializes the dictionary with given components.""" |
+ self.component_dict = {} |
+ |
+ # Create file dictionary for all the components. |
+ for component in components: |
+ self.component_dict[component] = FileDictionary() |
+ |
+ # Create file dict from callstack. |
+ self.__CreateFileDictFromCallstack(callstack) |
+ |
+ def GetFileDict(self, component): |
+ """Returns a file dictionary for a given component.""" |
+ return self.component_dict.get(component) |
+ |
+ def __GenerateFileDict(self, stack_frame_list): |
+ """Generates file dictionary, given an instance of StackFrame list.""" |
+ # Iterate through the list of stackframe objects. |
+ for stack_frame in stack_frame_list: |
+ # If the component of this line is not in the list of components to |
+ # look for, ignore this line. |
+ component_path = stack_frame.component_path |
+ if component_path not in self.component_dict: |
+ continue |
+ |
+ # Get values of the variables |
+ file_name = stack_frame.file_name |
+ file_path = stack_frame.file_path |
+ crashed_line_number = stack_frame.crashed_line_number |
+ stack_frame_index = stack_frame.index |
+ function = stack_frame.function |
+ |
+ # Add the file to this component's dictionary of files. |
+ file_dict = self.component_dict[component_path] |
+ file_dict.AddFile(file_name, file_path, crashed_line_number, |
+ stack_frame_index, function) |
+ |
+ def __CreateFileDictFromCallstack(self, callstack, top_n_frames=15): |
+ """Creates a file dict that maps a file to the occurrence in the stack. |
+ |
+ Args: |
+ callstack: A list containing parsed result from a single stack |
+ within a stacktrace. For example, a stacktrace from |
+ previously-allocated thread in release build stacktrace. |
+ top_n_frames: The number of frames to look for. |
+ |
+ Returns: |
+ Component_dict, a dictionary with key as a file name and value as another |
+ dictionary, which maps the file's path (because there can be multiple |
+ files with same name but in different directory) to the list of this |
+ file's place in stack, lines that this file caused a crash, and the name |
+ of the function. |
+ """ |
+ |
+ # Only look at first 15 frames of the stacktrace, below those are likely |
+ # to be noisy. Parse the stacktrace into the component dictionary. |
+ stack_list = callstack.GetTopNFrames(top_n_frames) |
+ self.__GenerateFileDict(stack_list) |
+ |
+ def __iter__(self): |
+ return iter(self.component_dict) |