~ubuntu-branches/ubuntu/hoary/binutils/hoary

« back to all changes in this revision

Viewing changes to ld/ldctor.c

  • Committer: Bazaar Package Importer
  • Author(s): James Troup
  • Date: 2004-05-19 10:35:44 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040519103544-17h3o6e8pwndydrg
Tags: 2.14.90.0.7-8
debian/rules: don't use gcc-2.95 on m68k.  Thanks to Adam Conrad for
pointing this out.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ldctor.c -- constructor support routines
 
2
   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
 
3
   2002, 2003 Free Software Foundation, Inc.
 
4
   By Steve Chamberlain <sac@cygnus.com>
 
5
 
 
6
This file is part of GLD, the Gnu Linker.
 
7
 
 
8
GLD 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 2, or (at your option)
 
11
any later version.
 
12
 
 
13
GLD 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 GLD; see the file COPYING.  If not, write to the Free
 
20
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
21
02111-1307, USA.  */
 
22
 
 
23
#include "bfd.h"
 
24
#include "sysdep.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_find_constructors
 
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 (strncmp (name, "GLOBAL_", sizeof "GLOBAL_" - 1) != 0)
 
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 (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 (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
}