diff options
-rwxr-xr-x | extra/stack_analyzer/stack_analyzer_unittest.py | 102 |
1 files changed, 100 insertions, 2 deletions
diff --git a/extra/stack_analyzer/stack_analyzer_unittest.py b/extra/stack_analyzer/stack_analyzer_unittest.py index d159b2e14a..eb2f69b751 100755 --- a/extra/stack_analyzer/stack_analyzer_unittest.py +++ b/extra/stack_analyzer/stack_analyzer_unittest.py @@ -424,9 +424,46 @@ class StackAnalyzerTest(unittest.TestCase): [funcs[0x2000], funcs[0x4000], funcs[0x2000]], ]) - def testAnalyzeDisassembly(self): + def testAndesAnalyzeDisassembly(self): disasm_text = ( '\n' + 'build/{BOARD}/RW/ec.RW.elf: file format elf32-nds32le' + '\n' + 'Disassembly of section .text:\n' + '\n' + '00000900 <wook_task>:\n' + ' ...\n' + '00001000 <hook_task>:\n' + ' 1000: fc 42\tpush25 $r10, #16 ! {$r6~$r10, $fp, $gp, $lp}\n' + ' 1004: 47 70\t\tmovi55 $r0, #1\n' + ' 1006: b1 13\tbnezs8 100929de <flash_command_write>\n' + ' 1008: 00 01 5c fc\tbne $r6, $r0, 2af6a\n' + '00002000 <console_task>:\n' + ' 2000: fc 00\t\tpush25 $r6, #0 ! {$r6, $fp, $gp, $lp} \n' + ' 2002: f0 0e fc c5\tjal 1000 <hook_task>\n' + ' 2006: f0 0e bd 3b\tj 53968 <get_program_memory_addr>\n' + ' 200a: de ad be ef\tswi.gp $r0, [ + #-11036]\n' + '00004000 <touchpad_calc>:\n' + ' 4000: 47 70\t\tmovi55 $r0, #1\n' + '00010000 <look_task>:' + ) + function_map = self.analyzer.AnalyzeDisassembly(disasm_text) + func_hook_task = sa.Function(0x1000, 'hook_task', 48, [ + sa.Callsite(0x1006, 0x100929de, True, None)]) + expect_funcmap = { + 0x1000: func_hook_task, + 0x2000: sa.Function(0x2000, 'console_task', 16, + [sa.Callsite(0x2002, 0x1000, False, func_hook_task), + sa.Callsite(0x2006, 0x53968, True, None)]), + 0x4000: sa.Function(0x4000, 'touchpad_calc', 0, []), + } + self.assertEqual(function_map, expect_funcmap) + + def testArmAnalyzeDisassembly(self): + disasm_text = ( + '\n' + 'build/{BOARD}/RW/ec.RW.elf: file format elf32-littlearm' + '\n' 'Disassembly of section .text:\n' '\n' '00000900 <wook_task>:\n' @@ -597,9 +634,70 @@ class StackAnalyzerTest(unittest.TestCase): @mock.patch('subprocess.check_output') @mock.patch('stack_analyzer.StackAnalyzer.AddressToLine') - def testAnalyze(self, addrtoline_mock, checkoutput_mock): + def testAndesAnalyze(self, addrtoline_mock, checkoutput_mock): disasm_text = ( '\n' + 'build/{BOARD}/RW/ec.RW.elf: file format elf32-nds32le' + '\n' + 'Disassembly of section .text:\n' + '\n' + '00000900 <wook_task>:\n' + ' ...\n' + '00001000 <hook_task>:\n' + ' 1000: fc 00\t\tpush25 $r10, #16 ! {$r6~$r10, $fp, $gp, $lp}\n' + ' 1002: 47 70\t\tmovi55 $r0, #1\n' + ' 1006: 00 01 5c fc\tbne $r6, $r0, 2af6a\n' + '00002000 <console_task>:\n' + ' 2000: fc 00\t\tpush25 $r6, #0 ! {$r6, $fp, $gp, $lp} \n' + ' 2002: f0 0e fc c5\tjal 1000 <hook_task>\n' + ' 2006: f0 0e bd 3b\tj 53968 <get_program_memory_addr>\n' + ' 200a: 12 34 56 78\tjral5 $r0\n' + ) + + addrtoline_mock.return_value = [('??', '??', 0)] + self.analyzer.annotation = { + 'exception_frame_size': 64, + 'remove': [['fake_func']], + } + + with mock.patch('__builtin__.print') as print_mock: + checkoutput_mock.return_value = disasm_text + self.analyzer.Analyze() + print_mock.assert_has_calls([ + mock.call( + 'Task: HOOKS, Max size: 96 (32 + 64), Allocated size: 2048'), + mock.call('Call Trace:'), + mock.call(' hook_task (32) [??:0] 1000'), + mock.call( + 'Task: CONSOLE, Max size: 112 (48 + 64), Allocated size: 460'), + mock.call('Call Trace:'), + mock.call(' console_task (16) [??:0] 2000'), + mock.call(' -> ??[??:0] 2002'), + mock.call(' hook_task (32) [??:0] 1000'), + mock.call('Unresolved indirect callsites:'), + mock.call(' In function console_task:'), + mock.call(' -> ??[??:0] 200a'), + mock.call('Unresolved annotation signatures:'), + mock.call(' fake_func: function is not found'), + ]) + + with self.assertRaisesRegexp(sa.StackAnalyzerError, + 'Failed to run objdump.'): + checkoutput_mock.side_effect = OSError() + self.analyzer.Analyze() + + with self.assertRaisesRegexp(sa.StackAnalyzerError, + 'objdump failed to disassemble.'): + checkoutput_mock.side_effect = subprocess.CalledProcessError(1, '') + self.analyzer.Analyze() + + @mock.patch('subprocess.check_output') + @mock.patch('stack_analyzer.StackAnalyzer.AddressToLine') + def testArmAnalyze(self, addrtoline_mock, checkoutput_mock): + disasm_text = ( + '\n' + 'build/{BOARD}/RW/ec.RW.elf: file format elf32-littlearm' + '\n' 'Disassembly of section .text:\n' '\n' '00000900 <wook_task>:\n' |