WvStreams
loader.cc
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  *
3  * XPLC - Cross-Platform Lightweight Components
4  * Copyright (C) 2002, Net Integration Technologies, Inc.
5  * Copyright (C) 2002-2004, Pierre Phaneuf
6  * Copyright (C) 2002-2004, Stéphane Lajoie
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21  * USA
22  */
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 
27 #include "config.h"
28 #include "loader.h"
29 
30 #ifdef HAVE_DLFCN_H
31 #include <dlfcn.h>
32 #endif
33 
34 #ifdef HAVE_MACH_O_DYLD_H
35 #include <mach-o/dyld.h>
36 #endif
37 
38 #if defined(WITH_DLOPEN) && defined(ENABLE_LOADER)
39 const char* loaderOpen(const char* aFilename,
40  void** aHandle) {
41  const char* rv = 0;
42 
43  /* clear out dl error */
44  static_cast<void>(dlerror());
45 
46  *aHandle = dlopen(aFilename, RTLD_NOW);
47 
48  if(!*aHandle)
49  rv = dlerror();
50 
51  return rv;
52 }
53 
54 const char* loaderSymbol(void* aHandle,
55  const char* aSymbol,
56  void** aPointer) {
57  /* clear out dl error */
58  static_cast<void>(dlerror());
59 
60  *aPointer = dlsym(aHandle, aSymbol);
61 
62  return dlerror();
63 }
64 
65 bool loaderClose(void*& aHandle) {
66  bool rv;
67 
68  rv = dlclose(aHandle) == 0;
69  aHandle = 0;
70 
71  return rv;
72 }
73 
74 #elif defined(WITH_DYLD) && defined(ENABLE_LOADER)
75 
76 const char* loaderOpen(const char* aFilename,
77  void** aHandle) {
78  NSObjectFileImage ofi = 0;
79  NSObjectFileImageReturnCode ofirc;
80 
81  ofirc = NSCreateObjectFileImageFromFile(aFilename, &ofi);
82  switch(ofirc) {
83  case NSObjectFileImageSuccess:
84  *aHandle = NSLinkModule(ofi, aFilename,
85  NSLINKMODULE_OPTION_RETURN_ON_ERROR
86  | NSLINKMODULE_OPTION_PRIVATE
87  | NSLINKMODULE_OPTION_BINDNOW);
88  NSDestroyObjectFileImage(ofi);
89  break;
90  case NSObjectFileImageInappropriateFile:
91  *aHandle =
92  const_cast<void*>(reinterpret_cast<const void*>(NSAddImage(aFilename, NSADDIMAGE_OPTION_RETURN_ON_ERROR)));
93  break;
94  default:
95  return "could not open dynamic library";
96  break;
97  }
98 
99  return 0;
100 }
101 
102 const char* loaderSymbol(void* aHandle,
103  const char* aSymbol,
104  void** aPointer) {
105  int len = strlen(aSymbol);
106  char* sym = static_cast<char*>(malloc(len + 2));
107  NSSymbol* nssym = 0;
108 
109  snprintf(sym, len + 2, "_%s", aSymbol);
110 
111  /* Check for both possible magic numbers depending on x86/ppc byte order */
112  if ((((struct mach_header *)aHandle)->magic == MH_MAGIC) ||
113  (((struct mach_header *)aHandle)->magic == MH_CIGAM)) {
114  if (NSIsSymbolNameDefinedInImage((struct mach_header *)aHandle, sym)) {
115  nssym = (NSModule *)NSLookupSymbolInImage((struct mach_header *)aHandle,
116  sym,
117  NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
118  | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
119  }
120  } else {
121  nssym = (NSModule *)NSLookupSymbolInModule(aHandle, sym);
122  }
123 
124  free(sym);
125 
126  if(!nssym) {
127  *aPointer = 0;
128  return "symbol not found";
129  }
130 
131  return 0;
132 }
133 
134 bool loaderClose(void*& aHandle) {
135  aHandle = 0;
136  return false;
137 }
138 
139 #elif defined(WIN32)
140 
141 #include <windows.h>
142 
143 const char* getErrorMessage() {
144  static char error[1024];
145  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, error, sizeof(error), 0);
146  return error;
147 }
148 
149 const char* loaderOpen(const char* aFilename,
150  void** aHandle) {
151  const char* rv = 0;
152 
153  UINT oldErrorMode = SetErrorMode(0);
154  SetErrorMode(oldErrorMode | SEM_FAILCRITICALERRORS);
155  *aHandle = LoadLibrary(aFilename);
156  SetErrorMode(oldErrorMode);
157 
158  if(!*aHandle)
159  rv = getErrorMessage();
160 
161  return rv;
162 }
163 
164 const char* loaderSymbol(void* aHandle,
165  const char* aSymbol,
166  void** aPointer) {
167  const char* rv = 0;
168 
169  *aPointer = (void *)GetProcAddress(static_cast<HMODULE>(aHandle), aSymbol);
170 
171  if(!aPointer)
172  rv = getErrorMessage();
173 
174  return rv;
175 }
176 
177 bool loaderClose(void*& aHandle) {
178  bool rv;
179 
180  rv = FreeLibrary(static_cast<HMODULE>(aHandle)) != 0;
181  aHandle = 0;
182 
183  return rv;
184 }
185 
186 #else
187 
188 const char* loaderOpen(const char* aFilename,
189  void** aHandle) {
190  *aHandle = 0;
191  return "dynamic loading not supported on this platform";
192 }
193 
194 const char* loaderSymbol(void* aHandle,
195  const char* aSymbol,
196  void** aPointer) {
197  *aPointer = 0;
198  return "dynamic loading not supported on this platform";
199 }
200 
201 bool loaderClose(void*& aHandle) {
202  aHandle = 0;
203  return false;
204 }
205 
206 #endif