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()
308 LPVOID lpMsgBuf
=NULL
;
311 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
314 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), // Default language
325 static char* str
= 0;
327 str
= strcpy(new char[strlen((char*)lpMsgBuf
)+1], (char*)lpMsgBuf
);
329 LocalFree( lpMsgBuf
);
333 } // namespace KWSYS_NAMESPACE
337 // ---------------------------------------------------------------
338 // 4. Implementation for BeOS
341 #include <string.h> // for strerror()
343 #include <be/kernel/image.h>
344 #include <be/support/Errors.h>
346 #define DYNAMICLOADER_DEFINED 1
348 namespace KWSYS_NAMESPACE
351 static image_id last_dynamic_err
= B_OK
;
353 //----------------------------------------------------------------------------
354 DynamicLoader::LibraryHandle
DynamicLoader::OpenLibrary(const char* libname
)
356 // image_id's are integers, errors are negative. Add one just in case we
357 // get a valid image_id of zero (is that even possible?).
358 image_id rc
= load_add_on(libname
);
361 last_dynamic_err
= rc
;
368 //----------------------------------------------------------------------------
369 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib
)
373 last_dynamic_err
= B_BAD_VALUE
;
378 // The function dlclose() returns 0 on success, and non-zero on error.
379 status_t rc
= unload_add_on(lib
-1);
382 last_dynamic_err
= rc
;
390 //----------------------------------------------------------------------------
391 DynamicLoader::SymbolPointer
DynamicLoader::GetSymbolAddress(
392 DynamicLoader::LibraryHandle lib
, const char* sym
)
394 // Hack to cast pointer-to-data to pointer-to-function.
398 DynamicLoader::SymbolPointer psym
;
405 last_dynamic_err
= B_BAD_VALUE
;
409 // !!! FIXME: BeOS can do function-only lookups...does this ever
410 // !!! FIXME: actually _want_ a data symbol lookup, or was this union
411 // !!! FIXME: a leftover of dlsym()? (s/ANY/TEXT for functions only).
412 status_t rc
= get_image_symbol(lib
-1,sym
,B_SYMBOL_TYPE_ANY
,&result
.pvoid
);
415 last_dynamic_err
= rc
;
422 //----------------------------------------------------------------------------
423 const char* DynamicLoader::LibPrefix()
428 //----------------------------------------------------------------------------
429 const char* DynamicLoader::LibExtension()
434 //----------------------------------------------------------------------------
435 const char* DynamicLoader::LastError()
437 const char *retval
= strerror(last_dynamic_err
);
438 last_dynamic_err
= B_OK
;
442 } // namespace KWSYS_NAMESPACE
445 // ---------------------------------------------------------------
446 // 5. Implementation for systems without dynamic libs
447 // __gnu_blrts__ is IBM BlueGene/L
448 // __LIBCATAMOUNT__ is defined on Catamount on Cray compute nodes
449 #if defined(__gnu_blrts__) || defined(__LIBCATAMOUNT__)
450 #include <string.h> // for strerror()
451 #define DYNAMICLOADER_DEFINED 1
453 namespace KWSYS_NAMESPACE
456 //----------------------------------------------------------------------------
457 DynamicLoader::LibraryHandle
DynamicLoader::OpenLibrary(const char* libname
)
462 //----------------------------------------------------------------------------
463 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib
)
473 //----------------------------------------------------------------------------
474 DynamicLoader::SymbolPointer
DynamicLoader::GetSymbolAddress(
475 DynamicLoader::LibraryHandle lib
, const char* sym
)
480 //----------------------------------------------------------------------------
481 const char* DynamicLoader::LibPrefix()
486 //----------------------------------------------------------------------------
487 const char* DynamicLoader::LibExtension()
492 //----------------------------------------------------------------------------
493 const char* DynamicLoader::LastError()
495 return "General error";
498 } // namespace KWSYS_NAMESPACE
501 // ---------------------------------------------------------------
502 // 6. Implementation for default UNIX machines.
503 // if nothing has been defined then use this
504 #ifndef DYNAMICLOADER_DEFINED
505 #define DYNAMICLOADER_DEFINED 1
506 // Setup for most unix machines
509 namespace KWSYS_NAMESPACE
512 //----------------------------------------------------------------------------
513 DynamicLoader::LibraryHandle
DynamicLoader::OpenLibrary(const char* libname
)
515 return dlopen(libname
, RTLD_LAZY
);
518 //----------------------------------------------------------------------------
519 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib
)
523 // The function dlclose() returns 0 on success, and non-zero on error.
524 return !dlclose(lib
);
530 //----------------------------------------------------------------------------
531 DynamicLoader::SymbolPointer
DynamicLoader::GetSymbolAddress(
532 DynamicLoader::LibraryHandle lib
, const char* sym
)
534 // Hack to cast pointer-to-data to pointer-to-function.
538 DynamicLoader::SymbolPointer psym
;
540 result
.pvoid
= dlsym(lib
, sym
);
544 //----------------------------------------------------------------------------
545 const char* DynamicLoader::LibPrefix()
550 //----------------------------------------------------------------------------
551 const char* DynamicLoader::LibExtension()
560 //----------------------------------------------------------------------------
561 const char* DynamicLoader::LastError()
566 } // namespace KWSYS_NAMESPACE