Back to index

cell-binutils  2.17cvs20070401
ldctor.c
Go to the documentation of this file.
00001 /* ldctor.c -- constructor support routines
00002    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
00003    2002, 2003, 2004, 2006 Free Software Foundation, Inc.
00004    By Steve Chamberlain <sac@cygnus.com>
00005 
00006 This file is part of GLD, the Gnu Linker.
00007 
00008 GLD is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2, or (at your option)
00011 any later version.
00012 
00013 GLD is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with GLD; see the file COPYING.  If not, write to the Free
00020 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00021 02110-1301, USA.  */
00022 
00023 #include "bfd.h"
00024 #include "sysdep.h"
00025 #include "bfdlink.h"
00026 #include "safe-ctype.h"
00027 
00028 #include "ld.h"
00029 #include "ldexp.h"
00030 #include "ldlang.h"
00031 #include "ldmisc.h"
00032 #include <ldgram.h>
00033 #include "ldmain.h"
00034 #include "ldctor.h"
00035 
00036 /* The list of statements needed to handle constructors.  These are
00037    invoked by the command CONSTRUCTORS in the linker script.  */
00038 lang_statement_list_type constructor_list;
00039 
00040 /* Whether the constructors should be sorted.  Note that this is
00041    global for the entire link; we assume that there is only a single
00042    CONSTRUCTORS command in the linker script.  */
00043 bfd_boolean constructors_sorted;
00044 
00045 /* The sets we have seen.  */
00046 struct set_info *sets;
00047 
00048 /* Add an entry to a set.  H is the entry in the linker hash table.
00049    RELOC is the relocation to use for an entry in the set.  SECTION
00050    and VALUE are the value to add.  This is called during the first
00051    phase of the link, when we are still gathering symbols together.
00052    We just record the information now.  The ldctor_build_sets
00053    function will construct the sets.  */
00054 
00055 void
00056 ldctor_add_set_entry (struct bfd_link_hash_entry *h,
00057                     bfd_reloc_code_real_type reloc,
00058                     const char *name,
00059                     asection *section,
00060                     bfd_vma value)
00061 {
00062   struct set_info *p;
00063   struct set_element *e;
00064   struct set_element **epp;
00065 
00066   for (p = sets; p != NULL; p = p->next)
00067     if (p->h == h)
00068       break;
00069 
00070   if (p == NULL)
00071     {
00072       p = xmalloc (sizeof (struct set_info));
00073       p->next = sets;
00074       sets = p;
00075       p->h = h;
00076       p->reloc = reloc;
00077       p->count = 0;
00078       p->elements = NULL;
00079     }
00080   else
00081     {
00082       if (p->reloc != reloc)
00083        {
00084          einfo (_("%P%X: Different relocs used in set %s\n"),
00085                h->root.string);
00086          return;
00087        }
00088 
00089       /* Don't permit a set to be constructed from different object
00090          file formats.  The same reloc may have different results.  We
00091          actually could sometimes handle this, but the case is
00092          unlikely to ever arise.  Sometimes constructor symbols are in
00093          unusual sections, such as the absolute section--this appears
00094          to be the case in Linux a.out--and in such cases we just
00095          assume everything is OK.  */
00096       if (p->elements != NULL
00097          && section->owner != NULL
00098          && p->elements->section->owner != NULL
00099          && strcmp (bfd_get_target (section->owner),
00100                    bfd_get_target (p->elements->section->owner)) != 0)
00101        {
00102          einfo (_("%P%X: Different object file formats composing set %s\n"),
00103                h->root.string);
00104          return;
00105        }
00106     }
00107 
00108   e = xmalloc (sizeof (struct set_element));
00109   e->next = NULL;
00110   e->name = name;
00111   e->section = section;
00112   e->value = value;
00113 
00114   for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
00115     ;
00116   *epp = e;
00117 
00118   ++p->count;
00119 }
00120 
00121 /* Get the priority of a g++ global constructor or destructor from the
00122    symbol name.  */
00123 
00124 static int
00125 ctor_prio (const char *name)
00126 {
00127   /* The name will look something like _GLOBAL_$I$65535$test02__Fv.
00128      There might be extra leading underscores, and the $ characters
00129      might be something else.  The I might be a D.  */
00130 
00131   while (*name == '_')
00132     ++name;
00133 
00134   if (! CONST_STRNEQ (name, "GLOBAL_"))
00135     return -1;
00136 
00137   name += sizeof "GLOBAL_" - 1;
00138 
00139   if (name[0] != name[2])
00140     return -1;
00141   if (name[1] != 'I' && name[1] != 'D')
00142     return -1;
00143   if (! ISDIGIT (name[3]))
00144     return -1;
00145 
00146   return atoi (name + 3);
00147 }
00148 
00149 /* This function is used to sort constructor elements by priority.  It
00150    is called via qsort.  */
00151 
00152 static int
00153 ctor_cmp (const void *p1, const void *p2)
00154 {
00155   const struct set_element * const *pe1 = p1;
00156   const struct set_element * const *pe2 = p2;
00157   const char *n1;
00158   const char *n2;
00159   int prio1;
00160   int prio2;
00161 
00162   n1 = (*pe1)->name;
00163   if (n1 == NULL)
00164     n1 = "";
00165   n2 = (*pe2)->name;
00166   if (n2 == NULL)
00167     n2 = "";
00168 
00169   /* We need to sort in reverse order by priority.  When two
00170      constructors have the same priority, we should maintain their
00171      current relative position.  */
00172 
00173   prio1 = ctor_prio (n1);
00174   prio2 = ctor_prio (n2);
00175 
00176   /* We sort in reverse order because that is what g++ expects.  */
00177   if (prio1 < prio2)
00178     return 1;
00179   else if (prio1 > prio2)
00180     return -1;
00181 
00182   /* Force a stable sort.  */
00183 
00184   if (pe1 < pe2)
00185     return -1;
00186   else if (pe1 > pe2)
00187     return 1;
00188   else
00189     return 0;
00190 }
00191 
00192 /* This function is called after the first phase of the link and
00193    before the second phase.  At this point all set information has
00194    been gathered.  We now put the statements to build the sets
00195    themselves into constructor_list.  */
00196 
00197 void
00198 ldctor_build_sets (void)
00199 {
00200   static bfd_boolean called;
00201   lang_statement_list_type *old;
00202   bfd_boolean header_printed;
00203   struct set_info *p;
00204 
00205   /* The emulation code may call us directly, but we only want to do
00206      this once.  */
00207   if (called)
00208     return;
00209   called = TRUE;
00210 
00211   if (constructors_sorted)
00212     {
00213       for (p = sets; p != NULL; p = p->next)
00214        {
00215          int c, i;
00216          struct set_element *e;
00217          struct set_element **array;
00218 
00219          if (p->elements == NULL)
00220            continue;
00221 
00222          c = 0;
00223          for (e = p->elements; e != NULL; e = e->next)
00224            ++c;
00225 
00226          array = xmalloc (c * sizeof *array);
00227 
00228          i = 0;
00229          for (e = p->elements; e != NULL; e = e->next)
00230            {
00231              array[i] = e;
00232              ++i;
00233            }
00234 
00235          qsort (array, c, sizeof *array, ctor_cmp);
00236 
00237          e = array[0];
00238          p->elements = e;
00239          for (i = 0; i < c - 1; i++)
00240            array[i]->next = array[i + 1];
00241          array[i]->next = NULL;
00242 
00243          free (array);
00244        }
00245     }
00246 
00247   old = stat_ptr;
00248   stat_ptr = &constructor_list;
00249 
00250   lang_list_init (stat_ptr);
00251 
00252   header_printed = FALSE;
00253   for (p = sets; p != NULL; p = p->next)
00254     {
00255       struct set_element *e;
00256       reloc_howto_type *howto;
00257       int reloc_size, size;
00258 
00259       /* If the symbol is defined, we may have been invoked from
00260         collect, and the sets may already have been built, so we do
00261         not do anything.  */
00262       if (p->h->type == bfd_link_hash_defined
00263          || p->h->type == bfd_link_hash_defweak)
00264        continue;
00265 
00266       /* For each set we build:
00267           set:
00268             .long number_of_elements
00269             .long element0
00270             ...
00271             .long elementN
00272             .long 0
00273         except that we use the right size instead of .long.  When
00274         generating relocatable output, we generate relocs instead of
00275         addresses.  */
00276       howto = bfd_reloc_type_lookup (output_bfd, p->reloc);
00277       if (howto == NULL)
00278        {
00279          if (link_info.relocatable)
00280            {
00281              einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
00282                    bfd_get_target (output_bfd),
00283                    bfd_get_reloc_code_name (p->reloc),
00284                    p->h->root.string);
00285              continue;
00286            }
00287 
00288          /* If this is not a relocatable link, all we need is the
00289             size, which we can get from the input BFD.  */
00290          if (p->elements->section->owner != NULL)
00291            howto = bfd_reloc_type_lookup (p->elements->section->owner,
00292                                       p->reloc);
00293          if (howto == NULL)
00294            {
00295              einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
00296                    bfd_get_target (p->elements->section->owner),
00297                    bfd_get_reloc_code_name (p->reloc),
00298                    p->h->root.string);
00299              continue;
00300            }
00301        }
00302 
00303       reloc_size = bfd_get_reloc_size (howto);
00304       switch (reloc_size)
00305        {
00306        case 1: size = BYTE; break;
00307        case 2: size = SHORT; break;
00308        case 4: size = LONG; break;
00309        case 8:
00310          if (howto->complain_on_overflow == complain_overflow_signed)
00311            size = SQUAD;
00312          else
00313            size = QUAD;
00314          break;
00315        default:
00316          einfo (_("%P%X: Unsupported size %d for set %s\n"),
00317                bfd_get_reloc_size (howto), p->h->root.string);
00318          size = LONG;
00319          break;
00320        }
00321 
00322       lang_add_assignment (exp_assop ('=', ".",
00323                                   exp_unop (ALIGN_K,
00324                                           exp_intop (reloc_size))));
00325       lang_add_assignment (exp_assop ('=', p->h->root.string,
00326                                   exp_nameop (NAME, ".")));
00327       lang_add_data (size, exp_intop (p->count));
00328 
00329       for (e = p->elements; e != NULL; e = e->next)
00330        {
00331          if (config.map_file != NULL)
00332            {
00333              int len;
00334 
00335              if (! header_printed)
00336               {
00337                 minfo (_("\nSet                 Symbol\n\n"));
00338                 header_printed = TRUE;
00339               }
00340 
00341              minfo ("%s", p->h->root.string);
00342              len = strlen (p->h->root.string);
00343 
00344              if (len >= 19)
00345               {
00346                 print_nl ();
00347                 len = 0;
00348               }
00349              while (len < 20)
00350               {
00351                 print_space ();
00352                 ++len;
00353               }
00354 
00355              if (e->name != NULL)
00356               minfo ("%T\n", e->name);
00357              else
00358               minfo ("%G\n", e->section->owner, e->section, e->value);
00359            }
00360 
00361          /* Need SEC_KEEP for --gc-sections.  */
00362          if (! bfd_is_abs_section (e->section))
00363            e->section->flags |= SEC_KEEP;
00364 
00365          if (link_info.relocatable)
00366            lang_add_reloc (p->reloc, howto, e->section, e->name,
00367                          exp_intop (e->value));
00368          else
00369            lang_add_data (size, exp_relop (e->section, e->value));
00370        }
00371 
00372       lang_add_data (size, exp_intop (0));
00373     }
00374 
00375   stat_ptr = old;
00376 }