ldctor.c revision 38889
1/* ldctor.c -- constructor support routines
2   Copyright (C) 1991, 92, 93, 94, 1995 Free Software Foundation, Inc.
3   By Steve Chamberlain <sac@cygnus.com>
4
5This file is part of GLD, the Gnu Linker.
6
7GLD is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GLD is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GLD; see the file COPYING.  If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21#include "bfd.h"
22#include "sysdep.h"
23#include "bfdlink.h"
24
25#include "ld.h"
26#include "ldexp.h"
27#include "ldlang.h"
28#include "ldmisc.h"
29#include "ldgram.h"
30#include "ldmain.h"
31#include "ldctor.h"
32
33/* The list of statements needed to handle constructors.  These are
34   invoked by the command CONSTRUCTORS in the linker script.  */
35lang_statement_list_type constructor_list;
36
37/* The sets we have seen.  */
38struct set_info *sets;
39
40/* Add an entry to a set.  H is the entry in the linker hash table.
41   RELOC is the relocation to use for an entry in the set.  SECTION
42   and VALUE are the value to add.  This is called during the first
43   phase of the link, when we are still gathering symbols together.
44   We just record the information now.  The ldctor_find_constructors
45   function will construct the sets.  */
46
47void
48ldctor_add_set_entry (h, reloc, name, section, value)
49     struct bfd_link_hash_entry *h;
50     bfd_reloc_code_real_type reloc;
51     const char *name;
52     asection *section;
53     bfd_vma value;
54{
55  struct set_info *p;
56  struct set_element *e;
57  struct set_element **epp;
58
59  for (p = sets; p != (struct set_info *) NULL; p = p->next)
60    if (p->h == h)
61      break;
62
63  if (p == (struct set_info *) NULL)
64    {
65      p = (struct set_info *) xmalloc (sizeof (struct set_info));
66      p->next = sets;
67      sets = p;
68      p->h = h;
69      p->reloc = reloc;
70      p->count = 0;
71      p->elements = NULL;
72    }
73  else
74    {
75      if (p->reloc != reloc)
76	{
77	  einfo ("%P%X: Different relocs used in set %s\n", h->root.string);
78	  return;
79	}
80
81      /* Don't permit a set to be constructed from different object
82         file formats.  The same reloc may have different results.  We
83         actually could sometimes handle this, but the case is
84         unlikely to ever arise.  Sometimes constructor symbols are in
85         unusual sections, such as the absolute section--this appears
86         to be the case in Linux a.out--and in such cases we just
87         assume everything is OK.  */
88      if (p->elements != NULL
89	  && section->owner != NULL
90	  && p->elements->section->owner != NULL
91	  && strcmp (bfd_get_target (section->owner),
92		     bfd_get_target (p->elements->section->owner)) != 0)
93	{
94	  einfo ("%P%X: Different object file formats composing set %s\n",
95		 h->root.string);
96	  return;
97	}
98    }
99
100  e = (struct set_element *) xmalloc (sizeof (struct set_element));
101  e->next = NULL;
102  e->name = name;
103  e->section = section;
104  e->value = value;
105
106  for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
107    ;
108  *epp = e;
109
110  ++p->count;
111}
112
113/* This function is called after the first phase of the link and
114   before the second phase.  At this point all set information has
115   been gathered.  We now put the statements to build the sets
116   themselves into constructor_list.  */
117
118void
119ldctor_build_sets ()
120{
121  static boolean called;
122  lang_statement_list_type *old;
123  boolean header_printed;
124  struct set_info *p;
125
126  /* The emulation code may call us directly, but we only want to do
127     this once.  */
128  if (called)
129    return;
130  called = true;
131
132  old = stat_ptr;
133  stat_ptr = &constructor_list;
134
135  lang_list_init (stat_ptr);
136
137  header_printed = false;
138  for (p = sets; p != (struct set_info *) NULL; p = p->next)
139    {
140      struct set_element *e;
141      reloc_howto_type *howto;
142      int reloc_size, size;
143
144      /* If the symbol is defined, we may have been invoked from
145	 collect, and the sets may already have been built, so we do
146	 not do anything.  */
147      if (p->h->type == bfd_link_hash_defined
148	  || p->h->type == bfd_link_hash_defweak)
149	continue;
150
151      /* For each set we build:
152	   set:
153	     .long number_of_elements
154	     .long element0
155	     ...
156	     .long elementN
157	     .long 0
158	 except that we use the right size instead of .long.  When
159	 generating relocateable output, we generate relocs instead of
160	 addresses.  */
161      howto = bfd_reloc_type_lookup (output_bfd, p->reloc);
162      if (howto == (reloc_howto_type *) NULL)
163	{
164	  if (link_info.relocateable)
165	    {
166	      einfo ("%P%X: %s does not support reloc %s for set %s\n",
167		     bfd_get_target (output_bfd),
168		     bfd_get_reloc_code_name (p->reloc),
169		     p->h->root.string);
170	      continue;
171	    }
172
173	  /* If this is not a relocateable link, all we need is the
174	     size, which we can get from the input BFD.  */
175	  howto = bfd_reloc_type_lookup (p->elements->section->owner,
176					 p->reloc);
177	  if (howto == NULL)
178	    {
179	      einfo ("%P%X: %s does not support reloc %s for set %s\n",
180		     bfd_get_target (p->elements->section->owner),
181		     bfd_get_reloc_code_name (p->reloc),
182		     p->h->root.string);
183	      continue;
184	    }
185	}
186
187      reloc_size = bfd_get_reloc_size (howto);
188      switch (reloc_size)
189	{
190	case 1: size = BYTE; break;
191	case 2: size = SHORT; break;
192	case 4: size = LONG; break;
193	case 8:
194	  if (howto->complain_on_overflow == complain_overflow_signed)
195	    size = SQUAD;
196	  else
197	    size = QUAD;
198	  break;
199	default:
200	  einfo ("%P%X: Unsupported size %d for set %s\n",
201		 bfd_get_reloc_size (howto), p->h->root.string);
202	  size = LONG;
203	  break;
204	}
205
206      lang_add_assignment (exp_assop ('=', ".",
207				      exp_unop (ALIGN_K,
208						exp_intop (reloc_size))));
209      lang_add_assignment (exp_assop ('=', p->h->root.string,
210				      exp_nameop (NAME, ".")));
211      lang_add_data (size, exp_intop ((bfd_vma) p->count));
212
213      for (e = p->elements; e != (struct set_element *) NULL; e = e->next)
214	{
215	  if (config.map_file != NULL)
216	    {
217	      int len;
218
219	      if (! header_printed)
220		{
221		  minfo ("\nSet                 Symbol\n\n");
222		  header_printed = true;
223		}
224
225	      minfo ("%s", p->h->root.string);
226	      len = strlen (p->h->root.string);
227
228	      if (len >= 19)
229		{
230		  print_nl ();
231		  len = 0;
232		}
233	      while (len < 20)
234		{
235		  print_space ();
236		  ++len;
237		}
238
239	      if (e->name != NULL)
240		minfo ("%T\n", e->name);
241	      else
242		minfo ("%G\n", e->section->owner, e->section, e->value);
243	    }
244
245	  if (link_info.relocateable)
246	    lang_add_reloc (p->reloc, howto, e->section, e->name,
247			    exp_intop (e->value));
248	  else
249	    lang_add_data (size, exp_relop (e->section, e->value));
250	}
251
252      lang_add_data (size, exp_intop (0));
253    }
254
255  stat_ptr = old;
256}
257