~ubuntu-branches/ubuntu/vivid/mpich/vivid-proposed

« back to all changes in this revision

Viewing changes to src/pm/hydra/tools/topo/hwloc/hwloc/src/libltdl/loaders/dyld.c

  • Committer: Package Import Robot
  • Author(s): Anton Gladky
  • Date: 2014-04-01 20:24:20 UTC
  • mfrom: (5.2.4 sid)
  • Revision ID: package-import@ubuntu.com-20140401202420-t5ey1ia2klt5dkq3
Tags: 3.1-4
* [c3e3398] Disable test_primitives, which is unreliable on some platforms.
            (Closes: #743047)
* [265a699] Add minimal autotest.

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
 
}