summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2019-09-18 00:31:37 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2019-09-18 00:31:37 +0000
commitf0988974b003b7dee4be811412dfbf1f08fc0b4f (patch)
tree6a68e41794bb6b1e4d9e2c971858a44a402346b6
parent939a46d25c6e64f2acb9790c942a2c026557f912 (diff)
parent33f5f32d4c1a0d2d59bd9b92b5d8a878f297283e (diff)
downloadextras-f0988974b003b7dee4be811412dfbf1f08fc0b4f.tar.gz
Merge "simpleperf: use path in binary_cache in pprof_proto_generator.py."
-rwxr-xr-xsimpleperf/scripts/pprof_proto_generator.py69
-rwxr-xr-xsimpleperf/scripts/test.py7
-rw-r--r--simpleperf/scripts/utils.py2
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):