blob: 6ec7c014999ccbce16a8f66930e1fe80bdafed62 [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// 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 <ucommon-config.h>
40#include <commoncpp/config.h>
41#include <commoncpp/export.h>
42#include <commoncpp/string.h>
43#include <commoncpp/exception.h>
44#include <commoncpp/slog.h>
45#include <commoncpp/file.h>
46#include <commoncpp/process.h>
47
48using namespace COMMONCPP_NAMESPACE;
49
50DSO *DSO::first = NULL;
51DSO *DSO::last = NULL;
52Mutex DSO::mutex;
53
54#if defined(HAVE_DLFCN_H)
55
56extern "C" {
57#include <dlfcn.h>
58}
59
60#ifndef RTLD_GLOBAL
61#define RTLD_GLOBAL 0
62#endif
63
64#endif // HAVE_DLFN_H
65
66#ifdef HAVE_SHL_LOAD
67#include <dl.h>
68#endif
69
70#ifdef HAVE_MACH_O_DYLD_H
71#include <mach-o/dyld.h>
72#define oModule ((oModule)(image))
73#endif
74
75#ifdef _MSWINDOWS_
76#define hImage ((HMODULE)(image))
77#endif
78
79void DSO::dynunload(void)
80{
81 while(DSO::last)
82 delete DSO::last;
83}
84
85DSO::~DSO()
86{
87#if defined(HAVE_MACH_DYLD)
88 NSSymbol sym;
89 void (*fini)(void);
90#endif
91 MutexLock lock(mutex);
92#if defined(_MSWINDOWS_)
93 if(image)
94 FreeLibrary(hImage);
95#elif defined(HAVE_MACH_DYLD)
96 if(image == NULL)
97 return;
98
99 sym = NSLookupSymbolInModule(oModule, "__fini");
100 if(sym != NULL) {
101 fini = (void (*)(void))NSAddressOfSymbol(sym);
102 fini();
103 }
104
105 NSUnLinkModule(oModule, NSUNLINKMODULE_OPTION_NONE);
106#elif defined(HAVE_SHL_LOAD)
107 if(image)
108 shl_unload(image);
109#elif defined(HAVE_DLFCN_H)
110 if(image)
111 dlclose(image);
112#endif
113
114 if(first == this && last == this)
115 first = last = NULL;
116
117 if(!next && !prev)
118 return;
119
120 if(prev)
121 prev->next = next;
122
123 if(next)
124 next->prev = prev;
125
126 if(first == this)
127 first = next;
128 if(last == this)
129 last = prev;
130}
131
132void DSO::loader(const char *filename, bool flag)
133{
134#if defined(HAVE_MACH_DYLD)
135 NSObjectFileImage oImage;
136 NSSymbol sym = NULL;
137 void (*init)(void);
138#endif
139
140 id = strrchr(filename, '/');
141 if(id)
142 ++id;
143 else
144 id = filename;
145
146 next = prev = NULL;
147
148#if defined(_MSWINDOWS_)
149 image = LoadLibrary(filename);
150 err = "none";
151#elif defined(HAVE_MACH_DYLD)
152 err = "none";
153 image = NULL;
154
155 fprintf(stderr, "**** HERE %s\n", filename);
156
157 switch(NSCreateObjectFileImageFromFile(filename, &oImage)) {
158 case NSObjectFileImageSuccess:
159 break;
160 default:
161 err = "unknown error";
162 return;
163 }
164 if(flag)
165 image = NSLinkModule(oImage, filename, NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
166 else
167 image = NSLinkModule(oImage, filename, NSLINKMODULE_OPTION_RETURN_ON_ERROR);
168 NSDestroyObjectFileImage(oImage);
169 if(oModule != NULL)
170 sym = NSLookupSymbolInModule(oModule, "__init");
171 if(sym) {
172 init = (void (*)(void))NSAddressOfSymbol(sym);
173 init();
174 }
175
176#elif defined(HAVE_SHL_LOAD)
177 err = "none";
178 if(flag)
179 image = shl_load(filename, BIND_IMMEDIATE, 0L);
180 else
181 image = shl_load(filename, BIND_DEFERRED, 0L);
182#elif defined(HAVE_DLFCN_H)
183 if(flag)
184 image = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
185 else
186 image = dlopen(filename, RTLD_LAZY | RTLD_GLOBAL);
187
188#endif
189
190#if defined(_MSWINDOWS_)
191 if(!image) {
192 err = "load failed";
193#elif defined(HAVE_MACH_DYLD)
194 if(image == NULL) {
195 err = "load failed";
196#elif defined(HAVE_SHL_LOAD)
197 if(!image) {
198 err = "load failed";
199#elif defined(HAVE_DLFCN_H)
200 if(!image) {
201 err = dlerror();
202#else
203 if(1) {
204 err = "load unsupported";
205#endif
206
207// since generally failure to map or load a plugin is fatel in most
208// cases, we should generally log the error to syslog as well as notify
209// the upper level system of the failure through exception.
210
211 slog.error() << "dso: " << id << ": " << err << std::endl;
212
213#ifdef CCXX_EXCEPTIONS
214 if(Thread::getException() == Thread::throwObject)
215 throw(this);
216#ifdef COMMON_STD_EXCEPTION
217 else if(Thread::getException() == Thread::throwException)
218 throw(DSOException(String(id) + err));
219#endif
220#endif
221 return;
222 }
223
224 if(!last) {
225 last = first = this;
226 return;
227 }
228
229 mutex.enterMutex();
230 last->next = this;
231 prev = last;
232 last = this;
233 mutex.leaveMutex();
234}
235
236DSO *DSO::getObject(const char *id)
237{
238 const char *chk = strrchr(id, '/');
239 DSO *dso;
240
241 if(chk)
242 ++chk;
243 else
244 chk = id;
245
246 mutex.enterMutex();
247 dso = first;
248 while(dso) {
249 if(!stricmp(dso->id, chk))
250 break;
251 dso = dso->next;
252 }
253 mutex.leaveMutex();
254 return dso;
255}
256
257bool DSO::isValid(void)
258{
259#if defined(_MSWINDOWS_)
260 if(!image)
261#elif defined(HAVE_MACH_DYLD)
262 if(image == NULL)
263#else
264 if(!image)
265#endif
266 return false;
267
268 return true;
269}
270
271DSO::addr_t DSO::operator[](const char *sym)
272{
273#if defined(HAVE_SHL_LOAD)
274 int value;
275 shl_t handle = (shl_t)image;
276
277 if(shl_findsym(&handle, sym, 0, &value) == 0)
278 return (DSO::addr_t)value;
279 else
280 return NULL;
281#elif defined(HAVE_MACH_DYLD)
282 NSSymbol oSymbol = NSLookupSymbolInModule(oModule, sym);
283 if(oSymbol)
284 return (DSO::addr_t)NSAddressOfSymbol(oSymbol);
285 else
286 return (DSO::addr_t)NULL;
287#elif defined(_MSWINDOWS_)
288 DSO::addr_t addr = (DSO::addr_t)GetProcAddress(hImage, sym);
289 if(!addr)
290 err = "symbol missing";
291
292 return addr;
293#elif defined(HAVE_DLFCN_H)
294 return (DSO::addr_t)dlsym(image, (char *)sym);
295#else
296 return (DSO::addr_t)NULL;
297#endif
298}
299
300#ifdef HAVE_MACH_DYLD
301static void MyLinkError(NSLinkEditErrors c, int errorNumber, const char *filename, const char *errstr)
302{
303 slog.error() << "dyld: " << filename << ": " << errstr << std::endl;
304}
305
306static void MyUndefined(const char *symname)
307{
308 slog.error() << "dyld: undefined: " << symname << std::endl;
309}
310
311static NSModule MyMultiple(NSSymbol s, NSModule oMod, NSModule nMod)
312{
313 slog.error() << "dyld: multiply defined symbols" << std::endl;
314}
315
316void DSO::setDebug(void)
317{
318 static NSLinkEditErrorHandlers handlers = {
319 &MyUndefined,
320 &MyMultiple,
321 &MyLinkError};
322
323 NSInstallLinkEditErrorHandlers(&handlers);
324}
325
326#else
327
328void DSO::setDebug(void)
329{
330}
331
332#endif
333