comparison src/loadso/macosx/SDL_dlcompat.c @ 1662:782fd950bd46 SDL-1.3

Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API. WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid. The code is now run through a consistent indent format: indent -i4 -nut -nsc -br -ce The headers are being converted to automatically generate doxygen documentation.
author Sam Lantinga <slouken@libsdl.org>
date Sun, 28 May 2006 13:04:16 +0000
parents 14717b52abc0
children 4da1ee79c9af
comparison
equal deleted inserted replaced
1661:281d3f4870e5 1662:782fd950bd46
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]; */
224 /* static int err_filled = 0; */ 232 /* static int err_filled = 0; */
225 233
226 /* Prototypes to internal functions */ 234 /* Prototypes to internal functions */
227 static void debug(const char *fmt, ...); 235 static void debug (const char *fmt, ...);
228 static void error(const char *str, ...); 236 static void error (const char *str, ...);
229 static const char *safegetenv(const char *s); 237 static const char *safegetenv (const char *s);
230 static const char *searchList(void); 238 static const char *searchList (void);
231 static const char *getSearchPath(int i); 239 static const char *getSearchPath (int i);
232 static const char *getFullPath(int i, const char *file); 240 static const char *getFullPath (int i, const char *file);
233 static const struct stat *findFile(const char *file, const char **fullPath); 241 static const struct stat *findFile (const char *file, const char **fullPath);
234 static int isValidStatus(struct dlstatus *status); 242 static int isValidStatus (struct dlstatus *status);
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,
241 static struct dlstatus *allocStatus(void); 249 int canSetError);
242 static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode); 250 static struct dlstatus *allocStatus (void);
243 static NSSymbol search_linked_libs(const struct mach_header *mh, const char *symbol); 251 static struct dlstatus *loadModule (const char *path, const struct stat *sbuf,
244 static const char *get_lib_name(const struct mach_header *mh); 252 int mode);
245 static const struct mach_header *get_mach_header_from_NSModule(NSModule mod); 253 static NSSymbol search_linked_libs (const struct mach_header *mh,
246 static void dlcompat_init_func(void); 254 const char *symbol);
247 static inline void dlcompat_init_check(void); 255 static const char *get_lib_name (const struct mach_header *mh);
248 static inline void dolock(void); 256 static const struct mach_header *get_mach_header_from_NSModule (NSModule mod);
249 static inline void dounlock(void); 257 static void dlcompat_init_func (void);
250 static void dlerrorfree(void *data); 258 static inline void dlcompat_init_check (void);
251 static void resetdlerror(void); 259 static inline void dolock (void);
252 static const struct mach_header *my_find_image(const char *name); 260 static inline void dounlock (void);
253 static const struct mach_header *image_for_address(const void *address); 261 static void dlerrorfree (void *data);
254 static inline char *dyld_error_str(void); 262 static void resetdlerror (void);
263 static const struct mach_header *my_find_image (const char *name);
264 static const struct mach_header *image_for_address (const void *address);
265 static inline char *dyld_error_str (void);
255 266
256 #if FINK_BUILD 267 #if FINK_BUILD
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,
263 static void *dlsym_auto_underscore_intern(void *handle, const char *symbol); 274 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) +
376 SDL_snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp, (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""), 389 4;
377 stdpath, '\0'); 390 buf = SDL_malloc (buf_size);
378 } 391 SDL_snprintf (buf, buf_size, "%s%s%s%s%s%c", dyldlp,
379 return buf; 392 (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""),
393 stdpath, '\0');
394 }
395 return buf;
380 } 396 }
381 397
382 /* Returns the ith search path from the list as computed by searchList() */ 398 /* Returns the ith search path from the list as computed by searchList() */
383 static const char *getSearchPath(int i) 399 static const char *
384 { 400 getSearchPath (int i)
385 static const char *list = 0; 401 {
386 static char **path = (char **)0; 402 static const char *list = 0;
387 static int end = 0; 403 static char **path = (char **) 0;
388 static int numsize = MAX_SEARCH_PATHS; 404 static int end = 0;
389 static char **tmp; 405 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 */ 406 static char **tmp;
391 if (i == -1) 407 /* So we can call SDL_free() in the "destructor" we use i=-1 to return the alloc'd array */
392 { 408 if (i == -1) {
393 return (const char*)path; 409 return (const char *) path;
394 } 410 }
395 if (!path) 411 if (!path) {
396 { 412 path = (char **) SDL_calloc (MAX_SEARCH_PATHS, sizeof (char **));
397 path = (char **)SDL_calloc(MAX_SEARCH_PATHS, sizeof(char **)); 413 }
398 } 414 if (!list && !end)
399 if (!list && !end) 415 list = searchList ();
400 list = searchList(); 416 if (i >= (numsize)) {
401 if (i >= (numsize)) 417 debug ("Increasing size for long PATH");
402 { 418 tmp =
403 debug("Increasing size for long PATH"); 419 (char **) SDL_calloc ((MAX_SEARCH_PATHS + numsize),
404 tmp = (char **)SDL_calloc((MAX_SEARCH_PATHS + numsize), sizeof(char **)); 420 sizeof (char **));
405 if (tmp) 421 if (tmp) {
406 { 422 SDL_memcpy (tmp, path, sizeof (char **) * numsize);
407 SDL_memcpy(tmp, path, sizeof(char **) * numsize); 423 SDL_free (path);
408 SDL_free(path); 424 path = tmp;
409 path = tmp; 425 numsize += MAX_SEARCH_PATHS;
410 numsize += MAX_SEARCH_PATHS; 426 } else {
411 } 427 return 0;
412 else 428 }
413 { 429 }
414 return 0; 430
415 } 431 while (!path[i] && !end) {
416 } 432 path[i] = strsep ((char **) &list, ":");
417 433
418 while (!path[i] && !end) 434 if (path[i][0] == 0)
419 { 435 path[i] = 0;
420 path[i] = strsep((char **)&list, ":"); 436 end = (list == 0);
421 437 }
422 if (path[i][0] == 0) 438 return path[i];
423 path[i] = 0; 439 }
424 end = (list == 0); 440
425 } 441 static const char *
426 return path[i]; 442 getFullPath (int i, const char *file)
427 } 443 {
428 444 static char buf[PATH_MAX];
429 static const char *getFullPath(int i, const char *file) 445 const char *path = getSearchPath (i);
430 { 446 if (path) {
431 static char buf[PATH_MAX]; 447 SDL_snprintf (buf, PATH_MAX, "%s/%s", path, file);
432 const char *path = getSearchPath(i); 448 }
433 if (path) 449 return path ? buf : 0;
434 {
435 SDL_snprintf(buf, PATH_MAX, "%s/%s", path, file);
436 }
437 return path ? buf : 0;
438 } 450 }
439 451
440 /* Given a file name, try to determine the full path for that file. Starts 452 /* 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 453 * its search in the current directory, and then tries all paths in the
442 * search list in the order they are specified there. 454 * search list in the order they are specified there.
443 */ 455 */
444 static const struct stat *findFile(const char *file, const char **fullPath) 456 static const struct stat *
445 { 457 findFile (const char *file, const char **fullPath)
446 int i = 0; 458 {
447 static struct stat sbuf; 459 int i = 0;
448 char *fileName; 460 static struct stat sbuf;
449 debug("finding file %s", file); 461 char *fileName;
450 *fullPath = file; 462 debug ("finding file %s", file);
451 if (0 == stat(file, &sbuf)) 463 *fullPath = file;
452 return &sbuf; 464 if (0 == stat (file, &sbuf))
453 if (SDL_strchr(file, '/')) 465 return &sbuf;
454 return 0; /* If the path had a / we don't look in env var places */ 466 if (SDL_strchr (file, '/'))
455 fileName = NULL; 467 return 0; /* If the path had a / we don't look in env var places */
456 if (!fileName) 468 fileName = NULL;
457 fileName = (char *)file; 469 if (!fileName)
458 while ((*fullPath = getFullPath(i++, fileName))) 470 fileName = (char *) file;
459 { 471 while ((*fullPath = getFullPath (i++, fileName))) {
460 if (0 == stat(*fullPath, &sbuf)) 472 if (0 == stat (*fullPath, &sbuf))
461 return &sbuf; 473 return &sbuf;
462 } 474 }
463 ; 475 ;
464 return 0; 476 return 0;
465 } 477 }
466 478
467 /* Determine whether a given dlstatus is valid or not */ 479 /* Determine whether a given dlstatus is valid or not */
468 static int isValidStatus(struct dlstatus *status) 480 static int
469 { 481 isValidStatus (struct dlstatus *status)
470 /* Walk the list to verify status is contained in it */ 482 {
471 struct dlstatus *dls = stqueue; 483 /* Walk the list to verify status is contained in it */
472 while (dls && status != dls) 484 struct dlstatus *dls = stqueue;
473 dls = dls->next; 485 while (dls && status != dls)
474 if (dls == 0) 486 dls = dls->next;
475 error("invalid handle"); 487 if (dls == 0)
476 else if ((dls->module == 0) || (dls->refs == 0)) 488 error ("invalid handle");
477 error("handle to closed library"); 489 else if ((dls->module == 0) || (dls->refs == 0))
478 else 490 error ("handle to closed library");
479 return TRUE; 491 else
480 return FALSE; 492 return TRUE;
481 } 493 return FALSE;
482 494 }
483 static inline int isFlagSet(int mode, int flag) 495
484 { 496 static inline int
485 return (mode & flag) == flag; 497 isFlagSet (int mode, int flag)
486 } 498 {
487 499 return (mode & flag) == flag;
488 static struct dlstatus *lookupStatus(const struct stat *sbuf) 500 }
489 { 501
490 struct dlstatus *dls = stqueue; 502 static struct dlstatus *
491 debug("looking for status"); 503 lookupStatus (const struct stat *sbuf)
492 while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0 504 {
493 || sbuf->st_dev != dls->device || sbuf->st_ino != dls->inode)) 505 struct dlstatus *dls = stqueue;
494 dls = dls->next; 506 debug ("looking for status");
495 return dls; 507 while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0
496 } 508 || sbuf->st_dev != dls->device
497 509 || sbuf->st_ino != dls->inode))
498 static void insertStatus(struct dlstatus *dls, const struct stat *sbuf) 510 dls = dls->next;
499 { 511 return dls;
500 debug("inserting status"); 512 }
501 dls->inode = sbuf->st_ino; 513
502 dls->device = sbuf->st_dev; 514 static void
503 dls->refs = 0; 515 insertStatus (struct dlstatus *dls, const struct stat *sbuf)
504 dls->mode = 0; 516 {
505 if ((dls->flags & DL_IN_LIST) == 0) 517 debug ("inserting status");
506 { 518 dls->inode = sbuf->st_ino;
507 dls->next = stqueue; 519 dls->device = sbuf->st_dev;
508 stqueue = dls; 520 dls->refs = 0;
509 dls->flags |= DL_IN_LIST; 521 dls->mode = 0;
510 } 522 if ((dls->flags & DL_IN_LIST) == 0) {
511 } 523 dls->next = stqueue;
512 524 stqueue = dls;
513 static struct dlstatus *allocStatus() 525 dls->flags |= DL_IN_LIST;
514 { 526 }
515 struct dlstatus *dls; 527 }
528
529 static struct dlstatus *
530 allocStatus ()
531 {
532 struct dlstatus *dls;
516 #ifdef REUSE_STATUS 533 #ifdef REUSE_STATUS
517 dls = stqueue; 534 dls = stqueue;
518 while (dls && dls->module) 535 while (dls && dls->module)
519 dls = dls->next; 536 dls = dls->next;
520 if (!dls) 537 if (!dls)
521 #endif 538 #endif
522 dls = SDL_calloc(sizeof(*dls),1); 539 dls = SDL_calloc (sizeof (*dls), 1);
523 return dls; 540 return dls;
524 } 541 }
525 542
526 static int promoteLocalToGlobal(struct dlstatus *dls) 543 static int
527 { 544 promoteLocalToGlobal (struct dlstatus *dls)
528 static int (*p) (NSModule module) = 0; 545 {
529 debug("promoting"); 546 static int (*p) (NSModule module) = 0;
530 if (!p) 547 debug ("promoting");
531 _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (void **)&p); 548 if (!p)
532 return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module)); 549 _dyld_func_lookup ("__dyld_NSMakePrivateModulePublic", (void **) &p);
533 } 550 return (dls->module == MAGIC_DYLIB_MOD) || (p && p (dls->module));
534 551 }
535 static void *reference(struct dlstatus *dls, int mode) 552
536 { 553 static void *
537 if (dls) 554 reference (struct dlstatus *dls, int mode)
538 { 555 {
539 if (dls->module == MAGIC_DYLIB_MOD && isFlagSet(mode, RTLD_LOCAL)) 556 if (dls) {
540 { 557 if (dls->module == MAGIC_DYLIB_MOD && isFlagSet (mode, RTLD_LOCAL)) {
541 warning("trying to open a .dylib with RTLD_LOCAL"); 558 warning ("trying to open a .dylib with RTLD_LOCAL");
542 error("unable to open a .dylib with RTLD_LOCAL"); 559 error ("unable to open a .dylib with RTLD_LOCAL");
543 return NULL; 560 return NULL;
544 } 561 }
545 if (isFlagSet(mode, RTLD_GLOBAL) && 562 if (isFlagSet (mode, RTLD_GLOBAL) &&
546 !isFlagSet(dls->mode, RTLD_GLOBAL) && !promoteLocalToGlobal(dls)) 563 !isFlagSet (dls->mode, RTLD_GLOBAL)
547 { 564 && !promoteLocalToGlobal (dls)) {
548 error("unable to promote local module to global"); 565 error ("unable to promote local module to global");
549 return NULL; 566 return NULL;
550 } 567 }
551 dls->mode |= mode; 568 dls->mode |= mode;
552 dls->refs++; 569 dls->refs++;
553 } 570 } else
554 else 571 debug ("reference called with NULL argument");
555 debug("reference called with NULL argument"); 572
556 573 return dls;
557 return dls; 574 }
558 } 575
559 576 static const struct mach_header *
560 static const struct mach_header *my_find_image(const char *name) 577 my_find_image (const char *name)
561 { 578 {
562 const struct mach_header *mh = 0; 579 const struct mach_header *mh = 0;
563 const char *id = NULL; 580 const char *id = NULL;
564 int i = _dyld_image_count(); 581 int i = _dyld_image_count ();
565 int j; 582 int j;
566 mh = (struct mach_header *) 583 mh = (struct mach_header *)
567 dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED | 584 dyld_NSAddImage (name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED |
568 NSADDIMAGE_OPTION_RETURN_ON_ERROR); 585 NSADDIMAGE_OPTION_RETURN_ON_ERROR);
569 if (!mh) 586 if (!mh) {
570 { 587 for (j = 0; j < i; j++) {
571 for (j = 0; j < i; j++) 588 id = _dyld_get_image_name (j);
572 { 589 if (!SDL_strcmp (id, name)) {
573 id = _dyld_get_image_name(j); 590 mh = _dyld_get_image_header (j);
574 if (!SDL_strcmp(id, name)) 591 break;
575 { 592 }
576 mh = _dyld_get_image_header(j); 593 }
577 break; 594 }
578 } 595 return mh;
579 }
580 }
581 return mh;
582 } 596 }
583 597
584 /* 598 /*
585 * dyld adds libraries by first adding the directly dependant libraries in link order, and 599 * 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 600 * 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 601 * 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. 602 * any of it's direct dependencies, then it probably isn't there.
589 */ 603 */
590 static NSSymbol search_linked_libs(const struct mach_header * mh, const char *symbol) 604 static NSSymbol
591 { 605 search_linked_libs (const struct mach_header *mh, const char *symbol)
592 unsigned int n; 606 {
593 struct load_command *lc = 0; 607 unsigned int n;
594 struct mach_header *wh; 608 struct load_command *lc = 0;
595 NSSymbol nssym = 0; 609 struct mach_header *wh;
596 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) 610 NSSymbol nssym = 0;
597 { 611 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage
598 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); 612 && dyld_NSLookupSymbolInImage) {
599 for (n = 0; n < mh->ncmds; n++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) 613 lc = (struct load_command *) ((char *) mh +
600 { 614 sizeof (struct mach_header));
601 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) 615 for (n = 0; n < mh->ncmds;
602 { 616 n++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) {
603 if ((wh = (struct mach_header *) 617 if ((LC_LOAD_DYLIB == lc->cmd)
604 my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset + 618 || (LC_LOAD_WEAK_DYLIB == lc->cmd)) {
605 (char *)lc)))) 619 if ((wh = (struct mach_header *)
606 { 620 my_find_image ((char
607 if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol)) 621 *) (((struct dylib_command *) lc)->
608 { 622 dylib.name.offset + (char *) lc)))) {
609 nssym = dyld_NSLookupSymbolInImage(wh, 623 if (dyld_NSIsSymbolNameDefinedInImage (wh, symbol)) {
610 symbol, 624 nssym = dyld_NSLookupSymbolInImage (wh,
611 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | 625 symbol,
612 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); 626 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
613 break; 627 |
614 } 628 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
615 } 629 break;
616 } 630 }
617 } 631 }
618 if ((!nssym) && NSIsSymbolNameDefined(symbol)) 632 }
619 { 633 }
620 /* I've never seen this debug message...*/ 634 if ((!nssym) && NSIsSymbolNameDefined (symbol)) {
621 debug("Symbol \"%s\" is defined but was not found", symbol); 635 /* I've never seen this debug message... */
622 } 636 debug ("Symbol \"%s\" is defined but was not found", symbol);
623 } 637 }
624 return nssym; 638 }
639 return nssym;
625 } 640 }
626 641
627 /* Up to the caller to SDL_free() returned string */ 642 /* Up to the caller to SDL_free() returned string */
628 static inline char *dyld_error_str() 643 static inline char *
629 { 644 dyld_error_str ()
630 NSLinkEditErrors dylder; 645 {
631 int dylderno; 646 NSLinkEditErrors dylder;
632 const char *dylderrstr; 647 int dylderno;
633 const char *dyldfile; 648 const char *dylderrstr;
634 char* retStr = NULL; 649 const char *dyldfile;
635 NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr); 650 char *retStr = NULL;
636 if (dylderrstr && *dylderrstr) 651 NSLinkEditError (&dylder, &dylderno, &dyldfile, &dylderrstr);
637 { 652 if (dylderrstr && *dylderrstr) {
638 retStr = SDL_strdup(dylderrstr); 653 retStr = SDL_strdup (dylderrstr);
639 } 654 }
640 return retStr; 655 return retStr;
641 } 656 }
642 657
643 static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError) 658 static void *
644 { 659 dlsymIntern (struct dlstatus *dls, const char *symbol, int canSetError)
645 NSSymbol nssym = 0; 660 {
646 #ifdef __GCC__ 661 NSSymbol nssym = 0;
647 void *caller = __builtin_return_address(1); /* Be *very* careful about inlining */ 662 #ifdef __GCC__
663 void *caller = __builtin_return_address (1); /* Be *very* careful about inlining */
648 #else 664 #else
649 void *caller = NULL; 665 void *caller = NULL;
650 #endif 666 #endif
651 const struct mach_header *caller_mh = 0; 667 const struct mach_header *caller_mh = 0;
652 char *savedErrorStr = NULL; 668 char *savedErrorStr = NULL;
653 resetdlerror(); 669 resetdlerror ();
654 #ifndef RTLD_SELF 670 #ifndef RTLD_SELF
655 #define RTLD_SELF ((void *) -3) 671 #define RTLD_SELF ((void *) -3)
656 #endif 672 #endif
657 if (NULL == dls) 673 if (NULL == dls)
658 dls = RTLD_SELF; 674 dls = RTLD_SELF;
659 if ((RTLD_NEXT == dls) || (RTLD_SELF == dls)) 675 if ((RTLD_NEXT == dls) || (RTLD_SELF == dls)) {
660 { 676 if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage
661 if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage && caller) 677 && caller) {
662 { 678 caller_mh = image_for_address (caller);
663 caller_mh = image_for_address(caller); 679 if (RTLD_SELF == dls) {
664 if (RTLD_SELF == dls) 680 /* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE
665 { 681 * 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 682 * this is acceptable.
667 * But it appears to work anyway, and looking at the code in dyld_libfuncs.c 683 */
668 * this is acceptable. 684 if (dyld_NSIsSymbolNameDefinedInImage (caller_mh, symbol)) {
669 */ 685 nssym = dyld_NSLookupSymbolInImage (caller_mh,
670 if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol)) 686 symbol,
671 { 687 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
672 nssym = dyld_NSLookupSymbolInImage(caller_mh, 688 |
673 symbol, 689 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
674 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | 690 }
675 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); 691 }
676 } 692 if (!nssym) {
677 } 693 if (RTLD_SELF == dls)
678 if (!nssym) 694 savedErrorStr = dyld_error_str ();
679 { 695 nssym = search_linked_libs (caller_mh, symbol);
680 if (RTLD_SELF == dls) 696 }
681 savedErrorStr = dyld_error_str(); 697 } else {
682 nssym = search_linked_libs(caller_mh, symbol); 698 if (canSetError)
683 } 699 error ("RTLD_SELF and RTLD_NEXT are not supported");
684 } 700 return NULL;
685 else 701 }
686 { 702 }
687 if (canSetError) 703 if (!nssym) {
688 error("RTLD_SELF and RTLD_NEXT are not supported"); 704
689 return NULL; 705 if (RTLD_DEFAULT == dls) {
690 } 706 dls = &mainStatus;
691 } 707 }
692 if (!nssym) 708 if (!isValidStatus (dls))
693 { 709 return NULL;
694 710
695 if (RTLD_DEFAULT == dls) 711 if (dls->module != MAGIC_DYLIB_MOD) {
696 { 712 nssym = NSLookupSymbolInModule (dls->module, symbol);
697 dls = &mainStatus; 713 if (!nssym && NSIsSymbolNameDefined (symbol)) {
698 } 714 debug ("Searching dependencies");
699 if (!isValidStatus(dls)) 715 savedErrorStr = dyld_error_str ();
700 return NULL; 716 nssym =
701 717 search_linked_libs (get_mach_header_from_NSModule
702 if (dls->module != MAGIC_DYLIB_MOD) 718 (dls->module), symbol);
703 { 719 }
704 nssym = NSLookupSymbolInModule(dls->module, symbol); 720 } else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage
705 if (!nssym && NSIsSymbolNameDefined(symbol)) 721 && dyld_NSLookupSymbolInImage) {
706 { 722 if (dyld_NSIsSymbolNameDefinedInImage (dls->lib, symbol)) {
707 debug("Searching dependencies"); 723 nssym = dyld_NSLookupSymbolInImage (dls->lib,
708 savedErrorStr = dyld_error_str(); 724 symbol,
709 nssym = search_linked_libs(get_mach_header_from_NSModule(dls->module), symbol); 725 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
710 } 726 |
711 } 727 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
712 else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) 728 } else if (NSIsSymbolNameDefined (symbol)) {
713 { 729 debug ("Searching dependencies");
714 if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol)) 730 savedErrorStr = dyld_error_str ();
715 { 731 nssym = search_linked_libs (dls->lib, symbol);
716 nssym = dyld_NSLookupSymbolInImage(dls->lib, 732 }
717 symbol, 733 } else if (dls->module == MAGIC_DYLIB_MOD) {
718 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | 734 /* Global context, use NSLookupAndBindSymbol */
719 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); 735 if (NSIsSymbolNameDefined (symbol)) {
720 } 736 /* There doesn't seem to be a return on error option for this call???
721 else if (NSIsSymbolNameDefined(symbol)) 737 this is potentially broken, if binding fails, it will improperly
722 { 738 exit the application. */
723 debug("Searching dependencies"); 739 nssym = NSLookupAndBindSymbol (symbol);
724 savedErrorStr = dyld_error_str(); 740 } else {
725 nssym = search_linked_libs(dls->lib, symbol); 741 if (savedErrorStr)
726 } 742 SDL_free (savedErrorStr);
727 } 743 savedErrorStr = SDL_malloc (256);
728 else if (dls->module == MAGIC_DYLIB_MOD) 744 SDL_snprintf (savedErrorStr, 256,
729 { 745 "Symbol \"%s\" not in global context", symbol);
730 /* Global context, use NSLookupAndBindSymbol */ 746 }
731 if (NSIsSymbolNameDefined(symbol)) 747 }
732 { 748 }
733 /* There doesn't seem to be a return on error option for this call??? 749 /* Error reporting */
734 this is potentially broken, if binding fails, it will improperly 750 if (!nssym) {
735 exit the application. */ 751 if (!savedErrorStr || !SDL_strlen (savedErrorStr)) {
736 nssym = NSLookupAndBindSymbol(symbol); 752 if (savedErrorStr)
737 } 753 SDL_free (savedErrorStr);
738 else 754 savedErrorStr = SDL_malloc (256);
739 { 755 SDL_snprintf (savedErrorStr, 256, "Symbol \"%s\" not found",
740 if (savedErrorStr) 756 symbol);
741 SDL_free(savedErrorStr); 757 }
742 savedErrorStr = SDL_malloc(256); 758 if (canSetError) {
743 SDL_snprintf(savedErrorStr, 256, "Symbol \"%s\" not in global context",symbol); 759 error (savedErrorStr);
744 } 760 } else {
745 } 761 debug (savedErrorStr);
746 } 762 }
747 /* Error reporting */ 763 if (savedErrorStr)
748 if (!nssym) 764 SDL_free (savedErrorStr);
749 { 765 return NULL;
750 if (!savedErrorStr || !SDL_strlen(savedErrorStr)) 766 }
751 { 767 return NSAddressOfSymbol (nssym);
752 if (savedErrorStr) 768 }
753 SDL_free(savedErrorStr); 769
754 savedErrorStr = SDL_malloc(256); 770 static struct dlstatus *
755 SDL_snprintf(savedErrorStr, 256,"Symbol \"%s\" not found",symbol); 771 loadModule (const char *path, const struct stat *sbuf, int mode)
756 } 772 {
757 if (canSetError) 773 NSObjectFileImage ofi = 0;
758 { 774 NSObjectFileImageReturnCode ofirc;
759 error(savedErrorStr); 775 struct dlstatus *dls;
760 } 776 NSLinkEditErrors ler;
761 else 777 int lerno;
762 { 778 const char *errstr;
763 debug(savedErrorStr); 779 const char *file;
764 } 780 void (*init) (void);
765 if (savedErrorStr) 781
766 SDL_free(savedErrorStr); 782 ofirc = NSCreateObjectFileImageFromFile (path, &ofi);
767 return NULL; 783 switch (ofirc) {
768 } 784 case NSObjectFileImageSuccess:
769 return NSAddressOfSymbol(nssym); 785 break;
770 } 786 case NSObjectFileImageInappropriateFile:
771 787 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage
772 static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode) 788 && dyld_NSLookupSymbolInImage) {
773 { 789 if (isFlagSet (mode, RTLD_LOCAL)) {
774 NSObjectFileImage ofi = 0; 790 warning ("trying to open a .dylib with RTLD_LOCAL");
775 NSObjectFileImageReturnCode ofirc; 791 error ("unable to open this file with RTLD_LOCAL");
776 struct dlstatus *dls; 792 return NULL;
777 NSLinkEditErrors ler; 793 }
778 int lerno; 794 } else {
779 const char *errstr; 795 error ("opening this file is unsupported on this system");
780 const char *file; 796 return NULL;
781 void (*init) (void); 797 }
782 798 break;
783 ofirc = NSCreateObjectFileImageFromFile(path, &ofi); 799 case NSObjectFileImageFailure:
784 switch (ofirc) 800 error ("object file setup failure");
785 { 801 return NULL;
786 case NSObjectFileImageSuccess: 802 case NSObjectFileImageArch:
787 break; 803 error ("no object for this architecture");
788 case NSObjectFileImageInappropriateFile: 804 return NULL;
789 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) 805 case NSObjectFileImageFormat:
790 { 806 error ("bad object file format");
791 if (isFlagSet(mode, RTLD_LOCAL)) 807 return NULL;
792 { 808 case NSObjectFileImageAccess:
793 warning("trying to open a .dylib with RTLD_LOCAL"); 809 error ("can't read object file");
794 error("unable to open this file with RTLD_LOCAL"); 810 return NULL;
795 return NULL; 811 default:
796 } 812 error ("unknown error from NSCreateObjectFileImageFromFile()");
797 } 813 return NULL;
798 else 814 }
799 { 815 dls = lookupStatus (sbuf);
800 error("opening this file is unsupported on this system"); 816 if (!dls) {
801 return NULL; 817 dls = allocStatus ();
802 } 818 }
803 break; 819 if (!dls) {
804 case NSObjectFileImageFailure: 820 error ("unable to allocate memory");
805 error("object file setup failure"); 821 return NULL;
806 return NULL; 822 }
807 case NSObjectFileImageArch: 823 // dls->lib = 0;
808 error("no object for this architecture"); 824 if (ofirc == NSObjectFileImageInappropriateFile) {
809 return NULL; 825 if ((dls->lib =
810 case NSObjectFileImageFormat: 826 dyld_NSAddImage (path, NSADDIMAGE_OPTION_RETURN_ON_ERROR))) {
811 error("bad object file format"); 827 debug ("Dynamic lib loaded at %ld", dls->lib);
812 return NULL; 828 ofi = MAGIC_DYLIB_OFI;
813 case NSObjectFileImageAccess: 829 dls->module = MAGIC_DYLIB_MOD;
814 error("can't read object file"); 830 ofirc = NSObjectFileImageSuccess;
815 return NULL; 831 /* Although it is possible with a bit of work to modify this so it works and
816 default: 832 functions with RTLD_NOW, I don't deem it necessary at the moment */
817 error("unknown error from NSCreateObjectFileImageFromFile()"); 833 }
818 return NULL; 834 if (!(dls->module)) {
819 } 835 NSLinkEditError (&ler, &lerno, &file, &errstr);
820 dls = lookupStatus(sbuf); 836 if (!errstr || (!SDL_strlen (errstr)))
821 if (!dls) 837 error ("Can't open this file type");
822 { 838 else
823 dls = allocStatus(); 839 error (errstr);
824 } 840 if ((dls->flags & DL_IN_LIST) == 0) {
825 if (!dls) 841 SDL_free (dls);
826 { 842 }
827 error("unable to allocate memory"); 843 return NULL;
828 return NULL; 844 }
829 } 845 } else {
830 // dls->lib = 0; 846 dls->module = NSLinkModule (ofi, path,
831 if (ofirc == NSObjectFileImageInappropriateFile) 847 NSLINKMODULE_OPTION_RETURN_ON_ERROR |
832 { 848 NSLINKMODULE_OPTION_PRIVATE |
833 if ((dls->lib = dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR))) 849 (isFlagSet (mode, RTLD_NOW) ?
834 { 850 NSLINKMODULE_OPTION_BINDNOW : 0));
835 debug("Dynamic lib loaded at %ld", dls->lib); 851 NSDestroyObjectFileImage (ofi);
836 ofi = MAGIC_DYLIB_OFI; 852 if (dls->module) {
837 dls->module = MAGIC_DYLIB_MOD; 853 dls->lib = get_mach_header_from_NSModule (dls->module);
838 ofirc = NSObjectFileImageSuccess; 854 }
839 /* Although it is possible with a bit of work to modify this so it works and 855 }
840 functions with RTLD_NOW, I don't deem it necessary at the moment */ 856 if (!dls->module) {
841 } 857 NSLinkEditError (&ler, &lerno, &file, &errstr);
842 if (!(dls->module)) 858 if ((dls->flags & DL_IN_LIST) == 0) {
843 { 859 SDL_free (dls);
844 NSLinkEditError(&ler, &lerno, &file, &errstr); 860 }
845 if (!errstr || (!SDL_strlen(errstr))) 861 error (errstr);
846 error("Can't open this file type"); 862 return NULL;
847 else 863 }
848 error(errstr); 864
849 if ((dls->flags & DL_IN_LIST) == 0) 865 insertStatus (dls, sbuf);
850 { 866 dls = reference (dls, mode);
851 SDL_free(dls); 867 if ((init = dlsymIntern (dls, "__init", 0))) {
852 } 868 debug ("calling _init()");
853 return NULL; 869 init ();
854 } 870 }
855 } 871 return dls;
856 else 872 }
857 { 873
858 dls->module = NSLinkModule(ofi, path, 874 inline static void
859 NSLINKMODULE_OPTION_RETURN_ON_ERROR | 875 dlcompat_init_check (void)
860 NSLINKMODULE_OPTION_PRIVATE | 876 {
861 (isFlagSet(mode, RTLD_NOW) ? NSLINKMODULE_OPTION_BINDNOW : 0)); 877 static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER;
862 NSDestroyObjectFileImage(ofi); 878 static int init_done = 0;
863 if (dls->module) 879
864 { 880 pthread_mutex_lock (&l);
865 dls->lib = get_mach_header_from_NSModule(dls->module); 881 if (!init_done) {
866 } 882 dlcompat_init_func ();
867 } 883 init_done = 1;
868 if (!dls->module) 884 }
869 { 885 pthread_mutex_unlock (&l);
870 NSLinkEditError(&ler, &lerno, &file, &errstr); 886 }
871 if ((dls->flags & DL_IN_LIST) == 0) 887
872 { 888 static void
873 SDL_free(dls); 889 dlcompat_init_func (void)
874 } 890 {
875 error(errstr); 891 _dyld_func_lookup ("__dyld_NSAddImage", (void **) &dyld_NSAddImage);
876 return NULL; 892 _dyld_func_lookup ("__dyld_NSIsSymbolNameDefinedInImage",
877 } 893 (void **) &dyld_NSIsSymbolNameDefinedInImage);
878 894 _dyld_func_lookup ("__dyld_NSLookupSymbolInImage",
879 insertStatus(dls, sbuf); 895 (void **) &dyld_NSLookupSymbolInImage);
880 dls = reference(dls, mode); 896 if (pthread_mutex_init (&dlcompat_mutex, NULL))
881 if ((init = dlsymIntern(dls, "__init", 0))) 897 exit (1);
882 { 898 if (pthread_key_create (&dlerror_key, &dlerrorfree))
883 debug("calling _init()"); 899 exit (1);
884 init(); 900 }
885 } 901
886 return dls; 902 static void
887 } 903 resetdlerror ()
888 904 {
889 inline static void dlcompat_init_check(void) 905 struct dlthread *tss;
890 { 906 tss = pthread_getspecific (dlerror_key);
891 static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER; 907 tss->errset = 0;
892 static int init_done = 0; 908 }
893 909
894 pthread_mutex_lock(&l); 910 static void
895 if (!init_done) { 911 dlerrorfree (void *data)
896 dlcompat_init_func(); 912 {
897 init_done = 1; 913 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 } 914 }
925 915
926 /* We kind of want a recursive lock here, but meet a little trouble 916 /* 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 917 * because they are not available pre OS X 10.2, so we fake it
928 * using thread specific storage to keep a lock count 918 * using thread specific storage to keep a lock count
929 */ 919 */
930 static inline void dolock(void) 920 static inline void
931 { 921 dolock (void)
932 int err = 0; 922 {
933 struct dlthread *tss; 923 int err = 0;
934 dlcompat_init_check(); 924 struct dlthread *tss;
935 tss = pthread_getspecific(dlerror_key); 925 dlcompat_init_check ();
936 if (!tss) 926 tss = pthread_getspecific (dlerror_key);
937 { 927 if (!tss) {
938 tss = SDL_malloc(sizeof(struct dlthread)); 928 tss = SDL_malloc (sizeof (struct dlthread));
939 tss->lockcnt = 0; 929 tss->lockcnt = 0;
940 tss->errset = 0; 930 tss->errset = 0;
941 if (pthread_setspecific(dlerror_key, tss)) 931 if (pthread_setspecific (dlerror_key, tss)) {
942 { 932 fprintf (stderr, "dlcompat: pthread_setspecific failed\n");
943 fprintf(stderr,"dlcompat: pthread_setspecific failed\n"); 933 exit (1);
944 exit(1); 934 }
945 } 935 }
946 } 936 if (!tss->lockcnt)
947 if (!tss->lockcnt) 937 err = pthread_mutex_lock (&dlcompat_mutex);
948 err = pthread_mutex_lock(&dlcompat_mutex); 938 tss->lockcnt = tss->lockcnt + 1;
949 tss->lockcnt = tss->lockcnt +1; 939 if (err)
950 if (err) 940 exit (err);
951 exit(err); 941 }
952 } 942
953 943 static inline void
954 static inline void dounlock(void) 944 dounlock (void)
955 { 945 {
956 int err = 0; 946 int err = 0;
957 struct dlthread *tss; 947 struct dlthread *tss;
958 tss = pthread_getspecific(dlerror_key); 948 tss = pthread_getspecific (dlerror_key);
959 tss->lockcnt = tss->lockcnt -1; 949 tss->lockcnt = tss->lockcnt - 1;
960 if (!tss->lockcnt) 950 if (!tss->lockcnt)
961 err = pthread_mutex_unlock(&dlcompat_mutex); 951 err = pthread_mutex_unlock (&dlcompat_mutex);
962 if (err) 952 if (err)
963 exit(err); 953 exit (err);
964 } 954 }
965 955
966 static void *SDL_OSX_dlopen(const char *path, int mode) 956 static void *
967 { 957 SDL_OSX_dlopen (const char *path, int mode)
968 const struct stat *sbuf; 958 {
969 struct dlstatus *dls; 959 const struct stat *sbuf;
970 const char *fullPath; 960 struct dlstatus *dls;
971 961 const char *fullPath;
972 dolock(); 962
973 resetdlerror(); 963 dolock ();
974 if (!path) 964 resetdlerror ();
975 { 965 if (!path) {
976 dls = &mainStatus; 966 dls = &mainStatus;
977 goto dlopenok; 967 goto dlopenok;
978 } 968 }
979 if (!(sbuf = findFile(path, &fullPath))) 969 if (!(sbuf = findFile (path, &fullPath))) {
980 { 970 error ("file \"%s\" not found", path);
981 error("file \"%s\" not found", path); 971 goto dlopenerror;
982 goto dlopenerror; 972 }
983 } 973 /* Now checks that it hasn't been closed already */
984 /* Now checks that it hasn't been closed already */ 974 if ((dls = lookupStatus (sbuf)) && (dls->refs > 0)) {
985 if ((dls = lookupStatus(sbuf)) && (dls->refs > 0)) 975 /* debug("status found"); */
986 { 976 dls = reference (dls, mode);
987 /* debug("status found"); */ 977 goto dlopenok;
988 dls = reference(dls, mode); 978 }
989 goto dlopenok;
990 }
991 #ifdef RTLD_NOLOAD 979 #ifdef RTLD_NOLOAD
992 if (isFlagSet(mode, RTLD_NOLOAD)) 980 if (isFlagSet (mode, RTLD_NOLOAD)) {
993 { 981 error ("no existing handle and RTLD_NOLOAD specified");
994 error("no existing handle and RTLD_NOLOAD specified"); 982 goto dlopenerror;
995 goto dlopenerror; 983 }
996 } 984 #endif
997 #endif 985 if (isFlagSet (mode, RTLD_LAZY) && isFlagSet (mode, RTLD_NOW)) {
998 if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW)) 986 error ("how can I load something both RTLD_LAZY and RTLD_NOW?");
999 { 987 goto dlopenerror;
1000 error("how can I load something both RTLD_LAZY and RTLD_NOW?"); 988 }
1001 goto dlopenerror; 989 dls = loadModule (fullPath, sbuf, mode);
1002 } 990
1003 dls = loadModule(fullPath, sbuf, mode);
1004
1005 dlopenok: 991 dlopenok:
1006 dounlock(); 992 dounlock ();
1007 return (void *)dls; 993 return (void *) dls;
1008 dlopenerror: 994 dlopenerror:
1009 dounlock(); 995 dounlock ();
1010 return NULL; 996 return NULL;
1011 } 997 }
1012 998
1013 #if !FINK_BUILD 999 #if !FINK_BUILD
1014 static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol) 1000 static void *
1015 { 1001 SDL_OSX_dlsym (void *dl_restrict handle, const char *dl_restrict symbol)
1016 int sym_len = SDL_strlen(symbol); 1002 {
1017 void *value = NULL; 1003 int sym_len = SDL_strlen (symbol);
1018 char *malloc_sym = NULL; 1004 void *value = NULL;
1019 dolock(); 1005 char *malloc_sym = NULL;
1020 malloc_sym = SDL_malloc(sym_len + 2); 1006 dolock ();
1021 if (malloc_sym) 1007 malloc_sym = SDL_malloc (sym_len + 2);
1022 { 1008 if (malloc_sym) {
1023 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); 1009 SDL_snprintf (malloc_sym, sym_len + 2, "_%s", symbol);
1024 value = dlsymIntern(handle, malloc_sym, 1); 1010 value = dlsymIntern (handle, malloc_sym, 1);
1025 SDL_free(malloc_sym); 1011 SDL_free (malloc_sym);
1026 } 1012 } else {
1027 else 1013 error ("Unable to allocate memory");
1028 { 1014 goto dlsymerror;
1029 error("Unable to allocate memory"); 1015 }
1030 goto dlsymerror; 1016 dounlock ();
1031 } 1017 return value;
1032 dounlock();
1033 return value;
1034 dlsymerror: 1018 dlsymerror:
1035 dounlock(); 1019 dounlock ();
1036 return NULL; 1020 return NULL;
1037 } 1021 }
1038 #endif 1022 #endif
1039 1023
1040 #if FINK_BUILD 1024 #if FINK_BUILD
1041 1025
1042 static void *dlsym_prepend_underscore(void *handle, const char *symbol) 1026 static void *
1043 { 1027 dlsym_prepend_underscore (void *handle, const char *symbol)
1044 void *answer; 1028 {
1045 dolock(); 1029 void *answer;
1046 answer = dlsym_prepend_underscore_intern(handle, symbol); 1030 dolock ();
1047 dounlock(); 1031 answer = dlsym_prepend_underscore_intern (handle, symbol);
1048 return answer; 1032 dounlock ();
1049 } 1033 return answer;
1050 1034 }
1051 static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol) 1035
1036 static void *
1037 dlsym_prepend_underscore_intern (void *handle, const char *symbol)
1052 { 1038 {
1053 /* 1039 /*
1054 * A quick and easy way for porting packages which call dlsym(handle,"sym") 1040 * 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 1041 * If the porter adds -Ddlsym=dlsym_prepend_underscore to the CFLAGS then
1056 * this function will be called, and will add the required underscore. 1042 * this function will be called, and will add the required underscore.
1057 * 1043 *
1058 * Note that I haven't figured out yet which should be "standard", prepend 1044 * 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 1045 * the underscore always, or not at all. These global functions need to go away
1060 * for opendarwin. 1046 * for opendarwin.
1061 */ 1047 */
1062 int sym_len = SDL_strlen(symbol); 1048 int sym_len = SDL_strlen (symbol);
1063 void *value = NULL; 1049 void *value = NULL;
1064 char *malloc_sym = NULL; 1050 char *malloc_sym = NULL;
1065 malloc_sym = SDL_malloc(sym_len + 2); 1051 malloc_sym = SDL_malloc (sym_len + 2);
1066 if (malloc_sym) 1052 if (malloc_sym) {
1067 { 1053 SDL_snprintf (malloc_sym, sym_len + 2, "_%s", symbol);
1068 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); 1054 value = dlsymIntern (handle, malloc_sym, 1);
1069 value = dlsymIntern(handle, malloc_sym, 1); 1055 SDL_free (malloc_sym);
1070 SDL_free(malloc_sym); 1056 } else {
1071 } 1057 error ("Unable to allocate memory");
1072 else 1058 }
1073 { 1059 return value;
1074 error("Unable to allocate memory"); 1060 }
1075 } 1061
1076 return value; 1062 static void *
1077 } 1063 dlsym_auto_underscore (void *handle, const char *symbol)
1078 1064 {
1079 static void *dlsym_auto_underscore(void *handle, const char *symbol) 1065 void *answer;
1080 { 1066 dolock ();
1081 void *answer; 1067 answer = dlsym_auto_underscore_intern (handle, symbol);
1082 dolock(); 1068 dounlock ();
1083 answer = dlsym_auto_underscore_intern(handle, symbol); 1069 return answer;
1084 dounlock(); 1070
1085 return answer; 1071 }
1086 1072 static void *
1087 } 1073 dlsym_auto_underscore_intern (void *handle, const char *symbol)
1088 static void *dlsym_auto_underscore_intern(void *handle, const char *symbol) 1074 {
1089 { 1075 struct dlstatus *dls = handle;
1090 struct dlstatus *dls = handle; 1076 void *addr = 0;
1091 void *addr = 0; 1077 addr = dlsymIntern (dls, symbol, 0);
1092 addr = dlsymIntern(dls, symbol, 0); 1078 if (!addr)
1093 if (!addr) 1079 addr = dlsym_prepend_underscore_intern (handle, symbol);
1094 addr = dlsym_prepend_underscore_intern(handle, symbol); 1080 return addr;
1095 return addr; 1081 }
1096 } 1082
1097 1083
1098 1084 static void *
1099 static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol) 1085 SDL_OSX_dlsym (void *dl_restrict handle, const char *dl_restrict symbol)
1100 { 1086 {
1101 struct dlstatus *dls = handle; 1087 struct dlstatus *dls = handle;
1102 void *addr = 0; 1088 void *addr = 0;
1103 dolock(); 1089 dolock ();
1104 addr = dlsymIntern(dls, symbol, 1); 1090 addr = dlsymIntern (dls, symbol, 1);
1105 dounlock(); 1091 dounlock ();
1106 return addr; 1092 return addr;
1107 } 1093 }
1108 #endif 1094 #endif
1109 1095
1110 static int SDL_OSX_dlclose(void *handle) 1096 static int
1111 { 1097 SDL_OSX_dlclose (void *handle)
1112 struct dlstatus *dls = handle; 1098 {
1113 dolock(); 1099 struct dlstatus *dls = handle;
1114 resetdlerror(); 1100 dolock ();
1115 if (!isValidStatus(dls)) 1101 resetdlerror ();
1116 { 1102 if (!isValidStatus (dls)) {
1117 goto dlcloseerror; 1103 goto dlcloseerror;
1118 } 1104 }
1119 if (dls->module == MAGIC_DYLIB_MOD) 1105 if (dls->module == MAGIC_DYLIB_MOD) {
1120 { 1106 const char *name;
1121 const char *name; 1107 if (!dls->lib) {
1122 if (!dls->lib) 1108 name = "global context";
1123 { 1109 } else {
1124 name = "global context"; 1110 name = get_lib_name (dls->lib);
1125 } 1111 }
1126 else 1112 warning ("trying to close a .dylib!");
1127 { 1113 error ("Not closing \"%s\" - dynamic libraries cannot be closed",
1128 name = get_lib_name(dls->lib); 1114 name);
1129 } 1115 goto dlcloseerror;
1130 warning("trying to close a .dylib!"); 1116 }
1131 error("Not closing \"%s\" - dynamic libraries cannot be closed", name); 1117 if (!dls->module) {
1132 goto dlcloseerror; 1118 error ("module already closed");
1133 } 1119 goto dlcloseerror;
1134 if (!dls->module) 1120 }
1135 { 1121
1136 error("module already closed"); 1122 if (dls->refs == 1) {
1137 goto dlcloseerror; 1123 unsigned long options = 0;
1138 } 1124 void (*fini) (void);
1139 1125 if ((fini = dlsymIntern (dls, "__fini", 0))) {
1140 if (dls->refs == 1) 1126 debug ("calling _fini()");
1141 { 1127 fini ();
1142 unsigned long options = 0; 1128 }
1143 void (*fini) (void); 1129 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 1130 #ifdef RTLD_NODELETE
1151 if (isFlagSet(dls->mode, RTLD_NODELETE)) 1131 if (isFlagSet (dls->mode, RTLD_NODELETE))
1152 options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; 1132 options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
1153 #endif 1133 #endif
1154 if (!NSUnLinkModule(dls->module, options)) 1134 if (!NSUnLinkModule (dls->module, options)) {
1155 { 1135 error ("unable to unlink module");
1156 error("unable to unlink module"); 1136 goto dlcloseerror;
1157 goto dlcloseerror; 1137 }
1158 } 1138 dls->refs--;
1159 dls->refs--; 1139 dls->module = 0;
1160 dls->module = 0; 1140 /* Note: the dlstatus struct dls is neither removed from the list
1161 /* Note: the dlstatus struct dls is neither removed from the list 1141 * 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 1142 * problem in mostly all cases, though.
1163 * problem in mostly all cases, though. 1143 */
1164 */ 1144 }
1165 } 1145 dounlock ();
1166 dounlock(); 1146 return 0;
1167 return 0;
1168 dlcloseerror: 1147 dlcloseerror:
1169 dounlock(); 1148 dounlock ();
1170 return 1; 1149 return 1;
1171 } 1150 }
1172 1151
1173 static const char *SDL_OSX_dlerror(void) 1152 static const char *
1174 { 1153 SDL_OSX_dlerror (void)
1175 struct dlthread *tss; 1154 {
1176 const char * err_str = NULL; 1155 struct dlthread *tss;
1177 dlcompat_init_check(); 1156 const char *err_str = NULL;
1178 tss = pthread_getspecific(dlerror_key); 1157 dlcompat_init_check ();
1179 if (tss != NULL && tss->errset != 0) { 1158 tss = pthread_getspecific (dlerror_key);
1180 tss->errset = 0; 1159 if (tss != NULL && tss->errset != 0) {
1181 err_str = tss->errstr; 1160 tss->errset = 0;
1182 } 1161 err_str = tss->errstr;
1183 return (err_str); 1162 }
1163 return (err_str);
1184 } 1164 }
1185 1165
1186 /* Given an address, return the mach_header for the image containing it 1166 /* 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. 1167 * or zero if the given address is not contained in any loaded images.
1188 */ 1168 */
1189 static const struct mach_header *image_for_address(const void *address) 1169 static const struct mach_header *
1190 { 1170 image_for_address (const void *address)
1191 unsigned long i; 1171 {
1192 unsigned long j; 1172 unsigned long i;
1193 unsigned long count = _dyld_image_count(); 1173 unsigned long j;
1194 const struct mach_header *mh = 0; 1174 unsigned long count = _dyld_image_count ();
1195 struct load_command *lc = 0; 1175 const struct mach_header *mh = 0;
1196 unsigned long addr = 0; 1176 struct load_command *lc = 0;
1197 for (i = 0; i < count; i++) 1177 unsigned long addr = 0;
1198 { 1178 for (i = 0; i < count; i++) {
1199 addr = (unsigned long)address - _dyld_get_image_vmaddr_slide(i); 1179 addr = (unsigned long) address - _dyld_get_image_vmaddr_slide (i);
1200 mh = _dyld_get_image_header(i); 1180 mh = _dyld_get_image_header (i);
1201 if (mh) 1181 if (mh) {
1202 { 1182 lc = (struct load_command *) ((char *) mh +
1203 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); 1183 sizeof (struct mach_header));
1204 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) 1184 for (j = 0; j < mh->ncmds;
1205 { 1185 j++, lc =
1206 if (LC_SEGMENT == lc->cmd && 1186 (struct load_command *) ((char *) lc + lc->cmdsize)) {
1207 addr >= ((struct segment_command *)lc)->vmaddr && 1187 if (LC_SEGMENT == lc->cmd &&
1208 addr < 1188 addr >= ((struct segment_command *) lc)->vmaddr &&
1209 ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) 1189 addr <
1210 { 1190 ((struct segment_command *) lc)->vmaddr +
1211 goto image_found; 1191 ((struct segment_command *) lc)->vmsize) {
1212 } 1192 goto image_found;
1213 } 1193 }
1214 } 1194 }
1215 mh = 0; 1195 }
1216 } 1196 mh = 0;
1197 }
1217 image_found: 1198 image_found:
1218 return mh; 1199 return mh;
1219 } 1200 }
1220 1201
1221 #if 0 /* unused */ 1202 #if 0 /* unused */
1222 static int SDL_OSX_dladdr(const void * dl_restrict p, SDL_OSX_Dl_info * dl_restrict info) 1203 static int
1204 SDL_OSX_dladdr (const void *dl_restrict p, SDL_OSX_Dl_info * dl_restrict info)
1223 { 1205 {
1224 /* 1206 /*
1225 FIXME: USe the routine image_for_address. 1207 FIXME: USe the routine image_for_address.
1226 */ 1208 */
1227 unsigned long i; 1209 unsigned long i;
1228 unsigned long j; 1210 unsigned long j;
1229 unsigned long count = _dyld_image_count(); 1211 unsigned long count = _dyld_image_count ();
1230 struct mach_header *mh = 0; 1212 struct mach_header *mh = 0;
1231 struct load_command *lc = 0; 1213 struct load_command *lc = 0;
1232 unsigned long addr = NULL; 1214 unsigned long addr = NULL;
1233 unsigned long table_off = (unsigned long)0; 1215 unsigned long table_off = (unsigned long) 0;
1234 int found = 0; 1216 int found = 0;
1235 if (!info) 1217 if (!info)
1236 return 0; 1218 return 0;
1237 dolock(); 1219 dolock ();
1238 resetdlerror(); 1220 resetdlerror ();
1239 info->dli_fname = 0; 1221 info->dli_fname = 0;
1240 info->dli_fbase = 0; 1222 info->dli_fbase = 0;
1241 info->dli_sname = 0; 1223 info->dli_sname = 0;
1242 info->dli_saddr = 0; 1224 info->dli_saddr = 0;
1243 /* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com> 1225 /* 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 1226 * to darwin-development AT lists DOT apple DOT com and slightly modified
1245 */ 1227 */
1246 for (i = 0; i < count; i++) 1228 for (i = 0; i < count; i++) {
1247 { 1229 addr = (unsigned long) p - _dyld_get_image_vmaddr_slide (i);
1248 addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i); 1230 mh = _dyld_get_image_header (i);
1249 mh = _dyld_get_image_header(i); 1231 if (mh) {
1250 if (mh) 1232 lc = (struct load_command *) ((char *) mh +
1251 { 1233 sizeof (struct mach_header));
1252 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); 1234 for (j = 0; j < mh->ncmds;
1253 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) 1235 j++, lc =
1254 { 1236 (struct load_command *) ((char *) lc + lc->cmdsize)) {
1255 if (LC_SEGMENT == lc->cmd && 1237 if (LC_SEGMENT == lc->cmd &&
1256 addr >= ((struct segment_command *)lc)->vmaddr && 1238 addr >= ((struct segment_command *) lc)->vmaddr &&
1257 addr < 1239 addr <
1258 ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) 1240 ((struct segment_command *) lc)->vmaddr +
1259 { 1241 ((struct segment_command *) lc)->vmsize) {
1260 info->dli_fname = _dyld_get_image_name(i); 1242 info->dli_fname = _dyld_get_image_name (i);
1261 info->dli_fbase = (void *)mh; 1243 info->dli_fbase = (void *) mh;
1262 found = 1; 1244 found = 1;
1263 break; 1245 break;
1264 } 1246 }
1265 } 1247 }
1266 if (found) 1248 if (found)
1267 break; 1249 break;
1268 } 1250 }
1269 } 1251 }
1270 if (!found) 1252 if (!found) {
1271 { 1253 dounlock ();
1272 dounlock(); 1254 return 0;
1273 return 0; 1255 }
1274 } 1256 lc = (struct load_command *) ((char *) mh + sizeof (struct mach_header));
1275 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); 1257 for (j = 0; j < mh->ncmds;
1276 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) 1258 j++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) {
1277 { 1259 if (LC_SEGMENT == lc->cmd) {
1278 if (LC_SEGMENT == lc->cmd) 1260 if (!SDL_strcmp
1279 { 1261 (((struct segment_command *) lc)->segname, "__LINKEDIT"))
1280 if (!SDL_strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT")) 1262 break;
1281 break; 1263 }
1282 } 1264 }
1283 } 1265 table_off =
1284 table_off = 1266 ((unsigned long) ((struct segment_command *) lc)->vmaddr) -
1285 ((unsigned long)((struct segment_command *)lc)->vmaddr) - 1267 ((unsigned long) ((struct segment_command *) lc)->fileoff) +
1286 ((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i); 1268 _dyld_get_image_vmaddr_slide (i);
1287 debug("table off %x", table_off); 1269 debug ("table off %x", table_off);
1288 1270
1289 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); 1271 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)) 1272 for (j = 0; j < mh->ncmds;
1291 { 1273 j++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) {
1292 if (LC_SYMTAB == lc->cmd) 1274 if (LC_SYMTAB == lc->cmd) {
1293 { 1275
1294 1276 struct nlist *symtable =
1295 struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off); 1277 (struct nlist *) (((struct symtab_command *) lc)->symoff +
1296 unsigned long numsyms = ((struct symtab_command *)lc)->nsyms; 1278 table_off);
1297 struct nlist *nearest = NULL; 1279 unsigned long numsyms = ((struct symtab_command *) lc)->nsyms;
1298 unsigned long diff = 0xffffffff; 1280 struct nlist *nearest = NULL;
1299 unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off); 1281 unsigned long diff = 0xffffffff;
1300 debug("symtable %x", symtable); 1282 unsigned long strtable =
1301 for (i = 0; i < numsyms; i++) 1283 (unsigned long) (((struct symtab_command *) lc)->stroff +
1302 { 1284 table_off);
1303 /* Ignore the following kinds of Symbols */ 1285 debug ("symtable %x", symtable);
1304 if ((!symtable->n_value) /* Undefined */ 1286 for (i = 0; i < numsyms; i++) {
1305 || (symtable->n_type >= N_PEXT) /* Debug symbol */ 1287 /* Ignore the following kinds of Symbols */
1306 || (!(symtable->n_type & N_EXT)) /* Local Symbol */ 1288 if ((!symtable->n_value) /* Undefined */
1307 ) 1289 ||(symtable->n_type >= N_PEXT) /* Debug symbol */
1308 { 1290 ||(!(symtable->n_type & N_EXT)) /* Local Symbol */
1309 symtable++; 1291 ) {
1310 continue; 1292 symtable++;
1311 } 1293 continue;
1312 if ((addr >= symtable->n_value) && (diff >= (symtable->n_value - addr))) 1294 }
1313 { 1295 if ((addr >= symtable->n_value)
1314 diff = (unsigned long)symtable->n_value - addr; 1296 && (diff >= (symtable->n_value - addr))) {
1315 nearest = symtable; 1297 diff = (unsigned long) symtable->n_value - addr;
1316 } 1298 nearest = symtable;
1317 symtable++; 1299 }
1318 } 1300 symtable++;
1319 if (nearest) 1301 }
1320 { 1302 if (nearest) {
1321 info->dli_saddr = nearest->n_value + ((void *)p - addr); 1303 info->dli_saddr = nearest->n_value + ((void *) p - addr);
1322 info->dli_sname = (char *)(strtable + nearest->n_un.n_strx); 1304 info->dli_sname = (char *) (strtable + nearest->n_un.n_strx);
1323 } 1305 }
1324 } 1306 }
1325 } 1307 }
1326 dounlock(); 1308 dounlock ();
1327 return 1; 1309 return 1;
1328 } 1310 }
1329 #endif 1311 #endif
1330 1312
1331 /* 1313 /*
1332 * Implement the dlfunc() interface, which behaves exactly the same as 1314 * Implement the dlfunc() interface, which behaves exactly the same as
1335 * about undefined behavior, and is intended as prior art for future 1317 * about undefined behavior, and is intended as prior art for future
1336 * POSIX standardization. This function requires that all pointer types 1318 * POSIX standardization. This function requires that all pointer types
1337 * have the same representation, which is true on all platforms FreeBSD 1319 * have the same representation, which is true on all platforms FreeBSD
1338 * runs on, but is not guaranteed by the C standard. 1320 * runs on, but is not guaranteed by the C standard.
1339 */ 1321 */
1340 #if 0 1322 #if 0
1341 static dlfunc_t SDL_OSX_dlfunc(void * dl_restrict handle, const char * dl_restrict symbol) 1323 static dlfunc_t
1342 { 1324 SDL_OSX_dlfunc (void *dl_restrict handle, const char *dl_restrict symbol)
1343 union 1325 {
1344 { 1326 union
1345 void *d; 1327 {
1346 dlfunc_t f; 1328 void *d;
1347 } rv; 1329 dlfunc_t f;
1348 int sym_len = SDL_strlen(symbol); 1330 } rv;
1349 char *malloc_sym = NULL; 1331 int sym_len = SDL_strlen (symbol);
1350 dolock(); 1332 char *malloc_sym = NULL;
1351 malloc_sym = SDL_malloc(sym_len + 2); 1333 dolock ();
1352 if (malloc_sym) 1334 malloc_sym = SDL_malloc (sym_len + 2);
1353 { 1335 if (malloc_sym) {
1354 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); 1336 SDL_snprintf (malloc_sym, sym_len + 2, "_%s", symbol);
1355 rv.d = dlsymIntern(handle, malloc_sym, 1); 1337 rv.d = dlsymIntern (handle, malloc_sym, 1);
1356 SDL_free(malloc_sym); 1338 SDL_free (malloc_sym);
1357 } 1339 } else {
1358 else 1340 error ("Unable to allocate memory");
1359 { 1341 goto dlfuncerror;
1360 error("Unable to allocate memory"); 1342 }
1361 goto dlfuncerror; 1343 dounlock ();
1362 } 1344 return rv.f;
1363 dounlock();
1364 return rv.f;
1365 dlfuncerror: 1345 dlfuncerror:
1366 dounlock(); 1346 dounlock ();
1367 return NULL; 1347 return NULL;
1368 } 1348 }
1369 #endif 1349 #endif
1370 1350
1371 1351
1372 1352
1376 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1356 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1377 /* System dependent library loading routines */ 1357 /* System dependent library loading routines */
1378 1358
1379 #include "SDL_loadso.h" 1359 #include "SDL_loadso.h"
1380 1360
1381 void *SDL_LoadObject(const char *sofile) 1361 void *
1382 { 1362 SDL_LoadObject (const char *sofile)
1383 void *handle = SDL_OSX_dlopen(sofile, RTLD_NOW); 1363 {
1384 const char *loaderror = SDL_OSX_dlerror(); 1364 void *handle = SDL_OSX_dlopen (sofile, RTLD_NOW);
1385 if ( handle == NULL ) { 1365 const char *loaderror = SDL_OSX_dlerror ();
1386 SDL_SetError("Failed loading %s: %s", sofile, loaderror); 1366 if (handle == NULL) {
1387 } 1367 SDL_SetError ("Failed loading %s: %s", sofile, loaderror);
1388 return(handle); 1368 }
1389 } 1369 return (handle);
1390 1370 }
1391 void *SDL_LoadFunction(void *handle, const char *name) 1371
1392 { 1372 void *
1393 void *symbol = SDL_OSX_dlsym(handle, name); 1373 SDL_LoadFunction (void *handle, const char *name)
1394 if ( symbol == NULL ) { 1374 {
1395 SDL_SetError("Failed loading %s: %s", name, SDL_OSX_dlerror()); 1375 void *symbol = SDL_OSX_dlsym (handle, name);
1396 } 1376 if (symbol == NULL) {
1397 return(symbol); 1377 SDL_SetError ("Failed loading %s: %s", name, SDL_OSX_dlerror ());
1398 } 1378 }
1399 1379 return (symbol);
1400 void SDL_UnloadObject(void *handle) 1380 }
1401 { 1381
1402 if ( handle != NULL ) { 1382 void
1403 SDL_OSX_dlclose(handle); 1383 SDL_UnloadObject (void *handle)
1404 } 1384 {
1385 if (handle != NULL) {
1386 SDL_OSX_dlclose (handle);
1387 }
1405 } 1388 }
1406 1389
1407 #endif /* SDL_LOADSO_DLCOMPAT */ 1390 #endif /* SDL_LOADSO_DLCOMPAT */
1391 /* vi: set ts=4 sw=4 expandtab: */