Modified: trunk/Tools/ChangeLog (139262 => 139263)
--- trunk/Tools/ChangeLog 2013-01-10 01:40:44 UTC (rev 139262)
+++ trunk/Tools/ChangeLog 2013-01-10 01:56:23 UTC (rev 139263)
@@ -1,3 +1,38 @@
+2013-01-09 Eric Seidel <[email protected]>
+
+ run-perf-tests --chromium-android --profile should show symbols for the kernel
+ https://bugs.webkit.org/show_bug.cgi?id=106498
+
+ Reviewed by Adam Barth.
+
+ Turns out this was easy, once I finally read the output from "perf report".
+ It appears there may be a bug in "perf record" on android, as it complains
+ about not being able to read from /proc/kallsyms even when
+ /proc/sys/kernel/kptr_restrict is 0. For now I've not bothered
+ to keep /proc/sys/kernel/kptr_restrict as 0 during the actual record
+ but rather just flip it to 0 long enough to grab the /proc/kallsyms
+ and then flip it back to whatever the device had.
+
+ /proc/sys/kernel/kptr_restrict controls what /proc/kallsyms returns
+ on Linux. /proc/kallsyms contains a mapping of kernel addresses
+ to symbol names. Its world-readable, but will return all 0s if you
+ don't have permission to see the kernel symbols. kptr_restrict
+ supports values 0, 1, 2. Where 0 means "everyone can see the real symbols"
+ 1 is only a specific group, and 2 is "no one, not even root".
+ By default kptr_restrict is 2 on Android it seems.
+ More kptr_restrict docs: http://lwn.net/Articles/420403/
+
+ I also took this opportunity to clean up how the perf record command
+ was built for use/display in AndroidPerf.profile_after_exit and
+ change to always using long-form names for the arguments (to hopefully help readability).
+
+ * Scripts/webkitpy/layout_tests/port/chromium_android.py:
+ (AndroidPerf.__init__):
+ (profile_after_exit):
+ (ChromiumAndroidDriver.__init__):
+ (ChromiumAndroidDriver._update_kallsyms_cache):
+ * Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py:
+
2013-01-09 Julie Parent <[email protected]>
Dashboard cleanup: remove dead code.
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py (139262 => 139263)
--- trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py 2013-01-10 01:40:44 UTC (rev 139262)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py 2013-01-10 01:56:23 UTC (rev 139263)
@@ -64,6 +64,7 @@
DRT_LIBRARY_NAME = 'libDumpRenderTree.so'
SCALING_GOVERNORS_PATTERN = "/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor"
+KPTR_RESTRICT_PATH = "/proc/sys/kernel/kptr_restrict"
# All the test cases are still served to DumpRenderTree through file protocol,
# but we use a file-to-http feature to bridge the file request to host's http
@@ -363,12 +364,13 @@
_cached_perf_host_path = None
_have_searched_for_perf_host = False
- def __init__(self, host, executable_path, output_dir, adb_path, device_serial, symfs_path, identifier=None):
+ def __init__(self, host, executable_path, output_dir, adb_path, device_serial, symfs_path, kallsyms_path, identifier=None):
super(AndroidPerf, self).__init__(host, executable_path, output_dir, "data", identifier)
self._device_serial = device_serial
self._adb_command = [adb_path, '-s', self._device_serial]
self._perf_process = None
self._symfs_path = symfs_path
+ self._kallsyms_path = kallsyms_path
def check_configuration(self):
# Check that perf is installed
@@ -451,8 +453,14 @@
self._run_adb_command(['pull', '/data/perf.data', self._output_path])
perfhost_path = self._perfhost_path()
+ perfhost_report_command = [
+ 'report',
+ '--input', self._output_path,
+ '--symfs', self._symfs_path,
+ '--kallsyms', self._kallsyms_path,
+ ]
if perfhost_path:
- perfhost_args = [perfhost_path, 'report', '-g', 'none', '-i', self._output_path, '--symfs', self._symfs_path]
+ perfhost_args = [perfhost_path] + perfhost_report_command + ['--call-graph', 'none']
perf_output = self._host.executive.run_command(perfhost_args)
# We could save off the full -g report to a file if users found that useful.
print self._first_ten_lines_of_profile(perf_output)
@@ -473,7 +481,7 @@
perfhost_display_patch = perfhost_path if perfhost_path else 'perfhost_linux'
print "To view the full profile, run:"
- print ' '.join([perfhost_display_patch, 'report', '-i', self._output_path, '--symfs', self._symfs_path])
+ print ' '.join([perfhost_display_patch] + perfhost_report_command)
class ChromiumAndroidDriver(driver.Driver):
@@ -488,16 +496,19 @@
self._forwarder_process = None
self._has_setup = False
self._original_governors = {}
+ self._original_kptr_restrict = None
self._device_serial = port._get_device_serial(worker_number)
self._adb_command_base = None
# FIXME: If we taught ProfileFactory about "target" devices we could
# just use the logic in Driver instead of duplicating it here.
if self._port.get_option("profile"):
+ # FIXME: This should be done once, instead of per-driver!
symfs_path = self._find_or_create_symfs()
+ kallsyms_path = self._update_kallsyms_cache(symfs_path)
# FIXME: We should pass this some sort of "Bridge" object abstraction around ADB instead of a path/device pair.
self._profiler = AndroidPerf(self._port.host, self._port._path_to_driver(), self._port.results_directory(),
- self._port.path_to_adb(), self._device_serial, symfs_path)\
+ self._port.path_to_adb(), self._device_serial, symfs_path, kallsyms_path)
# FIXME: This is a layering violation and should be moved to Port.check_sys_deps
# once we have an abstraction around an adb_path/device_serial pair to make it
# easy to make these class methods on AndroidPerf.
@@ -511,6 +522,22 @@
self._teardown_performance()
super(ChromiumAndroidDriver, self).__del__()
+ def _update_kallsyms_cache(self, output_dir):
+ kallsyms_name = "%s-kallsyms" % self._device_serial
+ kallsyms_cache_path = self._port.host.filesystem.join(output_dir, kallsyms_name)
+
+ self._restart_adb_as_root()
+
+ saved_kptr_restrict = self._run_adb_command(['shell', 'cat', KPTR_RESTRICT_PATH]).strip()
+ self._run_adb_command(['shell', 'echo', '0', '>', KPTR_RESTRICT_PATH])
+
+ print "Updating kallsyms file (%s) from device" % kallsyms_cache_path
+ self._pull_from_device("/proc/kallsyms", kallsyms_cache_path)
+
+ self._run_adb_command(['shell', 'echo', saved_kptr_restrict, '>', KPTR_RESTRICT_PATH])
+
+ return kallsyms_cache_path
+
def _find_or_create_symfs(self):
environment = self._port.host.copy_current_environment()
env = environment.to_dictionary()
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py (139262 => 139263)
--- trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py 2013-01-10 01:40:44 UTC (rev 139262)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py 2013-01-10 01:56:23 UTC (rev 139263)
@@ -309,7 +309,7 @@
2.73% DumpRenderTree DumpRenderTree [.] WebCore::DocumentV8Internal::getElementsByTagNameCallback(v8::Arguments const&)
"""
host = MockSystemHost()
- profiler = chromium_android.AndroidPerf(host, '/bin/executable', '/tmp/output', 'adb-path', 'device-serial', 'foo')
+ profiler = chromium_android.AndroidPerf(host, '/bin/executable', '/tmp/output', 'adb-path', 'device-serial', '/tmp/symfs', '/tmp/kallsyms', 'foo')
self.assertEqual(profiler._first_ten_lines_of_profile(perf_output), expected_first_ten_lines)