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 Chavez// This is the Android-specific Chromium linker, a tiny shared library 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// implementing a custom dynamic linker that can be used to load the 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// real Chromium libraries. 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// The main point of this linker is to be able to share the RELRO 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// section of libchrome.so (or equivalent) between renderer processes. 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// This source code *cannot* depend on anything from base/ or the C++ 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// STL, to keep the final library small, and avoid ugly dependency issues. 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "linker_jni.h" 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <sys/mman.h> 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <jni.h> 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stdlib.h> 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <string.h> 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "legacy_linker_jni.h" 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "modern_linker_jni.h" 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace chromium_android_linker { 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Variable containing LibInfo for the loaded library. 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezLibInfo_class s_lib_info_fields; 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Simple scoped UTF String class constructor. 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezString::String(JNIEnv* env, jstring str) { 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_ = env->GetStringUTFLength(str); 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ptr_ = static_cast<char*>(::malloc(size_ + 1)); 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Note: This runs before browser native code is loaded, and so cannot 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // rely on anything from base/. This means that we must use 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // GetStringUTFChars() and not base::android::ConvertJavaStringToUTF8(). 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // GetStringUTFChars() suffices because the only strings used here are 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // paths to APK files or names of shared libraries, all of which are 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // plain ASCII, defined and hard-coded by the Chromium Android build. 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // For more: see 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // https://crbug.com/508876 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Note: GetStringUTFChars() returns Java UTF-8 bytes. This is good 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // enough for the linker though. 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* bytes = env->GetStringUTFChars(str, nullptr); 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ::memcpy(ptr_, bytes, size_); 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ptr_[size_] = '\0'; 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez env->ReleaseStringUTFChars(str, bytes); 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Find the jclass JNI reference corresponding to a given |class_name|. 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// |env| is the current JNI environment handle. 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// On success, return true and set |*clazz|. 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool InitClassReference(JNIEnv* env, const char* class_name, jclass* clazz) { 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *clazz = env->FindClass(class_name); 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!*clazz) { 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_ERROR("Could not find class for %s", class_name); 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Initialize a jfieldID corresponding to the field of a given |clazz|, 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// with name |field_name| and signature |field_sig|. 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// |env| is the current JNI environment handle. 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// On success, return true and set |*field_id|. 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool InitFieldId(JNIEnv* env, 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jclass clazz, 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* field_name, 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* field_sig, 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jfieldID* field_id) { 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *field_id = env->GetFieldID(clazz, field_name, field_sig); 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!*field_id) { 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_ERROR("Could not find ID for field '%s'", field_name); 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_INFO("Found ID %p for field '%s'", *field_id, field_name); 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Initialize a jmethodID corresponding to the static method of a given 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// |clazz|, with name |method_name| and signature |method_sig|. 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// |env| is the current JNI environment handle. 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// On success, return true and set |*method_id|. 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool InitStaticMethodId(JNIEnv* env, 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jclass clazz, 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* method_name, 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* method_sig, 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jmethodID* method_id) { 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *method_id = env->GetStaticMethodID(clazz, method_name, method_sig); 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!*method_id) { 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_ERROR("Could not find ID for static method '%s'", method_name); 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_INFO("Found ID %p for static method '%s'", *method_id, method_name); 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Initialize a jfieldID corresponding to the static field of a given |clazz|, 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// with name |field_name| and signature |field_sig|. 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// |env| is the current JNI environment handle. 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// On success, return true and set |*field_id|. 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool InitStaticFieldId(JNIEnv* env, 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jclass clazz, 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* field_name, 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* field_sig, 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jfieldID* field_id) { 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *field_id = env->GetStaticFieldID(clazz, field_name, field_sig); 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!*field_id) { 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_ERROR("Could not find ID for static field '%s'", field_name); 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_INFO("Found ID %p for static field '%s'", *field_id, field_name); 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Initialize a jint corresponding to the static integer field of a class 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// with class name |class_name| and field name |field_name|. 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// |env| is the current JNI environment handle. 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// On success, return true and set |*value|. 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool InitStaticInt(JNIEnv* env, 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* class_name, 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* field_name, 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jint* value) { 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jclass clazz; 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!InitClassReference(env, class_name, &clazz)) 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jfieldID field_id; 134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!InitStaticFieldId(env, clazz, field_name, "I", &field_id)) 135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *value = env->GetStaticIntField(clazz, field_id); 138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_INFO("Found value %d for class '%s', static field '%s'", 139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *value, class_name, field_name); 140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use Android ASLR to create a random address into which we expect to be 145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// able to load libraries. Note that this is probabilistic; we unmap the 146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// address we get from mmap and assume we can re-map into it later. This 147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// works the majority of the time. If it doesn't, client code backs out and 148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// then loads the library normally at any available address. 149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// |env| is the current JNI environment handle, and |clazz| a class. 150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Returns the address selected by ASLR, or 0 on error. 151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezjlong GetRandomBaseLoadAddress(JNIEnv* env, jclass clazz) { 152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t bytes = kAddressSpaceReservationSize; 153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if RESERVE_BREAKPAD_GUARD_REGION 155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Pad the requested address space size for a Breakpad guard region. 156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bytes += kBreakpadGuardRegionBytes; 157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void* address = 160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mmap(nullptr, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (address == MAP_FAILED) { 162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_INFO("Random base load address not determinable"); 163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return 0; 164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez munmap(address, bytes); 166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if RESERVE_BREAKPAD_GUARD_REGION 168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Allow for a Breakpad guard region ahead of the returned address. 169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez address = reinterpret_cast<void*>( 170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez reinterpret_cast<uintptr_t>(address) + kBreakpadGuardRegionBytes); 171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_INFO("Random base load address is %p", address); 174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return static_cast<jlong>(reinterpret_cast<uintptr_t>(address)); 175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace { 178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezconst JNINativeMethod kNativeMethods[] = { 180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez {"nativeGetRandomBaseLoadAddress", 181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "(" 182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ")" 183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "J", 184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez reinterpret_cast<void*>(&GetRandomBaseLoadAddress)}, 185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}; 186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezconst size_t kNumNativeMethods = 188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sizeof(kNativeMethods) / sizeof(kNativeMethods[0]); 189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// JNI_OnLoad() initialization hook. 191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool LinkerJNIInit(JavaVM* vm, JNIEnv* env) { 192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_INFO("Entering"); 193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Register native methods. 195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jclass linker_class; 196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!InitClassReference(env, 197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "org/chromium/base/library_loader/Linker", 198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez &linker_class)) 199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_INFO("Registering native methods"); 202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (env->RegisterNatives(linker_class, kNativeMethods, kNumNativeMethods) < 0) 203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Find LibInfo field ids. 206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_INFO("Caching field IDs"); 207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!s_lib_info_fields.Init(env)) { 208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// JNI_OnLoad() hook called when the linker library is loaded through 215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// the regular System.LoadLibrary) API. This shall save the Java VM 216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// handle and initialize LibInfo fields. 217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezjint JNI_OnLoad(JavaVM* vm, void* reserved) { 218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_INFO("Entering"); 219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Get new JNIEnv 220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez JNIEnv* env; 221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (JNI_OK != vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4)) { 222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_ERROR("Could not create JNIEnv"); 223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return -1; 224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Initialize linker base and implementations. 227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!LinkerJNIInit(vm, env) 228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez || !LegacyLinkerJNIInit(vm, env) || !ModernLinkerJNIInit(vm, env)) { 229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return -1; 230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez LOG_INFO("Done"); 233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return JNI_VERSION_1_4; 234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace 237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace chromium_android_linker 238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezjint JNI_OnLoad(JavaVM* vm, void* reserved) { 240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return chromium_android_linker::JNI_OnLoad(vm, reserved); 241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 242