00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #if defined (HAVE_SHL_LOAD_API)
00028 #include <cerrno>
00029 #include <cstring>
00030 #endif
00031
00032 #if defined (HAVE_DYLD_API)
00033 #include <mach-o/dyld.h>
00034 #endif
00035
00036 extern "C"
00037 {
00038 #if defined (HAVE_DLOPEN_API)
00039 #if defined (HAVE_DLFCN_H)
00040 #include <dlfcn.h>
00041 #else
00042 extern void *dlopen (const char *, int);
00043 extern const char *dlerror (void);
00044 extern void *dlsym (void *, const char *);
00045 extern int dlclose (void *);
00046 #endif
00047 #elif defined (HAVE_SHL_LOAD_API)
00048 #include <dl.h>
00049 #endif
00050 }
00051
00052 #include "file-stat.h"
00053 #include "lo-error.h"
00054 #include "oct-shlib.h"
00055 #include "str-vec.h"
00056
00057 class
00058 octave_base_shlib : public octave_shlib
00059 {
00060 public:
00061
00062 octave_base_shlib (void)
00063 : octave_shlib (octave_xshlib ()), file (), fcn_names (),
00064 tm_loaded (static_cast<time_t> (0))
00065 { count = 1; }
00066
00067 octave_base_shlib (const std::string& f)
00068 : octave_shlib (octave_xshlib ()), file (f), fcn_names (),
00069 tm_loaded (static_cast<time_t> (0))
00070 { count = 1; }
00071
00072 ~octave_base_shlib (void) { }
00073
00074 void open (const std::string&, bool = false) { }
00075
00076 void *search (const std::string&, name_mangler = 0) { return 0; }
00077
00078 void close (octave_shlib::close_hook = 0) { }
00079
00080 bool remove (const std::string& fcn_name);
00081
00082 bool is_open (void) const { return false; }
00083
00084 bool is_out_of_date (void) const;
00085
00086 int number_of_functions_loaded (void) const { return fcn_names.length (); }
00087
00088 std::string file_name (void) const { return file; }
00089
00090 octave_time time_loaded (void) const { return tm_loaded; }
00091
00092 protected:
00093
00094 std::string file;
00095
00096 string_vector fcn_names;
00097
00098 octave_time tm_loaded;
00099
00100 void stamp_time (bool warn_future = false);
00101
00102 void add_to_fcn_names (const std::string& name);
00103
00104 void do_close_hook (octave_shlib::close_hook = 0);
00105
00106 void tabula_rasa (void);
00107
00108
00109
00110 octave_base_shlib (const octave_base_shlib&);
00111
00112 octave_base_shlib& operator = (const octave_base_shlib&);
00113 };
00114
00115 bool
00116 octave_base_shlib::remove (const std::string& fcn_name)
00117 {
00118 bool retval = false;
00119
00120 int n = number_of_functions_loaded ();
00121
00122 string_vector new_fcn_names (n);
00123
00124 int k = 0;
00125
00126 for (int i = 0; i < n; i++)
00127 {
00128 if (fcn_names(i) == fcn_name)
00129 retval = true;
00130 else
00131 new_fcn_names(k++) = fcn_names(i);
00132 }
00133
00134 new_fcn_names.resize (k);
00135
00136 fcn_names = new_fcn_names;
00137
00138 return retval;
00139 }
00140
00141 bool
00142 octave_base_shlib::is_out_of_date (void) const
00143 {
00144 file_stat fs (file);
00145
00146 return fs.is_newer (tm_loaded);
00147 }
00148
00149 void
00150 octave_base_shlib::stamp_time (bool warn_future)
00151 {
00152 tm_loaded.stamp ();
00153
00154 if (warn_future)
00155 {
00156 file_stat fs (file);
00157
00158 if (fs.is_newer (tm_loaded))
00159 (*current_liboctave_warning_handler)
00160 ("timestamp on file %s is in the future", file.c_str ());
00161 }
00162 }
00163
00164 void
00165 octave_base_shlib::add_to_fcn_names (const std::string& name)
00166 {
00167 int n = number_of_functions_loaded ();
00168
00169 for (int i = 0; i < n; i++)
00170 if (fcn_names(i) == name)
00171 return;
00172
00173 fcn_names.resize (n+1);
00174
00175 fcn_names(n) = name;
00176 }
00177
00178 void
00179 octave_base_shlib::do_close_hook (octave_shlib::close_hook cl_hook)
00180 {
00181 int n = number_of_functions_loaded ();
00182
00183 for (int i = 0; i < n; i++)
00184 cl_hook (fcn_names(i));
00185 }
00186
00187 void
00188 octave_base_shlib::tabula_rasa (void)
00189 {
00190 file = "";
00191
00192 fcn_names.resize (0);
00193
00194 tm_loaded = static_cast<time_t> (0);
00195 }
00196
00197 #if defined (HAVE_DLOPEN_API)
00198
00199 class
00200 octave_dlopen_shlib : public octave_base_shlib
00201 {
00202 public:
00203
00204 octave_dlopen_shlib (void);
00205
00206 ~octave_dlopen_shlib (void);
00207
00208 void open (const std::string& f, bool warn_future = false);
00209
00210 void *search (const std::string& name, name_mangler mangler = 0);
00211
00212 void close (octave_shlib::close_hook cl_hook = 0);
00213
00214 bool is_open (void) const { return (library != 0); }
00215
00216 private:
00217
00218
00219
00220 octave_dlopen_shlib (const octave_dlopen_shlib&);
00221
00222 octave_dlopen_shlib& operator = (const octave_dlopen_shlib&);
00223
00224 void *library;
00225 };
00226
00227 octave_dlopen_shlib::octave_dlopen_shlib (void)
00228 : octave_base_shlib (), library (0)
00229 {
00230 }
00231
00232 octave_dlopen_shlib::~octave_dlopen_shlib (void)
00233 {
00234 close ();
00235 }
00236
00237 void
00238 octave_dlopen_shlib::open (const std::string& f, bool warn_future)
00239 {
00240 if (! is_open ())
00241 {
00242 file = f;
00243
00244 int flags = 0;
00245
00246 #if defined (RTLD_LAZY)
00247 flags |= RTLD_LAZY;
00248 #endif
00249
00250 #if defined (RTLD_GLOBAL)
00251 flags |= RTLD_GLOBAL;
00252 #endif
00253
00254 library = dlopen (file.c_str (), flags);
00255
00256 if (library)
00257 stamp_time (warn_future);
00258 else
00259 {
00260 const char *msg = dlerror ();
00261
00262 if (msg)
00263 (*current_liboctave_error_handler) ("%s", msg);
00264 }
00265 }
00266 else
00267 (*current_liboctave_error_handler)
00268 ("shared library %s is already open", file.c_str ());
00269 }
00270
00271 void *
00272 octave_dlopen_shlib::search (const std::string& name,
00273 octave_shlib::name_mangler mangler)
00274 {
00275 void *function = 0;
00276
00277 if (is_open ())
00278 {
00279 std::string sym_name = name;
00280
00281 if (mangler)
00282 sym_name = mangler (name);
00283
00284 function = dlsym (library, sym_name.c_str ());
00285
00286 if (function)
00287 add_to_fcn_names (name);
00288 }
00289 else
00290 (*current_liboctave_error_handler)
00291 ("shared library %s is not open", file.c_str ());
00292
00293 return function;
00294 }
00295
00296 void
00297 octave_dlopen_shlib::close (octave_shlib::close_hook cl_hook)
00298 {
00299 if (is_open ())
00300 {
00301 do_close_hook (cl_hook);
00302
00303 dlclose (library);
00304
00305 library = 0;
00306
00307 tabula_rasa ();
00308 }
00309 }
00310
00311 #elif defined (HAVE_SHL_LOAD_API)
00312
00313 class
00314 octave_shl_load_shlib : public octave_base_shlib
00315 {
00316 public:
00317
00318 octave_shl_load_shlib (void);
00319
00320 ~octave_shl_load_shlib (void);
00321
00322 void open (const std::string& f, bool warn_future = false);
00323
00324 void *search (const std::string& name, name_mangler mangler = 0);
00325
00326 void close (octave_shlib::close_hook cl_hook = 0);
00327
00328 bool is_open (void) const { return (library != 0); }
00329
00330 private:
00331
00332
00333
00334 octave_shl_load_shlib (const octave_shl_load_shlib&);
00335
00336 octave_shl_load_shlib& operator = (const octave_shl_load_shlib&);
00337
00338 shl_t library;
00339 };
00340
00341 octave_shl_load_shlib::octave_shl_load_shlib (void)
00342 : octave_base_shlib (), library (0)
00343 {
00344 }
00345
00346 octave_shl_load_shlib::~octave_shl_load_shlib (void)
00347 {
00348 close ();
00349 }
00350
00351 void
00352 octave_shl_load_shlib::open (const std::string& f, bool warn_future)
00353 {
00354 if (! is_open ())
00355 {
00356 file = f;
00357
00358 library = shl_load (file.c_str (), BIND_DEFERRED, 0L);
00359
00360 if (library)
00361 stamp_time (warn_future);
00362 else
00363 {
00364 using namespace std;
00365 (*current_liboctave_error_handler) ("%s", strerror (errno));
00366 }
00367 }
00368 else
00369 (*current_liboctave_error_handler)
00370 ("shared library %s is already open", file.c_str ());
00371 }
00372
00373 void *
00374 octave_shl_load_shlib::search (const std::string& name,
00375 octave_shlib::name_mangler mangler)
00376 {
00377 void *function = 0;
00378
00379 if (is_open ())
00380 {
00381 std::string sym_name = name;
00382
00383 if (mangler)
00384 sym_name = mangler (name);
00385
00386 int status = shl_findsym (&library, sym_name.c_str (),
00387 TYPE_UNDEFINED, &function);
00388
00389 if (status == 0)
00390 add_to_fcn_names (name);
00391 }
00392 else
00393 (*current_liboctave_error_handler)
00394 ("shared library %s is not open", file.c_str ());
00395
00396 return function;
00397 }
00398
00399 void
00400 octave_shl_load_shlib::close (octave_shlib::close_hook cl_hook)
00401 {
00402 if (is_open ())
00403 {
00404 do_close_hook (cl_hook);
00405
00406 shl_unload (library);
00407
00408 library = 0;
00409
00410 tabula_rasa ();
00411 }
00412 }
00413
00414 #elif defined (HAVE_LOADLIBRARY_API)
00415
00416 class
00417 octave_w32_shlib: public octave_base_shlib
00418 {
00419 public:
00420
00421 octave_w32_shlib (void);
00422
00423 ~octave_w32_shlib (void);
00424
00425 void open (const std::string& f, bool warn_future = false);
00426
00427 void *search (const std::string& name, name_mangler mangler = 0);
00428
00429 void close (octave_shlib::close_hook cl_hook = 0);
00430
00431 bool is_open (void) const { return (handle != 0); }
00432
00433 private:
00434
00435
00436
00437 octave_w32_shlib (const octave_w32_shlib&);
00438
00439 octave_w32_shlib& operator = (const octave_w32_shlib&);
00440
00441 HINSTANCE handle;
00442 };
00443
00444 octave_w32_shlib::octave_w32_shlib (void)
00445 : octave_base_shlib (), handle (0)
00446 {
00447 }
00448
00449 octave_w32_shlib::~octave_w32_shlib (void)
00450 {
00451 close ();
00452 }
00453
00454 void
00455 octave_w32_shlib::open (const std::string& f, bool warn_future)
00456 {
00457 if (! is_open ())
00458 {
00459 file = f;
00460
00461 handle = LoadLibrary (file.c_str ());
00462
00463 if (handle != NULL)
00464 stamp_time (warn_future);
00465 else
00466 {
00467 DWORD lastError = GetLastError ();
00468 char *msg;
00469
00470 switch (lastError)
00471 {
00472 case ERROR_MOD_NOT_FOUND:
00473 case ERROR_DLL_NOT_FOUND:
00474 msg = "could not find library or dependents";
00475 break;
00476
00477 case ERROR_INVALID_DLL:
00478 msg = "library or its dependents are damaged";
00479 break;
00480
00481 case ERROR_DLL_INIT_FAILED:
00482 msg = "library initialization routine failed";
00483 break;
00484
00485 default:
00486 msg = "library open failed";
00487 }
00488
00489 (*current_liboctave_error_handler) ("%s: %s", msg, file.c_str ());
00490 }
00491 }
00492 else
00493 (*current_liboctave_error_handler)
00494 ("shared library %s is already open", file.c_str ());
00495 }
00496
00497 void *
00498 octave_w32_shlib::search (const std::string& name,
00499 octave_shlib::name_mangler mangler)
00500 {
00501 void *function = 0;
00502
00503 if (is_open ())
00504 {
00505 std::string sym_name = name;
00506
00507 if (mangler)
00508 sym_name = mangler (name);
00509
00510 function
00511 = static_cast<void *> (GetProcAddress (handle, sym_name.c_str ()));
00512
00513 if (function)
00514 add_to_fcn_names (name);
00515 }
00516 else
00517 (*current_liboctave_error_handler)
00518 ("shared library %s is not open", file.c_str ());
00519
00520 return function;
00521 }
00522
00523 void
00524 octave_w32_shlib::close (octave_shlib::close_hook cl_hook)
00525 {
00526 if (is_open ())
00527 {
00528 do_close_hook (cl_hook);
00529
00530 FreeLibrary (handle);
00531
00532 handle = 0;
00533
00534 tabula_rasa ();
00535 }
00536 }
00537
00538 #elif defined (HAVE_DYLD_API)
00539
00540 class
00541 octave_dyld_shlib : public octave_base_shlib
00542 {
00543 public:
00544
00545 octave_dyld_shlib (void);
00546
00547 ~octave_dyld_shlib (void);
00548
00549 void open (const std::string& f, bool warn_future = false);
00550
00551 void *search (const std::string& name, name_mangler mangler = 0);
00552
00553 void close (octave_shlib::close_hook cl_hook = 0);
00554
00555 bool is_open (void) const {return (isOpen); }
00556
00557 private:
00558
00559
00560
00561 octave_dyld_shlib (const octave_dyld_shlib&);
00562
00563 octave_dyld_shlib& operator = (const octave_dyld_shlib&);
00564
00565 bool isOpen;
00566 NSObjectFileImage img;
00567 NSModule handle;
00568 };
00569
00570 octave_dyld_shlib::octave_dyld_shlib (void)
00571 : octave_base_shlib (), isOpen (false), handle (0)
00572 {
00573 }
00574
00575 octave_dyld_shlib::~octave_dyld_shlib (void)
00576 {
00577 close ();
00578 }
00579
00580 void
00581 octave_dyld_shlib::open (const std::string& f, bool warn_future)
00582 {
00583 int returnCode;
00584
00585 if (! is_open ())
00586 {
00587 file = f;
00588
00589 returnCode = NSCreateObjectFileImageFromFile (file.c_str (), &img);
00590
00591 if (NSObjectFileImageSuccess == returnCode)
00592 {
00593 handle = NSLinkModule (img, file.c_str (),
00594 (NSLINKMODULE_OPTION_RETURN_ON_ERROR
00595 | NSLINKMODULE_OPTION_PRIVATE));
00596 if (handle)
00597 {
00598 stamp_time (warn_future);
00599 isOpen = true;
00600 }
00601 else
00602 {
00603 (*current_liboctave_error_handler)
00604 ("couldn't link module %s", file.c_str ());
00605 }
00606 }
00607 else
00608 {
00609 (*current_liboctave_error_handler)
00610 ("got NSObjectFileImageReturnCode %d", returnCode);
00611
00612
00613
00614 }
00615 }
00616 else
00617 {
00618 (*current_liboctave_error_handler)
00619 ("bundle %s is already open", file.c_str ());
00620 }
00621 }
00622
00623 void *
00624 octave_dyld_shlib::search (const std::string& name,
00625 octave_shlib::name_mangler mangler)
00626 {
00627 void *function = 0;
00628
00629 if (is_open ())
00630 {
00631 std::string sym_name = name;
00632
00633 if (mangler)
00634 sym_name = mangler (name);
00635
00636 NSSymbol symbol = NSLookupSymbolInModule (handle, sym_name.c_str ());
00637
00638 if (symbol)
00639 {
00640 function = NSAddressOfSymbol (symbol);
00641 add_to_fcn_names (name);
00642 }
00643 }
00644 else
00645 (*current_liboctave_error_handler)
00646 ("bundle %s is not open", file.c_str ());
00647
00648 return function;
00649 }
00650
00651 void
00652 octave_dyld_shlib::close (octave_shlib::close_hook cl_hook)
00653 {
00654 if (is_open ())
00655 {
00656 do_close_hook (cl_hook);
00657
00658 NSUnLinkModule (handle, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
00659
00660 handle = 0;
00661
00662 if (NSDestroyObjectFileImage (img))
00663 isOpen = false;
00664
00665 tabula_rasa ();
00666 }
00667 }
00668
00669 #endif
00670
00671 octave_shlib *
00672 octave_shlib::make_shlib (void)
00673 {
00674 #if defined (HAVE_DLOPEN_API)
00675 return new octave_dlopen_shlib ();
00676 #elif defined (HAVE_SHL_LOAD_API)
00677 return new octave_shl_load_shlib ();
00678 #elif defined (HAVE_LOADLIBRARY_API)
00679 return new octave_w32_shlib ();
00680 #elif defined (HAVE_DYLD_API)
00681 return new octave_dyld_shlib ();
00682 #else
00683 return new octave_base_shlib ();
00684 #endif
00685 }
00686
00687
00688
00689
00690
00691