1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2015 The Chromium Authors. All rights reserved. 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file. 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezpackage org.chromium.base.library_loader; 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport android.os.Build; 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport android.os.Bundle; 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport android.os.Parcel; 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport android.os.ParcelFileDescriptor; 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport android.os.Parcelable; 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport org.chromium.base.ContextUtils; 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport org.chromium.base.Log; 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport org.chromium.base.annotations.AccessedByNative; 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.util.HashMap; 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.util.Locale; 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.util.Map; 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport javax.annotation.Nullable; 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez/* 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Technical note: 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * The point of this class is to provide an alternative to System.loadLibrary() 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * to load native shared libraries. One specific feature that it supports is the 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * ability to save RAM by sharing the ELF RELRO sections between renderer 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * processes. 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * When two processes load the same native library at the _same_ memory address, 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * the content of their RELRO section (which includes C++ vtables or any 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * constants that contain pointers) will be largely identical [1]. 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * By default, the RELRO section is backed by private RAM in each process, 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * which is still significant on mobile (e.g. 1.28 MB / process on Chrome 30 for 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Android). 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * However, it is possible to save RAM by creating a shared memory region, 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * copy the RELRO content into it, then have each process swap its private, 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * regular RELRO, with a shared, read-only, mapping of the shared one. 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * This trick saves 98% of the RELRO section size per extra process, after the 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * first one. On the other hand, this requires careful communication between 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * the process where the shared RELRO is created and the one(s) where it is used. 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Note that swapping the regular RELRO with the shared one is not an atomic 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * operation. Care must be taken that no other thread tries to run native code 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * that accesses it during it. In practice, this means the swap must happen 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * before library native code is executed. 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * [1] The exceptions are pointers to external, randomized, symbols, like 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * those from some system libraries, but these are very few in practice. 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez/* 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Security considerations: 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - Whether the browser process loads its native libraries at the same 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * addresses as the service ones (to save RAM by sharing the RELRO too) 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * depends on the configuration variable BROWSER_SHARED_RELRO_CONFIG. 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Not using fixed library addresses in the browser process is preferred 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * for regular devices since it maintains the efficacy of ASLR as an 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * exploit mitigation across the render <-> browser privilege boundary. 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - The shared RELRO memory region is always forced read-only after creation, 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * which means it is impossible for a compromised service process to map 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * it read-write (e.g. by calling mmap() or mprotect()) and modify its 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * content, altering values seen in other service processes. 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - Once the RELRO ashmem region or file is mapped into a service process's 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * address space, the corresponding file descriptor is immediately closed. The 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * file descriptor is kept opened in the browser process, because a copy needs 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * to be sent to each new potential service process. 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - The common library load addresses are randomized for each instance of 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * the program on the device. See getRandomBaseLoadAddress() for more 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * details on how this is obtained. 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - When loading several libraries in service processes, a simple incremental 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * approach from the original random base load address is used. This is 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * sufficient to deal correctly with component builds (which can use dozens 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * of shared libraries), while regular builds always embed a single shared 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * library per APK. 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez/** 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Here's an explanation of how this class is supposed to be used: 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - Native shared libraries should be loaded with Linker.loadLibrary(), 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * instead of System.loadLibrary(). The two functions should behave the same 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * (at a high level). 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - Before loading any library, prepareLibraryLoad() should be called. 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - After loading all libraries, finishLibraryLoad() should be called, before 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * running any native code from any of the libraries (except their static 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * constructors, which can't be avoided). 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - A service process shall call either initServiceProcess() or 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * disableSharedRelros() early (i.e. before any loadLibrary() call). 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Otherwise, the linker considers that it is running inside the browser 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * process. This is because various Chromium projects have vastly 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * different initialization paths. 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * disableSharedRelros() completely disables shared RELROs, and loadLibrary() 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * will behave exactly like System.loadLibrary(). 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * initServiceProcess(baseLoadAddress) indicates that shared RELROs are to be 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * used in this process. 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - The browser is in charge of deciding where in memory each library should 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * be loaded. This address must be passed to each service process (see 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * ChromiumLinkerParams.java in content for a helper class to do so). 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - The browser will also generate shared RELROs for each library it loads. 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * More specifically, by default when in the browser process, the linker 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * will: 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - Load libraries randomly (just like System.loadLibrary()). 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - Compute the fixed address to be used to load the same library 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * in service processes. 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - Create a shared memory region populated with the RELRO region 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * content pre-relocated for the specific fixed address above. 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Note that these shared RELRO regions cannot be used inside the browser 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * process. They are also never mapped into it. 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * This behaviour is altered by the BROWSER_SHARED_RELRO_CONFIG configuration 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * variable below, which may force the browser to load the libraries at 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * fixed addresses too. 133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - Once all libraries are loaded in the browser process, one can call 135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * getSharedRelros() which returns a Bundle instance containing a map that 136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * links each loaded library to its shared RELRO region. 137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * This Bundle must be passed to each service process, for example through 139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * a Binder call (note that the Bundle includes file descriptors and cannot 140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * be added as an Intent extra). 141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - In a service process, finishLibraryLoad() and/or loadLibrary() may 143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * block until the RELRO section Bundle is received. This is typically 144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * done by calling useSharedRelros() from another thread. 145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * This method also ensures the process uses the shared RELROs. 147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezpublic abstract class Linker { 149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Log tag for this class. 150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private static final String TAG = "LibraryLoader"; 151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Name of the library that contains our JNI code. 153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private static final String LINKER_JNI_LIBRARY = "chromium_android_linker"; 154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Constants used to control the behaviour of the browser process with 156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // regards to the shared RELRO section. Not applicable to ModernLinker. 157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // NEVER -> The browser never uses it itself. 158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // LOW_RAM_ONLY -> It is only used on devices with low RAM. 159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // ALWAYS -> It is always used. 160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // NOTE: These names are known and expected by the Linker test scripts. 161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final int BROWSER_SHARED_RELRO_CONFIG_NEVER = 0; 162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final int BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY = 1; 163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final int BROWSER_SHARED_RELRO_CONFIG_ALWAYS = 2; 164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Configuration variable used to control how the browser process uses the 166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // shared RELRO. Only change this while debugging linker-related issues. 167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Not used by ModernLinker. 168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // NOTE: This variable's name is known and expected by the Linker test scripts. 169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final int BROWSER_SHARED_RELRO_CONFIG = 170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY; 171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Constants used to control the memory device config. Can be set explicitly 173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // by setMemoryDeviceConfigForTesting(). Not applicable to ModernLinker. 174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // INIT -> Value is undetermined (will check at runtime). 175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // LOW -> This is a low-memory device. 176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // NORMAL -> This is not a low-memory device. 177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final int MEMORY_DEVICE_CONFIG_INIT = 0; 178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final int MEMORY_DEVICE_CONFIG_LOW = 1; 179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final int MEMORY_DEVICE_CONFIG_NORMAL = 2; 180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Indicates if this is a low-memory device or not. The default is to 182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // determine this by probing the system at runtime, but this can be forced 183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // for testing by calling setMemoryDeviceConfigForTesting(). 184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Not used by ModernLinker. 185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected int mMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_INIT; 186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Set to true to enable debug logs. 188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected static final boolean DEBUG = false; 189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Used to pass the shared RELRO Bundle through Binder. 191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final String EXTRA_LINKER_SHARED_RELROS = 192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "org.chromium.base.android.linker.shared_relros"; 193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Guards all access to the linker. 195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected final Object mLock = new Object(); 196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The name of a class that implements TestRunner. 198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private String mTestRunnerClassName = null; 199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Size of reserved Breakpad guard region. Should match the value of 201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // kBreakpadGuardRegionBytes on the JNI side. Used when computing the load 202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // addresses of multiple loaded libraries. Set to 0 to disable the guard. 203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected static final int BREAKPAD_GUARD_REGION_BYTES = 16 * 1024 * 1024; 204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Size of the area requested when using ASLR to obtain a random load address. 206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Should match the value of kAddressSpaceReservationSize on the JNI side. 207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Used when computing the load addresses of multiple loaded libraries to 208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // ensure that we don't try to load outside the area originally requested. 209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected static final int ADDRESS_SPACE_RESERVATION = 192 * 1024 * 1024; 210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Constants used to indicate a given Linker implementation, for testing. 212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // LEGACY -> Always uses the LegacyLinker implementation. 213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // MODERN -> Always uses the ModernLinker implementation. 214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // NOTE: These names are known and expected by the Linker test scripts. 215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final int LINKER_IMPLEMENTATION_LEGACY = 1; 216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final int LINKER_IMPLEMENTATION_MODERN = 2; 217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Singleton. 219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private static Linker sSingleton = null; 220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private static Object sSingletonLock = new Object(); 221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Protected singleton constructor. 223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected Linker() { } 224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Get singleton instance. Returns either a LegacyLinker or a ModernLinker. 227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Returns a ModernLinker if running on Android M or later, otherwise returns 229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * a LegacyLinker. 230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * ModernLinker requires OS features from Android M and later: a system linker 232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * that handles packed relocations and load from APK, and android_dlopen_ext() 233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * for shared RELRO support. It cannot run on Android releases earlier than M. 234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * LegacyLinker runs on all Android releases but it is slower and more complex 236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * than ModernLinker, so ModernLinker is preferred for Android M and later. 237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return the Linker implementation instance. 239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final Linker getInstance() { 241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez synchronized (sSingletonLock) { 242645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (sSingleton == null) { 243645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // With incremental install, it's important to fall back to the "normal" 244645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // library loading path in order for the libraries to be found. 245645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez String appClass = 246645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ContextUtils.getApplicationContext().getApplicationInfo().className; 247645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez boolean isIncrementalInstall = 248645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez appClass != null && appClass.contains("incrementalinstall"); 249645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !isIncrementalInstall) { 250645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sSingleton = ModernLinker.create(); 251645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 252645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sSingleton = LegacyLinker.create(); 253645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 254645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "Using linker: " + sSingleton.getClass().getName()); 255645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 256645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return sSingleton; 257645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 258645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 259645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 260645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 261645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Check that native library linker tests are enabled. 262645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * If not enabled, calls to testing functions will fail with an assertion 263645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * error. 264645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 265645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return true if native library linker tests are enabled. 266645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 267645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static boolean areTestsEnabled() { 268645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return NativeLibraries.sEnableLinkerTests; 269645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 270645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 271645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 272645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Assert for testing. 273645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Hard assertion. Cannot be disabled. Used only by testing methods. 274645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 275645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private static void assertForTesting(boolean flag) { 276645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!flag) { 277645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new AssertionError(); 278645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 279645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 280645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 281645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 282645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Assert NativeLibraries.sEnableLinkerTests is true. 283645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Hard assertion that we are in a testing context. Cannot be disabled. The 284645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * test methods in this module permit injection of runnable code by class 285645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * name. To protect against both malicious and accidental use of these 286645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * methods, we ensure that NativeLibraries.sEnableLinkerTests is true when 287645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * any is called. 288645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 289645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private static void assertLinkerTestsAreEnabled() { 290645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!NativeLibraries.sEnableLinkerTests) { 291645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new AssertionError("Testing method called in non-testing context"); 292645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 293645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 294645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 295645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 296645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Set Linker implementation type. 297645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * For testing. Sets either a LegacyLinker or a ModernLinker. Must be called 298645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * before getInstance(). 299645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 300645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param type LINKER_IMPLEMENTATION_LEGACY or LINKER_IMPLEMENTATION_MODERN 301645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 302645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final void setImplementationForTesting(int type) { 303645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Sanity check. This method may only be called during tests. 304645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertLinkerTestsAreEnabled(); 305645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(type == LINKER_IMPLEMENTATION_LEGACY 306645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez || type == LINKER_IMPLEMENTATION_MODERN); 307645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 308645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez synchronized (sSingletonLock) { 309645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(sSingleton == null); 310645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 311645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (type == LINKER_IMPLEMENTATION_MODERN) { 312645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sSingleton = ModernLinker.create(); 313645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else if (type == LINKER_IMPLEMENTATION_LEGACY) { 314645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sSingleton = LegacyLinker.create(); 315645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 316645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "Forced linker: " + sSingleton.getClass().getName()); 317645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 318645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 319645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 320645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 321645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Get Linker implementation type. 322645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * For testing. 323645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 324645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return LINKER_IMPLEMENTATION_LEGACY or LINKER_IMPLEMENTATION_MODERN 325645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 326645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public final int getImplementationForTesting() { 327645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Sanity check. This method may only be called during tests. 328645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertLinkerTestsAreEnabled(); 329645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 330645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez synchronized (sSingletonLock) { 331645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(sSingleton == this); 332645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 333645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (sSingleton instanceof ModernLinker) { 334645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return LINKER_IMPLEMENTATION_MODERN; 335645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else if (sSingleton instanceof LegacyLinker) { 336645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return LINKER_IMPLEMENTATION_LEGACY; 337645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 338645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.wtf(TAG, "Invalid linker: " + sSingleton.getClass().getName()); 339645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(false); 340645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 341645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return 0; 342645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 343645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 344645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 345645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 346645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * A public interface used to run runtime linker tests after loading 347645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * libraries. Should only be used to implement the linker unit tests, 348645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * which is controlled by the value of NativeLibraries.sEnableLinkerTests 349645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * configured at build time. 350645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 351645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public interface TestRunner { 352645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 353645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Run runtime checks and return true if they all pass. 354645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 355645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param memoryDeviceConfig The current memory device configuration. 356645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param inBrowserProcess true iff this is the browser process. 357645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return true if all checks pass. 358645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 359645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public boolean runChecks(int memoryDeviceConfig, boolean inBrowserProcess); 360645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 361645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 362645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 363645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Set the TestRunner by its class name. It will be instantiated at 364645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * runtime after all libraries are loaded. 365645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 366645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param testRunnerClassName null or a String for the class name of the 367645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * TestRunner to use. 368645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 369645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public final void setTestRunnerClassNameForTesting(String testRunnerClassName) { 370645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (DEBUG) { 371645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "setTestRunnerClassNameForTesting(" + testRunnerClassName + ") called"); 372645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 373645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Sanity check. This method may only be called during tests. 374645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertLinkerTestsAreEnabled(); 375645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 376645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez synchronized (mLock) { 377645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(mTestRunnerClassName == null); 378645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mTestRunnerClassName = testRunnerClassName; 379645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 380645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 381645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 382645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 383645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Call this to retrieve the name of the current TestRunner class name 384645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * if any. This can be useful to pass it from the browser process to 385645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * child ones. 386645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 387645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return null or a String holding the name of the class implementing 388645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * the TestRunner set by calling setTestRunnerClassNameForTesting() previously. 389645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 390645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public final String getTestRunnerClassNameForTesting() { 391645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Sanity check. This method may only be called during tests. 392645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertLinkerTestsAreEnabled(); 393645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 394645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez synchronized (mLock) { 395645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return mTestRunnerClassName; 396645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 397645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 398645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 399645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 400645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Set up the Linker for a test. 401645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Convenience function that calls setImplementationForTesting() to force an 402645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * implementation, and then setTestRunnerClassNameForTesting() to set the test 403645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * class name. 404645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 405645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * On first call, instantiates a Linker of the requested type and sets its test 406645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * runner class name. On subsequent calls, checks that the singleton produced by 407645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * the first call matches the requested type and test runner class name. 408645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 409645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final void setupForTesting(int type, String testRunnerClassName) { 410645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (DEBUG) { 411645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "setupForTesting(" + type + ", " + testRunnerClassName + ") called"); 412645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 413645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Sanity check. This method may only be called during tests. 414645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertLinkerTestsAreEnabled(); 415645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 416645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez synchronized (sSingletonLock) { 417645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If this is the first call, configure the Linker to the given type and test class. 418645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (sSingleton == null) { 419645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez setImplementationForTesting(type); 420645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sSingleton.setTestRunnerClassNameForTesting(testRunnerClassName); 421645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 422645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 423645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 424645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If not the first call, check that the Linker configuration matches this request. 425645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(sSingleton.getImplementationForTesting() == type); 426645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez String ourTestRunnerClassName = sSingleton.getTestRunnerClassNameForTesting(); 427645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (testRunnerClassName == null) { 428645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(ourTestRunnerClassName == null); 429645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 430645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(ourTestRunnerClassName.equals(testRunnerClassName)); 431645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 432645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 433645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 434645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 435645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 436645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Instantiate and run the current TestRunner, if any. The TestRunner implementation 437645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * must be instantiated _after_ all libraries are loaded to ensure that its 438645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * native methods are properly registered. 439645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 440645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param memoryDeviceConfig LegacyLinker memory config, or 0 if unused 441645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param inBrowserProcess true if in the browser process 442645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 443645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected final void runTestRunnerClassForTesting(int memoryDeviceConfig, 444645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez boolean inBrowserProcess) { 445645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (DEBUG) { 446645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "runTestRunnerClassForTesting called"); 447645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 448645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Sanity check. This method may only be called during tests. 449645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertLinkerTestsAreEnabled(); 450645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 451645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez synchronized (mLock) { 452645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mTestRunnerClassName == null) { 453645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.wtf(TAG, "Linker runtime tests not set up for this process"); 454645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(false); 455645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 456645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (DEBUG) { 457645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "Instantiating " + mTestRunnerClassName); 458645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 459645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez TestRunner testRunner = null; 460645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try { 461645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez testRunner = (TestRunner) Class.forName(mTestRunnerClassName).newInstance(); 462645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } catch (Exception e) { 463645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.wtf(TAG, "Could not instantiate test runner class by name", e); 464645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(false); 465645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 466645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 467645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!testRunner.runChecks(memoryDeviceConfig, inBrowserProcess)) { 468645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.wtf(TAG, "Linker runtime tests failed in this process"); 469645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(false); 470645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 471645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 472645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "All linker tests passed"); 473645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 474645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 475645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 476645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 477645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Call this method before any other Linker method to force a specific 478645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * memory device configuration. Should only be used for testing. 479645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 480645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param memoryDeviceConfig MEMORY_DEVICE_CONFIG_LOW or MEMORY_DEVICE_CONFIG_NORMAL. 481645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 482645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public final void setMemoryDeviceConfigForTesting(int memoryDeviceConfig) { 483645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (DEBUG) { 484645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "setMemoryDeviceConfigForTesting(" + memoryDeviceConfig + ") called"); 485645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 486645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Sanity check. This method may only be called during tests. 487645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertLinkerTestsAreEnabled(); 488645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(memoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW 489645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez || memoryDeviceConfig == MEMORY_DEVICE_CONFIG_NORMAL); 490645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 491645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez synchronized (mLock) { 492645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assertForTesting(mMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT); 493645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 494645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mMemoryDeviceConfig = memoryDeviceConfig; 495645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (DEBUG) { 496645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW) { 497645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "Simulating a low-memory device"); 498645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 499645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "Simulating a regular-memory device"); 500645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 501645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 502645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 503645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 504645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 505645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 506645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Determine whether a library is the linker library. Also deal with the 507645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * component build that adds a .cr suffix to the name. 508645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 509645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param library the name of the library. 510645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return true is the library is the Linker's own JNI library. 511645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 512645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public boolean isChromiumLinkerLibrary(String library) { 513645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return library.equals(LINKER_JNI_LIBRARY) || library.equals(LINKER_JNI_LIBRARY + ".cr"); 514645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 515645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 516645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 517645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Load the Linker JNI library. Throws UnsatisfiedLinkError on error. 518645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * In a component build, the suffix ".cr" is added to each library name, so 519645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * if the initial load fails we retry with a suffix. 520645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 521645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected static void loadLinkerJniLibrary() { 522645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez String libName = "lib" + LINKER_JNI_LIBRARY + ".so"; 523645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (DEBUG) { 524645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "Loading " + libName); 525645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 526645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try { 527645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez System.loadLibrary(LINKER_JNI_LIBRARY); 528645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } catch (UnsatisfiedLinkError e) { 529645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.w(TAG, "Couldn't load " + libName + ", trying " + libName + ".cr"); 530645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez System.loadLibrary(LINKER_JNI_LIBRARY + ".cr"); 531645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 532645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 533645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 534645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 535645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Obtain a random base load address at which to place loaded libraries. 536645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 537645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return new base load address 538645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 539645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected long getRandomBaseLoadAddress() { 540645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // nativeGetRandomBaseLoadAddress() returns an address at which it has previously 541645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // successfully mapped an area larger than the largest library we expect to load, 542645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // on the basis that we will be able, with high probability, to map our library 543645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // into it. 544645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // 545645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // One issue with this is that we do not yet know the size of the library that 546645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // we will load is. If it is smaller than the size we used to obtain a random 547645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // address the library mapping may still succeed. The other issue is that 548645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // although highly unlikely, there is no guarantee that something else does not 549645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // map into the area we are going to use between here and when we try to map into it. 550645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // 551645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The above notes mean that all of this is probablistic. It is however okay to do 552645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // because if, worst case and unlikely, we get unlucky in our choice of address, 553645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // the back-out and retry without the shared RELRO in the ChildProcessService will 554645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // keep things running. 555645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez final long address = nativeGetRandomBaseLoadAddress(); 556645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (DEBUG) { 557645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, String.format(Locale.US, "Random native base load address: 0x%x", address)); 558645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 559645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return address; 560645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 561645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 562645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 563645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Load a native shared library with the Chromium linker. If the zip file 564645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * is not null, the shared library must be uncompressed and page aligned 565645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * inside the zipfile. Note the crazy linker treats libraries and files as 566645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * equivalent, so you can only open one library in a given zip file. The 567645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * library must not be the Chromium linker library. 568645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 569645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param zipFilePath The path of the zip file containing the library (or null). 570645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param libFilePath The path of the library (possibly in the zip file). 571645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 572645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void loadLibrary(@Nullable String zipFilePath, String libFilePath) { 573645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (DEBUG) { 574645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "loadLibrary: " + zipFilePath + ", " + libFilePath); 575645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 576645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez final boolean isFixedAddressPermitted = true; 577645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez loadLibraryImpl(zipFilePath, libFilePath, isFixedAddressPermitted); 578645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 579645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 580645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 581645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Load a native shared library with the Chromium linker, ignoring any 582645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * requested fixed address for RELRO sharing. If the zip file 583645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * is not null, the shared library must be uncompressed and page aligned 584645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * inside the zipfile. Note the crazy linker treats libraries and files as 585645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * equivalent, so you can only open one library in a given zip file. The 586645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * library must not be the Chromium linker library. 587645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 588645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param zipFilePath The path of the zip file containing the library (or null). 589645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param libFilePath The path of the library (possibly in the zip file). 590645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 591645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void loadLibraryNoFixedAddress(@Nullable String zipFilePath, String libFilePath) { 592645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (DEBUG) { 593645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.i(TAG, "loadLibraryAtAnyAddress: " + zipFilePath + ", " + libFilePath); 594645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 595645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez final boolean isFixedAddressPermitted = false; 596645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez loadLibraryImpl(zipFilePath, libFilePath, isFixedAddressPermitted); 597645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 598645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 599645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 600645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Call this method to determine if the chromium project must load the library 601645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * directly from a zip file. 602645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 603645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static boolean isInZipFile() { 604645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The auto-generated NativeLibraries.sUseLibraryInZipFile variable will be true 605645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // if the library remains embedded in the APK zip file on the target. 606645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return NativeLibraries.sUseLibraryInZipFile; 607645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 608645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 609645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 610645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Call this method to determine if this chromium project must 611645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * use this linker. If not, System.loadLibrary() should be used to load 612645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * libraries instead. 613645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 614645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static boolean isUsed() { 615645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The auto-generated NativeLibraries.sUseLinker variable will be true if the 616645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // build has not explicitly disabled Linker features. 617645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return NativeLibraries.sUseLinker; 618645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 619645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 620645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 621645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Call this method to determine if the linker will try to use shared RELROs 622645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * for the browser process. 623645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 624645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public abstract boolean isUsingBrowserSharedRelros(); 625645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 626645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 627645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Call this method just before loading any native shared libraries in this process. 628645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 629645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public abstract void prepareLibraryLoad(); 630645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 631645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 632645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Call this method just after loading all native shared libraries in this process. 633645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 634645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public abstract void finishLibraryLoad(); 635645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 636645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 637645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Call this to send a Bundle containing the shared RELRO sections to be 638645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * used in this process. If initServiceProcess() was previously called, 639645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * finishLibraryLoad() will not exit until this method is called in another 640645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * thread with a non-null value. 641645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 642645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param bundle The Bundle instance containing a map of shared RELRO sections 643645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * to use in this process. 644645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 645645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public abstract void useSharedRelros(Bundle bundle); 646645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 647645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 648645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Call this to retrieve the shared RELRO sections created in this process, 649645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * after loading all libraries. 650645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 651645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return a new Bundle instance, or null if RELRO sharing is disabled on 652645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * this system, or if initServiceProcess() was called previously. 653645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 654645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public abstract Bundle getSharedRelros(); 655645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 656645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 657645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 658645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Call this method before loading any libraries to indicate that this 659645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * process shall neither create or reuse shared RELRO sections. 660645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 661645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public abstract void disableSharedRelros(); 662645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 663645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 664645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Call this method before loading any libraries to indicate that this 665645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * process is ready to reuse shared RELRO sections from another one. 666645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Typically used when starting service processes. 667645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 668645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param baseLoadAddress the base library load address to use. 669645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 670645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public abstract void initServiceProcess(long baseLoadAddress); 671645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 672645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 673645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Retrieve the base load address of all shared RELRO sections. 674645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * This also enforces the creation of shared RELRO sections in 675645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * prepareLibraryLoad(), which can later be retrieved with getSharedRelros(). 676645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 677645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return a common, random base load address, or 0 if RELRO sharing is 678645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * disabled. 679645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 680645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public abstract long getBaseLoadAddress(); 681645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 682645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 683645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Implements loading a native shared library with the Chromium linker. 684645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 685645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param zipFilePath The path of the zip file containing the library (or null). 686645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param libFilePath The path of the library (possibly in the zip file). 687645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param isFixedAddressPermitted If true, uses a fixed load address if one was 688645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * supplied, otherwise ignores the fixed address and loads wherever available. 689645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 690645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez abstract void loadLibraryImpl(@Nullable String zipFilePath, 691645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez String libFilePath, 692645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez boolean isFixedAddressPermitted); 693645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 694645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 695645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Record information for a given library. 696645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * IMPORTANT: Native code knows about this class's fields, so 697645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * don't change them without modifying the corresponding C++ sources. 698645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Also, the LibInfo instance owns the shared RELRO file descriptor. 699645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 700645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static class LibInfo implements Parcelable { 701645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 702645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public LibInfo() { 703645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mLoadAddress = 0; 704645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mLoadSize = 0; 705645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mRelroStart = 0; 706645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mRelroSize = 0; 707645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mRelroFd = -1; 708645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 709645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 710645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void close() { 711645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mRelroFd >= 0) { 712645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try { 713645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ParcelFileDescriptor.adoptFd(mRelroFd).close(); 714645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } catch (java.io.IOException e) { 715645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (DEBUG) { 716645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.e(TAG, "Failed to close fd: " + mRelroFd); 717645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 718645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 719645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mRelroFd = -1; 720645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 721645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 722645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 723645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // from Parcelable 724645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public LibInfo(Parcel in) { 725645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mLoadAddress = in.readLong(); 726645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mLoadSize = in.readLong(); 727645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mRelroStart = in.readLong(); 728645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mRelroSize = in.readLong(); 729645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ParcelFileDescriptor fd = ParcelFileDescriptor.CREATOR.createFromParcel(in); 730645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If CreateSharedRelro fails, the OS file descriptor will be -1 and |fd| will be null. 731645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mRelroFd = (fd == null) ? -1 : fd.detachFd(); 732645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 733645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 734645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // from Parcelable 735645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @Override 736645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void writeToParcel(Parcel out, int flags) { 737645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mRelroFd >= 0) { 738645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez out.writeLong(mLoadAddress); 739645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez out.writeLong(mLoadSize); 740645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez out.writeLong(mRelroStart); 741645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez out.writeLong(mRelroSize); 742645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try { 743645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ParcelFileDescriptor fd = ParcelFileDescriptor.fromFd(mRelroFd); 744645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez fd.writeToParcel(out, 0); 745645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez fd.close(); 746645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } catch (java.io.IOException e) { 747645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Log.e(TAG, "Can't write LibInfo file descriptor to parcel", e); 748645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 749645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 750645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 751645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 752645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // from Parcelable 753645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @Override 754645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public int describeContents() { 755645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return Parcelable.CONTENTS_FILE_DESCRIPTOR; 756645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 757645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 758645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // from Parcelable 759645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public static final Parcelable.Creator<LibInfo> CREATOR = 760645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez new Parcelable.Creator<LibInfo>() { 761645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @Override 762645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public LibInfo createFromParcel(Parcel in) { 763645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return new LibInfo(in); 764645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 765645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 766645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @Override 767645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public LibInfo[] newArray(int size) { 768645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return new LibInfo[size]; 769645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 770645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez }; 771645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 772645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @Override 773645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public String toString() { 774645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return String.format(Locale.US, 775645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "[load=0x%x-0x%x relro=0x%x-0x%x fd=%d]", 776645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mLoadAddress, 777645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mLoadAddress + mLoadSize, 778645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mRelroStart, 779645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mRelroStart + mRelroSize, 780645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mRelroFd); 781645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 782645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 783645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // IMPORTANT: Don't change these fields without modifying the 784645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // native code that accesses them directly! 785645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @AccessedByNative 786645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public long mLoadAddress; // page-aligned library load address. 787645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @AccessedByNative 788645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public long mLoadSize; // page-aligned library load size. 789645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @AccessedByNative 790645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public long mRelroStart; // page-aligned address in memory, or 0 if none. 791645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @AccessedByNative 792645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public long mRelroSize; // page-aligned size in memory, or 0. 793645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @AccessedByNative 794645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public int mRelroFd; // shared RELRO file descriptor, or -1 795645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 796645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 797645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Create a Bundle from a map of LibInfo objects. 798645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected Bundle createBundleFromLibInfoMap(HashMap<String, LibInfo> map) { 799645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Bundle bundle = new Bundle(map.size()); 800645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (Map.Entry<String, LibInfo> entry : map.entrySet()) { 801645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bundle.putParcelable(entry.getKey(), entry.getValue()); 802645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 803645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return bundle; 804645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 805645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 806645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Create a new LibInfo map from a Bundle. 807645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected HashMap<String, LibInfo> createLibInfoMapFromBundle(Bundle bundle) { 808645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez HashMap<String, LibInfo> map = new HashMap<String, LibInfo>(); 809645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (String library : bundle.keySet()) { 810645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LibInfo libInfo = bundle.getParcelable(library); 811645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez map.put(library, libInfo); 812645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 813645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return map; 814645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 815645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 816645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Call the close() method on all values of a LibInfo map. 817645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez protected void closeLibInfoMap(HashMap<String, LibInfo> map) { 818645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (Map.Entry<String, LibInfo> entry : map.entrySet()) { 819645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez entry.getValue().close(); 820645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 821645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 822645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 823645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 824645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Return a random address that should be free to be mapped with the given size. 825645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Maps an area large enough for the largest library we might attempt to load, 826645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * and if successful then unmaps it and returns the address of the area allocated 827645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * by the system (with ASLR). The idea is that this area should remain free of 828645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * other mappings until we map our library into it. 829645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 830645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return address to pass to future mmap, or 0 on error. 831645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 832645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private static native long nativeGetRandomBaseLoadAddress(); 833645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 834