Commit 501c13b1 authored by Benoît Lizé's avatar Benoît Lizé Committed by Commit Bot

android: Remove the ability to load multiple library in custom linkers.

This was unused since at least 2016 (see crbug.com/657093). Remove the code to
support this both in LegacyLinker and ModernLinker. In the process, further
unify the two linkers, and refactor state tracking.

Bug: 979638

Change-Id: I4fad98228a841e1959a93f8ef5dbe5d29dfe7f30
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1715485Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Reviewed-by: default avatarEgor Pasko <pasko@chromium.org>
Commit-Queue: Benoit L <lizeb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683155}
parent ebf680f8
...@@ -168,10 +168,8 @@ public class LibraryLoader { ...@@ -168,10 +168,8 @@ public class LibraryLoader {
*/ */
public void ensureInitialized(@LibraryProcessType int processType) throws ProcessInitException { public void ensureInitialized(@LibraryProcessType int processType) throws ProcessInitException {
synchronized (mLock) { synchronized (mLock) {
if (mInitialized) { if (mInitialized) return;
// Already initialized, nothing to do.
return;
}
loadAlreadyLocked(ContextUtils.getApplicationContext().getApplicationInfo(), loadAlreadyLocked(ContextUtils.getApplicationContext().getApplicationInfo(),
false /* inZygote */); false /* inZygote */);
initializeAlreadyLocked(processType); initializeAlreadyLocked(processType);
...@@ -303,14 +301,14 @@ public class LibraryLoader { ...@@ -303,14 +301,14 @@ public class LibraryLoader {
boolean loadAtFixedAddress = true; boolean loadAtFixedAddress = true;
boolean success = true; boolean success = true;
try { try {
linker.loadLibrary(libFilePath); linker.loadLibrary(libFilePath, true /* isFixedAddressPermitted */);
} catch (UnsatisfiedLinkError e) { } catch (UnsatisfiedLinkError e) {
Log.w(TAG, "Failed to load native library with shared RELRO, retrying without"); Log.w(TAG, "Failed to load native library with shared RELRO, retrying without");
sLoadStatusRecorder.recordLoadAttempt( sLoadStatusRecorder.recordLoadAttempt(
false /* success */, isFirstAttempt, true /* loadAtFixedAddress */); false /* success */, isFirstAttempt, true /* loadAtFixedAddress */);
loadAtFixedAddress = false; loadAtFixedAddress = false;
success = false; success = false;
linker.loadLibraryNoFixedAddress(libFilePath); linker.loadLibrary(libFilePath, false /* isFixedAddressPermitted */);
success = true; success = true;
} finally { } finally {
sLoadStatusRecorder.recordLoadAttempt(success, isFirstAttempt, loadAtFixedAddress); sLoadStatusRecorder.recordLoadAttempt(success, isFirstAttempt, loadAtFixedAddress);
...@@ -332,43 +330,36 @@ public class LibraryLoader { ...@@ -332,43 +330,36 @@ public class LibraryLoader {
// triggering JNI_OnLoad in native code. // triggering JNI_OnLoad in native code.
// TODO(crbug.com/635567): Fix this properly. // TODO(crbug.com/635567): Fix this properly.
@SuppressLint({"DefaultLocale", "UnsafeDynamicallyLoadedCode"}) @SuppressLint({"DefaultLocale", "UnsafeDynamicallyLoadedCode"})
@GuardedBy("mLock")
private void loadAlreadyLocked(ApplicationInfo appInfo, boolean inZygote) private void loadAlreadyLocked(ApplicationInfo appInfo, boolean inZygote)
throws ProcessInitException { throws ProcessInitException {
try (TraceEvent te = TraceEvent.scoped("LibraryLoader.loadAlreadyLocked")) { try (TraceEvent te = TraceEvent.scoped("LibraryLoader.loadAlreadyLocked")) {
if (!mLoaded) { if (mLoaded) return;
assert !mInitialized; assert !mInitialized;
long startTime = SystemClock.uptimeMillis(); long startTime = SystemClock.uptimeMillis();
if (useChromiumLinker() && !inZygote) { if (useChromiumLinker() && !inZygote) {
// Load libraries using the Chromium linker.
Linker linker = Linker.getInstance(); Linker linker = Linker.getInstance();
String apkFilePath = isInZipFile() ? appInfo.sourceDir : null; // See base/android/linker/config.gni, the chromium linker is only enabled when we
linker.prepareLibraryLoad(apkFilePath); // have a single library.
// See base/android/linker/config.gni, the chromium linker is only enabled
// when we have a sinble library.
assert NativeLibraries.LIBRARIES.length == 1; assert NativeLibraries.LIBRARIES.length == 1;
for (String library : NativeLibraries.LIBRARIES) { String library = NativeLibraries.LIBRARIES[0];
// Don't self-load the linker. This is because the build system is
// not clever enough to understand that all the libraries packaged
// in the final .apk don't need to be explicitly loaded.
if (linker.isChromiumLinkerLibrary(library)) {
if (DEBUG) Log.i(TAG, "ignoring self-linker load");
continue;
}
if (apkFilePath != null) { if (isInZipFile()) {
Log.i(TAG, " Loading " + library + " from within " + apkFilePath); String sourceDir = appInfo.sourceDir;
linker.setApkFilePath(sourceDir);
Log.i(TAG, " Loading %s from within %s", library, sourceDir);
} else { } else {
Log.i(TAG, "Loading " + library); Log.i(TAG, "Loading %s", library);
} }
try { try {
// Load the library using this Linker. May throw UnsatisfiedLinkError. // Load the library using this Linker. May throw UnsatisfiedLinkError.
loadLibraryWithCustomLinkerAlreadyLocked(linker, loadLibraryWithCustomLinkerAlreadyLocked(
System.mapLibraryName(library), true /* isFirstAttempt */); linker, System.mapLibraryName(library), true /* isFirstAttempt */);
} catch (UnsatisfiedLinkError e) { } catch (UnsatisfiedLinkError e) {
if (!isInZipFile() && PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION) { if (!isInZipFile() && PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION) {
loadLibraryWithCustomLinkerAlreadyLocked(linker, loadLibraryWithCustomLinkerAlreadyLocked(linker,
...@@ -379,31 +370,28 @@ public class LibraryLoader { ...@@ -379,31 +370,28 @@ public class LibraryLoader {
throw(e); throw(e);
} }
} }
}
linker.finishLibraryLoad();
} else { } else {
setEnvForNative(); setEnvForNative();
preloadAlreadyLocked(appInfo); preloadAlreadyLocked(appInfo);
// If the libraries are located in the zip file, assert that the device API // If the libraries are located in the zip file, assert that the device API level is
// level is M or higher. On devices lower than M, the libraries should // M or higher. On devices lower than M, the libraries should always be loaded by
// always be loaded by LegacyLinker. // LegacyLinker.
assert !isInZipFile() || Build.VERSION.SDK_INT >= VERSION_CODES.M; assert !isInZipFile() || Build.VERSION.SDK_INT >= VERSION_CODES.M;
// Load libraries using the system linker. // Load libraries using the system linker.
for (String library : NativeLibraries.LIBRARIES) { for (String library : NativeLibraries.LIBRARIES) {
try { try {
if (!isInZipFile()) { if (!isInZipFile()) {
// The extract and retry logic isn't needed because this path is // The extract and retry logic isn't needed because this path is used
// used only for local development. // only for local development.
System.loadLibrary(library); System.loadLibrary(library);
} else { } else {
// Load directly from the APK. // Load directly from the APK.
boolean is64Bit = ApiHelperForM.isProcess64Bit(); boolean is64Bit = ApiHelperForM.isProcess64Bit();
String zipFilePath = appInfo.sourceDir; String zipFilePath = appInfo.sourceDir;
// In API level 23 and above, it’s possible to open a .so file // In API level 23 and above, it’s possible to open a .so file directly
// directly from the APK of the path form // from the APK of the path form
// "my_zip_file.zip!/libs/libstuff.so". See: // "my_zip_file.zip!/libs/libstuff.so". See:
// https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md#opening-shared-libraries-directly-from-an-apk // https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md#opening-shared-libraries-directly-from-an-apk
String libraryName = zipFilePath + "!/" String libraryName = zipFilePath + "!/"
...@@ -420,13 +408,10 @@ public class LibraryLoader { ...@@ -420,13 +408,10 @@ public class LibraryLoader {
long stopTime = SystemClock.uptimeMillis(); long stopTime = SystemClock.uptimeMillis();
mLibraryLoadTimeMs = stopTime - startTime; mLibraryLoadTimeMs = stopTime - startTime;
Log.i(TAG, String.format("Time to load native libraries: %d ms (timestamps %d-%d)", Log.i(TAG, "Time to load native libraries: %d ms (timestamps %d-%d)",
mLibraryLoadTimeMs, mLibraryLoadTimeMs, startTime % 10000, stopTime % 10000);
startTime % 10000,
stopTime % 10000));
mLoaded = true; mLoaded = true;
}
} catch (UnsatisfiedLinkError e) { } catch (UnsatisfiedLinkError e) {
throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED, e); throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED, e);
} }
...@@ -483,6 +468,7 @@ public class LibraryLoader { ...@@ -483,6 +468,7 @@ public class LibraryLoader {
// Switch the CommandLine over from Java to native if it hasn't already been done. // Switch the CommandLine over from Java to native if it hasn't already been done.
// This must happen after the code is loaded and after JNI is ready (since after the // This must happen after the code is loaded and after JNI is ready (since after the
// switch the Java CommandLine will delegate all calls the native CommandLine). // switch the Java CommandLine will delegate all calls the native CommandLine).
@GuardedBy("mLock")
private void ensureCommandLineSwitchedAlreadyLocked() { private void ensureCommandLineSwitchedAlreadyLocked() {
assert mLoaded; assert mLoaded;
if (mCommandLineSwitched) { if (mCommandLineSwitched) {
...@@ -493,6 +479,7 @@ public class LibraryLoader { ...@@ -493,6 +479,7 @@ public class LibraryLoader {
} }
// Invoke base::android::LibraryLoaded in library_loader_hooks.cc // Invoke base::android::LibraryLoaded in library_loader_hooks.cc
@GuardedBy("mLock")
private void initializeAlreadyLocked(@LibraryProcessType int processType) private void initializeAlreadyLocked(@LibraryProcessType int processType)
throws ProcessInitException { throws ProcessInitException {
if (mInitialized) { if (mInitialized) {
......
...@@ -420,22 +420,6 @@ bool LoadNoSharedRelocations(const String& path) { ...@@ -420,22 +420,6 @@ bool LoadNoSharedRelocations(const String& path) {
} // namespace } // namespace
// Get the CPU ABI string for which the linker is running.
//
// The returned string is used to construct the path to libchrome.so when
// loading directly from APK.
//
// |env| is the current JNI environment handle.
// |clazz| is the static class handle for org.chromium.base.Linker,
// and is ignored here.
// Returns the CPU ABI string for which the linker is running.
JNI_GENERATOR_EXPORT jstring
Java_org_chromium_base_library_1loader_ModernLinker_nativeGetCpuAbi(
JNIEnv* env,
jclass clazz) {
return env->NewStringUTF(CURRENT_ABI);
}
JNI_GENERATOR_EXPORT jboolean JNI_GENERATOR_EXPORT jboolean
Java_org_chromium_base_library_1loader_ModernLinker_nativeLoadLibraryCreateRelros( Java_org_chromium_base_library_1loader_ModernLinker_nativeLoadLibraryCreateRelros(
JNIEnv* env, JNIEnv* env,
......
...@@ -83,9 +83,7 @@ public class ContentChildProcessServiceDelegate implements ChildProcessServiceDe ...@@ -83,9 +83,7 @@ public class ContentChildProcessServiceDelegate implements ChildProcessServiceDe
if (LibraryLoader.useChromiumLinker() && !LibraryLoader.getInstance().isLoadedByZygote()) { if (LibraryLoader.useChromiumLinker() && !LibraryLoader.getInstance().isLoadedByZygote()) {
Bundle sharedRelros = connectionBundle.getBundle(Linker.EXTRA_LINKER_SHARED_RELROS); Bundle sharedRelros = connectionBundle.getBundle(Linker.EXTRA_LINKER_SHARED_RELROS);
if (sharedRelros != null) { if (sharedRelros != null) getLinker().provideSharedRelros(sharedRelros);
getLinker().useSharedRelros(sharedRelros);
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment