1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #include "sysdep.h"
24: #include "bfd.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:
37:
38: lang_statement_list_type constructor_list;
39:
40:
41:
42:
43: bfd_boolean constructors_sorted;
44:
45:
46: struct set_info *sets;
47:
48:
49:
50:
51:
52:
53:
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 = 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 (_("%P%X: Different relocs used in set %s\n"),
85: h->root.string);
86: return;
87: }
88:
89:
90:
91:
92:
93:
94:
95:
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 (_("%P%X: Different object file formats composing set %s\n"),
103: h->root.string);
104: return;
105: }
106: }
107:
108: e = xmalloc (sizeof (struct set_element));
109: e->next = NULL;
110: e->name = name;
111: e->section = section;
112: e->value = value;
113:
114: for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
115: ;
116: *epp = e;
117:
118: ++p->count;
119: }
120:
121:
122:
123:
124: static int
125: ctor_prio (const char *name)
126: {
127:
128:
129:
130:
131: while (*name == '_')
132: ++name;
133:
134: if (! CONST_STRNEQ (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:
150:
151:
152: static int
153: ctor_cmp (const void *p1, const void *p2)
154: {
155: const struct set_element * const *pe1 = p1;
156: const struct set_element * const *pe2 = 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:
170:
171:
172:
173: prio1 = ctor_prio (n1);
174: prio2 = ctor_prio (n2);
175:
176:
177: if (prio1 < prio2)
178: return 1;
179: else if (prio1 > prio2)
180: return -1;
181:
182:
183:
184: if (pe1 < pe2)
185: return -1;
186: else if (pe1 > pe2)
187: return 1;
188: else
189: return 0;
190: }
191:
192:
193:
194:
195:
196:
197: void
198: ldctor_build_sets (void)
199: {
200: static bfd_boolean called;
201: lang_statement_list_type *old;
202: bfd_boolean header_printed;
203: struct set_info *p;
204:
205:
206:
207: if (called)
208: return;
209: called = TRUE;
210:
211: if (constructors_sorted)
212: {
213: for (p = sets; p != NULL; p = p->next)
214: {
215: int c, i;
216: struct set_element *e;
217: struct set_element **array;
218:
219: if (p->elements == NULL)
220: continue;
221:
222: c = 0;
223: for (e = p->elements; e != NULL; e = e->next)
224: ++c;
225:
226: array = xmalloc (c * sizeof *array);
227:
228: i = 0;
229: for (e = p->elements; e != NULL; e = e->next)
230: {
231: array[i] = e;
232: ++i;
233: }
234:
235: qsort (array, c, sizeof *array, ctor_cmp);
236:
237: e = array[0];
238: p->elements = e;
239: for (i = 0; i < c - 1; i++)
240: array[i]->next = array[i + 1];
241: array[i]->next = NULL;
242:
243: free (array);
244: }
245: }
246:
247: old = stat_ptr;
248: stat_ptr = &constructor_list;
249:
250: lang_list_init (stat_ptr);
251:
252: header_printed = FALSE;
253: for (p = sets; p != NULL; p = p->next)
254: {
255: struct set_element *e;
256: reloc_howto_type *howto;
257: int reloc_size, size;
258:
259:
260:
261:
262: if (p->h->type == bfd_link_hash_defined
263: || p->h->type == bfd_link_hash_defweak)
264: continue;
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276: howto = bfd_reloc_type_lookup (output_bfd, p->reloc);
277: if (howto == NULL)
278: {
279: if (link_info.relocatable)
280: {
281: einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
282: bfd_get_target (output_bfd),
283: bfd_get_reloc_code_name (p->reloc),
284: p->h->root.string);
285: continue;
286: }
287:
288:
289:
290: if (p->elements->section->owner != NULL)
291: howto = bfd_reloc_type_lookup (p->elements->section->owner,
292: p->reloc);
293: if (howto == NULL)
294: {
295: einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
296: bfd_get_target (p->elements->section->owner),
297: bfd_get_reloc_code_name (p->reloc),
298: p->h->root.string);
299: continue;
300: }
301: }
302:
303: reloc_size = bfd_get_reloc_size (howto);
304: switch (reloc_size)
305: {
306: case 1: size = BYTE; break;
307: case 2: size = SHORT; break;
308: case 4: size = LONG; break;
309: case 8:
310: if (howto->complain_on_overflow == complain_overflow_signed)
311: size = SQUAD;
312: else
313: size = QUAD;
314: break;
315: default:
316: einfo (_("%P%X: Unsupported size %d for set %s\n"),
317: bfd_get_reloc_size (howto), p->h->root.string);
318: size = LONG;
319: break;
320: }
321:
322: lang_add_assignment (exp_assop ('=', ".",
323: exp_unop (ALIGN_K,
324: exp_intop (reloc_size))));
325: lang_add_assignment (exp_assop ('=', p->h->root.string,
326: exp_nameop (NAME, ".")));
327: lang_add_data (size, exp_intop (p->count));
328:
329: for (e = p->elements; e != NULL; e = e->next)
330: {
331: if (config.map_file != NULL)
332: {
333: int len;
334:
335: if (! header_printed)
336: {
337: minfo (_("\nSet Symbol\n\n"));
338: header_printed = TRUE;
339: }
340:
341: minfo ("%s", p->h->root.string);
342: len = strlen (p->h->root.string);
343:
344: if (len >= 19)
345: {
346: print_nl ();
347: len = 0;
348: }
349: while (len < 20)
350: {
351: print_space ();
352: ++len;
353: }
354:
355: if (e->name != NULL)
356: minfo ("%T\n", e->name);
357: else
358: minfo ("%G\n", e->section->owner, e->section, e->value);
359: }
360:
361:
362: if (! bfd_is_abs_section (e->section))
363: e->section->flags |= SEC_KEEP;
364:
365: if (link_info.relocatable)
366: lang_add_reloc (p->reloc, howto, e->section, e->name,
367: exp_intop (e->value));
368: else
369: lang_add_data (size, exp_relop (e->section, e->value));
370: }
371:
372: lang_add_data (size, exp_intop (0));
373: }
374:
375: stat_ptr = old;
376: }