diff options
author | Yabin Cui <yabinc@google.com> | 2019-09-18 00:31:37 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-09-18 00:31:37 +0000 |
commit | f0988974b003b7dee4be811412dfbf1f08fc0b4f (patch) | |
tree | 6a68e41794bb6b1e4d9e2c971858a44a402346b6 | |
parent | 939a46d25c6e64f2acb9790c942a2c026557f912 (diff) | |
parent | 33f5f32d4c1a0d2d59bd9b92b5d8a878f297283e (diff) | |
download | extras-f0988974b003b7dee4be811412dfbf1f08fc0b4f.tar.gz |
Merge "simpleperf: use path in binary_cache in pprof_proto_generator.py."
-rwxr-xr-x | simpleperf/scripts/pprof_proto_generator.py | 69 | ||||
-rwxr-xr-x | simpleperf/scripts/test.py | 7 | ||||
-rw-r--r-- | simpleperf/scripts/utils.py | 2 |
3 files changed, 46 insertions, 32 deletions
diff --git a/simpleperf/scripts/pprof_proto_generator.py b/simpleperf/scripts/pprof_proto_generator.py index fc3ef357..2a4e1d2a 100755 --- a/simpleperf/scripts/pprof_proto_generator.py +++ b/simpleperf/scripts/pprof_proto_generator.py @@ -281,7 +281,9 @@ class PprofProfileGenerator(object): self.mapping_list = [] self.function_map = {} self.function_list = [] - self.build_id_map = {} # map from filename to build_id + + # Map from dso_name in perf.data to (binary path, build_id). + self.binary_map = {} self.read_elf = ReadElf(self.config['ndk_path']) def gen(self): @@ -375,10 +377,10 @@ class PprofProfileGenerator(object): return sample_type_id def get_location_id(self, ip, symbol): - mapping_id = self.get_mapping_id(symbol.mapping[0], symbol.dso_name) + binary_path, build_id = self.get_binary(symbol.dso_name) + mapping_id = self.get_mapping_id(symbol.mapping[0], binary_path, build_id) location = Location(mapping_id, ip, symbol.vaddr_in_file) - function_id = self.get_function_id(symbol.symbol_name, symbol.dso_name, - symbol.symbol_addr) + function_id = self.get_function_id(symbol.symbol_name, binary_path, symbol.symbol_addr) if function_id: # Add Line only when it has a valid function id, see http://b/36988814. # Default line info only contains the function name @@ -395,9 +397,8 @@ class PprofProfileGenerator(object): self.location_map[location.key] = location return location.id - def get_mapping_id(self, report_mapping, filename): + def get_mapping_id(self, report_mapping, filename, build_id): filename_id = self.get_string_id(filename) - build_id = self.get_build_id(filename) build_id_id = self.get_string_id(build_id) mapping = Mapping(report_mapping.start, report_mapping.end, report_mapping.pgoff, filename_id, build_id_id) @@ -410,28 +411,36 @@ class PprofProfileGenerator(object): self.mapping_map[mapping.key] = mapping return mapping.id - def get_build_id(self, filename): - build_id = self.build_id_map.get(filename) - if build_id is None: - build_id = '' - # The build ids in perf.data are padded to 20 bytes, but pprof needs without padding. - # So read build id from the binary in binary_cache, and check it with build id in - # perf.data. - build_id_in_perf_data = self.lib.GetBuildIdForPath(filename) - if build_id_in_perf_data: - elf_path = find_real_dso_path(filename, self.config['binary_cache_dir']) - if elf_path: - elf_build_id = self.read_elf.get_build_id(elf_path, False) - if build_id_in_perf_data == self.read_elf.pad_build_id(elf_build_id): - build_id = elf_build_id - if not build_id and build_id_in_perf_data.startswith('0x'): - # Fallback to the way used by TrimZeroesFromBuildIDString() in quipper. - build_id = build_id_in_perf_data[2:] # remove '0x' - padding = '0' * 8 - while build_id.endswith(padding): - build_id = build_id[:-len(padding)] - self.build_id_map[filename] = build_id - return build_id + def get_binary(self, dso_name): + """ Return (binary_path, build_id) for a given dso_name. """ + value = self.binary_map.get(dso_name) + if value: + return value + + binary_path = dso_name + build_id = '' + + # The build ids in perf.data are padded to 20 bytes, but pprof needs without padding. + # So read build id from the binary in binary_cache, and check it with build id in + # perf.data. + build_id_in_perf_data = self.lib.GetBuildIdForPath(dso_name) + if build_id_in_perf_data: + # Try elf_path in binary cache. + elf_path = find_real_dso_path(dso_name, self.config['binary_cache_dir']) + if elf_path: + elf_build_id = self.read_elf.get_build_id(elf_path, False) + if build_id_in_perf_data == self.read_elf.pad_build_id(elf_build_id): + build_id = elf_build_id + binary_path = elf_path + + if not build_id and build_id_in_perf_data.startswith('0x'): + # Fallback to the way used by TrimZeroesFromBuildIDString() in quipper. + build_id = build_id_in_perf_data[2:] # remove '0x' + padding = '0' * 8 + while build_id.endswith(padding): + build_id = build_id[:-len(padding)] + self.binary_map[dso_name] = (binary_path, build_id) + return (binary_path, build_id) def get_mapping(self, mapping_id): return self.mapping_list[mapping_id - 1] if mapping_id > 0 else None @@ -468,7 +477,9 @@ class PprofProfileGenerator(object): if not find_tool_path('llvm-symbolizer', self.config['ndk_path']): log_info("Can't generate line information because can't find llvm-symbolizer.") return - addr2line = Addr2Nearestline(self.config['ndk_path'], self.config['binary_cache_dir'], True) + # We have changed dso names to paths in binary_cache in self.get_binary(). So no need to + # pass binary_cache_dir to addr2line. + addr2line = Addr2Nearestline(self.config['ndk_path'], None, True) # 2. Put all needed addresses to it. for location in self.location_list: diff --git a/simpleperf/scripts/test.py b/simpleperf/scripts/test.py index c5ecd93e..91f5f044 100755 --- a/simpleperf/scripts/test.py +++ b/simpleperf/scripts/test.py @@ -578,8 +578,13 @@ class TestExampleWithNative(TestExampleBase): "__start_thread"]) def test_pprof_proto_generator(self): + check_strings_with_lines = [ + "native-lib.cpp", + "BusyLoopThread", + # Check if dso name in perf.data is replaced by binary path in binary_cache. + 'filename: binary_cache/data/app/com.example.simpleperf.simpleperfexamplewithnative-'] self.common_test_pprof_proto_generator( - check_strings_with_lines=["native-lib.cpp", "BusyLoopThread"], + check_strings_with_lines, check_strings_without_lines=["BusyLoopThread"]) def test_inferno(self): diff --git a/simpleperf/scripts/utils.py b/simpleperf/scripts/utils.py index 4e2855e3..e0d40b24 100644 --- a/simpleperf/scripts/utils.py +++ b/simpleperf/scripts/utils.py @@ -380,8 +380,6 @@ def is_elf_file(path): def find_real_dso_path(dso_path_in_record_file, binary_cache_path): """ Given the path of a shared library in perf.data, find its real path in the file system. """ - if dso_path_in_record_file[0] != '/' or dso_path_in_record_file == '//anon': - return None if binary_cache_path: tmp_path = os.path.join(binary_cache_path, dso_path_in_record_file[1:]) if is_elf_file(tmp_path): |