diff options
-rw-r--r-- | Makefile.rules | 5 | ||||
-rw-r--r-- | extra/stack_analyzer/README.md | 3 | ||||
-rwxr-xr-x | extra/stack_analyzer/stack_analyzer.py | 13 | ||||
-rwxr-xr-x | extra/stack_analyzer/stack_analyzer_unittest.py | 50 |
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 |