00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
#include <pthread.h>
00033
#include <stdio.h>
00034
#include <stdlib.h>
00035
#include <string.h>
00036
#include <sys/types.h>
00037
#include <sys/stat.h>
00038
#include <stdarg.h>
00039
#include <limits.h>
00040
#include <mach-o/dyld.h>
00041
#include <mach-o/nlist.h>
00042
#include <mach-o/getsect.h>
00043
00044
00045
00046
00047
#ifndef __BSD_VISIBLE
00048 #define __BSD_VISIBLE 1
00049
#endif
00050
#include <asterisk/dlfcn-compat.h>
00051
00052
#ifndef dl_restrict
00053 #define dl_restrict __restrict
00054
#endif
00055
00056
#ifndef LC_LOAD_WEAK_DYLIB
00057 #define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
00058
#endif
00059
00060
00061
00062
00063
#ifndef LC_REQ_DYLD
00064 #define LC_REQ_DYLD 0x80000000
00065
#endif
00066
#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
00067 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
00068
#endif
00069
#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
00070 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
00071
#endif
00072
#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
00073 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
00074
#endif
00075
#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
00076 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
00077
#endif
00078
00079
static const struct mach_header *(*dyld_NSAddImage) (
const char *,
unsigned long) = 0;
00080
static int (*dyld_NSIsSymbolNameDefinedInImage) (
const struct mach_header *,
const char *) = 0;
00081
static NSSymbol(*dyld_NSLookupSymbolInImage)
00082 (
const struct mach_header *,
const char *,
unsigned long) = 0;
00083
00084
00085
00086
00087
00088
#undef REUSE_STATUS
00089
00090
00091 #define ERR_STR_LEN 251
00092
00093
00094 #define MAX_SEARCH_PATHS 32
00095
00096
00097 #define MAGIC_DYLIB_OFI ((NSObjectFileImage) 'DYOF')
00098 #define MAGIC_DYLIB_MOD ((NSModule) 'DYMO')
00099
00100
00101 #define DL_IN_LIST 0x01
00102
00103
00104
static pthread_mutex_t dlcompat_mutex;
00105
00106
00107
static pthread_key_t dlerror_key;
00108
00109 struct dlthread
00110 {
00111 int lockcnt;
00112 unsigned char errset;
00113 char errstr[
ERR_STR_LEN];
00114 };
00115
00116
00117
00118
00119 struct dlstatus
00120 {
00121 struct dlstatus *
next;
00122 NSModule
module;
00123 const struct mach_header *
lib;
00124 int refs;
00125 int mode;
00126 dev_t
device;
00127 ino_t
inode;
00128 int flags;
00129 };
00130
00131
00132
static struct dlstatus mainStatus = { 0,
MAGIC_DYLIB_MOD, NULL, -1,
RTLD_GLOBAL, 0, 0, 0 };
00133
static struct dlstatus *stqueue = &mainStatus;
00134
00135
00136
00137
00138
00139
00140
00141
static void debug(
const char *fmt, ...);
00142
static void error(
const char *str, ...);
00143
static const char *safegetenv(
const char *s);
00144
static const char *searchList(
void);
00145
static const char *getSearchPath(
int i);
00146
static const char *getFullPath(
int i,
const char *file);
00147
static const struct stat *findFile(
const char *file,
const char **fullPath);
00148
static int isValidStatus(
struct dlstatus *status);
00149
static inline int isFlagSet(
int mode,
int flag);
00150
static struct dlstatus *lookupStatus(
const struct stat *sbuf);
00151
static void insertStatus(
struct dlstatus *dls,
const struct stat *sbuf);
00152
static int promoteLocalToGlobal(
struct dlstatus *dls);
00153
static void *reference(
struct dlstatus *dls,
int mode);
00154
static void *dlsymIntern(
struct dlstatus *dls,
const char *symbol,
int canSetError);
00155
static struct dlstatus *allocStatus(
void);
00156
static struct dlstatus *loadModule(
const char *path,
const struct stat *sbuf,
int mode);
00157
static NSSymbol *search_linked_libs(
const struct mach_header *mh,
const char *symbol);
00158
static const char *get_lib_name(
const struct mach_header *mh);
00159
static const struct mach_header *get_mach_header_from_NSModule(NSModule * mod);
00160
static void dlcompat_init_func(
void);
00161
static inline void dolock(
void);
00162
static inline void dounlock(
void);
00163
static void dlerrorfree(
void *data);
00164
static void resetdlerror(
void);
00165
static const struct mach_header *my_find_image(
const char *name);
00166
static const struct mach_header *image_for_address(
const void *address);
00167
static void dlcompat_cleanup(
void);
00168
static inline const char *dyld_error_str(
void);
00169
00170
#if FINK_BUILD
00171
00172
void *dlsym_prepend_underscore(
void *handle,
const char *symbol);
00173
void *dlsym_auto_underscore(
void *handle,
const char *symbol);
00174
00175
00176
static void *dlsym_prepend_underscore_intern(
void *handle,
const char *symbol);
00177
static void *dlsym_auto_underscore_intern(
void *handle,
const char *symbol);
00178
#endif
00179
00180
00181
00182
static void debug(
const char *fmt, ...)
00183 {
00184
#if DEBUG > 1
00185
va_list arg;
00186 va_start(arg, fmt);
00187 fprintf(stderr,
"DLDEBUG: ");
00188 vfprintf(stderr, fmt, arg);
00189 fprintf(stderr,
"\n");
00190 fflush(stderr);
00191 va_end(arg);
00192
#endif
00193
}
00194
00195
static void error(
const char *str, ...)
00196 {
00197 va_list arg;
00198
struct dlthread *tss;
00199
char * err_str;
00200 va_start(arg, str);
00201 tss = pthread_getspecific(dlerror_key);
00202 err_str = tss->errstr;
00203 strncpy(err_str,
"dlcompat: ", ERR_STR_LEN);
00204 vsnprintf(err_str + 10, ERR_STR_LEN - 10, str, arg);
00205 va_end(arg);
00206 debug(
"ERROR: %s\n", err_str);
00207 tss->errset = 1;
00208 }
00209
00210
static void warning(
const char *str)
00211 {
00212
#if DEBUG > 0
00213
fprintf(stderr,
"WARNING: dlcompat: %s\n", str);
00214
#endif
00215
}
00216
00217
static const char *safegetenv(
const char *s)
00218 {
00219
const char *ss = getenv(s);
00220
return ss ? ss :
"";
00221 }
00222
00223
00224
00225
00226
00227
static const char *get_lib_name(
const struct mach_header *mh)
00228 {
00229
unsigned long count = _dyld_image_count();
00230
unsigned long i;
00231
const char *
val = NULL;
00232
if (mh)
00233 {
00234
for (i = 0; i < count; i++)
00235 {
00236
if (mh == _dyld_get_image_header(i))
00237 {
00238 val = _dyld_get_image_name(i);
00239
break;
00240 }
00241 }
00242 }
00243
return val;
00244 }
00245
00246
00247
00248
00249
00250
static const struct mach_header *get_mach_header_from_NSModule(NSModule * mod)
00251 {
00252
const char *mod_name = NSNameOfModule(mod);
00253
struct mach_header *mh = NULL;
00254
unsigned long count = _dyld_image_count();
00255
unsigned long i;
00256 debug(
"Module name: %s", mod_name);
00257
for (i = 0; i < count; i++)
00258 {
00259
if (!strcmp(mod_name, _dyld_get_image_name(i)))
00260 {
00261 mh = _dyld_get_image_header(i);
00262
break;
00263 }
00264 }
00265
return mh;
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
static const char *searchList()
00278 {
00279 size_t buf_size;
00280
static char *buf=NULL;
00281
const char *ldlp = safegetenv(
"LD_LIBRARY_PATH");
00282
const char *dyldlp = safegetenv(
"DYLD_LIBRARY_PATH");
00283
const char *stdpath = getenv(
"DYLD_FALLBACK_LIBRARY_PATH");
00284
if (!stdpath)
00285 stdpath =
"/usr/local/lib:/lib:/usr/lib";
00286
if (!buf)
00287 {
00288 buf_size = strlen(ldlp) + strlen(dyldlp) + strlen(stdpath) + 4;
00289 buf =
malloc(buf_size);
00290 snprintf(buf, buf_size,
"%s%s%s%s%s%c", dyldlp, (dyldlp[0] ?
":" :
""), ldlp, (ldlp[0] ?
":" :
""),
00291 stdpath,
'\0');
00292 }
00293
return buf;
00294 }
00295
00296
00297
static const char *getSearchPath(
int i)
00298 {
00299
static const char *list = 0;
00300
static char **path = (
char **)0;
00301
static int end = 0;
00302
static int numsize =
MAX_SEARCH_PATHS;
00303
static char **tmp;
00304
00305
if (i == -1)
00306 {
00307
return (
const char*)path;
00308 }
00309
if (!path)
00310 {
00311 path = (
char **)
calloc(MAX_SEARCH_PATHS,
sizeof(
char **));
00312 }
00313
if (!list && !end)
00314 list = searchList();
00315
if (i >= (numsize))
00316 {
00317 debug(
"Increasing size for long PATH");
00318 tmp = (
char **)
calloc((MAX_SEARCH_PATHS + numsize),
sizeof(
char **));
00319
if (tmp)
00320 {
00321 memcpy(tmp, path,
sizeof(
char **) * numsize);
00322
free(path);
00323 path = tmp;
00324 numsize +=
MAX_SEARCH_PATHS;
00325 }
00326
else
00327 {
00328
return 0;
00329 }
00330 }
00331
00332
while (!path[i] && !end)
00333 {
00334 path[i] = strsep((
char **)&list,
":");
00335
00336
if (path[i][0] == 0)
00337 path[i] = 0;
00338 end = (list == 0);
00339 }
00340
return path[i];
00341 }
00342
00343
static const char *getFullPath(
int i,
const char *file)
00344 {
00345
static char buf[PATH_MAX];
00346
const char *path = getSearchPath(i);
00347
if (path)
00348 {
00349 snprintf(buf, PATH_MAX,
"%s/%s", path, file);
00350 }
00351
return path ? buf : 0;
00352 }
00353
00354
00355
00356
00357
00358
static const struct stat *findFile(
const char *file,
const char **fullPath)
00359 {
00360
int i = 0;
00361
static struct stat sbuf;
00362
char *fileName;
00363 debug(
"finding file %s", file);
00364 *fullPath = file;
00365
if (0 == stat(file, &sbuf))
00366
return &sbuf;
00367
if (strchr(file,
'/'))
00368
return 0;
00369 fileName = NULL;
00370
if (!fileName)
00371 fileName = (
char *)file;
00372
while ((*fullPath = getFullPath(i++, fileName)))
00373 {
00374
if (0 == stat(*fullPath, &sbuf))
00375
return &sbuf;
00376 }
00377 ;
00378
return 0;
00379 }
00380
00381
00382
static int isValidStatus(
struct dlstatus *status)
00383 {
00384
00385
struct dlstatus *dls = stqueue;
00386
while (dls && status != dls)
00387 dls = dls->
next;
00388
if (dls == 0)
00389 error(
"invalid handle");
00390
else if ((dls->module == 0) || (dls->refs == 0))
00391 error(
"handle to closed library");
00392
else
00393
return TRUE;
00394
return FALSE;
00395 }
00396
00397
static inline int isFlagSet(
int mode,
int flag)
00398 {
00399
return (mode & flag) == flag;
00400 }
00401
00402
static struct dlstatus *lookupStatus(
const struct stat *sbuf)
00403 {
00404
struct dlstatus *dls = stqueue;
00405 debug(
"looking for status");
00406
while (dls && ( 0
00407 || sbuf->st_dev != dls->device || sbuf->st_ino != dls->inode))
00408 dls = dls->next;
00409
return dls;
00410 }
00411
00412
static void insertStatus(
struct dlstatus *dls,
const struct stat *sbuf)
00413 {
00414 debug(
"inserting status");
00415 dls->
inode = sbuf->st_ino;
00416 dls->
device = sbuf->st_dev;
00417 dls->
refs = 0;
00418 dls->
mode = 0;
00419
if ((dls->
flags &
DL_IN_LIST) == 0)
00420 {
00421 dls->
next = stqueue;
00422 stqueue = dls;
00423 dls->
flags |=
DL_IN_LIST;
00424 }
00425 }
00426
00427
static struct dlstatus *allocStatus()
00428 {
00429
struct dlstatus *dls;
00430
#ifdef REUSE_STATUS
00431
dls = stqueue;
00432
while (dls && dls->module)
00433 dls = dls->
next;
00434
if (!dls)
00435
#endif
00436
dls =
malloc(
sizeof(*dls));
00437 dls->flags = 0;
00438
return dls;
00439 }
00440
00441
static int promoteLocalToGlobal(
struct dlstatus *dls)
00442 {
00443
static int (*p) (NSModule
module) = 0;
00444 debug(
"promoting");
00445
if (!p)
00446 _dyld_func_lookup(
"__dyld_NSMakePrivateModulePublic", (
unsigned long *)&p);
00447
return (dls->
module ==
MAGIC_DYLIB_MOD) || (p && p(dls->
module));
00448 }
00449
00450
static void *reference(
struct dlstatus *dls,
int mode)
00451 {
00452
if (dls)
00453 {
00454
if (dls->
module ==
MAGIC_DYLIB_MOD && !isFlagSet(mode, RTLD_GLOBAL))
00455 {
00456 warning(
"trying to open a .dylib with RTLD_LOCAL");
00457 error(
"unable to open a .dylib with RTLD_LOCAL");
00458
return NULL;
00459 }
00460
if (isFlagSet(mode, RTLD_GLOBAL) &&
00461 !isFlagSet(dls->
mode, RTLD_GLOBAL) && !promoteLocalToGlobal(dls))
00462 {
00463 error(
"unable to promote local module to global");
00464
return NULL;
00465 }
00466 dls->
mode |= mode;
00467 dls->
refs++;
00468 }
00469
else
00470 debug(
"reference called with NULL argument");
00471
00472
return dls;
00473 }
00474
00475
static const struct mach_header *my_find_image(
const char *name)
00476 {
00477
const struct mach_header *mh = 0;
00478
const char *
id = NULL;
00479
int i = _dyld_image_count();
00480
int j;
00481 mh = (
struct mach_header *)
00482 dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED |
00483 NSADDIMAGE_OPTION_RETURN_ON_ERROR);
00484
if (!mh)
00485 {
00486
for (j = 0; j < i; j++)
00487 {
00488
id = _dyld_get_image_name(j);
00489
if (!strcmp(
id, name))
00490 {
00491 mh = _dyld_get_image_header(j);
00492
break;
00493 }
00494 }
00495 }
00496
return mh;
00497 }
00498
00499
00500
00501
00502
00503
00504
00505 NSSymbol *search_linked_libs(
const struct mach_header * mh,
const char *symbol)
00506 {
00507
int n;
00508
struct load_command *lc = 0;
00509
struct mach_header *wh;
00510 NSSymbol *nssym = 0;
00511
if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
00512 {
00513 lc = (
struct load_command *)((
char *)mh +
sizeof(
struct mach_header));
00514
for (n = 0; n < mh->ncmds; n++, lc = (
struct load_command *)((
char *)lc + lc->cmdsize))
00515 {
00516
if ((LC_LOAD_DYLIB == lc->cmd) || (
LC_LOAD_WEAK_DYLIB == lc->cmd))
00517 {
00518
if ((wh = (
struct mach_header *)
00519 my_find_image((
char *)(((
struct dylib_command *)lc)->dylib.name.offset +
00520 (
char *)lc))))
00521 {
00522
if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol))
00523 {
00524 nssym = dyld_NSLookupSymbolInImage(wh,
00525 symbol,
00526 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
00527 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
00528
break;
00529 }
00530 }
00531 }
00532 }
00533
if ((!nssym) && NSIsSymbolNameDefined(symbol))
00534 {
00535
00536 debug(
"Symbol \"%s\" is defined but was not found", symbol);
00537 }
00538 }
00539
return nssym;
00540 }
00541
00542
00543
static inline const char *dyld_error_str()
00544 {
00545 NSLinkEditErrors dylder;
00546
int dylderno;
00547
const char *dylderrstr;
00548
const char *dyldfile;
00549
const char* retStr = NULL;
00550 NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr);
00551
if (dylderrstr && strlen(dylderrstr))
00552 {
00553 retStr =
malloc(strlen(dylderrstr) +1);
00554 strcpy((
char*)retStr,dylderrstr);
00555 }
00556
return retStr;
00557 }
00558
00559
static void *dlsymIntern(
struct dlstatus *dls,
const char *symbol,
int canSetError)
00560 {
00561 NSSymbol *nssym = 0;
00562
void *caller = __builtin_return_address(1);
00563
const struct mach_header *caller_mh = 0;
00564
const char* savedErrorStr = NULL;
00565 resetdlerror();
00566
#ifndef RTLD_SELF
00567
#define RTLD_SELF ((void *) -3)
00568
#endif
00569
if (NULL == dls)
00570 dls =
RTLD_SELF;
00571
if ((
RTLD_NEXT == dls) || (
RTLD_SELF == dls))
00572 {
00573
if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
00574 {
00575 caller_mh = image_for_address(caller);
00576
if (
RTLD_SELF == dls)
00577 {
00578
00579
00580
00581
00582
if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol))
00583 {
00584 nssym = dyld_NSLookupSymbolInImage(caller_mh,
00585 symbol,
00586 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
00587 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
00588 }
00589 }
00590
if (!nssym)
00591 {
00592
if (
RTLD_SELF == dls)
00593 savedErrorStr = dyld_error_str();
00594 nssym = search_linked_libs(caller_mh, symbol);
00595 }
00596 }
00597
else
00598 {
00599
if (canSetError)
00600 error(
"RTLD_SELF and RTLD_NEXT are not supported");
00601
return NULL;
00602 }
00603 }
00604
if (!nssym)
00605 {
00606
00607
if (
RTLD_DEFAULT == dls)
00608 {
00609 dls = &mainStatus;
00610 }
00611
if (!isValidStatus(dls))
00612
return NULL;
00613
00614
if (dls->
module !=
MAGIC_DYLIB_MOD)
00615 {
00616 nssym = NSLookupSymbolInModule(dls->
module, symbol);
00617
if (!nssym && NSIsSymbolNameDefined(symbol))
00618 {
00619 debug(
"Searching dependencies");
00620 savedErrorStr = dyld_error_str();
00621 nssym = search_linked_libs(get_mach_header_from_NSModule(dls->
module), symbol);
00622 }
00623 }
00624
else if (dls->
lib && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
00625 {
00626
if (dyld_NSIsSymbolNameDefinedInImage(dls->
lib, symbol))
00627 {
00628 nssym = dyld_NSLookupSymbolInImage(dls->
lib,
00629 symbol,
00630 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
00631 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
00632 }
00633
else if (NSIsSymbolNameDefined(symbol))
00634 {
00635 debug(
"Searching dependencies");
00636 savedErrorStr = dyld_error_str();
00637 nssym = search_linked_libs(dls->
lib, symbol);
00638 }
00639 }
00640
else if (dls->
module ==
MAGIC_DYLIB_MOD)
00641 {
00642
00643
if (NSIsSymbolNameDefined(symbol))
00644 {
00645
00646
00647
00648 nssym = NSLookupAndBindSymbol(symbol);
00649 }
00650
else
00651 {
00652
if (savedErrorStr)
00653
free((
char*)savedErrorStr);
00654 savedErrorStr =
malloc(256);
00655 snprintf((
char*)savedErrorStr, 256,
"Symbol \"%s\" not in global context",symbol);
00656 }
00657 }
00658 }
00659
00660
if (!nssym)
00661 {
00662
if (!savedErrorStr || !strlen(savedErrorStr))
00663 {
00664
if (savedErrorStr)
00665
free((
char*)savedErrorStr);
00666 savedErrorStr =
malloc(256);
00667 snprintf((
char*)savedErrorStr, 256,
"Symbol \"%s\" not found",symbol);
00668 }
00669
if (canSetError)
00670 {
00671 error(savedErrorStr);
00672 }
00673
else
00674 {
00675 debug(savedErrorStr);
00676 }
00677
if (savedErrorStr)
00678
free((
char*)savedErrorStr);
00679
return NULL;
00680 }
00681
return NSAddressOfSymbol(nssym);
00682 }
00683
00684
static struct dlstatus *loadModule(
const char *path,
const struct stat *sbuf,
int mode)
00685 {
00686 NSObjectFileImage ofi = 0;
00687 NSObjectFileImageReturnCode ofirc;
00688
struct dlstatus *dls;
00689 NSLinkEditErrors ler;
00690
int lerno;
00691
const char *errstr;
00692
const char *file;
00693 void (*init) (
void);
00694 ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
00695
switch (ofirc)
00696 {
00697
case NSObjectFileImageSuccess:
00698
break;
00699
case NSObjectFileImageInappropriateFile:
00700
if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
00701 {
00702
if (!isFlagSet(mode, RTLD_GLOBAL))
00703 {
00704 warning(
"trying to open a .dylib with RTLD_LOCAL");
00705 error(
"unable to open this file with RTLD_LOCAL");
00706
return NULL;
00707 }
00708 }
00709
else
00710 {
00711 error(
"opening this file is unsupported on this system");
00712
return NULL;
00713 }
00714
break;
00715
case NSObjectFileImageFailure:
00716 error(
"object file setup failure");
00717
return NULL;
00718
case NSObjectFileImageArch:
00719 error(
"no object for this architecture");
00720
return NULL;
00721
case NSObjectFileImageFormat:
00722 error(
"bad object file format");
00723
return NULL;
00724
case NSObjectFileImageAccess:
00725 error(
"can't read object file");
00726
return NULL;
00727
default:
00728 error(
"unknown error from NSCreateObjectFileImageFromFile()");
00729
return NULL;
00730 }
00731 dls = lookupStatus(sbuf);
00732
if (!dls)
00733 {
00734 dls = allocStatus();
00735 }
00736
if (!dls)
00737 {
00738 error(
"unable to allocate memory");
00739
return NULL;
00740 }
00741 dls->
lib = 0;
00742
if (ofirc == NSObjectFileImageInappropriateFile)
00743 {
00744
if ((dls->
lib = dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR)))
00745 {
00746 debug(
"Dynamic lib loaded at %ld", dls->
lib);
00747 ofi =
MAGIC_DYLIB_OFI;
00748 dls->
module =
MAGIC_DYLIB_MOD;
00749 ofirc = NSObjectFileImageSuccess;
00750
00751
00752 }
00753
if (!(dls->
module))
00754 {
00755 NSLinkEditError(&ler, &lerno, &file, &errstr);
00756
if (!errstr || (!strlen(errstr)))
00757 error(
"Can't open this file type");
00758
else
00759 error(errstr);
00760
if ((dls->
flags &
DL_IN_LIST) == 0)
00761 {
00762
free(dls);
00763 }
00764
return NULL;
00765 }
00766 }
00767
else
00768 {
00769 dls->
module = NSLinkModule(ofi, path,
00770 NSLINKMODULE_OPTION_RETURN_ON_ERROR |
00771 NSLINKMODULE_OPTION_PRIVATE |
00772 (isFlagSet(mode, RTLD_NOW) ? NSLINKMODULE_OPTION_BINDNOW : 0));
00773 NSDestroyObjectFileImage(ofi);
00774
if (dls->
module)
00775 {
00776 dls->
lib = get_mach_header_from_NSModule(dls->
module);
00777 }
00778 }
00779
if (!dls->
module)
00780 {
00781 NSLinkEditError(&ler, &lerno, &file, &errstr);
00782
if ((dls->
flags &
DL_IN_LIST) == 0)
00783 {
00784
free(dls);
00785 }
00786 error(errstr);
00787
return NULL;
00788 }
00789
00790 insertStatus(dls, sbuf);
00791 dls = reference(dls, mode);
00792
if ((init = dlsymIntern(dls,
"__init", 0)))
00793 {
00794 debug(
"calling _init()");
00795 init();
00796 }
00797
return dls;
00798 }
00799
00800
static void dlcompat_init_func(
void)
00801 {
00802
static int inited = 0;
00803
if (!inited)
00804 {
00805 inited = 1;
00806 _dyld_func_lookup(
"__dyld_NSAddImage", (
unsigned long *)&dyld_NSAddImage);
00807 _dyld_func_lookup(
"__dyld_NSIsSymbolNameDefinedInImage",
00808 (
unsigned long *)&dyld_NSIsSymbolNameDefinedInImage);
00809 _dyld_func_lookup(
"__dyld_NSLookupSymbolInImage", (
unsigned long *)&dyld_NSLookupSymbolInImage);
00810
if (pthread_mutex_init(&dlcompat_mutex, NULL))
00811 exit(1);
00812
if (pthread_key_create(&dlerror_key, &dlerrorfree))
00813 exit(1);
00814
00815 atexit(dlcompat_cleanup);
00816 }
00817 }
00818
00819
#if 0
00820
#pragma CALL_ON_LOAD dlcompat_init_func
00821
#endif
00822
00823
static void dlcompat_cleanup(
void)
00824 {
00825
struct dlstatus *dls;
00826
struct dlstatus *next;
00827
char *data;
00828 data = (
char *)searchList();
00829
if ( data )
00830
free( data );
00831 data = (
char *)getSearchPath(-1);
00832
if ( data )
00833
free( data );
00834 pthread_mutex_destroy(&dlcompat_mutex);
00835 pthread_key_delete(dlerror_key);
00836 next = stqueue;
00837
while (next && (next != &mainStatus))
00838 {
00839 dls = next;
00840 next = dls->
next;
00841
free(dls);
00842 }
00843 }
00844
00845
static void resetdlerror()
00846 {
00847
struct dlthread *tss;
00848 tss = pthread_getspecific(dlerror_key);
00849 tss->errset = 0;
00850 }
00851
00852
static void dlerrorfree(
void *data)
00853 {
00854
free(data);
00855 }
00856
00857
00858
00859
00860
00861
static inline void dolock(
void)
00862 {
00863
int err = 0;
00864
struct dlthread *tss;
00865 tss = pthread_getspecific(dlerror_key);
00866
if (!tss)
00867 {
00868 tss =
malloc(
sizeof(
struct dlthread));
00869 tss->lockcnt = 0;
00870 tss->errset = 0;
00871
if (pthread_setspecific(dlerror_key, tss))
00872 {
00873 fprintf(stderr,
"dlcompat: pthread_setspecific failed\n");
00874 exit(1);
00875 }
00876 }
00877
if (!tss->lockcnt)
00878 err = pthread_mutex_lock(&dlcompat_mutex);
00879 tss->lockcnt = tss->lockcnt +1;
00880
if (err)
00881 exit(err);
00882 }
00883
00884
static inline void dounlock(
void)
00885 {
00886
int err = 0;
00887
struct dlthread *tss;
00888 tss = pthread_getspecific(dlerror_key);
00889 tss->lockcnt = tss->lockcnt -1;
00890
if (!tss->lockcnt)
00891 err = pthread_mutex_unlock(&dlcompat_mutex);
00892
if (err)
00893 exit(err);
00894 }
00895
00896 void *
dlopen(
const char *path,
int mode)
00897 {
00898
const struct stat *sbuf;
00899
struct dlstatus *dls;
00900
const char *fullPath;
00901 dlcompat_init_func();
00902 dolock();
00903 resetdlerror();
00904
if (!path)
00905 {
00906 dls = &mainStatus;
00907
goto dlopenok;
00908 }
00909
if (!(sbuf = findFile(path, &fullPath)))
00910 {
00911 error(
"file \"%s\" not found", path);
00912
goto dlopenerror;
00913 }
00914
00915
if ((dls = lookupStatus(sbuf)) && (dls->
refs > 0))
00916 {
00917
00918 dls = reference(dls, mode);
00919
goto dlopenok;
00920 }
00921
#ifdef RTLD_NOLOAD
00922
if (isFlagSet(mode,
RTLD_NOLOAD))
00923 {
00924 error(
"no existing handle and RTLD_NOLOAD specified");
00925
goto dlopenerror;
00926 }
00927
#endif
00928
if (isFlagSet(mode,
RTLD_LAZY) && isFlagSet(mode,
RTLD_NOW))
00929 {
00930 error(
"how can I load something both RTLD_LAZY and RTLD_NOW?");
00931
goto dlopenerror;
00932 }
00933 dls = loadModule(fullPath, sbuf, mode);
00934
00935 dlopenok:
00936 dounlock();
00937
return (
void *)dls;
00938 dlopenerror:
00939 dounlock();
00940
return NULL;
00941 }
00942
00943
#if !FINK_BUILD
00944 void *
dlsym(
void * dl_restrict handle,
const char * dl_restrict symbol)
00945 {
00946
int sym_len = strlen(symbol);
00947
void *value = NULL;
00948
char *malloc_sym = NULL;
00949 dolock();
00950 malloc_sym =
malloc(sym_len + 2);
00951
if (malloc_sym)
00952 {
00953 sprintf(malloc_sym,
"_%s", symbol);
00954 value = dlsymIntern(handle, malloc_sym, 1);
00955
free(malloc_sym);
00956 }
00957
else
00958 {
00959 error(
"Unable to allocate memory");
00960
goto dlsymerror;
00961 }
00962 dounlock();
00963
return value;
00964 dlsymerror:
00965 dounlock();
00966
return NULL;
00967 }
00968
#endif
00969
00970
#if FINK_BUILD
00971
00972
void *dlsym_prepend_underscore(
void *handle,
const char *symbol)
00973 {
00974
void *answer;
00975 dolock();
00976 answer = dlsym_prepend_underscore_intern(handle, symbol);
00977 dounlock();
00978
return answer;
00979 }
00980
00981
static void *dlsym_prepend_underscore_intern(
void *handle,
const char *symbol)
00982 {
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
int sym_len = strlen(symbol);
00993
void *value = NULL;
00994
char *malloc_sym = NULL;
00995 malloc_sym =
malloc(sym_len + 2);
00996
if (malloc_sym)
00997 {
00998 sprintf(malloc_sym,
"_%s", symbol);
00999 value = dlsymIntern(handle, malloc_sym, 1);
01000
free(malloc_sym);
01001 }
01002
else
01003 {
01004 error(
"Unable to allocate memory");
01005 }
01006
return value;
01007 }
01008
01009
void *dlsym_auto_underscore(
void *handle,
const char *symbol)
01010 {
01011
void *answer;
01012 dolock();
01013 answer = dlsym_auto_underscore_intern(handle, symbol);
01014 dounlock();
01015
return answer;
01016
01017 }
01018
static void *dlsym_auto_underscore_intern(
void *handle,
const char *symbol)
01019 {
01020
struct dlstatus *dls = handle;
01021
void *addr = 0;
01022 addr = dlsymIntern(dls, symbol, 0);
01023
if (!addr)
01024 addr = dlsym_prepend_underscore_intern(handle, symbol);
01025
return addr;
01026 }
01027
01028
01029
void *
dlsym(
void * dl_restrict handle,
const char * dl_restrict symbol)
01030 {
01031
struct dlstatus *dls = handle;
01032
void *addr = 0;
01033 dolock();
01034 addr = dlsymIntern(dls, symbol, 1);
01035 dounlock();
01036
return addr;
01037 }
01038
#endif
01039
01040 int dlclose(
void *handle)
01041 {
01042
struct dlstatus *dls = handle;
01043 dolock();
01044 resetdlerror();
01045
if (!isValidStatus(dls))
01046 {
01047
goto dlcloseerror;
01048 }
01049
if (dls->
module ==
MAGIC_DYLIB_MOD)
01050 {
01051
const char *name;
01052
if (!dls->
lib)
01053 {
01054 name =
"global context";
01055 }
01056
else
01057 {
01058 name = get_lib_name(dls->
lib);
01059 }
01060 warning(
"trying to close a .dylib!");
01061 error(
"Not closing \"%s\" - dynamic libraries cannot be closed", name);
01062
goto dlcloseerror;
01063 }
01064
if (!dls->
module)
01065 {
01066 error(
"module already closed");
01067
goto dlcloseerror;
01068 }
01069
01070
if (dls->
refs == 1)
01071 {
01072
unsigned long options = 0;
01073 void (*fini) (
void);
01074
if ((fini = dlsymIntern(dls,
"__fini", 0)))
01075 {
01076 debug(
"calling _fini()");
01077 fini();
01078 }
01079
#ifdef __ppc__
01080
options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
01081
#endif
01082
#if 1
01083
01084
01085
01086
01087
01088
if ((
const struct section *)NULL !=
01089 getsectbynamefromheader(get_mach_header_from_NSModule(dls->
module),
01090
"__DATA",
"__mod_term_func"))
01091 {
01092 options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
01093 }
01094
#endif
01095
#ifdef RTLD_NODELETE
01096
if (isFlagSet(dls->
mode,
RTLD_NODELETE))
01097 options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
01098
#endif
01099
if (!NSUnLinkModule(dls->
module, options))
01100 {
01101 error(
"unable to unlink module");
01102
goto dlcloseerror;
01103 }
01104 dls->
refs--;
01105 dls->
module = 0;
01106
01107
01108
01109
01110 }
01111 dounlock();
01112
return 0;
01113 dlcloseerror:
01114 dounlock();
01115
return 1;
01116 }
01117
01118 const char *
dlerror(
void)
01119 {
01120
struct dlthread *tss;
01121
char * err_str;
01122 tss = pthread_getspecific(dlerror_key);
01123 err_str = tss->errstr;
01124 tss = pthread_getspecific(dlerror_key);
01125
if (tss->errset == 0)
01126
return 0;
01127 tss->errset = 0;
01128
return (err_str );
01129 }
01130
01131
01132
01133
01134
const struct mach_header *image_for_address(
const void *address)
01135 {
01136
unsigned long i;
01137
unsigned long j;
01138
unsigned long count = _dyld_image_count();
01139
struct mach_header *mh = 0;
01140
struct load_command *lc = 0;
01141
unsigned long addr = NULL;
01142
for (i = 0; i < count; i++)
01143 {
01144 addr = (
unsigned long)address - _dyld_get_image_vmaddr_slide(i);
01145 mh = _dyld_get_image_header(i);
01146
if (mh)
01147 {
01148 lc = (
struct load_command *)((
char *)mh +
sizeof(
struct mach_header));
01149
for (j = 0; j < mh->ncmds; j++, lc = (
struct load_command *)((
char *)lc + lc->cmdsize))
01150 {
01151
if (LC_SEGMENT == lc->cmd &&
01152 addr >= ((
struct segment_command *)lc)->vmaddr &&
01153 addr <
01154 ((
struct segment_command *)lc)->vmaddr + ((
struct segment_command *)lc)->vmsize)
01155 {
01156
goto image_found;
01157 }
01158 }
01159 }
01160 mh = 0;
01161 }
01162 image_found:
01163
return mh;
01164 }
01165
01166 int dladdr(
const void * dl_restrict p,
Dl_info * dl_restrict info)
01167 {
01168
01169
01170
01171
unsigned long i;
01172
unsigned long j;
01173
unsigned long count = _dyld_image_count();
01174
struct mach_header *mh = 0;
01175
struct load_command *lc = 0;
01176
unsigned long addr = NULL;
01177
unsigned long table_off = (
unsigned long)0;
01178
int found = 0;
01179
if (!info)
01180
return 0;
01181 dolock();
01182 resetdlerror();
01183 info->dli_fname = 0;
01184 info->dli_fbase = 0;
01185 info->dli_sname = 0;
01186 info->dli_saddr = 0;
01187
01188
01189
01190
for (i = 0; i < count; i++)
01191 {
01192 addr = (
unsigned long)p - _dyld_get_image_vmaddr_slide(i);
01193 mh = _dyld_get_image_header(i);
01194
if (mh)
01195 {
01196 lc = (
struct load_command *)((
char *)mh +
sizeof(
struct mach_header));
01197
for (j = 0; j < mh->ncmds; j++, lc = (
struct load_command *)((
char *)lc + lc->cmdsize))
01198 {
01199
if (LC_SEGMENT == lc->cmd &&
01200 addr >= ((
struct segment_command *)lc)->vmaddr &&
01201 addr <
01202 ((
struct segment_command *)lc)->vmaddr + ((
struct segment_command *)lc)->vmsize)
01203 {
01204 info->dli_fname = _dyld_get_image_name(i);
01205 info->dli_fbase = (
void *)mh;
01206 found = 1;
01207
break;
01208 }
01209 }
01210
if (found)
01211
break;
01212 }
01213 }
01214
if (!found)
01215 {
01216 dounlock();
01217
return 0;
01218 }
01219 lc = (
struct load_command *)((
char *)mh +
sizeof(
struct mach_header));
01220
for (j = 0; j < mh->ncmds; j++, lc = (
struct load_command *)((
char *)lc + lc->cmdsize))
01221 {
01222
if (LC_SEGMENT == lc->cmd)
01223 {
01224
if (!strcmp(((
struct segment_command *)lc)->segname,
"__LINKEDIT"))
01225
break;
01226 }
01227 }
01228 table_off =
01229 ((
unsigned long)((
struct segment_command *)lc)->vmaddr) -
01230 ((
unsigned long)((
struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i);
01231 debug(
"table off %x", table_off);
01232
01233 lc = (
struct load_command *)((
char *)mh +
sizeof(
struct mach_header));
01234
for (j = 0; j < mh->ncmds; j++, lc = (
struct load_command *)((
char *)lc + lc->cmdsize))
01235 {
01236
if (LC_SYMTAB == lc->cmd)
01237 {
01238
01239
struct nlist *symtable = (
struct nlist *)(((
struct symtab_command *)lc)->symoff + table_off);
01240
unsigned long numsyms = ((
struct symtab_command *)lc)->nsyms;
01241
struct nlist *nearest = NULL;
01242
unsigned long diff = 0xffffffff;
01243
unsigned long strtable = (
unsigned long)(((
struct symtab_command *)lc)->stroff + table_off);
01244 debug(
"symtable %x", symtable);
01245
for (i = 0; i < numsyms; i++)
01246 {
01247
01248
if ((!symtable->n_value)
01249 || (symtable->n_type >= N_PEXT)
01250 || (!(symtable->n_type & N_EXT))
01251 )
01252 {
01253 symtable++;
01254
continue;
01255 }
01256
if ((addr >= symtable->n_value) && (diff >= (symtable->n_value - addr)))
01257 {
01258 diff = (
unsigned long)symtable->n_value - addr;
01259 nearest = symtable;
01260 }
01261 symtable++;
01262 }
01263
if (nearest)
01264 {
01265 info->dli_saddr = nearest->n_value + ((
void *)p - addr);
01266 info->dli_sname = (
char *)(strtable + nearest->n_un.n_strx);
01267 }
01268 }
01269 }
01270 dounlock();
01271
return 1;
01272 }
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
#if 0
01285
dlfunc_t dlfunc(
void * dl_restrict handle,
const char * dl_restrict symbol)
01286 {
01287
union
01288
{
01289
void *d;
01290 dlfunc_t f;
01291 } rv;
01292
int sym_len = strlen(symbol);
01293
char *malloc_sym = NULL;
01294 dolock();
01295 malloc_sym =
malloc(sym_len + 2);
01296
if (malloc_sym)
01297 {
01298 sprintf(malloc_sym,
"_%s", symbol);
01299 rv.d = dlsymIntern(handle, malloc_sym, 1);
01300
free(malloc_sym);
01301 }
01302
else
01303 {
01304 error(
"Unable to allocate memory");
01305
goto dlfuncerror;
01306 }
01307 dounlock();
01308
return rv.f;
01309 dlfuncerror:
01310 dounlock();
01311
return NULL;
01312 }
01313
#endif