Chromium Code Reviews| 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 | |
| 5 import logging | |
| 6 | |
| 7 import chromium_deps | |
| 8 import crash_utils | |
| 9 import findit_for_crash as findit | |
| 10 import stacktrace | |
| 11 | |
| 12 | |
| 13 def SplitStacktrace(stacktrace_string): | |
| 14 """Preprocesses stacktrace string into two parts, release and debug. | |
| 15 | |
| 16 Args: | |
| 17 stacktrace_string: A string representation of stacktrace, | |
| 18 in clusterfuzz format. | |
| 19 | |
| 20 Returns: | |
| 21 A tuple of list of strings, release build stacktrace and | |
| 22 debug build stacktrace. | |
| 23 """ | |
| 24 # Make sure we only parse release/debug build stacktrace, and ignore | |
| 25 # unsymbolised stacktrace. | |
| 26 in_release_or_debug_stacktrace = False | |
| 27 release_build_stacktrace_lines = None | |
| 28 debug_build_stacktrace_lines = None | |
| 29 current_stacktrace_lines = [] | |
| 30 | |
| 31 # Iterate through all lines in stacktrace. | |
| 32 for line in stacktrace_string.splitlines(): | |
| 33 line = line.strip() | |
| 34 | |
| 35 # If the line starts with +, it signifies the start of new stacktrace. | |
| 36 if line.startswith('+'): | |
| 37 if 'Release Build Stacktrace' in line: | |
| 38 in_release_or_debug_stacktrace = True | |
| 39 current_stacktrace_lines = [] | |
| 40 release_build_stacktrace_lines = current_stacktrace_lines | |
| 41 | |
| 42 elif 'Debug Build Stacktrace' in line: | |
| 43 in_release_or_debug_stacktrace = True | |
| 44 current_stacktrace_lines = [] | |
| 45 debug_build_stacktrace_lines = current_stacktrace_lines | |
| 46 | |
| 47 # If the stacktrace is neither release/debug build stacktrace, ignore | |
| 48 # all lines after it until we encounter release/debug build stacktrace. | |
| 49 else: | |
| 50 in_release_or_debug_stacktrace = False | |
| 51 | |
| 52 # This case, it must be that the line is an actual stack frame, so add to | |
| 53 # the current stacktrace. | |
| 54 elif in_release_or_debug_stacktrace: | |
| 55 current_stacktrace_lines.append(line) | |
| 56 | |
| 57 return (release_build_stacktrace_lines, debug_build_stacktrace_lines) | |
| 58 | |
| 59 | |
| 60 def FindCulpritCLs(stacktrace_string, | |
| 61 build_type, | |
| 62 chrome_regression=None, | |
| 63 component_regression=None, | |
| 64 chrome_crash_revision=None, | |
| 65 component_crash_revision=None, | |
| 66 crashing_component=None): | |
| 67 """Returns the result, a list of result.Result objects and message. | |
| 68 | |
| 69 Args: | |
| 70 stacktrace_string: A string representing stacktrace. | |
| 71 build_type: The type of the job. | |
| 72 chrome_regression: A string, chrome regression from clusterfuzz, in format | |
| 73 '123456:123457' | |
| 74 component_regression: A string, component regression in the same format. | |
| 75 chrome_crash_revision: A crash revision of chrome, in string. | |
| 76 component_crash_revision: A crash revision of the component, | |
| 77 if component build. | |
| 78 crashing_component: Yet to be decided. | |
| 79 | |
| 80 Returns: | |
| 81 A list of result objects, along with the short description on where the | |
| 82 result is from. | |
| 83 """ | |
| 84 build_type = build_type.lower() | |
| 85 if 'android' in build_type or 'syzyasan' in build_type: | |
|
Martin Barbella
2014/08/19 19:52:12
Is there any reason that android needs to be skipp
jeun
2014/08/19 21:37:43
Done.
| |
| 86 return ('This build type is currently not supported.', []) | |
| 87 | |
| 88 logging.basicConfig(filename='errors.log', level=logging.WARNING, | |
| 89 filemode='w+') | |
|
Martin Barbella
2014/08/19 19:52:12
Why is this w+?
jeun
2014/08/19 21:37:43
It creates errors.log file if it is not already th
| |
| 90 | |
| 91 component_to_crash_revision_dict = {} | |
| 92 component_to_regression_dict = {} | |
| 93 | |
| 94 # TODO(jeun): Come up with a good way to connect crashing component name to | |
| 95 # its path. | |
| 96 if component_regression or component_crash_revision: | |
| 97 return ('Component builds are not supported yet.', []) | |
| 98 | |
| 99 # If chrome regression is available, parse DEPS file. | |
| 100 chrome_regression = crash_utils.SplitRange(chrome_regression) | |
| 101 if chrome_regression: | |
| 102 chrome_regression_start = chrome_regression[0] | |
| 103 chrome_regression_end = chrome_regression[1] | |
| 104 | |
| 105 # Do not parse regression information for crashes introduced before the | |
| 106 # first archived build. | |
| 107 if chrome_regression_start != '0': | |
| 108 component_to_regression_dict = chromium_deps.GetChromiumComponentRange( | |
| 109 chrome_regression_start, chrome_regression_end) | |
| 110 | |
| 111 # Parse crash revision. | |
| 112 if chrome_crash_revision: | |
| 113 component_to_crash_revision_dict = chromium_deps.GetChromiumComponents( | |
| 114 chrome_crash_revision) | |
| 115 | |
| 116 # Parsed DEPS is used to normalize the stacktrace. Since parsed regression | |
| 117 # and parsed crash state essentially contain same information, use either. | |
| 118 if component_to_regression_dict: | |
| 119 parsed_deps = component_to_regression_dict | |
| 120 elif component_to_crash_revision_dict: | |
| 121 parsed_deps = component_to_crash_revision_dict | |
| 122 else: | |
| 123 return (('Identifying culprit CL requires at lease one of regression ' | |
| 124 'information or crash revision'), []) | |
| 125 | |
| 126 # Split stacktrace into release build/debug build and parse them. | |
| 127 (release_build_stacktrace, debug_build_stacktrace) = SplitStacktrace( | |
| 128 stacktrace_string) | |
| 129 parsed_release_build_stacktrace = stacktrace.Stacktrace( | |
| 130 release_build_stacktrace, build_type, parsed_deps) | |
| 131 parsed_debug_build_stacktrace = stacktrace.Stacktrace( | |
| 132 debug_build_stacktrace, build_type, parsed_deps) | |
| 133 | |
| 134 # Get a highest priority callstack (main_stack) from stacktrace, with release | |
| 135 # build stacktrace in higher priority than debug build stacktace. This stack | |
| 136 # is the callstack to find blame information for. | |
| 137 if parsed_release_build_stacktrace.stack_list: | |
| 138 main_stack = parsed_release_build_stacktrace.GetCrashStack() | |
| 139 elif parsed_debug_build_stacktrace.stack_list: | |
| 140 main_stack = parsed_debug_build_stacktrace.GetCrashStack() | |
| 141 else: | |
| 142 return ('Stacktrace is malformed.', []) | |
| 143 | |
| 144 # Run the algorithm on the parsed stacktrace, and return the result. | |
| 145 stacktrace_list = [parsed_release_build_stacktrace, | |
| 146 parsed_debug_build_stacktrace] | |
| 147 return findit.FindItForCrash( | |
| 148 stacktrace_list, main_stack, component_to_regression_dict, | |
| 149 component_to_crash_revision_dict) | |
| OLD | NEW |