OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [linux/] [dl/] [dl-deps.c] - Blame information for rev 438

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/* Load the dependencies of a mapped object.
2
   Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
3
   This file is part of the GNU C Library.
4
 
5
   The GNU C Library is free software; you can redistribute it and/or
6
   modify it under the terms of the GNU Lesser General Public
7
   License as published by the Free Software Foundation; either
8
   version 2.1 of the License, or (at your option) any later version.
9
 
10
   The GNU C Library is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
   Lesser General Public License for more details.
14
 
15
   You should have received a copy of the GNU Lesser General Public
16
   License along with the GNU C Library; if not, write to the Free
17
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18
   02111-1307 USA.  */
19
 
20
#include <assert.h>
21
#include <dlfcn.h>
22
#include <errno.h>
23
#include <libintl.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <unistd.h>
27
#include <sys/param.h>
28
#include <ldsodefs.h>
29
 
30
#include <dl-dst.h>
31
 
32
/* Whether an shared object references one or more auxiliary objects
33
   is signaled by the AUXTAG entry in l_info.  */
34
#define AUXTAG  (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
35
                 + DT_EXTRATAGIDX (DT_AUXILIARY))
36
/* Whether an shared object references one or more auxiliary objects
37
   is signaled by the AUXTAG entry in l_info.  */
38
#define FILTERTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
39
                   + DT_EXTRATAGIDX (DT_FILTER))
40
 
41
/* This is zero at program start to signal that the global scope map is
42
   allocated by rtld.  Later it keeps the size of the map.  It might be
43
   reset if in _dl_close if the last global object is removed.  */
44
size_t _dl_global_scope_alloc;
45
 
46
extern size_t _dl_platformlen;
47
 
48
/* When loading auxiliary objects we must ignore errors.  It's ok if
49
   an object is missing.  */
50
struct openaux_args
51
  {
52
    /* The arguments to openaux.  */
53
    struct link_map *map;
54
    int trace_mode;
55
    const char *strtab;
56
    const char *name;
57
 
58
    /* The return value of openaux.  */
59
    struct link_map *aux;
60
  };
61
 
62
static void
63
openaux (void *a)
64
{
65
  struct openaux_args *args = (struct openaux_args *) a;
66
 
67
  args->aux = _dl_map_object (args->map, args->name, 0,
68
                              (args->map->l_type == lt_executable
69
                               ? lt_library : args->map->l_type),
70
                              args->trace_mode, 0);
71
}
72
 
73
 
74
 
75
/* We use a very special kind of list to track the path
76
   through the list of loaded shared objects.  We have to
77
   produce a flat list with unique members of all involved objects.
78
*/
79
struct list
80
  {
81
    int done;                   /* Nonzero if this map was processed.  */
82
    struct link_map *map;       /* The data.  */
83
    struct list *next;  /* Elements for normal list.  */
84
  };
85
 
86
 
87
/* Macro to expand DST.  It is an macro since we use `alloca'.  */
88
#define expand_dst(l, str, fatal) \
89
  ({                                                                          \
90
    const char *__str = (str);                                                \
91
    const char *__result = __str;                                             \
92
    size_t __cnt = DL_DST_COUNT(__str, 0);                                     \
93
                                                                              \
94
    if (__cnt != 0)                                                            \
95
      {                                                                       \
96
        char *__newp;                                                         \
97
                                                                              \
98
        __newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str),  \
99
                                                   __cnt));                   \
100
                                                                              \
101
        __result = DL_DST_SUBSTITUTE (l, __str, __newp, 0);                    \
102
                                                                              \
103
        if (*__result == '\0')                                                \
104
          {                                                                   \
105
            /* The replacement for the DST is not known.  We can't            \
106
               processed.  */                                                 \
107
            if (fatal)                                                        \
108
              _dl_signal_error (0, __str, NULL, N_("\
109
empty dynamics string token substitution"));                                  \
110
            else                                                              \
111
              {                                                               \
112
                /* This is for DT_AUXILIARY.  */                              \
113
                if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0))     \
114
                  _dl_debug_printf ("cannot load auxiliary `%s' because of"   \
115
                                    "empty dynamic string token "             \
116
                                    "substitution\n", __str);                 \
117
                continue;                                                     \
118
              }                                                               \
119
          }                                                                   \
120
      }                                                                       \
121
                                                                              \
122
    __result; })
123
 
124
 
125
void
126
internal_function
127
_dl_map_object_deps (struct link_map *map,
128
                     struct link_map **preloads, unsigned int npreloads,
129
                     int trace_mode)
130
{
131
  struct list known[1 + npreloads + 1];
132
  struct list *runp, *tail;
133
  unsigned int nlist, i;
134
  /* Object name.  */
135
  const char *name;
136
  int errno_saved;
137
  int errno_reason;
138
  const char *errstring;
139
  const char *objname;
140
 
141
  auto inline void preload (struct link_map *map);
142
 
143
  inline void preload (struct link_map *map)
144
    {
145
      known[nlist].done = 0;
146
      known[nlist].map = map;
147
      known[nlist].next = &known[nlist + 1];
148
 
149
      ++nlist;
150
      /* We use `l_reserved' as a mark bit to detect objects we have
151
         already put in the search list and avoid adding duplicate
152
         elements later in the list.  */
153
      map->l_reserved = 1;
154
    }
155
 
156
  /* No loaded object so far.  */
157
  nlist = 0;
158
 
159
  /* First load MAP itself.  */
160
  preload (map);
161
 
162
  /* Add the preloaded items after MAP but before any of its dependencies.  */
163
  for (i = 0; i < npreloads; ++i)
164
    preload (preloads[i]);
165
 
166
  /* Terminate the lists.  */
167
  known[nlist - 1].next = NULL;
168
 
169
  /* Pointer to last unique object.  */
170
  tail = &known[nlist - 1];
171
 
172
  /* Process each element of the search list, loading each of its
173
     auxiliary objects and immediate dependencies.  Auxiliary objects
174
     will be added in the list before the object itself and
175
     dependencies will be appended to the list as we step through it.
176
     This produces a flat, ordered list that represents a
177
     breadth-first search of the dependency tree.
178
 
179
     The whole process is complicated by the fact that we better
180
     should use alloca for the temporary list elements.  But using
181
     alloca means we cannot use recursive function calls.  */
182
  errno_saved = errno;
183
  errno_reason = 0;
184
  errstring = NULL;
185
  errno = 0;
186
  name = NULL;
187
  for (runp = known; runp; )
188
    {
189
      struct link_map *l = runp->map;
190
      struct link_map **needed = NULL;
191
      unsigned int nneeded = 0;
192
 
193
      /* Unless otherwise stated, this object is handled.  */
194
      runp->done = 1;
195
 
196
      /* Allocate a temporary record to contain the references to the
197
         dependencies of this object.  */
198
      if (l->l_searchlist.r_list == NULL && l->l_initfini == NULL
199
          && l != map && l->l_ldnum > 0)
200
        needed = (struct link_map **) alloca (l->l_ldnum
201
                                              * sizeof (struct link_map *));
202
 
203
      if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG])
204
        {
205
          const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
206
          struct openaux_args args;
207
          struct list *orig;
208
          const ElfW(Dyn) *d;
209
 
210
          args.strtab = strtab;
211
          args.map = l;
212
          args.trace_mode = trace_mode;
213
          orig = runp;
214
 
215
          for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
216
            if (__builtin_expect (d->d_tag, DT_NEEDED) == DT_NEEDED)
217
              {
218
                /* Map in the needed object.  */
219
                struct link_map *dep;
220
                int err;
221
 
222
                /* Recognize DSTs.  */
223
                name = expand_dst (l, strtab + d->d_un.d_val, 0);
224
                /* Store the tag in the argument structure.  */
225
                args.name = name;
226
 
227
                err = _dl_catch_error (&objname, &errstring, openaux, &args);
228
                if (__builtin_expect (errstring != NULL, 0))
229
                  {
230
                    if (err)
231
                      errno_reason = err;
232
                    else
233
                      errno_reason = -1;
234
                    goto out;
235
                  }
236
                else
237
                  dep = args.aux;
238
 
239
                if (! dep->l_reserved)
240
                  {
241
                    /* Allocate new entry.  */
242
                    struct list *newp;
243
 
244
                    newp = alloca (sizeof (struct list));
245
 
246
                    /* Append DEP to the list.  */
247
                    newp->map = dep;
248
                    newp->done = 0;
249
                    newp->next = NULL;
250
                    tail->next = newp;
251
                    tail = newp;
252
                    ++nlist;
253
                    /* Set the mark bit that says it's already in the list.  */
254
                    dep->l_reserved = 1;
255
                  }
256
 
257
                /* Remember this dependency.  */
258
                if (needed != NULL)
259
                  needed[nneeded++] = dep;
260
              }
261
            else if (d->d_tag == DT_AUXILIARY || d->d_tag == DT_FILTER)
262
              {
263
                struct list *newp;
264
 
265
                /* Recognize DSTs.  */
266
                name = expand_dst (l, strtab + d->d_un.d_val,
267
                                   d->d_tag == DT_AUXILIARY);
268
                /* Store the tag in the argument structure.  */
269
                args.name = name;
270
 
271
                if (d->d_tag == DT_AUXILIARY)
272
                  {
273
                    int err;
274
 
275
                    /* Say that we are about to load an auxiliary library.  */
276
                    if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0))
277
                      _dl_debug_printf ("load auxiliary object=%s"
278
                                        " requested by file=%s\n", name,
279
                                        l->l_name[0]
280
                                        ? l->l_name : _dl_argv[0]);
281
 
282
                    /* We must be prepared that the addressed shared
283
                       object is not available.  */
284
                    err = _dl_catch_error (&objname, &errstring, openaux,
285
                                           &args);
286
                    if (__builtin_expect (errstring != NULL, 0))
287
                      {
288
                        /* We are not interested in the error message.  */
289
                        assert (errstring != NULL);
290
                        if (errstring != _dl_out_of_memory)
291
                          free ((char *) errstring);
292
 
293
                        /* Simply ignore this error and continue the work.  */
294
                        continue;
295
                      }
296
                  }
297
                else
298
                  {
299
                    int err;
300
 
301
                    /* Say that we are about to load an auxiliary library.  */
302
                    if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0))
303
                      _dl_debug_printf ("load filtered object=%s"
304
                                        " requested by file=%s\n", name,
305
                                        l->l_name[0]
306
                                        ? l->l_name : _dl_argv[0]);
307
 
308
                    /* For filter objects the dependency must be available.  */
309
                    err = _dl_catch_error (&objname, &errstring, openaux,
310
                                           &args);
311
                    if (__builtin_expect (errstring != NULL, 0))
312
                      {
313
                        if (err)
314
                          errno_reason = err;
315
                        else
316
                          errno_reason = -1;
317
                        goto out;
318
                      }
319
                  }
320
 
321
                /* The auxiliary object is actually available.
322
                   Incorporate the map in all the lists.  */
323
 
324
                /* Allocate new entry.  This always has to be done.  */
325
                newp = alloca (sizeof (struct list));
326
 
327
                /* We want to insert the new map before the current one,
328
                   but we have no back links.  So we copy the contents of
329
                   the current entry over.  Note that ORIG and NEWP now
330
                   have switched their meanings.  */
331
                memcpy (newp, orig, sizeof (*newp));
332
 
333
                /* Initialize new entry.  */
334
                orig->done = 0;
335
                orig->map = args.aux;
336
 
337
                /* Remember this dependency.  */
338
                if (needed != NULL)
339
                  needed[nneeded++] = args.aux;
340
 
341
                /* We must handle two situations here: the map is new,
342
                   so we must add it in all three lists.  If the map
343
                   is already known, we have two further possibilities:
344
                   - if the object is before the current map in the
345
                   search list, we do nothing.  It is already found
346
                   early
347
                   - if the object is after the current one, we must
348
                   move it just before the current map to make sure
349
                   the symbols are found early enough
350
                */
351
                if (args.aux->l_reserved)
352
                  {
353
                    /* The object is already somewhere in the list.
354
                       Locate it first.  */
355
                    struct list *late;
356
 
357
                    /* This object is already in the search list we
358
                       are building.  Don't add a duplicate pointer.
359
                       Just added by _dl_map_object.  */
360
                    for (late = newp; late->next != NULL; late = late->next)
361
                      if (late->next->map == args.aux)
362
                        break;
363
 
364
                    if (late->next != NULL)
365
                      {
366
                        /* The object is somewhere behind the current
367
                           position in the search path.  We have to
368
                           move it to this earlier position.  */
369
                        orig->next = newp;
370
 
371
                        /* Now remove the later entry from the list
372
                           and adjust the tail pointer.  */
373
                        if (tail == late->next)
374
                          tail = late;
375
                        late->next = late->next->next;
376
 
377
                        /* We must move the object earlier in the chain.  */
378
                        if (args.aux->l_prev != NULL)
379
                          args.aux->l_prev->l_next = args.aux->l_next;
380
                        if (args.aux->l_next != NULL)
381
                          args.aux->l_next->l_prev = args.aux->l_prev;
382
 
383
                        args.aux->l_prev = newp->map->l_prev;
384
                        newp->map->l_prev = args.aux;
385
                        if (args.aux->l_prev != NULL)
386
                          args.aux->l_prev->l_next = args.aux;
387
                        args.aux->l_next = newp->map;
388
                      }
389
                    else
390
                      {
391
                        /* The object must be somewhere earlier in the
392
                           list.  Undo to the current list element what
393
                           we did above.  */
394
                        memcpy (orig, newp, sizeof (*newp));
395
                        continue;
396
                      }
397
                  }
398
                else
399
                  {
400
                    /* This is easy.  We just add the symbol right here.  */
401
                    orig->next = newp;
402
                    ++nlist;
403
                    /* Set the mark bit that says it's already in the list.  */
404
                    args.aux->l_reserved = 1;
405
 
406
                    /* The only problem is that in the double linked
407
                       list of all objects we don't have this new
408
                       object at the correct place.  Correct this here.  */
409
                    if (args.aux->l_prev)
410
                      args.aux->l_prev->l_next = args.aux->l_next;
411
                    if (args.aux->l_next)
412
                      args.aux->l_next->l_prev = args.aux->l_prev;
413
 
414
                    args.aux->l_prev = newp->map->l_prev;
415
                    newp->map->l_prev = args.aux;
416
                    if (args.aux->l_prev != NULL)
417
                      args.aux->l_prev->l_next = args.aux;
418
                    args.aux->l_next = newp->map;
419
                  }
420
 
421
                /* Move the tail pointer if necessary.  */
422
                if (orig == tail)
423
                  tail = newp;
424
 
425
                /* Move on the insert point.  */
426
                orig = newp;
427
              }
428
        }
429
 
430
      /* Terminate the list of dependencies and store the array address.  */
431
      if (needed != NULL)
432
        {
433
          needed[nneeded++] = NULL;
434
 
435
          l->l_initfini = (struct link_map **)
436
            malloc ((nneeded + 1) * sizeof needed[0]);
437
          if (l->l_initfini == NULL)
438
            _dl_signal_error (ENOMEM, map->l_name, NULL,
439
                              N_("cannot allocate dependency list"));
440
          l->l_initfini[0] = l;
441
          memcpy (&l->l_initfini[1], needed, nneeded * sizeof needed[0]);
442
        }
443
 
444
      /* If we have no auxiliary objects just go on to the next map.  */
445
      if (runp->done)
446
        do
447
          runp = runp->next;
448
        while (runp != NULL && runp->done);
449
    }
450
 
451
 out:
452
  if (errno == 0 && errno_saved != 0)
453
    __set_errno (errno_saved);
454
 
455
  if (map->l_initfini != NULL && map->l_type == lt_loaded)
456
    {
457
      /* This object was previously loaded as a dependency and we have
458
         a separate l_initfini list.  We don't need it anymore.  */
459
      assert (map->l_searchlist.r_list == NULL);
460
      free (map->l_initfini);
461
    }
462
 
463
  /* Store the search list we built in the object.  It will be used for
464
     searches in the scope of this object.  */
465
  map->l_initfini =
466
    (struct link_map **) malloc ((2 * nlist + 1)
467
                                 * sizeof (struct link_map *));
468
  if (map->l_initfini == NULL)
469
    _dl_signal_error (ENOMEM, map->l_name, NULL,
470
                      N_("cannot allocate symbol search list"));
471
 
472
 
473
  map->l_searchlist.r_list = &map->l_initfini[nlist + 1];
474
  map->l_searchlist.r_nlist = nlist;
475
 
476
  for (nlist = 0, runp = known; runp; runp = runp->next)
477
    {
478
      if (__builtin_expect (trace_mode, 0) && runp->map->l_faked)
479
        /* This can happen when we trace the loading.  */
480
        --map->l_searchlist.r_nlist;
481
      else
482
        map->l_searchlist.r_list[nlist++] = runp->map;
483
 
484
      /* Now clear all the mark bits we set in the objects on the search list
485
         to avoid duplicates, so the next call starts fresh.  */
486
      runp->map->l_reserved = 0;
487
    }
488
 
489
  /* Maybe we can remove some relocation dependencies now.  */
490
  assert (map->l_searchlist.r_list[0] == map);
491
  for (i = 0; i < map->l_reldepsact; ++i)
492
    {
493
      unsigned int j;
494
 
495
      for (j = 1; j < nlist; ++j)
496
        if (map->l_searchlist.r_list[j] == map->l_reldeps[i])
497
          {
498
            /* A direct or transitive dependency is also on the list
499
               of relocation dependencies.  Remove the latter.  */
500
            --map->l_reldeps[i]->l_opencount;
501
 
502
            for (j = i + 1; j < map->l_reldepsact; ++j)
503
              map->l_reldeps[j - 1] = map->l_reldeps[j];
504
 
505
            --map->l_reldepsact;
506
 
507
            /* Account for the '++i' performed by the 'for'.  */
508
            --i;
509
            break;
510
          }
511
    }
512
 
513
  /* Now determine the order in which the initialization has to happen.  */
514
  memcpy (map->l_initfini, map->l_searchlist.r_list,
515
          nlist * sizeof (struct link_map *));
516
  /* We can skip looking for the binary itself which is at the front
517
     of the search list.  Look through the list backward so that circular
518
     dependencies are not changing the order.  */
519
  for (i = 1; i < nlist; ++i)
520
    {
521
      struct link_map *l = map->l_searchlist.r_list[i];
522
      unsigned int j;
523
      unsigned int k;
524
 
525
      /* Find the place in the initfini list where the map is currently
526
         located.  */
527
      for (j = 1; map->l_initfini[j] != l; ++j)
528
        ;
529
 
530
      /* Find all object for which the current one is a dependency and
531
         move the found object (if necessary) in front.  */
532
      for (k = j + 1; k < nlist; ++k)
533
        {
534
          struct link_map **runp;
535
 
536
          runp = map->l_initfini[k]->l_initfini;
537
          if (runp != NULL)
538
            {
539
              while (*runp != NULL)
540
                if (__builtin_expect (*runp++ == l, 0))
541
                  {
542
                    struct link_map *here = map->l_initfini[k];
543
 
544
                    /* Move it now.  */
545
                    memmove (&map->l_initfini[j] + 1,
546
                             &map->l_initfini[j],
547
                             (k - j) * sizeof (struct link_map *));
548
                    map->l_initfini[j] = here;
549
 
550
                    break;
551
                  }
552
            }
553
        }
554
    }
555
  /* Terminate the list of dependencies.  */
556
  map->l_initfini[nlist] = NULL;
557
 
558
  if (errno_reason)
559
    _dl_signal_error (errno_reason == -1 ? 0 : errno_reason,
560
                      objname, NULL, errstring);
561
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.