Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Support/DynamicLibrary.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
//  This file implements the operating system DynamicLibrary concept.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/Support/DynamicLibrary.h"
14
#include "llvm-c/Support.h"
15
#include "llvm/ADT/DenseSet.h"
16
#include "llvm/ADT/STLExtras.h"
17
#include "llvm/ADT/StringMap.h"
18
#include "llvm/Config/config.h"
19
#include "llvm/Support/ManagedStatic.h"
20
#include "llvm/Support/Mutex.h"
21
#include <cstdio>
22
#include <cstring>
23
#include <vector>
24
25
using namespace llvm;
26
using namespace llvm::sys;
27
28
// All methods for HandleSet should be used holding SymbolsMutex.
29
class DynamicLibrary::HandleSet {
30
  typedef std::vector<void *> HandleList;
31
  HandleList Handles;
32
  void *Process;
33
34
public:
35
  static void *DLOpen(const char *Filename, std::string *Err);
36
  static void DLClose(void *Handle);
37
  static void *DLSym(void *Handle, const char *Symbol);
38
39
389
  HandleSet() : Process(nullptr) {}
40
  ~HandleSet();
41
42
139
  HandleList::iterator Find(void *Handle) {
43
139
    return std::find(Handles.begin(), Handles.end(), Handle);
44
139
  }
45
46
0
  bool Contains(void *Handle) {
47
0
    return Handle == Process || Find(Handle) != Handles.end();
48
0
  }
49
50
532
  bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
51
#ifdef _WIN32
52
    assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
53
#endif
54
55
532
    if (LLVM_LIKELY(!IsProcess)) {
56
139
      if (Find(Handle) != Handles.end()) {
57
15
        if (CanClose)
58
15
          DLClose(Handle);
59
15
        return false;
60
15
      }
61
124
      Handles.push_back(Handle);
62
393
    } else {
63
393
#ifndef _WIN32
64
393
      if (Process) {
65
126
        if (CanClose)
66
126
          DLClose(Process);
67
126
        if (Process == Handle)
68
126
          return false;
69
267
      }
70
267
#endif
71
267
      Process = Handle;
72
267
    }
73
532
    
return true391
;
74
532
  }
75
76
7
  void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
77
7
    if (Order & SO_LoadOrder) {
78
0
      for (void *Handle : Handles) {
79
0
        if (void *Ptr = DLSym(Handle, Symbol))
80
0
          return Ptr;
81
0
      }
82
7
    } else {
83
7
      for (void *Handle : llvm::reverse(Handles)) {
84
7
        if (void *Ptr = DLSym(Handle, Symbol))
85
7
          return Ptr;
86
7
      }
87
7
    }
88
7
    
return nullptr0
;
89
7
  }
90
91
251
  void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
92
251
    assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&
93
251
           "Invalid Ordering");
94
251
95
251
    if (!Process || 
(Order & SO_LoadedFirst)245
) {
96
7
      if (void *Ptr = LibLookup(Symbol, Order))
97
7
        return Ptr;
98
244
    }
99
244
    if (Process) {
100
244
      // Use OS facilities to search the current binary and all loaded libs.
101
244
      if (void *Ptr = DLSym(Process, Symbol))
102
224
        return Ptr;
103
20
104
20
      // Search any libs that might have been skipped because of RTLD_LOCAL.
105
20
      if (Order & SO_LoadedLast) {
106
0
        if (void *Ptr = LibLookup(Symbol, Order))
107
0
          return Ptr;
108
20
      }
109
20
    }
110
20
    return nullptr;
111
20
  }
112
};
113
114
namespace {
115
// Collection of symbol name/value pairs to be searched prior to any libraries.
116
static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols;
117
// Collection of known library handles.
118
static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles;
119
// Lock for ExplicitSymbols and OpenedHandles.
120
static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex;
121
}
122
123
#ifdef _WIN32
124
125
#include "Windows/DynamicLibrary.inc"
126
127
#else
128
129
#include "Unix/DynamicLibrary.inc"
130
131
#endif
132
133
char DynamicLibrary::Invalid;
134
DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder =
135
    DynamicLibrary::SO_Linker;
136
137
namespace llvm {
138
22
void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
139
22
  return DoSearch(SymbolName); // DynamicLibrary.inc
140
22
}
141
}
142
143
3
void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
144
3
  SmartScopedLock<true> Lock(*SymbolsMutex);
145
3
  (*ExplicitSymbols)[SymbolName] = SymbolValue;
146
3
}
147
148
DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
149
532
                                                   std::string *Err) {
150
532
  // Force OpenedHandles to be added into the ManagedStatic list before any
151
532
  // ManagedStatic can be added from static constructors in HandleSet::DLOpen.
152
532
  HandleSet& HS = *OpenedHandles;
153
532
154
532
  void *Handle = HandleSet::DLOpen(FileName, Err);
155
532
  if (Handle != &Invalid) {
156
532
    SmartScopedLock<true> Lock(*SymbolsMutex);
157
532
    HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
158
532
  }
159
532
160
532
  return DynamicLibrary(Handle);
161
532
}
162
163
DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
164
0
                                                   std::string *Err) {
165
0
  SmartScopedLock<true> Lock(*SymbolsMutex);
166
0
  // If we've already loaded this library, tell the caller.
167
0
  if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false))
168
0
    *Err = "Library already loaded";
169
0
170
0
  return DynamicLibrary(Handle);
171
0
}
172
173
45
void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
174
45
  if (!isValid())
175
0
    return nullptr;
176
45
  return HandleSet::DLSym(Data, SymbolName);
177
45
}
178
179
255
void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
180
255
  {
181
255
    SmartScopedLock<true> Lock(*SymbolsMutex);
182
255
183
255
    // First check symbols added via AddSymbol().
184
255
    if (ExplicitSymbols.isConstructed()) {
185
2
      StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
186
2
187
2
      if (i != ExplicitSymbols->end())
188
2
        return i->second;
189
253
    }
190
253
191
253
    // Now search the libraries.
192
253
    if (OpenedHandles.isConstructed()) {
193
251
      if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder))
194
231
        return Ptr;
195
22
    }
196
22
  }
197
22
198
22
  return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
199
22
}
200
201
//===----------------------------------------------------------------------===//
202
// C API.
203
//===----------------------------------------------------------------------===//
204
205
0
LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
206
0
  return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
207
0
}
208
209
0
void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
210
0
  return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
211
0
}
212
213
0
void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
214
0
  return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
215
0
}