Mercurial > sdl-ios-xcode
comparison src/loadso/macosx/SDL_dlcompat.c @ 1895:c121d94672cb
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 10 Jul 2006 21:04:37 +0000 |
parents | e308d020d315 |
children | e1da92da346c |
comparison
equal
deleted
inserted
replaced
1894:c69cee13dd76 | 1895:c121d94672cb |
---|---|
83 #define __BSD_VISIBLE 1 | 83 #define __BSD_VISIBLE 1 |
84 #endif | 84 #endif |
85 | 85 |
86 /*include "dlfcn.h"*/ | 86 /*include "dlfcn.h"*/ |
87 #ifdef __cplusplus | 87 #ifdef __cplusplus |
88 extern "C" { | 88 extern "C" |
89 { | |
89 #endif | 90 #endif |
90 | 91 |
91 #if defined (__GNUC__) && __GNUC__ > 3 | 92 #if defined (__GNUC__) && __GNUC__ > 3 |
92 #define dl_restrict __restrict | 93 #define dl_restrict __restrict |
93 #else | 94 #else |
97 #if 0 | 98 #if 0 |
98 #ifndef _POSIX_SOURCE | 99 #ifndef _POSIX_SOURCE |
99 /* | 100 /* |
100 * Structure filled in by dladdr(). | 101 * Structure filled in by dladdr(). |
101 */ | 102 */ |
102 typedef struct SDL_OSX_dl_info { | 103 typedef struct SDL_OSX_dl_info |
103 const char *dli_fname; /* Pathname of shared object */ | 104 { |
104 void *dli_fbase; /* Base address of shared object */ | 105 const char *dli_fname; /* Pathname of shared object */ |
105 const char *dli_sname; /* Name of nearest symbol */ | 106 void *dli_fbase; /* Base address of shared object */ |
106 void *dli_saddr; /* Address of nearest symbol */ | 107 const char *dli_sname; /* Name of nearest symbol */ |
107 } SDL_OSX_Dl_info; | 108 void *dli_saddr; /* Address of nearest symbol */ |
108 | 109 } SDL_OSX_Dl_info; |
109 static int SDL_OSX_dladdr(const void * dl_restrict, SDL_OSX_Dl_info * dl_restrict); | 110 |
110 #endif /* ! _POSIX_SOURCE */ | 111 static int SDL_OSX_dladdr(const void *dl_restrict, |
111 #endif /* 0 */ | 112 SDL_OSX_Dl_info * dl_restrict); |
112 | 113 #endif /* ! _POSIX_SOURCE */ |
113 static int SDL_OSX_dlclose(void * handle); | 114 #endif /* 0 */ |
114 static const char * SDL_OSX_dlerror(void); | 115 |
115 static void * SDL_OSX_dlopen(const char *path, int mode); | 116 static int SDL_OSX_dlclose(void *handle); |
116 static void * SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol); | 117 static const char *SDL_OSX_dlerror(void); |
118 static void *SDL_OSX_dlopen(const char *path, int mode); | |
119 static void *SDL_OSX_dlsym(void *dl_restrict handle, | |
120 const char *dl_restrict symbol); | |
117 | 121 |
118 #define RTLD_LAZY 0x1 | 122 #define RTLD_LAZY 0x1 |
119 #define RTLD_NOW 0x2 | 123 #define RTLD_NOW 0x2 |
120 #define RTLD_LOCAL 0x4 | 124 #define RTLD_LOCAL 0x4 |
121 #define RTLD_GLOBAL 0x8 | 125 #define RTLD_GLOBAL 0x8 |
125 #define RTLD_NODELETE 0x80 | 129 #define RTLD_NODELETE 0x80 |
126 | 130 |
127 /* | 131 /* |
128 * Special handle arguments for SDL_OSX_dlsym(). | 132 * Special handle arguments for SDL_OSX_dlsym(). |
129 */ | 133 */ |
130 #define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ | 134 #define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ |
131 #define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ | 135 #define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ |
132 #endif /* ! _POSIX_SOURCE */ | 136 #endif /* ! _POSIX_SOURCE */ |
133 | 137 |
134 #ifdef __cplusplus | 138 #ifdef __cplusplus |
135 } | 139 } |
136 #endif | 140 #endif |
137 | 141 |
160 #endif | 164 #endif |
161 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR | 165 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR |
162 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4 | 166 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4 |
163 #endif | 167 #endif |
164 /* These symbols will be looked for in dyld */ | 168 /* These symbols will be looked for in dyld */ |
165 static const struct mach_header *(*dyld_NSAddImage) (const char *, unsigned long) = 0; | 169 static const struct mach_header *(*dyld_NSAddImage) (const char *, |
166 static int (*dyld_NSIsSymbolNameDefinedInImage) (const struct mach_header *, const char *) = 0; | 170 unsigned long) = 0; |
167 static NSSymbol(*dyld_NSLookupSymbolInImage) | 171 static int (*dyld_NSIsSymbolNameDefinedInImage) (const struct mach_header *, |
168 (const struct mach_header *, const char *, unsigned long) = 0; | 172 const char *) = 0; |
173 static NSSymbol(*dyld_NSLookupSymbolInImage) (const struct mach_header *, | |
174 const char *, unsigned long) = | |
175 0; | |
169 | 176 |
170 /* Define this to make dlcompat reuse data block. This way in theory we save | 177 /* Define this to make dlcompat reuse data block. This way in theory we save |
171 * a little bit of overhead. However we then couldn't correctly catch excess | 178 * a little bit of overhead. However we then couldn't correctly catch excess |
172 * calls to SDL_OSX_dlclose(). Hence we don't use this feature | 179 * calls to SDL_OSX_dlclose(). Hence we don't use this feature |
173 */ | 180 */ |
192 */ | 199 */ |
193 static pthread_key_t dlerror_key; | 200 static pthread_key_t dlerror_key; |
194 | 201 |
195 struct dlthread | 202 struct dlthread |
196 { | 203 { |
197 int lockcnt; | 204 int lockcnt; |
198 unsigned char errset; | 205 unsigned char errset; |
199 char errstr[ERR_STR_LEN]; | 206 char errstr[ERR_STR_LEN]; |
200 }; | 207 }; |
201 | 208 |
202 /* This is our central data structure. Whenever a module is loaded via | 209 /* This is our central data structure. Whenever a module is loaded via |
203 * SDL_OSX_dlopen(), we create such a struct. | 210 * SDL_OSX_dlopen(), we create such a struct. |
204 */ | 211 */ |
205 struct dlstatus | 212 struct dlstatus |
206 { | 213 { |
207 struct dlstatus *next; /* pointer to next element in the linked list */ | 214 struct dlstatus *next; /* pointer to next element in the linked list */ |
208 NSModule module; | 215 NSModule module; |
209 const struct mach_header *lib; | 216 const struct mach_header *lib; |
210 int refs; /* reference count */ | 217 int refs; /* reference count */ |
211 int mode; /* mode in which this module was loaded */ | 218 int mode; /* mode in which this module was loaded */ |
212 dev_t device; | 219 dev_t device; |
213 ino_t inode; | 220 ino_t inode; |
214 int flags; /* Any internal flags we may need */ | 221 int flags; /* Any internal flags we may need */ |
215 }; | 222 }; |
216 | 223 |
217 /* Head node of the dlstatus list */ | 224 /* Head node of the dlstatus list */ |
218 static struct dlstatus mainStatus = { 0, MAGIC_DYLIB_MOD, NULL, -1, RTLD_GLOBAL, 0, 0, 0 }; | 225 static struct dlstatus mainStatus = |
226 { 0, MAGIC_DYLIB_MOD, NULL, -1, RTLD_GLOBAL, 0, 0, 0 }; | |
219 static struct dlstatus *stqueue = &mainStatus; | 227 static struct dlstatus *stqueue = &mainStatus; |
220 | 228 |
221 | 229 |
222 /* Storage for the last error message (used by dlerror()) */ | 230 /* Storage for the last error message (used by dlerror()) */ |
223 /* static char err_str[ERR_STR_LEN]; */ | 231 /* static char err_str[ERR_STR_LEN]; */ |
235 static inline int isFlagSet(int mode, int flag); | 243 static inline int isFlagSet(int mode, int flag); |
236 static struct dlstatus *lookupStatus(const struct stat *sbuf); | 244 static struct dlstatus *lookupStatus(const struct stat *sbuf); |
237 static void insertStatus(struct dlstatus *dls, const struct stat *sbuf); | 245 static void insertStatus(struct dlstatus *dls, const struct stat *sbuf); |
238 static int promoteLocalToGlobal(struct dlstatus *dls); | 246 static int promoteLocalToGlobal(struct dlstatus *dls); |
239 static void *reference(struct dlstatus *dls, int mode); | 247 static void *reference(struct dlstatus *dls, int mode); |
240 static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError); | 248 static void *dlsymIntern(struct dlstatus *dls, const char *symbol, |
249 int canSetError); | |
241 static struct dlstatus *allocStatus(void); | 250 static struct dlstatus *allocStatus(void); |
242 static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode); | 251 static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, |
243 static NSSymbol search_linked_libs(const struct mach_header *mh, const char *symbol); | 252 int mode); |
253 static NSSymbol search_linked_libs(const struct mach_header *mh, | |
254 const char *symbol); | |
244 static const char *get_lib_name(const struct mach_header *mh); | 255 static const char *get_lib_name(const struct mach_header *mh); |
245 static const struct mach_header *get_mach_header_from_NSModule(NSModule mod); | 256 static const struct mach_header *get_mach_header_from_NSModule(NSModule mod); |
246 static void dlcompat_init_func(void); | 257 static void dlcompat_init_func(void); |
247 static inline void dlcompat_init_check(void); | 258 static inline void dlcompat_init_check(void); |
248 static inline void dolock(void); | 259 static inline void dolock(void); |
257 /* Two Global Functions */ | 268 /* Two Global Functions */ |
258 static void *dlsym_prepend_underscore(void *handle, const char *symbol); | 269 static void *dlsym_prepend_underscore(void *handle, const char *symbol); |
259 static void *dlsym_auto_underscore(void *handle, const char *symbol); | 270 static void *dlsym_auto_underscore(void *handle, const char *symbol); |
260 | 271 |
261 /* And their _intern counterparts */ | 272 /* And their _intern counterparts */ |
262 static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol); | 273 static void *dlsym_prepend_underscore_intern(void *handle, |
274 const char *symbol); | |
263 static void *dlsym_auto_underscore_intern(void *handle, const char *symbol); | 275 static void *dlsym_auto_underscore_intern(void *handle, const char *symbol); |
264 #endif | 276 #endif |
265 | 277 |
266 /* Functions */ | 278 /* Functions */ |
267 | 279 |
268 static void debug(const char *fmt, ...) | 280 static void |
281 debug(const char *fmt, ...) | |
269 { | 282 { |
270 #if DEBUG > 1 | 283 #if DEBUG > 1 |
271 va_list arg; | 284 va_list arg; |
272 va_start(arg, fmt); | 285 va_start(arg, fmt); |
273 fprintf(stderr, "DLDEBUG: "); | 286 fprintf(stderr, "DLDEBUG: "); |
274 vfprintf(stderr, fmt, arg); | 287 vfprintf(stderr, fmt, arg); |
275 fprintf(stderr, "\n"); | 288 fprintf(stderr, "\n"); |
276 fflush(stderr); | 289 fflush(stderr); |
277 va_end(arg); | 290 va_end(arg); |
278 #endif | 291 #endif |
279 } | 292 } |
280 | 293 |
281 static void error(const char *str, ...) | 294 static void |
282 { | 295 error(const char *str, ...) |
283 va_list arg; | 296 { |
284 struct dlthread *tss; | 297 va_list arg; |
285 char * err_str; | 298 struct dlthread *tss; |
286 va_start(arg, str); | 299 char *err_str; |
287 tss = pthread_getspecific(dlerror_key); | 300 va_start(arg, str); |
288 err_str = tss->errstr; | 301 tss = pthread_getspecific(dlerror_key); |
289 SDL_strlcpy(err_str, "dlcompat: ", ERR_STR_LEN); | 302 err_str = tss->errstr; |
290 vsnprintf(err_str + 10, ERR_STR_LEN - 10, str, arg); | 303 SDL_strlcpy(err_str, "dlcompat: ", ERR_STR_LEN); |
291 va_end(arg); | 304 vsnprintf(err_str + 10, ERR_STR_LEN - 10, str, arg); |
292 debug("ERROR: %s\n", err_str); | 305 va_end(arg); |
293 tss->errset = 1; | 306 debug("ERROR: %s\n", err_str); |
294 } | 307 tss->errset = 1; |
295 | 308 } |
296 static void warning(const char *str) | 309 |
310 static void | |
311 warning(const char *str) | |
297 { | 312 { |
298 #if DEBUG > 0 | 313 #if DEBUG > 0 |
299 fprintf(stderr, "WARNING: dlcompat: %s\n", str); | 314 fprintf(stderr, "WARNING: dlcompat: %s\n", str); |
300 #endif | 315 #endif |
301 } | 316 } |
302 | 317 |
303 static const char *safegetenv(const char *s) | 318 static const char * |
304 { | 319 safegetenv(const char *s) |
305 const char *ss = SDL_getenv(s); | 320 { |
306 return ss ? ss : ""; | 321 const char *ss = SDL_getenv(s); |
322 return ss ? ss : ""; | |
307 } | 323 } |
308 | 324 |
309 /* because this is only used for debugging and error reporting functions, we | 325 /* because this is only used for debugging and error reporting functions, we |
310 * don't really care about how elegant it is... it could use the load | 326 * don't really care about how elegant it is... it could use the load |
311 * commands to find the install name of the library, but... | 327 * commands to find the install name of the library, but... |
312 */ | 328 */ |
313 static const char *get_lib_name(const struct mach_header *mh) | 329 static const char * |
314 { | 330 get_lib_name(const struct mach_header *mh) |
315 unsigned long count = _dyld_image_count(); | 331 { |
316 unsigned long i; | 332 unsigned long count = _dyld_image_count(); |
317 const char *val = NULL; | 333 unsigned long i; |
318 if (mh) | 334 const char *val = NULL; |
319 { | 335 if (mh) { |
320 for (i = 0; i < count; i++) | 336 for (i = 0; i < count; i++) { |
321 { | 337 if (mh == _dyld_get_image_header(i)) { |
322 if (mh == _dyld_get_image_header(i)) | 338 val = _dyld_get_image_name(i); |
323 { | 339 break; |
324 val = _dyld_get_image_name(i); | 340 } |
325 break; | 341 } |
326 } | 342 } |
327 } | 343 return val; |
328 } | |
329 return val; | |
330 } | 344 } |
331 | 345 |
332 /* Returns the mach_header for the module bu going through all the loaded images | 346 /* Returns the mach_header for the module bu going through all the loaded images |
333 * and finding the one with the same name as the module. There really ought to be | 347 * and finding the one with the same name as the module. There really ought to be |
334 * an api for doing this, would be faster, but there isn't one right now | 348 * an api for doing this, would be faster, but there isn't one right now |
335 */ | 349 */ |
336 static const struct mach_header *get_mach_header_from_NSModule(NSModule mod) | 350 static const struct mach_header * |
337 { | 351 get_mach_header_from_NSModule(NSModule mod) |
338 const char *mod_name = NSNameOfModule(mod); | 352 { |
339 const struct mach_header *mh = NULL; | 353 const char *mod_name = NSNameOfModule(mod); |
340 unsigned long count = _dyld_image_count(); | 354 const struct mach_header *mh = NULL; |
341 unsigned long i; | 355 unsigned long count = _dyld_image_count(); |
342 debug("Module name: %s", mod_name); | 356 unsigned long i; |
343 for (i = 0; i < count; i++) | 357 debug("Module name: %s", mod_name); |
344 { | 358 for (i = 0; i < count; i++) { |
345 if (!SDL_strcmp(mod_name, _dyld_get_image_name(i))) | 359 if (!SDL_strcmp(mod_name, _dyld_get_image_name(i))) { |
346 { | 360 mh = _dyld_get_image_header(i); |
347 mh = _dyld_get_image_header(i); | 361 break; |
348 break; | 362 } |
349 } | 363 } |
350 } | 364 return mh; |
351 return mh; | |
352 } | 365 } |
353 | 366 |
354 | 367 |
355 /* Compute and return a list of all directories that we should search when | 368 /* Compute and return a list of all directories that we should search when |
356 * trying to locate a module. We first look at the values of LD_LIBRARY_PATH | 369 * trying to locate a module. We first look at the values of LD_LIBRARY_PATH |
358 * /usr/lib and /lib. Since both of the environments variables can contain a | 371 * /usr/lib and /lib. Since both of the environments variables can contain a |
359 * list of colon seperated paths, we simply concat them and the two other paths | 372 * list of colon seperated paths, we simply concat them and the two other paths |
360 * into one big string, which we then can easily parse. | 373 * into one big string, which we then can easily parse. |
361 * Splitting this string into the actual path list is done by getSearchPath() | 374 * Splitting this string into the actual path list is done by getSearchPath() |
362 */ | 375 */ |
363 static const char *searchList() | 376 static const char * |
364 { | 377 searchList() |
365 size_t buf_size; | 378 { |
366 static char *buf=NULL; | 379 size_t buf_size; |
367 const char *ldlp = safegetenv("LD_LIBRARY_PATH"); | 380 static char *buf = NULL; |
368 const char *dyldlp = safegetenv("DYLD_LIBRARY_PATH"); | 381 const char *ldlp = safegetenv("LD_LIBRARY_PATH"); |
369 const char *stdpath = SDL_getenv("DYLD_FALLBACK_LIBRARY_PATH"); | 382 const char *dyldlp = safegetenv("DYLD_LIBRARY_PATH"); |
370 if (!stdpath) | 383 const char *stdpath = SDL_getenv("DYLD_FALLBACK_LIBRARY_PATH"); |
371 stdpath = "/usr/local/lib:/lib:/usr/lib"; | 384 if (!stdpath) |
372 if (!buf) | 385 stdpath = "/usr/local/lib:/lib:/usr/lib"; |
373 { | 386 if (!buf) { |
374 buf_size = SDL_strlen(ldlp) + SDL_strlen(dyldlp) + SDL_strlen(stdpath) + 4; | 387 buf_size = |
375 buf = SDL_malloc(buf_size); | 388 SDL_strlen(ldlp) + SDL_strlen(dyldlp) + SDL_strlen(stdpath) + 4; |
376 SDL_snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp, (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""), | 389 buf = SDL_malloc(buf_size); |
377 stdpath, '\0'); | 390 SDL_snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp, |
378 } | 391 (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""), |
379 return buf; | 392 stdpath, '\0'); |
393 } | |
394 return buf; | |
380 } | 395 } |
381 | 396 |
382 /* Returns the ith search path from the list as computed by searchList() */ | 397 /* Returns the ith search path from the list as computed by searchList() */ |
383 static const char *getSearchPath(int i) | 398 static const char * |
384 { | 399 getSearchPath(int i) |
385 static const char *list = 0; | 400 { |
386 static char **path = (char **)0; | 401 static const char *list = 0; |
387 static int end = 0; | 402 static char **path = (char **) 0; |
388 static int numsize = MAX_SEARCH_PATHS; | 403 static int end = 0; |
389 static char **tmp; | 404 static int numsize = MAX_SEARCH_PATHS; |
390 /* So we can call SDL_free() in the "destructor" we use i=-1 to return the alloc'd array */ | 405 static char **tmp; |
391 if (i == -1) | 406 /* So we can call SDL_free() in the "destructor" we use i=-1 to return the alloc'd array */ |
392 { | 407 if (i == -1) { |
393 return (const char*)path; | 408 return (const char *) path; |
394 } | 409 } |
395 if (!path) | 410 if (!path) { |
396 { | 411 path = (char **) SDL_calloc(MAX_SEARCH_PATHS, sizeof(char **)); |
397 path = (char **)SDL_calloc(MAX_SEARCH_PATHS, sizeof(char **)); | 412 } |
398 } | 413 if (!list && !end) |
399 if (!list && !end) | 414 list = searchList(); |
400 list = searchList(); | 415 if (i >= (numsize)) { |
401 if (i >= (numsize)) | 416 debug("Increasing size for long PATH"); |
402 { | 417 tmp = |
403 debug("Increasing size for long PATH"); | 418 (char **) SDL_calloc((MAX_SEARCH_PATHS + numsize), |
404 tmp = (char **)SDL_calloc((MAX_SEARCH_PATHS + numsize), sizeof(char **)); | 419 sizeof(char **)); |
405 if (tmp) | 420 if (tmp) { |
406 { | 421 SDL_memcpy(tmp, path, sizeof(char **) * numsize); |
407 SDL_memcpy(tmp, path, sizeof(char **) * numsize); | 422 SDL_free(path); |
408 SDL_free(path); | 423 path = tmp; |
409 path = tmp; | 424 numsize += MAX_SEARCH_PATHS; |
410 numsize += MAX_SEARCH_PATHS; | 425 } else { |
411 } | 426 return 0; |
412 else | 427 } |
413 { | 428 } |
414 return 0; | 429 |
415 } | 430 while (!path[i] && !end) { |
416 } | 431 path[i] = strsep((char **) &list, ":"); |
417 | 432 |
418 while (!path[i] && !end) | 433 if (path[i][0] == 0) |
419 { | 434 path[i] = 0; |
420 path[i] = strsep((char **)&list, ":"); | 435 end = (list == 0); |
421 | 436 } |
422 if (path[i][0] == 0) | 437 return path[i]; |
423 path[i] = 0; | 438 } |
424 end = (list == 0); | 439 |
425 } | 440 static const char * |
426 return path[i]; | 441 getFullPath(int i, const char *file) |
427 } | 442 { |
428 | 443 static char buf[PATH_MAX]; |
429 static const char *getFullPath(int i, const char *file) | 444 const char *path = getSearchPath(i); |
430 { | 445 if (path) { |
431 static char buf[PATH_MAX]; | 446 SDL_snprintf(buf, PATH_MAX, "%s/%s", path, file); |
432 const char *path = getSearchPath(i); | 447 } |
433 if (path) | 448 return path ? buf : 0; |
434 { | |
435 SDL_snprintf(buf, PATH_MAX, "%s/%s", path, file); | |
436 } | |
437 return path ? buf : 0; | |
438 } | 449 } |
439 | 450 |
440 /* Given a file name, try to determine the full path for that file. Starts | 451 /* Given a file name, try to determine the full path for that file. Starts |
441 * its search in the current directory, and then tries all paths in the | 452 * its search in the current directory, and then tries all paths in the |
442 * search list in the order they are specified there. | 453 * search list in the order they are specified there. |
443 */ | 454 */ |
444 static const struct stat *findFile(const char *file, const char **fullPath) | 455 static const struct stat * |
445 { | 456 findFile(const char *file, const char **fullPath) |
446 int i = 0; | 457 { |
447 static struct stat sbuf; | 458 int i = 0; |
448 char *fileName; | 459 static struct stat sbuf; |
449 debug("finding file %s", file); | 460 char *fileName; |
450 *fullPath = file; | 461 debug("finding file %s", file); |
451 if (0 == stat(file, &sbuf)) | 462 *fullPath = file; |
452 return &sbuf; | 463 if (0 == stat(file, &sbuf)) |
453 if (SDL_strchr(file, '/')) | 464 return &sbuf; |
454 return 0; /* If the path had a / we don't look in env var places */ | 465 if (SDL_strchr(file, '/')) |
455 fileName = NULL; | 466 return 0; /* If the path had a / we don't look in env var places */ |
456 if (!fileName) | 467 fileName = NULL; |
457 fileName = (char *)file; | 468 if (!fileName) |
458 while ((*fullPath = getFullPath(i++, fileName))) | 469 fileName = (char *) file; |
459 { | 470 while ((*fullPath = getFullPath(i++, fileName))) { |
460 if (0 == stat(*fullPath, &sbuf)) | 471 if (0 == stat(*fullPath, &sbuf)) |
461 return &sbuf; | 472 return &sbuf; |
462 } | 473 } |
463 ; | 474 ; |
464 return 0; | 475 return 0; |
465 } | 476 } |
466 | 477 |
467 /* Determine whether a given dlstatus is valid or not */ | 478 /* Determine whether a given dlstatus is valid or not */ |
468 static int isValidStatus(struct dlstatus *status) | 479 static int |
469 { | 480 isValidStatus(struct dlstatus *status) |
470 /* Walk the list to verify status is contained in it */ | 481 { |
471 struct dlstatus *dls = stqueue; | 482 /* Walk the list to verify status is contained in it */ |
472 while (dls && status != dls) | 483 struct dlstatus *dls = stqueue; |
473 dls = dls->next; | 484 while (dls && status != dls) |
474 if (dls == 0) | 485 dls = dls->next; |
475 error("invalid handle"); | 486 if (dls == 0) |
476 else if ((dls->module == 0) || (dls->refs == 0)) | 487 error("invalid handle"); |
477 error("handle to closed library"); | 488 else if ((dls->module == 0) || (dls->refs == 0)) |
478 else | 489 error("handle to closed library"); |
479 return TRUE; | 490 else |
480 return FALSE; | 491 return TRUE; |
481 } | 492 return FALSE; |
482 | 493 } |
483 static inline int isFlagSet(int mode, int flag) | 494 |
484 { | 495 static inline int |
485 return (mode & flag) == flag; | 496 isFlagSet(int mode, int flag) |
486 } | 497 { |
487 | 498 return (mode & flag) == flag; |
488 static struct dlstatus *lookupStatus(const struct stat *sbuf) | 499 } |
489 { | 500 |
490 struct dlstatus *dls = stqueue; | 501 static struct dlstatus * |
491 debug("looking for status"); | 502 lookupStatus(const struct stat *sbuf) |
492 while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0 | 503 { |
493 || sbuf->st_dev != dls->device || sbuf->st_ino != dls->inode)) | 504 struct dlstatus *dls = stqueue; |
494 dls = dls->next; | 505 debug("looking for status"); |
495 return dls; | 506 while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0 |
496 } | 507 || sbuf->st_dev != dls->device |
497 | 508 || sbuf->st_ino != dls->inode)) |
498 static void insertStatus(struct dlstatus *dls, const struct stat *sbuf) | 509 dls = dls->next; |
499 { | 510 return dls; |
500 debug("inserting status"); | 511 } |
501 dls->inode = sbuf->st_ino; | 512 |
502 dls->device = sbuf->st_dev; | 513 static void |
503 dls->refs = 0; | 514 insertStatus(struct dlstatus *dls, const struct stat *sbuf) |
504 dls->mode = 0; | 515 { |
505 if ((dls->flags & DL_IN_LIST) == 0) | 516 debug("inserting status"); |
506 { | 517 dls->inode = sbuf->st_ino; |
507 dls->next = stqueue; | 518 dls->device = sbuf->st_dev; |
508 stqueue = dls; | 519 dls->refs = 0; |
509 dls->flags |= DL_IN_LIST; | 520 dls->mode = 0; |
510 } | 521 if ((dls->flags & DL_IN_LIST) == 0) { |
511 } | 522 dls->next = stqueue; |
512 | 523 stqueue = dls; |
513 static struct dlstatus *allocStatus() | 524 dls->flags |= DL_IN_LIST; |
514 { | 525 } |
515 struct dlstatus *dls; | 526 } |
527 | |
528 static struct dlstatus * | |
529 allocStatus() | |
530 { | |
531 struct dlstatus *dls; | |
516 #ifdef REUSE_STATUS | 532 #ifdef REUSE_STATUS |
517 dls = stqueue; | 533 dls = stqueue; |
518 while (dls && dls->module) | 534 while (dls && dls->module) |
519 dls = dls->next; | 535 dls = dls->next; |
520 if (!dls) | 536 if (!dls) |
521 #endif | 537 #endif |
522 dls = SDL_calloc(sizeof(*dls),1); | 538 dls = SDL_calloc(sizeof(*dls), 1); |
523 return dls; | 539 return dls; |
524 } | 540 } |
525 | 541 |
526 static int promoteLocalToGlobal(struct dlstatus *dls) | 542 static int |
527 { | 543 promoteLocalToGlobal(struct dlstatus *dls) |
528 static int (*p) (NSModule module) = 0; | 544 { |
529 debug("promoting"); | 545 static int (*p) (NSModule module) = 0; |
530 if (!p) | 546 debug("promoting"); |
531 _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (void **)&p); | 547 if (!p) |
532 return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module)); | 548 _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (void **) &p); |
533 } | 549 return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module)); |
534 | 550 } |
535 static void *reference(struct dlstatus *dls, int mode) | 551 |
536 { | 552 static void * |
537 if (dls) | 553 reference(struct dlstatus *dls, int mode) |
538 { | 554 { |
539 if (dls->module == MAGIC_DYLIB_MOD && isFlagSet(mode, RTLD_LOCAL)) | 555 if (dls) { |
540 { | 556 if (dls->module == MAGIC_DYLIB_MOD && isFlagSet(mode, RTLD_LOCAL)) { |
541 warning("trying to open a .dylib with RTLD_LOCAL"); | 557 warning("trying to open a .dylib with RTLD_LOCAL"); |
542 error("unable to open a .dylib with RTLD_LOCAL"); | 558 error("unable to open a .dylib with RTLD_LOCAL"); |
543 return NULL; | 559 return NULL; |
544 } | 560 } |
545 if (isFlagSet(mode, RTLD_GLOBAL) && | 561 if (isFlagSet(mode, RTLD_GLOBAL) && !isFlagSet(dls->mode, RTLD_GLOBAL) |
546 !isFlagSet(dls->mode, RTLD_GLOBAL) && !promoteLocalToGlobal(dls)) | 562 && !promoteLocalToGlobal(dls)) { |
547 { | 563 error("unable to promote local module to global"); |
548 error("unable to promote local module to global"); | 564 return NULL; |
549 return NULL; | 565 } |
550 } | 566 dls->mode |= mode; |
551 dls->mode |= mode; | 567 dls->refs++; |
552 dls->refs++; | 568 } else |
553 } | 569 debug("reference called with NULL argument"); |
554 else | 570 |
555 debug("reference called with NULL argument"); | 571 return dls; |
556 | 572 } |
557 return dls; | 573 |
558 } | 574 static const struct mach_header * |
559 | 575 my_find_image(const char *name) |
560 static const struct mach_header *my_find_image(const char *name) | 576 { |
561 { | 577 const struct mach_header *mh = 0; |
562 const struct mach_header *mh = 0; | 578 const char *id = NULL; |
563 const char *id = NULL; | 579 int i = _dyld_image_count(); |
564 int i = _dyld_image_count(); | 580 int j; |
565 int j; | 581 mh = (struct mach_header *) |
566 mh = (struct mach_header *) | 582 dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED | |
567 dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED | | 583 NSADDIMAGE_OPTION_RETURN_ON_ERROR); |
568 NSADDIMAGE_OPTION_RETURN_ON_ERROR); | 584 if (!mh) { |
569 if (!mh) | 585 for (j = 0; j < i; j++) { |
570 { | 586 id = _dyld_get_image_name(j); |
571 for (j = 0; j < i; j++) | 587 if (!SDL_strcmp(id, name)) { |
572 { | 588 mh = _dyld_get_image_header(j); |
573 id = _dyld_get_image_name(j); | 589 break; |
574 if (!SDL_strcmp(id, name)) | 590 } |
575 { | 591 } |
576 mh = _dyld_get_image_header(j); | 592 } |
577 break; | 593 return mh; |
578 } | |
579 } | |
580 } | |
581 return mh; | |
582 } | 594 } |
583 | 595 |
584 /* | 596 /* |
585 * dyld adds libraries by first adding the directly dependant libraries in link order, and | 597 * dyld adds libraries by first adding the directly dependant libraries in link order, and |
586 * then adding the dependencies for those libraries, so we should do the same... but we don't | 598 * then adding the dependencies for those libraries, so we should do the same... but we don't |
587 * bother adding the extra dependencies, if the symbols are neither in the loaded image nor | 599 * bother adding the extra dependencies, if the symbols are neither in the loaded image nor |
588 * any of it's direct dependencies, then it probably isn't there. | 600 * any of it's direct dependencies, then it probably isn't there. |
589 */ | 601 */ |
590 static NSSymbol search_linked_libs(const struct mach_header * mh, const char *symbol) | 602 static NSSymbol |
591 { | 603 search_linked_libs(const struct mach_header *mh, const char *symbol) |
592 unsigned int n; | 604 { |
593 struct load_command *lc = 0; | 605 unsigned int n; |
594 struct mach_header *wh; | 606 struct load_command *lc = 0; |
595 NSSymbol nssym = 0; | 607 struct mach_header *wh; |
596 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) | 608 NSSymbol nssym = 0; |
597 { | 609 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage |
598 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); | 610 && dyld_NSLookupSymbolInImage) { |
599 for (n = 0; n < mh->ncmds; n++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | 611 lc = (struct load_command *) ((char *) mh + |
600 { | 612 sizeof(struct mach_header)); |
601 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) | 613 for (n = 0; n < mh->ncmds; |
602 { | 614 n++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) { |
603 if ((wh = (struct mach_header *) | 615 if ((LC_LOAD_DYLIB == lc->cmd) |
604 my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset + | 616 || (LC_LOAD_WEAK_DYLIB == lc->cmd)) { |
605 (char *)lc)))) | 617 if ((wh = (struct mach_header *) |
606 { | 618 my_find_image((char |
607 if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol)) | 619 *) (((struct dylib_command *) lc)-> |
608 { | 620 dylib.name.offset + (char *) lc)))) { |
609 nssym = dyld_NSLookupSymbolInImage(wh, | 621 if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol)) { |
610 symbol, | 622 nssym = dyld_NSLookupSymbolInImage(wh, |
611 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | | 623 symbol, |
612 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); | 624 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
613 break; | 625 | |
614 } | 626 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); |
615 } | 627 break; |
616 } | 628 } |
617 } | 629 } |
618 if ((!nssym) && NSIsSymbolNameDefined(symbol)) | 630 } |
619 { | 631 } |
620 /* I've never seen this debug message...*/ | 632 if ((!nssym) && NSIsSymbolNameDefined(symbol)) { |
621 debug("Symbol \"%s\" is defined but was not found", symbol); | 633 /* I've never seen this debug message... */ |
622 } | 634 debug("Symbol \"%s\" is defined but was not found", symbol); |
623 } | 635 } |
624 return nssym; | 636 } |
637 return nssym; | |
625 } | 638 } |
626 | 639 |
627 /* Up to the caller to SDL_free() returned string */ | 640 /* Up to the caller to SDL_free() returned string */ |
628 static inline char *dyld_error_str() | 641 static inline char * |
629 { | 642 dyld_error_str() |
630 NSLinkEditErrors dylder; | 643 { |
631 int dylderno; | 644 NSLinkEditErrors dylder; |
632 const char *dylderrstr; | 645 int dylderno; |
633 const char *dyldfile; | 646 const char *dylderrstr; |
634 char* retStr = NULL; | 647 const char *dyldfile; |
635 NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr); | 648 char *retStr = NULL; |
636 if (dylderrstr && *dylderrstr) | 649 NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr); |
637 { | 650 if (dylderrstr && *dylderrstr) { |
638 retStr = SDL_strdup(dylderrstr); | 651 retStr = SDL_strdup(dylderrstr); |
639 } | 652 } |
640 return retStr; | 653 return retStr; |
641 } | 654 } |
642 | 655 |
643 static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError) | 656 static void * |
644 { | 657 dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError) |
645 NSSymbol nssym = 0; | 658 { |
646 #ifdef __GCC__ | 659 NSSymbol nssym = 0; |
647 void *caller = __builtin_return_address(1); /* Be *very* careful about inlining */ | 660 #ifdef __GCC__ |
661 void *caller = __builtin_return_address(1); /* Be *very* careful about inlining */ | |
648 #else | 662 #else |
649 void *caller = NULL; | 663 void *caller = NULL; |
650 #endif | 664 #endif |
651 const struct mach_header *caller_mh = 0; | 665 const struct mach_header *caller_mh = 0; |
652 char *savedErrorStr = NULL; | 666 char *savedErrorStr = NULL; |
653 resetdlerror(); | 667 resetdlerror(); |
654 #ifndef RTLD_SELF | 668 #ifndef RTLD_SELF |
655 #define RTLD_SELF ((void *) -3) | 669 #define RTLD_SELF ((void *) -3) |
656 #endif | 670 #endif |
657 if (NULL == dls) | 671 if (NULL == dls) |
658 dls = RTLD_SELF; | 672 dls = RTLD_SELF; |
659 if ((RTLD_NEXT == dls) || (RTLD_SELF == dls)) | 673 if ((RTLD_NEXT == dls) || (RTLD_SELF == dls)) { |
660 { | 674 if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage |
661 if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage && caller) | 675 && caller) { |
662 { | 676 caller_mh = image_for_address(caller); |
663 caller_mh = image_for_address(caller); | 677 if (RTLD_SELF == dls) { |
664 if (RTLD_SELF == dls) | 678 /* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE |
665 { | 679 * But it appears to work anyway, and looking at the code in dyld_libfuncs.c |
666 /* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE | 680 * this is acceptable. |
667 * But it appears to work anyway, and looking at the code in dyld_libfuncs.c | 681 */ |
668 * this is acceptable. | 682 if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol)) { |
669 */ | 683 nssym = dyld_NSLookupSymbolInImage(caller_mh, |
670 if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol)) | 684 symbol, |
671 { | 685 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
672 nssym = dyld_NSLookupSymbolInImage(caller_mh, | 686 | |
673 symbol, | 687 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); |
674 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | | 688 } |
675 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); | 689 } |
676 } | 690 if (!nssym) { |
677 } | 691 if (RTLD_SELF == dls) |
678 if (!nssym) | 692 savedErrorStr = dyld_error_str(); |
679 { | 693 nssym = search_linked_libs(caller_mh, symbol); |
680 if (RTLD_SELF == dls) | 694 } |
681 savedErrorStr = dyld_error_str(); | 695 } else { |
682 nssym = search_linked_libs(caller_mh, symbol); | 696 if (canSetError) |
683 } | 697 error("RTLD_SELF and RTLD_NEXT are not supported"); |
684 } | 698 return NULL; |
685 else | 699 } |
686 { | 700 } |
687 if (canSetError) | 701 if (!nssym) { |
688 error("RTLD_SELF and RTLD_NEXT are not supported"); | 702 |
689 return NULL; | 703 if (RTLD_DEFAULT == dls) { |
690 } | 704 dls = &mainStatus; |
691 } | 705 } |
692 if (!nssym) | 706 if (!isValidStatus(dls)) |
693 { | 707 return NULL; |
694 | 708 |
695 if (RTLD_DEFAULT == dls) | 709 if (dls->module != MAGIC_DYLIB_MOD) { |
696 { | 710 nssym = NSLookupSymbolInModule(dls->module, symbol); |
697 dls = &mainStatus; | 711 if (!nssym && NSIsSymbolNameDefined(symbol)) { |
698 } | 712 debug("Searching dependencies"); |
699 if (!isValidStatus(dls)) | 713 savedErrorStr = dyld_error_str(); |
700 return NULL; | 714 nssym = |
701 | 715 search_linked_libs(get_mach_header_from_NSModule |
702 if (dls->module != MAGIC_DYLIB_MOD) | 716 (dls->module), symbol); |
703 { | 717 } |
704 nssym = NSLookupSymbolInModule(dls->module, symbol); | 718 } else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage |
705 if (!nssym && NSIsSymbolNameDefined(symbol)) | 719 && dyld_NSLookupSymbolInImage) { |
706 { | 720 if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol)) { |
707 debug("Searching dependencies"); | 721 nssym = dyld_NSLookupSymbolInImage(dls->lib, |
708 savedErrorStr = dyld_error_str(); | 722 symbol, |
709 nssym = search_linked_libs(get_mach_header_from_NSModule(dls->module), symbol); | 723 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
710 } | 724 | |
711 } | 725 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); |
712 else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) | 726 } else if (NSIsSymbolNameDefined(symbol)) { |
713 { | 727 debug("Searching dependencies"); |
714 if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol)) | 728 savedErrorStr = dyld_error_str(); |
715 { | 729 nssym = search_linked_libs(dls->lib, symbol); |
716 nssym = dyld_NSLookupSymbolInImage(dls->lib, | 730 } |
717 symbol, | 731 } else if (dls->module == MAGIC_DYLIB_MOD) { |
718 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | | 732 /* Global context, use NSLookupAndBindSymbol */ |
719 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); | 733 if (NSIsSymbolNameDefined(symbol)) { |
720 } | 734 /* There doesn't seem to be a return on error option for this call??? |
721 else if (NSIsSymbolNameDefined(symbol)) | 735 this is potentially broken, if binding fails, it will improperly |
722 { | 736 exit the application. */ |
723 debug("Searching dependencies"); | 737 nssym = NSLookupAndBindSymbol(symbol); |
724 savedErrorStr = dyld_error_str(); | 738 } else { |
725 nssym = search_linked_libs(dls->lib, symbol); | 739 if (savedErrorStr) |
726 } | 740 SDL_free(savedErrorStr); |
727 } | 741 savedErrorStr = SDL_malloc(256); |
728 else if (dls->module == MAGIC_DYLIB_MOD) | 742 SDL_snprintf(savedErrorStr, 256, |
729 { | 743 "Symbol \"%s\" not in global context", symbol); |
730 /* Global context, use NSLookupAndBindSymbol */ | 744 } |
731 if (NSIsSymbolNameDefined(symbol)) | 745 } |
732 { | 746 } |
733 /* There doesn't seem to be a return on error option for this call??? | 747 /* Error reporting */ |
734 this is potentially broken, if binding fails, it will improperly | 748 if (!nssym) { |
735 exit the application. */ | 749 if (!savedErrorStr || !SDL_strlen(savedErrorStr)) { |
736 nssym = NSLookupAndBindSymbol(symbol); | 750 if (savedErrorStr) |
737 } | 751 SDL_free(savedErrorStr); |
738 else | 752 savedErrorStr = SDL_malloc(256); |
739 { | 753 SDL_snprintf(savedErrorStr, 256, "Symbol \"%s\" not found", |
740 if (savedErrorStr) | 754 symbol); |
741 SDL_free(savedErrorStr); | 755 } |
742 savedErrorStr = SDL_malloc(256); | 756 if (canSetError) { |
743 SDL_snprintf(savedErrorStr, 256, "Symbol \"%s\" not in global context",symbol); | 757 error(savedErrorStr); |
744 } | 758 } else { |
745 } | 759 debug(savedErrorStr); |
746 } | 760 } |
747 /* Error reporting */ | 761 if (savedErrorStr) |
748 if (!nssym) | 762 SDL_free(savedErrorStr); |
749 { | 763 return NULL; |
750 if (!savedErrorStr || !SDL_strlen(savedErrorStr)) | 764 } |
751 { | 765 return NSAddressOfSymbol(nssym); |
752 if (savedErrorStr) | 766 } |
753 SDL_free(savedErrorStr); | 767 |
754 savedErrorStr = SDL_malloc(256); | 768 static struct dlstatus * |
755 SDL_snprintf(savedErrorStr, 256,"Symbol \"%s\" not found",symbol); | 769 loadModule(const char *path, const struct stat *sbuf, int mode) |
756 } | 770 { |
757 if (canSetError) | 771 NSObjectFileImage ofi = 0; |
758 { | 772 NSObjectFileImageReturnCode ofirc; |
759 error(savedErrorStr); | 773 struct dlstatus *dls; |
760 } | 774 NSLinkEditErrors ler; |
761 else | 775 int lerno; |
762 { | 776 const char *errstr; |
763 debug(savedErrorStr); | 777 const char *file; |
764 } | 778 void (*init) (void); |
765 if (savedErrorStr) | 779 |
766 SDL_free(savedErrorStr); | 780 ofirc = NSCreateObjectFileImageFromFile(path, &ofi); |
767 return NULL; | 781 switch (ofirc) { |
768 } | 782 case NSObjectFileImageSuccess: |
769 return NSAddressOfSymbol(nssym); | 783 break; |
770 } | 784 case NSObjectFileImageInappropriateFile: |
771 | 785 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage |
772 static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode) | 786 && dyld_NSLookupSymbolInImage) { |
773 { | 787 if (isFlagSet(mode, RTLD_LOCAL)) { |
774 NSObjectFileImage ofi = 0; | 788 warning("trying to open a .dylib with RTLD_LOCAL"); |
775 NSObjectFileImageReturnCode ofirc; | 789 error("unable to open this file with RTLD_LOCAL"); |
776 struct dlstatus *dls; | 790 return NULL; |
777 NSLinkEditErrors ler; | 791 } |
778 int lerno; | 792 } else { |
779 const char *errstr; | 793 error("opening this file is unsupported on this system"); |
780 const char *file; | 794 return NULL; |
781 void (*init) (void); | 795 } |
782 | 796 break; |
783 ofirc = NSCreateObjectFileImageFromFile(path, &ofi); | 797 case NSObjectFileImageFailure: |
784 switch (ofirc) | 798 error("object file setup failure"); |
785 { | 799 return NULL; |
786 case NSObjectFileImageSuccess: | 800 case NSObjectFileImageArch: |
787 break; | 801 error("no object for this architecture"); |
788 case NSObjectFileImageInappropriateFile: | 802 return NULL; |
789 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) | 803 case NSObjectFileImageFormat: |
790 { | 804 error("bad object file format"); |
791 if (isFlagSet(mode, RTLD_LOCAL)) | 805 return NULL; |
792 { | 806 case NSObjectFileImageAccess: |
793 warning("trying to open a .dylib with RTLD_LOCAL"); | 807 error("can't read object file"); |
794 error("unable to open this file with RTLD_LOCAL"); | 808 return NULL; |
795 return NULL; | 809 default: |
796 } | 810 error("unknown error from NSCreateObjectFileImageFromFile()"); |
797 } | 811 return NULL; |
798 else | 812 } |
799 { | 813 dls = lookupStatus(sbuf); |
800 error("opening this file is unsupported on this system"); | 814 if (!dls) { |
801 return NULL; | 815 dls = allocStatus(); |
802 } | 816 } |
803 break; | 817 if (!dls) { |
804 case NSObjectFileImageFailure: | 818 error("unable to allocate memory"); |
805 error("object file setup failure"); | 819 return NULL; |
806 return NULL; | 820 } |
807 case NSObjectFileImageArch: | 821 // dls->lib = 0; |
808 error("no object for this architecture"); | 822 if (ofirc == NSObjectFileImageInappropriateFile) { |
809 return NULL; | 823 if ((dls->lib = |
810 case NSObjectFileImageFormat: | 824 dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR))) { |
811 error("bad object file format"); | 825 debug("Dynamic lib loaded at %ld", dls->lib); |
812 return NULL; | 826 ofi = MAGIC_DYLIB_OFI; |
813 case NSObjectFileImageAccess: | 827 dls->module = MAGIC_DYLIB_MOD; |
814 error("can't read object file"); | 828 ofirc = NSObjectFileImageSuccess; |
815 return NULL; | 829 /* Although it is possible with a bit of work to modify this so it works and |
816 default: | 830 functions with RTLD_NOW, I don't deem it necessary at the moment */ |
817 error("unknown error from NSCreateObjectFileImageFromFile()"); | 831 } |
818 return NULL; | 832 if (!(dls->module)) { |
819 } | 833 NSLinkEditError(&ler, &lerno, &file, &errstr); |
820 dls = lookupStatus(sbuf); | 834 if (!errstr || (!SDL_strlen(errstr))) |
821 if (!dls) | 835 error("Can't open this file type"); |
822 { | 836 else |
823 dls = allocStatus(); | 837 error(errstr); |
824 } | 838 if ((dls->flags & DL_IN_LIST) == 0) { |
825 if (!dls) | 839 SDL_free(dls); |
826 { | 840 } |
827 error("unable to allocate memory"); | 841 return NULL; |
828 return NULL; | 842 } |
829 } | 843 } else { |
830 // dls->lib = 0; | 844 dls->module = NSLinkModule(ofi, path, |
831 if (ofirc == NSObjectFileImageInappropriateFile) | 845 NSLINKMODULE_OPTION_RETURN_ON_ERROR | |
832 { | 846 NSLINKMODULE_OPTION_PRIVATE | |
833 if ((dls->lib = dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR))) | 847 (isFlagSet(mode, RTLD_NOW) ? |
834 { | 848 NSLINKMODULE_OPTION_BINDNOW : 0)); |
835 debug("Dynamic lib loaded at %ld", dls->lib); | 849 NSDestroyObjectFileImage(ofi); |
836 ofi = MAGIC_DYLIB_OFI; | 850 if (dls->module) { |
837 dls->module = MAGIC_DYLIB_MOD; | 851 dls->lib = get_mach_header_from_NSModule(dls->module); |
838 ofirc = NSObjectFileImageSuccess; | 852 } |
839 /* Although it is possible with a bit of work to modify this so it works and | 853 } |
840 functions with RTLD_NOW, I don't deem it necessary at the moment */ | 854 if (!dls->module) { |
841 } | 855 NSLinkEditError(&ler, &lerno, &file, &errstr); |
842 if (!(dls->module)) | 856 if ((dls->flags & DL_IN_LIST) == 0) { |
843 { | 857 SDL_free(dls); |
844 NSLinkEditError(&ler, &lerno, &file, &errstr); | 858 } |
845 if (!errstr || (!SDL_strlen(errstr))) | 859 error(errstr); |
846 error("Can't open this file type"); | 860 return NULL; |
847 else | 861 } |
848 error(errstr); | 862 |
849 if ((dls->flags & DL_IN_LIST) == 0) | 863 insertStatus(dls, sbuf); |
850 { | 864 dls = reference(dls, mode); |
851 SDL_free(dls); | 865 if ((init = dlsymIntern(dls, "__init", 0))) { |
852 } | 866 debug("calling _init()"); |
853 return NULL; | 867 init(); |
854 } | 868 } |
855 } | 869 return dls; |
856 else | 870 } |
857 { | 871 |
858 dls->module = NSLinkModule(ofi, path, | 872 inline static void |
859 NSLINKMODULE_OPTION_RETURN_ON_ERROR | | 873 dlcompat_init_check(void) |
860 NSLINKMODULE_OPTION_PRIVATE | | 874 { |
861 (isFlagSet(mode, RTLD_NOW) ? NSLINKMODULE_OPTION_BINDNOW : 0)); | 875 static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER; |
862 NSDestroyObjectFileImage(ofi); | 876 static int init_done = 0; |
863 if (dls->module) | 877 |
864 { | 878 pthread_mutex_lock(&l); |
865 dls->lib = get_mach_header_from_NSModule(dls->module); | 879 if (!init_done) { |
866 } | 880 dlcompat_init_func(); |
867 } | 881 init_done = 1; |
868 if (!dls->module) | 882 } |
869 { | 883 pthread_mutex_unlock(&l); |
870 NSLinkEditError(&ler, &lerno, &file, &errstr); | 884 } |
871 if ((dls->flags & DL_IN_LIST) == 0) | 885 |
872 { | 886 static void |
873 SDL_free(dls); | 887 dlcompat_init_func(void) |
874 } | 888 { |
875 error(errstr); | 889 _dyld_func_lookup("__dyld_NSAddImage", (void **) &dyld_NSAddImage); |
876 return NULL; | 890 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", |
877 } | 891 (void **) &dyld_NSIsSymbolNameDefinedInImage); |
878 | 892 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", |
879 insertStatus(dls, sbuf); | 893 (void **) &dyld_NSLookupSymbolInImage); |
880 dls = reference(dls, mode); | 894 if (pthread_mutex_init(&dlcompat_mutex, NULL)) |
881 if ((init = dlsymIntern(dls, "__init", 0))) | 895 exit(1); |
882 { | 896 if (pthread_key_create(&dlerror_key, &dlerrorfree)) |
883 debug("calling _init()"); | 897 exit(1); |
884 init(); | 898 } |
885 } | 899 |
886 return dls; | 900 static void |
887 } | 901 resetdlerror() |
888 | 902 { |
889 inline static void dlcompat_init_check(void) | 903 struct dlthread *tss; |
890 { | 904 tss = pthread_getspecific(dlerror_key); |
891 static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER; | 905 tss->errset = 0; |
892 static int init_done = 0; | 906 } |
893 | 907 |
894 pthread_mutex_lock(&l); | 908 static void |
895 if (!init_done) { | 909 dlerrorfree(void *data) |
896 dlcompat_init_func(); | 910 { |
897 init_done = 1; | 911 SDL_free(data); |
898 } | |
899 pthread_mutex_unlock(&l); | |
900 } | |
901 | |
902 static void dlcompat_init_func(void) | |
903 { | |
904 _dyld_func_lookup("__dyld_NSAddImage", (void **)&dyld_NSAddImage); | |
905 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", | |
906 (void **)&dyld_NSIsSymbolNameDefinedInImage); | |
907 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void **)&dyld_NSLookupSymbolInImage); | |
908 if (pthread_mutex_init(&dlcompat_mutex, NULL)) | |
909 exit(1); | |
910 if (pthread_key_create(&dlerror_key, &dlerrorfree)) | |
911 exit(1); | |
912 } | |
913 | |
914 static void resetdlerror() | |
915 { | |
916 struct dlthread *tss; | |
917 tss = pthread_getspecific(dlerror_key); | |
918 tss->errset = 0; | |
919 } | |
920 | |
921 static void dlerrorfree(void *data) | |
922 { | |
923 SDL_free(data); | |
924 } | 912 } |
925 | 913 |
926 /* We kind of want a recursive lock here, but meet a little trouble | 914 /* We kind of want a recursive lock here, but meet a little trouble |
927 * because they are not available pre OS X 10.2, so we fake it | 915 * because they are not available pre OS X 10.2, so we fake it |
928 * using thread specific storage to keep a lock count | 916 * using thread specific storage to keep a lock count |
929 */ | 917 */ |
930 static inline void dolock(void) | 918 static inline void |
931 { | 919 dolock(void) |
932 int err = 0; | 920 { |
933 struct dlthread *tss; | 921 int err = 0; |
934 dlcompat_init_check(); | 922 struct dlthread *tss; |
935 tss = pthread_getspecific(dlerror_key); | 923 dlcompat_init_check(); |
936 if (!tss) | 924 tss = pthread_getspecific(dlerror_key); |
937 { | 925 if (!tss) { |
938 tss = SDL_malloc(sizeof(struct dlthread)); | 926 tss = SDL_malloc(sizeof(struct dlthread)); |
939 tss->lockcnt = 0; | 927 tss->lockcnt = 0; |
940 tss->errset = 0; | 928 tss->errset = 0; |
941 if (pthread_setspecific(dlerror_key, tss)) | 929 if (pthread_setspecific(dlerror_key, tss)) { |
942 { | 930 fprintf(stderr, "dlcompat: pthread_setspecific failed\n"); |
943 fprintf(stderr,"dlcompat: pthread_setspecific failed\n"); | 931 exit(1); |
944 exit(1); | 932 } |
945 } | 933 } |
946 } | 934 if (!tss->lockcnt) |
947 if (!tss->lockcnt) | 935 err = pthread_mutex_lock(&dlcompat_mutex); |
948 err = pthread_mutex_lock(&dlcompat_mutex); | 936 tss->lockcnt = tss->lockcnt + 1; |
949 tss->lockcnt = tss->lockcnt +1; | 937 if (err) |
950 if (err) | 938 exit(err); |
951 exit(err); | 939 } |
952 } | 940 |
953 | 941 static inline void |
954 static inline void dounlock(void) | 942 dounlock(void) |
955 { | 943 { |
956 int err = 0; | 944 int err = 0; |
957 struct dlthread *tss; | 945 struct dlthread *tss; |
958 tss = pthread_getspecific(dlerror_key); | 946 tss = pthread_getspecific(dlerror_key); |
959 tss->lockcnt = tss->lockcnt -1; | 947 tss->lockcnt = tss->lockcnt - 1; |
960 if (!tss->lockcnt) | 948 if (!tss->lockcnt) |
961 err = pthread_mutex_unlock(&dlcompat_mutex); | 949 err = pthread_mutex_unlock(&dlcompat_mutex); |
962 if (err) | 950 if (err) |
963 exit(err); | 951 exit(err); |
964 } | 952 } |
965 | 953 |
966 static void *SDL_OSX_dlopen(const char *path, int mode) | 954 static void * |
967 { | 955 SDL_OSX_dlopen(const char *path, int mode) |
968 const struct stat *sbuf; | 956 { |
969 struct dlstatus *dls; | 957 const struct stat *sbuf; |
970 const char *fullPath; | 958 struct dlstatus *dls; |
971 | 959 const char *fullPath; |
972 dolock(); | 960 |
973 resetdlerror(); | 961 dolock(); |
974 if (!path) | 962 resetdlerror(); |
975 { | 963 if (!path) { |
976 dls = &mainStatus; | 964 dls = &mainStatus; |
977 goto dlopenok; | 965 goto dlopenok; |
978 } | 966 } |
979 if (!(sbuf = findFile(path, &fullPath))) | 967 if (!(sbuf = findFile(path, &fullPath))) { |
980 { | 968 error("file \"%s\" not found", path); |
981 error("file \"%s\" not found", path); | 969 goto dlopenerror; |
982 goto dlopenerror; | 970 } |
983 } | 971 /* Now checks that it hasn't been closed already */ |
984 /* Now checks that it hasn't been closed already */ | 972 if ((dls = lookupStatus(sbuf)) && (dls->refs > 0)) { |
985 if ((dls = lookupStatus(sbuf)) && (dls->refs > 0)) | 973 /* debug("status found"); */ |
986 { | 974 dls = reference(dls, mode); |
987 /* debug("status found"); */ | 975 goto dlopenok; |
988 dls = reference(dls, mode); | 976 } |
989 goto dlopenok; | |
990 } | |
991 #ifdef RTLD_NOLOAD | 977 #ifdef RTLD_NOLOAD |
992 if (isFlagSet(mode, RTLD_NOLOAD)) | 978 if (isFlagSet(mode, RTLD_NOLOAD)) { |
993 { | 979 error("no existing handle and RTLD_NOLOAD specified"); |
994 error("no existing handle and RTLD_NOLOAD specified"); | 980 goto dlopenerror; |
995 goto dlopenerror; | 981 } |
996 } | 982 #endif |
997 #endif | 983 if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW)) { |
998 if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW)) | 984 error("how can I load something both RTLD_LAZY and RTLD_NOW?"); |
999 { | 985 goto dlopenerror; |
1000 error("how can I load something both RTLD_LAZY and RTLD_NOW?"); | 986 } |
1001 goto dlopenerror; | 987 dls = loadModule(fullPath, sbuf, mode); |
1002 } | 988 |
1003 dls = loadModule(fullPath, sbuf, mode); | |
1004 | |
1005 dlopenok: | 989 dlopenok: |
1006 dounlock(); | 990 dounlock(); |
1007 return (void *)dls; | 991 return (void *) dls; |
1008 dlopenerror: | 992 dlopenerror: |
1009 dounlock(); | 993 dounlock(); |
1010 return NULL; | 994 return NULL; |
1011 } | 995 } |
1012 | 996 |
1013 #if !FINK_BUILD | 997 #if !FINK_BUILD |
1014 static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol) | 998 static void * |
1015 { | 999 SDL_OSX_dlsym(void *dl_restrict handle, const char *dl_restrict symbol) |
1016 int sym_len = SDL_strlen(symbol); | 1000 { |
1017 void *value = NULL; | 1001 int sym_len = SDL_strlen(symbol); |
1018 char *malloc_sym = NULL; | 1002 void *value = NULL; |
1019 dolock(); | 1003 char *malloc_sym = NULL; |
1020 malloc_sym = SDL_malloc(sym_len + 2); | 1004 dolock(); |
1021 if (malloc_sym) | 1005 malloc_sym = SDL_malloc(sym_len + 2); |
1022 { | 1006 if (malloc_sym) { |
1023 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); | 1007 SDL_snprintf(malloc_sym, sym_len + 2, "_%s", symbol); |
1024 value = dlsymIntern(handle, malloc_sym, 1); | 1008 value = dlsymIntern(handle, malloc_sym, 1); |
1025 SDL_free(malloc_sym); | 1009 SDL_free(malloc_sym); |
1026 } | 1010 } else { |
1027 else | 1011 error("Unable to allocate memory"); |
1028 { | 1012 goto dlsymerror; |
1029 error("Unable to allocate memory"); | 1013 } |
1030 goto dlsymerror; | 1014 dounlock(); |
1031 } | 1015 return value; |
1032 dounlock(); | |
1033 return value; | |
1034 dlsymerror: | 1016 dlsymerror: |
1035 dounlock(); | 1017 dounlock(); |
1036 return NULL; | 1018 return NULL; |
1037 } | 1019 } |
1038 #endif | 1020 #endif |
1039 | 1021 |
1040 #if FINK_BUILD | 1022 #if FINK_BUILD |
1041 | 1023 |
1042 static void *dlsym_prepend_underscore(void *handle, const char *symbol) | 1024 static void * |
1043 { | 1025 dlsym_prepend_underscore(void *handle, const char *symbol) |
1044 void *answer; | 1026 { |
1045 dolock(); | 1027 void *answer; |
1046 answer = dlsym_prepend_underscore_intern(handle, symbol); | 1028 dolock(); |
1047 dounlock(); | 1029 answer = dlsym_prepend_underscore_intern(handle, symbol); |
1048 return answer; | 1030 dounlock(); |
1049 } | 1031 return answer; |
1050 | 1032 } |
1051 static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol) | 1033 |
1034 static void * | |
1035 dlsym_prepend_underscore_intern(void *handle, const char *symbol) | |
1052 { | 1036 { |
1053 /* | 1037 /* |
1054 * A quick and easy way for porting packages which call dlsym(handle,"sym") | 1038 * A quick and easy way for porting packages which call dlsym(handle,"sym") |
1055 * If the porter adds -Ddlsym=dlsym_prepend_underscore to the CFLAGS then | 1039 * If the porter adds -Ddlsym=dlsym_prepend_underscore to the CFLAGS then |
1056 * this function will be called, and will add the required underscore. | 1040 * this function will be called, and will add the required underscore. |
1057 * | 1041 * |
1058 * Note that I haven't figured out yet which should be "standard", prepend | 1042 * Note that I haven't figured out yet which should be "standard", prepend |
1059 * the underscore always, or not at all. These global functions need to go away | 1043 * the underscore always, or not at all. These global functions need to go away |
1060 * for opendarwin. | 1044 * for opendarwin. |
1061 */ | 1045 */ |
1062 int sym_len = SDL_strlen(symbol); | 1046 int sym_len = SDL_strlen(symbol); |
1063 void *value = NULL; | 1047 void *value = NULL; |
1064 char *malloc_sym = NULL; | 1048 char *malloc_sym = NULL; |
1065 malloc_sym = SDL_malloc(sym_len + 2); | 1049 malloc_sym = SDL_malloc(sym_len + 2); |
1066 if (malloc_sym) | 1050 if (malloc_sym) { |
1067 { | 1051 SDL_snprintf(malloc_sym, sym_len + 2, "_%s", symbol); |
1068 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); | 1052 value = dlsymIntern(handle, malloc_sym, 1); |
1069 value = dlsymIntern(handle, malloc_sym, 1); | 1053 SDL_free(malloc_sym); |
1070 SDL_free(malloc_sym); | 1054 } else { |
1071 } | 1055 error("Unable to allocate memory"); |
1072 else | 1056 } |
1073 { | 1057 return value; |
1074 error("Unable to allocate memory"); | 1058 } |
1075 } | 1059 |
1076 return value; | 1060 static void * |
1077 } | 1061 dlsym_auto_underscore(void *handle, const char *symbol) |
1078 | 1062 { |
1079 static void *dlsym_auto_underscore(void *handle, const char *symbol) | 1063 void *answer; |
1080 { | 1064 dolock(); |
1081 void *answer; | 1065 answer = dlsym_auto_underscore_intern(handle, symbol); |
1082 dolock(); | 1066 dounlock(); |
1083 answer = dlsym_auto_underscore_intern(handle, symbol); | 1067 return answer; |
1084 dounlock(); | 1068 |
1085 return answer; | 1069 } |
1086 | 1070 static void * |
1087 } | 1071 dlsym_auto_underscore_intern(void *handle, const char *symbol) |
1088 static void *dlsym_auto_underscore_intern(void *handle, const char *symbol) | 1072 { |
1089 { | 1073 struct dlstatus *dls = handle; |
1090 struct dlstatus *dls = handle; | 1074 void *addr = 0; |
1091 void *addr = 0; | 1075 addr = dlsymIntern(dls, symbol, 0); |
1092 addr = dlsymIntern(dls, symbol, 0); | 1076 if (!addr) |
1093 if (!addr) | 1077 addr = dlsym_prepend_underscore_intern(handle, symbol); |
1094 addr = dlsym_prepend_underscore_intern(handle, symbol); | 1078 return addr; |
1095 return addr; | 1079 } |
1096 } | 1080 |
1097 | 1081 |
1098 | 1082 static void * |
1099 static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol) | 1083 SDL_OSX_dlsym(void *dl_restrict handle, const char *dl_restrict symbol) |
1100 { | 1084 { |
1101 struct dlstatus *dls = handle; | 1085 struct dlstatus *dls = handle; |
1102 void *addr = 0; | 1086 void *addr = 0; |
1103 dolock(); | 1087 dolock(); |
1104 addr = dlsymIntern(dls, symbol, 1); | 1088 addr = dlsymIntern(dls, symbol, 1); |
1105 dounlock(); | 1089 dounlock(); |
1106 return addr; | 1090 return addr; |
1107 } | 1091 } |
1108 #endif | 1092 #endif |
1109 | 1093 |
1110 static int SDL_OSX_dlclose(void *handle) | 1094 static int |
1111 { | 1095 SDL_OSX_dlclose(void *handle) |
1112 struct dlstatus *dls = handle; | 1096 { |
1113 dolock(); | 1097 struct dlstatus *dls = handle; |
1114 resetdlerror(); | 1098 dolock(); |
1115 if (!isValidStatus(dls)) | 1099 resetdlerror(); |
1116 { | 1100 if (!isValidStatus(dls)) { |
1117 goto dlcloseerror; | 1101 goto dlcloseerror; |
1118 } | 1102 } |
1119 if (dls->module == MAGIC_DYLIB_MOD) | 1103 if (dls->module == MAGIC_DYLIB_MOD) { |
1120 { | 1104 const char *name; |
1121 const char *name; | 1105 if (!dls->lib) { |
1122 if (!dls->lib) | 1106 name = "global context"; |
1123 { | 1107 } else { |
1124 name = "global context"; | 1108 name = get_lib_name(dls->lib); |
1125 } | 1109 } |
1126 else | 1110 warning("trying to close a .dylib!"); |
1127 { | 1111 error("Not closing \"%s\" - dynamic libraries cannot be closed", |
1128 name = get_lib_name(dls->lib); | 1112 name); |
1129 } | 1113 goto dlcloseerror; |
1130 warning("trying to close a .dylib!"); | 1114 } |
1131 error("Not closing \"%s\" - dynamic libraries cannot be closed", name); | 1115 if (!dls->module) { |
1132 goto dlcloseerror; | 1116 error("module already closed"); |
1133 } | 1117 goto dlcloseerror; |
1134 if (!dls->module) | 1118 } |
1135 { | 1119 |
1136 error("module already closed"); | 1120 if (dls->refs == 1) { |
1137 goto dlcloseerror; | 1121 unsigned long options = 0; |
1138 } | 1122 void (*fini) (void); |
1139 | 1123 if ((fini = dlsymIntern(dls, "__fini", 0))) { |
1140 if (dls->refs == 1) | 1124 debug("calling _fini()"); |
1141 { | 1125 fini(); |
1142 unsigned long options = 0; | 1126 } |
1143 void (*fini) (void); | 1127 options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; |
1144 if ((fini = dlsymIntern(dls, "__fini", 0))) | |
1145 { | |
1146 debug("calling _fini()"); | |
1147 fini(); | |
1148 } | |
1149 options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; | |
1150 #ifdef RTLD_NODELETE | 1128 #ifdef RTLD_NODELETE |
1151 if (isFlagSet(dls->mode, RTLD_NODELETE)) | 1129 if (isFlagSet(dls->mode, RTLD_NODELETE)) |
1152 options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; | 1130 options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; |
1153 #endif | 1131 #endif |
1154 if (!NSUnLinkModule(dls->module, options)) | 1132 if (!NSUnLinkModule(dls->module, options)) { |
1155 { | 1133 error("unable to unlink module"); |
1156 error("unable to unlink module"); | 1134 goto dlcloseerror; |
1157 goto dlcloseerror; | 1135 } |
1158 } | 1136 dls->refs--; |
1159 dls->refs--; | 1137 dls->module = 0; |
1160 dls->module = 0; | 1138 /* Note: the dlstatus struct dls is neither removed from the list |
1161 /* Note: the dlstatus struct dls is neither removed from the list | 1139 * nor is the memory it occupies freed. This shouldn't pose a |
1162 * nor is the memory it occupies freed. This shouldn't pose a | 1140 * problem in mostly all cases, though. |
1163 * problem in mostly all cases, though. | 1141 */ |
1164 */ | 1142 } |
1165 } | 1143 dounlock(); |
1166 dounlock(); | 1144 return 0; |
1167 return 0; | |
1168 dlcloseerror: | 1145 dlcloseerror: |
1169 dounlock(); | 1146 dounlock(); |
1170 return 1; | 1147 return 1; |
1171 } | 1148 } |
1172 | 1149 |
1173 static const char *SDL_OSX_dlerror(void) | 1150 static const char * |
1174 { | 1151 SDL_OSX_dlerror(void) |
1175 struct dlthread *tss; | 1152 { |
1176 const char * err_str = NULL; | 1153 struct dlthread *tss; |
1177 dlcompat_init_check(); | 1154 const char *err_str = NULL; |
1178 tss = pthread_getspecific(dlerror_key); | 1155 dlcompat_init_check(); |
1179 if (tss != NULL && tss->errset != 0) { | 1156 tss = pthread_getspecific(dlerror_key); |
1180 tss->errset = 0; | 1157 if (tss != NULL && tss->errset != 0) { |
1181 err_str = tss->errstr; | 1158 tss->errset = 0; |
1182 } | 1159 err_str = tss->errstr; |
1183 return (err_str); | 1160 } |
1161 return (err_str); | |
1184 } | 1162 } |
1185 | 1163 |
1186 /* Given an address, return the mach_header for the image containing it | 1164 /* Given an address, return the mach_header for the image containing it |
1187 * or zero if the given address is not contained in any loaded images. | 1165 * or zero if the given address is not contained in any loaded images. |
1188 */ | 1166 */ |
1189 static const struct mach_header *image_for_address(const void *address) | 1167 static const struct mach_header * |
1190 { | 1168 image_for_address(const void *address) |
1191 unsigned long i; | 1169 { |
1192 unsigned long j; | 1170 unsigned long i; |
1193 unsigned long count = _dyld_image_count(); | 1171 unsigned long j; |
1194 const struct mach_header *mh = 0; | 1172 unsigned long count = _dyld_image_count(); |
1195 struct load_command *lc = 0; | 1173 const struct mach_header *mh = 0; |
1196 unsigned long addr = 0; | 1174 struct load_command *lc = 0; |
1197 for (i = 0; i < count; i++) | 1175 unsigned long addr = 0; |
1198 { | 1176 for (i = 0; i < count; i++) { |
1199 addr = (unsigned long)address - _dyld_get_image_vmaddr_slide(i); | 1177 addr = (unsigned long) address - _dyld_get_image_vmaddr_slide(i); |
1200 mh = _dyld_get_image_header(i); | 1178 mh = _dyld_get_image_header(i); |
1201 if (mh) | 1179 if (mh) { |
1202 { | 1180 lc = (struct load_command *) ((char *) mh + |
1203 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); | 1181 sizeof(struct mach_header)); |
1204 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | 1182 for (j = 0; j < mh->ncmds; |
1205 { | 1183 j++, lc = |
1206 if (LC_SEGMENT == lc->cmd && | 1184 (struct load_command *) ((char *) lc + lc->cmdsize)) { |
1207 addr >= ((struct segment_command *)lc)->vmaddr && | 1185 if (LC_SEGMENT == lc->cmd && |
1208 addr < | 1186 addr >= ((struct segment_command *) lc)->vmaddr && |
1209 ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) | 1187 addr < |
1210 { | 1188 ((struct segment_command *) lc)->vmaddr + |
1211 goto image_found; | 1189 ((struct segment_command *) lc)->vmsize) { |
1212 } | 1190 goto image_found; |
1213 } | 1191 } |
1214 } | 1192 } |
1215 mh = 0; | 1193 } |
1216 } | 1194 mh = 0; |
1195 } | |
1217 image_found: | 1196 image_found: |
1218 return mh; | 1197 return mh; |
1219 } | 1198 } |
1220 | 1199 |
1221 #if 0 /* unused */ | 1200 #if 0 /* unused */ |
1222 static int SDL_OSX_dladdr(const void * dl_restrict p, SDL_OSX_Dl_info * dl_restrict info) | 1201 static int |
1202 SDL_OSX_dladdr(const void *dl_restrict p, SDL_OSX_Dl_info * dl_restrict info) | |
1223 { | 1203 { |
1224 /* | 1204 /* |
1225 FIXME: USe the routine image_for_address. | 1205 FIXME: USe the routine image_for_address. |
1226 */ | 1206 */ |
1227 unsigned long i; | 1207 unsigned long i; |
1228 unsigned long j; | 1208 unsigned long j; |
1229 unsigned long count = _dyld_image_count(); | 1209 unsigned long count = _dyld_image_count(); |
1230 struct mach_header *mh = 0; | 1210 struct mach_header *mh = 0; |
1231 struct load_command *lc = 0; | 1211 struct load_command *lc = 0; |
1232 unsigned long addr = NULL; | 1212 unsigned long addr = NULL; |
1233 unsigned long table_off = (unsigned long)0; | 1213 unsigned long table_off = (unsigned long) 0; |
1234 int found = 0; | 1214 int found = 0; |
1235 if (!info) | 1215 if (!info) |
1236 return 0; | 1216 return 0; |
1237 dolock(); | 1217 dolock(); |
1238 resetdlerror(); | 1218 resetdlerror(); |
1239 info->dli_fname = 0; | 1219 info->dli_fname = 0; |
1240 info->dli_fbase = 0; | 1220 info->dli_fbase = 0; |
1241 info->dli_sname = 0; | 1221 info->dli_sname = 0; |
1242 info->dli_saddr = 0; | 1222 info->dli_saddr = 0; |
1243 /* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com> | 1223 /* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com> |
1244 * to darwin-development AT lists DOT apple DOT com and slightly modified | 1224 * to darwin-development AT lists DOT apple DOT com and slightly modified |
1245 */ | 1225 */ |
1246 for (i = 0; i < count; i++) | 1226 for (i = 0; i < count; i++) { |
1247 { | 1227 addr = (unsigned long) p - _dyld_get_image_vmaddr_slide(i); |
1248 addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i); | 1228 mh = _dyld_get_image_header(i); |
1249 mh = _dyld_get_image_header(i); | 1229 if (mh) { |
1250 if (mh) | 1230 lc = (struct load_command *) ((char *) mh + |
1251 { | 1231 sizeof(struct mach_header)); |
1252 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); | 1232 for (j = 0; j < mh->ncmds; |
1253 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | 1233 j++, lc = |
1254 { | 1234 (struct load_command *) ((char *) lc + lc->cmdsize)) { |
1255 if (LC_SEGMENT == lc->cmd && | 1235 if (LC_SEGMENT == lc->cmd && |
1256 addr >= ((struct segment_command *)lc)->vmaddr && | 1236 addr >= ((struct segment_command *) lc)->vmaddr && |
1257 addr < | 1237 addr < |
1258 ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) | 1238 ((struct segment_command *) lc)->vmaddr + |
1259 { | 1239 ((struct segment_command *) lc)->vmsize) { |
1260 info->dli_fname = _dyld_get_image_name(i); | 1240 info->dli_fname = _dyld_get_image_name(i); |
1261 info->dli_fbase = (void *)mh; | 1241 info->dli_fbase = (void *) mh; |
1262 found = 1; | 1242 found = 1; |
1263 break; | 1243 break; |
1264 } | 1244 } |
1265 } | 1245 } |
1266 if (found) | 1246 if (found) |
1267 break; | 1247 break; |
1268 } | 1248 } |
1269 } | 1249 } |
1270 if (!found) | 1250 if (!found) { |
1271 { | 1251 dounlock(); |
1272 dounlock(); | 1252 return 0; |
1273 return 0; | 1253 } |
1274 } | 1254 lc = (struct load_command *) ((char *) mh + sizeof(struct mach_header)); |
1275 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); | 1255 for (j = 0; j < mh->ncmds; |
1276 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | 1256 j++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) { |
1277 { | 1257 if (LC_SEGMENT == lc->cmd) { |
1278 if (LC_SEGMENT == lc->cmd) | 1258 if (!SDL_strcmp |
1279 { | 1259 (((struct segment_command *) lc)->segname, "__LINKEDIT")) |
1280 if (!SDL_strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT")) | 1260 break; |
1281 break; | 1261 } |
1282 } | 1262 } |
1283 } | 1263 table_off = |
1284 table_off = | 1264 ((unsigned long) ((struct segment_command *) lc)->vmaddr) - |
1285 ((unsigned long)((struct segment_command *)lc)->vmaddr) - | 1265 ((unsigned long) ((struct segment_command *) lc)->fileoff) + |
1286 ((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i); | 1266 _dyld_get_image_vmaddr_slide(i); |
1287 debug("table off %x", table_off); | 1267 debug("table off %x", table_off); |
1288 | 1268 |
1289 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); | 1269 lc = (struct load_command *) ((char *) mh + sizeof(struct mach_header)); |
1290 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | 1270 for (j = 0; j < mh->ncmds; |
1291 { | 1271 j++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) { |
1292 if (LC_SYMTAB == lc->cmd) | 1272 if (LC_SYMTAB == lc->cmd) { |
1293 { | 1273 |
1294 | 1274 struct nlist *symtable = |
1295 struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off); | 1275 (struct nlist *) (((struct symtab_command *) lc)->symoff + |
1296 unsigned long numsyms = ((struct symtab_command *)lc)->nsyms; | 1276 table_off); |
1297 struct nlist *nearest = NULL; | 1277 unsigned long numsyms = ((struct symtab_command *) lc)->nsyms; |
1298 unsigned long diff = 0xffffffff; | 1278 struct nlist *nearest = NULL; |
1299 unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off); | 1279 unsigned long diff = 0xffffffff; |
1300 debug("symtable %x", symtable); | 1280 unsigned long strtable = |
1301 for (i = 0; i < numsyms; i++) | 1281 (unsigned long) (((struct symtab_command *) lc)->stroff + |
1302 { | 1282 table_off); |
1303 /* Ignore the following kinds of Symbols */ | 1283 debug("symtable %x", symtable); |
1304 if ((!symtable->n_value) /* Undefined */ | 1284 for (i = 0; i < numsyms; i++) { |
1305 || (symtable->n_type >= N_PEXT) /* Debug symbol */ | 1285 /* Ignore the following kinds of Symbols */ |
1306 || (!(symtable->n_type & N_EXT)) /* Local Symbol */ | 1286 if ((!symtable->n_value) /* Undefined */ |
1307 ) | 1287 ||(symtable->n_type >= N_PEXT) /* Debug symbol */ |
1308 { | 1288 ||(!(symtable->n_type & N_EXT)) /* Local Symbol */ |
1309 symtable++; | 1289 ) { |
1310 continue; | 1290 symtable++; |
1311 } | 1291 continue; |
1312 if ((addr >= symtable->n_value) && (diff >= (symtable->n_value - addr))) | 1292 } |
1313 { | 1293 if ((addr >= symtable->n_value) |
1314 diff = (unsigned long)symtable->n_value - addr; | 1294 && (diff >= (symtable->n_value - addr))) { |
1315 nearest = symtable; | 1295 diff = (unsigned long) symtable->n_value - addr; |
1316 } | 1296 nearest = symtable; |
1317 symtable++; | 1297 } |
1318 } | 1298 symtable++; |
1319 if (nearest) | 1299 } |
1320 { | 1300 if (nearest) { |
1321 info->dli_saddr = nearest->n_value + ((void *)p - addr); | 1301 info->dli_saddr = nearest->n_value + ((void *) p - addr); |
1322 info->dli_sname = (char *)(strtable + nearest->n_un.n_strx); | 1302 info->dli_sname = (char *) (strtable + nearest->n_un.n_strx); |
1323 } | 1303 } |
1324 } | 1304 } |
1325 } | 1305 } |
1326 dounlock(); | 1306 dounlock(); |
1327 return 1; | 1307 return 1; |
1328 } | 1308 } |
1329 #endif | 1309 #endif |
1330 | 1310 |
1331 /* | 1311 /* |
1332 * Implement the dlfunc() interface, which behaves exactly the same as | 1312 * Implement the dlfunc() interface, which behaves exactly the same as |
1335 * about undefined behavior, and is intended as prior art for future | 1315 * about undefined behavior, and is intended as prior art for future |
1336 * POSIX standardization. This function requires that all pointer types | 1316 * POSIX standardization. This function requires that all pointer types |
1337 * have the same representation, which is true on all platforms FreeBSD | 1317 * have the same representation, which is true on all platforms FreeBSD |
1338 * runs on, but is not guaranteed by the C standard. | 1318 * runs on, but is not guaranteed by the C standard. |
1339 */ | 1319 */ |
1340 #if 0 | 1320 #if 0 |
1341 static dlfunc_t SDL_OSX_dlfunc(void * dl_restrict handle, const char * dl_restrict symbol) | 1321 static dlfunc_t |
1342 { | 1322 SDL_OSX_dlfunc(void *dl_restrict handle, const char *dl_restrict symbol) |
1343 union | 1323 { |
1344 { | 1324 union |
1345 void *d; | 1325 { |
1346 dlfunc_t f; | 1326 void *d; |
1347 } rv; | 1327 dlfunc_t f; |
1348 int sym_len = SDL_strlen(symbol); | 1328 } rv; |
1349 char *malloc_sym = NULL; | 1329 int sym_len = SDL_strlen(symbol); |
1350 dolock(); | 1330 char *malloc_sym = NULL; |
1351 malloc_sym = SDL_malloc(sym_len + 2); | 1331 dolock(); |
1352 if (malloc_sym) | 1332 malloc_sym = SDL_malloc(sym_len + 2); |
1353 { | 1333 if (malloc_sym) { |
1354 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); | 1334 SDL_snprintf(malloc_sym, sym_len + 2, "_%s", symbol); |
1355 rv.d = dlsymIntern(handle, malloc_sym, 1); | 1335 rv.d = dlsymIntern(handle, malloc_sym, 1); |
1356 SDL_free(malloc_sym); | 1336 SDL_free(malloc_sym); |
1357 } | 1337 } else { |
1358 else | 1338 error("Unable to allocate memory"); |
1359 { | 1339 goto dlfuncerror; |
1360 error("Unable to allocate memory"); | 1340 } |
1361 goto dlfuncerror; | 1341 dounlock(); |
1362 } | 1342 return rv.f; |
1363 dounlock(); | |
1364 return rv.f; | |
1365 dlfuncerror: | 1343 dlfuncerror: |
1366 dounlock(); | 1344 dounlock(); |
1367 return NULL; | 1345 return NULL; |
1368 } | 1346 } |
1369 #endif | 1347 #endif |
1370 | 1348 |
1371 | 1349 |
1372 | 1350 |
1376 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | 1354 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
1377 /* System dependent library loading routines */ | 1355 /* System dependent library loading routines */ |
1378 | 1356 |
1379 #include "SDL_loadso.h" | 1357 #include "SDL_loadso.h" |
1380 | 1358 |
1381 void *SDL_LoadObject(const char *sofile) | 1359 void * |
1382 { | 1360 SDL_LoadObject(const char *sofile) |
1383 void *handle = SDL_OSX_dlopen(sofile, RTLD_NOW); | 1361 { |
1384 const char *loaderror = SDL_OSX_dlerror(); | 1362 void *handle = SDL_OSX_dlopen(sofile, RTLD_NOW); |
1385 if ( handle == NULL ) { | 1363 const char *loaderror = SDL_OSX_dlerror(); |
1386 SDL_SetError("Failed loading %s: %s", sofile, loaderror); | 1364 if (handle == NULL) { |
1387 } | 1365 SDL_SetError("Failed loading %s: %s", sofile, loaderror); |
1388 return(handle); | 1366 } |
1389 } | 1367 return (handle); |
1390 | 1368 } |
1391 void *SDL_LoadFunction(void *handle, const char *name) | 1369 |
1392 { | 1370 void * |
1393 void *symbol = SDL_OSX_dlsym(handle, name); | 1371 SDL_LoadFunction(void *handle, const char *name) |
1394 if ( symbol == NULL ) { | 1372 { |
1395 SDL_SetError("Failed loading %s: %s", name, SDL_OSX_dlerror()); | 1373 void *symbol = SDL_OSX_dlsym(handle, name); |
1396 } | 1374 if (symbol == NULL) { |
1397 return(symbol); | 1375 SDL_SetError("Failed loading %s: %s", name, SDL_OSX_dlerror()); |
1398 } | 1376 } |
1399 | 1377 return (symbol); |
1400 void SDL_UnloadObject(void *handle) | 1378 } |
1401 { | 1379 |
1402 if ( handle != NULL ) { | 1380 void |
1403 SDL_OSX_dlclose(handle); | 1381 SDL_UnloadObject(void *handle) |
1404 } | 1382 { |
1383 if (handle != NULL) { | |
1384 SDL_OSX_dlclose(handle); | |
1385 } | |
1405 } | 1386 } |
1406 | 1387 |
1407 #endif /* SDL_LOADSO_DLCOMPAT */ | 1388 #endif /* SDL_LOADSO_DLCOMPAT */ |
1389 /* vi: set ts=4 sw=4 expandtab: */ |