1 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
2 // Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 // As a special exception, you may use this file as part of a free software
19 // library without restriction. Specifically, if other files instantiate
20 // templates or use macros or inline functions from this file, or you compile
21 // this file and link it with other files to produce an executable, this
22 // file does not by itself cause the resulting executable to be covered by
23 // the GNU General Public License. This exception does not however
24 // invalidate any other reasons why the executable file might be covered by
25 // the GNU General Public License.
26 //
27 // This exception applies only to the code released under the name GNU
28 // Common C++. If you copy code from other releases into a copy of GNU
29 // Common C++, as the General Public License permits, the exception does
30 // not apply to the code that you add in this way. To avoid misleading
31 // anyone as to the status of such modified files, you must delete
32 // this exception notice from them.
33 //
34 // If you write modifications of your own for GNU Common C++, it is your choice
35 // whether to permit this exception to apply to your modifications.
36 // If you do not wish that, delete this exception notice.
37 //
38
39 #include <cc++/config.h>
40 #include <cc++/export.h>
41 #include <cc++/exception.h>
42 #include <cc++/slog.h>
43 #include <cc++/file.h>
44 #include "private.h"
45
46 #ifdef CCXX_NAMESPACES
47 namespace ost {
48 #endif
49
50 #ifdef HAVE_MODULES
51 DSO *DSO::first = NULL;
52 DSO *DSO::last = NULL;
53 Mutex DSO::mutex;
54
55 #if defined(HAVE_DLFCN_H)
56
57 extern "C" {
58 #include <dlfcn.h>
59 }
60
61 #ifndef RTLD_GLOBAL
62 #define RTLD_GLOBAL 0
63 #endif
64
65 #endif // HAVE_DLFN_H
66
dynunload(void)67 void DSO::dynunload(void)
68 {
69 while(DSO::last)
70 delete DSO::last;
71 }
72
~DSO()73 DSO::~DSO()
74 {
75 #if defined(HAVE_MACH_DYLD)
76 NSSymbol sym;
77 void (*fini)(void);
78 #endif
79 MutexLock lock(mutex);
80 #if defined(WIN32)
81 if(hImage)
82 FreeLibrary(hImage);
83 #elif defined(HAVE_MACH_DYLD)
84 if(oModule == NULL)
85 return;
86
87 sym = NSLookupSymbolInModule(oModule, "__fini");
88 if(sym != NULL) {
89 fini = (void (*)(void))NSAddressOfSymbol(sym);
90 fini();
91 }
92
93 NSUnLinkModule(oModule, NSUNLINKMODULE_OPTION_NONE);
94 #elif defined(HAVE_SHL_LOAD)
95 if(image)
96 shl_unload(image);
97 #else
98 if(image)
99 dlclose(image);
100 #endif
101
102 if(first == this && last == this)
103 first = last = NULL;
104
105 if(!next && !prev)
106 return;
107
108 if(prev)
109 prev->next = next;
110
111 if(next)
112 next->prev = prev;
113
114 if(first == this)
115 first = next;
116 if(last == this)
117 last = prev;
118 }
119
loader(const char * filename,bool flag)120 void DSO::loader(const char *filename, bool flag)
121 {
122 #if defined(HAVE_MACH_DYLD)
123 NSObjectFileImage oImage;
124 NSSymbol sym = NULL;
125 void (*init)(void);
126 #endif
127
128 id = strrchr(filename, '/');
129 if(id)
130 ++id;
131 else
132 id = filename;
133
134 next = prev = NULL;
135
136 #if defined(WIN32)
137 hImage = LoadLibrary(filename);
138 err = "none";
139 #elif defined(HAVE_MACH_DYLD)
140 err = "none";
141 oModule = NULL;
142
143 fprintf(stderr, "**** HERE %s\n", filename);
144
145 switch(NSCreateObjectFileImageFromFile(filename, &oImage)) {
146 case NSObjectFileImageSuccess:
147 break;
148 default:
149 err = "unknown error";
150 return;
151 }
152 if(flag)
153 oModule = NSLinkModule(oImage, filename, NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
154 else
155 oModule = NSLinkModule(oImage, filename, NSLINKMODULE_OPTION_RETURN_ON_ERROR);
156 NSDestroyObjectFileImage(oImage);
157 if(oModule != NULL)
158 sym = NSLookupSymbolInModule(oModule, "__init");
159 if(sym) {
160 init = (void (*)(void))NSAddressOfSymbol(sym);
161 init();
162 }
163
164 #elif defined(HAVE_SHL_LOAD)
165 err = "none";
166 if(flag)
167 image = shl_load(filename, BIND_IMMEDIATE, 0L);
168 else
169 image = shl_load(filename, BIND_DEFERRED, 0L);
170 #else
171 if(flag)
172 image = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
173 else
174 image = dlopen(filename, RTLD_LAZY | RTLD_GLOBAL);
175
176 #endif
177
178 #if defined(WIN32)
179 if(!hImage) {
180 err = "load failed";
181 #elif defined(HAVE_MACH_DYLD)
182 if(oModule == NULL) {
183 err = "load failed";
184 #elif defined(HAVE_SHL_LOAD)
185 if(!image) {
186 err = "load failed";
187 #else
188 if(!image) {
189 err = dlerror();
190 #endif
191
192 // since generally failure to map or load a plugin is fatel in most
193 // cases, we should generally log the error to syslog as well as notify
194 // the upper level system of the failure through exception.
195
196 slog.error() << "dso: " << id << ": " << err << std::endl;
197
198 #ifdef CCXX_EXCEPTIONS
199 if(Thread::getException() == Thread::throwObject)
200 throw(this);
201 #ifdef COMMON_STD_EXCEPTION
202 else if(Thread::getException() == Thread::throwException)
203 throw(DSOException(String(id) + err));
204 #endif
205 #endif
206 return;
207 }
208
209 if(!last) {
210 last = first = this;
211 return;
212 }
213
214 mutex.enterMutex();
215 last->next = this;
216 prev = last;
217 last = this;
218 mutex.leaveMutex();
219 }
220
221 DSO *DSO::getObject(const char *id)
222 {
223 const char *chk = strrchr(id, '/');
224 DSO *dso;
225
226 if(chk)
227 ++chk;
228 else
229 chk = id;
230
231 mutex.enterMutex();
232 dso = first;
233 while(dso) {
234 if(!stricmp(dso->id, chk))
235 break;
236 dso = dso->next;
237 }
238 mutex.leaveMutex();
239 return dso;
240 }
241
242 bool DSO::isValid(void)
243 {
244 #if defined(WIN32)
245 if(!hImage)
246 #elif defined(HAVE_MACH_DYLD)
247 if(oModule == NULL)
248 #else
249 if(!image)
250 #endif
251 return false;
252
253 return true;
254 }
255
256 void *DSO::operator[](const char *sym)
257 {
258 #if defined(HAVE_SHL_LOAD)
259 int value;
260 shl_t handle = (shl_t)image;
261
262 if(shl_findsym(&handle, sym, 0, &value) == 0)
263 return (void *)value;
264 else
265 return NULL;
266 #elif defined(HAVE_MACH_DYLD)
267 NSSymbol oSymbol = NSLookupSymbolInModule(oModule, sym);
268 if(oSymbol)
269 return NSAddressOfSymbol(oSymbol);
270 else
271 return NULL;
272 #elif defined(WIN32)
273 void *addr = (void *)GetProcAddress(hImage, sym);
274 if(!addr)
275 err = "symbol missing";
276
277 return addr;
278 #else
279 return dlsym(image, (char *)sym);
280 #endif
281 }
282
283 #endif
284
285
286 #ifdef HAVE_MACH_DYLD
287 static void MyLinkError(NSLinkEditErrors c, int errorNumber, const char *filename, const char *errstr)
288 {
289 slog.error() << "dyld: " << filename << ": " << errstr << std::endl;
290 }
291
292 static void MyUndefined(const char *symname)
293 {
294 slog.error() << "dyld: undefined: " << symname << std::endl;
295 }
296
297 static NSModule MyMultiple(NSSymbol s, NSModule oMod, NSModule nMod)
298 {
299 slog.error() << "dyld: multiply defined symbols" << std::endl;
300 }
301
302 void DSO::setDebug(void)
303 {
304 static NSLinkEditErrorHandlers handlers = {
305 &MyUndefined,
306 &MyMultiple,
307 &MyLinkError};
308
309 NSInstallLinkEditErrorHandlers(&handlers);
310 }
311
312 #else
313
314 void DSO::setDebug(void)
315 {
316 }
317
318 #endif
319
320 #ifdef CCXX_NAMESPACES
321 }
322 #endif
323
324
325 /** EMACS **
326 * Local variables:
327 * mode: c++
328 * c-basic-offset: 4
329 * End:
330 */
331