summaryrefslogtreecommitdiff
path: root/extra/stack_analyzer
diff options
context:
space:
mode:
authorChe-yu Wu <cheyuw@google.com>2017-09-05 11:05:26 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-09-05 23:01:09 -0700
commitce15362e895bac60f18d7fa000029be6e7879e9f (patch)
tree9c45d766c358f9b67665cf5e638d64bb067a163e /extra/stack_analyzer
parent848cf8f7983bd1b7df3429de9b99124215de1539 (diff)
downloadchrome-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/stack_analyzer')
-rw-r--r--extra/stack_analyzer/example_annotation.yaml16
-rwxr-xr-xextra/stack_analyzer/stack_analyzer.py64
-rwxr-xr-xextra/stack_analyzer/stack_analyzer_unittest.py19
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, []),