diff options
author | Che-yu Wu <cheyuw@google.com> | 2017-09-05 11:05:26 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-09-05 23:01:09 -0700 |
commit | ce15362e895bac60f18d7fa000029be6e7879e9f (patch) | |
tree | 9c45d766c358f9b67665cf5e638d64bb067a163e /extra | |
parent | 848cf8f7983bd1b7df3429de9b99124215de1539 (diff) | |
download | chrome-ec-ce15362e895bac60f18d7fa000029be6e7879e9f.tar.gz |
extra/stack_analyzer: Support function sets in invalid paths.
There are lots of invalid paths have common segments.
In this patch, each vertex of an invalid path can be a function set.
Examples can be found in extra/stack_analyzer/example_annotation.yaml
BUG=chromium:648840
BRANCH=none
TEST=extra/stack_analyzer/stack_analyzer_unittest.py
make BOARD=elm SECTION=RW \
ANNOTATION=./extra/stack_analyzer/example_annotation.yaml \
analyzestack
Change-Id: Ib10d68edd04725af4d803f54f7e208e55d574c7d
Signed-off-by: Che-yu Wu <cheyuw@google.com>
Reviewed-on: https://chromium-review.googlesource.com/649453
Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
Diffstat (limited to 'extra')
-rw-r--r-- | extra/stack_analyzer/example_annotation.yaml | 16 | ||||
-rwxr-xr-x | extra/stack_analyzer/stack_analyzer.py | 64 | ||||
-rwxr-xr-x | extra/stack_analyzer/stack_analyzer_unittest.py | 19 |
3 files changed, 76 insertions, 23 deletions
diff --git a/extra/stack_analyzer/example_annotation.yaml b/extra/stack_analyzer/example_annotation.yaml index 3b96d90b89..92dff8922f 100644 --- a/extra/stack_analyzer/example_annotation.yaml +++ b/extra/stack_analyzer/example_annotation.yaml @@ -24,6 +24,18 @@ remove: # Remove some invalid paths. - [pd_send_request_msg, set_state, pd_power_supply_reset] - [__tx_char, __tx_char] -- [pd_send_request_msg, set_state, set_state] -- [pd_send_request_msg, set_state, set_state, pd_power_supply_reset] - [set_state, set_state, set_state] + +# Remove two invalid paths with the common prefix. +- [pd_execute_hard_reset, set_state, [charge_manager_update_dualrole, pd_dfp_exit_mode]] +# It is equivalent to the following two lines, +# - [pd_execute_hard_reset, set_state, charge_manager_update_dualrole] +# - [pd_execute_hard_reset, set_state, pd_dfp_exit_mode] + +# Remove four invalid paths with the common segment. +- [[pd_send_request_msg, pd_request_vconn_swap], set_state, [usb_mux_set, pd_power_supply_reset]] +# It is equivalent to the following four lines, +# - [pd_send_request_msg, set_state, usb_mux_set] +# - [pd_send_request_msg, set_state, pd_power_supply_reset] +# - [pd_request_vconn_swap, set_state, usb_mux_set] +# - [pd_request_vconn_swap, set_state, pd_power_supply_reset] diff --git a/extra/stack_analyzer/stack_analyzer.py b/extra/stack_analyzer/stack_analyzer.py index 30aac28728..af58ef7ef0 100755 --- a/extra/stack_analyzer/stack_analyzer.py +++ b/extra/stack_analyzer/stack_analyzer.py @@ -765,21 +765,49 @@ class StackAnalyzer(object): add_rules[src_sig].add(dst_sig) if 'remove' in self.annotation and self.annotation['remove'] is not None: - for remove_sigtxts in self.annotation['remove']: - if isinstance(remove_sigtxts, str): - remove_sigtxts = [remove_sigtxts] - - remove_path = [] - for remove_sigtxt in remove_sigtxts: - remove_sig = NormalizeSignature(remove_sigtxt) - if remove_sig is None: - invalid_sigtxts.add(remove_sigtxt) + for sigtxt_path in self.annotation['remove']: + if isinstance(sigtxt_path, str): + # The path has only one vertex. + sigtxt_path = [sigtxt_path] + + if len(sigtxt_path) == 0: + continue + + # Generate multiple remove paths from all the combinations of the + # signatures of each vertex. + sig_paths = [[]] + broken_flag = False + for sigtxt_node in sigtxt_path: + if isinstance(sigtxt_node, str): + # The vertex has only one signature. + sigtxt_set = {sigtxt_node} + elif isinstance(sigtxt_node, list): + # The vertex has multiple signatures. + sigtxt_set = set(sigtxt_node) else: - remove_path.append(remove_sig) + # Assume the format of annotation is verified. There should be no + # invalid case. + assert False + + sig_set = set() + for sigtxt in sigtxt_set: + sig = NormalizeSignature(sigtxt) + if sig is None: + invalid_sigtxts.add(sigtxt) + broken_flag = True + elif not broken_flag: + sig_set.add(sig) + + if broken_flag: + continue + + # Append each signature of the current node to the all previous + # remove paths. + sig_paths = [path + [sig] for path in sig_paths for sig in sig_set] - if len(remove_path) == len(remove_sigtxts): + if not broken_flag: # All signatures are normalized. The remove path has no error. - remove_rules.append(remove_path) + remove_rules.extend(sig_paths) return (add_rules, remove_rules, invalid_sigtxts) @@ -897,21 +925,15 @@ class StackAnalyzer(object): skip_flag = True break else: - paths = [] - for remove_path in remove_paths: - # Append each function of the current signature to the all previous - # remove paths. - for remove_func in remove_funcs: - paths.append(remove_path + [remove_func]) - - remove_paths = paths + # Append each function of the current signature to the all previous + # remove paths. + remove_paths = [p + [f] for p in remove_paths for f in remove_funcs] if skip_flag: # Ignore the broken remove path. continue for remove_path in remove_paths: - skip_flag = False # Deduplicate the remove paths. if remove_path not in remove_list: remove_list.append(remove_path) diff --git a/extra/stack_analyzer/stack_analyzer_unittest.py b/extra/stack_analyzer/stack_analyzer_unittest.py index f6036a65e9..a3bd80a186 100755 --- a/extra/stack_analyzer/stack_analyzer_unittest.py +++ b/extra/stack_analyzer/stack_analyzer_unittest.py @@ -226,6 +226,25 @@ class StackAnalyzerTest(unittest.TestCase): self.assertEqual(remove_rules, []) self.assertEqual(invalid_sigtxts, set()) + self.analyzer.annotation = { + 'add': None, + 'remove': [ + [['a', 'b'], ['0', '[', '2'], 'x'], + [['a', 'b[x:3]'], ['0', '1', '2'], 'x'], + ], + } + (add_rules, remove_rules, invalid_sigtxts) = self.analyzer.LoadAnnotation() + self.assertEqual(add_rules, {}) + self.assertEqual(remove_rules, [ + [('a', None, None), ('1', None, None), ('x', None, None)], + [('a', None, None), ('0', None, None), ('x', None, None)], + [('a', None, None), ('2', None, None), ('x', None, None)], + [('b', os.path.abspath('x'), 3), ('1', None, None), ('x', None, None)], + [('b', os.path.abspath('x'), 3), ('0', None, None), ('x', None, None)], + [('b', os.path.abspath('x'), 3), ('2', None, None), ('x', None, None)], + ]) + self.assertEqual(invalid_sigtxts, {'['}) + funcs = { 0x1000: sa.Function(0x1000, 'hook_task', 0, []), 0x2000: sa.Function(0x2000, 'console_task', 0, []), |