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 #include "crazy_linker_globals.h"
6 
7 #include <new>
8 
9 #include <pthread.h>
10 
11 namespace crazy {
12 
13 namespace {
14 
15 // Implement lazy-initialized static variable without a C++ constructor.
16 // Note that this is leaky, i.e. the instance is never destroyed, but
17 // this was also the case with the previous heap-based implementation.
18 pthread_once_t s_once = PTHREAD_ONCE_INIT;
19 
20 union Storage {
21   char dummy;
22   Globals globals;
23 
Storage()24   Storage() {}
~Storage()25   ~Storage() {}
26 };
27 
28 Storage s_storage;
29 
InitGlobals()30 void InitGlobals() {
31   new (&s_storage.globals) Globals();
32 }
33 
34 }  // namespace
35 
Globals()36 Globals::Globals() {
37   // IMPORTANT: The global mutex must be recursive to allow for recursive
38   // dlopen() calls. See http://crbug.com/843804.
39   pthread_mutexattr_t attr;
40   pthread_mutexattr_init(&attr);
41   pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
42   pthread_mutex_init(&lock_, &attr);
43   pthread_mutexattr_destroy(&attr);
44 
45   search_paths_.ResetFromEnv("LD_LIBRARY_PATH");
46 }
47 
~Globals()48 Globals::~Globals() {
49   pthread_mutex_destroy(&lock_);
50 }
51 
Lock()52 void Globals::Lock() {
53   pthread_mutex_lock(&lock_);
54 }
55 
Unlock()56 void Globals::Unlock() {
57   pthread_mutex_unlock(&lock_);
58 }
59 
60 // static
Get()61 Globals* Globals::Get() {
62   pthread_once(&s_once, InitGlobals);
63   return &s_storage.globals;
64 }
65 
66 // TECHNICAL NOTE: The mutex below does not have to be recursive, unlike the
67 // other one, because it should be only operated on during the following
68 // operations:
69 //
70 //   - Acquired before, and released after, calling one of the system linker's
71 //     functions that may modify the global link-map. Note that these should
72 //     never call back into the crazy linker.
73 //
74 //   - Acquired and released when modifying the global link-map in
75 //     crazy::RDebug::AddEntryImpl() and crazy::RDebug::DelEntryImpl(). These
76 //     do not call the system linker, or make any kind of recursive calls.
77 
78 // static
79 pthread_mutex_t ScopedLinkMapLocker::s_lock_ = PTHREAD_MUTEX_INITIALIZER;
80 
81 }  // namespace crazy
82