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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [ld/] [ldctor.c] - Blame information for rev 184

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

Line No. Rev Author Line
1 145 khays
/* ldctor.c -- constructor support routines
2
   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3
   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
4
   Free Software Foundation, Inc.
5
   By Steve Chamberlain <sac@cygnus.com>
6
 
7
   This file is part of the GNU Binutils.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program; if not, write to the Free Software
21
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22
   MA 02110-1301, USA.  */
23
 
24
#include "sysdep.h"
25
#include "bfd.h"
26
#include "bfdlink.h"
27
#include "safe-ctype.h"
28
 
29
#include "ld.h"
30
#include "ldexp.h"
31
#include "ldlang.h"
32
#include "ldmisc.h"
33
#include <ldgram.h>
34
#include "ldmain.h"
35
#include "ldctor.h"
36
 
37
/* The list of statements needed to handle constructors.  These are
38
   invoked by the command CONSTRUCTORS in the linker script.  */
39
lang_statement_list_type constructor_list;
40
 
41
/* Whether the constructors should be sorted.  Note that this is
42
   global for the entire link; we assume that there is only a single
43
   CONSTRUCTORS command in the linker script.  */
44
bfd_boolean constructors_sorted;
45
 
46
/* The sets we have seen.  */
47
struct set_info *sets;
48
 
49
/* Add an entry to a set.  H is the entry in the linker hash table.
50
   RELOC is the relocation to use for an entry in the set.  SECTION
51
   and VALUE are the value to add.  This is called during the first
52
   phase of the link, when we are still gathering symbols together.
53
   We just record the information now.  The ldctor_build_sets
54
   function will construct the sets.  */
55
 
56
void
57
ldctor_add_set_entry (struct bfd_link_hash_entry *h,
58
                      bfd_reloc_code_real_type reloc,
59
                      const char *name,
60
                      asection *section,
61
                      bfd_vma value)
62
{
63
  struct set_info *p;
64
  struct set_element *e;
65
  struct set_element **epp;
66
 
67
  for (p = sets; p != NULL; p = p->next)
68
    if (p->h == h)
69
      break;
70
 
71
  if (p == NULL)
72
    {
73
      p = (struct set_info *) xmalloc (sizeof (struct set_info));
74
      p->next = sets;
75
      sets = p;
76
      p->h = h;
77
      p->reloc = reloc;
78
      p->count = 0;
79
      p->elements = NULL;
80
    }
81
  else
82
    {
83
      if (p->reloc != reloc)
84
        {
85
          einfo (_("%P%X: Different relocs used in set %s\n"),
86
                 h->root.string);
87
          return;
88
        }
89
 
90
      /* Don't permit a set to be constructed from different object
91
         file formats.  The same reloc may have different results.  We
92
         actually could sometimes handle this, but the case is
93
         unlikely to ever arise.  Sometimes constructor symbols are in
94
         unusual sections, such as the absolute section--this appears
95
         to be the case in Linux a.out--and in such cases we just
96
         assume everything is OK.  */
97
      if (p->elements != NULL
98
          && section->owner != NULL
99
          && p->elements->section->owner != NULL
100
          && strcmp (bfd_get_target (section->owner),
101
                     bfd_get_target (p->elements->section->owner)) != 0)
102
        {
103
          einfo (_("%P%X: Different object file formats composing set %s\n"),
104
                 h->root.string);
105
          return;
106
        }
107
    }
108
 
109
  e = (struct set_element *) xmalloc (sizeof (struct set_element));
110
  e->next = NULL;
111
  e->name = name;
112
  e->section = section;
113
  e->value = value;
114
 
115
  for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
116
    ;
117
  *epp = e;
118
 
119
  ++p->count;
120
}
121
 
122
/* Get the priority of a g++ global constructor or destructor from the
123
   symbol name.  */
124
 
125
static int
126
ctor_prio (const char *name)
127
{
128
  /* The name will look something like _GLOBAL_$I$65535$test02__Fv.
129
     There might be extra leading underscores, and the $ characters
130
     might be something else.  The I might be a D.  */
131
 
132
  while (*name == '_')
133
    ++name;
134
 
135
  if (! CONST_STRNEQ (name, "GLOBAL_"))
136
    return -1;
137
 
138
  name += sizeof "GLOBAL_" - 1;
139
 
140
  if (name[0] != name[2])
141
    return -1;
142
  if (name[1] != 'I' && name[1] != 'D')
143
    return -1;
144
  if (! ISDIGIT (name[3]))
145
    return -1;
146
 
147
  return atoi (name + 3);
148
}
149
 
150
/* This function is used to sort constructor elements by priority.  It
151
   is called via qsort.  */
152
 
153
static int
154
ctor_cmp (const void *p1, const void *p2)
155
{
156
  const struct set_element * const *pe1 =
157
      (const struct set_element * const *) p1;
158
  const struct set_element * const *pe2 =
159
      (const struct set_element * const *) p2;
160
  const char *n1;
161
  const char *n2;
162
  int prio1;
163
  int prio2;
164
 
165
  n1 = (*pe1)->name;
166
  if (n1 == NULL)
167
    n1 = "";
168
  n2 = (*pe2)->name;
169
  if (n2 == NULL)
170
    n2 = "";
171
 
172
  /* We need to sort in reverse order by priority.  When two
173
     constructors have the same priority, we should maintain their
174
     current relative position.  */
175
 
176
  prio1 = ctor_prio (n1);
177
  prio2 = ctor_prio (n2);
178
 
179
  /* We sort in reverse order because that is what g++ expects.  */
180
  if (prio1 < prio2)
181
    return 1;
182
  else if (prio1 > prio2)
183
    return -1;
184
 
185
  /* Force a stable sort.  */
186
 
187
  if (pe1 < pe2)
188
    return -1;
189
  else if (pe1 > pe2)
190
    return 1;
191
  else
192
    return 0;
193
}
194
 
195
/* This function is called after the first phase of the link and
196
   before the second phase.  At this point all set information has
197
   been gathered.  We now put the statements to build the sets
198
   themselves into constructor_list.  */
199
 
200
void
201
ldctor_build_sets (void)
202
{
203
  static bfd_boolean called;
204
  bfd_boolean header_printed;
205
  struct set_info *p;
206
 
207
  /* The emulation code may call us directly, but we only want to do
208
     this once.  */
209
  if (called)
210
    return;
211
  called = TRUE;
212
 
213
  if (constructors_sorted)
214
    {
215
      for (p = sets; p != NULL; p = p->next)
216
        {
217
          int c, i;
218
          struct set_element *e;
219
          struct set_element **array;
220
 
221
          if (p->elements == NULL)
222
            continue;
223
 
224
          c = 0;
225
          for (e = p->elements; e != NULL; e = e->next)
226
            ++c;
227
 
228
          array = (struct set_element **) xmalloc (c * sizeof *array);
229
 
230
          i = 0;
231
          for (e = p->elements; e != NULL; e = e->next)
232
            {
233
              array[i] = e;
234
              ++i;
235
            }
236
 
237
          qsort (array, c, sizeof *array, ctor_cmp);
238
 
239
          e = array[0];
240
          p->elements = e;
241
          for (i = 0; i < c - 1; i++)
242
            array[i]->next = array[i + 1];
243
          array[i]->next = NULL;
244
 
245
          free (array);
246
        }
247
    }
248
 
249
  lang_list_init (&constructor_list);
250
  push_stat_ptr (&constructor_list);
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_assign (".",
323
                                       exp_unop (ALIGN_K,
324
                                                 exp_intop (reloc_size))));
325
      lang_add_assignment (exp_assign (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
  pop_stat_ptr ();
376
}

powered by: WebSVN 2.1.0

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