Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(468)

Side by Side Diff: android/linker/legacy_linker_jni.cc

Issue 2043183002: Update to Chromium //base at Chromium commit 01cb97b2e09618bbc3a60c7348f0a844eea20547. (Closed) Base URL: https://github.com/domokit/base.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « android/linker/legacy_linker_jni.h ('k') | android/linker/linker_jni.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 // This is the Android-specific Chromium linker, a tiny shared library 5 // This is the version of the Android-specific Chromium linker that uses
6 // implementing a custom dynamic linker that can be used to load the 6 // the crazy linker to load libraries.
7 // real Chromium libraries (e.g. libcontentshell.so).
8
9 // The main point of this linker is to be able to share the RELRO
10 // section of libcontentshell.so (or equivalent) between the browser and
11 // renderer process.
12 7
13 // This source code *cannot* depend on anything from base/ or the C++ 8 // This source code *cannot* depend on anything from base/ or the C++
14 // STL, to keep the final library small, and avoid ugly dependency issues. 9 // STL, to keep the final library small, and avoid ugly dependency issues.
15 10
16 #include <android/log.h> 11 #include "legacy_linker_jni.h"
12
17 #include <crazy_linker.h> 13 #include <crazy_linker.h>
18 #include <fcntl.h> 14 #include <fcntl.h>
19 #include <jni.h> 15 #include <jni.h>
20 #include <limits.h> 16 #include <limits.h>
21 #include <stdlib.h> 17 #include <stdlib.h>
22 #include <sys/mman.h>
23 #include <unistd.h> 18 #include <unistd.h>
24 19
25 // See commentary in crazy_linker_elf_loader.cpp for the effect of setting 20 #include "linker_jni.h"
26 // this. If changing there, change here also.
27 //
28 // For more, see:
29 // https://crbug.com/504410
30 #define RESERVE_BREAKPAD_GUARD_REGION 1
31 21
32 // Set this to 1 to enable debug traces to the Android log. 22 namespace chromium_android_linker {
33 // Note that LOG() from "base/logging.h" cannot be used, since it is
34 // in base/ which hasn't been loaded yet.
35 #define DEBUG 0
36
37 #define TAG "chromium_android_linker"
38
39 #if DEBUG
40 #define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
41 #else
42 #define LOG_INFO(...) ((void)0)
43 #endif
44 #define LOG_ERROR(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
45
46 #define UNUSED __attribute__((unused))
47
48 namespace { 23 namespace {
49 24
50 // A simply scoped UTF String class that can be initialized from
51 // a Java jstring handle. Modeled like std::string, which cannot
52 // be used here.
53 class String {
54 public:
55 String(JNIEnv* env, jstring str);
56
57 ~String() {
58 if (ptr_)
59 ::free(ptr_);
60 }
61
62 const char* c_str() const { return ptr_ ? ptr_ : ""; }
63 size_t size() const { return size_; }
64
65 private:
66 char* ptr_;
67 size_t size_;
68 };
69
70 String::String(JNIEnv* env, jstring str) {
71 size_ = env->GetStringUTFLength(str);
72 ptr_ = static_cast<char*>(::malloc(size_ + 1));
73
74 // Note: This runs before browser native code is loaded, and so cannot
75 // rely on anything from base/. This means that we must use
76 // GetStringUTFChars() and not base::android::ConvertJavaStringToUTF8().
77 //
78 // GetStringUTFChars() suffices because the only strings used here are
79 // paths to APK files or names of shared libraries, all of which are
80 // plain ASCII, defined and hard-coded by the Chromium Android build.
81 //
82 // For more: see
83 // https://crbug.com/508876
84 //
85 // Note: GetStringUTFChars() returns Java UTF-8 bytes. This is good
86 // enough for the linker though.
87 const char* bytes = env->GetStringUTFChars(str, NULL);
88 ::memcpy(ptr_, bytes, size_);
89 ptr_[size_] = '\0';
90
91 env->ReleaseStringUTFChars(str, bytes);
92 }
93
94 // Return true iff |address| is a valid address for the target CPU.
95 bool IsValidAddress(jlong address) {
96 return static_cast<jlong>(static_cast<size_t>(address)) == address;
97 }
98
99 // Find the jclass JNI reference corresponding to a given |class_name|.
100 // |env| is the current JNI environment handle.
101 // On success, return true and set |*clazz|.
102 bool InitClassReference(JNIEnv* env, const char* class_name, jclass* clazz) {
103 *clazz = env->FindClass(class_name);
104 if (!*clazz) {
105 LOG_ERROR("Could not find class for %s", class_name);
106 return false;
107 }
108 return true;
109 }
110
111 // Initialize a jfieldID corresponding to the field of a given |clazz|,
112 // with name |field_name| and signature |field_sig|.
113 // |env| is the current JNI environment handle.
114 // On success, return true and set |*field_id|.
115 bool InitFieldId(JNIEnv* env,
116 jclass clazz,
117 const char* field_name,
118 const char* field_sig,
119 jfieldID* field_id) {
120 *field_id = env->GetFieldID(clazz, field_name, field_sig);
121 if (!*field_id) {
122 LOG_ERROR("Could not find ID for field '%s'", field_name);
123 return false;
124 }
125 LOG_INFO("%s: Found ID %p for field '%s'", __FUNCTION__, *field_id,
126 field_name);
127 return true;
128 }
129
130 // Initialize a jmethodID corresponding to the static method of a given
131 // |clazz|, with name |method_name| and signature |method_sig|.
132 // |env| is the current JNI environment handle.
133 // On success, return true and set |*method_id|.
134 bool InitStaticMethodId(JNIEnv* env,
135 jclass clazz,
136 const char* method_name,
137 const char* method_sig,
138 jmethodID* method_id) {
139 *method_id = env->GetStaticMethodID(clazz, method_name, method_sig);
140 if (!*method_id) {
141 LOG_ERROR("Could not find ID for static method '%s'", method_name);
142 return false;
143 }
144 LOG_INFO("%s: Found ID %p for static method '%s'", __FUNCTION__, *method_id,
145 method_name);
146 return true;
147 }
148
149 // Initialize a jfieldID corresponding to the static field of a given |clazz|,
150 // with name |field_name| and signature |field_sig|.
151 // |env| is the current JNI environment handle.
152 // On success, return true and set |*field_id|.
153 bool InitStaticFieldId(JNIEnv* env,
154 jclass clazz,
155 const char* field_name,
156 const char* field_sig,
157 jfieldID* field_id) {
158 *field_id = env->GetStaticFieldID(clazz, field_name, field_sig);
159 if (!*field_id) {
160 LOG_ERROR("Could not find ID for static field '%s'", field_name);
161 return false;
162 }
163 LOG_INFO("%s: Found ID %p for static field '%s'", __FUNCTION__, *field_id,
164 field_name);
165 return true;
166 }
167
168 // Initialize a jint corresponding to the static integer field of a class
169 // with class name |class_name| and field name |field_name|.
170 // |env| is the current JNI environment handle.
171 // On success, return true and set |*value|.
172 bool InitStaticInt(JNIEnv* env,
173 const char* class_name,
174 const char* field_name,
175 jint* value) {
176 jclass clazz;
177 if (!InitClassReference(env, class_name, &clazz))
178 return false;
179
180 jfieldID field_id;
181 if (!InitStaticFieldId(env, clazz, field_name, "I", &field_id))
182 return false;
183
184 *value = env->GetStaticIntField(clazz, field_id);
185 LOG_INFO("%s: Found value %d for class '%s', static field '%s'", __FUNCTION__,
186 *value, class_name, field_name);
187
188 return true;
189 }
190
191 // A class used to model the field IDs of the org.chromium.base.Linker
192 // LibInfo inner class, used to communicate data with the Java side
193 // of the linker.
194 struct LibInfo_class {
195 jfieldID load_address_id;
196 jfieldID load_size_id;
197 jfieldID relro_start_id;
198 jfieldID relro_size_id;
199 jfieldID relro_fd_id;
200
201 // Initialize an instance.
202 bool Init(JNIEnv* env) {
203 jclass clazz;
204 if (!InitClassReference(
205 env, "org/chromium/base/library_loader/Linker$LibInfo", &clazz)) {
206 return false;
207 }
208
209 return InitFieldId(env, clazz, "mLoadAddress", "J", &load_address_id) &&
210 InitFieldId(env, clazz, "mLoadSize", "J", &load_size_id) &&
211 InitFieldId(env, clazz, "mRelroStart", "J", &relro_start_id) &&
212 InitFieldId(env, clazz, "mRelroSize", "J", &relro_size_id) &&
213 InitFieldId(env, clazz, "mRelroFd", "I", &relro_fd_id);
214 }
215
216 void SetLoadInfo(JNIEnv* env,
217 jobject library_info_obj,
218 size_t load_address,
219 size_t load_size) {
220 env->SetLongField(library_info_obj, load_address_id, load_address);
221 env->SetLongField(library_info_obj, load_size_id, load_size);
222 }
223
224 // Use this instance to convert a RelroInfo reference into
225 // a crazy_library_info_t.
226 void GetRelroInfo(JNIEnv* env,
227 jobject library_info_obj,
228 size_t* relro_start,
229 size_t* relro_size,
230 int* relro_fd) {
231 *relro_start = static_cast<size_t>(
232 env->GetLongField(library_info_obj, relro_start_id));
233
234 *relro_size =
235 static_cast<size_t>(env->GetLongField(library_info_obj, relro_size_id));
236
237 *relro_fd = env->GetIntField(library_info_obj, relro_fd_id);
238 }
239
240 void SetRelroInfo(JNIEnv* env,
241 jobject library_info_obj,
242 size_t relro_start,
243 size_t relro_size,
244 int relro_fd) {
245 env->SetLongField(library_info_obj, relro_start_id, relro_start);
246 env->SetLongField(library_info_obj, relro_size_id, relro_size);
247 env->SetIntField(library_info_obj, relro_fd_id, relro_fd);
248 }
249 };
250
251 static LibInfo_class s_lib_info_fields;
252
253 // Retrieve the SDK build version and pass it into the crazy linker. This 25 // Retrieve the SDK build version and pass it into the crazy linker. This
254 // needs to be done early in initialization, before any other crazy linker 26 // needs to be done early in initialization, before any other crazy linker
255 // code is run. 27 // code is run.
256 // |env| is the current JNI environment handle. 28 // |env| is the current JNI environment handle.
257 // On success, return true. 29 // On success, return true.
258 bool InitSDKVersionInfo(JNIEnv* env) { 30 bool InitSDKVersionInfo(JNIEnv* env) {
259 jint value = 0; 31 jint value = 0;
260 if (!InitStaticInt(env, "android/os/Build$VERSION", "SDK_INT", &value)) 32 if (!InitStaticInt(env, "android/os/Build$VERSION", "SDK_INT", &value))
261 return false; 33 return false;
262 34
263 crazy_set_sdk_build_version(static_cast<int>(value)); 35 crazy_set_sdk_build_version(static_cast<int>(value));
264 LOG_INFO("%s: Set SDK build version to %d", __FUNCTION__, 36 LOG_INFO("Set SDK build version to %d", static_cast<int>(value));
265 static_cast<int>(value));
266 37
267 return true; 38 return true;
268 } 39 }
269 40
270 // The linker uses a single crazy_context_t object created on demand. 41 // The linker uses a single crazy_context_t object created on demand.
271 // There is no need to protect this against concurrent access, locking 42 // There is no need to protect this against concurrent access, locking
272 // is already handled on the Java side. 43 // is already handled on the Java side.
273 static crazy_context_t* s_crazy_context; 44 crazy_context_t* GetCrazyContext() {
45 static crazy_context_t* s_crazy_context = nullptr;
274 46
275 crazy_context_t* GetCrazyContext() {
276 if (!s_crazy_context) { 47 if (!s_crazy_context) {
277 // Create new context. 48 // Create new context.
278 s_crazy_context = crazy_context_create(); 49 s_crazy_context = crazy_context_create();
279 50
280 // Ensure libraries located in the same directory as the linker 51 // Ensure libraries located in the same directory as the linker
281 // can be loaded before system ones. 52 // can be loaded before system ones.
282 crazy_context_add_search_path_for_address( 53 crazy_context_add_search_path_for_address(
283 s_crazy_context, reinterpret_cast<void*>(&s_crazy_context)); 54 s_crazy_context, reinterpret_cast<void*>(&s_crazy_context));
284 } 55 }
285 56
286 return s_crazy_context; 57 return s_crazy_context;
287 } 58 }
288 59
289 // A scoped crazy_library_t that automatically closes the handle 60 // A scoped crazy_library_t that automatically closes the handle
290 // on scope exit, unless Release() has been called. 61 // on scope exit, unless Release() has been called.
291 class ScopedLibrary { 62 class ScopedLibrary {
292 public: 63 public:
293 ScopedLibrary() : lib_(NULL) {} 64 ScopedLibrary() : lib_(nullptr) {}
294 65
295 ~ScopedLibrary() { 66 ~ScopedLibrary() {
296 if (lib_) 67 if (lib_)
297 crazy_library_close_with_context(lib_, GetCrazyContext()); 68 crazy_library_close_with_context(lib_, GetCrazyContext());
298 } 69 }
299 70
300 crazy_library_t* Get() { return lib_; } 71 crazy_library_t* Get() { return lib_; }
301 72
302 crazy_library_t** GetPtr() { return &lib_; } 73 crazy_library_t** GetPtr() { return &lib_; }
303 74
304 crazy_library_t* Release() { 75 crazy_library_t* Release() {
305 crazy_library_t* ret = lib_; 76 crazy_library_t* ret = lib_;
306 lib_ = NULL; 77 lib_ = nullptr;
307 return ret; 78 return ret;
308 } 79 }
309 80
310 private: 81 private:
311 crazy_library_t* lib_; 82 crazy_library_t* lib_;
312 }; 83 };
313 84
314 namespace {
315
316 template <class LibraryOpener> 85 template <class LibraryOpener>
317 bool GenericLoadLibrary(JNIEnv* env, 86 bool GenericLoadLibrary(JNIEnv* env,
318 const char* library_name, 87 const char* library_name,
319 jlong load_address, 88 jlong load_address,
320 jobject lib_info_obj, 89 jobject lib_info_obj,
321 const LibraryOpener& opener) { 90 const LibraryOpener& opener) {
91 LOG_INFO("Called for %s, at address 0x%llx", library_name, load_address);
322 crazy_context_t* context = GetCrazyContext(); 92 crazy_context_t* context = GetCrazyContext();
323 93
324 if (!IsValidAddress(load_address)) { 94 if (!IsValidAddress(load_address)) {
325 LOG_ERROR("%s: Invalid address 0x%llx", __FUNCTION__, load_address); 95 LOG_ERROR("Invalid address 0x%llx", load_address);
326 return false; 96 return false;
327 } 97 }
328 98
329 // Set the desired load address (0 means randomize it). 99 // Set the desired load address (0 means randomize it).
330 crazy_context_set_load_address(context, static_cast<size_t>(load_address)); 100 crazy_context_set_load_address(context, static_cast<size_t>(load_address));
331 101
332 ScopedLibrary library; 102 ScopedLibrary library;
333 if (!opener.Open(library.GetPtr(), library_name, context)) { 103 if (!opener.Open(library.GetPtr(), library_name, context)) {
334 return false; 104 return false;
335 } 105 }
336 106
337 crazy_library_info_t info; 107 crazy_library_info_t info;
338 if (!crazy_library_get_info(library.Get(), context, &info)) { 108 if (!crazy_library_get_info(library.Get(), context, &info)) {
339 LOG_ERROR("%s: Could not get library information for %s: %s", __FUNCTION__, 109 LOG_ERROR("Could not get library information for %s: %s", library_name,
340 library_name, crazy_context_get_error(context)); 110 crazy_context_get_error(context));
341 return false; 111 return false;
342 } 112 }
343 113
344 // Release library object to keep it alive after the function returns. 114 // Release library object to keep it alive after the function returns.
345 library.Release(); 115 library.Release();
346 116
347 s_lib_info_fields.SetLoadInfo(env, lib_info_obj, info.load_address, 117 s_lib_info_fields.SetLoadInfo(env, lib_info_obj, info.load_address,
348 info.load_size); 118 info.load_size);
349 LOG_INFO("%s: Success loading library %s", __FUNCTION__, library_name); 119 LOG_INFO("Success loading library %s", library_name);
350 return true; 120 return true;
351 } 121 }
352 122
353 // Used for opening the library in a regular file. 123 // Used for opening the library in a regular file.
354 class FileLibraryOpener { 124 class FileLibraryOpener {
355 public: 125 public:
356 bool Open(crazy_library_t** library, 126 bool Open(crazy_library_t** library,
357 const char* library_name, 127 const char* library_name,
358 crazy_context_t* context) const; 128 crazy_context_t* context) const;
359 }; 129 };
360 130
361 bool FileLibraryOpener::Open(crazy_library_t** library, 131 bool FileLibraryOpener::Open(crazy_library_t** library,
362 const char* library_name, 132 const char* library_name,
363 crazy_context_t* context) const { 133 crazy_context_t* context) const {
364 if (!crazy_library_open(library, library_name, context)) { 134 if (!crazy_library_open(library, library_name, context)) {
365 LOG_ERROR("%s: Could not open %s: %s", __FUNCTION__, library_name, 135 LOG_ERROR("Could not open %s: %s", library_name,
366 crazy_context_get_error(context)); 136 crazy_context_get_error(context));
367 return false; 137 return false;
368 } 138 }
369 return true; 139 return true;
370 } 140 }
371 141
372 // Used for opening the library in a zip file. 142 // Used for opening the library in a zip file.
373 class ZipLibraryOpener { 143 class ZipLibraryOpener {
374 public: 144 public:
375 explicit ZipLibraryOpener(const char* zip_file) : zip_file_(zip_file) {} 145 explicit ZipLibraryOpener(const char* zip_file) : zip_file_(zip_file) {}
376 bool Open(crazy_library_t** library, 146 bool Open(crazy_library_t** library,
377 const char* library_name, 147 const char* library_name,
378 crazy_context_t* context) const; 148 crazy_context_t* context) const;
379 149
380 private: 150 private:
381 const char* zip_file_; 151 const char* zip_file_;
382 }; 152 };
383 153
384 bool ZipLibraryOpener::Open(crazy_library_t** library, 154 bool ZipLibraryOpener::Open(crazy_library_t** library,
385 const char* library_name, 155 const char* library_name,
386 crazy_context_t* context) const { 156 crazy_context_t* context) const {
387 if (!crazy_library_open_in_zip_file(library, zip_file_, library_name, 157 if (!crazy_library_open_in_zip_file(library, zip_file_, library_name,
388 context)) { 158 context)) {
389 LOG_ERROR("%s: Could not open %s in zip file %s: %s", __FUNCTION__, 159 LOG_ERROR("Could not open %s in zip file %s: %s", library_name, zip_file_,
390 library_name, zip_file_, crazy_context_get_error(context)); 160 crazy_context_get_error(context));
391 return false; 161 return false;
392 } 162 }
393 return true; 163 return true;
394 } 164 }
395 165
396 } // unnamed namespace
397
398 // Load a library with the chromium linker. This will also call its 166 // Load a library with the chromium linker. This will also call its
399 // JNI_OnLoad() method, which shall register its methods. Note that 167 // JNI_OnLoad() method, which shall register its methods. Note that
400 // lazy native method resolution will _not_ work after this, because 168 // lazy native method resolution will _not_ work after this, because
401 // Dalvik uses the system's dlsym() which won't see the new library, 169 // Dalvik uses the system's dlsym() which won't see the new library,
402 // so explicit registration is mandatory. 170 // so explicit registration is mandatory.
171 //
403 // |env| is the current JNI environment handle. 172 // |env| is the current JNI environment handle.
404 // |clazz| is the static class handle for org.chromium.base.Linker, 173 // |clazz| is the static class handle for org.chromium.base.Linker,
405 // and is ignored here. 174 // and is ignored here.
406 // |library_name| is the library name (e.g. libfoo.so). 175 // |library_name| is the library name (e.g. libfoo.so).
407 // |load_address| is an explicit load address. 176 // |load_address| is an explicit load address.
408 // |library_info| is a LibInfo handle used to communicate information 177 // |library_info| is a LibInfo handle used to communicate information
409 // with the Java side. 178 // with the Java side.
410 // Return true on success. 179 // Return true on success.
411 jboolean LoadLibrary(JNIEnv* env, 180 jboolean LoadLibrary(JNIEnv* env,
412 jclass clazz, 181 jclass clazz,
413 jstring library_name, 182 jstring library_name,
414 jlong load_address, 183 jlong load_address,
415 jobject lib_info_obj) { 184 jobject lib_info_obj) {
416 String lib_name(env, library_name); 185 String lib_name(env, library_name);
417 FileLibraryOpener opener; 186 FileLibraryOpener opener;
187
418 return GenericLoadLibrary(env, lib_name.c_str(), 188 return GenericLoadLibrary(env, lib_name.c_str(),
419 static_cast<size_t>(load_address), lib_info_obj, 189 static_cast<size_t>(load_address), lib_info_obj,
420 opener); 190 opener);
421 } 191 }
422 192
423 // Load a library from a zipfile with the chromium linker. The 193 // Load a library from a zipfile with the chromium linker. The
424 // library in the zipfile must be uncompressed and page aligned. 194 // library in the zipfile must be uncompressed and page aligned.
425 // The basename of the library is given. The library is expected 195 // The basename of the library is given. The library is expected
426 // to be lib/<abi_tag>/crazy.<basename>. The <abi_tag> used will be the 196 // to be lib/<abi_tag>/crazy.<basename>. The <abi_tag> used will be the
427 // same as the abi for this linker. The "crazy." prefix is included 197 // same as the abi for this linker. The "crazy." prefix is included
(...skipping 16 matching lines...) Expand all
444 // Returns true on success. 214 // Returns true on success.
445 jboolean LoadLibraryInZipFile(JNIEnv* env, 215 jboolean LoadLibraryInZipFile(JNIEnv* env,
446 jclass clazz, 216 jclass clazz,
447 jstring zipfile_name, 217 jstring zipfile_name,
448 jstring library_name, 218 jstring library_name,
449 jlong load_address, 219 jlong load_address,
450 jobject lib_info_obj) { 220 jobject lib_info_obj) {
451 String zipfile_name_str(env, zipfile_name); 221 String zipfile_name_str(env, zipfile_name);
452 String lib_name(env, library_name); 222 String lib_name(env, library_name);
453 ZipLibraryOpener opener(zipfile_name_str.c_str()); 223 ZipLibraryOpener opener(zipfile_name_str.c_str());
224
454 return GenericLoadLibrary(env, lib_name.c_str(), 225 return GenericLoadLibrary(env, lib_name.c_str(),
455 static_cast<size_t>(load_address), lib_info_obj, 226 static_cast<size_t>(load_address), lib_info_obj,
456 opener); 227 opener);
457 } 228 }
458 229
459 // Class holding the Java class and method ID for the Java side Linker 230 // Class holding the Java class and method ID for the Java side Linker
460 // postCallbackOnMainThread method. 231 // postCallbackOnMainThread method.
461 struct JavaCallbackBindings_class { 232 struct JavaCallbackBindings_class {
462 jclass clazz; 233 jclass clazz;
463 jmethodID method_id; 234 jmethodID method_id;
(...skipping 10 matching lines...) Expand all
474 245
475 // Designated receiver function for callbacks from Java. Its name is known 246 // Designated receiver function for callbacks from Java. Its name is known
476 // to the Java side. 247 // to the Java side.
477 // |env| is the current JNI environment handle and is ignored here. 248 // |env| is the current JNI environment handle and is ignored here.
478 // |clazz| is the static class handle for org.chromium.base.Linker, 249 // |clazz| is the static class handle for org.chromium.base.Linker,
479 // and is ignored here. 250 // and is ignored here.
480 // |arg| is a pointer to an allocated crazy_callback_t, deleted after use. 251 // |arg| is a pointer to an allocated crazy_callback_t, deleted after use.
481 void RunCallbackOnUiThread(JNIEnv* env, jclass clazz, jlong arg) { 252 void RunCallbackOnUiThread(JNIEnv* env, jclass clazz, jlong arg) {
482 crazy_callback_t* callback = reinterpret_cast<crazy_callback_t*>(arg); 253 crazy_callback_t* callback = reinterpret_cast<crazy_callback_t*>(arg);
483 254
484 LOG_INFO("%s: Called back from java with handler %p, opaque %p", __FUNCTION__, 255 LOG_INFO("Called back from java with handler %p, opaque %p",
485 callback->handler, callback->opaque); 256 callback->handler, callback->opaque);
486 257
487 crazy_callback_run(callback); 258 crazy_callback_run(callback);
488 delete callback; 259 delete callback;
489 } 260 }
490 261
491 // Request a callback from Java. The supplied crazy_callback_t is valid only 262 // Request a callback from Java. The supplied crazy_callback_t is valid only
492 // for the duration of this call, so we copy it to a newly allocated 263 // for the duration of this call, so we copy it to a newly allocated
493 // crazy_callback_t and then call the Java side's postCallbackOnMainThread. 264 // crazy_callback_t and then call the Java side's postCallbackOnMainThread.
494 // This will call back to to our RunCallbackOnUiThread some time 265 // This will call back to to our RunCallbackOnUiThread some time
(...skipping 15 matching lines...) Expand all
510 if (JNI_OK != 281 if (JNI_OK !=
511 vm->GetEnv(reinterpret_cast<void**>(&env), minimum_jni_version)) { 282 vm->GetEnv(reinterpret_cast<void**>(&env), minimum_jni_version)) {
512 LOG_ERROR("Could not create JNIEnv"); 283 LOG_ERROR("Could not create JNIEnv");
513 return false; 284 return false;
514 } 285 }
515 286
516 // Copy the callback; the one passed as an argument may be temporary. 287 // Copy the callback; the one passed as an argument may be temporary.
517 crazy_callback_t* callback = new crazy_callback_t(); 288 crazy_callback_t* callback = new crazy_callback_t();
518 *callback = *callback_request; 289 *callback = *callback_request;
519 290
520 LOG_INFO("%s: Calling back to java with handler %p, opaque %p", __FUNCTION__, 291 LOG_INFO("Calling back to java with handler %p, opaque %p", callback->handler,
521 callback->handler, callback->opaque); 292 callback->opaque);
522 293
523 jlong arg = static_cast<jlong>(reinterpret_cast<uintptr_t>(callback)); 294 jlong arg = static_cast<jlong>(reinterpret_cast<uintptr_t>(callback));
524 295
525 env->CallStaticVoidMethod(s_java_callback_bindings.clazz, 296 env->CallStaticVoidMethod(s_java_callback_bindings.clazz,
526 s_java_callback_bindings.method_id, arg); 297 s_java_callback_bindings.method_id, arg);
527 298
528 // Back out and return false if we encounter a JNI exception. 299 // Back out and return false if we encounter a JNI exception.
529 if (env->ExceptionCheck() == JNI_TRUE) { 300 if (env->ExceptionCheck() == JNI_TRUE) {
530 env->ExceptionDescribe(); 301 env->ExceptionDescribe();
531 env->ExceptionClear(); 302 env->ExceptionClear();
532 delete callback; 303 delete callback;
533 return false; 304 return false;
534 } 305 }
535 306
536 return true; 307 return true;
537 } 308 }
538 309
539 jboolean CreateSharedRelro(JNIEnv* env, 310 jboolean CreateSharedRelro(JNIEnv* env,
540 jclass clazz, 311 jclass clazz,
541 jstring library_name, 312 jstring library_name,
542 jlong load_address, 313 jlong load_address,
543 jobject lib_info_obj) { 314 jobject lib_info_obj) {
544 String lib_name(env, library_name); 315 String lib_name(env, library_name);
545 316
546 LOG_INFO("%s: Called for %s", __FUNCTION__, lib_name.c_str()); 317 LOG_INFO("Called for %s", lib_name.c_str());
547 318
548 if (!IsValidAddress(load_address)) { 319 if (!IsValidAddress(load_address)) {
549 LOG_ERROR("%s: Invalid address 0x%llx", __FUNCTION__, load_address); 320 LOG_ERROR("Invalid address 0x%llx", load_address);
550 return false; 321 return false;
551 } 322 }
552 323
553 ScopedLibrary library; 324 ScopedLibrary library;
554 if (!crazy_library_find_by_name(lib_name.c_str(), library.GetPtr())) { 325 if (!crazy_library_find_by_name(lib_name.c_str(), library.GetPtr())) {
555 LOG_ERROR("%s: Could not find %s", __FUNCTION__, lib_name.c_str()); 326 LOG_ERROR("Could not find %s", lib_name.c_str());
556 return false; 327 return false;
557 } 328 }
558 329
559 crazy_context_t* context = GetCrazyContext(); 330 crazy_context_t* context = GetCrazyContext();
560 size_t relro_start = 0; 331 size_t relro_start = 0;
561 size_t relro_size = 0; 332 size_t relro_size = 0;
562 int relro_fd = -1; 333 int relro_fd = -1;
563 334
564 if (!crazy_library_create_shared_relro( 335 if (!crazy_library_create_shared_relro(
565 library.Get(), context, static_cast<size_t>(load_address), 336 library.Get(), context, static_cast<size_t>(load_address),
566 &relro_start, &relro_size, &relro_fd)) { 337 &relro_start, &relro_size, &relro_fd)) {
567 LOG_ERROR("%s: Could not create shared RELRO sharing for %s: %s\n", 338 LOG_ERROR("Could not create shared RELRO sharing for %s: %s\n",
568 __FUNCTION__, lib_name.c_str(), crazy_context_get_error(context)); 339 lib_name.c_str(), crazy_context_get_error(context));
569 return false; 340 return false;
570 } 341 }
571 342
572 s_lib_info_fields.SetRelroInfo(env, lib_info_obj, relro_start, relro_size, 343 s_lib_info_fields.SetRelroInfo(env, lib_info_obj, relro_start, relro_size,
573 relro_fd); 344 relro_fd);
574 return true; 345 return true;
575 } 346 }
576 347
577 jboolean UseSharedRelro(JNIEnv* env, 348 jboolean UseSharedRelro(JNIEnv* env,
578 jclass clazz, 349 jclass clazz,
579 jstring library_name, 350 jstring library_name,
580 jobject lib_info_obj) { 351 jobject lib_info_obj) {
581 String lib_name(env, library_name); 352 String lib_name(env, library_name);
582 353
583 LOG_INFO("%s: called for %s, lib_info_ref=%p", __FUNCTION__, lib_name.c_str(), 354 LOG_INFO("Called for %s, lib_info_ref=%p", lib_name.c_str(), lib_info_obj);
584 lib_info_obj);
585 355
586 ScopedLibrary library; 356 ScopedLibrary library;
587 if (!crazy_library_find_by_name(lib_name.c_str(), library.GetPtr())) { 357 if (!crazy_library_find_by_name(lib_name.c_str(), library.GetPtr())) {
588 LOG_ERROR("%s: Could not find %s", __FUNCTION__, lib_name.c_str()); 358 LOG_ERROR("Could not find %s", lib_name.c_str());
589 return false; 359 return false;
590 } 360 }
591 361
592 crazy_context_t* context = GetCrazyContext(); 362 crazy_context_t* context = GetCrazyContext();
593 size_t relro_start = 0; 363 size_t relro_start = 0;
594 size_t relro_size = 0; 364 size_t relro_size = 0;
595 int relro_fd = -1; 365 int relro_fd = -1;
596 s_lib_info_fields.GetRelroInfo(env, lib_info_obj, &relro_start, &relro_size, 366 s_lib_info_fields.GetRelroInfo(env, lib_info_obj, &relro_start, &relro_size,
597 &relro_fd); 367 &relro_fd);
598 368
599 LOG_INFO("%s: library=%s relro start=%p size=%p fd=%d", __FUNCTION__, 369 LOG_INFO("library=%s relro start=%p size=%p fd=%d", lib_name.c_str(),
600 lib_name.c_str(), (void*)relro_start, (void*)relro_size, relro_fd); 370 (void*)relro_start, (void*)relro_size, relro_fd);
601 371
602 if (!crazy_library_use_shared_relro(library.Get(), context, relro_start, 372 if (!crazy_library_use_shared_relro(library.Get(), context, relro_start,
603 relro_size, relro_fd)) { 373 relro_size, relro_fd)) {
604 LOG_ERROR("%s: Could not use shared RELRO for %s: %s", __FUNCTION__, 374 LOG_ERROR("Could not use shared RELRO for %s: %s", lib_name.c_str(),
605 lib_name.c_str(), crazy_context_get_error(context)); 375 crazy_context_get_error(context));
606 return false; 376 return false;
607 } 377 }
608 378
609 LOG_INFO("%s: Library %s using shared RELRO section!", __FUNCTION__, 379 LOG_INFO("Library %s using shared RELRO section!", lib_name.c_str());
610 lib_name.c_str());
611 380
612 return true; 381 return true;
613 } 382 }
614 383
615 jlong GetRandomBaseLoadAddress(JNIEnv* env, jclass clazz, jlong bytes) {
616 #if RESERVE_BREAKPAD_GUARD_REGION
617 // Add a Breakpad guard region. 16Mb should be comfortably larger than
618 // the largest relocation packer saving we expect to encounter.
619 static const size_t kBreakpadGuardRegionBytes = 16 * 1024 * 1024;
620 bytes += kBreakpadGuardRegionBytes;
621 #endif
622
623 void* address =
624 mmap(NULL, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
625 if (address == MAP_FAILED) {
626 LOG_INFO("%s: Random base load address not determinable\n", __FUNCTION__);
627 return 0;
628 }
629 munmap(address, bytes);
630
631 #if RESERVE_BREAKPAD_GUARD_REGION
632 // Allow for a Breakpad guard region ahead of the returned address.
633 address = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(address) +
634 kBreakpadGuardRegionBytes);
635 #endif
636
637 LOG_INFO("%s: Random base load address is %p\n", __FUNCTION__, address);
638 return static_cast<jlong>(reinterpret_cast<uintptr_t>(address));
639 }
640
641 const JNINativeMethod kNativeMethods[] = { 384 const JNINativeMethod kNativeMethods[] = {
642 {"nativeLoadLibrary", 385 {"nativeLoadLibrary",
643 "(" 386 "("
644 "Ljava/lang/String;" 387 "Ljava/lang/String;"
645 "J" 388 "J"
646 "Lorg/chromium/base/library_loader/Linker$LibInfo;" 389 "Lorg/chromium/base/library_loader/Linker$LibInfo;"
647 ")" 390 ")"
648 "Z", 391 "Z",
649 reinterpret_cast<void*>(&LoadLibrary)}, 392 reinterpret_cast<void*>(&LoadLibrary)},
650 {"nativeLoadLibraryInZipFile", 393 {"nativeLoadLibraryInZipFile",
(...skipping 19 matching lines...) Expand all
670 ")" 413 ")"
671 "Z", 414 "Z",
672 reinterpret_cast<void*>(&CreateSharedRelro)}, 415 reinterpret_cast<void*>(&CreateSharedRelro)},
673 {"nativeUseSharedRelro", 416 {"nativeUseSharedRelro",
674 "(" 417 "("
675 "Ljava/lang/String;" 418 "Ljava/lang/String;"
676 "Lorg/chromium/base/library_loader/Linker$LibInfo;" 419 "Lorg/chromium/base/library_loader/Linker$LibInfo;"
677 ")" 420 ")"
678 "Z", 421 "Z",
679 reinterpret_cast<void*>(&UseSharedRelro)}, 422 reinterpret_cast<void*>(&UseSharedRelro)},
680 {"nativeGetRandomBaseLoadAddress",
681 "("
682 "J"
683 ")"
684 "J",
685 reinterpret_cast<void*>(&GetRandomBaseLoadAddress)},
686 }; 423 };
687 424
688 } // namespace 425 } // namespace
689 426
690 // JNI_OnLoad() hook called when the linker library is loaded through 427 bool LegacyLinkerJNIInit(JavaVM* vm, JNIEnv* env) {
691 // the regular System.LoadLibrary) API. This shall save the Java VM 428 LOG_INFO("Entering");
692 // handle and initialize LibInfo fields.
693 jint JNI_OnLoad(JavaVM* vm, void* reserved) {
694 LOG_INFO("%s: Entering", __FUNCTION__);
695 // Get new JNIEnv
696 JNIEnv* env;
697 if (JNI_OK != vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4)) {
698 LOG_ERROR("Could not create JNIEnv");
699 return -1;
700 }
701 429
702 // Initialize SDK version info. 430 // Initialize SDK version info.
703 LOG_INFO("%s: Retrieving SDK version info", __FUNCTION__); 431 LOG_INFO("Retrieving SDK version info");
704 if (!InitSDKVersionInfo(env)) 432 if (!InitSDKVersionInfo(env))
705 return -1; 433 return false;
706 434
707 // Register native methods. 435 // Register native methods.
708 jclass linker_class; 436 jclass linker_class;
709 if (!InitClassReference(env, "org/chromium/base/library_loader/LegacyLinker", 437 if (!InitClassReference(env, "org/chromium/base/library_loader/LegacyLinker",
710 &linker_class)) 438 &linker_class))
711 return -1; 439 return false;
712 440
713 LOG_INFO("%s: Registering native methods", __FUNCTION__); 441 LOG_INFO("Registering native methods");
714 env->RegisterNatives(linker_class, kNativeMethods, 442 env->RegisterNatives(linker_class, kNativeMethods,
715 sizeof(kNativeMethods) / sizeof(kNativeMethods[0])); 443 sizeof(kNativeMethods) / sizeof(kNativeMethods[0]));
716 444
717 // Find LibInfo field ids.
718 LOG_INFO("%s: Caching field IDs", __FUNCTION__);
719 if (!s_lib_info_fields.Init(env)) {
720 return -1;
721 }
722
723 // Resolve and save the Java side Linker callback class and method. 445 // Resolve and save the Java side Linker callback class and method.
724 LOG_INFO("%s: Resolving callback bindings", __FUNCTION__); 446 LOG_INFO("Resolving callback bindings");
725 if (!s_java_callback_bindings.Init(env, linker_class)) { 447 if (!s_java_callback_bindings.Init(env, linker_class)) {
726 return -1; 448 return false;
727 } 449 }
728 450
729 // Save JavaVM* handle into context. 451 // Save JavaVM* handle into context.
730 crazy_context_t* context = GetCrazyContext(); 452 crazy_context_t* context = GetCrazyContext();
731 crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4); 453 crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4);
732 454
733 // Register the function that the crazy linker can call to post code 455 // Register the function that the crazy linker can call to post code
734 // for later execution. 456 // for later execution.
735 crazy_context_set_callback_poster(context, &PostForLaterExecution, NULL); 457 crazy_context_set_callback_poster(context, &PostForLaterExecution, nullptr);
736 458
737 LOG_INFO("%s: Done", __FUNCTION__); 459 return true;
738 return JNI_VERSION_1_4;
739 } 460 }
461
462 } // namespace chromium_android_linker
OLDNEW
« no previous file with comments | « android/linker/legacy_linker_jni.h ('k') | android/linker/linker_jni.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698