source: squid-ssl/trunk/fuentes/libltdl/loaders/dyld.c @ 5496

Last change on this file since 5496 was 5496, checked in by Juanma, 23 months ago

Initial release

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