summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.rules5
-rw-r--r--extra/stack_analyzer/README.md3
-rwxr-xr-xextra/stack_analyzer/stack_analyzer.py13
-rwxr-xr-xextra/stack_analyzer/stack_analyzer_unittest.py50
4 files changed, 46 insertions, 25 deletions
diff --git a/Makefile.rules b/Makefile.rules
index 7e66d2ef77..d589556558 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -541,6 +541,7 @@ newsizes:
# them first is because elf dependencies will cause the elf files be rebuilt for
# updating date, which shouldn't happen when analyzing the existing firmwares.
.PHONY: analyzestack
+ANNOTATION ?= ./$(BDIR)/analyzestack.yaml
analyzestack: $(out)/util/export_taskinfo.so
@if [ "$(SECTION)" != "RO" ] && [ "$(SECTION)" != "RW" ]; then \
echo "Please specify SECTION=RO or RW. The default is RW."; \
@@ -554,8 +555,8 @@ analyzestack: $(out)/util/export_taskinfo.so
fi; \
extra/stack_analyzer/stack_analyzer.py --objdump "$(OBJDUMP)" \
--addr2line "$(ADDR2LINE)" --section "$$SECTION" \
- $(if $(ANNOTATION),--annotation $(ANNOTATION),) \
- --export_taskinfo "$$EXPORT_TASKINFO" "$$ELF"
+ --annotation $(ANNOTATION) \
+ --export_taskinfo "$$EXPORT_TASKINFO" "$$ELF"
.SECONDARY:
diff --git a/extra/stack_analyzer/README.md b/extra/stack_analyzer/README.md
index b809ccc5a2..a13b3b66db 100644
--- a/extra/stack_analyzer/README.md
+++ b/extra/stack_analyzer/README.md
@@ -15,7 +15,8 @@ In `src/platform/ec`, run
make BOARD=${BOARD} SECTION=${SECTION} ANNOTATION=${ANNOTATION} analyzestack
```
The `${SECTION}` can be `RO` or `RW`. The `${ANNOTATION}` is a optional
-annotation file, see the example_annotation.yaml.
+annotation file, see the example_annotation.yaml, by default,
+board/$BOARD/analyzestack.yaml is used.
Output
------
diff --git a/extra/stack_analyzer/stack_analyzer.py b/extra/stack_analyzer/stack_analyzer.py
index f08470bafc..a839515b9e 100755
--- a/extra/stack_analyzer/stack_analyzer.py
+++ b/extra/stack_analyzer/stack_analyzer.py
@@ -1439,19 +1439,26 @@ def main():
# Load annotation config.
if options.annotation is None:
annotation = {}
+ elif not os.path.exists(options.annotation):
+ print('Warning: Annotation file {} does not exist.'
+ .format(options.annotation))
+ annotation = {}
else:
try:
with open(options.annotation, 'r') as annotation_file:
annotation = yaml.safe_load(annotation_file)
except yaml.YAMLError:
- raise StackAnalyzerError('Failed to parse annotation file.')
+ raise StackAnalyzerError('Failed to parse annotation file {}.'
+ .format(options.annotation))
except IOError:
- raise StackAnalyzerError('Failed to open annotation file.')
+ raise StackAnalyzerError('Failed to open annotation file {}.'
+ .format(options.annotation))
# TODO(cheyuw): Do complete annotation format verification.
if not isinstance(annotation, dict):
- raise StackAnalyzerError('Invalid annotation file.')
+ raise StackAnalyzerError('Invalid annotation file {}.'
+ .format(options.annotation))
# Generate and parse the symbols.
try:
diff --git a/extra/stack_analyzer/stack_analyzer_unittest.py b/extra/stack_analyzer/stack_analyzer_unittest.py
index cac4383906..1fe4944844 100755
--- a/extra/stack_analyzer/stack_analyzer_unittest.py
+++ b/extra/stack_analyzer/stack_analyzer_unittest.py
@@ -640,25 +640,37 @@ class StackAnalyzerTest(unittest.TestCase):
annotation='fake')
parseargs_mock.return_value = args
- with mock.patch('__builtin__.print') as print_mock:
- sa.main()
- print_mock.assert_called_once_with(
- 'Error: Failed to open annotation file.')
-
- with mock.patch('__builtin__.print') as print_mock:
- with mock.patch('__builtin__.open', mock.mock_open()) as open_mock:
- open_mock.return_value.read.side_effect = ['{', '']
- sa.main()
- open_mock.assert_called_once_with('fake', 'r')
- print_mock.assert_called_once_with(
- 'Error: Failed to parse annotation file.')
-
- with mock.patch('__builtin__.print') as print_mock:
- with mock.patch('__builtin__.open',
- mock.mock_open(read_data='')) as open_mock:
- sa.main()
- print_mock.assert_called_once_with(
- 'Error: Invalid annotation file.')
+ with mock.patch('os.path.exists') as path_mock:
+ path_mock.return_value = False
+ with mock.patch('__builtin__.print') as print_mock:
+ with mock.patch('__builtin__.open', mock.mock_open()) as open_mock:
+ sa.main()
+ print_mock.assert_any_call(
+ 'Warning: Annotation file fake does not exist.')
+
+ with mock.patch('os.path.exists') as path_mock:
+ path_mock.return_value = True
+ with mock.patch('__builtin__.print') as print_mock:
+ with mock.patch('__builtin__.open', mock.mock_open()) as open_mock:
+ open_mock.side_effect = IOError()
+ sa.main()
+ print_mock.assert_called_once_with(
+ 'Error: Failed to open annotation file fake.')
+
+ with mock.patch('__builtin__.print') as print_mock:
+ with mock.patch('__builtin__.open', mock.mock_open()) as open_mock:
+ open_mock.return_value.read.side_effect = ['{', '']
+ sa.main()
+ open_mock.assert_called_once_with('fake', 'r')
+ print_mock.assert_called_once_with(
+ 'Error: Failed to parse annotation file fake.')
+
+ with mock.patch('__builtin__.print') as print_mock:
+ with mock.patch('__builtin__.open',
+ mock.mock_open(read_data='')) as open_mock:
+ sa.main()
+ print_mock.assert_called_once_with(
+ 'Error: Invalid annotation file fake.')
args.annotation = None