OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/base/latebindingsymboltable.h" | |
12 | |
13 #if defined(WEBRTC_POSIX) | |
14 #include <dlfcn.h> | |
15 #endif | |
16 | |
17 #include "webrtc/base/logging.h" | |
18 | |
19 namespace rtc { | |
20 | |
21 #if defined(WEBRTC_POSIX) | |
22 static const DllHandle kInvalidDllHandle = NULL; | |
23 #else | |
24 #error Not implemented | |
25 #endif | |
26 | |
27 static const char *GetDllError() { | |
28 #if defined(WEBRTC_POSIX) | |
29 const char *err = dlerror(); | |
30 if (err) { | |
31 return err; | |
32 } else { | |
33 return "No error"; | |
34 } | |
35 #else | |
36 #error Not implemented | |
37 #endif | |
38 } | |
39 | |
40 static bool LoadSymbol(DllHandle handle, | |
41 const char *symbol_name, | |
42 void **symbol) { | |
43 #if defined(WEBRTC_POSIX) | |
44 *symbol = dlsym(handle, symbol_name); | |
45 const char *err = dlerror(); | |
46 if (err) { | |
47 LOG(LS_ERROR) << "Error loading symbol " << symbol_name << ": " << err; | |
48 return false; | |
49 } else if (!*symbol) { | |
50 // ELF allows for symbols to be NULL, but that should never happen for our | |
51 // usage. | |
52 LOG(LS_ERROR) << "Symbol " << symbol_name << " is NULL"; | |
53 return false; | |
54 } | |
55 return true; | |
56 #else | |
57 #error Not implemented | |
58 #endif | |
59 } | |
60 | |
61 LateBindingSymbolTable::LateBindingSymbolTable(const TableInfo *info, | |
62 void **table) | |
63 : info_(info), | |
64 table_(table), | |
65 handle_(kInvalidDllHandle), | |
66 undefined_symbols_(false) { | |
67 ClearSymbols(); | |
68 } | |
69 | |
70 LateBindingSymbolTable::~LateBindingSymbolTable() { | |
71 Unload(); | |
72 } | |
73 | |
74 bool LateBindingSymbolTable::IsLoaded() const { | |
75 return handle_ != kInvalidDllHandle; | |
76 } | |
77 | |
78 bool LateBindingSymbolTable::Load() { | |
79 ASSERT(info_->dll_name != NULL); | |
80 return LoadFromPath(info_->dll_name); | |
81 } | |
82 | |
83 bool LateBindingSymbolTable::LoadFromPath(const char *dll_path) { | |
84 if (IsLoaded()) { | |
85 return true; | |
86 } | |
87 if (undefined_symbols_) { | |
88 // We do not attempt to load again because repeated attempts are not | |
89 // likely to succeed and DLL loading is costly. | |
90 LOG(LS_ERROR) << "We know there are undefined symbols"; | |
91 return false; | |
92 } | |
93 | |
94 #if defined(WEBRTC_POSIX) | |
95 handle_ = dlopen(dll_path, | |
96 // RTLD_NOW front-loads symbol resolution so that errors are | |
97 // caught early instead of causing a process abort later. | |
98 // RTLD_LOCAL prevents other modules from automatically | |
99 // seeing symbol definitions in the newly-loaded tree. This | |
100 // is necessary for same-named symbols in different ABI | |
101 // versions of the same library to not explode. | |
102 RTLD_NOW|RTLD_LOCAL | |
103 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) && defined(RTLD_DEEPBIND) | |
104 // RTLD_DEEPBIND makes symbol dependencies in the | |
105 // newly-loaded tree prefer to resolve to definitions within | |
106 // that tree (the default on OS X). This is necessary for | |
107 // same-named symbols in different ABI versions of the same | |
108 // library to not explode. | |
109 |RTLD_DEEPBIND | |
110 #endif | |
111 ); // NOLINT | |
112 #else | |
113 #error Not implemented | |
114 #endif | |
115 | |
116 if (handle_ == kInvalidDllHandle) { | |
117 LOG(LS_WARNING) << "Can't load " << dll_path << ": " | |
118 << GetDllError(); | |
119 return false; | |
120 } | |
121 #if defined(WEBRTC_POSIX) | |
122 // Clear any old errors. | |
123 dlerror(); | |
124 #endif | |
125 for (int i = 0; i < info_->num_symbols; ++i) { | |
126 if (!LoadSymbol(handle_, info_->symbol_names[i], &table_[i])) { | |
127 undefined_symbols_ = true; | |
128 Unload(); | |
129 return false; | |
130 } | |
131 } | |
132 return true; | |
133 } | |
134 | |
135 void LateBindingSymbolTable::Unload() { | |
136 if (!IsLoaded()) { | |
137 return; | |
138 } | |
139 | |
140 #if defined(WEBRTC_POSIX) | |
141 if (dlclose(handle_) != 0) { | |
142 LOG(LS_ERROR) << GetDllError(); | |
143 } | |
144 #else | |
145 #error Not implemented | |
146 #endif | |
147 | |
148 handle_ = kInvalidDllHandle; | |
149 ClearSymbols(); | |
150 } | |
151 | |
152 void LateBindingSymbolTable::ClearSymbols() { | |
153 memset(table_, 0, sizeof(void *) * info_->num_symbols); | |
154 } | |
155 | |
156 } // namespace rtc | |
OLD | NEW |