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