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