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