xref: /openbsd-src/gnu/usr.bin/binutils-2.17/ld/ldctor.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* ldctor.c -- constructor support routines
2*3d8817e4Smiod    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3*3d8817e4Smiod    2002, 2003, 2004 Free Software Foundation, Inc.
4*3d8817e4Smiod    By Steve Chamberlain <sac@cygnus.com>
5*3d8817e4Smiod 
6*3d8817e4Smiod This file is part of GLD, the Gnu Linker.
7*3d8817e4Smiod 
8*3d8817e4Smiod GLD is free software; you can redistribute it and/or modify
9*3d8817e4Smiod it under the terms of the GNU General Public License as published by
10*3d8817e4Smiod the Free Software Foundation; either version 2, or (at your option)
11*3d8817e4Smiod any later version.
12*3d8817e4Smiod 
13*3d8817e4Smiod GLD is distributed in the hope that it will be useful,
14*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
15*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*3d8817e4Smiod GNU General Public License for more details.
17*3d8817e4Smiod 
18*3d8817e4Smiod You should have received a copy of the GNU General Public License
19*3d8817e4Smiod along with GLD; see the file COPYING.  If not, write to the Free
20*3d8817e4Smiod Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21*3d8817e4Smiod 02110-1301, USA.  */
22*3d8817e4Smiod 
23*3d8817e4Smiod #include "bfd.h"
24*3d8817e4Smiod #include "sysdep.h"
25*3d8817e4Smiod #include "bfdlink.h"
26*3d8817e4Smiod #include "safe-ctype.h"
27*3d8817e4Smiod 
28*3d8817e4Smiod #include "ld.h"
29*3d8817e4Smiod #include "ldexp.h"
30*3d8817e4Smiod #include "ldlang.h"
31*3d8817e4Smiod #include "ldmisc.h"
32*3d8817e4Smiod #include <ldgram.h>
33*3d8817e4Smiod #include "ldmain.h"
34*3d8817e4Smiod #include "ldctor.h"
35*3d8817e4Smiod 
36*3d8817e4Smiod /* The list of statements needed to handle constructors.  These are
37*3d8817e4Smiod    invoked by the command CONSTRUCTORS in the linker script.  */
38*3d8817e4Smiod lang_statement_list_type constructor_list;
39*3d8817e4Smiod 
40*3d8817e4Smiod /* Whether the constructors should be sorted.  Note that this is
41*3d8817e4Smiod    global for the entire link; we assume that there is only a single
42*3d8817e4Smiod    CONSTRUCTORS command in the linker script.  */
43*3d8817e4Smiod bfd_boolean constructors_sorted;
44*3d8817e4Smiod 
45*3d8817e4Smiod /* The sets we have seen.  */
46*3d8817e4Smiod struct set_info *sets;
47*3d8817e4Smiod 
48*3d8817e4Smiod /* Add an entry to a set.  H is the entry in the linker hash table.
49*3d8817e4Smiod    RELOC is the relocation to use for an entry in the set.  SECTION
50*3d8817e4Smiod    and VALUE are the value to add.  This is called during the first
51*3d8817e4Smiod    phase of the link, when we are still gathering symbols together.
52*3d8817e4Smiod    We just record the information now.  The ldctor_build_sets
53*3d8817e4Smiod    function will construct the sets.  */
54*3d8817e4Smiod 
55*3d8817e4Smiod void
ldctor_add_set_entry(struct bfd_link_hash_entry * h,bfd_reloc_code_real_type reloc,const char * name,asection * section,bfd_vma value)56*3d8817e4Smiod ldctor_add_set_entry (struct bfd_link_hash_entry *h,
57*3d8817e4Smiod 		      bfd_reloc_code_real_type reloc,
58*3d8817e4Smiod 		      const char *name,
59*3d8817e4Smiod 		      asection *section,
60*3d8817e4Smiod 		      bfd_vma value)
61*3d8817e4Smiod {
62*3d8817e4Smiod   struct set_info *p;
63*3d8817e4Smiod   struct set_element *e;
64*3d8817e4Smiod   struct set_element **epp;
65*3d8817e4Smiod 
66*3d8817e4Smiod   for (p = sets; p != NULL; p = p->next)
67*3d8817e4Smiod     if (p->h == h)
68*3d8817e4Smiod       break;
69*3d8817e4Smiod 
70*3d8817e4Smiod   if (p == NULL)
71*3d8817e4Smiod     {
72*3d8817e4Smiod       p = xmalloc (sizeof (struct set_info));
73*3d8817e4Smiod       p->next = sets;
74*3d8817e4Smiod       sets = p;
75*3d8817e4Smiod       p->h = h;
76*3d8817e4Smiod       p->reloc = reloc;
77*3d8817e4Smiod       p->count = 0;
78*3d8817e4Smiod       p->elements = NULL;
79*3d8817e4Smiod     }
80*3d8817e4Smiod   else
81*3d8817e4Smiod     {
82*3d8817e4Smiod       if (p->reloc != reloc)
83*3d8817e4Smiod 	{
84*3d8817e4Smiod 	  einfo (_("%P%X: Different relocs used in set %s\n"),
85*3d8817e4Smiod 		 h->root.string);
86*3d8817e4Smiod 	  return;
87*3d8817e4Smiod 	}
88*3d8817e4Smiod 
89*3d8817e4Smiod       /* Don't permit a set to be constructed from different object
90*3d8817e4Smiod          file formats.  The same reloc may have different results.  We
91*3d8817e4Smiod          actually could sometimes handle this, but the case is
92*3d8817e4Smiod          unlikely to ever arise.  Sometimes constructor symbols are in
93*3d8817e4Smiod          unusual sections, such as the absolute section--this appears
94*3d8817e4Smiod          to be the case in Linux a.out--and in such cases we just
95*3d8817e4Smiod          assume everything is OK.  */
96*3d8817e4Smiod       if (p->elements != NULL
97*3d8817e4Smiod 	  && section->owner != NULL
98*3d8817e4Smiod 	  && p->elements->section->owner != NULL
99*3d8817e4Smiod 	  && strcmp (bfd_get_target (section->owner),
100*3d8817e4Smiod 		     bfd_get_target (p->elements->section->owner)) != 0)
101*3d8817e4Smiod 	{
102*3d8817e4Smiod 	  einfo (_("%P%X: Different object file formats composing set %s\n"),
103*3d8817e4Smiod 		 h->root.string);
104*3d8817e4Smiod 	  return;
105*3d8817e4Smiod 	}
106*3d8817e4Smiod     }
107*3d8817e4Smiod 
108*3d8817e4Smiod   e = xmalloc (sizeof (struct set_element));
109*3d8817e4Smiod   e->next = NULL;
110*3d8817e4Smiod   e->name = name;
111*3d8817e4Smiod   e->section = section;
112*3d8817e4Smiod   e->value = value;
113*3d8817e4Smiod 
114*3d8817e4Smiod   for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
115*3d8817e4Smiod     ;
116*3d8817e4Smiod   *epp = e;
117*3d8817e4Smiod 
118*3d8817e4Smiod   ++p->count;
119*3d8817e4Smiod }
120*3d8817e4Smiod 
121*3d8817e4Smiod /* Get the priority of a g++ global constructor or destructor from the
122*3d8817e4Smiod    symbol name.  */
123*3d8817e4Smiod 
124*3d8817e4Smiod static int
ctor_prio(const char * name)125*3d8817e4Smiod ctor_prio (const char *name)
126*3d8817e4Smiod {
127*3d8817e4Smiod   /* The name will look something like _GLOBAL_$I$65535$test02__Fv.
128*3d8817e4Smiod      There might be extra leading underscores, and the $ characters
129*3d8817e4Smiod      might be something else.  The I might be a D.  */
130*3d8817e4Smiod 
131*3d8817e4Smiod   while (*name == '_')
132*3d8817e4Smiod     ++name;
133*3d8817e4Smiod 
134*3d8817e4Smiod   if (strncmp (name, "GLOBAL_", sizeof "GLOBAL_" - 1) != 0)
135*3d8817e4Smiod     return -1;
136*3d8817e4Smiod 
137*3d8817e4Smiod   name += sizeof "GLOBAL_" - 1;
138*3d8817e4Smiod 
139*3d8817e4Smiod   if (name[0] != name[2])
140*3d8817e4Smiod     return -1;
141*3d8817e4Smiod   if (name[1] != 'I' && name[1] != 'D')
142*3d8817e4Smiod     return -1;
143*3d8817e4Smiod   if (! ISDIGIT (name[3]))
144*3d8817e4Smiod     return -1;
145*3d8817e4Smiod 
146*3d8817e4Smiod   return atoi (name + 3);
147*3d8817e4Smiod }
148*3d8817e4Smiod 
149*3d8817e4Smiod /* This function is used to sort constructor elements by priority.  It
150*3d8817e4Smiod    is called via qsort.  */
151*3d8817e4Smiod 
152*3d8817e4Smiod static int
ctor_cmp(const void * p1,const void * p2)153*3d8817e4Smiod ctor_cmp (const void *p1, const void *p2)
154*3d8817e4Smiod {
155*3d8817e4Smiod   const struct set_element * const *pe1 = p1;
156*3d8817e4Smiod   const struct set_element * const *pe2 = p2;
157*3d8817e4Smiod   const char *n1;
158*3d8817e4Smiod   const char *n2;
159*3d8817e4Smiod   int prio1;
160*3d8817e4Smiod   int prio2;
161*3d8817e4Smiod 
162*3d8817e4Smiod   n1 = (*pe1)->name;
163*3d8817e4Smiod   if (n1 == NULL)
164*3d8817e4Smiod     n1 = "";
165*3d8817e4Smiod   n2 = (*pe2)->name;
166*3d8817e4Smiod   if (n2 == NULL)
167*3d8817e4Smiod     n2 = "";
168*3d8817e4Smiod 
169*3d8817e4Smiod   /* We need to sort in reverse order by priority.  When two
170*3d8817e4Smiod      constructors have the same priority, we should maintain their
171*3d8817e4Smiod      current relative position.  */
172*3d8817e4Smiod 
173*3d8817e4Smiod   prio1 = ctor_prio (n1);
174*3d8817e4Smiod   prio2 = ctor_prio (n2);
175*3d8817e4Smiod 
176*3d8817e4Smiod   /* We sort in reverse order because that is what g++ expects.  */
177*3d8817e4Smiod   if (prio1 < prio2)
178*3d8817e4Smiod     return 1;
179*3d8817e4Smiod   else if (prio1 > prio2)
180*3d8817e4Smiod     return -1;
181*3d8817e4Smiod 
182*3d8817e4Smiod   /* Force a stable sort.  */
183*3d8817e4Smiod 
184*3d8817e4Smiod   if (pe1 < pe2)
185*3d8817e4Smiod     return -1;
186*3d8817e4Smiod   else if (pe1 > pe2)
187*3d8817e4Smiod     return 1;
188*3d8817e4Smiod   else
189*3d8817e4Smiod     return 0;
190*3d8817e4Smiod }
191*3d8817e4Smiod 
192*3d8817e4Smiod /* This function is called after the first phase of the link and
193*3d8817e4Smiod    before the second phase.  At this point all set information has
194*3d8817e4Smiod    been gathered.  We now put the statements to build the sets
195*3d8817e4Smiod    themselves into constructor_list.  */
196*3d8817e4Smiod 
197*3d8817e4Smiod void
ldctor_build_sets(void)198*3d8817e4Smiod ldctor_build_sets (void)
199*3d8817e4Smiod {
200*3d8817e4Smiod   static bfd_boolean called;
201*3d8817e4Smiod   lang_statement_list_type *old;
202*3d8817e4Smiod   bfd_boolean header_printed;
203*3d8817e4Smiod   struct set_info *p;
204*3d8817e4Smiod 
205*3d8817e4Smiod   /* The emulation code may call us directly, but we only want to do
206*3d8817e4Smiod      this once.  */
207*3d8817e4Smiod   if (called)
208*3d8817e4Smiod     return;
209*3d8817e4Smiod   called = TRUE;
210*3d8817e4Smiod 
211*3d8817e4Smiod   if (constructors_sorted)
212*3d8817e4Smiod     {
213*3d8817e4Smiod       for (p = sets; p != NULL; p = p->next)
214*3d8817e4Smiod 	{
215*3d8817e4Smiod 	  int c, i;
216*3d8817e4Smiod 	  struct set_element *e;
217*3d8817e4Smiod 	  struct set_element **array;
218*3d8817e4Smiod 
219*3d8817e4Smiod 	  if (p->elements == NULL)
220*3d8817e4Smiod 	    continue;
221*3d8817e4Smiod 
222*3d8817e4Smiod 	  c = 0;
223*3d8817e4Smiod 	  for (e = p->elements; e != NULL; e = e->next)
224*3d8817e4Smiod 	    ++c;
225*3d8817e4Smiod 
226*3d8817e4Smiod 	  array = xmalloc (c * sizeof *array);
227*3d8817e4Smiod 
228*3d8817e4Smiod 	  i = 0;
229*3d8817e4Smiod 	  for (e = p->elements; e != NULL; e = e->next)
230*3d8817e4Smiod 	    {
231*3d8817e4Smiod 	      array[i] = e;
232*3d8817e4Smiod 	      ++i;
233*3d8817e4Smiod 	    }
234*3d8817e4Smiod 
235*3d8817e4Smiod 	  qsort (array, c, sizeof *array, ctor_cmp);
236*3d8817e4Smiod 
237*3d8817e4Smiod 	  e = array[0];
238*3d8817e4Smiod 	  p->elements = e;
239*3d8817e4Smiod 	  for (i = 0; i < c - 1; i++)
240*3d8817e4Smiod 	    array[i]->next = array[i + 1];
241*3d8817e4Smiod 	  array[i]->next = NULL;
242*3d8817e4Smiod 
243*3d8817e4Smiod 	  free (array);
244*3d8817e4Smiod 	}
245*3d8817e4Smiod     }
246*3d8817e4Smiod 
247*3d8817e4Smiod   old = stat_ptr;
248*3d8817e4Smiod   stat_ptr = &constructor_list;
249*3d8817e4Smiod 
250*3d8817e4Smiod   lang_list_init (stat_ptr);
251*3d8817e4Smiod 
252*3d8817e4Smiod   header_printed = FALSE;
253*3d8817e4Smiod   for (p = sets; p != NULL; p = p->next)
254*3d8817e4Smiod     {
255*3d8817e4Smiod       struct set_element *e;
256*3d8817e4Smiod       reloc_howto_type *howto;
257*3d8817e4Smiod       int reloc_size, size;
258*3d8817e4Smiod 
259*3d8817e4Smiod       /* If the symbol is defined, we may have been invoked from
260*3d8817e4Smiod 	 collect, and the sets may already have been built, so we do
261*3d8817e4Smiod 	 not do anything.  */
262*3d8817e4Smiod       if (p->h->type == bfd_link_hash_defined
263*3d8817e4Smiod 	  || p->h->type == bfd_link_hash_defweak)
264*3d8817e4Smiod 	continue;
265*3d8817e4Smiod 
266*3d8817e4Smiod       /* For each set we build:
267*3d8817e4Smiod 	   set:
268*3d8817e4Smiod 	     .long number_of_elements
269*3d8817e4Smiod 	     .long element0
270*3d8817e4Smiod 	     ...
271*3d8817e4Smiod 	     .long elementN
272*3d8817e4Smiod 	     .long 0
273*3d8817e4Smiod 	 except that we use the right size instead of .long.  When
274*3d8817e4Smiod 	 generating relocatable output, we generate relocs instead of
275*3d8817e4Smiod 	 addresses.  */
276*3d8817e4Smiod       howto = bfd_reloc_type_lookup (output_bfd, p->reloc);
277*3d8817e4Smiod       if (howto == NULL)
278*3d8817e4Smiod 	{
279*3d8817e4Smiod 	  if (link_info.relocatable)
280*3d8817e4Smiod 	    {
281*3d8817e4Smiod 	      einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
282*3d8817e4Smiod 		     bfd_get_target (output_bfd),
283*3d8817e4Smiod 		     bfd_get_reloc_code_name (p->reloc),
284*3d8817e4Smiod 		     p->h->root.string);
285*3d8817e4Smiod 	      continue;
286*3d8817e4Smiod 	    }
287*3d8817e4Smiod 
288*3d8817e4Smiod 	  /* If this is not a relocatable link, all we need is the
289*3d8817e4Smiod 	     size, which we can get from the input BFD.  */
290*3d8817e4Smiod 	  if (p->elements->section->owner != NULL)
291*3d8817e4Smiod 	    howto = bfd_reloc_type_lookup (p->elements->section->owner,
292*3d8817e4Smiod 					   p->reloc);
293*3d8817e4Smiod 	  if (howto == NULL)
294*3d8817e4Smiod 	    {
295*3d8817e4Smiod 	      einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
296*3d8817e4Smiod 		     bfd_get_target (p->elements->section->owner),
297*3d8817e4Smiod 		     bfd_get_reloc_code_name (p->reloc),
298*3d8817e4Smiod 		     p->h->root.string);
299*3d8817e4Smiod 	      continue;
300*3d8817e4Smiod 	    }
301*3d8817e4Smiod 	}
302*3d8817e4Smiod 
303*3d8817e4Smiod       reloc_size = bfd_get_reloc_size (howto);
304*3d8817e4Smiod       switch (reloc_size)
305*3d8817e4Smiod 	{
306*3d8817e4Smiod 	case 1: size = BYTE; break;
307*3d8817e4Smiod 	case 2: size = SHORT; break;
308*3d8817e4Smiod 	case 4: size = LONG; break;
309*3d8817e4Smiod 	case 8:
310*3d8817e4Smiod 	  if (howto->complain_on_overflow == complain_overflow_signed)
311*3d8817e4Smiod 	    size = SQUAD;
312*3d8817e4Smiod 	  else
313*3d8817e4Smiod 	    size = QUAD;
314*3d8817e4Smiod 	  break;
315*3d8817e4Smiod 	default:
316*3d8817e4Smiod 	  einfo (_("%P%X: Unsupported size %d for set %s\n"),
317*3d8817e4Smiod 		 bfd_get_reloc_size (howto), p->h->root.string);
318*3d8817e4Smiod 	  size = LONG;
319*3d8817e4Smiod 	  break;
320*3d8817e4Smiod 	}
321*3d8817e4Smiod 
322*3d8817e4Smiod       lang_add_assignment (exp_assop ('=', ".",
323*3d8817e4Smiod 				      exp_unop (ALIGN_K,
324*3d8817e4Smiod 						exp_intop (reloc_size))));
325*3d8817e4Smiod       lang_add_assignment (exp_assop ('=', p->h->root.string,
326*3d8817e4Smiod 				      exp_nameop (NAME, ".")));
327*3d8817e4Smiod       lang_add_data (size, exp_intop (p->count));
328*3d8817e4Smiod 
329*3d8817e4Smiod       for (e = p->elements; e != NULL; e = e->next)
330*3d8817e4Smiod 	{
331*3d8817e4Smiod 	  if (config.map_file != NULL)
332*3d8817e4Smiod 	    {
333*3d8817e4Smiod 	      int len;
334*3d8817e4Smiod 
335*3d8817e4Smiod 	      if (! header_printed)
336*3d8817e4Smiod 		{
337*3d8817e4Smiod 		  minfo (_("\nSet                 Symbol\n\n"));
338*3d8817e4Smiod 		  header_printed = TRUE;
339*3d8817e4Smiod 		}
340*3d8817e4Smiod 
341*3d8817e4Smiod 	      minfo ("%s", p->h->root.string);
342*3d8817e4Smiod 	      len = strlen (p->h->root.string);
343*3d8817e4Smiod 
344*3d8817e4Smiod 	      if (len >= 19)
345*3d8817e4Smiod 		{
346*3d8817e4Smiod 		  print_nl ();
347*3d8817e4Smiod 		  len = 0;
348*3d8817e4Smiod 		}
349*3d8817e4Smiod 	      while (len < 20)
350*3d8817e4Smiod 		{
351*3d8817e4Smiod 		  print_space ();
352*3d8817e4Smiod 		  ++len;
353*3d8817e4Smiod 		}
354*3d8817e4Smiod 
355*3d8817e4Smiod 	      if (e->name != NULL)
356*3d8817e4Smiod 		minfo ("%T\n", e->name);
357*3d8817e4Smiod 	      else
358*3d8817e4Smiod 		minfo ("%G\n", e->section->owner, e->section, e->value);
359*3d8817e4Smiod 	    }
360*3d8817e4Smiod 
361*3d8817e4Smiod 	  /* Need SEC_KEEP for --gc-sections.  */
362*3d8817e4Smiod 	  if (! bfd_is_abs_section (e->section))
363*3d8817e4Smiod 	    e->section->flags |= SEC_KEEP;
364*3d8817e4Smiod 
365*3d8817e4Smiod 	  if (link_info.relocatable)
366*3d8817e4Smiod 	    lang_add_reloc (p->reloc, howto, e->section, e->name,
367*3d8817e4Smiod 			    exp_intop (e->value));
368*3d8817e4Smiod 	  else
369*3d8817e4Smiod 	    lang_add_data (size, exp_relop (e->section, e->value));
370*3d8817e4Smiod 	}
371*3d8817e4Smiod 
372*3d8817e4Smiod       lang_add_data (size, exp_intop (0));
373*3d8817e4Smiod     }
374*3d8817e4Smiod 
375*3d8817e4Smiod   stat_ptr = old;
376*3d8817e4Smiod }
377