1*288bf522SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*288bf522SAndroid Build Coastguard Worker# 3*288bf522SAndroid Build Coastguard Worker# Copyright (C) 2021 The Android Open Source Project 4*288bf522SAndroid Build Coastguard Worker# 5*288bf522SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*288bf522SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*288bf522SAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*288bf522SAndroid Build Coastguard Worker# 9*288bf522SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*288bf522SAndroid Build Coastguard Worker# 11*288bf522SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*288bf522SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*288bf522SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*288bf522SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*288bf522SAndroid Build Coastguard Worker# limitations under the License. 16*288bf522SAndroid Build Coastguard Worker 17*288bf522SAndroid Build Coastguard Workerimport io 18*288bf522SAndroid Build Coastguard Workerimport os 19*288bf522SAndroid Build Coastguard Workerfrom pathlib import Path 20*288bf522SAndroid Build Coastguard Worker 21*288bf522SAndroid Build Coastguard Workerfrom binary_cache_builder import BinaryCacheBuilder 22*288bf522SAndroid Build Coastguard Workerfrom simpleperf_utils import (Addr2Nearestline, AddrRange, BinaryFinder, Disassembly, Objdump, 23*288bf522SAndroid Build Coastguard Worker ReadElf, SourceFileSearcher, is_windows, remove) 24*288bf522SAndroid Build Coastguard Workerfrom . test_utils import TestBase, TestHelper 25*288bf522SAndroid Build Coastguard Worker 26*288bf522SAndroid Build Coastguard Worker 27*288bf522SAndroid Build Coastguard Workerclass TestTools(TestBase): 28*288bf522SAndroid Build Coastguard Worker def test_addr2nearestline(self): 29*288bf522SAndroid Build Coastguard Worker self.run_addr2nearestline_test(True) 30*288bf522SAndroid Build Coastguard Worker self.run_addr2nearestline_test(False) 31*288bf522SAndroid Build Coastguard Worker 32*288bf522SAndroid Build Coastguard Worker def run_addr2nearestline_test(self, with_function_name): 33*288bf522SAndroid Build Coastguard Worker test_map = { 34*288bf522SAndroid Build Coastguard Worker '/simpleperf_runtest_two_functions_arm64': [ 35*288bf522SAndroid Build Coastguard Worker { 36*288bf522SAndroid Build Coastguard Worker 'func_addr': 0x112c, 37*288bf522SAndroid Build Coastguard Worker 'addr': 0x112c, 38*288bf522SAndroid Build Coastguard Worker 'source': 'system/extras/simpleperf/runtest/two_functions.cpp:20', 39*288bf522SAndroid Build Coastguard Worker 'function': 'main', 40*288bf522SAndroid Build Coastguard Worker }, 41*288bf522SAndroid Build Coastguard Worker { 42*288bf522SAndroid Build Coastguard Worker 'func_addr': 0x104c, 43*288bf522SAndroid Build Coastguard Worker 'addr': 0x105c, 44*288bf522SAndroid Build Coastguard Worker 'source': "system/extras/simpleperf/runtest/two_functions.cpp:7", 45*288bf522SAndroid Build Coastguard Worker 'function': "Function1()", 46*288bf522SAndroid Build Coastguard Worker }, 47*288bf522SAndroid Build Coastguard Worker ], 48*288bf522SAndroid Build Coastguard Worker '/simpleperf_runtest_two_functions_arm': [ 49*288bf522SAndroid Build Coastguard Worker { 50*288bf522SAndroid Build Coastguard Worker 'func_addr': 0x1304, 51*288bf522SAndroid Build Coastguard Worker 'addr': 0x131a, 52*288bf522SAndroid Build Coastguard Worker 'source': """system/extras/simpleperf/runtest/two_functions.cpp:8 53*288bf522SAndroid Build Coastguard Worker system/extras/simpleperf/runtest/two_functions.cpp:22""", 54*288bf522SAndroid Build Coastguard Worker 'function': """Function1() 55*288bf522SAndroid Build Coastguard Worker main""", 56*288bf522SAndroid Build Coastguard Worker }, 57*288bf522SAndroid Build Coastguard Worker { 58*288bf522SAndroid Build Coastguard Worker 'func_addr': 0x1304, 59*288bf522SAndroid Build Coastguard Worker 'addr': 0x131c, 60*288bf522SAndroid Build Coastguard Worker 'source': """system/extras/simpleperf/runtest/two_functions.cpp:16 61*288bf522SAndroid Build Coastguard Worker system/extras/simpleperf/runtest/two_functions.cpp:23""", 62*288bf522SAndroid Build Coastguard Worker 'function': """Function2() 63*288bf522SAndroid Build Coastguard Worker main""", 64*288bf522SAndroid Build Coastguard Worker } 65*288bf522SAndroid Build Coastguard Worker ], 66*288bf522SAndroid Build Coastguard Worker '/simpleperf_runtest_two_functions_x86_64': [ 67*288bf522SAndroid Build Coastguard Worker { 68*288bf522SAndroid Build Coastguard Worker 'func_addr': 0x19e0, 69*288bf522SAndroid Build Coastguard Worker 'addr': 0x19f6, 70*288bf522SAndroid Build Coastguard Worker 'source': """system/extras/simpleperf/runtest/two_functions.cpp:8 71*288bf522SAndroid Build Coastguard Worker system/extras/simpleperf/runtest/two_functions.cpp:22""", 72*288bf522SAndroid Build Coastguard Worker 'function': """Function1() 73*288bf522SAndroid Build Coastguard Worker main""", 74*288bf522SAndroid Build Coastguard Worker }, 75*288bf522SAndroid Build Coastguard Worker { 76*288bf522SAndroid Build Coastguard Worker 'func_addr': 0x19e0, 77*288bf522SAndroid Build Coastguard Worker 'addr': 0x1a19, 78*288bf522SAndroid Build Coastguard Worker 'source': """system/extras/simpleperf/runtest/two_functions.cpp:16 79*288bf522SAndroid Build Coastguard Worker system/extras/simpleperf/runtest/two_functions.cpp:23""", 80*288bf522SAndroid Build Coastguard Worker 'function': """Function2() 81*288bf522SAndroid Build Coastguard Worker main""", 82*288bf522SAndroid Build Coastguard Worker } 83*288bf522SAndroid Build Coastguard Worker ], 84*288bf522SAndroid Build Coastguard Worker '/simpleperf_runtest_two_functions_x86': [ 85*288bf522SAndroid Build Coastguard Worker { 86*288bf522SAndroid Build Coastguard Worker 'func_addr': 0x16e0, 87*288bf522SAndroid Build Coastguard Worker 'addr': 0x16f6, 88*288bf522SAndroid Build Coastguard Worker 'source': """system/extras/simpleperf/runtest/two_functions.cpp:8 89*288bf522SAndroid Build Coastguard Worker system/extras/simpleperf/runtest/two_functions.cpp:22""", 90*288bf522SAndroid Build Coastguard Worker 'function': """Function1() 91*288bf522SAndroid Build Coastguard Worker main""", 92*288bf522SAndroid Build Coastguard Worker }, 93*288bf522SAndroid Build Coastguard Worker { 94*288bf522SAndroid Build Coastguard Worker 'func_addr': 0x16e0, 95*288bf522SAndroid Build Coastguard Worker 'addr': 0x1710, 96*288bf522SAndroid Build Coastguard Worker 'source': """system/extras/simpleperf/runtest/two_functions.cpp:16 97*288bf522SAndroid Build Coastguard Worker system/extras/simpleperf/runtest/two_functions.cpp:23""", 98*288bf522SAndroid Build Coastguard Worker 'function': """Function2() 99*288bf522SAndroid Build Coastguard Worker main""", 100*288bf522SAndroid Build Coastguard Worker } 101*288bf522SAndroid Build Coastguard Worker ], 102*288bf522SAndroid Build Coastguard Worker } 103*288bf522SAndroid Build Coastguard Worker 104*288bf522SAndroid Build Coastguard Worker binary_finder = BinaryFinder(TestHelper.testdata_dir, ReadElf(TestHelper.ndk_path)) 105*288bf522SAndroid Build Coastguard Worker addr2line = Addr2Nearestline(TestHelper.ndk_path, binary_finder, with_function_name) 106*288bf522SAndroid Build Coastguard Worker for dso_path in test_map: 107*288bf522SAndroid Build Coastguard Worker test_addrs = test_map[dso_path] 108*288bf522SAndroid Build Coastguard Worker for test_addr in test_addrs: 109*288bf522SAndroid Build Coastguard Worker addr2line.add_addr(dso_path, None, test_addr['func_addr'], test_addr['addr']) 110*288bf522SAndroid Build Coastguard Worker addr2line.convert_addrs_to_lines(4) 111*288bf522SAndroid Build Coastguard Worker for dso_path in test_map: 112*288bf522SAndroid Build Coastguard Worker dso = addr2line.get_dso(dso_path) 113*288bf522SAndroid Build Coastguard Worker self.assertIsNotNone(dso, dso_path) 114*288bf522SAndroid Build Coastguard Worker test_addrs = test_map[dso_path] 115*288bf522SAndroid Build Coastguard Worker for test_addr in test_addrs: 116*288bf522SAndroid Build Coastguard Worker expected_files = [] 117*288bf522SAndroid Build Coastguard Worker expected_lines = [] 118*288bf522SAndroid Build Coastguard Worker expected_functions = [] 119*288bf522SAndroid Build Coastguard Worker for line in test_addr['source'].split('\n'): 120*288bf522SAndroid Build Coastguard Worker items = line.split(':') 121*288bf522SAndroid Build Coastguard Worker expected_files.append(items[0].strip()) 122*288bf522SAndroid Build Coastguard Worker expected_lines.append(int(items[1])) 123*288bf522SAndroid Build Coastguard Worker for line in test_addr['function'].split('\n'): 124*288bf522SAndroid Build Coastguard Worker expected_functions.append(line.strip()) 125*288bf522SAndroid Build Coastguard Worker self.assertEqual(len(expected_files), len(expected_functions)) 126*288bf522SAndroid Build Coastguard Worker 127*288bf522SAndroid Build Coastguard Worker if with_function_name: 128*288bf522SAndroid Build Coastguard Worker expected_source = list(zip(expected_files, expected_lines, expected_functions)) 129*288bf522SAndroid Build Coastguard Worker else: 130*288bf522SAndroid Build Coastguard Worker expected_source = list(zip(expected_files, expected_lines)) 131*288bf522SAndroid Build Coastguard Worker 132*288bf522SAndroid Build Coastguard Worker actual_source = addr2line.get_addr_source(dso, test_addr['addr']) 133*288bf522SAndroid Build Coastguard Worker if is_windows(): 134*288bf522SAndroid Build Coastguard Worker self.assertIsNotNone(actual_source, 'for %s:0x%x' % 135*288bf522SAndroid Build Coastguard Worker (dso_path, test_addr['addr'])) 136*288bf522SAndroid Build Coastguard Worker for i, source in enumerate(actual_source): 137*288bf522SAndroid Build Coastguard Worker new_source = list(source) 138*288bf522SAndroid Build Coastguard Worker new_source[0] = new_source[0].replace('\\', '/') 139*288bf522SAndroid Build Coastguard Worker actual_source[i] = tuple(new_source) 140*288bf522SAndroid Build Coastguard Worker 141*288bf522SAndroid Build Coastguard Worker self.assertEqual(actual_source, expected_source, 142*288bf522SAndroid Build Coastguard Worker 'for %s:0x%x, expected source %s, actual source %s' % 143*288bf522SAndroid Build Coastguard Worker (dso_path, test_addr['addr'], expected_source, actual_source)) 144*288bf522SAndroid Build Coastguard Worker 145*288bf522SAndroid Build Coastguard Worker def test_addr2nearestline_parse_output(self): 146*288bf522SAndroid Build Coastguard Worker output = """ 147*288bf522SAndroid Build Coastguard Worker0x104c 148*288bf522SAndroid Build Coastguard Workersystem/extras/simpleperf/runtest/two_functions.cpp:6:0 149*288bf522SAndroid Build Coastguard Worker 150*288bf522SAndroid Build Coastguard Worker0x1094 151*288bf522SAndroid Build Coastguard Workersystem/extras/simpleperf/runtest/two_functions.cpp:9:10 152*288bf522SAndroid Build Coastguard Worker 153*288bf522SAndroid Build Coastguard Worker0x10bb 154*288bf522SAndroid Build Coastguard Workersystem/extras/simpleperf/runtest/two_functions.cpp:11:1 155*288bf522SAndroid Build Coastguard Worker 156*288bf522SAndroid Build Coastguard Worker0x10bc 157*288bf522SAndroid Build Coastguard Workersystem/extras/simpleperf/runtest/two_functions.cpp:13:0 158*288bf522SAndroid Build Coastguard Worker 159*288bf522SAndroid Build Coastguard Worker0x1104 160*288bf522SAndroid Build Coastguard Workersystem/extras/simpleperf/runtest/two_functions.cpp:16:10 161*288bf522SAndroid Build Coastguard Worker 162*288bf522SAndroid Build Coastguard Worker0x112b 163*288bf522SAndroid Build Coastguard Workersystem/extras/simpleperf/runtest/two_functions.cpp:18:1 164*288bf522SAndroid Build Coastguard Worker 165*288bf522SAndroid Build Coastguard Worker0x112c 166*288bf522SAndroid Build Coastguard Workersystem/extras/simpleperf/runtest/two_functions.cpp:20:0 167*288bf522SAndroid Build Coastguard Worker 168*288bf522SAndroid Build Coastguard Worker0x113c 169*288bf522SAndroid Build Coastguard Workersystem/extras/simpleperf/runtest/two_functions.cpp:22:5 170*288bf522SAndroid Build Coastguard Worker 171*288bf522SAndroid Build Coastguard Worker0x1140 172*288bf522SAndroid Build Coastguard Workersystem/extras/simpleperf/runtest/two_functions.cpp:23:5 173*288bf522SAndroid Build Coastguard Worker 174*288bf522SAndroid Build Coastguard Worker0x1147 175*288bf522SAndroid Build Coastguard Workersystem/extras/simpleperf/runtest/two_functions.cpp:21:3 176*288bf522SAndroid Build Coastguard Worker """ 177*288bf522SAndroid Build Coastguard Worker dso = Addr2Nearestline.Dso(None) 178*288bf522SAndroid Build Coastguard Worker binary_finder = BinaryFinder(TestHelper.testdata_dir, ReadElf(TestHelper.ndk_path)) 179*288bf522SAndroid Build Coastguard Worker addr2line = Addr2Nearestline(TestHelper.ndk_path, binary_finder, False) 180*288bf522SAndroid Build Coastguard Worker addr_map = addr2line.parse_line_output(output, dso) 181*288bf522SAndroid Build Coastguard Worker expected_addr_map = { 182*288bf522SAndroid Build Coastguard Worker 0x104c: [('system/extras/simpleperf/runtest/two_functions.cpp', 6)], 183*288bf522SAndroid Build Coastguard Worker 0x1094: [('system/extras/simpleperf/runtest/two_functions.cpp', 9)], 184*288bf522SAndroid Build Coastguard Worker 0x10bb: [('system/extras/simpleperf/runtest/two_functions.cpp', 11)], 185*288bf522SAndroid Build Coastguard Worker 0x10bc: [('system/extras/simpleperf/runtest/two_functions.cpp', 13)], 186*288bf522SAndroid Build Coastguard Worker 0x1104: [('system/extras/simpleperf/runtest/two_functions.cpp', 16)], 187*288bf522SAndroid Build Coastguard Worker 0x112b: [('system/extras/simpleperf/runtest/two_functions.cpp', 18)], 188*288bf522SAndroid Build Coastguard Worker 0x112c: [('system/extras/simpleperf/runtest/two_functions.cpp', 20)], 189*288bf522SAndroid Build Coastguard Worker 0x113c: [('system/extras/simpleperf/runtest/two_functions.cpp', 22)], 190*288bf522SAndroid Build Coastguard Worker 0x1140: [('system/extras/simpleperf/runtest/two_functions.cpp', 23)], 191*288bf522SAndroid Build Coastguard Worker 0x1147: [('system/extras/simpleperf/runtest/two_functions.cpp', 21)], 192*288bf522SAndroid Build Coastguard Worker } 193*288bf522SAndroid Build Coastguard Worker self.assertEqual(len(expected_addr_map), len(addr_map)) 194*288bf522SAndroid Build Coastguard Worker for addr in expected_addr_map: 195*288bf522SAndroid Build Coastguard Worker expected_source_list = expected_addr_map[addr] 196*288bf522SAndroid Build Coastguard Worker source_list = addr_map[addr] 197*288bf522SAndroid Build Coastguard Worker self.assertEqual(len(expected_source_list), len(source_list)) 198*288bf522SAndroid Build Coastguard Worker for expected_source, source in zip(expected_source_list, source_list): 199*288bf522SAndroid Build Coastguard Worker file_path = dso.file_id_to_name[source[0]] 200*288bf522SAndroid Build Coastguard Worker self.assertEqual(file_path, expected_source[0]) 201*288bf522SAndroid Build Coastguard Worker self.assertEqual(source[1], expected_source[1]) 202*288bf522SAndroid Build Coastguard Worker 203*288bf522SAndroid Build Coastguard Worker def test_objdump(self): 204*288bf522SAndroid Build Coastguard Worker test_map = { 205*288bf522SAndroid Build Coastguard Worker '/simpleperf_runtest_two_functions_arm64': { 206*288bf522SAndroid Build Coastguard Worker 'start_addr': 0x112c, 207*288bf522SAndroid Build Coastguard Worker 'len': 28, 208*288bf522SAndroid Build Coastguard Worker 'expected_items': [ 209*288bf522SAndroid Build Coastguard Worker ('main', 0), 210*288bf522SAndroid Build Coastguard Worker ('two_functions.cpp:20', 0), 211*288bf522SAndroid Build Coastguard Worker ('1134: add x29, sp, #0x10', 0x1134), 212*288bf522SAndroid Build Coastguard Worker ], 213*288bf522SAndroid Build Coastguard Worker }, 214*288bf522SAndroid Build Coastguard Worker '/simpleperf_runtest_two_functions_arm': { 215*288bf522SAndroid Build Coastguard Worker 'start_addr': 0x1304, 216*288bf522SAndroid Build Coastguard Worker 'len': 40, 217*288bf522SAndroid Build Coastguard Worker 'expected_items': [ 218*288bf522SAndroid Build Coastguard Worker ('main', 0), 219*288bf522SAndroid Build Coastguard Worker ('two_functions.cpp:20', 0), 220*288bf522SAndroid Build Coastguard Worker ('1318: bne 0x1312 <main+0xe>', 0x1318), 221*288bf522SAndroid Build Coastguard Worker ], 222*288bf522SAndroid Build Coastguard Worker }, 223*288bf522SAndroid Build Coastguard Worker '/simpleperf_runtest_two_functions_x86_64': { 224*288bf522SAndroid Build Coastguard Worker 'start_addr': 0x19e0, 225*288bf522SAndroid Build Coastguard Worker 'len': 151, 226*288bf522SAndroid Build Coastguard Worker 'expected_items': [ 227*288bf522SAndroid Build Coastguard Worker ('main', 0), 228*288bf522SAndroid Build Coastguard Worker ('two_functions.cpp:20', 0), 229*288bf522SAndroid Build Coastguard Worker (r'19f0: movl %eax, 0x2462(%rip)', 0x19f0), 230*288bf522SAndroid Build Coastguard Worker ], 231*288bf522SAndroid Build Coastguard Worker }, 232*288bf522SAndroid Build Coastguard Worker '/simpleperf_runtest_two_functions_x86': { 233*288bf522SAndroid Build Coastguard Worker 'start_addr': 0x16e0, 234*288bf522SAndroid Build Coastguard Worker 'len': 65, 235*288bf522SAndroid Build Coastguard Worker 'expected_items': [ 236*288bf522SAndroid Build Coastguard Worker ('main', 0), 237*288bf522SAndroid Build Coastguard Worker ('two_functions.cpp:20', 0), 238*288bf522SAndroid Build Coastguard Worker (r'16f7: cmpl $0x5f5e100, %ecx', 0x16f7), 239*288bf522SAndroid Build Coastguard Worker ], 240*288bf522SAndroid Build Coastguard Worker }, 241*288bf522SAndroid Build Coastguard Worker } 242*288bf522SAndroid Build Coastguard Worker binary_finder = BinaryFinder(TestHelper.testdata_dir, ReadElf(TestHelper.ndk_path)) 243*288bf522SAndroid Build Coastguard Worker objdump = Objdump(TestHelper.ndk_path, binary_finder) 244*288bf522SAndroid Build Coastguard Worker for dso_path in test_map: 245*288bf522SAndroid Build Coastguard Worker dso = test_map[dso_path] 246*288bf522SAndroid Build Coastguard Worker dso_info = objdump.get_dso_info(dso_path, None) 247*288bf522SAndroid Build Coastguard Worker self.assertIsNotNone(dso_info, dso_path) 248*288bf522SAndroid Build Coastguard Worker addr_range = AddrRange(dso['start_addr'], dso['len']) 249*288bf522SAndroid Build Coastguard Worker disassembly = objdump.disassemble_function(dso_info, addr_range) 250*288bf522SAndroid Build Coastguard Worker self.assertTrue(disassembly, dso_path) 251*288bf522SAndroid Build Coastguard Worker self._check_disassembly(disassembly, dso_path, dso) 252*288bf522SAndroid Build Coastguard Worker 253*288bf522SAndroid Build Coastguard Worker result = objdump.disassemble_functions(dso_info, [addr_range]) 254*288bf522SAndroid Build Coastguard Worker self.assertTrue(result, dso_path) 255*288bf522SAndroid Build Coastguard Worker self.assertEqual(len(result), 1) 256*288bf522SAndroid Build Coastguard Worker self._check_disassembly(result[0], dso_path, dso) 257*288bf522SAndroid Build Coastguard Worker 258*288bf522SAndroid Build Coastguard Worker def _check_disassembly(self, disassembly: Disassembly, dso_path: str, dso) -> None: 259*288bf522SAndroid Build Coastguard Worker disassemble_code = disassembly.lines 260*288bf522SAndroid Build Coastguard Worker i = 0 261*288bf522SAndroid Build Coastguard Worker for expected_line, expected_addr in dso['expected_items']: 262*288bf522SAndroid Build Coastguard Worker found = False 263*288bf522SAndroid Build Coastguard Worker while i < len(disassemble_code): 264*288bf522SAndroid Build Coastguard Worker line, addr = disassemble_code[i] 265*288bf522SAndroid Build Coastguard Worker if addr == expected_addr and expected_line in line: 266*288bf522SAndroid Build Coastguard Worker found = True 267*288bf522SAndroid Build Coastguard Worker i += 1 268*288bf522SAndroid Build Coastguard Worker break 269*288bf522SAndroid Build Coastguard Worker i += 1 270*288bf522SAndroid Build Coastguard Worker if not found: 271*288bf522SAndroid Build Coastguard Worker s = '\n'.join('%s:0x%x' % item for item in disassemble_code) 272*288bf522SAndroid Build Coastguard Worker self.fail('for %s, %s:0x%x not found in disassemble code:\n%s' % 273*288bf522SAndroid Build Coastguard Worker (dso_path, expected_line, expected_addr, s)) 274*288bf522SAndroid Build Coastguard Worker 275*288bf522SAndroid Build Coastguard Worker def test_objdump_parse_disassembly_for_functions(self): 276*288bf522SAndroid Build Coastguard Worker # Parse kernel disassembly. 277*288bf522SAndroid Build Coastguard Worker s = """ 278*288bf522SAndroid Build Coastguard Workerffffffc008000000 <_text>: 279*288bf522SAndroid Build Coastguard Worker; _text(): 280*288bf522SAndroid Build Coastguard Worker; arch/arm64/kernel/head.S:60 281*288bf522SAndroid Build Coastguard Workerffffffc008000000: ccmp x18, #0x0, #0xd, pl 282*288bf522SAndroid Build Coastguard Workerffffffc008000004: b 0xffffffc009b2a37c <primary_entry> 283*288bf522SAndroid Build Coastguard Worker 284*288bf522SAndroid Build Coastguard Workerffffffc008000008 <$d.1>: 285*288bf522SAndroid Build Coastguard Workerffffffc008000008: 00 00 00 00 .word 0x00000000 286*288bf522SAndroid Build Coastguard Workerffffffc0089bbb30 <readl>: 287*288bf522SAndroid Build Coastguard Worker; readl(): 288*288bf522SAndroid Build Coastguard Worker; include/asm-generic/io.h:218 289*288bf522SAndroid Build Coastguard Workerffffffc0089bbb30: paciasp 290*288bf522SAndroid Build Coastguard Workerffffffc0089bbb34: stp x29, x30, [sp, #-0x30]! 291*288bf522SAndroid Build Coastguard Worker """ 292*288bf522SAndroid Build Coastguard Worker addr_ranges = [AddrRange(0xffffffc008000000, 8), 293*288bf522SAndroid Build Coastguard Worker AddrRange(0xffffffc008000010, 10), 294*288bf522SAndroid Build Coastguard Worker AddrRange(0xffffffc0089bbb30, 20)] 295*288bf522SAndroid Build Coastguard Worker binary_finder = BinaryFinder(TestHelper.testdata_dir, ReadElf(TestHelper.ndk_path)) 296*288bf522SAndroid Build Coastguard Worker objdump = Objdump(TestHelper.ndk_path, binary_finder) 297*288bf522SAndroid Build Coastguard Worker result = objdump._parse_disassembly_for_functions(io.StringIO(s), addr_ranges) 298*288bf522SAndroid Build Coastguard Worker self.assertEqual(len(result), 3) 299*288bf522SAndroid Build Coastguard Worker self.assertEqual( 300*288bf522SAndroid Build Coastguard Worker result[0].lines, 301*288bf522SAndroid Build Coastguard Worker [('ffffffc008000000 <_text>:', 0xffffffc008000000), 302*288bf522SAndroid Build Coastguard Worker ('; _text():', 0), 303*288bf522SAndroid Build Coastguard Worker ('; arch/arm64/kernel/head.S:60', 0), 304*288bf522SAndroid Build Coastguard Worker ('ffffffc008000000: ccmp x18, #0x0, #0xd, pl', 0xffffffc008000000), 305*288bf522SAndroid Build Coastguard Worker ('ffffffc008000004: b 0xffffffc009b2a37c <primary_entry>', 306*288bf522SAndroid Build Coastguard Worker 0xffffffc008000004), 307*288bf522SAndroid Build Coastguard Worker ('', 0)]) 308*288bf522SAndroid Build Coastguard Worker self.assertEqual(len(result[1].lines), 0) 309*288bf522SAndroid Build Coastguard Worker self.assertEqual(result[2].lines, [ 310*288bf522SAndroid Build Coastguard Worker ('ffffffc0089bbb30 <readl>:', 0xffffffc0089bbb30), 311*288bf522SAndroid Build Coastguard Worker ('; readl():', 0), 312*288bf522SAndroid Build Coastguard Worker ('; include/asm-generic/io.h:218', 0), 313*288bf522SAndroid Build Coastguard Worker ('ffffffc0089bbb30: paciasp', 0xffffffc0089bbb30), 314*288bf522SAndroid Build Coastguard Worker ('ffffffc0089bbb34: stp x29, x30, [sp, #-0x30]!', 0xffffffc0089bbb34), 315*288bf522SAndroid Build Coastguard Worker ('', 0)]) 316*288bf522SAndroid Build Coastguard Worker 317*288bf522SAndroid Build Coastguard Worker # Parse user space library disassembly. 318*288bf522SAndroid Build Coastguard Worker s = """ 319*288bf522SAndroid Build Coastguard Worker0000000000200000 <art::gc::collector::ConcurrentCopying::ProcessMarkStack()>: 320*288bf522SAndroid Build Coastguard Worker; art::gc::collector::ConcurrentCopying::ProcessMarkStack(): 321*288bf522SAndroid Build Coastguard Worker; art/runtime/gc/collector/concurrent_copying.cc:2121 322*288bf522SAndroid Build Coastguard Worker 200000: stp x29, x30, [sp, #-0x20]! 323*288bf522SAndroid Build Coastguard Worker 200004: stp x20, x19, [sp, #0x10] 324*288bf522SAndroid Build Coastguard Worker """ 325*288bf522SAndroid Build Coastguard Worker addr_ranges = [AddrRange(0x200000, 8)] 326*288bf522SAndroid Build Coastguard Worker result = objdump._parse_disassembly_for_functions(io.StringIO(s), addr_ranges) 327*288bf522SAndroid Build Coastguard Worker self.assertEqual(len(result), 1) 328*288bf522SAndroid Build Coastguard Worker self.assertEqual(result[0].lines, [ 329*288bf522SAndroid Build Coastguard Worker ('0000000000200000 <art::gc::collector::ConcurrentCopying::ProcessMarkStack()>:', 330*288bf522SAndroid Build Coastguard Worker 0x200000), 331*288bf522SAndroid Build Coastguard Worker ('; art::gc::collector::ConcurrentCopying::ProcessMarkStack():', 0), 332*288bf522SAndroid Build Coastguard Worker ('; art/runtime/gc/collector/concurrent_copying.cc:2121', 0), 333*288bf522SAndroid Build Coastguard Worker (' 200000: stp x29, x30, [sp, #-0x20]!', 0x200000), 334*288bf522SAndroid Build Coastguard Worker (' 200004: stp x20, x19, [sp, #0x10]', 0x200004), 335*288bf522SAndroid Build Coastguard Worker ('', 0)]) 336*288bf522SAndroid Build Coastguard Worker 337*288bf522SAndroid Build Coastguard Worker def test_readelf(self): 338*288bf522SAndroid Build Coastguard Worker test_map = { 339*288bf522SAndroid Build Coastguard Worker 'simpleperf_runtest_two_functions_arm64': { 340*288bf522SAndroid Build Coastguard Worker 'arch': 'arm64', 341*288bf522SAndroid Build Coastguard Worker 'build_id': '0xb4f1b49b0fe9e34e78fb14e5374c930c00000000', 342*288bf522SAndroid Build Coastguard Worker 'sections': ['.note.gnu.build-id', '.dynsym', '.text', '.rodata', '.eh_frame', 343*288bf522SAndroid Build Coastguard Worker '.eh_frame_hdr', '.debug_info', '.debug_line', '.symtab'], 344*288bf522SAndroid Build Coastguard Worker }, 345*288bf522SAndroid Build Coastguard Worker 'simpleperf_runtest_two_functions_arm': { 346*288bf522SAndroid Build Coastguard Worker 'arch': 'arm', 347*288bf522SAndroid Build Coastguard Worker 'build_id': '0x6b5c2ee980465d306b580c5a8bc9767f00000000', 348*288bf522SAndroid Build Coastguard Worker }, 349*288bf522SAndroid Build Coastguard Worker 'simpleperf_runtest_two_functions_x86_64': { 350*288bf522SAndroid Build Coastguard Worker 'arch': 'x86_64', 351*288bf522SAndroid Build Coastguard Worker }, 352*288bf522SAndroid Build Coastguard Worker 'simpleperf_runtest_two_functions_x86': { 353*288bf522SAndroid Build Coastguard Worker 'arch': 'x86', 354*288bf522SAndroid Build Coastguard Worker } 355*288bf522SAndroid Build Coastguard Worker } 356*288bf522SAndroid Build Coastguard Worker readelf = ReadElf(TestHelper.ndk_path) 357*288bf522SAndroid Build Coastguard Worker for dso_path in test_map: 358*288bf522SAndroid Build Coastguard Worker dso_info = test_map[dso_path] 359*288bf522SAndroid Build Coastguard Worker path = os.path.join(TestHelper.testdata_dir, dso_path) 360*288bf522SAndroid Build Coastguard Worker self.assertEqual(dso_info['arch'], readelf.get_arch(path)) 361*288bf522SAndroid Build Coastguard Worker if 'build_id' in dso_info: 362*288bf522SAndroid Build Coastguard Worker self.assertEqual(dso_info['build_id'], readelf.get_build_id(path), dso_path) 363*288bf522SAndroid Build Coastguard Worker if 'sections' in dso_info: 364*288bf522SAndroid Build Coastguard Worker sections = readelf.get_sections(path) 365*288bf522SAndroid Build Coastguard Worker for section in dso_info['sections']: 366*288bf522SAndroid Build Coastguard Worker self.assertIn(section, sections) 367*288bf522SAndroid Build Coastguard Worker self.assertEqual(readelf.get_arch('not_exist_file'), 'unknown') 368*288bf522SAndroid Build Coastguard Worker self.assertEqual(readelf.get_build_id('not_exist_file'), '') 369*288bf522SAndroid Build Coastguard Worker self.assertEqual(readelf.get_sections('not_exist_file'), []) 370*288bf522SAndroid Build Coastguard Worker 371*288bf522SAndroid Build Coastguard Worker def test_source_file_searcher(self): 372*288bf522SAndroid Build Coastguard Worker searcher = SourceFileSearcher( 373*288bf522SAndroid Build Coastguard Worker [TestHelper.testdata_path('SimpleperfExampleCpp'), 374*288bf522SAndroid Build Coastguard Worker TestHelper.testdata_path('SimpleperfExampleKotlin')]) 375*288bf522SAndroid Build Coastguard Worker 376*288bf522SAndroid Build Coastguard Worker def format_path(path): 377*288bf522SAndroid Build Coastguard Worker return os.path.join(TestHelper.testdata_dir, path.replace('/', os.sep)) 378*288bf522SAndroid Build Coastguard Worker # Find a C++ file with pure file name. 379*288bf522SAndroid Build Coastguard Worker self.assertEqual( 380*288bf522SAndroid Build Coastguard Worker format_path('SimpleperfExampleCpp/app/src/main/cpp/native-lib.cpp'), 381*288bf522SAndroid Build Coastguard Worker searcher.get_real_path('native-lib.cpp')) 382*288bf522SAndroid Build Coastguard Worker # Find a C++ file with an absolute file path. 383*288bf522SAndroid Build Coastguard Worker self.assertEqual( 384*288bf522SAndroid Build Coastguard Worker format_path('SimpleperfExampleCpp/app/src/main/cpp/native-lib.cpp'), 385*288bf522SAndroid Build Coastguard Worker searcher.get_real_path('/data/native-lib.cpp')) 386*288bf522SAndroid Build Coastguard Worker # Find a Java file. 387*288bf522SAndroid Build Coastguard Worker self.assertEqual( 388*288bf522SAndroid Build Coastguard Worker format_path( 389*288bf522SAndroid Build Coastguard Worker 'SimpleperfExampleCpp/app/src/main/java/simpleperf/example/cpp/MainActivity.java'), 390*288bf522SAndroid Build Coastguard Worker searcher.get_real_path('cpp/MainActivity.java')) 391*288bf522SAndroid Build Coastguard Worker # Find a Kotlin file. 392*288bf522SAndroid Build Coastguard Worker self.assertEqual( 393*288bf522SAndroid Build Coastguard Worker format_path( 394*288bf522SAndroid Build Coastguard Worker 'SimpleperfExampleKotlin/app/src/main/java/simpleperf/example/kotlin/' + 395*288bf522SAndroid Build Coastguard Worker 'MainActivity.kt'), 396*288bf522SAndroid Build Coastguard Worker searcher.get_real_path('MainActivity.kt')) 397*288bf522SAndroid Build Coastguard Worker 398*288bf522SAndroid Build Coastguard Worker def test_is_elf_file(self): 399*288bf522SAndroid Build Coastguard Worker self.assertTrue(ReadElf.is_elf_file(TestHelper.testdata_path( 400*288bf522SAndroid Build Coastguard Worker 'simpleperf_runtest_two_functions_arm'))) 401*288bf522SAndroid Build Coastguard Worker with open('not_elf', 'wb') as fh: 402*288bf522SAndroid Build Coastguard Worker fh.write(b'\x90123') 403*288bf522SAndroid Build Coastguard Worker try: 404*288bf522SAndroid Build Coastguard Worker self.assertFalse(ReadElf.is_elf_file('not_elf')) 405*288bf522SAndroid Build Coastguard Worker finally: 406*288bf522SAndroid Build Coastguard Worker remove('not_elf') 407*288bf522SAndroid Build Coastguard Worker 408*288bf522SAndroid Build Coastguard Worker def test_binary_finder(self): 409*288bf522SAndroid Build Coastguard Worker # Create binary_cache. 410*288bf522SAndroid Build Coastguard Worker binary_cache_builder = BinaryCacheBuilder(TestHelper.ndk_path, False) 411*288bf522SAndroid Build Coastguard Worker elf_name = 'simpleperf_runtest_two_functions_arm' 412*288bf522SAndroid Build Coastguard Worker elf_path = TestHelper.testdata_path(elf_name) 413*288bf522SAndroid Build Coastguard Worker readelf = ReadElf(TestHelper.ndk_path) 414*288bf522SAndroid Build Coastguard Worker build_id = readelf.get_build_id(elf_path) 415*288bf522SAndroid Build Coastguard Worker self.assertGreater(len(build_id), 0) 416*288bf522SAndroid Build Coastguard Worker binary_cache_builder.binaries[elf_name] = build_id 417*288bf522SAndroid Build Coastguard Worker 418*288bf522SAndroid Build Coastguard Worker filename_without_build_id = '/data/symfs_without_build_id/elf' 419*288bf522SAndroid Build Coastguard Worker binary_cache_builder.binaries[filename_without_build_id] = '' 420*288bf522SAndroid Build Coastguard Worker 421*288bf522SAndroid Build Coastguard Worker binary_cache_builder.copy_binaries_from_symfs_dirs([TestHelper.testdata_dir]) 422*288bf522SAndroid Build Coastguard Worker binary_cache_builder.create_build_id_list() 423*288bf522SAndroid Build Coastguard Worker 424*288bf522SAndroid Build Coastguard Worker # Test BinaryFinder. 425*288bf522SAndroid Build Coastguard Worker path_in_binary_cache = binary_cache_builder.find_path_in_cache(elf_name) 426*288bf522SAndroid Build Coastguard Worker binary_finder = BinaryFinder(binary_cache_builder.binary_cache_dir, readelf) 427*288bf522SAndroid Build Coastguard Worker # Find binary using build id. 428*288bf522SAndroid Build Coastguard Worker path = binary_finder.find_binary('[not_exist_file]', build_id) 429*288bf522SAndroid Build Coastguard Worker self.assertEqual(path, path_in_binary_cache) 430*288bf522SAndroid Build Coastguard Worker # Find binary using path. 431*288bf522SAndroid Build Coastguard Worker path = binary_finder.find_binary(filename_without_build_id, None) 432*288bf522SAndroid Build Coastguard Worker self.assertIsNotNone(path) 433*288bf522SAndroid Build Coastguard Worker # Find binary using absolute path. 434*288bf522SAndroid Build Coastguard Worker path = binary_finder.find_binary(str(path_in_binary_cache), None) 435*288bf522SAndroid Build Coastguard Worker self.assertEqual(path, path_in_binary_cache) 436*288bf522SAndroid Build Coastguard Worker 437*288bf522SAndroid Build Coastguard Worker # The binary should has a matched build id. 438*288bf522SAndroid Build Coastguard Worker path = binary_finder.find_binary('/' + elf_name, 'wrong_build_id') 439*288bf522SAndroid Build Coastguard Worker self.assertIsNone(path) 440