(root)/
binutils-2.41/
ld/
ldctor.c
       1  /* ldctor.c -- constructor support routines
       2     Copyright (C) 1991-2023 Free Software Foundation, Inc.
       3     By Steve Chamberlain <sac@cygnus.com>
       4  
       5     This file is part of the GNU Binutils.
       6  
       7     This program is free software; you can redistribute it and/or modify
       8     it under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 3 of the License, or
      10     (at your option) any later version.
      11  
      12     This program is distributed in the hope that it will be useful,
      13     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15     GNU General Public License for more details.
      16  
      17     You should have received a copy of the GNU General Public License
      18     along with this program; if not, write to the Free Software
      19     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      20     MA 02110-1301, USA.  */
      21  
      22  #include "sysdep.h"
      23  #include "bfd.h"
      24  #include "bfdlink.h"
      25  #include "safe-ctype.h"
      26  #include "ctf-api.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  bool 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 = (struct set_info *) 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 (_("%X%P: 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 (_("%X%P: different object file formats composing set %s\n"),
     103  		 h->root.string);
     104  	  return;
     105  	}
     106      }
     107  
     108    e = (struct set_element *) xmalloc (sizeof (struct set_element));
     109    e->u.next = NULL;
     110    e->name = name;
     111    e->section = section;
     112    e->value = value;
     113  
     114    for (epp = &p->elements; *epp != NULL; epp = &(*epp)->u.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 (!startswith (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 *pe1 = *(const struct set_element **) p1;
     156    const struct set_element *pe2 = *(const struct set_element **) 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    if (prio1 > prio2)
     180      return -1;
     181  
     182    /* Force a stable sort.  */
     183    if (pe1->u.idx < pe2->u.idx)
     184      return -1;
     185    if (pe1->u.idx > pe2->u.idx)
     186      return 1;
     187    return 0;
     188  }
     189  
     190  /* This function is called after the first phase of the link and
     191     before the second phase.  At this point all set information has
     192     been gathered.  We now put the statements to build the sets
     193     themselves into constructor_list.  */
     194  
     195  void
     196  ldctor_build_sets (void)
     197  {
     198    static bool called;
     199    bool header_printed;
     200    struct set_info *p;
     201  
     202    /* The emulation code may call us directly, but we only want to do
     203       this once.  */
     204    if (called)
     205      return;
     206    called = true;
     207  
     208    if (constructors_sorted)
     209      {
     210        for (p = sets; p != NULL; p = p->next)
     211  	{
     212  	  int c, i;
     213  	  struct set_element *e, *enext;
     214  	  struct set_element **array;
     215  
     216  	  if (p->elements == NULL)
     217  	    continue;
     218  
     219  	  c = 0;
     220  	  for (e = p->elements; e != NULL; e = e->u.next)
     221  	    ++c;
     222  
     223  	  array = (struct set_element **) xmalloc (c * sizeof *array);
     224  
     225  	  i = 0;
     226  	  for (e = p->elements; e != NULL; e = enext)
     227  	    {
     228  	      array[i] = e;
     229  	      enext = e->u.next;
     230  	      e->u.idx = i;
     231  	      ++i;
     232  	    }
     233  
     234  	  qsort (array, c, sizeof *array, ctor_cmp);
     235  
     236  	  e = array[0];
     237  	  p->elements = e;
     238  	  for (i = 0; i < c - 1; i++)
     239  	    array[i]->u.next = array[i + 1];
     240  	  array[i]->u.next = NULL;
     241  
     242  	  free (array);
     243  	}
     244      }
     245  
     246    lang_list_init (&constructor_list);
     247    push_stat_ptr (&constructor_list);
     248  
     249    header_printed = false;
     250    for (p = sets; p != NULL; p = p->next)
     251      {
     252        struct set_element *e;
     253        reloc_howto_type *howto;
     254        int reloc_size, size;
     255  
     256        /* If the symbol is defined, we may have been invoked from
     257  	 collect, and the sets may already have been built, so we do
     258  	 not do anything.  */
     259        if (p->h->type == bfd_link_hash_defined
     260  	  || p->h->type == bfd_link_hash_defweak)
     261  	continue;
     262  
     263        /* For each set we build:
     264  	   set:
     265  	     .long number_of_elements
     266  	     .long element0
     267  	     ...
     268  	     .long elementN
     269  	     .long 0
     270  	 except that we use the right size instead of .long.  When
     271  	 generating relocatable output, we generate relocs instead of
     272  	 addresses.  */
     273        howto = bfd_reloc_type_lookup (link_info.output_bfd, p->reloc);
     274        if (howto == NULL)
     275  	{
     276  	  if (bfd_link_relocatable (&link_info))
     277  	    {
     278  	      einfo (_("%X%P: %s does not support reloc %s for set %s\n"),
     279  		     bfd_get_target (link_info.output_bfd),
     280  		     bfd_get_reloc_code_name (p->reloc),
     281  		     p->h->root.string);
     282  	      continue;
     283  	    }
     284  
     285  	  /* If this is not a relocatable link, all we need is the
     286  	     size, which we can get from the input BFD.  */
     287  	  if (p->elements->section->owner != NULL)
     288  	    howto = bfd_reloc_type_lookup (p->elements->section->owner,
     289  					   p->reloc);
     290  	  if (howto == NULL)
     291  	    {
     292  	      /* See PR 20911 for a reproducer.  */
     293  	      if (p->elements->section->owner == NULL)
     294  		einfo (_("%X%P: special section %s does not support reloc %s for set %s\n"),
     295  		       bfd_section_name (p->elements->section),
     296  		       bfd_get_reloc_code_name (p->reloc),
     297  		       p->h->root.string);
     298  	      else
     299  		einfo (_("%X%P: %s does not support reloc %s for set %s\n"),
     300  		       bfd_get_target (p->elements->section->owner),
     301  		       bfd_get_reloc_code_name (p->reloc),
     302  		       p->h->root.string);
     303  	      continue;
     304  	    }
     305  	}
     306  
     307        reloc_size = bfd_get_reloc_size (howto);
     308        switch (reloc_size)
     309  	{
     310  	case 1: size = BYTE; break;
     311  	case 2: size = SHORT; break;
     312  	case 4: size = LONG; break;
     313  	case 8:
     314  	  if (howto->complain_on_overflow == complain_overflow_signed)
     315  	    size = SQUAD;
     316  	  else
     317  	    size = QUAD;
     318  	  break;
     319  	default:
     320  	  einfo (_("%X%P: unsupported size %d for set %s\n"),
     321  		 bfd_get_reloc_size (howto), p->h->root.string);
     322  	  size = LONG;
     323  	  break;
     324  	}
     325  
     326        lang_add_assignment (exp_assign (".",
     327  				       exp_unop (ALIGN_K,
     328  						 exp_intop (reloc_size)),
     329  				       false));
     330        lang_add_assignment (exp_assign (p->h->root.string,
     331  				       exp_nameop (NAME, "."),
     332  				       false));
     333        lang_add_data (size, exp_intop (p->count));
     334  
     335        for (e = p->elements; e != NULL; e = e->u.next)
     336  	{
     337  	  if (config.map_file != NULL)
     338  	    {
     339  	      int len;
     340  
     341  	      if (!header_printed)
     342  		{
     343  		  minfo (_("\nSet                 Symbol\n\n"));
     344  		  header_printed = true;
     345  		}
     346  
     347  	      minfo ("%s", p->h->root.string);
     348  	      len = strlen (p->h->root.string);
     349  
     350  	      if (len >= 19)
     351  		{
     352  		  print_nl ();
     353  		  len = 0;
     354  		}
     355  	      print_spaces (20 - len);
     356  
     357  	      if (e->name != NULL)
     358  		minfo ("%pT\n", e->name);
     359  	      else
     360  		minfo ("%G\n", e->section->owner, e->section, e->value);
     361  	    }
     362  
     363  	  /* Need SEC_KEEP for --gc-sections.  */
     364  	  if (!bfd_is_abs_section (e->section))
     365  	    e->section->flags |= SEC_KEEP;
     366  
     367  	  if (bfd_link_relocatable (&link_info))
     368  	    lang_add_reloc (p->reloc, howto, e->section, e->name,
     369  			    exp_intop (e->value));
     370  	  else
     371  	    lang_add_data (size, exp_relop (e->section, e->value));
     372  	}
     373  
     374        lang_add_data (size, exp_intop (0));
     375      }
     376  
     377    pop_stat_ptr ();
     378  }