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
|
|
|
|
|
|