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