Annotation of parser3/src/lib/ltdl/loaders/dyld.c, revision 1.2
1.1 moko 1: /* loader-dyld.c -- dynamic linking on darwin and OS X
2:
1.2 ! moko 3: Copyright (C) 1998-2000, 2004, 2006-2008, 2011-2019, 2021-2024 Free
! 4: Software Foundation, Inc.
1.1 moko 5: Written by Peter O'Gorman, 1998
6:
7: NOTE: The canonical source of this file is maintained with the
8: GNU Libtool package. Report bugs to bug-libtool@gnu.org.
9:
10: GNU Libltdl is free software; you can redistribute it and/or
11: modify it under the terms of the GNU Lesser General Public
12: License as published by the Free Software Foundation; either
13: version 2 of the License, or (at your option) any later version.
14:
15: As a special exception to the GNU Lesser General Public License,
16: if you distribute this file as part of a program or library that
17: is built using GNU Libtool, you may include this file under the
18: same distribution terms that you use for the rest of that program.
19:
20: GNU Libltdl is distributed in the hope that it will be useful,
21: but WITHOUT ANY WARRANTY; without even the implied warranty of
22: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23: GNU Lesser General Public License for more details.
24:
25: You should have received a copy of the GNU Lesser General Public
1.2 ! moko 26: License along with GNU Libltdl. If not, see <https://www.gnu.org/licenses/>.
1.1 moko 27: */
28:
29: #include "lt__private.h"
30: #include "lt_dlloader.h"
31:
32: /* Use the preprocessor to rename non-static symbols to avoid namespace
33: collisions when the loader code is statically linked into libltdl.
34: Use the "<module_name>_LTX_" prefix so that the symbol addresses can
35: be fetched from the preloaded symbol list by lt_dlsym(): */
36: #define get_vtable dyld_LTX_get_vtable
37:
38: LT_BEGIN_C_DECLS
39: LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
40: LT_END_C_DECLS
41:
42:
43: /* Boilerplate code to set up the vtable for hooking this loader into
44: libltdl's loader list: */
45: static int vl_init (lt_user_data loader_data);
46: static int vl_exit (lt_user_data loader_data);
47: static lt_module vm_open (lt_user_data loader_data, const char *filename,
48: lt_dladvise advise);
49: static int vm_close (lt_user_data loader_data, lt_module module);
50: static void * vm_sym (lt_user_data loader_data, lt_module module,
51: const char *symbolname);
52:
53: static lt_dlvtable *vtable = 0;
54:
55: /* Return the vtable for this loader, only the name and sym_prefix
56: attributes (plus the virtual function implementations, obviously)
57: change between loaders. */
58: lt_dlvtable *
59: get_vtable (lt_user_data loader_data)
60: {
61: if (!vtable)
62: {
63: vtable = lt__zalloc (sizeof *vtable);
64: }
65:
66: if (vtable && !vtable->name)
67: {
68: vtable->name = "lt_dyld";
69: vtable->sym_prefix = "_";
70: vtable->dlloader_init = vl_init;
71: vtable->module_open = vm_open;
72: vtable->module_close = vm_close;
73: vtable->find_sym = vm_sym;
74: vtable->dlloader_exit = vl_exit;
75: vtable->dlloader_data = loader_data;
76: vtable->priority = LT_DLLOADER_APPEND;
77: }
78:
79: if (vtable && (vtable->dlloader_data != loader_data))
80: {
81: LT__SETERROR (INIT_LOADER);
82: return 0;
83: }
84:
85: return vtable;
86: }
87:
88:
89:
90: /* --- IMPLEMENTATION --- */
91:
92:
1.2 ! moko 93: #if defined HAVE_MACH_O_DYLD_H
! 94: # if !defined __APPLE_CC__ && !defined __MWERKS__ && !defined __private_extern__
1.1 moko 95: /* Is this correct? Does it still function properly? */
96: # define __private_extern__ extern
97: # endif
98: # include <mach-o/dyld.h>
99: #endif
100:
101: #include <mach-o/getsect.h>
102:
103: /* We have to put some stuff here that isn't in older dyld.h files */
1.2 ! moko 104: #if !defined ENUM_DYLD_BOOL
1.1 moko 105: # define ENUM_DYLD_BOOL
106: # undef FALSE
107: # undef TRUE
108: enum DYLD_BOOL {
109: FALSE,
110: TRUE
111: };
112: #endif
1.2 ! moko 113: #if !defined LC_REQ_DYLD
1.1 moko 114: # define LC_REQ_DYLD 0x80000000
115: #endif
1.2 ! moko 116: #if !defined LC_LOAD_WEAK_DYLIB
1.1 moko 117: # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
118: #endif
119:
1.2 ! moko 120: #if !defined NSADDIMAGE_OPTION_NONE
1.1 moko 121: # define NSADDIMAGE_OPTION_NONE 0x0
122: #endif
1.2 ! moko 123: #if !defined NSADDIMAGE_OPTION_RETURN_ON_ERROR
1.1 moko 124: # define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
125: #endif
1.2 ! moko 126: #if !defined NSADDIMAGE_OPTION_WITH_SEARCHING
1.1 moko 127: # define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
128: #endif
1.2 ! moko 129: #if !defined NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1.1 moko 130: # define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
131: #endif
1.2 ! moko 132: #if !defined NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
1.1 moko 133: # define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
134: #endif
135:
1.2 ! moko 136: #if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1.1 moko 137: # define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
138: #endif
1.2 ! moko 139: #if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1.1 moko 140: # define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
141: #endif
1.2 ! moko 142: #if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
1.1 moko 143: # define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
144: #endif
1.2 ! moko 145: #if !defined NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1.1 moko 146: # define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
147: #endif
148:
149: #define LT__SYMLOOKUP_OPTS (NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW \
150: | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR)
151:
1.2 ! moko 152: #if defined __BIG_ENDIAN__
1.1 moko 153: # define LT__MAGIC MH_MAGIC
154: #else
155: # define LT__MAGIC MH_CIGAM
156: #endif
157:
158: #define DYLD__SETMYERROR(errmsg) LT__SETERRORSTR (dylderror (errmsg))
159: #define DYLD__SETERROR(errcode) DYLD__SETMYERROR (LT__STRERROR (errcode))
160:
161: typedef struct mach_header mach_header;
162: typedef struct dylib_command dylib_command;
163:
164: static const char *dylderror (const char *errmsg);
165: static const mach_header *lt__nsmodule_get_header (NSModule module);
166: static const char *lt__header_get_instnam (const mach_header *mh);
167: static const mach_header *lt__match_loadedlib (const char *name);
168: static NSSymbol lt__linkedlib_symbol (const char *symname, const mach_header *mh);
169:
170: static const mach_header *(*lt__addimage) (const char *image_name,
171: unsigned long options) = 0;
172: static NSSymbol (*lt__image_symbol) (const mach_header *image,
173: const char *symbolName,
174: unsigned long options) = 0;
175: static enum DYLD_BOOL (*lt__image_symbol_p) (const mach_header *image,
176: const char *symbolName) = 0;
177: static enum DYLD_BOOL (*lt__module_export) (NSModule module) = 0;
178:
179: static int dyld_cannot_close = 0;
180:
181:
182: /* A function called through the vtable when this loader is no
183: longer needed by the application. */
184: static int
1.2 ! moko 185: vl_exit (lt_user_data loader_data LT__UNUSED)
1.1 moko 186: {
187: vtable = NULL;
188: return 0;
189: }
190:
191: /* A function called through the vtable to initialise this loader. */
192: static int
193: vl_init (lt_user_data loader_data)
194: {
195: int errors = 0;
196:
197: if (! dyld_cannot_close)
198: {
199: if (!_dyld_present ())
200: {
201: ++errors;
202: }
203: else
204: {
205: (void) _dyld_func_lookup ("__dyld_NSAddImage",
206: (unsigned long*) <__addimage);
207: (void) _dyld_func_lookup ("__dyld_NSLookupSymbolInImage",
208: (unsigned long*)<__image_symbol);
209: (void) _dyld_func_lookup ("__dyld_NSIsSymbolNameDefinedInImage",
210: (unsigned long*) <__image_symbol_p);
211: (void) _dyld_func_lookup ("__dyld_NSMakePrivateModulePublic",
212: (unsigned long*) <__module_export);
213: dyld_cannot_close = lt_dladderror ("can't close a dylib");
214: }
215: }
216:
217: return errors;
218: }
219:
220:
221: /* A function called through the vtable to open a module with this
222: loader. Returns an opaque representation of the newly opened
223: module for processing with this loader's other vtable functions. */
224: static lt_module
225: vm_open (lt_user_data loader_data, const char *filename,
1.2 ! moko 226: lt_dladvise advise LT__UNUSED)
1.1 moko 227: {
228: lt_module module = 0;
229: NSObjectFileImage ofi = 0;
230:
231: if (!filename)
232: {
233: return (lt_module) -1;
234: }
235:
236: switch (NSCreateObjectFileImageFromFile (filename, &ofi))
237: {
238: case NSObjectFileImageSuccess:
239: module = NSLinkModule (ofi, filename, NSLINKMODULE_OPTION_RETURN_ON_ERROR
1.2 ! moko 240: | NSLINKMODULE_OPTION_PRIVATE
! 241: | NSLINKMODULE_OPTION_BINDNOW);
1.1 moko 242: NSDestroyObjectFileImage (ofi);
243:
244: if (module)
245: {
246: lt__module_export (module);
247: }
248: break;
249:
250: case NSObjectFileImageInappropriateFile:
251: if (lt__image_symbol_p && lt__image_symbol)
252: {
253: module = (lt_module) lt__addimage(filename,
254: NSADDIMAGE_OPTION_RETURN_ON_ERROR);
255: }
256: break;
257:
258: case NSObjectFileImageFailure:
259: case NSObjectFileImageArch:
260: case NSObjectFileImageFormat:
261: case NSObjectFileImageAccess:
262: /*NOWORK*/
263: break;
264: }
265:
266: if (!module)
267: {
268: DYLD__SETERROR (CANNOT_OPEN);
269: }
270:
271: return module;
272: }
273:
274:
275: /* A function called through the vtable when a particular module
276: should be unloaded. */
277: static int
278: vm_close (lt_user_data loader_data, lt_module module)
279: {
280: int errors = 0;
281:
282: if (module != (lt_module) -1)
283: {
284: const mach_header *mh = (const mach_header *) module;
285: int flags = 0;
286: if (mh->magic == LT__MAGIC)
287: {
288: lt_dlseterror (dyld_cannot_close);
289: ++errors;
290: }
291: else
292: {
293: /* Currently, if a module contains c++ static destructors and it
294: is unloaded, we get a segfault in atexit(), due to compiler and
295: dynamic loader differences of opinion, this works around that. */
296: if ((const struct section *) NULL !=
297: getsectbynamefromheader (lt__nsmodule_get_header (module),
298: "__DATA", "__mod_term_func"))
299: {
300: flags |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
301: }
1.2 ! moko 302: #if defined __ppc__
1.1 moko 303: flags |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
304: #endif
305: if (!NSUnLinkModule (module, flags))
306: {
307: DYLD__SETERROR (CANNOT_CLOSE);
308: ++errors;
309: }
310: }
311: }
312:
313: return errors;
314: }
315:
316: /* A function called through the vtable to get the address of
317: a symbol loaded from a particular module. */
318: static void *
319: vm_sym (lt_user_data loader_data, lt_module module, const char *name)
320: {
321: NSSymbol *nssym = 0;
322: const mach_header *mh = (const mach_header *) module;
323: char saveError[256] = "Symbol not found";
324:
325: if (module == (lt_module) -1)
326: {
327: void *address, *unused;
328: _dyld_lookup_and_bind (name, (unsigned long*) &address, &unused);
329: return address;
330: }
331:
332: if (mh->magic == LT__MAGIC)
333: {
334: if (lt__image_symbol_p && lt__image_symbol)
335: {
336: if (lt__image_symbol_p (mh, name))
337: {
338: nssym = lt__image_symbol (mh, name, LT__SYMLOOKUP_OPTS);
339: }
340: }
341:
342: }
343: else
344: {
345: nssym = NSLookupSymbolInModule (module, name);
346: }
347:
348: if (!nssym)
349: {
1.2 ! moko 350: strlcpy (saveError, dylderror (LT__STRERROR (SYMBOL_NOT_FOUND)), 255);
1.1 moko 351: saveError[255] = 0;
352: if (!mh)
353: {
354: mh = (mach_header *)lt__nsmodule_get_header (module);
355: }
356: nssym = lt__linkedlib_symbol (name, mh);
357: }
358:
359: if (!nssym)
360: {
361: LT__SETERRORSTR (saveError);
362: }
363:
364: return nssym ? NSAddressOfSymbol (nssym) : 0;
365: }
366:
367:
368:
369:
370: /* --- HELPER FUNCTIONS --- */
371:
372:
373: /* Return the dyld error string, or the passed in error string if none. */
374: static const char *
375: dylderror (const char *errmsg)
376: {
377: NSLinkEditErrors ler;
378: int lerno;
379: const char *file;
380: const char *errstr;
381:
382: NSLinkEditError (&ler, &lerno, &file, &errstr);
383:
384: if (! (errstr && *errstr))
385: {
386: errstr = errmsg;
387: }
388:
389: return errstr;
390: }
391:
392: /* There should probably be an apple dyld api for this. */
393: static const mach_header *
394: lt__nsmodule_get_header (NSModule module)
395: {
396: int i = _dyld_image_count();
397: const char *modname = NSNameOfModule (module);
398: const mach_header *mh = 0;
399:
400: if (!modname)
401: return NULL;
402:
403: while (i > 0)
404: {
405: --i;
406: if (strneq (_dyld_get_image_name (i), modname))
407: {
408: mh = _dyld_get_image_header (i);
409: break;
410: }
411: }
412:
413: return mh;
414: }
415:
416: /* NSAddImage is also used to get the loaded image, but it only works if
417: the lib is installed, for uninstalled libs we need to check the
418: install_names against each other. Note that this is still broken if
419: DYLD_IMAGE_SUFFIX is set and a different lib was loaded as a result. */
420: static const char *
421: lt__header_get_instnam (const mach_header *mh)
422: {
423: unsigned long offset = sizeof(mach_header);
424: const char* result = 0;
425: int j;
426:
427: for (j = 0; j < mh->ncmds; j++)
428: {
429: struct load_command *lc;
430:
431: lc = (struct load_command*) (((unsigned long) mh) + offset);
432: if (LC_ID_DYLIB == lc->cmd)
433: {
434: result=(char*)(((dylib_command*) lc)->dylib.name.offset +
435: (unsigned long) lc);
436: }
437: offset += lc->cmdsize;
438: }
439:
440: return result;
441: }
442:
443: static const mach_header *
444: lt__match_loadedlib (const char *name)
445: {
446: const mach_header *mh = 0;
447: int i = _dyld_image_count();
448:
449: while (i > 0)
450: {
451: const char *id;
452:
453: --i;
454: id = lt__header_get_instnam (_dyld_get_image_header (i));
455: if (id && strneq (id, name))
456: {
457: mh = _dyld_get_image_header (i);
458: break;
459: }
460: }
461:
462: return mh;
463: }
464:
465: /* Safe to assume our mh is good. */
466: static NSSymbol
467: lt__linkedlib_symbol (const char *symname, const mach_header *mh)
468: {
469: NSSymbol symbol = 0;
470:
471: if (lt__image_symbol && NSIsSymbolNameDefined (symname))
472: {
473: unsigned long offset = sizeof(mach_header);
474: struct load_command *lc;
475: int j;
476:
477: for (j = 0; j < mh->ncmds; j++)
478: {
479: lc = (struct load_command*) (((unsigned long) mh) + offset);
480: if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
481: {
482: unsigned long base = ((dylib_command *) lc)->dylib.name.offset;
483: char *name = (char *) (base + (unsigned long) lc);
484: const mach_header *mh1 = lt__match_loadedlib (name);
485:
486: if (!mh1)
487: {
488: /* Maybe NSAddImage can find it */
489: mh1 = lt__addimage (name,
490: NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
491: | NSADDIMAGE_OPTION_WITH_SEARCHING
492: | NSADDIMAGE_OPTION_RETURN_ON_ERROR);
493: }
494:
495: if (mh1)
496: {
497: symbol = lt__image_symbol (mh1, symname, LT__SYMLOOKUP_OPTS);
498: if (symbol)
499: break;
500: }
501: }
502:
503: offset += lc->cmdsize;
504: }
505: }
506:
507: return symbol;
508: }
E-mail: