1*635a8641SAndroid Build Coastguard Worker# Copyright (c) 2012 The Chromium Authors. All rights reserved. 2*635a8641SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 3*635a8641SAndroid Build Coastguard Worker# found in the LICENSE file. 4*635a8641SAndroid Build Coastguard Worker 5*635a8641SAndroid Build Coastguard Worker# pylint: disable=R0201 6*635a8641SAndroid Build Coastguard Worker 7*635a8641SAndroid Build Coastguard Workerimport glob 8*635a8641SAndroid Build Coastguard Workerimport logging 9*635a8641SAndroid Build Coastguard Workerimport os.path 10*635a8641SAndroid Build Coastguard Workerimport subprocess 11*635a8641SAndroid Build Coastguard Workerimport sys 12*635a8641SAndroid Build Coastguard Worker 13*635a8641SAndroid Build Coastguard Workerfrom devil.android import device_errors 14*635a8641SAndroid Build Coastguard Workerfrom devil.android.valgrind_tools import base_tool 15*635a8641SAndroid Build Coastguard Workerfrom pylib.constants import DIR_SOURCE_ROOT 16*635a8641SAndroid Build Coastguard Worker 17*635a8641SAndroid Build Coastguard Worker 18*635a8641SAndroid Build Coastguard Workerdef SetChromeTimeoutScale(device, scale): 19*635a8641SAndroid Build Coastguard Worker """Sets the timeout scale in /data/local/tmp/chrome_timeout_scale to scale.""" 20*635a8641SAndroid Build Coastguard Worker path = '/data/local/tmp/chrome_timeout_scale' 21*635a8641SAndroid Build Coastguard Worker if not scale or scale == 1.0: 22*635a8641SAndroid Build Coastguard Worker # Delete if scale is None/0.0/1.0 since the default timeout scale is 1.0 23*635a8641SAndroid Build Coastguard Worker device.RemovePath(path, force=True, as_root=True) 24*635a8641SAndroid Build Coastguard Worker else: 25*635a8641SAndroid Build Coastguard Worker device.WriteFile(path, '%f' % scale, as_root=True) 26*635a8641SAndroid Build Coastguard Worker 27*635a8641SAndroid Build Coastguard Worker 28*635a8641SAndroid Build Coastguard Worker 29*635a8641SAndroid Build Coastguard Workerclass AddressSanitizerTool(base_tool.BaseTool): 30*635a8641SAndroid Build Coastguard Worker """AddressSanitizer tool.""" 31*635a8641SAndroid Build Coastguard Worker 32*635a8641SAndroid Build Coastguard Worker WRAPPER_NAME = '/system/bin/asanwrapper' 33*635a8641SAndroid Build Coastguard Worker # Disable memcmp overlap check.There are blobs (gl drivers) 34*635a8641SAndroid Build Coastguard Worker # on some android devices that use memcmp on overlapping regions, 35*635a8641SAndroid Build Coastguard Worker # nothing we can do about that. 36*635a8641SAndroid Build Coastguard Worker EXTRA_OPTIONS = 'strict_memcmp=0,use_sigaltstack=1' 37*635a8641SAndroid Build Coastguard Worker 38*635a8641SAndroid Build Coastguard Worker def __init__(self, device): 39*635a8641SAndroid Build Coastguard Worker super(AddressSanitizerTool, self).__init__() 40*635a8641SAndroid Build Coastguard Worker self._device = device 41*635a8641SAndroid Build Coastguard Worker 42*635a8641SAndroid Build Coastguard Worker @classmethod 43*635a8641SAndroid Build Coastguard Worker def CopyFiles(cls, device): 44*635a8641SAndroid Build Coastguard Worker """Copies ASan tools to the device.""" 45*635a8641SAndroid Build Coastguard Worker libs = glob.glob(os.path.join(DIR_SOURCE_ROOT, 46*635a8641SAndroid Build Coastguard Worker 'third_party/llvm-build/Release+Asserts/', 47*635a8641SAndroid Build Coastguard Worker 'lib/clang/*/lib/linux/', 48*635a8641SAndroid Build Coastguard Worker 'libclang_rt.asan-arm-android.so')) 49*635a8641SAndroid Build Coastguard Worker assert len(libs) == 1 50*635a8641SAndroid Build Coastguard Worker subprocess.call( 51*635a8641SAndroid Build Coastguard Worker [os.path.join( 52*635a8641SAndroid Build Coastguard Worker DIR_SOURCE_ROOT, 53*635a8641SAndroid Build Coastguard Worker 'tools/android/asan/third_party/asan_device_setup.sh'), 54*635a8641SAndroid Build Coastguard Worker '--device', str(device), 55*635a8641SAndroid Build Coastguard Worker '--lib', libs[0], 56*635a8641SAndroid Build Coastguard Worker '--extra-options', AddressSanitizerTool.EXTRA_OPTIONS]) 57*635a8641SAndroid Build Coastguard Worker device.WaitUntilFullyBooted() 58*635a8641SAndroid Build Coastguard Worker 59*635a8641SAndroid Build Coastguard Worker def GetTestWrapper(self): 60*635a8641SAndroid Build Coastguard Worker return AddressSanitizerTool.WRAPPER_NAME 61*635a8641SAndroid Build Coastguard Worker 62*635a8641SAndroid Build Coastguard Worker def GetUtilWrapper(self): 63*635a8641SAndroid Build Coastguard Worker """Returns the wrapper for utilities, such as forwarder. 64*635a8641SAndroid Build Coastguard Worker 65*635a8641SAndroid Build Coastguard Worker AddressSanitizer wrapper must be added to all instrumented binaries, 66*635a8641SAndroid Build Coastguard Worker including forwarder and the like. This can be removed if such binaries 67*635a8641SAndroid Build Coastguard Worker were built without instrumentation. """ 68*635a8641SAndroid Build Coastguard Worker return self.GetTestWrapper() 69*635a8641SAndroid Build Coastguard Worker 70*635a8641SAndroid Build Coastguard Worker def SetupEnvironment(self): 71*635a8641SAndroid Build Coastguard Worker try: 72*635a8641SAndroid Build Coastguard Worker self._device.EnableRoot() 73*635a8641SAndroid Build Coastguard Worker except device_errors.CommandFailedError as e: 74*635a8641SAndroid Build Coastguard Worker # Try to set the timeout scale anyway. 75*635a8641SAndroid Build Coastguard Worker # TODO(jbudorick) Handle this exception appropriately after interface 76*635a8641SAndroid Build Coastguard Worker # conversions are finished. 77*635a8641SAndroid Build Coastguard Worker logging.error(str(e)) 78*635a8641SAndroid Build Coastguard Worker SetChromeTimeoutScale(self._device, self.GetTimeoutScale()) 79*635a8641SAndroid Build Coastguard Worker 80*635a8641SAndroid Build Coastguard Worker def CleanUpEnvironment(self): 81*635a8641SAndroid Build Coastguard Worker SetChromeTimeoutScale(self._device, None) 82*635a8641SAndroid Build Coastguard Worker 83*635a8641SAndroid Build Coastguard Worker def GetTimeoutScale(self): 84*635a8641SAndroid Build Coastguard Worker # Very slow startup. 85*635a8641SAndroid Build Coastguard Worker return 20.0 86*635a8641SAndroid Build Coastguard Worker 87*635a8641SAndroid Build Coastguard Worker 88*635a8641SAndroid Build Coastguard WorkerTOOL_REGISTRY = { 89*635a8641SAndroid Build Coastguard Worker 'asan': AddressSanitizerTool, 90*635a8641SAndroid Build Coastguard Worker} 91*635a8641SAndroid Build Coastguard Worker 92*635a8641SAndroid Build Coastguard Worker 93*635a8641SAndroid Build Coastguard Workerdef CreateTool(tool_name, device): 94*635a8641SAndroid Build Coastguard Worker """Creates a tool with the specified tool name. 95*635a8641SAndroid Build Coastguard Worker 96*635a8641SAndroid Build Coastguard Worker Args: 97*635a8641SAndroid Build Coastguard Worker tool_name: Name of the tool to create. 98*635a8641SAndroid Build Coastguard Worker device: A DeviceUtils instance. 99*635a8641SAndroid Build Coastguard Worker Returns: 100*635a8641SAndroid Build Coastguard Worker A tool for the specified tool_name. 101*635a8641SAndroid Build Coastguard Worker """ 102*635a8641SAndroid Build Coastguard Worker if not tool_name: 103*635a8641SAndroid Build Coastguard Worker return base_tool.BaseTool() 104*635a8641SAndroid Build Coastguard Worker 105*635a8641SAndroid Build Coastguard Worker ctor = TOOL_REGISTRY.get(tool_name) 106*635a8641SAndroid Build Coastguard Worker if ctor: 107*635a8641SAndroid Build Coastguard Worker return ctor(device) 108*635a8641SAndroid Build Coastguard Worker else: 109*635a8641SAndroid Build Coastguard Worker print('Unknown tool %s, available tools: %s' % ( 110*635a8641SAndroid Build Coastguard Worker tool_name, ', '.join(sorted(TOOL_REGISTRY.keys())))) 111*635a8641SAndroid Build Coastguard Worker sys.exit(1) 112*635a8641SAndroid Build Coastguard Worker 113*635a8641SAndroid Build Coastguard Workerdef PushFilesForTool(tool_name, device): 114*635a8641SAndroid Build Coastguard Worker """Pushes the files required for |tool_name| to |device|. 115*635a8641SAndroid Build Coastguard Worker 116*635a8641SAndroid Build Coastguard Worker Args: 117*635a8641SAndroid Build Coastguard Worker tool_name: Name of the tool to create. 118*635a8641SAndroid Build Coastguard Worker device: A DeviceUtils instance. 119*635a8641SAndroid Build Coastguard Worker """ 120*635a8641SAndroid Build Coastguard Worker if not tool_name: 121*635a8641SAndroid Build Coastguard Worker return 122*635a8641SAndroid Build Coastguard Worker 123*635a8641SAndroid Build Coastguard Worker clazz = TOOL_REGISTRY.get(tool_name) 124*635a8641SAndroid Build Coastguard Worker if clazz: 125*635a8641SAndroid Build Coastguard Worker clazz.CopyFiles(device) 126*635a8641SAndroid Build Coastguard Worker else: 127*635a8641SAndroid Build Coastguard Worker print('Unknown tool %s, available tools: %s' % ( 128*635a8641SAndroid Build Coastguard Worker tool_name, ', '.join(sorted(TOOL_REGISTRY.keys())))) 129*635a8641SAndroid Build Coastguard Worker sys.exit(1) 130*635a8641SAndroid Build Coastguard Worker 131