* elf32-spu.c (spu_stub_name): Don't put input section in stub name.
[deliverable/binutils-gdb.git] / bfd / elf32-spu.c
1 /* SPU specific support for 32-bit ELF
2
3 Copyright 2006, 2007 Free Software Foundation, Inc.
4
5 This file is part of BFD, the Binary File Descriptor library.
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 2 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 along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "bfdlink.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/spu.h"
27 #include "elf32-spu.h"
28
29 /* We use RELA style relocs. Don't define USE_REL. */
30
31 static bfd_reloc_status_type spu_elf_rel9 (bfd *, arelent *, asymbol *,
32 void *, asection *,
33 bfd *, char **);
34
35 /* Values of type 'enum elf_spu_reloc_type' are used to index this
36 array, so it must be declared in the order of that type. */
37
38 static reloc_howto_type elf_howto_table[] = {
39 HOWTO (R_SPU_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont,
40 bfd_elf_generic_reloc, "SPU_NONE",
41 FALSE, 0, 0x00000000, FALSE),
42 HOWTO (R_SPU_ADDR10, 4, 2, 10, FALSE, 14, complain_overflow_bitfield,
43 bfd_elf_generic_reloc, "SPU_ADDR10",
44 FALSE, 0, 0x00ffc000, FALSE),
45 HOWTO (R_SPU_ADDR16, 2, 2, 16, FALSE, 7, complain_overflow_bitfield,
46 bfd_elf_generic_reloc, "SPU_ADDR16",
47 FALSE, 0, 0x007fff80, FALSE),
48 HOWTO (R_SPU_ADDR16_HI, 16, 2, 16, FALSE, 7, complain_overflow_bitfield,
49 bfd_elf_generic_reloc, "SPU_ADDR16_HI",
50 FALSE, 0, 0x007fff80, FALSE),
51 HOWTO (R_SPU_ADDR16_LO, 0, 2, 16, FALSE, 7, complain_overflow_dont,
52 bfd_elf_generic_reloc, "SPU_ADDR16_LO",
53 FALSE, 0, 0x007fff80, FALSE),
54 HOWTO (R_SPU_ADDR18, 0, 2, 18, FALSE, 7, complain_overflow_bitfield,
55 bfd_elf_generic_reloc, "SPU_ADDR18",
56 FALSE, 0, 0x01ffff80, FALSE),
57 HOWTO (R_SPU_ADDR32, 0, 2, 32, FALSE, 0, complain_overflow_dont,
58 bfd_elf_generic_reloc, "SPU_ADDR32",
59 FALSE, 0, 0xffffffff, FALSE),
60 HOWTO (R_SPU_REL16, 2, 2, 16, TRUE, 7, complain_overflow_bitfield,
61 bfd_elf_generic_reloc, "SPU_REL16",
62 FALSE, 0, 0x007fff80, TRUE),
63 HOWTO (R_SPU_ADDR7, 0, 2, 7, FALSE, 14, complain_overflow_dont,
64 bfd_elf_generic_reloc, "SPU_ADDR7",
65 FALSE, 0, 0x001fc000, FALSE),
66 HOWTO (R_SPU_REL9, 2, 2, 9, TRUE, 0, complain_overflow_signed,
67 spu_elf_rel9, "SPU_REL9",
68 FALSE, 0, 0x0180007f, TRUE),
69 HOWTO (R_SPU_REL9I, 2, 2, 9, TRUE, 0, complain_overflow_signed,
70 spu_elf_rel9, "SPU_REL9I",
71 FALSE, 0, 0x0000c07f, TRUE),
72 HOWTO (R_SPU_ADDR10I, 0, 2, 10, FALSE, 14, complain_overflow_signed,
73 bfd_elf_generic_reloc, "SPU_ADDR10I",
74 FALSE, 0, 0x00ffc000, FALSE),
75 HOWTO (R_SPU_ADDR16I, 0, 2, 16, FALSE, 7, complain_overflow_signed,
76 bfd_elf_generic_reloc, "SPU_ADDR16I",
77 FALSE, 0, 0x007fff80, FALSE),
78 HOWTO (R_SPU_REL32, 0, 2, 32, TRUE, 0, complain_overflow_dont,
79 bfd_elf_generic_reloc, "SPU_REL32",
80 FALSE, 0, 0xffffffff, TRUE),
81 };
82
83 static struct bfd_elf_special_section const spu_elf_special_sections[] = {
84 { ".toe", 4, 0, SHT_NOBITS, SHF_ALLOC },
85 { NULL, 0, 0, 0, 0 }
86 };
87
88 static enum elf_spu_reloc_type
89 spu_elf_bfd_to_reloc_type (bfd_reloc_code_real_type code)
90 {
91 switch (code)
92 {
93 default:
94 return R_SPU_NONE;
95 case BFD_RELOC_SPU_IMM10W:
96 return R_SPU_ADDR10;
97 case BFD_RELOC_SPU_IMM16W:
98 return R_SPU_ADDR16;
99 case BFD_RELOC_SPU_LO16:
100 return R_SPU_ADDR16_LO;
101 case BFD_RELOC_SPU_HI16:
102 return R_SPU_ADDR16_HI;
103 case BFD_RELOC_SPU_IMM18:
104 return R_SPU_ADDR18;
105 case BFD_RELOC_SPU_PCREL16:
106 return R_SPU_REL16;
107 case BFD_RELOC_SPU_IMM7:
108 return R_SPU_ADDR7;
109 case BFD_RELOC_SPU_IMM8:
110 return R_SPU_NONE;
111 case BFD_RELOC_SPU_PCREL9a:
112 return R_SPU_REL9;
113 case BFD_RELOC_SPU_PCREL9b:
114 return R_SPU_REL9I;
115 case BFD_RELOC_SPU_IMM10:
116 return R_SPU_ADDR10I;
117 case BFD_RELOC_SPU_IMM16:
118 return R_SPU_ADDR16I;
119 case BFD_RELOC_32:
120 return R_SPU_ADDR32;
121 case BFD_RELOC_32_PCREL:
122 return R_SPU_REL32;
123 }
124 }
125
126 static void
127 spu_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
128 arelent *cache_ptr,
129 Elf_Internal_Rela *dst)
130 {
131 enum elf_spu_reloc_type r_type;
132
133 r_type = (enum elf_spu_reloc_type) ELF32_R_TYPE (dst->r_info);
134 BFD_ASSERT (r_type < R_SPU_max);
135 cache_ptr->howto = &elf_howto_table[(int) r_type];
136 }
137
138 static reloc_howto_type *
139 spu_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
140 bfd_reloc_code_real_type code)
141 {
142 return elf_howto_table + spu_elf_bfd_to_reloc_type (code);
143 }
144
145 /* Apply R_SPU_REL9 and R_SPU_REL9I relocs. */
146
147 static bfd_reloc_status_type
148 spu_elf_rel9 (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
149 void *data, asection *input_section,
150 bfd *output_bfd, char **error_message)
151 {
152 bfd_size_type octets;
153 bfd_vma val;
154 long insn;
155
156 /* If this is a relocatable link (output_bfd test tells us), just
157 call the generic function. Any adjustment will be done at final
158 link time. */
159 if (output_bfd != NULL)
160 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
161 input_section, output_bfd, error_message);
162
163 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
164 return bfd_reloc_outofrange;
165 octets = reloc_entry->address * bfd_octets_per_byte (abfd);
166
167 /* Get symbol value. */
168 val = 0;
169 if (!bfd_is_com_section (symbol->section))
170 val = symbol->value;
171 if (symbol->section->output_section)
172 val += symbol->section->output_section->vma;
173
174 val += reloc_entry->addend;
175
176 /* Make it pc-relative. */
177 val -= input_section->output_section->vma + input_section->output_offset;
178
179 val >>= 2;
180 if (val + 256 >= 512)
181 return bfd_reloc_overflow;
182
183 insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
184
185 /* Move two high bits of value to REL9I and REL9 position.
186 The mask will take care of selecting the right field. */
187 val = (val & 0x7f) | ((val & 0x180) << 7) | ((val & 0x180) << 16);
188 insn &= ~reloc_entry->howto->dst_mask;
189 insn |= val & reloc_entry->howto->dst_mask;
190 bfd_put_32 (abfd, insn, (bfd_byte *) data + octets);
191 return bfd_reloc_ok;
192 }
193
194 static bfd_boolean
195 spu_elf_new_section_hook (bfd *abfd, asection *sec)
196 {
197 if (!sec->used_by_bfd)
198 {
199 struct _spu_elf_section_data *sdata;
200
201 sdata = bfd_zalloc (abfd, sizeof (*sdata));
202 if (sdata == NULL)
203 return FALSE;
204 sec->used_by_bfd = sdata;
205 }
206
207 return _bfd_elf_new_section_hook (abfd, sec);
208 }
209
210 /* Specially mark defined symbols named _EAR_* with BSF_KEEP so that
211 strip --strip-unneeded will not remove them. */
212
213 static void
214 spu_elf_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym)
215 {
216 if (sym->name != NULL
217 && sym->section != bfd_abs_section_ptr
218 && strncmp (sym->name, "_EAR_", 5) == 0)
219 sym->flags |= BSF_KEEP;
220 }
221
222 /* SPU ELF linker hash table. */
223
224 struct spu_link_hash_table
225 {
226 struct elf_link_hash_table elf;
227
228 /* The stub hash table. */
229 struct bfd_hash_table stub_hash_table;
230
231 /* Shortcuts to overlay sections. */
232 asection *stub;
233 asection *ovtab;
234
235 struct elf_link_hash_entry *ovly_load;
236
237 /* An array of two output sections per overlay region, chosen such that
238 the first section vma is the overlay buffer vma (ie. the section has
239 the lowest vma in the group that occupy the region), and the second
240 section vma+size specifies the end of the region. We keep pointers
241 to sections like this because section vmas may change when laying
242 them out. */
243 asection **ovl_region;
244
245 /* Number of overlay buffers. */
246 unsigned int num_buf;
247
248 /* Total number of overlays. */
249 unsigned int num_overlays;
250
251 /* Set if we should emit symbols for stubs. */
252 unsigned int emit_stub_syms:1;
253
254 /* Set if we want stubs on calls out of overlay regions to
255 non-overlay regions. */
256 unsigned int non_overlay_stubs : 1;
257
258 /* Set on error. */
259 unsigned int stub_overflow : 1;
260 };
261
262 #define spu_hash_table(p) \
263 ((struct spu_link_hash_table *) ((p)->hash))
264
265 struct spu_stub_hash_entry
266 {
267 struct bfd_hash_entry root;
268
269 /* Destination of this stub. */
270 asection *target_section;
271 bfd_vma target_off;
272
273 /* Offset of entry in stub section. */
274 bfd_vma off;
275
276 /* Offset from this stub to stub that loads the overlay index. */
277 bfd_vma delta;
278 };
279
280 /* Create an entry in a spu stub hash table. */
281
282 static struct bfd_hash_entry *
283 stub_hash_newfunc (struct bfd_hash_entry *entry,
284 struct bfd_hash_table *table,
285 const char *string)
286 {
287 /* Allocate the structure if it has not already been allocated by a
288 subclass. */
289 if (entry == NULL)
290 {
291 entry = bfd_hash_allocate (table, sizeof (struct spu_stub_hash_entry));
292 if (entry == NULL)
293 return entry;
294 }
295
296 /* Call the allocation method of the superclass. */
297 entry = bfd_hash_newfunc (entry, table, string);
298 if (entry != NULL)
299 {
300 struct spu_stub_hash_entry *sh = (struct spu_stub_hash_entry *) entry;
301
302 sh->target_section = NULL;
303 sh->target_off = 0;
304 sh->off = 0;
305 sh->delta = 0;
306 }
307
308 return entry;
309 }
310
311 /* Create a spu ELF linker hash table. */
312
313 static struct bfd_link_hash_table *
314 spu_elf_link_hash_table_create (bfd *abfd)
315 {
316 struct spu_link_hash_table *htab;
317
318 htab = bfd_malloc (sizeof (*htab));
319 if (htab == NULL)
320 return NULL;
321
322 if (!_bfd_elf_link_hash_table_init (&htab->elf, abfd,
323 _bfd_elf_link_hash_newfunc,
324 sizeof (struct elf_link_hash_entry)))
325 {
326 free (htab);
327 return NULL;
328 }
329
330 /* Init the stub hash table too. */
331 if (!bfd_hash_table_init (&htab->stub_hash_table, stub_hash_newfunc,
332 sizeof (struct spu_stub_hash_entry)))
333 return NULL;
334
335 memset (&htab->stub, 0,
336 sizeof (*htab) - offsetof (struct spu_link_hash_table, stub));
337
338 return &htab->elf.root;
339 }
340
341 /* Free the derived linker hash table. */
342
343 static void
344 spu_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
345 {
346 struct spu_link_hash_table *ret = (struct spu_link_hash_table *) hash;
347
348 bfd_hash_table_free (&ret->stub_hash_table);
349 _bfd_generic_link_hash_table_free (hash);
350 }
351
352 /* Find the symbol for the given R_SYMNDX in IBFD and set *HP and *SYMP
353 to (hash, NULL) for global symbols, and (NULL, sym) for locals. Set
354 *SYMSECP to the symbol's section. *LOCSYMSP caches local syms. */
355
356 static bfd_boolean
357 get_sym_h (struct elf_link_hash_entry **hp,
358 Elf_Internal_Sym **symp,
359 asection **symsecp,
360 Elf_Internal_Sym **locsymsp,
361 unsigned long r_symndx,
362 bfd *ibfd)
363 {
364 Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
365
366 if (r_symndx >= symtab_hdr->sh_info)
367 {
368 struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd);
369 struct elf_link_hash_entry *h;
370
371 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
372 while (h->root.type == bfd_link_hash_indirect
373 || h->root.type == bfd_link_hash_warning)
374 h = (struct elf_link_hash_entry *) h->root.u.i.link;
375
376 if (hp != NULL)
377 *hp = h;
378
379 if (symp != NULL)
380 *symp = NULL;
381
382 if (symsecp != NULL)
383 {
384 asection *symsec = NULL;
385 if (h->root.type == bfd_link_hash_defined
386 || h->root.type == bfd_link_hash_defweak)
387 symsec = h->root.u.def.section;
388 *symsecp = symsec;
389 }
390 }
391 else
392 {
393 Elf_Internal_Sym *sym;
394 Elf_Internal_Sym *locsyms = *locsymsp;
395
396 if (locsyms == NULL)
397 {
398 locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
399 if (locsyms == NULL)
400 locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
401 symtab_hdr->sh_info,
402 0, NULL, NULL, NULL);
403 if (locsyms == NULL)
404 return FALSE;
405 *locsymsp = locsyms;
406 }
407 sym = locsyms + r_symndx;
408
409 if (hp != NULL)
410 *hp = NULL;
411
412 if (symp != NULL)
413 *symp = sym;
414
415 if (symsecp != NULL)
416 {
417 asection *symsec = NULL;
418 if ((sym->st_shndx != SHN_UNDEF
419 && sym->st_shndx < SHN_LORESERVE)
420 || sym->st_shndx > SHN_HIRESERVE)
421 symsec = bfd_section_from_elf_index (ibfd, sym->st_shndx);
422 *symsecp = symsec;
423 }
424 }
425 return TRUE;
426 }
427
428 /* Build a name for an entry in the stub hash table. We can't use a
429 local symbol name because ld -r might generate duplicate local symbols. */
430
431 static char *
432 spu_stub_name (const asection *sym_sec,
433 const struct elf_link_hash_entry *h,
434 const Elf_Internal_Rela *rel)
435 {
436 char *stub_name;
437 bfd_size_type len;
438
439 if (h)
440 {
441 len = strlen (h->root.root.string) + 1 + 8 + 1;
442 stub_name = bfd_malloc (len);
443 if (stub_name == NULL)
444 return stub_name;
445
446 sprintf (stub_name, "%s+%x",
447 h->root.root.string,
448 (int) rel->r_addend & 0xffffffff);
449 len -= 8;
450 }
451 else
452 {
453 len = 8 + 1 + 8 + 1 + 8 + 1;
454 stub_name = bfd_malloc (len);
455 if (stub_name == NULL)
456 return stub_name;
457
458 sprintf (stub_name, "%x:%x+%x",
459 sym_sec->id & 0xffffffff,
460 (int) ELF32_R_SYM (rel->r_info) & 0xffffffff,
461 (int) rel->r_addend & 0xffffffff);
462 len = strlen (stub_name);
463 }
464
465 if (stub_name[len - 2] == '+'
466 && stub_name[len - 1] == '0'
467 && stub_name[len] == 0)
468 stub_name[len - 2] = 0;
469
470 return stub_name;
471 }
472
473 /* Create the note section if not already present. This is done early so
474 that the linker maps the sections to the right place in the output. */
475
476 bfd_boolean
477 spu_elf_create_sections (bfd *output_bfd, struct bfd_link_info *info)
478 {
479 bfd *ibfd;
480
481 for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->next)
482 if (bfd_get_section_by_name (ibfd, SPU_PTNOTE_SPUNAME) != NULL)
483 break;
484
485 if (ibfd == NULL)
486 {
487 /* Make SPU_PTNOTE_SPUNAME section. */
488 asection *s;
489 size_t name_len;
490 size_t size;
491 bfd_byte *data;
492 flagword flags;
493
494 ibfd = info->input_bfds;
495 flags = SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
496 s = bfd_make_section_anyway_with_flags (ibfd, SPU_PTNOTE_SPUNAME, flags);
497 if (s == NULL
498 || !bfd_set_section_alignment (ibfd, s, 4))
499 return FALSE;
500
501 name_len = strlen (bfd_get_filename (output_bfd)) + 1;
502 size = 12 + ((sizeof (SPU_PLUGIN_NAME) + 3) & -4);
503 size += (name_len + 3) & -4;
504
505 if (!bfd_set_section_size (ibfd, s, size))
506 return FALSE;
507
508 data = bfd_zalloc (ibfd, size);
509 if (data == NULL)
510 return FALSE;
511
512 bfd_put_32 (ibfd, sizeof (SPU_PLUGIN_NAME), data + 0);
513 bfd_put_32 (ibfd, name_len, data + 4);
514 bfd_put_32 (ibfd, 1, data + 8);
515 memcpy (data + 12, SPU_PLUGIN_NAME, sizeof (SPU_PLUGIN_NAME));
516 memcpy (data + 12 + ((sizeof (SPU_PLUGIN_NAME) + 3) & -4),
517 bfd_get_filename (output_bfd), name_len);
518 s->contents = data;
519 }
520
521 return TRUE;
522 }
523
524 /* Return the section that should be marked against GC for a given
525 relocation. */
526
527 static asection *
528 spu_elf_gc_mark_hook (asection *sec,
529 struct bfd_link_info *info ATTRIBUTE_UNUSED,
530 Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
531 struct elf_link_hash_entry *h,
532 Elf_Internal_Sym *sym)
533 {
534 if (h != NULL)
535 {
536 switch (h->root.type)
537 {
538 case bfd_link_hash_defined:
539 case bfd_link_hash_defweak:
540 return h->root.u.def.section;
541
542 case bfd_link_hash_common:
543 return h->root.u.c.p->section;
544
545 default:
546 break;
547 }
548 }
549 else
550 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
551
552 return NULL;
553 }
554
555 /* qsort predicate to sort sections by vma. */
556
557 static int
558 sort_sections (const void *a, const void *b)
559 {
560 const asection *const *s1 = a;
561 const asection *const *s2 = b;
562 bfd_signed_vma delta = (*s1)->vma - (*s2)->vma;
563
564 if (delta != 0)
565 return delta < 0 ? -1 : 1;
566
567 return (*s1)->index - (*s2)->index;
568 }
569
570 /* Identify overlays in the output bfd, and number them. */
571
572 bfd_boolean
573 spu_elf_find_overlays (bfd *output_bfd, struct bfd_link_info *info)
574 {
575 struct spu_link_hash_table *htab = spu_hash_table (info);
576 asection **alloc_sec;
577 unsigned int i, n, ovl_index, num_buf;
578 asection *s;
579 bfd_vma ovl_end;
580
581 if (output_bfd->section_count < 2)
582 return FALSE;
583
584 alloc_sec = bfd_malloc (output_bfd->section_count * sizeof (*alloc_sec));
585 if (alloc_sec == NULL)
586 return FALSE;
587
588 /* Pick out all the alloced sections. */
589 for (n = 0, s = output_bfd->sections; s != NULL; s = s->next)
590 if ((s->flags & SEC_ALLOC) != 0
591 && (s->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != SEC_THREAD_LOCAL
592 && s->size != 0)
593 alloc_sec[n++] = s;
594
595 if (n == 0)
596 {
597 free (alloc_sec);
598 return FALSE;
599 }
600
601 /* Sort them by vma. */
602 qsort (alloc_sec, n, sizeof (*alloc_sec), sort_sections);
603
604 /* Look for overlapping vmas. Any with overlap must be overlays.
605 Count them. Also count the number of overlay regions and for
606 each region save a section from that region with the lowest vma
607 and another section with the highest end vma. */
608 ovl_end = alloc_sec[0]->vma + alloc_sec[0]->size;
609 for (ovl_index = 0, num_buf = 0, i = 1; i < n; i++)
610 {
611 s = alloc_sec[i];
612 if (s->vma < ovl_end)
613 {
614 asection *s0 = alloc_sec[i - 1];
615
616 if (spu_elf_section_data (s0)->ovl_index == 0)
617 {
618 spu_elf_section_data (s0)->ovl_index = ++ovl_index;
619 alloc_sec[num_buf * 2] = s0;
620 alloc_sec[num_buf * 2 + 1] = s0;
621 num_buf++;
622 }
623 spu_elf_section_data (s)->ovl_index = ++ovl_index;
624 if (ovl_end < s->vma + s->size)
625 {
626 ovl_end = s->vma + s->size;
627 alloc_sec[num_buf * 2 - 1] = s;
628 }
629 }
630 else
631 ovl_end = s->vma + s->size;
632 }
633
634 htab->num_overlays = ovl_index;
635 htab->num_buf = num_buf;
636 if (ovl_index == 0)
637 {
638 free (alloc_sec);
639 return FALSE;
640 }
641
642 alloc_sec = bfd_realloc (alloc_sec, num_buf * 2 * sizeof (*alloc_sec));
643 if (alloc_sec == NULL)
644 return FALSE;
645
646 htab->ovl_region = alloc_sec;
647 return TRUE;
648 }
649
650 /* One of these per stub. */
651 #define SIZEOF_STUB1 8
652 #define ILA_79 0x4200004f /* ila $79,function_address */
653 #define BR 0x32000000 /* br stub2 */
654
655 /* One of these per overlay. */
656 #define SIZEOF_STUB2 8
657 #define ILA_78 0x4200004e /* ila $78,overlay_number */
658 /* br __ovly_load */
659 #define NOP 0x40200000
660
661 /* Return true for all relative and absolute branch and hint instructions.
662 bra 00110000 0..
663 brasl 00110001 0..
664 br 00110010 0..
665 brsl 00110011 0..
666 brz 00100000 0..
667 brnz 00100001 0..
668 brhz 00100010 0..
669 brhnz 00100011 0..
670 hbra 0001000..
671 hbrr 0001001.. */
672
673 static bfd_boolean
674 is_branch (const unsigned char *insn)
675 {
676 return (((insn[0] & 0xec) == 0x20 && (insn[1] & 0x80) == 0)
677 || (insn[0] & 0xfc) == 0x10);
678 }
679
680 /* Return TRUE if this reloc symbol should possibly go via an overlay stub. */
681
682 static bfd_boolean
683 needs_ovl_stub (const char *sym_name,
684 asection *sym_sec,
685 asection *input_section,
686 struct spu_link_hash_table *htab,
687 bfd_boolean is_branch)
688 {
689 if (htab->num_overlays == 0)
690 return FALSE;
691
692 if (sym_sec == NULL
693 || sym_sec->output_section == NULL)
694 return FALSE;
695
696 /* setjmp always goes via an overlay stub, because then the return
697 and hence the longjmp goes via __ovly_return. That magically
698 makes setjmp/longjmp between overlays work. */
699 if (strncmp (sym_name, "setjmp", 6) == 0
700 && (sym_name[6] == '\0' || sym_name[6] == '@'))
701 return TRUE;
702
703 /* Usually, symbols in non-overlay sections don't need stubs. */
704 if (spu_elf_section_data (sym_sec->output_section)->ovl_index == 0
705 && !htab->non_overlay_stubs)
706 return FALSE;
707
708 /* A reference from some other section to a symbol in an overlay
709 section needs a stub. */
710 if (spu_elf_section_data (sym_sec->output_section)->ovl_index
711 != spu_elf_section_data (input_section->output_section)->ovl_index)
712 return TRUE;
713
714 /* If this insn isn't a branch then we are possibly taking the
715 address of a function and passing it out somehow. */
716 return !is_branch;
717 }
718
719 struct stubarr {
720 struct spu_stub_hash_entry **sh;
721 unsigned int count;
722 };
723
724 /* Called via bfd_hash_traverse to set up pointers to all symbols
725 in the stub hash table. */
726
727 static bfd_boolean
728 populate_stubs (struct bfd_hash_entry *bh, void *inf)
729 {
730 struct stubarr *stubs = inf;
731
732 stubs->sh[--stubs->count] = (struct spu_stub_hash_entry *) bh;
733 return TRUE;
734 }
735
736 /* qsort predicate to sort stubs by overlay number. */
737
738 static int
739 sort_stubs (const void *a, const void *b)
740 {
741 const struct spu_stub_hash_entry *const *sa = a;
742 const struct spu_stub_hash_entry *const *sb = b;
743 int i;
744 bfd_signed_vma d;
745
746 i = spu_elf_section_data ((*sa)->target_section->output_section)->ovl_index;
747 i -= spu_elf_section_data ((*sb)->target_section->output_section)->ovl_index;
748 if (i != 0)
749 return i;
750
751 d = ((*sa)->target_section->output_section->vma
752 + (*sa)->target_section->output_offset
753 + (*sa)->target_off
754 - (*sb)->target_section->output_section->vma
755 - (*sb)->target_section->output_offset
756 - (*sb)->target_off);
757 if (d != 0)
758 return d < 0 ? -1 : 1;
759
760 /* Two functions at the same address. Aliases perhaps. */
761 i = strcmp ((*sb)->root.string, (*sa)->root.string);
762 BFD_ASSERT (i != 0);
763 return i;
764 }
765
766 /* Allocate space for overlay call and return stubs. */
767
768 bfd_boolean
769 spu_elf_size_stubs (bfd *output_bfd,
770 struct bfd_link_info *info,
771 int non_overlay_stubs,
772 asection **stub,
773 asection **ovtab,
774 asection **toe)
775 {
776 struct spu_link_hash_table *htab = spu_hash_table (info);
777 bfd *ibfd;
778 struct stubarr stubs;
779 unsigned i, group;
780 flagword flags;
781
782 htab->non_overlay_stubs = non_overlay_stubs;
783 stubs.count = 0;
784 for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
785 {
786 extern const bfd_target bfd_elf32_spu_vec;
787 Elf_Internal_Shdr *symtab_hdr;
788 asection *section;
789 Elf_Internal_Sym *local_syms = NULL;
790
791 if (ibfd->xvec != &bfd_elf32_spu_vec)
792 continue;
793
794 /* We'll need the symbol table in a second. */
795 symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
796 if (symtab_hdr->sh_info == 0)
797 continue;
798
799 /* Walk over each section attached to the input bfd. */
800 for (section = ibfd->sections; section != NULL; section = section->next)
801 {
802 Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
803
804 /* If there aren't any relocs, then there's nothing more to do. */
805 if ((section->flags & SEC_RELOC) == 0
806 || (section->flags & SEC_ALLOC) == 0
807 || (section->flags & SEC_LOAD) == 0
808 || section->reloc_count == 0)
809 continue;
810
811 /* If this section is a link-once section that will be
812 discarded, then don't create any stubs. */
813 if (section->output_section == NULL
814 || section->output_section->owner != output_bfd)
815 continue;
816
817 /* Get the relocs. */
818 internal_relocs
819 = _bfd_elf_link_read_relocs (ibfd, section, NULL, NULL,
820 info->keep_memory);
821 if (internal_relocs == NULL)
822 goto error_ret_free_local;
823
824 /* Now examine each relocation. */
825 irela = internal_relocs;
826 irelaend = irela + section->reloc_count;
827 for (; irela < irelaend; irela++)
828 {
829 enum elf_spu_reloc_type r_type;
830 unsigned int r_indx;
831 asection *sym_sec;
832 Elf_Internal_Sym *sym;
833 struct elf_link_hash_entry *h;
834 const char *sym_name;
835 char *stub_name;
836 struct spu_stub_hash_entry *sh;
837 unsigned int sym_type;
838 enum _insn_type { non_branch, branch, call } insn_type;
839
840 r_type = ELF32_R_TYPE (irela->r_info);
841 r_indx = ELF32_R_SYM (irela->r_info);
842
843 if (r_type >= R_SPU_max)
844 {
845 bfd_set_error (bfd_error_bad_value);
846 goto error_ret_free_internal;
847 }
848
849 /* Determine the reloc target section. */
850 if (!get_sym_h (&h, &sym, &sym_sec, &local_syms, r_indx, ibfd))
851 goto error_ret_free_internal;
852
853 if (sym_sec == NULL
854 || sym_sec->output_section == NULL
855 || sym_sec->output_section->owner != output_bfd)
856 continue;
857
858 /* Ensure no stubs for user supplied overlay manager syms. */
859 if (h != NULL
860 && (strcmp (h->root.root.string, "__ovly_load") == 0
861 || strcmp (h->root.root.string, "__ovly_return") == 0))
862 continue;
863
864 insn_type = non_branch;
865 if (r_type == R_SPU_REL16
866 || r_type == R_SPU_ADDR16)
867 {
868 unsigned char insn[4];
869
870 if (!bfd_get_section_contents (ibfd, section, insn,
871 irela->r_offset, 4))
872 goto error_ret_free_internal;
873
874 if (is_branch (insn))
875 {
876 insn_type = branch;
877 if ((insn[0] & 0xfd) == 0x31)
878 insn_type = call;
879 }
880 }
881
882 /* We are only interested in function symbols. */
883 if (h != NULL)
884 {
885 sym_type = h->type;
886 sym_name = h->root.root.string;
887 }
888 else
889 {
890 sym_type = ELF_ST_TYPE (sym->st_info);
891 sym_name = bfd_elf_sym_name (sym_sec->owner,
892 symtab_hdr,
893 sym,
894 sym_sec);
895 }
896 if (sym_type != STT_FUNC)
897 {
898 /* It's common for people to write assembly and forget
899 to give function symbols the right type. Handle
900 calls to such symbols, but warn so that (hopefully)
901 people will fix their code. We need the symbol
902 type to be correct to distinguish function pointer
903 initialisation from other pointer initialisation. */
904 if (insn_type == call)
905 (*_bfd_error_handler) (_("warning: call to non-function"
906 " symbol %s defined in %B"),
907 sym_sec->owner, sym_name);
908 else
909 continue;
910 }
911
912 if (!needs_ovl_stub (sym_name, sym_sec, section, htab,
913 insn_type != non_branch))
914 continue;
915
916 stub_name = spu_stub_name (sym_sec, h, irela);
917 if (stub_name == NULL)
918 goto error_ret_free_internal;
919
920 sh = (struct spu_stub_hash_entry *)
921 bfd_hash_lookup (&htab->stub_hash_table, stub_name,
922 TRUE, FALSE);
923 if (sh == NULL)
924 {
925 free (stub_name);
926 error_ret_free_internal:
927 if (elf_section_data (section)->relocs != internal_relocs)
928 free (internal_relocs);
929 error_ret_free_local:
930 if (local_syms != NULL
931 && (symtab_hdr->contents
932 != (unsigned char *) local_syms))
933 free (local_syms);
934 return FALSE;
935 }
936
937 /* If this entry isn't new, we already have a stub. */
938 if (sh->target_section != NULL)
939 {
940 free (stub_name);
941 continue;
942 }
943
944 sh->target_section = sym_sec;
945 if (h != NULL)
946 sh->target_off = h->root.u.def.value;
947 else
948 sh->target_off = sym->st_value;
949 sh->target_off += irela->r_addend;
950
951 stubs.count += 1;
952 }
953
954 /* We're done with the internal relocs, free them. */
955 if (elf_section_data (section)->relocs != internal_relocs)
956 free (internal_relocs);
957 }
958
959 if (local_syms != NULL
960 && symtab_hdr->contents != (unsigned char *) local_syms)
961 {
962 if (!info->keep_memory)
963 free (local_syms);
964 else
965 symtab_hdr->contents = (unsigned char *) local_syms;
966 }
967 }
968
969 *stub = NULL;
970 if (stubs.count == 0)
971 return TRUE;
972
973 ibfd = info->input_bfds;
974 flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY
975 | SEC_HAS_CONTENTS | SEC_IN_MEMORY);
976 htab->stub = bfd_make_section_anyway_with_flags (ibfd, ".stub", flags);
977 *stub = htab->stub;
978 if (htab->stub == NULL
979 || !bfd_set_section_alignment (ibfd, htab->stub, 2))
980 return FALSE;
981
982 flags = (SEC_ALLOC | SEC_LOAD
983 | SEC_HAS_CONTENTS | SEC_IN_MEMORY);
984 htab->ovtab = bfd_make_section_anyway_with_flags (ibfd, ".ovtab", flags);
985 *ovtab = htab->ovtab;
986 if (htab->ovtab == NULL
987 || !bfd_set_section_alignment (ibfd, htab->stub, 4))
988 return FALSE;
989
990 *toe = bfd_make_section_anyway_with_flags (ibfd, ".toe", SEC_ALLOC);
991 if (*toe == NULL
992 || !bfd_set_section_alignment (ibfd, *toe, 4))
993 return FALSE;
994 (*toe)->size = 16;
995
996 /* Retrieve all the stubs and sort. */
997 stubs.sh = bfd_malloc (stubs.count * sizeof (*stubs.sh));
998 if (stubs.sh == NULL)
999 return FALSE;
1000 i = stubs.count;
1001 bfd_hash_traverse (&htab->stub_hash_table, populate_stubs, &stubs);
1002 BFD_ASSERT (stubs.count == 0);
1003
1004 stubs.count = i;
1005 qsort (stubs.sh, stubs.count, sizeof (*stubs.sh), sort_stubs);
1006
1007 /* Now that the stubs are sorted, place them in the stub section.
1008 Stubs are grouped per overlay
1009 . ila $79,func1
1010 . br 1f
1011 . ila $79,func2
1012 . br 1f
1013 .
1014 .
1015 . ila $79,funcn
1016 . nop
1017 . 1:
1018 . ila $78,ovl_index
1019 . br __ovly_load */
1020
1021 group = 0;
1022 for (i = 0; i < stubs.count; i++)
1023 {
1024 if (spu_elf_section_data (stubs.sh[group]->target_section
1025 ->output_section)->ovl_index
1026 != spu_elf_section_data (stubs.sh[i]->target_section
1027 ->output_section)->ovl_index)
1028 {
1029 htab->stub->size += SIZEOF_STUB2;
1030 for (; group != i; group++)
1031 stubs.sh[group]->delta
1032 = stubs.sh[i - 1]->off - stubs.sh[group]->off;
1033 }
1034 if (group == i
1035 || ((stubs.sh[i - 1]->target_section->output_section->vma
1036 + stubs.sh[i - 1]->target_section->output_offset
1037 + stubs.sh[i - 1]->target_off)
1038 != (stubs.sh[i]->target_section->output_section->vma
1039 + stubs.sh[i]->target_section->output_offset
1040 + stubs.sh[i]->target_off)))
1041 {
1042 stubs.sh[i]->off = htab->stub->size;
1043 htab->stub->size += SIZEOF_STUB1;
1044 }
1045 else
1046 stubs.sh[i]->off = stubs.sh[i - 1]->off;
1047 }
1048 if (group != i)
1049 htab->stub->size += SIZEOF_STUB2;
1050 for (; group != i; group++)
1051 stubs.sh[group]->delta = stubs.sh[i - 1]->off - stubs.sh[group]->off;
1052
1053 /* htab->ovtab consists of two arrays.
1054 . struct {
1055 . u32 vma;
1056 . u32 size;
1057 . u32 file_off;
1058 . u32 buf;
1059 . } _ovly_table[];
1060 .
1061 . struct {
1062 . u32 mapped;
1063 . } _ovly_buf_table[]; */
1064
1065 htab->ovtab->alignment_power = 4;
1066 htab->ovtab->size = htab->num_overlays * 16 + htab->num_buf * 4;
1067
1068 return TRUE;
1069 }
1070
1071 /* Functions to handle embedded spu_ovl.o object. */
1072
1073 static void *
1074 ovl_mgr_open (struct bfd *nbfd ATTRIBUTE_UNUSED, void *stream)
1075 {
1076 return stream;
1077 }
1078
1079 static file_ptr
1080 ovl_mgr_pread (struct bfd *abfd ATTRIBUTE_UNUSED,
1081 void *stream,
1082 void *buf,
1083 file_ptr nbytes,
1084 file_ptr offset)
1085 {
1086 struct _ovl_stream *os;
1087 size_t count;
1088 size_t max;
1089
1090 os = (struct _ovl_stream *) stream;
1091 max = (const char *) os->end - (const char *) os->start;
1092
1093 if ((ufile_ptr) offset >= max)
1094 return 0;
1095
1096 count = nbytes;
1097 if (count > max - offset)
1098 count = max - offset;
1099
1100 memcpy (buf, (const char *) os->start + offset, count);
1101 return count;
1102 }
1103
1104 bfd_boolean
1105 spu_elf_open_builtin_lib (bfd **ovl_bfd, const struct _ovl_stream *stream)
1106 {
1107 *ovl_bfd = bfd_openr_iovec ("builtin ovl_mgr",
1108 "elf32-spu",
1109 ovl_mgr_open,
1110 (void *) stream,
1111 ovl_mgr_pread,
1112 NULL,
1113 NULL);
1114 return *ovl_bfd != NULL;
1115 }
1116
1117 /* Fill in the ila and br for a stub. On the last stub for a group,
1118 write the stub that sets the overlay number too. */
1119
1120 static bfd_boolean
1121 write_one_stub (struct bfd_hash_entry *bh, void *inf)
1122 {
1123 struct spu_stub_hash_entry *ent = (struct spu_stub_hash_entry *) bh;
1124 struct spu_link_hash_table *htab = inf;
1125 asection *sec = htab->stub;
1126 asection *s = ent->target_section;
1127 unsigned int ovl;
1128 bfd_vma val;
1129
1130 val = ent->target_off + s->output_offset + s->output_section->vma;
1131 bfd_put_32 (sec->owner, ILA_79 + ((val << 7) & 0x01ffff80),
1132 sec->contents + ent->off);
1133 val = ent->delta + 4;
1134 bfd_put_32 (sec->owner, BR + ((val << 5) & 0x007fff80),
1135 sec->contents + ent->off + 4);
1136
1137 /* If this is the last stub of this group, write stub2. */
1138 if (ent->delta == 0)
1139 {
1140 bfd_put_32 (sec->owner, NOP,
1141 sec->contents + ent->off + 4);
1142
1143 ovl = spu_elf_section_data (s->output_section)->ovl_index;
1144 bfd_put_32 (sec->owner, ILA_78 + ((ovl << 7) & 0x01ffff80),
1145 sec->contents + ent->off + 8);
1146
1147 val = (htab->ovly_load->root.u.def.section->output_section->vma
1148 + htab->ovly_load->root.u.def.section->output_offset
1149 + htab->ovly_load->root.u.def.value
1150 - (sec->output_section->vma
1151 + sec->output_offset
1152 + ent->off + 12));
1153
1154 if (val + 0x20000 >= 0x40000)
1155 htab->stub_overflow = TRUE;
1156
1157 bfd_put_32 (sec->owner, BR + ((val << 5) & 0x007fff80),
1158 sec->contents + ent->off + 12);
1159 }
1160
1161 if (htab->emit_stub_syms)
1162 {
1163 struct elf_link_hash_entry *h;
1164 size_t len1, len2;
1165 char *name;
1166
1167 len1 = sizeof ("00000000.ovl_call.") - 1;
1168 len2 = strlen (ent->root.string);
1169 name = bfd_malloc (len1 + len2 + 1);
1170 if (name == NULL)
1171 return FALSE;
1172 memcpy (name, "00000000.ovl_call.", len1);
1173 memcpy (name + len1, ent->root.string, len2 + 1);
1174 h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
1175 if (h == NULL)
1176 return FALSE;
1177 if (h->root.type == bfd_link_hash_new)
1178 {
1179 h->root.type = bfd_link_hash_defined;
1180 h->root.u.def.section = sec;
1181 h->root.u.def.value = ent->off;
1182 h->size = (ent->delta == 0
1183 ? SIZEOF_STUB1 + SIZEOF_STUB2 : SIZEOF_STUB1);
1184 h->type = STT_FUNC;
1185 h->ref_regular = 1;
1186 h->def_regular = 1;
1187 h->ref_regular_nonweak = 1;
1188 h->forced_local = 1;
1189 h->non_elf = 0;
1190 }
1191 }
1192
1193 return TRUE;
1194 }
1195
1196 /* Define an STT_OBJECT symbol. */
1197
1198 static struct elf_link_hash_entry *
1199 define_ovtab_symbol (struct spu_link_hash_table *htab, const char *name)
1200 {
1201 struct elf_link_hash_entry *h;
1202
1203 h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
1204 if (h == NULL)
1205 return NULL;
1206
1207 if (h->root.type != bfd_link_hash_defined
1208 || !h->def_regular)
1209 {
1210 h->root.type = bfd_link_hash_defined;
1211 h->root.u.def.section = htab->ovtab;
1212 h->type = STT_OBJECT;
1213 h->ref_regular = 1;
1214 h->def_regular = 1;
1215 h->ref_regular_nonweak = 1;
1216 h->non_elf = 0;
1217 }
1218 else
1219 {
1220 (*_bfd_error_handler) (_("%B is not allowed to define %s"),
1221 h->root.u.def.section->owner,
1222 h->root.root.string);
1223 bfd_set_error (bfd_error_bad_value);
1224 return NULL;
1225 }
1226
1227 return h;
1228 }
1229
1230 /* Fill in all stubs and the overlay tables. */
1231
1232 bfd_boolean
1233 spu_elf_build_stubs (struct bfd_link_info *info, int emit_syms, asection *toe)
1234 {
1235 struct spu_link_hash_table *htab = spu_hash_table (info);
1236 struct elf_link_hash_entry *h;
1237 bfd_byte *p;
1238 asection *s;
1239 bfd *obfd;
1240 unsigned int i;
1241
1242 htab->emit_stub_syms = emit_syms;
1243 htab->stub->contents = bfd_zalloc (htab->stub->owner, htab->stub->size);
1244 if (htab->stub->contents == NULL)
1245 return FALSE;
1246
1247 h = elf_link_hash_lookup (&htab->elf, "__ovly_load", FALSE, FALSE, FALSE);
1248 htab->ovly_load = h;
1249 BFD_ASSERT (h != NULL
1250 && (h->root.type == bfd_link_hash_defined
1251 || h->root.type == bfd_link_hash_defweak)
1252 && h->def_regular);
1253
1254 s = h->root.u.def.section->output_section;
1255 if (spu_elf_section_data (s)->ovl_index)
1256 {
1257 (*_bfd_error_handler) (_("%s in overlay section"),
1258 h->root.u.def.section->owner);
1259 bfd_set_error (bfd_error_bad_value);
1260 return FALSE;
1261 }
1262
1263 /* Write out all the stubs. */
1264 bfd_hash_traverse (&htab->stub_hash_table, write_one_stub, htab);
1265
1266 if (htab->stub_overflow)
1267 {
1268 (*_bfd_error_handler) (_("overlay stub relocation overflow"));
1269 bfd_set_error (bfd_error_bad_value);
1270 return FALSE;
1271 }
1272
1273 htab->ovtab->contents = bfd_zalloc (htab->ovtab->owner, htab->ovtab->size);
1274 if (htab->ovtab->contents == NULL)
1275 return FALSE;
1276
1277 /* Write out _ovly_table. */
1278 p = htab->ovtab->contents;
1279 obfd = htab->ovtab->output_section->owner;
1280 for (s = obfd->sections; s != NULL; s = s->next)
1281 {
1282 unsigned int ovl_index = spu_elf_section_data (s)->ovl_index;
1283
1284 if (ovl_index != 0)
1285 {
1286 unsigned int lo, hi, mid;
1287 unsigned long off = (ovl_index - 1) * 16;
1288 bfd_put_32 (htab->ovtab->owner, s->vma, p + off);
1289 bfd_put_32 (htab->ovtab->owner, (s->size + 15) & -16, p + off + 4);
1290 /* file_off written later in spu_elf_modify_program_headers. */
1291
1292 lo = 0;
1293 hi = htab->num_buf;
1294 while (lo < hi)
1295 {
1296 mid = (lo + hi) >> 1;
1297 if (htab->ovl_region[2 * mid + 1]->vma
1298 + htab->ovl_region[2 * mid + 1]->size <= s->vma)
1299 lo = mid + 1;
1300 else if (htab->ovl_region[2 * mid]->vma > s->vma)
1301 hi = mid;
1302 else
1303 {
1304 bfd_put_32 (htab->ovtab->owner, mid + 1, p + off + 12);
1305 break;
1306 }
1307 }
1308 BFD_ASSERT (lo < hi);
1309 }
1310 }
1311
1312 /* Write out _ovly_buf_table. */
1313 p = htab->ovtab->contents + htab->num_overlays * 16;
1314 for (i = 0; i < htab->num_buf; i++)
1315 {
1316 bfd_put_32 (htab->ovtab->owner, 0, p);
1317 p += 4;
1318 }
1319
1320 h = define_ovtab_symbol (htab, "_ovly_table");
1321 if (h == NULL)
1322 return FALSE;
1323 h->root.u.def.value = 0;
1324 h->size = htab->num_overlays * 16;
1325
1326 h = define_ovtab_symbol (htab, "_ovly_table_end");
1327 if (h == NULL)
1328 return FALSE;
1329 h->root.u.def.value = htab->num_overlays * 16;
1330 h->size = 0;
1331
1332 h = define_ovtab_symbol (htab, "_ovly_buf_table");
1333 if (h == NULL)
1334 return FALSE;
1335 h->root.u.def.value = htab->num_overlays * 16;
1336 h->size = htab->num_buf * 4;
1337
1338 h = define_ovtab_symbol (htab, "_ovly_buf_table_end");
1339 if (h == NULL)
1340 return FALSE;
1341 h->root.u.def.value = htab->num_overlays * 16 + htab->num_buf * 4;
1342 h->size = 0;
1343
1344 h = define_ovtab_symbol (htab, "_EAR_");
1345 if (h == NULL)
1346 return FALSE;
1347 h->root.u.def.section = toe;
1348 h->root.u.def.value = 0;
1349 h->size = 16;
1350
1351 return TRUE;
1352 }
1353
1354 /* Apply RELOCS to CONTENTS of INPUT_SECTION from INPUT_BFD. */
1355
1356 static bfd_boolean
1357 spu_elf_relocate_section (bfd *output_bfd,
1358 struct bfd_link_info *info,
1359 bfd *input_bfd,
1360 asection *input_section,
1361 bfd_byte *contents,
1362 Elf_Internal_Rela *relocs,
1363 Elf_Internal_Sym *local_syms,
1364 asection **local_sections)
1365 {
1366 Elf_Internal_Shdr *symtab_hdr;
1367 struct elf_link_hash_entry **sym_hashes;
1368 Elf_Internal_Rela *rel, *relend;
1369 struct spu_link_hash_table *htab;
1370 bfd_boolean ret = TRUE;
1371
1372 htab = spu_hash_table (info);
1373 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1374 sym_hashes = (struct elf_link_hash_entry **) (elf_sym_hashes (input_bfd));
1375
1376 rel = relocs;
1377 relend = relocs + input_section->reloc_count;
1378 for (; rel < relend; rel++)
1379 {
1380 int r_type;
1381 reloc_howto_type *howto;
1382 unsigned long r_symndx;
1383 Elf_Internal_Sym *sym;
1384 asection *sec;
1385 struct elf_link_hash_entry *h;
1386 const char *sym_name;
1387 bfd_vma relocation;
1388 bfd_vma addend;
1389 bfd_reloc_status_type r;
1390 bfd_boolean unresolved_reloc;
1391 bfd_boolean warned;
1392
1393 r_symndx = ELF32_R_SYM (rel->r_info);
1394 r_type = ELF32_R_TYPE (rel->r_info);
1395 howto = elf_howto_table + r_type;
1396 unresolved_reloc = FALSE;
1397 warned = FALSE;
1398
1399 h = NULL;
1400 sym = NULL;
1401 sec = NULL;
1402 if (r_symndx < symtab_hdr->sh_info)
1403 {
1404 sym = local_syms + r_symndx;
1405 sec = local_sections[r_symndx];
1406 sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
1407 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1408 }
1409 else
1410 {
1411 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1412 r_symndx, symtab_hdr, sym_hashes,
1413 h, sec, relocation,
1414 unresolved_reloc, warned);
1415 sym_name = h->root.root.string;
1416 }
1417
1418 if (sec != NULL && elf_discarded_section (sec))
1419 {
1420 /* For relocs against symbols from removed linkonce sections,
1421 or sections discarded by a linker script, we just want the
1422 section contents zeroed. Avoid any special processing. */
1423 _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
1424 rel->r_info = 0;
1425 rel->r_addend = 0;
1426 continue;
1427 }
1428
1429 if (info->relocatable)
1430 continue;
1431
1432 if (unresolved_reloc)
1433 {
1434 (*_bfd_error_handler)
1435 (_("%B(%s+0x%lx): unresolvable %s relocation against symbol `%s'"),
1436 input_bfd,
1437 bfd_get_section_name (input_bfd, input_section),
1438 (long) rel->r_offset,
1439 howto->name,
1440 sym_name);
1441 ret = FALSE;
1442 }
1443
1444 /* If this symbol is in an overlay area, we may need to relocate
1445 to the overlay stub. */
1446 addend = rel->r_addend;
1447 if (needs_ovl_stub (sym_name, sec, input_section, htab,
1448 is_branch (contents + rel->r_offset)))
1449 {
1450 char *stub_name;
1451 struct spu_stub_hash_entry *sh;
1452
1453 stub_name = spu_stub_name (sec, h, rel);
1454 if (stub_name == NULL)
1455 return FALSE;
1456
1457 sh = (struct spu_stub_hash_entry *)
1458 bfd_hash_lookup (&htab->stub_hash_table, stub_name, FALSE, FALSE);
1459 if (sh != NULL)
1460 {
1461 relocation = (htab->stub->output_section->vma
1462 + htab->stub->output_offset
1463 + sh->off);
1464 addend = 0;
1465 }
1466 free (stub_name);
1467 }
1468
1469 r = _bfd_final_link_relocate (howto,
1470 input_bfd,
1471 input_section,
1472 contents,
1473 rel->r_offset, relocation, addend);
1474
1475 if (r != bfd_reloc_ok)
1476 {
1477 const char *msg = (const char *) 0;
1478
1479 switch (r)
1480 {
1481 case bfd_reloc_overflow:
1482 if (!((*info->callbacks->reloc_overflow)
1483 (info, (h ? &h->root : NULL), sym_name, howto->name,
1484 (bfd_vma) 0, input_bfd, input_section, rel->r_offset)))
1485 return FALSE;
1486 break;
1487
1488 case bfd_reloc_undefined:
1489 if (!((*info->callbacks->undefined_symbol)
1490 (info, sym_name, input_bfd, input_section,
1491 rel->r_offset, TRUE)))
1492 return FALSE;
1493 break;
1494
1495 case bfd_reloc_outofrange:
1496 msg = _("internal error: out of range error");
1497 goto common_error;
1498
1499 case bfd_reloc_notsupported:
1500 msg = _("internal error: unsupported relocation error");
1501 goto common_error;
1502
1503 case bfd_reloc_dangerous:
1504 msg = _("internal error: dangerous error");
1505 goto common_error;
1506
1507 default:
1508 msg = _("internal error: unknown error");
1509 /* fall through */
1510
1511 common_error:
1512 if (!((*info->callbacks->warning)
1513 (info, msg, sym_name, input_bfd, input_section,
1514 rel->r_offset)))
1515 return FALSE;
1516 break;
1517 }
1518 }
1519 }
1520
1521 return ret;
1522 }
1523
1524 static int spu_plugin = 0;
1525
1526 void
1527 spu_elf_plugin (int val)
1528 {
1529 spu_plugin = val;
1530 }
1531
1532 /* Set ELF header e_type for plugins. */
1533
1534 static void
1535 spu_elf_post_process_headers (bfd *abfd,
1536 struct bfd_link_info *info ATTRIBUTE_UNUSED)
1537 {
1538 if (spu_plugin)
1539 {
1540 Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
1541
1542 i_ehdrp->e_type = ET_DYN;
1543 }
1544 }
1545
1546 /* We may add an extra PT_LOAD segment for .toe. We also need extra
1547 segments for overlays. */
1548
1549 static int
1550 spu_elf_additional_program_headers (bfd *abfd, struct bfd_link_info *info)
1551 {
1552 struct spu_link_hash_table *htab = spu_hash_table (info);
1553 int extra = htab->num_overlays;
1554 asection *sec;
1555
1556 if (extra)
1557 ++extra;
1558
1559 sec = bfd_get_section_by_name (abfd, ".toe");
1560 if (sec != NULL && (sec->flags & SEC_LOAD) != 0)
1561 ++extra;
1562
1563 return extra;
1564 }
1565
1566 /* Remove .toe section from other PT_LOAD segments and put it in
1567 a segment of its own. Put overlays in separate segments too. */
1568
1569 static bfd_boolean
1570 spu_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
1571 {
1572 asection *toe, *s;
1573 struct elf_segment_map *m;
1574 unsigned int i;
1575
1576 if (info == NULL)
1577 return TRUE;
1578
1579 toe = bfd_get_section_by_name (abfd, ".toe");
1580 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
1581 if (m->p_type == PT_LOAD && m->count > 1)
1582 for (i = 0; i < m->count; i++)
1583 if ((s = m->sections[i]) == toe
1584 || spu_elf_section_data (s)->ovl_index != 0)
1585 {
1586 struct elf_segment_map *m2;
1587 bfd_vma amt;
1588
1589 if (i + 1 < m->count)
1590 {
1591 amt = sizeof (struct elf_segment_map);
1592 amt += (m->count - (i + 2)) * sizeof (m->sections[0]);
1593 m2 = bfd_zalloc (abfd, amt);
1594 if (m2 == NULL)
1595 return FALSE;
1596 m2->count = m->count - (i + 1);
1597 memcpy (m2->sections, m->sections + i + 1,
1598 m2->count * sizeof (m->sections[0]));
1599 m2->p_type = PT_LOAD;
1600 m2->next = m->next;
1601 m->next = m2;
1602 }
1603 m->count = 1;
1604 if (i != 0)
1605 {
1606 m->count = i;
1607 amt = sizeof (struct elf_segment_map);
1608 m2 = bfd_zalloc (abfd, amt);
1609 if (m2 == NULL)
1610 return FALSE;
1611 m2->p_type = PT_LOAD;
1612 m2->count = 1;
1613 m2->sections[0] = s;
1614 m2->next = m->next;
1615 m->next = m2;
1616 }
1617 break;
1618 }
1619
1620 return TRUE;
1621 }
1622
1623 /* Check that all loadable section VMAs lie in the range
1624 LO .. HI inclusive. */
1625
1626 asection *
1627 spu_elf_check_vma (bfd *abfd, bfd_vma lo, bfd_vma hi)
1628 {
1629 struct elf_segment_map *m;
1630 unsigned int i;
1631
1632 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
1633 if (m->p_type == PT_LOAD)
1634 for (i = 0; i < m->count; i++)
1635 if (m->sections[i]->size != 0
1636 && (m->sections[i]->vma < lo
1637 || m->sections[i]->vma > hi
1638 || m->sections[i]->vma + m->sections[i]->size - 1 > hi))
1639 return m->sections[i];
1640
1641 return NULL;
1642 }
1643
1644 /* Tweak phdrs before writing them out. */
1645
1646 static int
1647 spu_elf_modify_program_headers (bfd *abfd, struct bfd_link_info *info)
1648 {
1649 const struct elf_backend_data *bed;
1650 struct elf_obj_tdata *tdata;
1651 Elf_Internal_Phdr *phdr, *last;
1652 struct spu_link_hash_table *htab;
1653 unsigned int count;
1654 unsigned int i;
1655
1656 if (info == NULL)
1657 return TRUE;
1658
1659 bed = get_elf_backend_data (abfd);
1660 tdata = elf_tdata (abfd);
1661 phdr = tdata->phdr;
1662 count = tdata->program_header_size / bed->s->sizeof_phdr;
1663 htab = spu_hash_table (info);
1664 if (htab->num_overlays != 0)
1665 {
1666 struct elf_segment_map *m;
1667 unsigned int o;
1668
1669 for (i = 0, m = elf_tdata (abfd)->segment_map; m; ++i, m = m->next)
1670 if (m->count != 0
1671 && (o = spu_elf_section_data (m->sections[0])->ovl_index) != 0)
1672 {
1673 /* Mark this as an overlay header. */
1674 phdr[i].p_flags |= PF_OVERLAY;
1675
1676 if (htab->ovtab != NULL && htab->ovtab->size != 0)
1677 {
1678 bfd_byte *p = htab->ovtab->contents;
1679 unsigned int off = (o - 1) * 16 + 8;
1680
1681 /* Write file_off into _ovly_table. */
1682 bfd_put_32 (htab->ovtab->owner, phdr[i].p_offset, p + off);
1683 }
1684 }
1685 }
1686
1687 /* Round up p_filesz and p_memsz of PT_LOAD segments to multiples
1688 of 16. This should always be possible when using the standard
1689 linker scripts, but don't create overlapping segments if
1690 someone is playing games with linker scripts. */
1691 last = NULL;
1692 for (i = count; i-- != 0; )
1693 if (phdr[i].p_type == PT_LOAD)
1694 {
1695 unsigned adjust;
1696
1697 adjust = -phdr[i].p_filesz & 15;
1698 if (adjust != 0
1699 && last != NULL
1700 && phdr[i].p_offset + phdr[i].p_filesz > last->p_offset - adjust)
1701 break;
1702
1703 adjust = -phdr[i].p_memsz & 15;
1704 if (adjust != 0
1705 && last != NULL
1706 && phdr[i].p_filesz != 0
1707 && phdr[i].p_vaddr + phdr[i].p_memsz > last->p_vaddr - adjust
1708 && phdr[i].p_vaddr + phdr[i].p_memsz <= last->p_vaddr)
1709 break;
1710
1711 if (phdr[i].p_filesz != 0)
1712 last = &phdr[i];
1713 }
1714
1715 if (i == (unsigned int) -1)
1716 for (i = count; i-- != 0; )
1717 if (phdr[i].p_type == PT_LOAD)
1718 {
1719 unsigned adjust;
1720
1721 adjust = -phdr[i].p_filesz & 15;
1722 phdr[i].p_filesz += adjust;
1723
1724 adjust = -phdr[i].p_memsz & 15;
1725 phdr[i].p_memsz += adjust;
1726 }
1727
1728 return TRUE;
1729 }
1730
1731 /* Arrange for our linker created section to be output. */
1732
1733 static bfd_boolean
1734 spu_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED,
1735 Elf_Internal_Shdr *i_shdrp)
1736 {
1737 asection *sec;
1738
1739 sec = i_shdrp->bfd_section;
1740 if (sec != NULL
1741 && (sec->flags & SEC_LINKER_CREATED) != 0
1742 && sec->name != NULL
1743 && strcmp (sec->name, SPU_PTNOTE_SPUNAME) == 0)
1744 i_shdrp->contents = sec->contents;
1745
1746 return TRUE;
1747 }
1748
1749 #define TARGET_BIG_SYM bfd_elf32_spu_vec
1750 #define TARGET_BIG_NAME "elf32-spu"
1751 #define ELF_ARCH bfd_arch_spu
1752 #define ELF_MACHINE_CODE EM_SPU
1753 /* This matches the alignment need for DMA. */
1754 #define ELF_MAXPAGESIZE 0x80
1755 #define elf_backend_rela_normal 1
1756 #define elf_backend_can_gc_sections 1
1757
1758 #define bfd_elf32_bfd_reloc_type_lookup spu_elf_reloc_type_lookup
1759 #define elf_info_to_howto spu_elf_info_to_howto
1760 #define elf_backend_gc_mark_hook spu_elf_gc_mark_hook
1761 #define elf_backend_relocate_section spu_elf_relocate_section
1762 #define elf_backend_symbol_processing spu_elf_backend_symbol_processing
1763 #define bfd_elf32_new_section_hook spu_elf_new_section_hook
1764 #define bfd_elf32_bfd_link_hash_table_create spu_elf_link_hash_table_create
1765 #define bfd_elf32_bfd_link_hash_table_free spu_elf_link_hash_table_free
1766
1767 #define elf_backend_additional_program_headers spu_elf_additional_program_headers
1768 #define elf_backend_modify_segment_map spu_elf_modify_segment_map
1769 #define elf_backend_modify_program_headers spu_elf_modify_program_headers
1770 #define elf_backend_post_process_headers spu_elf_post_process_headers
1771 #define elf_backend_section_processing spu_elf_section_processing
1772 #define elf_backend_special_sections spu_elf_special_sections
1773
1774 #include "elf32-target.h"
This page took 0.066612 seconds and 5 git commands to generate.