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