OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.base.library_loader; | 5 package org.chromium.base.library_loader; |
6 | 6 |
7 import android.os.Build; | 7 import android.os.Build; |
8 import android.os.Bundle; | 8 import android.os.Bundle; |
9 import android.os.Parcel; | 9 import android.os.Parcel; |
10 import android.os.ParcelFileDescriptor; | 10 import android.os.ParcelFileDescriptor; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 * - In a service process, finishLibraryLoad() and/or loadLibrary() may | 141 * - In a service process, finishLibraryLoad() and/or loadLibrary() may |
142 * block until the RELRO section Bundle is received. This is typically | 142 * block until the RELRO section Bundle is received. This is typically |
143 * done by calling useSharedRelros() from another thread. | 143 * done by calling useSharedRelros() from another thread. |
144 * | 144 * |
145 * This method also ensures the process uses the shared RELROs. | 145 * This method also ensures the process uses the shared RELROs. |
146 */ | 146 */ |
147 public abstract class Linker { | 147 public abstract class Linker { |
148 // Log tag for this class. | 148 // Log tag for this class. |
149 private static final String TAG = "cr.library_loader"; | 149 private static final String TAG = "cr.library_loader"; |
150 | 150 |
| 151 // Name of the library that contains our JNI code. |
| 152 private static final String LINKER_JNI_LIBRARY = "chromium_android_linker"; |
| 153 |
151 // Constants used to control the behaviour of the browser process with | 154 // Constants used to control the behaviour of the browser process with |
152 // regards to the shared RELRO section. Not applicable to ModernLinker. | 155 // regards to the shared RELRO section. Not applicable to ModernLinker. |
153 // NEVER -> The browser never uses it itself. | 156 // NEVER -> The browser never uses it itself. |
154 // LOW_RAM_ONLY -> It is only used on devices with low RAM. | 157 // LOW_RAM_ONLY -> It is only used on devices with low RAM. |
155 // ALWAYS -> It is always used. | 158 // ALWAYS -> It is always used. |
156 // NOTE: These names are known and expected by the Linker test scripts. | 159 // NOTE: These names are known and expected by the Linker test scripts. |
157 public static final int BROWSER_SHARED_RELRO_CONFIG_NEVER = 0; | 160 public static final int BROWSER_SHARED_RELRO_CONFIG_NEVER = 0; |
158 public static final int BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY = 1; | 161 public static final int BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY = 1; |
159 public static final int BROWSER_SHARED_RELRO_CONFIG_ALWAYS = 2; | 162 public static final int BROWSER_SHARED_RELRO_CONFIG_ALWAYS = 2; |
160 | 163 |
(...skipping 12 matching lines...) Expand all Loading... |
173 public static final int MEMORY_DEVICE_CONFIG_INIT = 0; | 176 public static final int MEMORY_DEVICE_CONFIG_INIT = 0; |
174 public static final int MEMORY_DEVICE_CONFIG_LOW = 1; | 177 public static final int MEMORY_DEVICE_CONFIG_LOW = 1; |
175 public static final int MEMORY_DEVICE_CONFIG_NORMAL = 2; | 178 public static final int MEMORY_DEVICE_CONFIG_NORMAL = 2; |
176 | 179 |
177 // Indicates if this is a low-memory device or not. The default is to | 180 // Indicates if this is a low-memory device or not. The default is to |
178 // determine this by probing the system at runtime, but this can be forced | 181 // determine this by probing the system at runtime, but this can be forced |
179 // for testing by calling setMemoryDeviceConfigForTesting(). | 182 // for testing by calling setMemoryDeviceConfigForTesting(). |
180 // Not used by ModernLinker. | 183 // Not used by ModernLinker. |
181 protected int mMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_INIT; | 184 protected int mMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_INIT; |
182 | 185 |
183 // Name of the library that contains our JNI code. | |
184 protected static final String LINKER_JNI_LIBRARY = "chromium_android_linker"
; | |
185 | |
186 // Set to true to enable debug logs. | 186 // Set to true to enable debug logs. |
187 protected static final boolean DEBUG = false; | 187 protected static final boolean DEBUG = false; |
188 | 188 |
189 // Used to pass the shared RELRO Bundle through Binder. | 189 // Used to pass the shared RELRO Bundle through Binder. |
190 public static final String EXTRA_LINKER_SHARED_RELROS = | 190 public static final String EXTRA_LINKER_SHARED_RELROS = |
191 "org.chromium.base.android.linker.shared_relros"; | 191 "org.chromium.base.android.linker.shared_relros"; |
192 | 192 |
193 // Guards all access to the linker. | 193 // Guards all access to the linker. |
194 protected final Object mLock = new Object(); | 194 protected final Object mLock = new Object(); |
195 | 195 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 } | 250 } |
251 } | 251 } |
252 | 252 |
253 /** | 253 /** |
254 * Check that native library linker tests are enabled. | 254 * Check that native library linker tests are enabled. |
255 * If not enabled, calls to testing functions will fail with an assertion | 255 * If not enabled, calls to testing functions will fail with an assertion |
256 * error. | 256 * error. |
257 * | 257 * |
258 * @return true if native library linker tests are enabled. | 258 * @return true if native library linker tests are enabled. |
259 */ | 259 */ |
260 public static boolean areLinkerTestsEnabled() { | 260 public static boolean areTestsEnabled() { |
261 return NativeLibraries.sEnableLinkerTests; | 261 return NativeLibraries.sEnableLinkerTests; |
262 } | 262 } |
263 | 263 |
264 /** | 264 /** |
265 * Assert for testing. | 265 * Assert for testing. |
266 * Hard assertion. Cannot be disabled. Used only by testing methods. | 266 * Hard assertion. Cannot be disabled. Used only by testing methods. |
267 */ | 267 */ |
268 private static void assertForTesting(boolean flag) { | 268 private static void assertForTesting(boolean flag) { |
269 if (!flag) { | 269 if (!flag) { |
270 throw new AssertionError(); | 270 throw new AssertionError(); |
(...skipping 14 matching lines...) Expand all Loading... |
285 } | 285 } |
286 } | 286 } |
287 | 287 |
288 /** | 288 /** |
289 * Set Linker implementation type. | 289 * Set Linker implementation type. |
290 * For testing. Sets either a LegacyLinker or a ModernLinker. Must be called | 290 * For testing. Sets either a LegacyLinker or a ModernLinker. Must be called |
291 * before getInstance(). | 291 * before getInstance(). |
292 * | 292 * |
293 * @param type LINKER_IMPLEMENTATION_LEGACY or LINKER_IMPLEMENTATION_MODERN | 293 * @param type LINKER_IMPLEMENTATION_LEGACY or LINKER_IMPLEMENTATION_MODERN |
294 */ | 294 */ |
295 public static final void setLinkerImplementationForTesting(int type) { | 295 public static final void setImplementationForTesting(int type) { |
296 // Sanity check. This method may only be called during tests. | 296 // Sanity check. This method may only be called during tests. |
297 assertLinkerTestsAreEnabled(); | 297 assertLinkerTestsAreEnabled(); |
298 assertForTesting( | 298 assertForTesting( |
299 type == LINKER_IMPLEMENTATION_LEGACY || type == LINKER_IMPLEMENT
ATION_MODERN); | 299 type == LINKER_IMPLEMENTATION_LEGACY || type == LINKER_IMPLEMENT
ATION_MODERN); |
300 | 300 |
301 synchronized (sSingletonLock) { | 301 synchronized (sSingletonLock) { |
302 assertForTesting(sSingleton == null); | 302 assertForTesting(sSingleton == null); |
303 | 303 |
304 if (type == LINKER_IMPLEMENTATION_MODERN) { | 304 if (type == LINKER_IMPLEMENTATION_MODERN) { |
305 sSingleton = ModernLinker.create(); | 305 sSingleton = ModernLinker.create(); |
306 } else if (type == LINKER_IMPLEMENTATION_LEGACY) { | 306 } else if (type == LINKER_IMPLEMENTATION_LEGACY) { |
307 sSingleton = LegacyLinker.create(); | 307 sSingleton = LegacyLinker.create(); |
308 } else { | 308 } else { |
309 return; | 309 return; |
310 } | 310 } |
311 Log.i(TAG, "Forced linker: " + sSingleton.getClass().getName()); | 311 Log.i(TAG, "Forced linker: " + sSingleton.getClass().getName()); |
312 } | 312 } |
313 } | 313 } |
314 | 314 |
315 /** | 315 /** |
316 * Get Linker implementation type. | 316 * Get Linker implementation type. |
317 * For testing. | 317 * For testing. |
318 * | 318 * |
319 * @return LINKER_IMPLEMENTATION_LEGACY or LINKER_IMPLEMENTATION_MODERN | 319 * @return LINKER_IMPLEMENTATION_LEGACY or LINKER_IMPLEMENTATION_MODERN |
320 */ | 320 */ |
321 public int getLinkerImplementationForTesting() { | 321 public int getImplementationForTesting() { |
322 // Sanity check. This method may only be called during tests. | 322 // Sanity check. This method may only be called during tests. |
323 assertLinkerTestsAreEnabled(); | 323 assertLinkerTestsAreEnabled(); |
324 assertForTesting(sSingleton != null); | |
325 | 324 |
326 if (sSingleton instanceof ModernLinker) { | 325 synchronized (sSingletonLock) { |
327 return LINKER_IMPLEMENTATION_MODERN; | 326 assertForTesting(sSingleton != null); |
328 } else if (sSingleton instanceof LegacyLinker) { | 327 |
329 return LINKER_IMPLEMENTATION_LEGACY; | 328 if (sSingleton instanceof ModernLinker) { |
| 329 return LINKER_IMPLEMENTATION_MODERN; |
| 330 } else if (sSingleton instanceof LegacyLinker) { |
| 331 return LINKER_IMPLEMENTATION_LEGACY; |
| 332 } |
| 333 Log.e(TAG, "Invalid linker: " + sSingleton.getClass().getName()); |
| 334 return 0; |
330 } | 335 } |
331 Log.e(TAG, "Invalid linker: " + sSingleton.getClass().getName()); | |
332 return 0; | |
333 } | 336 } |
334 | 337 |
335 /** | 338 /** |
336 * A public interface used to run runtime linker tests after loading | 339 * A public interface used to run runtime linker tests after loading |
337 * libraries. Should only be used to implement the linker unit tests, | 340 * libraries. Should only be used to implement the linker unit tests, |
338 * which is controlled by the value of NativeLibraries.sEnableLinkerTests | 341 * which is controlled by the value of NativeLibraries.sEnableLinkerTests |
339 * configured at build time. | 342 * configured at build time. |
340 */ | 343 */ |
341 public interface TestRunner { | 344 public interface TestRunner { |
342 /** | 345 /** |
343 * Run runtime checks and return true if they all pass. | 346 * Run runtime checks and return true if they all pass. |
344 * | 347 * |
345 * @param memoryDeviceConfig The current memory device configuration. | 348 * @param memoryDeviceConfig The current memory device configuration. |
346 * @param inBrowserProcess true iff this is the browser process. | 349 * @param inBrowserProcess true iff this is the browser process. |
347 * @return true if all checks pass. | 350 * @return true if all checks pass. |
348 */ | 351 */ |
349 public boolean runChecks(int memoryDeviceConfig, boolean inBrowserProces
s); | 352 public boolean runChecks(int memoryDeviceConfig, boolean inBrowserProces
s); |
350 } | 353 } |
351 | 354 |
352 /** | 355 /** |
353 * Set the TestRunner by its class name. It will be instantiated at | 356 * Set the TestRunner by its class name. It will be instantiated at |
354 * runtime after all libraries are loaded. | 357 * runtime after all libraries are loaded. |
355 * | 358 * |
356 * @param testRunnerClassName null or a String for the class name of the | 359 * @param testRunnerClassName null or a String for the class name of the |
357 * TestRunner to use. | 360 * TestRunner to use. |
358 */ | 361 */ |
359 public void setTestRunnerClassNameForTesting(String testRunnerClassName) { | 362 public void setTestRunnerClassNameForTesting(String testRunnerClassName) { |
360 if (DEBUG) { | 363 if (DEBUG) { |
361 Log.i(TAG, "setTestRunnerByClassNameForTesting(" + testRunnerClassNa
me + ") called"); | 364 Log.i(TAG, "setTestRunnerClassNameForTesting(" + testRunnerClassName
+ ") called"); |
362 } | 365 } |
363 // Sanity check. This method may only be called during tests. | 366 // Sanity check. This method may only be called during tests. |
364 assertLinkerTestsAreEnabled(); | 367 assertLinkerTestsAreEnabled(); |
365 | 368 |
366 synchronized (mLock) { | 369 synchronized (mLock) { |
367 assertForTesting(mTestRunnerClassName == null); | 370 assertForTesting(mTestRunnerClassName == null); |
368 mTestRunnerClassName = testRunnerClassName; | 371 mTestRunnerClassName = testRunnerClassName; |
369 } | 372 } |
370 } | 373 } |
371 | 374 |
372 /** | 375 /** |
373 * Call this to retrieve the name of the current TestRunner class name | 376 * Call this to retrieve the name of the current TestRunner class name |
374 * if any. This can be useful to pass it from the browser process to | 377 * if any. This can be useful to pass it from the browser process to |
375 * child ones. | 378 * child ones. |
376 * | 379 * |
377 * @return null or a String holding the name of the class implementing | 380 * @return null or a String holding the name of the class implementing |
378 * the TestRunner set by calling setTestRunnerClassNameForTesting() previous
ly. | 381 * the TestRunner set by calling setTestRunnerClassNameForTesting() previous
ly. |
379 */ | 382 */ |
380 public String getTestRunnerClassNameForTesting() { | 383 public String getTestRunnerClassNameForTesting() { |
381 // Sanity check. This method may only be called during tests. | 384 // Sanity check. This method may only be called during tests. |
382 assertLinkerTestsAreEnabled(); | 385 assertLinkerTestsAreEnabled(); |
383 | 386 |
384 synchronized (mLock) { | 387 synchronized (mLock) { |
385 return mTestRunnerClassName; | 388 return mTestRunnerClassName; |
386 } | 389 } |
387 } | 390 } |
388 | 391 |
389 /** | 392 /** |
| 393 * Set up the Linker for a test. |
| 394 * Convenience function that calls setImplementationForTesting() to force an |
| 395 * implementation, and then setTestRunnerClassNameForTesting() to set the te
st |
| 396 * class name. |
| 397 * |
| 398 * On first call, instantiates a Linker of the requested type and sets its t
est |
| 399 * runner class name. On subsequent calls, checks that the singleton produce
d by |
| 400 * the first call matches the requested type and test runner class name. |
| 401 */ |
| 402 public static void setupForTesting(int type, String testRunnerClassName) { |
| 403 if (DEBUG) { |
| 404 Log.i(TAG, "setupForTesting(" + type + ", " + testRunnerClassName +
") called"); |
| 405 } |
| 406 // Sanity check. This method may only be called during tests. |
| 407 assertLinkerTestsAreEnabled(); |
| 408 |
| 409 synchronized (sSingletonLock) { |
| 410 // If this is the first call, configure the Linker to the given type
and test class. |
| 411 if (sSingleton == null) { |
| 412 setImplementationForTesting(type); |
| 413 sSingleton.setTestRunnerClassNameForTesting(testRunnerClassName)
; |
| 414 return; |
| 415 } |
| 416 |
| 417 // If not the first call, check that the Linker configuration matche
s this request. |
| 418 assertForTesting(sSingleton.getImplementationForTesting() == type); |
| 419 String ourTestRunnerClassName = sSingleton.getTestRunnerClassNameFor
Testing(); |
| 420 if (testRunnerClassName == null) { |
| 421 assertForTesting(ourTestRunnerClassName == null); |
| 422 } else { |
| 423 assertForTesting(ourTestRunnerClassName.equals(testRunnerClassNa
me)); |
| 424 } |
| 425 } |
| 426 } |
| 427 |
| 428 /** |
390 * Instantiate and run the current TestRunner, if any. The TestRunner implem
entation | 429 * Instantiate and run the current TestRunner, if any. The TestRunner implem
entation |
391 * must be instantiated _after_ all libraries are loaded to ensure that its | 430 * must be instantiated _after_ all libraries are loaded to ensure that its |
392 * native methods are properly registered. | 431 * native methods are properly registered. |
393 * | 432 * |
394 * @param memoryDeviceConfig LegacyLinker memory config, or 0 if unused | 433 * @param memoryDeviceConfig LegacyLinker memory config, or 0 if unused |
395 * @param inBrowserProcess true if in the browser process | 434 * @param inBrowserProcess true if in the browser process |
396 */ | 435 */ |
397 protected void runTestRunnerClassForTesting(int memoryDeviceConfig, boolean
inBrowserProcess) { | 436 protected void runTestRunnerClassForTesting(int memoryDeviceConfig, boolean
inBrowserProcess) { |
398 if (DEBUG) { | 437 if (DEBUG) { |
399 Log.i(TAG, "runTestRunnerClassForTesting called"); | 438 Log.i(TAG, "runTestRunnerClassForTesting called"); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 */ | 503 */ |
465 public boolean isChromiumLinkerLibrary(String library) { | 504 public boolean isChromiumLinkerLibrary(String library) { |
466 return library.equals(LINKER_JNI_LIBRARY) || library.equals(LINKER_JNI_L
IBRARY + ".cr"); | 505 return library.equals(LINKER_JNI_LIBRARY) || library.equals(LINKER_JNI_L
IBRARY + ".cr"); |
467 } | 506 } |
468 | 507 |
469 /** | 508 /** |
470 * Load the Linker JNI library. Throws UnsatisfiedLinkError on error. | 509 * Load the Linker JNI library. Throws UnsatisfiedLinkError on error. |
471 * In a component build, the suffix ".cr" is added to each library name, so | 510 * In a component build, the suffix ".cr" is added to each library name, so |
472 * if the initial load fails we retry with a suffix. | 511 * if the initial load fails we retry with a suffix. |
473 */ | 512 */ |
474 protected void loadLinkerJNILibrary() { | 513 protected static void loadLinkerJniLibrary() { |
475 String libName = "lib" + LINKER_JNI_LIBRARY + ".so"; | 514 String libName = "lib" + LINKER_JNI_LIBRARY + ".so"; |
476 if (DEBUG) { | 515 if (DEBUG) { |
477 Log.i(TAG, "Loading " + libName); | 516 Log.i(TAG, "Loading " + libName); |
478 } | 517 } |
479 try { | 518 try { |
480 System.loadLibrary(LINKER_JNI_LIBRARY); | 519 System.loadLibrary(LINKER_JNI_LIBRARY); |
481 } catch (UnsatisfiedLinkError e) { | 520 } catch (UnsatisfiedLinkError e) { |
482 Log.w(TAG, "Couldn't load " + libName + ", trying " + libName + ".so
"); | 521 Log.w(TAG, "Couldn't load " + libName + ", trying " + libName + ".cr
"); |
483 System.loadLibrary(LINKER_JNI_LIBRARY + ".cr"); | 522 System.loadLibrary(LINKER_JNI_LIBRARY + ".cr"); |
484 } | 523 } |
485 } | 524 } |
486 | 525 |
487 /** | 526 /** |
488 * Obtain a random base load address at which to place loaded libraries. | 527 * Obtain a random base load address at which to place loaded libraries. |
489 * | 528 * |
490 * @return new base load address | 529 * @return new base load address |
491 */ | 530 */ |
492 protected long getRandomBaseLoadAddress() { | 531 protected long getRandomBaseLoadAddress() { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 Log.i(TAG, "loadLibraryAtAnyAddress: " + zipFilePath + ", " + libFil
ePath); | 585 Log.i(TAG, "loadLibraryAtAnyAddress: " + zipFilePath + ", " + libFil
ePath); |
547 } | 586 } |
548 final boolean isFixedAddressPermitted = false; | 587 final boolean isFixedAddressPermitted = false; |
549 loadLibraryImpl(zipFilePath, libFilePath, isFixedAddressPermitted); | 588 loadLibraryImpl(zipFilePath, libFilePath, isFixedAddressPermitted); |
550 } | 589 } |
551 | 590 |
552 /** | 591 /** |
553 * Call this method to determine if the chromium project must load the libra
ry | 592 * Call this method to determine if the chromium project must load the libra
ry |
554 * directly from a zip file. | 593 * directly from a zip file. |
555 */ | 594 */ |
556 public boolean isInZipFile() { | 595 public static boolean isInZipFile() { |
557 // The auto-generated NativeLibraries.sUseLibraryInZipFile variable will
be true | 596 // The auto-generated NativeLibraries.sUseLibraryInZipFile variable will
be true |
558 // if the library remains embedded in the APK zip file on the target. | 597 // if the library remains embedded in the APK zip file on the target. |
559 return NativeLibraries.sUseLibraryInZipFile; | 598 return NativeLibraries.sUseLibraryInZipFile; |
560 } | 599 } |
561 | 600 |
562 /** | 601 /** |
563 * Call this method to determine if this chromium project must | 602 * Call this method to determine if this chromium project must |
564 * use this linker. If not, System.loadLibrary() should be used to load | 603 * use this linker. If not, System.loadLibrary() should be used to load |
565 * libraries instead. | 604 * libraries instead. |
566 */ | 605 */ |
567 public abstract boolean isUsed(); | 606 public static boolean isUsed() { |
| 607 // The auto-generated NativeLibraries.sUseLinker variable will be true i
f the |
| 608 // build has not explicitly disabled Linker features. |
| 609 return NativeLibraries.sUseLinker; |
| 610 } |
568 | 611 |
569 /** | 612 /** |
570 * Call this method to determine if the linker will try to use shared RELROs | 613 * Call this method to determine if the linker will try to use shared RELROs |
571 * for the browser process. | 614 * for the browser process. |
572 */ | 615 */ |
573 public abstract boolean isUsingBrowserSharedRelros(); | 616 public abstract boolean isUsingBrowserSharedRelros(); |
574 | 617 |
575 /** | 618 /** |
576 * Call this method just before loading any native shared libraries in this
process. | 619 * Call this method just before loading any native shared libraries in this
process. |
577 */ | 620 */ |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 * Return a random address that should be free to be mapped with the given s
ize. | 814 * Return a random address that should be free to be mapped with the given s
ize. |
772 * Maps an area large enough for the largest library we might attempt to loa
d, | 815 * Maps an area large enough for the largest library we might attempt to loa
d, |
773 * and if successful then unmaps it and returns the address of the area allo
cated | 816 * and if successful then unmaps it and returns the address of the area allo
cated |
774 * by the system (with ASLR). The idea is that this area should remain free
of | 817 * by the system (with ASLR). The idea is that this area should remain free
of |
775 * other mappings until we map our library into it. | 818 * other mappings until we map our library into it. |
776 * | 819 * |
777 * @return address to pass to future mmap, or 0 on error. | 820 * @return address to pass to future mmap, or 0 on error. |
778 */ | 821 */ |
779 private static native long nativeGetRandomBaseLoadAddress(); | 822 private static native long nativeGetRandomBaseLoadAddress(); |
780 } | 823 } |
OLD | NEW |