1 /*=========================================================================
3 Program: KWSys - Kitware System Library
4 Module: $RCSfile: DynamicLoader.cxx,v $
6 Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
7 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notices for more information.
13 =========================================================================*/
14 #include "kwsysPrivate.h"
15 #include KWSYS_HEADER(DynamicLoader.hxx)
17 #include KWSYS_HEADER(Configure.hxx)
19 // Work-around CMake dependency scanning limitation. This must
20 // duplicate the above list of headers.
22 # include "DynamicLoader.hxx.in"
23 # include "Configure.hxx.in"
26 // This file is actually 3 different implementations.
27 // 1. HP machines which uses shl_load
28 // 2. Mac OS X 10.2.x and earlier which uses NSLinkModule
29 // 3. Windows which uses LoadLibrary
30 // 4. Most unix systems (including Mac OS X 10.3 and later) which use dlopen
31 // (default) Each part of the ifdef contains a complete implementation for
32 // the static methods of DynamicLoader.
34 // ---------------------------------------------------------------
35 // 1. Implementation for HPUX machines
39 #define DYNAMICLOADER_DEFINED 1
41 namespace KWSYS_NAMESPACE
44 //----------------------------------------------------------------------------
45 DynamicLoader::LibraryHandle
DynamicLoader::OpenLibrary(const char* libname
)
47 return shl_load(libname
, BIND_DEFERRED
| DYNAMIC_PATH
, 0L);
50 //----------------------------------------------------------------------------
51 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib
)
53 return !shl_unload(lib
);
56 //----------------------------------------------------------------------------
57 DynamicLoader::SymbolPointer
58 DynamicLoader::GetSymbolAddress(DynamicLoader::LibraryHandle lib
, const char* sym
)
63 /* TYPE_PROCEDURE Look for a function or procedure. (This used to be default)
64 * TYPE_DATA Look for a symbol in the data segment (for example, variables).
65 * TYPE_UNDEFINED Look for any symbol.
67 status
= shl_findsym (&lib
, sym
, TYPE_UNDEFINED
, &addr
);
68 void* result
= (status
< 0) ? (void*)0 : addr
;
70 // Hack to cast pointer-to-data to pointer-to-function.
71 return *reinterpret_cast<DynamicLoader::SymbolPointer
*>(&result
);
74 //----------------------------------------------------------------------------
75 const char* DynamicLoader::LibPrefix()
80 //----------------------------------------------------------------------------
81 const char* DynamicLoader::LibExtension()
86 //----------------------------------------------------------------------------
87 const char* DynamicLoader::LastError()
89 // TODO: Need implementation with errno/strerror
90 /* If successful, shl_findsym returns an integer (int) value zero. If
91 * shl_findsym cannot find sym, it returns -1 and sets errno to zero.
92 * If any other errors occur, shl_findsym returns -1 and sets errno to one
93 * of these values (defined in <errno.h>):
95 * A format error was detected in the specified library.
97 * A symbol on which sym depends could not be found.
99 * The specified handle is invalid.
106 return strerror(errno
);
112 } // namespace KWSYS_NAMESPACE
117 // ---------------------------------------------------------------
118 // 2. Implementation for Mac OS X 10.2.x and earlier
120 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
121 #include <string.h> // for strlen
122 #include <mach-o/dyld.h>
123 #define DYNAMICLOADER_DEFINED 1
125 namespace KWSYS_NAMESPACE
128 //----------------------------------------------------------------------------
129 DynamicLoader::LibraryHandle
DynamicLoader::OpenLibrary(const char* libname
)
131 NSObjectFileImageReturnCode rc
;
132 NSObjectFileImage image
= 0;
134 rc
= NSCreateObjectFileImageFromFile(libname
, &image
);
135 // rc == NSObjectFileImageInappropriateFile when trying to load a dylib file
136 if( rc
!= NSObjectFileImageSuccess
)
140 NSModule handle
= NSLinkModule(image
, libname
,
141 NSLINKMODULE_OPTION_BINDNOW
|NSLINKMODULE_OPTION_RETURN_ON_ERROR
);
142 NSDestroyObjectFileImage(image
);
146 //----------------------------------------------------------------------------
147 int DynamicLoader::CloseLibrary( DynamicLoader::LibraryHandle lib
)
149 // NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
150 // With this option the memory for the module is not deallocated
151 // allowing pointers into the module to still be valid.
152 // You should use this option instead if your code experience some problems
153 // reported against Panther 10.3.9 (fixed in Tiger 10.4.2 and up)
154 bool success
= NSUnLinkModule(lib
, NSUNLINKMODULE_OPTION_NONE
);
158 //----------------------------------------------------------------------------
159 DynamicLoader::SymbolPointer
DynamicLoader::GetSymbolAddress(
160 DynamicLoader::LibraryHandle lib
, const char* sym
)
163 // Need to prepend symbols with '_' on Apple-gcc compilers
164 size_t len
= strlen(sym
);
165 char *rsym
= new char[len
+ 1 + 1];
169 NSSymbol symbol
= NSLookupSymbolInModule(lib
, rsym
);
172 result
= NSAddressOfSymbol(symbol
);
176 // Hack to cast pointer-to-data to pointer-to-function.
177 return *reinterpret_cast<DynamicLoader::SymbolPointer
*>(&result
);
180 //----------------------------------------------------------------------------
181 const char* DynamicLoader::LibPrefix()
186 //----------------------------------------------------------------------------
187 const char* DynamicLoader::LibExtension()
189 // NSCreateObjectFileImageFromFile fail when dealing with dylib image
190 // it returns NSObjectFileImageInappropriateFile
195 //----------------------------------------------------------------------------
196 const char* DynamicLoader::LastError()
201 } // namespace KWSYS_NAMESPACE
203 #endif // MAC_OS_X_VERSION_MAX_ALLOWED < 1030
206 // ---------------------------------------------------------------
207 // 3. Implementation for Windows win32 code but not cygwin
208 #if defined(_WIN32) && !defined(__CYGWIN__)
210 #define DYNAMICLOADER_DEFINED 1
212 namespace KWSYS_NAMESPACE
215 //----------------------------------------------------------------------------
216 DynamicLoader::LibraryHandle
DynamicLoader::OpenLibrary(const char* libname
)
218 DynamicLoader::LibraryHandle lh
;
220 wchar_t libn
[MB_CUR_MAX
];
221 mbstowcs(libn
, libname
, MB_CUR_MAX
);
222 lh
= LoadLibrary(libn
);
224 lh
= LoadLibrary(libname
);
229 //----------------------------------------------------------------------------
230 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib
)
232 return (int)FreeLibrary(lib
);
235 //----------------------------------------------------------------------------
236 DynamicLoader::SymbolPointer
DynamicLoader::GetSymbolAddress(
237 DynamicLoader::LibraryHandle lib
, const char* sym
)
239 // TODO: The calling convention affects the name of the symbol. We
240 // should have a tool to help get the symbol with the desired
241 // calling convention. Currently we assume cdecl.
244 // __cdecl = "_func" (default)
245 // __fastcall = "@_func"
246 // __stdcall = "func"
250 // __fastcall = "@_func@X"
251 // __stdcall = "_func@X"
252 // __watcall = "func_" (default)
255 // __cdecl = "func" (default)
256 // __fastcall = "@_func@X"
257 // __stdcall = "_func@X"
259 // Note that the "@X" part of the name above is the total size (in
260 // bytes) of the arguments on the stack.
262 #if defined(__BORLANDC__) || defined(__WATCOMC__)
263 // Need to prepend symbols with '_'
264 size_t len
= strlen(sym
);
265 char *rsym
= new char[len
+ 1 + 1];
269 const char *rsym
= sym
;
272 wchar_t wsym
[MB_CUR_MAX
];
273 mbstowcs(wsym
, rsym
, MB_CUR_MAX
);
274 result
= GetProcAddress(lib
, wsym
);
276 result
= (void*)GetProcAddress(lib
, rsym
);
278 #if defined(__BORLANDC__) || defined(__WATCOMC__)
281 // Hack to cast pointer-to-data to pointer-to-function.
283 return *(DynamicLoader::SymbolPointer
*)(&result
);
285 return *reinterpret_cast<DynamicLoader::SymbolPointer
*>(&result
);
289 //----------------------------------------------------------------------------
290 const char* DynamicLoader::LibPrefix()
299 //----------------------------------------------------------------------------
300 const char* DynamicLoader::LibExtension()
305 //----------------------------------------------------------------------------
306 const char* DynamicLoader::LastError()
311 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
314 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), // Default language
320 static char* str
= 0;
322 str
= strcpy(new char[strlen((char*)lpMsgBuf
)+1], (char*)lpMsgBuf
);
324 LocalFree( lpMsgBuf
);
328 } // namespace KWSYS_NAMESPACE
332 // ---------------------------------------------------------------
333 // 4. Implementation for BeOS
335 #include <string.h> // for strerror()
336 #include <be/kernel/image.h>
337 #include <be/support/Errors.h>
338 #define DYNAMICLOADER_DEFINED 1
340 namespace KWSYS_NAMESPACE
343 static image_id last_dynamic_err
= B_OK
;
345 //----------------------------------------------------------------------------
346 DynamicLoader::LibraryHandle
DynamicLoader::OpenLibrary(const char* libname
)
348 // image_id's are integers, errors are negative. Add one just in case we
349 // get a valid image_id of zero (is that even possible?).
350 image_id rc
= load_add_on(libname
);
353 last_dynamic_err
= rc
;
360 //----------------------------------------------------------------------------
361 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib
)
365 last_dynamic_err
= B_BAD_VALUE
;
370 // The function dlclose() returns 0 on success, and non-zero on error.
371 status_t rc
= unload_add_on(lib
-1);
374 last_dynamic_err
= rc
;
382 //----------------------------------------------------------------------------
383 DynamicLoader::SymbolPointer
DynamicLoader::GetSymbolAddress(
384 DynamicLoader::LibraryHandle lib
, const char* sym
)
386 // Hack to cast pointer-to-data to pointer-to-function.
390 DynamicLoader::SymbolPointer psym
;
397 last_dynamic_err
= B_BAD_VALUE
;
401 // !!! FIXME: BeOS can do function-only lookups...does this ever
402 // !!! FIXME: actually _want_ a data symbol lookup, or was this union
403 // !!! FIXME: a leftover of dlsym()? (s/ANY/TEXT for functions only).
404 status_t rc
= get_image_symbol(lib
-1,sym
,B_SYMBOL_TYPE_ANY
,&result
.pvoid
);
407 last_dynamic_err
= rc
;
414 //----------------------------------------------------------------------------
415 const char* DynamicLoader::LibPrefix()
420 //----------------------------------------------------------------------------
421 const char* DynamicLoader::LibExtension()
426 //----------------------------------------------------------------------------
427 const char* DynamicLoader::LastError()
429 const char *retval
= strerror(last_dynamic_err
);
430 last_dynamic_err
= B_OK
;
434 } // namespace KWSYS_NAMESPACE
437 // ---------------------------------------------------------------
438 // 5. Implementation for systems without dynamic libs
439 // __gnu_blrts__ is IBM BlueGene/L
440 // __LIBCATAMOUNT__ is defined on Catamount on Cray compute nodes
441 #if defined(__gnu_blrts__) || defined(__LIBCATAMOUNT__)
442 #include <string.h> // for strerror()
443 #define DYNAMICLOADER_DEFINED 1
445 namespace KWSYS_NAMESPACE
448 //----------------------------------------------------------------------------
449 DynamicLoader::LibraryHandle
DynamicLoader::OpenLibrary(const char* libname
)
454 //----------------------------------------------------------------------------
455 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib
)
465 //----------------------------------------------------------------------------
466 DynamicLoader::SymbolPointer
DynamicLoader::GetSymbolAddress(
467 DynamicLoader::LibraryHandle lib
, const char* sym
)
472 //----------------------------------------------------------------------------
473 const char* DynamicLoader::LibPrefix()
478 //----------------------------------------------------------------------------
479 const char* DynamicLoader::LibExtension()
484 //----------------------------------------------------------------------------
485 const char* DynamicLoader::LastError()
487 return "General error";
490 } // namespace KWSYS_NAMESPACE
493 // ---------------------------------------------------------------
494 // 6. Implementation for default UNIX machines.
495 // if nothing has been defined then use this
496 #ifndef DYNAMICLOADER_DEFINED
497 #define DYNAMICLOADER_DEFINED 1
498 // Setup for most unix machines
501 namespace KWSYS_NAMESPACE
504 //----------------------------------------------------------------------------
505 DynamicLoader::LibraryHandle
DynamicLoader::OpenLibrary(const char* libname
)
507 return dlopen(libname
, RTLD_LAZY
);
510 //----------------------------------------------------------------------------
511 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib
)
515 // The function dlclose() returns 0 on success, and non-zero on error.
516 return !dlclose(lib
);
522 //----------------------------------------------------------------------------
523 DynamicLoader::SymbolPointer
DynamicLoader::GetSymbolAddress(
524 DynamicLoader::LibraryHandle lib
, const char* sym
)
526 // Hack to cast pointer-to-data to pointer-to-function.
530 DynamicLoader::SymbolPointer psym
;
532 result
.pvoid
= dlsym(lib
, sym
);
536 //----------------------------------------------------------------------------
537 const char* DynamicLoader::LibPrefix()
542 //----------------------------------------------------------------------------
543 const char* DynamicLoader::LibExtension()
552 //----------------------------------------------------------------------------
553 const char* DynamicLoader::LastError()
558 } // namespace KWSYS_NAMESPACE