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 3 // found in the LICENSE file. 4 5 #ifndef CRAZY_LINKER_GLOBALS_H 6 #define CRAZY_LINKER_GLOBALS_H 7 8 #include <pthread.h> 9 10 #include "crazy_linker_library_list.h" 11 #include "crazy_linker_pointer_set.h" 12 #include "crazy_linker_rdebug.h" 13 #include "crazy_linker_search_path_list.h" 14 15 // All crazy linker globals are declared in this header. 16 17 namespace crazy { 18 19 class Globals { 20 public: 21 // Get the single Globals instance for this process. 22 static Globals* Get(); 23 24 // Default constructor. 25 Globals(); 26 27 // Destructor. 28 ~Globals(); 29 30 // Acquire and release the mutex that protects all other non-static members. 31 // ScopedLockedGlobals is recommended, to avoid using these directly. 32 void Lock(); 33 void Unlock(); 34 35 // The list of libraries known to the crazy linker. libraries()36 LibraryList* libraries() { return &libraries_; } 37 38 // The RDebug instance for this process. rdebug()39 RDebug* rdebug() { return &rdebug_; } 40 41 // Set of valid handles returned by the dlopen() wrapper. This is 42 // required to deal with rare cases where the wrapper is passed 43 // a handle that was opened with the system linker by mistake. valid_handles()44 PointerSet* valid_handles() { return &valid_handles_; } 45 46 // The current library search path list used by the dlopen() wrapper. 47 // Initialized from LD_LIBRARY_PATH when ::Get() creates the instance. search_path_list()48 SearchPathList* search_path_list() { return &search_paths_; } 49 50 // Save JavaVM instance pointer and minimum JNI version required by this 51 // client. If |java_vm| is not nullptr, it will be used to call JNI_OnLoad() 52 // on every library loaded through the crazy linker, if available, and 53 // JNI_UnLoad() when unloading them, respectively. InitJavaVm(void * java_vm,int min_jni_version)54 void InitJavaVm(void* java_vm, int min_jni_version) { 55 java_vm_ = java_vm; 56 min_jni_version_ = min_jni_version; 57 } 58 59 // Return current JavaVM instance pointer. java_vm()60 void* java_vm() const { return java_vm_; } 61 62 // Return current minimum JNI version number. minimum_jni_version()63 int minimum_jni_version() const { return min_jni_version_; } 64 65 // Convenience function to get the global RDebug instance. GetRDebug()66 static RDebug* GetRDebug() { return Get()->rdebug(); } 67 68 private: 69 pthread_mutex_t lock_; 70 void* java_vm_ = nullptr; 71 int min_jni_version_ = 0; 72 LibraryList libraries_; 73 SearchPathList search_paths_; 74 RDebug rdebug_; 75 PointerSet valid_handles_; 76 }; 77 78 // Convenience class to retrieve the Globals instance and lock it at the same 79 // time on construction, then release it on destruction. Also dereference can 80 // be used to access global methods and members. 81 class ScopedLockedGlobals { 82 public: 83 // Default constructor acquires the lock on the global instance. ScopedLockedGlobals()84 ScopedLockedGlobals() : globals_(Globals::Get()) { globals_->Lock(); } 85 86 // Destructor releases the lock. ~ScopedLockedGlobals()87 ~ScopedLockedGlobals() { globals_->Unlock(); } 88 89 // Disallow copy operations. 90 ScopedLockedGlobals(const ScopedLockedGlobals&) = delete; 91 ScopedLockedGlobals& operator=(const ScopedLockedGlobals&) = delete; 92 93 // Dereference operator. 94 Globals* operator->() { return globals_; } 95 96 private: 97 Globals* globals_; 98 }; 99 100 // Convenience class used to operate on a mutex used to synchronize access to 101 // the global _r_debug link map, at least from threads using the crazy linker. 102 class ScopedLinkMapLocker { 103 public: ScopedLinkMapLocker()104 ScopedLinkMapLocker() { pthread_mutex_lock(&s_lock_); } ~ScopedLinkMapLocker()105 ~ScopedLinkMapLocker() { pthread_mutex_unlock(&s_lock_); } 106 107 private: 108 static pthread_mutex_t s_lock_; 109 }; 110 111 } // namespace crazy 112 113 #endif // CRAZY_LINKER_GLOBALS_H 114