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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [ld/] [ldctor.c] - Blame information for rev 844

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

Line No. Rev Author Line
1 38 julius
/* ldctor.c -- constructor support routines
2
   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3
   2002, 2003, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
4
   By Steve Chamberlain <sac@cygnus.com>
5
 
6
   This file is part of the GNU Binutils.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
#include "sysdep.h"
24
#include "bfd.h"
25
#include "bfdlink.h"
26
#include "safe-ctype.h"
27
 
28
#include "ld.h"
29
#include "ldexp.h"
30
#include "ldlang.h"
31
#include "ldmisc.h"
32
#include <ldgram.h>
33
#include "ldmain.h"
34
#include "ldctor.h"
35
 
36
/* The list of statements needed to handle constructors.  These are
37
   invoked by the command CONSTRUCTORS in the linker script.  */
38
lang_statement_list_type constructor_list;
39
 
40
/* Whether the constructors should be sorted.  Note that this is
41
   global for the entire link; we assume that there is only a single
42
   CONSTRUCTORS command in the linker script.  */
43
bfd_boolean constructors_sorted;
44
 
45
/* The sets we have seen.  */
46
struct set_info *sets;
47
 
48
/* Add an entry to a set.  H is the entry in the linker hash table.
49
   RELOC is the relocation to use for an entry in the set.  SECTION
50
   and VALUE are the value to add.  This is called during the first
51
   phase of the link, when we are still gathering symbols together.
52
   We just record the information now.  The ldctor_build_sets
53
   function will construct the sets.  */
54
 
55
void
56
ldctor_add_set_entry (struct bfd_link_hash_entry *h,
57
                      bfd_reloc_code_real_type reloc,
58
                      const char *name,
59
                      asection *section,
60
                      bfd_vma value)
61
{
62
  struct set_info *p;
63
  struct set_element *e;
64
  struct set_element **epp;
65
 
66
  for (p = sets; p != NULL; p = p->next)
67
    if (p->h == h)
68
      break;
69
 
70
  if (p == NULL)
71
    {
72
      p = xmalloc (sizeof (struct set_info));
73
      p->next = sets;
74
      sets = p;
75
      p->h = h;
76
      p->reloc = reloc;
77
      p->count = 0;
78
      p->elements = NULL;
79
    }
80
  else
81
    {
82
      if (p->reloc != reloc)
83
        {
84
          einfo (_("%P%X: Different relocs used in set %s\n"),
85
                 h->root.string);
86
          return;
87
        }
88
 
89
      /* Don't permit a set to be constructed from different object
90
         file formats.  The same reloc may have different results.  We
91
         actually could sometimes handle this, but the case is
92
         unlikely to ever arise.  Sometimes constructor symbols are in
93
         unusual sections, such as the absolute section--this appears
94
         to be the case in Linux a.out--and in such cases we just
95
         assume everything is OK.  */
96
      if (p->elements != NULL
97
          && section->owner != NULL
98
          && p->elements->section->owner != NULL
99
          && strcmp (bfd_get_target (section->owner),
100
                     bfd_get_target (p->elements->section->owner)) != 0)
101
        {
102
          einfo (_("%P%X: Different object file formats composing set %s\n"),
103
                 h->root.string);
104
          return;
105
        }
106
    }
107
 
108
  e = xmalloc (sizeof (struct set_element));
109
  e->next = NULL;
110
  e->name = name;
111
  e->section = section;
112
  e->value = value;
113
 
114
  for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
115
    ;
116
  *epp = e;
117
 
118
  ++p->count;
119
}
120
 
121
/* Get the priority of a g++ global constructor or destructor from the
122
   symbol name.  */
123
 
124
static int
125
ctor_prio (const char *name)
126
{
127
  /* The name will look something like _GLOBAL_$I$65535$test02__Fv.
128
     There might be extra leading underscores, and the $ characters
129
     might be something else.  The I might be a D.  */
130
 
131
  while (*name == '_')
132
    ++name;
133
 
134
  if (! CONST_STRNEQ (name, "GLOBAL_"))
135
    return -1;
136
 
137
  name += sizeof "GLOBAL_" - 1;
138
 
139
  if (name[0] != name[2])
140
    return -1;
141
  if (name[1] != 'I' && name[1] != 'D')
142
    return -1;
143
  if (! ISDIGIT (name[3]))
144
    return -1;
145
 
146
  return atoi (name + 3);
147
}
148
 
149
/* This function is used to sort constructor elements by priority.  It
150
   is called via qsort.  */
151
 
152
static int
153
ctor_cmp (const void *p1, const void *p2)
154
{
155
  const struct set_element * const *pe1 = p1;
156
  const struct set_element * const *pe2 = p2;
157
  const char *n1;
158
  const char *n2;
159
  int prio1;
160
  int prio2;
161
 
162
  n1 = (*pe1)->name;
163
  if (n1 == NULL)
164
    n1 = "";
165
  n2 = (*pe2)->name;
166
  if (n2 == NULL)
167
    n2 = "";
168
 
169
  /* We need to sort in reverse order by priority.  When two
170
     constructors have the same priority, we should maintain their
171
     current relative position.  */
172
 
173
  prio1 = ctor_prio (n1);
174
  prio2 = ctor_prio (n2);
175
 
176
  /* We sort in reverse order because that is what g++ expects.  */
177
  if (prio1 < prio2)
178
    return 1;
179
  else if (prio1 > prio2)
180
    return -1;
181
 
182
  /* Force a stable sort.  */
183
 
184
  if (pe1 < pe2)
185
    return -1;
186
  else if (pe1 > pe2)
187
    return 1;
188
  else
189
    return 0;
190
}
191
 
192
/* This function is called after the first phase of the link and
193
   before the second phase.  At this point all set information has
194
   been gathered.  We now put the statements to build the sets
195
   themselves into constructor_list.  */
196
 
197
void
198
ldctor_build_sets (void)
199
{
200
  static bfd_boolean called;
201
  lang_statement_list_type *old;
202
  bfd_boolean header_printed;
203
  struct set_info *p;
204
 
205
  /* The emulation code may call us directly, but we only want to do
206
     this once.  */
207
  if (called)
208
    return;
209
  called = TRUE;
210
 
211
  if (constructors_sorted)
212
    {
213
      for (p = sets; p != NULL; p = p->next)
214
        {
215
          int c, i;
216
          struct set_element *e;
217
          struct set_element **array;
218
 
219
          if (p->elements == NULL)
220
            continue;
221
 
222
          c = 0;
223
          for (e = p->elements; e != NULL; e = e->next)
224
            ++c;
225
 
226
          array = xmalloc (c * sizeof *array);
227
 
228
          i = 0;
229
          for (e = p->elements; e != NULL; e = e->next)
230
            {
231
              array[i] = e;
232
              ++i;
233
            }
234
 
235
          qsort (array, c, sizeof *array, ctor_cmp);
236
 
237
          e = array[0];
238
          p->elements = e;
239
          for (i = 0; i < c - 1; i++)
240
            array[i]->next = array[i + 1];
241
          array[i]->next = NULL;
242
 
243
          free (array);
244
        }
245
    }
246
 
247
  old = stat_ptr;
248
  stat_ptr = &constructor_list;
249
 
250
  lang_list_init (stat_ptr);
251
 
252
  header_printed = FALSE;
253
  for (p = sets; p != NULL; p = p->next)
254
    {
255
      struct set_element *e;
256
      reloc_howto_type *howto;
257
      int reloc_size, size;
258
 
259
      /* If the symbol is defined, we may have been invoked from
260
         collect, and the sets may already have been built, so we do
261
         not do anything.  */
262
      if (p->h->type == bfd_link_hash_defined
263
          || p->h->type == bfd_link_hash_defweak)
264
        continue;
265
 
266
      /* For each set we build:
267
           set:
268
             .long number_of_elements
269
             .long element0
270
             ...
271
             .long elementN
272
             .long 0
273
         except that we use the right size instead of .long.  When
274
         generating relocatable output, we generate relocs instead of
275
         addresses.  */
276
      howto = bfd_reloc_type_lookup (link_info.output_bfd, p->reloc);
277
      if (howto == NULL)
278
        {
279
          if (link_info.relocatable)
280
            {
281
              einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
282
                     bfd_get_target (link_info.output_bfd),
283
                     bfd_get_reloc_code_name (p->reloc),
284
                     p->h->root.string);
285
              continue;
286
            }
287
 
288
          /* If this is not a relocatable link, all we need is the
289
             size, which we can get from the input BFD.  */
290
          if (p->elements->section->owner != NULL)
291
            howto = bfd_reloc_type_lookup (p->elements->section->owner,
292
                                           p->reloc);
293
          if (howto == NULL)
294
            {
295
              einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
296
                     bfd_get_target (p->elements->section->owner),
297
                     bfd_get_reloc_code_name (p->reloc),
298
                     p->h->root.string);
299
              continue;
300
            }
301
        }
302
 
303
      reloc_size = bfd_get_reloc_size (howto);
304
      switch (reloc_size)
305
        {
306
        case 1: size = BYTE; break;
307
        case 2: size = SHORT; break;
308
        case 4: size = LONG; break;
309
        case 8:
310
          if (howto->complain_on_overflow == complain_overflow_signed)
311
            size = SQUAD;
312
          else
313
            size = QUAD;
314
          break;
315
        default:
316
          einfo (_("%P%X: Unsupported size %d for set %s\n"),
317
                 bfd_get_reloc_size (howto), p->h->root.string);
318
          size = LONG;
319
          break;
320
        }
321
 
322
      lang_add_assignment (exp_assop ('=', ".",
323
                                      exp_unop (ALIGN_K,
324
                                                exp_intop (reloc_size))));
325
      lang_add_assignment (exp_assop ('=', p->h->root.string,
326
                                      exp_nameop (NAME, ".")));
327
      lang_add_data (size, exp_intop (p->count));
328
 
329
      for (e = p->elements; e != NULL; e = e->next)
330
        {
331
          if (config.map_file != NULL)
332
            {
333
              int len;
334
 
335
              if (! header_printed)
336
                {
337
                  minfo (_("\nSet                 Symbol\n\n"));
338
                  header_printed = TRUE;
339
                }
340
 
341
              minfo ("%s", p->h->root.string);
342
              len = strlen (p->h->root.string);
343
 
344
              if (len >= 19)
345
                {
346
                  print_nl ();
347
                  len = 0;
348
                }
349
              while (len < 20)
350
                {
351
                  print_space ();
352
                  ++len;
353
                }
354
 
355
              if (e->name != NULL)
356
                minfo ("%T\n", e->name);
357
              else
358
                minfo ("%G\n", e->section->owner, e->section, e->value);
359
            }
360
 
361
          /* Need SEC_KEEP for --gc-sections.  */
362
          if (! bfd_is_abs_section (e->section))
363
            e->section->flags |= SEC_KEEP;
364
 
365
          if (link_info.relocatable)
366
            lang_add_reloc (p->reloc, howto, e->section, e->name,
367
                            exp_intop (e->value));
368
          else
369
            lang_add_data (size, exp_relop (e->section, e->value));
370
        }
371
 
372
      lang_add_data (size, exp_intop (0));
373
    }
374
 
375
  stat_ptr = old;
376
}

powered by: WebSVN 2.1.0

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