Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1863)

Unified Diff: build/android/pylib/linker/test_case.py

Issue 23717023: Android: Add chrome-specific dynamic linker. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update content_tests.gypi Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « build/android/pylib/linker/setup.py ('k') | build/java_apk.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: build/android/pylib/linker/test_case.py
diff --git a/build/android/pylib/linker/test_case.py b/build/android/pylib/linker/test_case.py
index b8a256676341f90169677342d5c8983e293566ce..3f8ea73212be91eaeedff3d781fe591e4b8dd484 100644
--- a/build/android/pylib/linker/test_case.py
+++ b/build/android/pylib/linker/test_case.py
@@ -42,6 +42,7 @@ import subprocess
import tempfile
import time
+from pylib import constants
from pylib import android_commands
from pylib import flag_changer
from pylib.base import base_test_result
@@ -52,6 +53,17 @@ _PACKAGE_NAME='org.chromium.content_linker_test_apk'
_ACTIVITY_NAME='.ContentLinkerTestActivity'
_COMMAND_LINE_FILE='/data/local/tmp/content-linker-test-command-line'
+# Path to the Linker.java source file.
+_LINKER_JAVA_SOURCE_PATH = \
+ 'content/public/android/java/src/org/chromium/content/app/Linker.java'
+
+# A regular expression used to extract the browser shared RELRO configuration
+# from the Java source file above.
+_RE_LINKER_BROWSER_CONFIG = \
+ re.compile(r'.*BROWSER_SHARED_RELRO_CONFIG\s+=\s+' + \
+ 'BROWSER_SHARED_RELRO_CONFIG_(\S+)\s*;.*',
+ re.MULTILINE | re.DOTALL)
+
# Logcat filters used during each test. Only the 'chromium' one is really
# needed, but the logs are added to the TestResult in case of error, and
# it is handy to have the 'content_android_linker' ones as well when
@@ -67,6 +79,38 @@ re_library_address = re.compile(
r'(BROWSER|RENDERER)_LIBRARY_ADDRESS: (\S+) ([0-9A-Fa-f]+)')
+def _GetBrowserSharedRelroConfig():
+ """Returns a string corresponding to the Linker's configuration of shared
+ RELRO sections in the browser process. This parses the Java linker source
+ file to get the appropriate information.
+ Return:
+ None in case of error (e.g. could not locate the source file).
+ 'NEVER' if the browser process shall never use shared RELROs.
+ 'LOW_RAM_ONLY' if if uses it only on low-end devices.
+ 'ALWAYS' if it always uses a shared RELRO.
+ """
+ source_path = \
+ os.path.join(constants.DIR_SOURCE_ROOT, _LINKER_JAVA_SOURCE_PATH)
+ if not os.path.exists(source_path):
+ logging.error('Could not find linker source file: ' + source_path)
+ return None
+
+ with open(source_path) as f:
+ configs = _RE_LINKER_BROWSER_CONFIG.findall(f.read())
+ if not configs:
+ logging.error(
+ 'Can\'t find browser shared RELRO configuration value in ' + \
+ source_path)
+ return None
+
+ if configs[0] not in ['NEVER', 'LOW_RAM_ONLY', 'ALWAYS']:
+ logging.error('Unexpected browser config value: ' + configs[0])
+ return None
+
+ logging.info('Found linker browser shared RELRO config: ' + configs[0])
+ return configs[0]
+
+
def _WriteCommandLineFile(adb, command_line, command_line_file):
"""Create a command-line file on the device. This does not use FlagChanger
because its implementation assumes the device has 'su', and thus does
@@ -401,10 +445,14 @@ class LinkerLibraryAddressTest(LinkerTestCaseBase):
logging.error('Renderer libraries loaded at high addresses: %s', bad_libs)
return ResultType.FAIL, logs
- if self.is_low_memory:
- # For low-memory devices, the libraries must all be loaded at the same
- # addresses. This also implicitly checks that the browser libraries are at
- # low addresses.
+ browser_config = _GetBrowserSharedRelroConfig()
+ if not browser_config:
+ return ResultType.FAIL, 'Bad linker source configuration'
+
+ if browser_config == 'ALWAYS' or \
+ (browser_config == 'LOW_RAM_ONLY' and self.is_low_memory):
+ # The libraries must all be loaded at the same addresses. This also
+ # implicitly checks that the browser libraries are at low addresses.
addr_mismatches = []
for lib_name, lib_address in browser_libs.iteritems():
lib_address2 = renderer_libs[lib_name]
@@ -416,10 +464,10 @@ class LinkerLibraryAddressTest(LinkerTestCaseBase):
addr_mismatches)
return ResultType.FAIL, logs
- # For regular devices, check that libraries are loaded at 'high-addresses'.
+ # Otherwise, check that libraries are loaded at 'high-addresses'.
# Note that for low-memory devices, the previous checks ensure that they
# were loaded at low-addresses.
- if not self.is_low_memory:
+ else:
bad_libs = []
for lib_name, lib_address in browser_libs.iteritems():
if lib_address < memory_boundary:
@@ -473,9 +521,14 @@ class LinkerRandomizationTest(LinkerTestCaseBase):
renderer_status, renderer_logs = _CheckLoadAddressRandomization(
renderer_lib_map_list, 'Renderer')
+ browser_config = _GetBrowserSharedRelroConfig()
+ if not browser_config:
+ return ResultType.FAIL, 'Bad linker source configuration'
+
if not browser_status:
- if self.is_low_memory:
- return ResultType.FAIL, browser_logs
+ if browser_config == 'ALWAYS' or \
+ (browser_config == 'LOW_RAM_ONLY' and self.is_low_memory):
+ return ResultType.FAIL, browser_logs
# IMPORTANT NOTE: The system's ASLR implementation seems to be very poor
# when starting an activity process in a loop with "adb shell am start".
@@ -501,3 +554,67 @@ class LinkerRandomizationTest(LinkerTestCaseBase):
return ResultType.FAIL, renderer_logs
return ResultType.PASS, logs
+
+
+class LinkerLowMemoryThresholdTest(LinkerTestCaseBase):
+ """This test checks that the definitions for the low-memory device physical
+ RAM threshold are identical in the base/ and linker sources. Because these
+ two components should absolutely not depend on each other, it's difficult
+ to perform this check correctly at runtime inside the linker test binary
+ without introducing hairy dependency issues in the build, or complicated
+ plumbing at runtime.
+
+ To work-around this, this test looks directly into the sources for a
+ definition of the same constant that should look like:
+
+ #define ANDROID_LOW_MEMORY_DEVICE_THRESHOLD_MB <number>
+
+ And will check that the values for <number> are identical in all of
+ them."""
+
+ # A regular expression used to find the definition of the threshold in all
+ # sources:
+ _RE_THRESHOLD_DEFINITION = re.compile(
+ r'^\s*#\s*define\s+ANDROID_LOW_MEMORY_DEVICE_THRESHOLD_MB\s+(\d+)\s*$',
+ re.MULTILINE)
+
+ # The list of source files, relative to DIR_SOURCE_ROOT, which must contain
+ # a line that matches the re above.
+ _SOURCES_LIST = [
+ 'base/android/sys_utils.cc',
+ 'content/common/android/linker/linker_jni.cc' ]
+
+ def _RunTest(self, adb):
+ failure = False
+ values = []
+ # First, collect all the values in all input sources.
+ re = LinkerLowMemoryThresholdTest._RE_THRESHOLD_DEFINITION
+ for source in LinkerLowMemoryThresholdTest._SOURCES_LIST:
+ source_path = os.path.join(constants.DIR_SOURCE_ROOT, source);
+ if not os.path.exists(source_path):
+ logging.error('Missing source file: ' + source_path)
+ failure = True
+ continue
+ with open(source_path) as f:
+ source_text = f.read()
+ # For some reason, re.match() never works here.
+ source_values = re.findall(source_text)
+ if not source_values:
+ logging.error('Missing low-memory threshold definition in ' + \
+ source_path)
+ logging.error('Source:\n%s\n' % source_text)
+ failure = True
+ continue
+ values += source_values
+
+ # Second, check that they are all the same.
+ if not failure:
+ for value in values[1:]:
+ if value != values[0]:
+ logging.error('Value mismatch: ' + repr(values))
+ failure = True
+
+ if failure:
+ return ResultType.FAIL, 'Incorrect low-end memory threshold definitions!'
+
+ return ResultType.PASS, ''
« no previous file with comments | « build/android/pylib/linker/setup.py ('k') | build/java_apk.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698