Doxygen Source Code Documentation
dlopen.c File Reference
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <limits.h>#include "mach-o/dyld.h"#include "dlfcn.h"Go to the source code of this file.
Data Structures | |
| struct | dlopen_handle |
Defines | |
| #define | DEBUG_PRINT(format) /**/ |
| #define | DEBUG_PRINT1(format, arg1) /**/ |
| #define | DEBUG_PRINT2(format, arg1, arg2) /**/ |
| #define | DEBUG_PRINT3(format, arg1, arg2, arg3) /**/ |
Functions | |
| enum DYLD_BOOL | NSMakePrivateModulePublic (NSModule module) |
| int | _dl_search_paths (const char *filename, char *pathbuf, struct stat *stat_buf) |
| void * | dlopen (const char *path, int mode) |
| void * | dlsym (void *handle, const char *symbol) |
| const char * | dlerror (void) |
| int | dlclose (void *handle) |
Variables | |
| dlopen_handle * | dlopen_handles = NULL |
| const struct dlopen_handle | main_program_handle = {NULL} |
| char * | dlerror_pointer = NULL |
Define Documentation
|
|
Definition at line 51 of file dlopen.c. Referenced by dlclose(). |
|
|
|
|
|
|
|
|
|
Function Documentation
|
||||||||||||||||
|
Definition at line 107 of file dlopen.c. References getenv(), p, and q. Referenced by dlopen().
00111 {
00112 const char *pathspec;
00113 const char *element;
00114 const char *p;
00115 char *q;
00116 char *pathbuf_end;
00117 const char *envvars[] = {
00118 "$DYLD_LIBRARY_PATH",
00119 "$LD_LIBRARY_PATH",
00120 "/usr/lib:/lib",
00121 NULL };
00122 int envvar_index;
00123
00124 pathbuf_end = pathbuf + PATH_MAX - 8;
00125
00126 for(envvar_index = 0; envvars[envvar_index]; envvar_index++){
00127 if(envvars[envvar_index][0] == '$'){
00128 pathspec = getenv(envvars[envvar_index]+1);
00129 }
00130 else {
00131 pathspec = envvars[envvar_index];
00132 }
00133
00134 if(pathspec != NULL){
00135 element = pathspec;
00136 while(*element){
00137 /* extract path list element */
00138 p = element;
00139 q = pathbuf;
00140 while(*p && *p != ':' && q < pathbuf_end) *q++ = *p++;
00141 if(q == pathbuf){ /* empty element */
00142 if(*p){
00143 element = p+1;
00144 continue;
00145 }
00146 break;
00147 }
00148 if (*p){
00149 element = p+1;
00150 }
00151 else{
00152 element = p; /* this terminates the loop */
00153 }
00154
00155 /* add slash if neccessary */
00156 if(*(q-1) != '/' && q < pathbuf_end){
00157 *q++ = '/';
00158 }
00159
00160 /* append module name */
00161 p = filename;
00162 while(*p && q < pathbuf_end) *q++ = *p++;
00163 *q++ = 0;
00164
00165 if(q >= pathbuf_end){
00166 /* maybe add an error message here */
00167 break;
00168 }
00169
00170 if(stat(pathbuf, stat_buf) == 0){
00171 return 0;
00172 }
00173 }
00174 }
00175 }
00176
00177 /* we have searched everywhere, now we give up */
00178 return -1;
00179 }
|
|
|
Definition at line 462 of file dlopen.c. References DEBUG_PRINT, DEBUG_PRINT1, dlerror_pointer, dlopen_handle::dlopen_count, dlopen_handle::dlopen_mode, free, dlopen_handle::module, dlopen_handle::next, dlopen_handle::prev, RTLD_LAZY_UNDEF, and RTLD_NODELETE.
00464 {
00465 struct dlopen_handle *p, *q;
00466 unsigned long options;
00467 NSSymbol NSSymbol;
00468 void (*fini)(void);
00469
00470 DEBUG_PRINT1("libdl: dlclose(%p) -> ", handle);
00471
00472 dlerror_pointer = NULL;
00473 q = (struct dlopen_handle *)handle;
00474 p = dlopen_handles;
00475 while(p != NULL){
00476 if(p == q){
00477 /* if the dlopen() count is not zero we are done */
00478 p->dlopen_count--;
00479 if(p->dlopen_count != 0){
00480 DEBUG_PRINT("OK");
00481 return(0);
00482 }
00483
00484 /* call the fini function if one exists */
00485 NSSymbol = NSLookupSymbolInModule(p->module, "__fini");
00486 if(NSSymbol != NULL){
00487 fini = NSAddressOfSymbol(NSSymbol);
00488 fini();
00489 }
00490
00491 /* unlink the module for this handle */
00492 options = 0;
00493 if(p->dlopen_mode & RTLD_NODELETE)
00494 options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
00495 if(p->dlopen_mode & RTLD_LAZY_UNDEF)
00496 options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
00497 if(NSUnLinkModule(p->module, options) == FALSE){
00498 dlerror_pointer = "NSUnLinkModule() failed for dlclose()";
00499 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00500 return(-1);
00501 }
00502 if(p->prev != NULL)
00503 p->prev->next = p->next;
00504 if(p->next != NULL)
00505 p->next->prev = p->prev;
00506 if(dlopen_handles == p)
00507 dlopen_handles = p->next;
00508 free(p);
00509 DEBUG_PRINT("OK");
00510 return(0);
00511 }
00512 p = p->next;
00513 }
00514 dlerror_pointer = "invalid handle passed to dlclose()";
00515 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00516 return(-1);
00517 }
|
|
|
Definition at line 448 of file dlopen.c. References dlerror_pointer, and p.
00450 {
00451 const char *p;
00452
00453 p = (const char *)dlerror_pointer;
00454 dlerror_pointer = NULL;
00455 return(p);
00456 }
|
|
||||||||||||
|
Definition at line 185 of file dlopen.c. References _dl_search_paths(), DEBUG_PRINT1, DEBUG_PRINT2, dlopen_handle::dev, dlerror_pointer, dlopen_handle::dlopen_count, dlopen_handle::dlopen_mode, dlopen_handle::ino, malloc, dlopen_handle::module, dlopen_handle::next, NSMakePrivateModulePublic(), dlopen_handle::prev, retval(), RTLD_GLOBAL, RTLD_LAZY_UNDEF, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_NOW, RTLD_UNSHARED, and strerror().
00188 {
00189 const char *module_path;
00190 void *retval;
00191 struct stat stat_buf;
00192 NSObjectFileImage objectFileImage;
00193 NSObjectFileImageReturnCode ofile_result_code;
00194 NSModule module;
00195 struct dlopen_handle *p;
00196 unsigned long options;
00197 NSSymbol NSSymbol;
00198 void (*init)(void);
00199 char pathbuf[PATH_MAX];
00200
00201 DEBUG_PRINT2("libdl: dlopen(%s,0x%x) -> ", path, (unsigned int)mode);
00202
00203 dlerror_pointer = NULL;
00204 /*
00205 * A NULL path is to indicate the caller wants a handle for the
00206 * main program.
00207 */
00208 if(path == NULL){
00209 retval = (void *)&main_program_handle;
00210 DEBUG_PRINT1("main / %p\n", retval);
00211 return(retval);
00212 }
00213
00214 /* see if the path exists and if so get the device and inode number */
00215 if(stat(path, &stat_buf) == -1){
00216 dlerror_pointer = strerror(errno);
00217
00218 if(path[0] == '/'){
00219 DEBUG_PRINT1("ERROR (stat): %s\n", dlerror_pointer);
00220 return(NULL);
00221 }
00222
00223 /* search for the module in various places */
00224 if(_dl_search_paths(path, pathbuf, &stat_buf)){
00225 /* dlerror_pointer is unmodified */
00226 DEBUG_PRINT1("ERROR (stat): %s\n", dlerror_pointer);
00227 return(NULL);
00228 }
00229 DEBUG_PRINT1("found %s -> ", pathbuf);
00230 module_path = pathbuf;
00231 dlerror_pointer = NULL;
00232 }
00233 else{
00234 module_path = path;
00235 }
00236
00237 /*
00238 * If we don't want an unshared handle see if we already have a handle
00239 * for this path.
00240 */
00241 if((mode & RTLD_UNSHARED) != RTLD_UNSHARED){
00242 p = dlopen_handles;
00243 while(p != NULL){
00244 if(p->dev == stat_buf.st_dev && p->ino == stat_buf.st_ino){
00245 /* skip unshared handles */
00246 if((p->dlopen_mode & RTLD_UNSHARED) == RTLD_UNSHARED)
00247 continue;
00248 /*
00249 * We have already created a handle for this path. The
00250 * caller might be trying to promote an RTLD_LOCAL handle
00251 * to a RTLD_GLOBAL. Or just looking it up with
00252 * RTLD_NOLOAD.
00253 */
00254 if((p->dlopen_mode & RTLD_LOCAL) == RTLD_LOCAL &&
00255 (mode & RTLD_GLOBAL) == RTLD_GLOBAL){
00256 /* promote the handle */
00257 if(NSMakePrivateModulePublic(p->module) == TRUE){
00258 p->dlopen_mode &= ~RTLD_LOCAL;
00259 p->dlopen_mode |= RTLD_GLOBAL;
00260 p->dlopen_count++;
00261 DEBUG_PRINT1("%p\n", p);
00262 return(p);
00263 }
00264 else{
00265 dlerror_pointer = "can't promote handle from "
00266 "RTLD_LOCAL to RTLD_GLOBAL";
00267 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00268 return(NULL);
00269 }
00270 }
00271 p->dlopen_count++;
00272 DEBUG_PRINT1("%p\n", p);
00273 return(p);
00274 }
00275 p = p->next;
00276 }
00277 }
00278
00279 /*
00280 * We do not have a handle for this path if we were just trying to
00281 * look it up return NULL to indicate we don't have it.
00282 */
00283 if((mode & RTLD_NOLOAD) == RTLD_NOLOAD){
00284 dlerror_pointer = "no existing handle for path RTLD_NOLOAD test";
00285 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00286 return(NULL);
00287 }
00288
00289 /* try to create an object file image from this path */
00290 ofile_result_code = NSCreateObjectFileImageFromFile(module_path,
00291 &objectFileImage);
00292 if(ofile_result_code != NSObjectFileImageSuccess){
00293 switch(ofile_result_code){
00294 case NSObjectFileImageFailure:
00295 dlerror_pointer = "object file setup failure";
00296 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00297 return(NULL);
00298 case NSObjectFileImageInappropriateFile:
00299 dlerror_pointer = "not a Mach-O MH_BUNDLE file type";
00300 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00301 return(NULL);
00302 case NSObjectFileImageArch:
00303 dlerror_pointer = "no object for this architecture";
00304 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00305 return(NULL);
00306 case NSObjectFileImageFormat:
00307 dlerror_pointer = "bad object file format";
00308 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00309 return(NULL);
00310 case NSObjectFileImageAccess:
00311 dlerror_pointer = "can't read object file";
00312 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00313 return(NULL);
00314 default:
00315 dlerror_pointer = "unknown error from "
00316 "NSCreateObjectFileImageFromFile()";
00317 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00318 return(NULL);
00319 }
00320 }
00321
00322 /* try to link in this object file image */
00323 options = NSLINKMODULE_OPTION_PRIVATE;
00324 if((mode & RTLD_NOW) == RTLD_NOW)
00325 options |= NSLINKMODULE_OPTION_BINDNOW;
00326 module = NSLinkModule(objectFileImage, module_path, options);
00327 NSDestroyObjectFileImage(objectFileImage) ;
00328 if(module == NULL){
00329 dlerror_pointer = "NSLinkModule() failed for dlopen()";
00330 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00331 return(NULL);
00332 }
00333
00334 /*
00335 * If the handle is to be global promote the handle. It is done this
00336 * way to avoid multiply defined symbols.
00337 */
00338 if((mode & RTLD_GLOBAL) == RTLD_GLOBAL){
00339 if(NSMakePrivateModulePublic(module) == FALSE){
00340 dlerror_pointer = "can't promote handle from RTLD_LOCAL to "
00341 "RTLD_GLOBAL";
00342 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00343 return(NULL);
00344 }
00345 }
00346
00347 p = malloc(sizeof(struct dlopen_handle));
00348 if(p == NULL){
00349 dlerror_pointer = "can't allocate memory for the dlopen handle";
00350 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00351 return(NULL);
00352 }
00353
00354 /* fill in the handle */
00355 p->dev = stat_buf.st_dev;
00356 p->ino = stat_buf.st_ino;
00357 if(mode & RTLD_GLOBAL)
00358 p->dlopen_mode = RTLD_GLOBAL;
00359 else
00360 p->dlopen_mode = RTLD_LOCAL;
00361 p->dlopen_mode |= (mode & RTLD_UNSHARED) |
00362 (mode & RTLD_NODELETE) |
00363 (mode & RTLD_LAZY_UNDEF);
00364 p->dlopen_count = 1;
00365 p->module = module;
00366 p->prev = NULL;
00367 p->next = dlopen_handles;
00368 if(dlopen_handles != NULL)
00369 dlopen_handles->prev = p;
00370 dlopen_handles = p;
00371
00372 /* call the init function if one exists */
00373 NSSymbol = NSLookupSymbolInModule(p->module, "__init");
00374 if(NSSymbol != NULL){
00375 init = NSAddressOfSymbol(NSSymbol);
00376 init();
00377 }
00378
00379 DEBUG_PRINT1("%p\n", p);
00380 return(p);
00381 }
|
|
||||||||||||
|
Definition at line 387 of file dlopen.c. References DEBUG_PRINT1, DEBUG_PRINT2, dlerror_pointer, dlopen_handle::module, and dlopen_handle::next.
00390 {
00391 struct dlopen_handle *dlopen_handle, *p;
00392 NSSymbol NSSymbol;
00393 void *address;
00394
00395 DEBUG_PRINT2("libdl: dlsym(%p,%s) -> ", handle, symbol);
00396
00397 dlopen_handle = (struct dlopen_handle *)handle;
00398
00399 /*
00400 * If this is the handle for the main program do a global lookup.
00401 */
00402 if(dlopen_handle == (struct dlopen_handle *)&main_program_handle){
00403 if(NSIsSymbolNameDefined(symbol) == TRUE){
00404 NSSymbol = NSLookupAndBindSymbol(symbol);
00405 address = NSAddressOfSymbol(NSSymbol);
00406 dlerror_pointer = NULL;
00407 DEBUG_PRINT1("%p\n", address);
00408 return(address);
00409 }
00410 else{
00411 dlerror_pointer = "symbol not found";
00412 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00413 return(NULL);
00414 }
00415 }
00416
00417 /*
00418 * Find this handle and do a lookup in just this module.
00419 */
00420 p = dlopen_handles;
00421 while(p != NULL){
00422 if(dlopen_handle == p){
00423 NSSymbol = NSLookupSymbolInModule(p->module, symbol);
00424 if(NSSymbol != NULL){
00425 address = NSAddressOfSymbol(NSSymbol);
00426 dlerror_pointer = NULL;
00427 DEBUG_PRINT1("%p\n", address);
00428 return(address);
00429 }
00430 else{
00431 dlerror_pointer = "symbol not found";
00432 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00433 return(NULL);
00434 }
00435 }
00436 p = p->next;
00437 }
00438
00439 dlerror_pointer = "bad handle passed to dlsym()";
00440 DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer);
00441 return(NULL);
00442 }
|
|
|
typedef enum { FALSE = 0, TRUE = 1 } bool; * Definition at line 84 of file dlopen.c. References p. Referenced by dlopen().
00086 {
00087 static enum DYLD_BOOL (*p)(NSModule module) = NULL;
00088
00089 if(p == NULL)
00090 _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",
00091 (unsigned long *)&p);
00092 if(p == NULL){
00093 #ifdef DEBUG
00094 printf("_dyld_func_lookup of __dyld_NSMakePrivateModulePublic "
00095 "failed\n");
00096 #endif
00097 return(FALSE);
00098 }
00099 return(p(module));
00100 }
|
Variable Documentation
|
|
|
|
|
|
|
|
|