~ubuntu-branches/ubuntu/karmic/mpg123/karmic

« back to all changes in this revision

Viewing changes to libltdl/loaders/dyld.c

  • Committer: Bazaar Package Importer
  • Author(s): César Muñoz Albitres
  • Date: 2009-05-03 17:55:27 UTC
  • mfrom: (6.2.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090503175527-z94edsnxmiccxpy8
Tags: 1.7.2-3ubuntu1
* Merge from debian unstable, remaining changes:
  - Remove arts from dependencies

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* loader-dyld.c -- dynamic linking on darwin and OS X
 
2
 
 
3
   Copyright (C) 1998, 1999, 2000, 2004, 2006,
 
4
                 2007, 2008 Free Software Foundation, Inc.
 
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
 
26
License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
 
27
copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
 
28
or obtained by writing to the Free Software Foundation, Inc.,
 
29
51 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
 
 
41
LT_BEGIN_C_DECLS
 
42
LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
 
43
LT_END_C_DECLS
 
44
 
 
45
 
 
46
/* Boilerplate code to set up the vtable for hooking this loader into
 
47
   libltdl's loader list:  */
 
48
static int       vl_init  (lt_user_data loader_data);
 
49
static int       vl_exit  (lt_user_data loader_data);
 
50
static lt_module vm_open  (lt_user_data loader_data, const char *filename,
 
51
                           lt_dladvise advise);
 
52
static int       vm_close (lt_user_data loader_data, lt_module module);
 
53
static void *    vm_sym   (lt_user_data loader_data, lt_module module,
 
54
                          const char *symbolname);
 
55
 
 
56
static 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.  */
 
61
lt_dlvtable *
 
62
get_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
 
 
96
#if defined(HAVE_MACH_O_DYLD_H)
 
97
#  if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
 
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 */
 
107
#if !defined(ENUM_DYLD_BOOL)
 
108
# define ENUM_DYLD_BOOL
 
109
# undef FALSE
 
110
# undef TRUE
 
111
 enum DYLD_BOOL {
 
112
    FALSE,
 
113
    TRUE
 
114
 };
 
115
#endif
 
116
#if !defined(LC_REQ_DYLD)
 
117
# define LC_REQ_DYLD 0x80000000
 
118
#endif
 
119
#if !defined(LC_LOAD_WEAK_DYLIB)
 
120
# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
 
121
#endif
 
122
 
 
123
#if !defined(NSADDIMAGE_OPTION_NONE)
 
124
#  define NSADDIMAGE_OPTION_NONE                          0x0
 
125
#endif
 
126
#if !defined(NSADDIMAGE_OPTION_RETURN_ON_ERROR)
 
127
#  define NSADDIMAGE_OPTION_RETURN_ON_ERROR               0x1
 
128
#endif
 
129
#if !defined(NSADDIMAGE_OPTION_WITH_SEARCHING)
 
130
#  define NSADDIMAGE_OPTION_WITH_SEARCHING                0x2
 
131
#endif
 
132
#if !defined(NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED)
 
133
#  define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED         0x4
 
134
#endif
 
135
#if !defined(NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME)
 
136
#  define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
 
137
#endif
 
138
 
 
139
#if !defined(NSLOOKUPSYMBOLINIMAGE_OPTION_BIND)
 
140
#  define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND               0x0
 
141
#endif
 
142
#if !defined(NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW)
 
143
#  define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW           0x1
 
144
#endif
 
145
#if !defined(NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY)
 
146
#  define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY         0x2
 
147
#endif
 
148
#if !defined(NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR)
 
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
 
 
155
#if defined(__BIG_ENDIAN__)
 
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
 
 
164
typedef struct mach_header mach_header;
 
165
typedef struct dylib_command dylib_command;
 
166
 
 
167
static const char *dylderror (const char *errmsg);
 
168
static const mach_header *lt__nsmodule_get_header (NSModule module);
 
169
static const char *lt__header_get_instnam (const mach_header *mh);
 
170
static const mach_header *lt__match_loadedlib (const char *name);
 
171
static NSSymbol lt__linkedlib_symbol (const char *symname, const mach_header *mh);
 
172
 
 
173
static const mach_header *(*lt__addimage)       (const char *image_name,
 
174
                                                 unsigned long options) = 0;
 
175
static NSSymbol (*lt__image_symbol)             (const mach_header *image,
 
176
                                                 const char *symbolName,
 
177
                                                 unsigned long options) = 0;
 
178
static enum DYLD_BOOL (*lt__image_symbol_p)     (const mach_header *image,
 
179
                                                 const char *symbolName) = 0;
 
180
static enum DYLD_BOOL (*lt__module_export)      (NSModule module) = 0;
 
181
 
 
182
static 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.  */
 
187
static int
 
188
vl_exit (lt_user_data LT__UNUSED loader_data)
 
189
{
 
190
  vtable = NULL;
 
191
  return 0;
 
192
}
 
193
 
 
194
/* A function called through the vtable to initialise this loader.  */
 
195
static int
 
196
vl_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.  */
 
227
static lt_module
 
228
vm_open (lt_user_data loader_data, const char *filename,
 
229
         lt_dladvise LT__UNUSED advise)
 
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
 
243
                                            | NSLINKMODULE_OPTION_PRIVATE
 
244
                                            | NSLINKMODULE_OPTION_BINDNOW);
 
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.  */
 
280
static int
 
281
vm_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
            }
 
305
#if defined(__ppc__)
 
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.  */
 
321
static void *
 
322
vm_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
    {
 
353
      strncpy (saveError, dylderror (LT__STRERROR (SYMBOL_NOT_FOUND)), 255);
 
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. */
 
377
static const char *
 
378
dylderror (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. */
 
396
static const mach_header *
 
397
lt__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.  */
 
423
static const char *
 
424
lt__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
 
 
446
static const mach_header *
 
447
lt__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. */
 
469
static NSSymbol
 
470
lt__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
}