blob: 936a2dd117190ee0614520fb456e5e52d067d039 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// 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
47namespace ost {
48#endif
49
50#ifdef HAVE_MODULES
51DSO *DSO::first = NULL;
52DSO *DSO::last = NULL;
53Mutex DSO::mutex;
54
55#if defined(HAVE_DLFCN_H)
56
57extern "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
67void DSO::dynunload(void)
68{
69 while(DSO::last)
70 delete DSO::last;
71}
72
73DSO::~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
120void 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
221DSO *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
242bool 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
256void *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
287static void MyLinkError(NSLinkEditErrors c, int errorNumber, const char *filename, const char *errstr)
288{
289 slog.error() << "dyld: " << filename << ": " << errstr << std::endl;
290}
291
292static void MyUndefined(const char *symname)
293{
294 slog.error() << "dyld: undefined: " << symname << std::endl;
295}
296
297static NSModule MyMultiple(NSSymbol s, NSModule oMod, NSModule nMod)
298{
299 slog.error() << "dyld: multiply defined symbols" << std::endl;
300}
301
302void DSO::setDebug(void)
303{
304 static NSLinkEditErrorHandlers handlers = {
305 &MyUndefined,
306 &MyMultiple,
307 &MyLinkError};
308
309 NSInstallLinkEditErrorHandlers(&handlers);
310}
311
312#else
313
314void 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 */