Mercurial > hg > xemacs-beta
annotate src/sysdll.c @ 4895:65ad2cd9f2ff
Automated merge with http://hg.debian.org/hg/xemacs/xemacs
| author | Ben Wing <ben@xemacs.org> |
|---|---|
| date | Fri, 29 Jan 2010 15:06:36 -0600 |
| parents | b3ea9c582280 |
| children | 19a72041c5ed |
| rev | line source |
|---|---|
| 428 | 1 /* sysdll.c --- system dependent support for dynamic linked libraries |
| 2 Copyright (C) 1998 Free Software Foundation, Inc. | |
| 3 Author: William Perry <wmperry@aventail.com> | |
| 4 | |
| 5 This file is part of XEmacs. | |
| 6 | |
| 7 XEmacs is free software; you can redistribute it and/or modify it | |
| 8 under the terms of the GNU General Public License as published by the | |
| 9 Free Software Foundation; either version 2, or (at your option) any | |
| 10 later version. | |
| 11 | |
| 12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
| 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 15 for more details. | |
| 16 | |
| 17 You should have received a copy of the GNU General Public License | |
| 18 along with XEmacs; see the file COPYING. If not, write to the Free | |
| 19 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
| 20 02111-1307, USA. */ | |
| 21 | |
| 22 #ifdef HAVE_CONFIG_H | |
| 23 #include <config.h> | |
| 24 #endif | |
| 25 | |
| 430 | 26 #include <stdlib.h> |
| 1272 | 27 #include "lisp.h" |
| 428 | 28 #include "sysdll.h" |
| 29 | |
| 1383 | 30 #ifdef DLSYM_NEEDS_UNDERSCORE |
| 31 #define MAYBE_PREPEND_UNDERSCORE(n) do { \ | |
| 1706 | 32 CIbyte *buf = alloca_array (CIbyte, strlen (n) + 2); \ |
| 1383 | 33 *buf = '_'; \ |
| 34 strcpy (buf + 1, n); \ | |
| 35 n = buf; \ | |
| 36 } while (0) | |
| 37 #else | |
| 38 #define MAYBE_PREPEND_UNDERSCORE(n) | |
| 39 #endif | |
| 40 | |
| 428 | 41 /* This whole file is conditional upon HAVE_SHLIB */ |
| 42 #ifdef HAVE_SHLIB | |
| 43 | |
| 44 /* Thankfully, most systems follow the ELFish dlopen() method. | |
| 45 */ | |
| 452 | 46 #if defined(HAVE_DLOPEN) |
| 428 | 47 #include <dlfcn.h> |
| 48 | |
| 49 #ifndef RTLD_LAZY | |
| 1383 | 50 # ifdef DL_LAZY |
| 51 # define RTLD_LAZY DL_LAZY | |
| 52 # else | |
| 53 # define RTLD_LAZY 1 | |
| 54 # endif | |
| 428 | 55 #endif /* RTLD_LAZY isn't defined under FreeBSD - ick */ |
| 56 | |
| 863 | 57 #ifndef RTLD_NOW |
| 1383 | 58 # ifdef DL_NOW |
| 59 # define RTLD_NOW DL_NOW | |
| 60 # else | |
| 61 # define RTLD_NOW 2 | |
| 62 # endif | |
| 863 | 63 #endif |
| 64 | |
| 428 | 65 dll_handle |
| 1706 | 66 dll_open (Lisp_Object fname) |
| 428 | 67 { |
| 1706 | 68 Extbyte *soname; |
| 69 | |
| 70 if (NILP (fname)) | |
| 71 { | |
| 72 soname = NULL; | |
| 73 } | |
| 74 else | |
| 75 { | |
| 76 LISP_STRING_TO_EXTERNAL (fname, soname, Qdll_filename_encoding); | |
| 77 } | |
| 78 return (dll_handle) dlopen (soname, RTLD_NOW); | |
| 428 | 79 } |
| 80 | |
| 81 int | |
| 82 dll_close (dll_handle h) | |
| 83 { | |
| 442 | 84 return dlclose ((void *) h); |
| 428 | 85 } |
| 86 | |
| 87 dll_func | |
| 1706 | 88 dll_function (dll_handle h, const CIbyte *n) |
| 428 | 89 { |
| 1383 | 90 MAYBE_PREPEND_UNDERSCORE (n); |
| 442 | 91 return (dll_func) dlsym ((void *) h, n); |
| 428 | 92 } |
| 93 | |
| 94 dll_var | |
| 1706 | 95 dll_variable (dll_handle h, const CIbyte *n) |
| 428 | 96 { |
| 1383 | 97 MAYBE_PREPEND_UNDERSCORE (n); |
| 428 | 98 return (dll_var)dlsym ((void *)h, n); |
| 99 } | |
| 100 | |
| 1706 | 101 Lisp_Object |
| 1811 | 102 dll_error () |
| 428 | 103 { |
| 1706 | 104 const Extbyte *msg; |
| 428 | 105 #if defined(HAVE_DLERROR) || defined(dlerror) |
| 1706 | 106 msg = (const Extbyte *) dlerror (); |
| 428 | 107 #elif defined(HAVE__DLERROR) |
| 1706 | 108 msg = (const Extbyte *) _dlerror(); |
| 428 | 109 #else |
| 1706 | 110 msg = (const Extbyte *) "Shared library error"; |
| 428 | 111 #endif |
|
4834
b3ea9c582280
Use new cygwin_conv_path API with Cygwin 1.7 for converting names between Win32 and POSIX, UTF-8-aware, with attendant changes elsewhere
Ben Wing <ben@xemacs.org>
parents:
3841
diff
changeset
|
112 return build_ext_string (msg, Qerror_message_encoding); |
| 428 | 113 } |
| 114 | |
| 115 #elif defined(HAVE_SHL_LOAD) | |
| 116 /* This is the HP/UX version */ | |
| 117 #include <dl.h> | |
| 118 dll_handle | |
| 1706 | 119 dll_open (Lisp_Object fname) |
| 428 | 120 { |
| 1706 | 121 Extbyte *soname; |
| 428 | 122 |
| 1706 | 123 if (NILP (fname)) |
| 124 { | |
| 125 soname = NULL; | |
| 126 } | |
| 127 else | |
| 128 { | |
| 129 LISP_STRING_TO_EXTERNAL (fname, soname, Qdll_filename_encoding); | |
| 130 } | |
| 131 return (dll_handle) shl_load (soname, BIND_DEFERRED, 0L); | |
| 428 | 132 } |
| 133 | |
| 134 int | |
| 135 dll_close (dll_handle h) | |
| 136 { | |
| 442 | 137 return shl_unload ((shl_t) h); |
| 428 | 138 } |
| 139 | |
| 140 dll_func | |
| 1706 | 141 dll_function (dll_handle h, const CIbyte *n) |
| 428 | 142 { |
| 143 long handle = 0L; | |
| 144 | |
| 442 | 145 if (shl_findsym ((shl_t *) &h, n, TYPE_PROCEDURE, &handle)) |
| 428 | 146 return NULL; |
| 147 | |
| 442 | 148 return (dll_func) handle; |
| 428 | 149 } |
| 150 | |
| 151 dll_var | |
| 1706 | 152 dll_variable (dll_handle h, const CIbyte *n) |
| 428 | 153 { |
| 154 long handle = 0L; | |
| 155 | |
| 442 | 156 if (shl_findsym ((shl_t *) &h, n, TYPE_DATA, &handle)) |
| 428 | 157 return NULL; |
| 158 | |
| 442 | 159 return (dll_var) handle; |
| 428 | 160 } |
| 161 | |
| 1706 | 162 Lisp_Object |
| 1811 | 163 dll_error () |
| 428 | 164 { |
| 165 /* #### WTF?! Shouldn't this at least attempt to get strerror or | |
| 166 something? --hniksic */ | |
|
4834
b3ea9c582280
Use new cygwin_conv_path API with Cygwin 1.7 for converting names between Win32 and POSIX, UTF-8-aware, with attendant changes elsewhere
Ben Wing <ben@xemacs.org>
parents:
3841
diff
changeset
|
167 return build_string ("Generic shared library error", |
|
b3ea9c582280
Use new cygwin_conv_path API with Cygwin 1.7 for converting names between Win32 and POSIX, UTF-8-aware, with attendant changes elsewhere
Ben Wing <ben@xemacs.org>
parents:
3841
diff
changeset
|
168 Qerror_message_encoding); |
| 428 | 169 } |
| 170 | |
| 1632 | 171 #elif defined (WIN32_NATIVE) || defined (CYGWIN) |
| 442 | 172 |
| 1632 | 173 #include "syswindows.h" |
| 174 #include "sysfile.h" | |
| 442 | 175 |
| 428 | 176 dll_handle |
| 1706 | 177 dll_open (Lisp_Object fname) |
| 428 | 178 { |
| 1706 | 179 Extbyte *soname; |
| 180 | |
| 181 if (NILP (fname)) | |
| 182 { | |
| 183 soname = NULL; | |
| 184 } | |
| 185 else | |
| 186 { | |
|
4834
b3ea9c582280
Use new cygwin_conv_path API with Cygwin 1.7 for converting names between Win32 and POSIX, UTF-8-aware, with attendant changes elsewhere
Ben Wing <ben@xemacs.org>
parents:
3841
diff
changeset
|
187 LISP_LOCAL_FILE_FORMAT_TO_TSTR (fname, soname); |
| 1706 | 188 } |
| 189 return (dll_handle) qxeLoadLibrary (soname); | |
| 428 | 190 } |
| 191 | |
| 192 int | |
| 193 dll_close (dll_handle h) | |
| 194 { | |
| 1706 | 195 return FreeLibrary ((HMODULE) h); |
| 428 | 196 } |
| 197 | |
| 198 dll_func | |
| 1706 | 199 dll_function (dll_handle h, const CIbyte *n) |
| 428 | 200 { |
| 1706 | 201 return (dll_func) GetProcAddress ((HINSTANCE) h, n); |
| 428 | 202 } |
| 203 | |
| 204 dll_func | |
| 1706 | 205 dll_variable (dll_handle h, const CIbyte *n) |
| 428 | 206 { |
| 1706 | 207 return (dll_func) GetProcAddress ((HINSTANCE) h, n); |
| 428 | 208 } |
| 209 | |
| 1706 | 210 Lisp_Object |
| 1811 | 211 dll_error () |
| 428 | 212 { |
| 1706 | 213 CIbyte err[32]; |
| 214 snprintf (err, 32, "Windows DLL Error %lu", GetLastError ()); | |
| 215 return build_string (err); | |
| 428 | 216 } |
| 1383 | 217 #elif defined(HAVE_DYLD) |
| 218 /* This section supports MacOSX dynamic libraries. Dynamically | |
| 219 loadable libraries must be compiled as bundles, not dynamiclibs. | |
| 220 */ | |
| 221 | |
| 222 #include <mach-o/dyld.h> | |
| 223 | |
| 224 dll_handle | |
| 1706 | 225 dll_open (Lisp_Object fname) |
| 1383 | 226 { |
| 1706 | 227 Extbyte *soname; |
| 1383 | 228 NSObjectFileImage file; |
| 1418 | 229 NSModule out; |
| 1706 | 230 NSObjectFileImageReturnCode ret; |
| 231 | |
| 2855 | 232 /* |
| 233 * MacOS X dll support is for bundles, not the current executable, so return | |
| 234 * NULL is this case. However, dll_function() uses a special hack where a | |
| 235 * NULL handle can be used to find executable symbols. This satisfies the | |
| 236 * needs of ui-gtk.c but is not a general solution. | |
| 237 */ | |
| 1706 | 238 if (NILP (fname)) |
| 239 { | |
| 2855 | 240 return NULL; |
| 1706 | 241 } |
| 242 else | |
| 243 { | |
| 244 LISP_STRING_TO_EXTERNAL (fname, soname, Qdll_filename_encoding); | |
| 245 } | |
| 246 ret = NSCreateObjectFileImageFromFile(soname, &file); | |
| 1383 | 247 if (ret != NSObjectFileImageSuccess) { |
| 248 return NULL; | |
| 249 } | |
| 1706 | 250 out = NSLinkModule(file, soname, |
| 1418 | 251 NSLINKMODULE_OPTION_BINDNOW | |
| 252 NSLINKMODULE_OPTION_PRIVATE | | |
| 253 NSLINKMODULE_OPTION_RETURN_ON_ERROR); | |
| 1383 | 254 return (dll_handle)out; |
| 255 } | |
| 256 | |
| 257 int | |
| 258 dll_close (dll_handle h) | |
| 259 { | |
| 260 return NSUnLinkModule((NSModule)h, NSUNLINKMODULE_OPTION_NONE); | |
| 261 } | |
| 262 | |
| 1851 | 263 /* Given an address, return the mach_header for the image containing it |
| 264 * or zero if the given address is not contained in any loaded images. | |
| 265 * | |
| 266 * Note: image_for_address(), my_find_image() and search_linked_libs() are | |
| 267 * based on code from the dlcompat library | |
| 268 * (http://www.opendarwin.org/projects/dlcompat). | |
| 269 */ | |
| 270 | |
| 3841 | 271 static const struct mach_header* |
| 1851 | 272 image_for_address(void *address) |
| 273 { | |
| 274 unsigned long i; | |
| 275 unsigned long count = _dyld_image_count(); | |
| 3841 | 276 const struct mach_header *mh = 0; |
| 1851 | 277 |
| 278 for (i = 0; i < count; i++) | |
| 279 { | |
| 280 unsigned long addr = (unsigned long)address - | |
| 281 _dyld_get_image_vmaddr_slide(i); | |
| 282 mh = _dyld_get_image_header(i); | |
| 283 | |
| 284 if (mh) | |
| 285 { | |
| 286 struct load_command *lc = | |
| 287 (struct load_command *)((char *)mh + sizeof(struct mach_header)); | |
| 288 unsigned long j; | |
| 289 | |
| 290 for (j = 0; j < mh->ncmds; | |
| 291 j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | |
| 292 { | |
| 293 if (LC_SEGMENT == lc->cmd && | |
| 294 addr >= ((struct segment_command *)lc)->vmaddr && | |
| 295 addr < | |
| 296 ((struct segment_command *)lc)->vmaddr + | |
| 297 ((struct segment_command *)lc)->vmsize) | |
| 298 { | |
| 299 goto image_found; | |
| 300 } | |
| 301 } | |
| 302 } | |
| 303 | |
| 304 mh = 0; | |
| 305 } | |
| 306 | |
| 307 image_found: | |
| 308 return mh; | |
| 309 } | |
| 310 | |
| 311 static const struct mach_header* | |
| 312 my_find_image(const char *name) | |
| 313 { | |
| 314 const struct mach_header *mh = (struct mach_header *) | |
| 315 NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED | | |
| 316 NSADDIMAGE_OPTION_RETURN_ON_ERROR); | |
| 317 | |
| 318 if (!mh) | |
| 319 { | |
| 320 int count = _dyld_image_count(); | |
| 321 int j; | |
| 322 | |
| 323 for (j = 0; j < count; j++) | |
| 324 { | |
| 325 const char *id = _dyld_get_image_name(j); | |
| 326 | |
| 327 if (!strcmp(id, name)) | |
| 328 { | |
| 329 mh = _dyld_get_image_header(j); | |
| 330 break; | |
| 331 } | |
| 332 } | |
| 333 } | |
| 334 | |
| 335 return mh; | |
| 336 } | |
| 337 | |
| 338 /* | |
| 339 * dyld adds libraries by first adding the directly dependant libraries in | |
| 340 * link order, and then adding the dependencies for those libraries, so we | |
| 341 * should do the same... but we don't bother adding the extra dependencies, if | |
| 342 * the symbols are neither in the loaded image nor any of it's direct | |
| 343 * dependencies, then it probably isn't there. | |
| 344 */ | |
| 345 static NSSymbol | |
| 346 search_linked_libs(const struct mach_header * mh, const char *symbol) | |
| 347 { | |
| 2054 | 348 unsigned long n; |
| 1851 | 349 NSSymbol nssym = 0; |
| 350 | |
| 351 struct load_command *lc = | |
| 352 (struct load_command *)((char *)mh + sizeof(struct mach_header)); | |
| 353 | |
| 354 for (n = 0; n < mh->ncmds; | |
| 355 n++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | |
| 356 { | |
| 357 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) | |
| 358 { | |
| 359 struct mach_header *wh; | |
| 360 | |
| 361 if ((wh = (struct mach_header *) | |
| 362 my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset + | |
| 363 (char *)lc)))) | |
| 364 { | |
| 365 if (NSIsSymbolNameDefinedInImage(wh, symbol)) | |
| 366 { | |
| 367 nssym = | |
| 368 NSLookupSymbolInImage(wh, | |
| 369 symbol, | |
| 370 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | | |
| 371 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); | |
| 372 break; | |
| 373 } | |
| 374 } | |
| 375 } | |
| 376 } | |
| 377 | |
| 378 return nssym; | |
| 379 } | |
| 380 | |
| 1383 | 381 dll_func |
| 1706 | 382 dll_function (dll_handle h, const CIbyte *n) |
| 1383 | 383 { |
| 1851 | 384 NSSymbol sym = 0; |
| 1383 | 385 MAYBE_PREPEND_UNDERSCORE (n); |
| 1851 | 386 |
| 387 /* NULL means the program image and shared libraries, not bundles. */ | |
| 388 | |
| 389 if (h == NULL) | |
| 390 { | |
| 391 /* NOTE: This assumes that this function is included in the main program | |
| 392 and not in a shared library. */ | |
| 2054 | 393 const struct mach_header* my_mh = image_for_address((void*) &dll_function); |
| 1851 | 394 |
| 395 if (NSIsSymbolNameDefinedInImage(my_mh, n)) | |
| 396 { | |
| 397 sym = | |
| 398 NSLookupSymbolInImage(my_mh, | |
| 399 n, | |
| 400 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | | |
| 401 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); | |
| 402 } | |
| 403 | |
| 404 if (!sym) | |
| 405 { | |
| 406 sym = search_linked_libs(my_mh, n); | |
| 407 } | |
| 408 } | |
| 409 else | |
| 410 { | |
| 411 sym = NSLookupSymbolInModule((NSModule)h, n); | |
| 412 } | |
| 413 | |
| 414 if (sym == 0) return 0; | |
| 415 return (dll_func)NSAddressOfSymbol(sym); | |
| 416 } | |
| 1383 | 417 |
| 418 dll_var | |
| 1706 | 419 dll_variable (dll_handle h, const CIbyte *n) |
| 1383 | 420 { |
| 421 NSSymbol sym; | |
| 422 MAYBE_PREPEND_UNDERSCORE (n); | |
| 423 sym = NSLookupSymbolInModule((NSModule)h, n); | |
| 424 if (sym == 0) return 0; | |
| 425 return (dll_var)NSAddressOfSymbol(sym); | |
| 426 } | |
| 427 | |
| 1706 | 428 Lisp_Object |
| 1811 | 429 dll_error () |
| 1383 | 430 { |
| 431 NSLinkEditErrors c; | |
| 432 int errorNumber; | |
| 1706 | 433 const CIbyte *fileNameWithError, *errorString; |
| 1383 | 434 NSLinkEditError(&c, &errorNumber, &fileNameWithError, &errorString); |
|
4834
b3ea9c582280
Use new cygwin_conv_path API with Cygwin 1.7 for converting names between Win32 and POSIX, UTF-8-aware, with attendant changes elsewhere
Ben Wing <ben@xemacs.org>
parents:
3841
diff
changeset
|
435 return build_ext_string (errorString, Qerror_message_encoding); |
| 1383 | 436 } |
| 2078 | 437 #elif HAVE_LTDL |
| 438 /* Libtool's libltdl */ | |
| 439 #include <ltdl.h> | |
| 440 | |
| 441 dll_handle | |
| 442 dll_open (Lisp_Object fname) | |
| 443 { | |
| 444 Extbyte *soname; | |
| 445 | |
| 446 if (NILP (fname)) | |
| 447 { | |
| 448 soname = NULL; | |
| 449 } | |
| 450 else | |
| 451 { | |
| 452 LISP_STRING_TO_EXTERNAL (fname, soname, Qdll_filename_encoding); | |
| 453 } | |
| 454 return (dll_handle) lt_dlopen (soname); | |
| 455 } | |
| 456 | |
| 457 int | |
| 458 dll_close (dll_handle h) | |
| 459 { | |
| 460 return lt_dlclose ((lt_dlhandle) h); | |
| 461 } | |
| 462 | |
| 463 dll_func | |
| 464 dll_function (dll_handle h, const CIbyte *n) | |
| 465 { | |
| 466 MAYBE_PREPEND_UNDERSCORE (n); | |
| 467 return (dll_func) lt_dlsym ((lt_dlhandle) h, n); | |
| 468 } | |
| 469 | |
| 470 dll_var | |
| 471 dll_variable (dll_handle h, const CIbyte *n) | |
| 472 { | |
| 473 MAYBE_PREPEND_UNDERSCORE (n); | |
| 474 return (dll_var) lt_dlsym ((lt_dlhandle) h, n); | |
| 475 } | |
| 476 | |
| 477 Lisp_Object | |
| 478 dll_error () | |
| 479 { | |
|
4834
b3ea9c582280
Use new cygwin_conv_path API with Cygwin 1.7 for converting names between Win32 and POSIX, UTF-8-aware, with attendant changes elsewhere
Ben Wing <ben@xemacs.org>
parents:
3841
diff
changeset
|
480 return build_ext_string (lt_dlerror (), Qerror_message_encoding); |
| 2078 | 481 } |
| 428 | 482 #else |
| 1706 | 483 /* Catchall if we don't know about this system's method of dynamic loading */ |
| 428 | 484 dll_handle |
| 1706 | 485 dll_open (Lisp_Object fname) |
| 428 | 486 { |
| 487 return NULL; | |
| 488 } | |
| 489 | |
| 490 int | |
| 491 dll_close (dll_handle h) | |
| 492 { | |
| 493 return 0; | |
| 494 } | |
| 495 | |
| 496 dll_func | |
| 1706 | 497 dll_function (dll_handle h, const CIbyte *n) |
| 428 | 498 { |
| 499 return NULL; | |
| 500 } | |
| 501 | |
| 502 dll_func | |
| 1706 | 503 dll_variable (dll_handle h, const CIbyte *n) |
| 428 | 504 { |
| 505 return NULL; | |
| 506 } | |
| 507 | |
| 1706 | 508 Lisp_Object |
| 1811 | 509 dll_error () |
| 428 | 510 { |
| 1706 | 511 return build_string ("Shared libraries not implemented on this system"); |
| 428 | 512 } |
| 513 #endif /* System conditionals */ | |
| 514 | |
| 515 #endif /* HAVE_SHLIB */ |
