X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-spu.c;h=8e0d0c5d5d2373ee5557c78e2ef11dd15cc146df;hb=c48182bfe408e06e3301ee887fd9a7b06bedff37;hp=8b1a9f1d559e8a9269c570f2103ba90ecbf7c032;hpb=2fc6d3b01285cee9613f9c52c08b57e91b4f01f6;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-spu.c b/bfd/elf32-spu.c index 8b1a9f1d55..8e0d0c5d5d 100644 --- a/bfd/elf32-spu.c +++ b/bfd/elf32-spu.c @@ -1,6 +1,6 @@ /* SPU specific support for 32-bit ELF - Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 2006-2016 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -37,7 +37,7 @@ static bfd_reloc_status_type spu_elf_rel9 (bfd *, arelent *, asymbol *, array, so it must be declared in the order of that type. */ static reloc_howto_type elf_howto_table[] = { - HOWTO (R_SPU_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont, + HOWTO (R_SPU_NONE, 0, 3, 0, FALSE, 0, complain_overflow_dont, bfd_elf_generic_reloc, "SPU_NONE", FALSE, 0, 0x00000000, FALSE), HOWTO (R_SPU_ADDR10, 4, 2, 10, FALSE, 14, complain_overflow_bitfield, @@ -88,6 +88,9 @@ static reloc_howto_type elf_howto_table[] = { HOWTO (R_SPU_PPU64, 0, 4, 64, FALSE, 0, complain_overflow_dont, bfd_elf_generic_reloc, "SPU_PPU64", FALSE, 0, -1, FALSE), + HOWTO (R_SPU_ADD_PIC, 0, 0, 0, FALSE, 0, complain_overflow_dont, + bfd_elf_generic_reloc, "SPU_ADD_PIC", + FALSE, 0, 0x00000000, FALSE), }; static struct bfd_elf_special_section const spu_elf_special_sections[] = { @@ -102,6 +105,8 @@ spu_elf_bfd_to_reloc_type (bfd_reloc_code_real_type code) switch (code) { default: + return (enum elf_spu_reloc_type) -1; + case BFD_RELOC_NONE: return R_SPU_NONE; case BFD_RELOC_SPU_IMM10W: return R_SPU_ADDR10; @@ -135,6 +140,8 @@ spu_elf_bfd_to_reloc_type (bfd_reloc_code_real_type code) return R_SPU_PPU32; case BFD_RELOC_SPU_PPU64: return R_SPU_PPU64; + case BFD_RELOC_SPU_ADD_PIC: + return R_SPU_ADD_PIC; } } @@ -146,7 +153,14 @@ spu_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, enum elf_spu_reloc_type r_type; r_type = (enum elf_spu_reloc_type) ELF32_R_TYPE (dst->r_info); - BFD_ASSERT (r_type < R_SPU_max); + /* PR 17512: file: 90c2a92e. */ + if (r_type >= R_SPU_max) + { + _bfd_error_handler (_("%B: unrecognised SPU reloc number: %d"), + abfd, r_type); + bfd_set_error (bfd_error_bad_value); + r_type = R_SPU_NONE; + } cache_ptr->howto = &elf_howto_table[(int) r_type]; } @@ -156,7 +170,7 @@ spu_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, { enum elf_spu_reloc_type r_type = spu_elf_bfd_to_reloc_type (code); - if (r_type == R_SPU_NONE) + if (r_type == (enum elf_spu_reloc_type) -1) return NULL; return elf_howto_table + r_type; @@ -267,7 +281,8 @@ spu_elf_object_p (bfd *abfd) { Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[j]; - if (ELF_IS_SECTION_IN_SEGMENT_MEMORY (shdr, phdr)) + if (ELF_SECTION_SIZE (shdr, phdr) != 0 + && ELF_SECTION_IN_SEGMENT (shdr, phdr)) { asection *sec = shdr->bfd_section; spu_elf_section_data (sec)->u.o.ovl_index = num_ovl; @@ -326,19 +341,13 @@ struct spu_link_hash_table /* How much memory we have. */ unsigned int local_store; - /* Local store --auto-overlay should reserve for non-overlay - functions and data. */ - unsigned int overlay_fixed; - /* Local store --auto-overlay should reserve for stack and heap. */ - unsigned int reserved; - /* If reserved is not specified, stack analysis will calculate a value - for the stack. This parameter adjusts that value to allow for - negative sp access (the ABI says 2000 bytes below sp are valid, - and the overlay manager uses some of this area). */ - int extra_stack_space; + /* Count of overlay stubs needed in non-overlay area. */ unsigned int non_ovly_stub; + /* Pointer to the fixup section */ + asection *sfixup; + /* Set on error. */ unsigned int stub_err : 1; }; @@ -357,7 +366,8 @@ struct got_entry }; #define spu_hash_table(p) \ - ((struct spu_link_hash_table *) ((p)->hash)) + (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ + == SPU_ELF_DATA ? ((struct spu_link_hash_table *) ((p)->hash)) : NULL) struct call_info { @@ -438,21 +448,19 @@ spu_elf_link_hash_table_create (bfd *abfd) { struct spu_link_hash_table *htab; - htab = bfd_malloc (sizeof (*htab)); + htab = bfd_zmalloc (sizeof (*htab)); if (htab == NULL) return NULL; if (!_bfd_elf_link_hash_table_init (&htab->elf, abfd, _bfd_elf_link_hash_newfunc, - sizeof (struct elf_link_hash_entry))) + sizeof (struct elf_link_hash_entry), + SPU_ELF_DATA)) { free (htab); return NULL; } - memset (&htab->ovtab, 0, - sizeof (*htab) - offsetof (struct spu_link_hash_table, ovtab)); - htab->elf.init_got_refcount.refcount = 0; htab->elf.init_got_refcount.glist = NULL; htab->elf.init_got_offset.offset = 0; @@ -553,9 +561,10 @@ get_sym_h (struct elf_link_hash_entry **hp, bfd_boolean spu_elf_create_sections (struct bfd_link_info *info) { + struct spu_link_hash_table *htab = spu_hash_table (info); bfd *ibfd; - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) if (bfd_get_section_by_name (ibfd, SPU_PTNOTE_SPUNAME) != NULL) break; @@ -595,6 +604,22 @@ spu_elf_create_sections (struct bfd_link_info *info) s->contents = data; } + if (htab->params->emit_fixups) + { + asection *s; + flagword flags; + + if (htab->elf.dynobj == NULL) + htab->elf.dynobj = ibfd; + ibfd = htab->elf.dynobj; + flags = (SEC_LOAD | SEC_ALLOC | SEC_READONLY | SEC_HAS_CONTENTS + | SEC_IN_MEMORY | SEC_LINKER_CREATED); + s = bfd_make_section_anyway_with_flags (ibfd, ".fixup", flags); + if (s == NULL || !bfd_set_section_alignment (ibfd, s, 2)) + return FALSE; + htab->sfixup = s; + } + return TRUE; } @@ -656,9 +681,10 @@ spu_elf_find_overlays (struct bfd_link_info *info) ovl_end = alloc_sec[0]->vma + alloc_sec[0]->size; if (htab->params->ovly_flavour == ovly_soft_icache) { + unsigned int prev_buf = 0, set_id = 0; + /* Look for an overlapping vma to find the first overlay section. */ bfd_vma vma_start = 0; - bfd_vma lma_start = 0; for (i = 1; i < n; i++) { @@ -667,10 +693,6 @@ spu_elf_find_overlays (struct bfd_link_info *info) { asection *s0 = alloc_sec[i - 1]; vma_start = s0->vma; - if (strncmp (s0->name, ".ovl.init", 9) != 0) - lma_start = s0->lma; - else - lma_start = s->lma; ovl_end = (s0->vma + ((bfd_vma) 1 << (htab->num_lines_log2 + htab->line_size_log2))); @@ -695,8 +717,10 @@ spu_elf_find_overlays (struct bfd_link_info *info) if (strncmp (s->name, ".ovl.init", 9) != 0) { num_buf = ((s->vma - vma_start) >> htab->line_size_log2) + 1; - if (((s->vma - vma_start) & (htab->params->line_size - 1)) - || ((s->lma - lma_start) & (htab->params->line_size - 1))) + set_id = (num_buf == prev_buf)? set_id + 1 : 0; + prev_buf = num_buf; + + if ((s->vma - vma_start) & (htab->params->line_size - 1)) { info->callbacks->einfo (_("%X%P: overlay section %A " "does not start on a cache line.\n"), @@ -715,7 +739,7 @@ spu_elf_find_overlays (struct bfd_link_info *info) alloc_sec[ovl_index++] = s; spu_elf_section_data (s)->u.o.ovl_index - = ((s->lma - lma_start) >> htab->line_size_log2) + 1; + = (set_id << htab->num_lines_log2) + num_buf; spu_elf_section_data (s)->u.o.ovl_buf = num_buf; } } @@ -990,9 +1014,9 @@ needs_ovl_stub (struct elf_link_hash_entry *h, sym, sym_sec); } - (*_bfd_error_handler) (_("warning: call to non-function" - " symbol %s defined in %B"), - sym_sec->owner, sym_name); + _bfd_error_handler + (_("warning: call to non-function symbol %s defined in %B"), + sym_sec->owner, sym_name); } } @@ -1127,7 +1151,7 @@ count_stub (struct spu_link_hash_table *htab, } /* Support two sizes of overlay stubs, a slower more compact stub of two - intructions, and a faster stub of four instructions. + instructions, and a faster stub of four instructions. Soft-icache stubs are four or eight words. */ static unsigned int @@ -1407,7 +1431,7 @@ build_stub (struct bfd_link_info *info, add = (int) irela->r_addend & 0xffffffff; if (add != 0) len += 1 + 8; - name = bfd_malloc (len); + name = bfd_malloc (len + 1); if (name == NULL) return FALSE; @@ -1467,7 +1491,7 @@ allocate_spuear_stubs (struct elf_link_hash_entry *h, void *inf) { return count_stub (htab, NULL, NULL, nonovl_stub, h, NULL); } - + return TRUE; } @@ -1493,7 +1517,7 @@ build_spuear_stubs (struct elf_link_hash_entry *h, void *inf) return build_stub (info, NULL, NULL, nonovl_stub, h, NULL, h->root.u.def.value, sym_sec); } - + return TRUE; } @@ -1505,14 +1529,14 @@ process_stubs (struct bfd_link_info *info, bfd_boolean build) struct spu_link_hash_table *htab = spu_hash_table (info); bfd *ibfd; - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { - extern const bfd_target bfd_elf32_spu_vec; + extern const bfd_target spu_elf32_vec; Elf_Internal_Shdr *symtab_hdr; asection *isec; Elf_Internal_Sym *local_syms = NULL; - if (ibfd->xvec != &bfd_elf32_spu_vec) + if (ibfd->xvec != &spu_elf32_vec) continue; /* We'll need the symbol table in a second. */ @@ -1627,7 +1651,7 @@ process_stubs (struct bfd_link_info *info, bfd_boolean build) } /* Allocate space for overlay call and return stubs. - Return 0 on error, 1 if no stubs, 2 otherwise. */ + Return 0 on error, 1 if no overlays, 2 otherwise. */ int spu_elf_size_stubs (struct bfd_link_info *info) @@ -1647,39 +1671,39 @@ spu_elf_size_stubs (struct bfd_link_info *info) if (htab->stub_err) return 0; - if (htab->stub_count == NULL) - return 1; - ibfd = info->input_bfds; - amt = (htab->num_overlays + 1) * sizeof (*htab->stub_sec); - htab->stub_sec = bfd_zmalloc (amt); - if (htab->stub_sec == NULL) - return 0; - - flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY - | SEC_HAS_CONTENTS | SEC_IN_MEMORY); - stub = bfd_make_section_anyway_with_flags (ibfd, ".stub", flags); - htab->stub_sec[0] = stub; - if (stub == NULL - || !bfd_set_section_alignment (ibfd, stub, - ovl_stub_size_log2 (htab->params))) - return 0; - stub->size = htab->stub_count[0] * ovl_stub_size (htab->params); - if (htab->params->ovly_flavour == ovly_soft_icache) - /* Extra space for linked list entries. */ - stub->size += htab->stub_count[0] * 16; - - for (i = 0; i < htab->num_overlays; ++i) + if (htab->stub_count != NULL) { - asection *osec = htab->ovl_sec[i]; - unsigned int ovl = spu_elf_section_data (osec)->u.o.ovl_index; + amt = (htab->num_overlays + 1) * sizeof (*htab->stub_sec); + htab->stub_sec = bfd_zmalloc (amt); + if (htab->stub_sec == NULL) + return 0; + + flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY + | SEC_HAS_CONTENTS | SEC_IN_MEMORY); stub = bfd_make_section_anyway_with_flags (ibfd, ".stub", flags); - htab->stub_sec[ovl] = stub; + htab->stub_sec[0] = stub; if (stub == NULL || !bfd_set_section_alignment (ibfd, stub, ovl_stub_size_log2 (htab->params))) return 0; - stub->size = htab->stub_count[ovl] * ovl_stub_size (htab->params); + stub->size = htab->stub_count[0] * ovl_stub_size (htab->params); + if (htab->params->ovly_flavour == ovly_soft_icache) + /* Extra space for linked list entries. */ + stub->size += htab->stub_count[0] * 16; + + for (i = 0; i < htab->num_overlays; ++i) + { + asection *osec = htab->ovl_sec[i]; + unsigned int ovl = spu_elf_section_data (osec)->u.o.ovl_index; + stub = bfd_make_section_anyway_with_flags (ibfd, ".stub", flags); + htab->stub_sec[ovl] = stub; + if (stub == NULL + || !bfd_set_section_alignment (ibfd, stub, + ovl_stub_size_log2 (htab->params))) + return 0; + stub->size = htab->stub_count[ovl] * ovl_stub_size (htab->params); + } } if (htab->params->ovly_flavour == ovly_soft_icache) @@ -1707,6 +1731,8 @@ spu_elf_size_stubs (struct bfd_link_info *info) htab->init->size = 16; } + else if (htab->stub_count == NULL) + return 1; else { /* htab->ovtab consists of two arrays. @@ -1750,29 +1776,32 @@ spu_elf_place_overlay_data (struct bfd_link_info *info) { struct spu_link_hash_table *htab = spu_hash_table (info); unsigned int i; - const char *ovout; - - if (htab->stub_count == NULL) - return; - - (*htab->params->place_spu_section) (htab->stub_sec[0], NULL, ".text"); - for (i = 0; i < htab->num_overlays; ++i) + if (htab->stub_sec != NULL) { - asection *osec = htab->ovl_sec[i]; - unsigned int ovl = spu_elf_section_data (osec)->u.o.ovl_index; - (*htab->params->place_spu_section) (htab->stub_sec[ovl], osec, NULL); + (*htab->params->place_spu_section) (htab->stub_sec[0], NULL, ".text"); + + for (i = 0; i < htab->num_overlays; ++i) + { + asection *osec = htab->ovl_sec[i]; + unsigned int ovl = spu_elf_section_data (osec)->u.o.ovl_index; + (*htab->params->place_spu_section) (htab->stub_sec[ovl], osec, NULL); + } } if (htab->params->ovly_flavour == ovly_soft_icache) (*htab->params->place_spu_section) (htab->init, NULL, ".ovl.init"); - ovout = ".data"; - if (htab->params->ovly_flavour == ovly_soft_icache) - ovout = ".bss"; - (*htab->params->place_spu_section) (htab->ovtab, NULL, ovout); + if (htab->ovtab != NULL) + { + const char *ovout = ".data"; + if (htab->params->ovly_flavour == ovly_soft_icache) + ovout = ".bss"; + (*htab->params->place_spu_section) (htab->ovtab, NULL, ovout); + } - (*htab->params->place_spu_section) (htab->toe, NULL, ".toe"); + if (htab->toe != NULL) + (*htab->params->place_spu_section) (htab->toe, NULL, ".toe"); } /* Functions to handle embedded spu_ovl.o object. */ @@ -1808,6 +1837,18 @@ ovl_mgr_pread (struct bfd *abfd ATTRIBUTE_UNUSED, return count; } +static int +ovl_mgr_stat (struct bfd *abfd ATTRIBUTE_UNUSED, + void *stream, + struct stat *sb) +{ + struct _ovl_stream *os = (struct _ovl_stream *) stream; + + memset (sb, 0, sizeof (*sb)); + sb->st_size = (const char *) os->end - (const char *) os->start; + return 0; +} + bfd_boolean spu_elf_open_builtin_lib (bfd **ovl_bfd, const struct _ovl_stream *stream) { @@ -1817,7 +1858,7 @@ spu_elf_open_builtin_lib (bfd **ovl_bfd, const struct _ovl_stream *stream) (void *) stream, ovl_mgr_pread, NULL, - NULL); + ovl_mgr_stat); return *ovl_bfd != NULL; } @@ -1854,16 +1895,16 @@ define_ovtab_symbol (struct spu_link_hash_table *htab, const char *name) } else if (h->root.u.def.section->owner != NULL) { - (*_bfd_error_handler) (_("%B is not allowed to define %s"), - h->root.u.def.section->owner, - h->root.root.string); + _bfd_error_handler (_("%B is not allowed to define %s"), + h->root.u.def.section->owner, + h->root.root.string); bfd_set_error (bfd_error_bad_value); return NULL; } else { - (*_bfd_error_handler) (_("you are not allowed to define %s in a script"), - h->root.root.string); + _bfd_error_handler (_("you are not allowed to define %s in a script"), + h->root.root.string); bfd_set_error (bfd_error_bad_value); return NULL; } @@ -1883,63 +1924,63 @@ spu_elf_build_stubs (struct bfd_link_info *info) bfd *obfd; unsigned int i; - if (htab->stub_count == NULL) - return TRUE; - - for (i = 0; i <= htab->num_overlays; i++) - if (htab->stub_sec[i]->size != 0) - { - htab->stub_sec[i]->contents = bfd_zalloc (htab->stub_sec[i]->owner, - htab->stub_sec[i]->size); - if (htab->stub_sec[i]->contents == NULL) - return FALSE; - htab->stub_sec[i]->rawsize = htab->stub_sec[i]->size; - htab->stub_sec[i]->size = 0; - } - - for (i = 0; i < 2; i++) + if (htab->num_overlays != 0) { - h = htab->ovly_entry[i]; - BFD_ASSERT (h != NULL); - - if ((h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - && h->def_regular) + for (i = 0; i < 2; i++) { - s = h->root.u.def.section->output_section; - if (spu_elf_section_data (s)->u.o.ovl_index) + h = htab->ovly_entry[i]; + if (h != NULL + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && h->def_regular) { - (*_bfd_error_handler) (_("%s in overlay section"), - h->root.root.string); - bfd_set_error (bfd_error_bad_value); - return FALSE; + s = h->root.u.def.section->output_section; + if (spu_elf_section_data (s)->u.o.ovl_index) + { + _bfd_error_handler (_("%s in overlay section"), + h->root.root.string); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } } } - else - BFD_ASSERT (0); } - /* Fill in all the stubs. */ - process_stubs (info, TRUE); - if (!htab->stub_err) - elf_link_hash_traverse (&htab->elf, build_spuear_stubs, info); - - if (htab->stub_err) + if (htab->stub_sec != NULL) { - (*_bfd_error_handler) (_("overlay stub relocation overflow")); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } + for (i = 0; i <= htab->num_overlays; i++) + if (htab->stub_sec[i]->size != 0) + { + htab->stub_sec[i]->contents = bfd_zalloc (htab->stub_sec[i]->owner, + htab->stub_sec[i]->size); + if (htab->stub_sec[i]->contents == NULL) + return FALSE; + htab->stub_sec[i]->rawsize = htab->stub_sec[i]->size; + htab->stub_sec[i]->size = 0; + } - for (i = 0; i <= htab->num_overlays; i++) - { - if (htab->stub_sec[i]->size != htab->stub_sec[i]->rawsize) + /* Fill in all the stubs. */ + process_stubs (info, TRUE); + if (!htab->stub_err) + elf_link_hash_traverse (&htab->elf, build_spuear_stubs, info); + + if (htab->stub_err) { - (*_bfd_error_handler) (_("stubs don't match calculated size")); + _bfd_error_handler (_("overlay stub relocation overflow")); bfd_set_error (bfd_error_bad_value); return FALSE; } - htab->stub_sec[i]->rawsize = 0; + + for (i = 0; i <= htab->num_overlays; i++) + { + if (htab->stub_sec[i]->size != htab->stub_sec[i]->rawsize) + { + _bfd_error_handler (_("stubs don't match calculated size")); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + htab->stub_sec[i]->rawsize = 0; + } } if (htab->ovtab == NULL || htab->ovtab->size == 0) @@ -2131,7 +2172,7 @@ spu_elf_check_vma (struct bfd_link_info *info) htab->local_store = hi + 1 - lo; - for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + for (m = elf_seg_map (abfd); m != NULL; m = m->next) if (m->p_type == PT_LOAD) for (i = 0; i < m->count; i++) if (m->sections[i]->size != 0 @@ -2666,19 +2707,12 @@ mark_functions_via_relocs (asection *sec, Elf_Internal_Sym *sym; struct elf_link_hash_entry *h; bfd_vma val; - bfd_boolean reject, is_call; + bfd_boolean nonbranch, is_call; struct function_info *caller; struct call_info *callee; - reject = FALSE; r_type = ELF32_R_TYPE (irela->r_info); - if (r_type != R_SPU_REL16 - && r_type != R_SPU_ADDR16) - { - reject = TRUE; - if (!(call_tree && spu_hash_table (info)->params->auto_overlay)) - continue; - } + nonbranch = r_type != R_SPU_REL16 && r_type != R_SPU_ADDR16; r_indx = ELF32_R_SYM (irela->r_info); if (!get_sym_h (&h, &sym, &sym_sec, psyms, r_indx, sec->owner)) @@ -2689,7 +2723,7 @@ mark_functions_via_relocs (asection *sec, continue; is_call = FALSE; - if (!reject) + if (!nonbranch) { unsigned char insn[4]; @@ -2720,14 +2754,13 @@ mark_functions_via_relocs (asection *sec, } else { - reject = TRUE; - if (!(call_tree && spu_hash_table (info)->params->auto_overlay) - || is_hint (insn)) + nonbranch = TRUE; + if (is_hint (insn)) continue; } } - if (reject) + if (nonbranch) { /* For --auto-overlay, count possible stubs we need for function pointer references. */ @@ -2737,8 +2770,20 @@ mark_functions_via_relocs (asection *sec, else sym_type = ELF_ST_TYPE (sym->st_info); if (sym_type == STT_FUNC) - spu_hash_table (info)->non_ovly_stub += 1; - continue; + { + if (call_tree && spu_hash_table (info)->params->auto_overlay) + spu_hash_table (info)->non_ovly_stub += 1; + /* If the symbol type is STT_FUNC then this must be a + function pointer initialisation. */ + continue; + } + /* Ignore data references. */ + if ((sym_sec->flags & (SEC_ALLOC | SEC_LOAD | SEC_CODE)) + != (SEC_ALLOC | SEC_LOAD | SEC_CODE)) + continue; + /* Otherwise we probably have a jump table reloc for + a switch statement or some other reference to a + code label. */ } if (h) @@ -2785,8 +2830,9 @@ mark_functions_via_relocs (asection *sec, return FALSE; callee->is_tail = !is_call; callee->is_pasted = FALSE; + callee->broken_cycle = FALSE; callee->priority = priority; - callee->count = 1; + callee->count = nonbranch? 0 : 1; if (callee->fun->last_caller != sec) { callee->fun->last_caller = sec; @@ -2878,6 +2924,8 @@ pasted_function (asection *sec) callee->fun = fun; callee->is_tail = TRUE; callee->is_pasted = TRUE; + callee->broken_cycle = FALSE; + callee->priority = 0; callee->count = 1; if (!insert_callee (fun_start, callee)) free (callee); @@ -2909,7 +2957,7 @@ discover_functions (struct bfd_link_info *info) bfd_boolean gaps = FALSE; bfd_idx = 0; - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) bfd_idx++; psym_arr = bfd_zmalloc (bfd_idx * sizeof (*psym_arr)); @@ -2918,19 +2966,19 @@ discover_functions (struct bfd_link_info *info) sec_arr = bfd_zmalloc (bfd_idx * sizeof (*sec_arr)); if (sec_arr == NULL) return FALSE; - + for (ibfd = info->input_bfds, bfd_idx = 0; ibfd != NULL; - ibfd = ibfd->link_next, bfd_idx++) + ibfd = ibfd->link.next, bfd_idx++) { - extern const bfd_target bfd_elf32_spu_vec; + extern const bfd_target spu_elf32_vec; Elf_Internal_Shdr *symtab_hdr; asection *sec; size_t symcount; Elf_Internal_Sym *syms, *sy, **psyms, **psy; asection **psecs, **p; - if (ibfd->xvec != &bfd_elf32_spu_vec) + if (ibfd->xvec != &spu_elf32_vec) continue; /* Read all the symbols. */ @@ -2951,7 +2999,7 @@ discover_functions (struct bfd_link_info *info) if (symtab_hdr->contents != NULL) { /* Don't use cached symbols since the generic ELF linker - code only reads local symbols, and we need globals too. */ + code only reads local symbols, and we need globals too. */ free (symtab_hdr->contents); symtab_hdr->contents = NULL; } @@ -3029,7 +3077,7 @@ discover_functions (struct bfd_link_info *info) relocations. */ for (ibfd = info->input_bfds, bfd_idx = 0; ibfd != NULL; - ibfd = ibfd->link_next, bfd_idx++) + ibfd = ibfd->link.next, bfd_idx++) { asection *sec; @@ -3043,7 +3091,7 @@ discover_functions (struct bfd_link_info *info) for (ibfd = info->input_bfds, bfd_idx = 0; ibfd != NULL; - ibfd = ibfd->link_next, bfd_idx++) + ibfd = ibfd->link.next, bfd_idx++) { Elf_Internal_Shdr *symtab_hdr; asection *sec; @@ -3082,12 +3130,12 @@ discover_functions (struct bfd_link_info *info) } } - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { - extern const bfd_target bfd_elf32_spu_vec; + extern const bfd_target spu_elf32_vec; asection *sec; - if (ibfd->xvec != &bfd_elf32_spu_vec) + if (ibfd->xvec != &spu_elf32_vec) continue; /* Some of the symbols we've installed as marking the @@ -3125,7 +3173,7 @@ discover_functions (struct bfd_link_info *info) for (ibfd = info->input_bfds, bfd_idx = 0; ibfd != NULL; - ibfd = ibfd->link_next, bfd_idx++) + ibfd = ibfd->link.next, bfd_idx++) { if (psym_arr[bfd_idx] == NULL) continue; @@ -3154,12 +3202,12 @@ for_each_node (bfd_boolean (*doit) (struct function_info *, { bfd *ibfd; - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { - extern const bfd_target bfd_elf32_spu_vec; + extern const bfd_target spu_elf32_vec; asection *sec; - if (ibfd->xvec != &bfd_elf32_spu_vec) + if (ibfd->xvec != &spu_elf32_vec) continue; for (sec = ibfd->sections; sec != NULL; sec = sec->next) @@ -3303,12 +3351,12 @@ build_call_tree (struct bfd_link_info *info) bfd *ibfd; unsigned int depth; - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { - extern const bfd_target bfd_elf32_spu_vec; + extern const bfd_target spu_elf32_vec; asection *sec; - if (ibfd->xvec != &bfd_elf32_spu_vec) + if (ibfd->xvec != &spu_elf32_vec) continue; for (sec = ibfd->sections; sec != NULL; sec = sec->next) @@ -3680,12 +3728,12 @@ auto_ovl_lib_functions (struct bfd_link_info *info, unsigned int lib_size) memset (&dummy_caller, 0, sizeof (dummy_caller)); lib_count = 0; - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { - extern const bfd_target bfd_elf32_spu_vec; + extern const bfd_target spu_elf32_vec; asection *sec; - if (ibfd->xvec != &bfd_elf32_spu_vec) + if (ibfd->xvec != &spu_elf32_vec) continue; for (sec = ibfd->sections; sec != NULL; sec = sec->next) @@ -4037,7 +4085,7 @@ sort_bfds (const void *a, const void *b) bfd *const *abfd1 = a; bfd *const *abfd2 = b; - return strcmp ((*abfd1)->filename, (*abfd2)->filename); + return filename_cmp ((*abfd1)->filename, (*abfd2)->filename); } static unsigned int @@ -4050,7 +4098,7 @@ print_one_overlay_section (FILE *script, struct bfd_link_info *info) { unsigned int j; - + for (j = base; j < count && ovly_map[j] == ovlynum; j++) { asection *sec = ovly_sections[2 * j]; @@ -4130,6 +4178,7 @@ spu_elf_auto_overlay (struct bfd_link_info *info) bfd **bfd_arr; struct elf_segment_map *m; unsigned int fixed_size, lo, hi; + unsigned int reserved; struct spu_link_hash_table *htab; unsigned int base, i, count, bfd_count; unsigned int region, ovlynum; @@ -4146,7 +4195,7 @@ spu_elf_auto_overlay (struct bfd_link_info *info) /* Find the extents of our loadable image. */ lo = (unsigned int) -1; hi = 0; - for (m = elf_tdata (info->output_bfd)->segment_map; m != NULL; m = m->next) + for (m = elf_seg_map (info->output_bfd); m != NULL; m = m->next) if (m->p_type == PT_LOAD) for (i = 0; i < m->count; i++) if (m->sections[i]->size != 0) @@ -4165,7 +4214,8 @@ spu_elf_auto_overlay (struct bfd_link_info *info) goto err_exit; htab = spu_hash_table (info); - if (htab->reserved == 0) + reserved = htab->params->auto_overlay_reserved; + if (reserved == 0) { struct _sum_stack_param sum_stack_param; @@ -4173,11 +4223,12 @@ spu_elf_auto_overlay (struct bfd_link_info *info) sum_stack_param.overall_stack = 0; if (!for_each_node (sum_stack, info, &sum_stack_param, TRUE)) goto err_exit; - htab->reserved = sum_stack_param.overall_stack + htab->extra_stack_space; + reserved = (sum_stack_param.overall_stack + + htab->params->extra_stack_space); } /* No need for overlays if everything already fits. */ - if (fixed_size + htab->reserved <= htab->local_store + if (fixed_size + reserved <= htab->local_store && htab->params->ovly_flavour != ovly_soft_icache) { htab->params->auto_overlay = 0; @@ -4222,7 +4273,7 @@ spu_elf_auto_overlay (struct bfd_link_info *info) goto err_exit; bfd_count = 0; - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) ++bfd_count; bfd_arr = bfd_malloc (bfd_count * sizeof (*bfd_arr)); if (bfd_arr == NULL) @@ -4232,13 +4283,13 @@ spu_elf_auto_overlay (struct bfd_link_info *info) count = 0; bfd_count = 0; total_overlay_size = 0; - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { - extern const bfd_target bfd_elf32_spu_vec; + extern const bfd_target spu_elf32_vec; asection *sec; unsigned int old_count; - if (ibfd->xvec != &bfd_elf32_spu_vec) + if (ibfd->xvec != &spu_elf32_vec) continue; old_count = count; @@ -4266,7 +4317,7 @@ spu_elf_auto_overlay (struct bfd_link_info *info) qsort (bfd_arr, bfd_count, sizeof (*bfd_arr), sort_bfds); for (i = 1; i < bfd_count; ++i) - if (strcmp (bfd_arr[i - 1]->filename, bfd_arr[i]->filename) == 0) + if (filename_cmp (bfd_arr[i - 1]->filename, bfd_arr[i]->filename) == 0) { if (bfd_arr[i - 1]->my_archive == bfd_arr[i]->my_archive) { @@ -4290,7 +4341,7 @@ spu_elf_auto_overlay (struct bfd_link_info *info) } free (bfd_arr); - fixed_size += htab->reserved; + fixed_size += reserved; fixed_size += htab->non_ovly_stub * ovl_stub_size (htab->params); if (fixed_size + mos_param.max_overlay_size <= htab->local_store) { @@ -4329,13 +4380,13 @@ spu_elf_auto_overlay (struct bfd_link_info *info) (bfd_vma) mos_param.max_overlay_size); /* Now see if we should put some functions in the non-overlay area. */ - else if (fixed_size < htab->overlay_fixed) + else if (fixed_size < htab->params->auto_overlay_fixed) { unsigned int max_fixed, lib_size; max_fixed = htab->local_store - mos_param.max_overlay_size; - if (max_fixed > htab->overlay_fixed) - max_fixed = htab->overlay_fixed; + if (max_fixed > htab->params->auto_overlay_fixed) + max_fixed = htab->params->auto_overlay_fixed; lib_size = max_fixed - fixed_size; lib_size = auto_ovl_lib_functions (info, lib_size); if (lib_size == (unsigned int) -1) @@ -4374,7 +4425,7 @@ spu_elf_auto_overlay (struct bfd_link_info *info) struct call_info *call, *pasty; struct _spu_elf_section_data *sec_data; struct spu_elf_stack_info *sinfo; - int k; + unsigned int k; /* See whether we can add this section to the current overlay without overflowing our overlay buffer. */ @@ -4394,7 +4445,7 @@ spu_elf_auto_overlay (struct bfd_link_info *info) { /* Pasted sections must stay together, so add their sizes too. */ - struct call_info *pasty = find_pasted_call (sec); + pasty = find_pasted_call (sec); while (pasty != NULL) { struct function_info *call_fun = pasty->fun; @@ -4421,7 +4472,7 @@ spu_elf_auto_overlay (struct bfd_link_info *info) pasty = NULL; sec_data = spu_elf_section_data (sec); sinfo = sec_data->u.i.stack_info; - for (k = 0; k < sinfo->num_fun; ++k) + for (k = 0; k < (unsigned) sinfo->num_fun; ++k) for (call = sinfo->fun[k].call_list; call; call = call->next) if (call->is_pasted) { @@ -4451,7 +4502,6 @@ spu_elf_auto_overlay (struct bfd_link_info *info) num_stubs = 0; for (call = dummy_caller.call_list; call; call = call->next) { - unsigned int k; unsigned int stub_delta = 1; if (htab->params->ovly_flavour == ovly_soft_icache) @@ -4501,13 +4551,12 @@ spu_elf_auto_overlay (struct bfd_link_info *info) script = htab->params->spu_elf_open_overlay_script (); - if (fprintf (script, "SECTIONS\n{\n") <= 0) - goto file_err; - if (htab->params->ovly_flavour == ovly_soft_icache) { + if (fprintf (script, "SECTIONS\n{\n") <= 0) + goto file_err; + if (fprintf (script, - " .data.icache ALIGN (16) : { *(.ovtab) *(.data.icache) }\n" " . = ALIGN (%u);\n" " .ovl.init : { *(.ovl.init) }\n" " . = ABSOLUTE (ADDR (.ovl.init));\n", @@ -4522,10 +4571,10 @@ spu_elf_auto_overlay (struct bfd_link_info *info) unsigned int vma, lma; vma = (indx & (htab->params->num_lines - 1)) << htab->line_size_log2; - lma = indx << htab->line_size_log2; + lma = vma + (((indx >> htab->num_lines_log2) + 1) << 18); if (fprintf (script, " .ovly%u ABSOLUTE (ADDR (.ovl.init)) + %u " - ": AT (ALIGN (LOADADDR (.ovl.init) + SIZEOF (.ovl.init), 16) + %u) {\n", + ": AT (LOADADDR (.ovl.init) + %u) {\n", ovlynum, vma, lma) <= 0) goto file_err; @@ -4543,9 +4592,15 @@ spu_elf_auto_overlay (struct bfd_link_info *info) if (fprintf (script, " . = ABSOLUTE (ADDR (.ovl.init)) + %u;\n", 1 << (htab->num_lines_log2 + htab->line_size_log2)) <= 0) goto file_err; + + if (fprintf (script, "}\nINSERT AFTER .toe;\n") <= 0) + goto file_err; } else { + if (fprintf (script, "SECTIONS\n{\n") <= 0) + goto file_err; + if (fprintf (script, " . = ALIGN (16);\n" " .ovl.init : { *(.ovl.init) }\n" @@ -4597,13 +4652,13 @@ spu_elf_auto_overlay (struct bfd_link_info *info) goto file_err; } + if (fprintf (script, "}\nINSERT BEFORE .text;\n") <= 0) + goto file_err; } free (ovly_map); free (ovly_sections); - if (fprintf (script, "}\nINSERT BEFORE .text;\n") <= 0) - goto file_err; if (fclose (script) != 0) goto file_err; @@ -4674,7 +4729,7 @@ spu_elf_final_link (bfd *output_bfd, struct bfd_link_info *info) return bfd_elf_final_link (output_bfd, info); } -/* Called when not normally emitting relocs, ie. !info->relocatable +/* Called when not normally emitting relocs, ie. !bfd_link_relocatable (info) and !info->emitrelocations. Returns a count of special relocs that need to be emitted. */ @@ -4705,6 +4760,48 @@ spu_elf_count_relocs (struct bfd_link_info *info, asection *sec) return count; } +/* Functions for adding fixup records to .fixup */ + +#define FIXUP_RECORD_SIZE 4 + +#define FIXUP_PUT(output_bfd,htab,index,addr) \ + bfd_put_32 (output_bfd, addr, \ + htab->sfixup->contents + FIXUP_RECORD_SIZE * (index)) +#define FIXUP_GET(output_bfd,htab,index) \ + bfd_get_32 (output_bfd, \ + htab->sfixup->contents + FIXUP_RECORD_SIZE * (index)) + +/* Store OFFSET in .fixup. This assumes it will be called with an + increasing OFFSET. When this OFFSET fits with the last base offset, + it just sets a bit, otherwise it adds a new fixup record. */ +static void +spu_elf_emit_fixup (bfd * output_bfd, struct bfd_link_info *info, + bfd_vma offset) +{ + struct spu_link_hash_table *htab = spu_hash_table (info); + asection *sfixup = htab->sfixup; + bfd_vma qaddr = offset & ~(bfd_vma) 15; + bfd_vma bit = ((bfd_vma) 8) >> ((offset & 15) >> 2); + if (sfixup->reloc_count == 0) + { + FIXUP_PUT (output_bfd, htab, 0, qaddr | bit); + sfixup->reloc_count++; + } + else + { + bfd_vma base = FIXUP_GET (output_bfd, htab, sfixup->reloc_count - 1); + if (qaddr != (base & ~(bfd_vma) 15)) + { + if ((sfixup->reloc_count + 1) * FIXUP_RECORD_SIZE > sfixup->size) + _bfd_error_handler (_("fatal error while creating .fixup")); + FIXUP_PUT (output_bfd, htab, sfixup->reloc_count, qaddr | bit); + sfixup->reloc_count++; + } + else + FIXUP_PUT (output_bfd, htab, sfixup->reloc_count - 1, base | bit); + } +} + /* Apply RELOCS to CONTENTS of INPUT_SECTION from INPUT_BFD. */ static int @@ -4751,14 +4848,12 @@ spu_elf_relocate_section (bfd *output_bfd, bfd_vma addend; bfd_reloc_status_type r; bfd_boolean unresolved_reloc; - bfd_boolean warned; enum _stub_type stub_type; r_symndx = ELF32_R_SYM (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); howto = elf_howto_table + r_type; unresolved_reloc = FALSE; - warned = FALSE; h = NULL; sym = NULL; sec = NULL; @@ -4776,6 +4871,11 @@ spu_elf_relocate_section (bfd *output_bfd, h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + if (info->wrap_hash != NULL + && (input_section->flags & SEC_DEBUGGING) != 0) + h = ((struct elf_link_hash_entry *) + unwrap_hash_lookup (info, input_bfd, &h->root)); + while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; @@ -4802,37 +4902,39 @@ spu_elf_relocate_section (bfd *output_bfd, else if (info->unresolved_syms_in_objects == RM_IGNORE && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) ; - else if (!info->relocatable + else if (!bfd_link_relocatable (info) && !(r_type == R_SPU_PPU32 || r_type == R_SPU_PPU64)) { bfd_boolean err; err = (info->unresolved_syms_in_objects == RM_GENERATE_ERROR || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT); - if (!info->callbacks->undefined_symbol (info, - h->root.root.string, - input_bfd, - input_section, - rel->r_offset, err)) - return FALSE; - warned = TRUE; + (*info->callbacks->undefined_symbol) (info, + h->root.root.string, + input_bfd, + input_section, + rel->r_offset, err); } sym_name = h->root.root.string; } - if (sec != NULL && elf_discarded_section (sec)) - { - /* For relocs against symbols from removed linkonce sections, - or sections discarded by a linker script, we just want the - section contents zeroed. Avoid any special processing. */ - _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); - rel->r_info = 0; - rel->r_addend = 0; - continue; - } + if (sec != NULL && discarded_section (sec)) + RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, + rel, 1, relend, howto, 0, contents); - if (info->relocatable) + if (bfd_link_relocatable (info)) continue; + /* Change "a rt,ra,rb" to "ai rt,ra,0". */ + if (r_type == R_SPU_ADD_PIC + && h != NULL + && !(h->def_regular || ELF_COMMON_DEF_P (h))) + { + bfd_byte *loc = contents + rel->r_offset; + loc[0] = 0x1c; + loc[1] = 0x00; + loc[2] &= 0x3f; + } + is_ea_sym = (ea != NULL && sec != NULL && sec->output_section == ea); @@ -4887,6 +4989,16 @@ spu_elf_relocate_section (bfd *output_bfd, } } + if (htab->params->emit_fixups && !bfd_link_relocatable (info) + && (input_section->flags & SEC_ALLOC) != 0 + && r_type == R_SPU_ADDR32) + { + bfd_vma offset; + offset = rel->r_offset + input_section->output_section->vma + + input_section->output_offset; + spu_elf_emit_fixup (output_bfd, info, offset); + } + if (unresolved_reloc) ; else if (r_type == R_SPU_PPU32 || r_type == R_SPU_PPU64) @@ -4910,9 +5022,11 @@ spu_elf_relocate_section (bfd *output_bfd, else if (is_ea_sym) unresolved_reloc = TRUE; - if (unresolved_reloc) + if (unresolved_reloc + && _bfd_elf_section_offset (output_bfd, info, input_section, + rel->r_offset) != (bfd_vma) -1) { - (*_bfd_error_handler) + _bfd_error_handler (_("%B(%s+0x%lx): unresolvable %s relocation against symbol `%s'"), input_bfd, bfd_get_section_name (input_bfd, input_section), @@ -4935,17 +5049,14 @@ spu_elf_relocate_section (bfd *output_bfd, switch (r) { case bfd_reloc_overflow: - if (!((*info->callbacks->reloc_overflow) - (info, (h ? &h->root : NULL), sym_name, howto->name, - (bfd_vma) 0, input_bfd, input_section, rel->r_offset))) - return FALSE; + (*info->callbacks->reloc_overflow) + (info, (h ? &h->root : NULL), sym_name, howto->name, + (bfd_vma) 0, input_bfd, input_section, rel->r_offset); break; case bfd_reloc_undefined: - if (!((*info->callbacks->undefined_symbol) - (info, sym_name, input_bfd, input_section, - rel->r_offset, TRUE))) - return FALSE; + (*info->callbacks->undefined_symbol) + (info, sym_name, input_bfd, input_section, rel->r_offset, TRUE); break; case bfd_reloc_outofrange: @@ -4966,10 +5077,8 @@ spu_elf_relocate_section (bfd *output_bfd, common_error: ret = FALSE; - if (!((*info->callbacks->warning) - (info, msg, sym_name, input_bfd, input_section, - rel->r_offset))) - return FALSE; + (*info->callbacks->warning) (info, msg, sym_name, input_bfd, + input_section, rel->r_offset); break; } } @@ -4994,7 +5103,7 @@ spu_elf_relocate_section (bfd *output_bfd, } input_section->reloc_count = wrel - relocs; /* Backflips for _bfd_elf_link_output_relocs. */ - rel_hdr = &elf_section_data (input_section)->rel_hdr; + rel_hdr = _bfd_elf_single_rel_hdr (input_section); rel_hdr->sh_size = input_section->reloc_count * rel_hdr->sh_entsize; ret = 2; } @@ -5002,6 +5111,13 @@ spu_elf_relocate_section (bfd *output_bfd, return ret; } +static bfd_boolean +spu_elf_finish_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) +{ + return TRUE; +} + /* Adjust _SPUEAR_ syms to point at their overlay stubs. */ static int @@ -5013,7 +5129,7 @@ spu_elf_output_symbol_hook (struct bfd_link_info *info, { struct spu_link_hash_table *htab = spu_hash_table (info); - if (!info->relocatable + if (!bfd_link_relocatable (info) && htab->stub_sec != NULL && h != NULL && (h->root.type == bfd_link_hash_defined @@ -5050,8 +5166,7 @@ spu_elf_plugin (int val) /* Set ELF header e_type for plugins. */ static void -spu_elf_post_process_headers (bfd *abfd, - struct bfd_link_info *info ATTRIBUTE_UNUSED) +spu_elf_post_process_headers (bfd *abfd, struct bfd_link_info *info) { if (spu_plugin) { @@ -5059,6 +5174,8 @@ spu_elf_post_process_headers (bfd *abfd, i_ehdrp->e_type = ET_DYN; } + + _bfd_elf_post_process_headers (abfd, info); } /* We may add an extra PT_LOAD segment for .toe. We also need extra @@ -5101,7 +5218,7 @@ spu_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info) return TRUE; toe = bfd_get_section_by_name (abfd, ".toe"); - for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + for (m = elf_seg_map (abfd); m != NULL; m = m->next) if (m->p_type == PT_LOAD && m->count > 1) for (i = 0; i < m->count; i++) if ((s = m->sections[i]) == toe @@ -5151,14 +5268,14 @@ spu_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info) as PF_OVERLAY) will be placed into SPU local store on startup. */ /* Move all overlay segments onto a separate list. */ - p = &elf_tdata (abfd)->segment_map; + p = &elf_seg_map (abfd); p_overlay = &m_overlay; while (*p != NULL) { if ((*p)->p_type == PT_LOAD && (*p)->count == 1 && spu_elf_section_data ((*p)->sections[0])->u.o.ovl_index != 0) { - struct elf_segment_map *m = *p; + m = *p; *p = m->next; *p_overlay = m; p_overlay = &m->next; @@ -5169,8 +5286,8 @@ spu_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info) } /* Re-insert overlay segments at the head of the segment map. */ - *p_overlay = elf_tdata (abfd)->segment_map; - elf_tdata (abfd)->segment_map = m_overlay; + *p_overlay = elf_seg_map (abfd); + elf_seg_map (abfd) = m_overlay; return TRUE; } @@ -5205,14 +5322,14 @@ spu_elf_modify_program_headers (bfd *abfd, struct bfd_link_info *info) bed = get_elf_backend_data (abfd); tdata = elf_tdata (abfd); phdr = tdata->phdr; - count = tdata->program_header_size / bed->s->sizeof_phdr; + count = elf_program_header_size (abfd) / bed->s->sizeof_phdr; htab = spu_hash_table (info); if (htab->num_overlays != 0) { struct elf_segment_map *m; unsigned int o; - for (i = 0, m = elf_tdata (abfd)->segment_map; m; ++i, m = m->next) + for (i = 0, m = elf_seg_map (abfd); m; ++i, m = m->next) if (m->count != 0 && (o = spu_elf_section_data (m->sections[0])->u.o.ovl_index) != 0) { @@ -5282,9 +5399,77 @@ spu_elf_modify_program_headers (bfd *abfd, struct bfd_link_info *info) return TRUE; } -#define TARGET_BIG_SYM bfd_elf32_spu_vec +bfd_boolean +spu_elf_size_sections (bfd * output_bfd, struct bfd_link_info *info) +{ + struct spu_link_hash_table *htab = spu_hash_table (info); + if (htab->params->emit_fixups) + { + asection *sfixup = htab->sfixup; + int fixup_count = 0; + bfd *ibfd; + size_t size; + + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) + { + asection *isec; + + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) + continue; + + /* Walk over each section attached to the input bfd. */ + for (isec = ibfd->sections; isec != NULL; isec = isec->next) + { + Elf_Internal_Rela *internal_relocs, *irelaend, *irela; + bfd_vma base_end; + + /* If there aren't any relocs, then there's nothing more + to do. */ + if ((isec->flags & SEC_ALLOC) == 0 + || (isec->flags & SEC_RELOC) == 0 + || isec->reloc_count == 0) + continue; + + /* Get the relocs. */ + internal_relocs = + _bfd_elf_link_read_relocs (ibfd, isec, NULL, NULL, + info->keep_memory); + if (internal_relocs == NULL) + return FALSE; + + /* 1 quadword can contain up to 4 R_SPU_ADDR32 + relocations. They are stored in a single word by + saving the upper 28 bits of the address and setting the + lower 4 bits to a bit mask of the words that have the + relocation. BASE_END keeps track of the next quadword. */ + irela = internal_relocs; + irelaend = irela + isec->reloc_count; + base_end = 0; + for (; irela < irelaend; irela++) + if (ELF32_R_TYPE (irela->r_info) == R_SPU_ADDR32 + && irela->r_offset >= base_end) + { + base_end = (irela->r_offset & ~(bfd_vma) 15) + 16; + fixup_count++; + } + } + } + + /* We always have a NULL fixup as a sentinel */ + size = (fixup_count + 1) * FIXUP_RECORD_SIZE; + if (!bfd_set_section_size (output_bfd, sfixup, size)) + return FALSE; + sfixup->contents = (bfd_byte *) bfd_zalloc (info->input_bfds, size); + if (sfixup->contents == NULL) + return FALSE; + } + return TRUE; +} + +#define TARGET_BIG_SYM spu_elf32_vec #define TARGET_BIG_NAME "elf32-spu" #define ELF_ARCH bfd_arch_spu +#define ELF_TARGET_ID SPU_ELF_DATA #define ELF_MACHINE_CODE EM_SPU /* This matches the alignment need for DMA. */ #define ELF_MAXPAGESIZE 0x80 @@ -5296,6 +5481,7 @@ spu_elf_modify_program_headers (bfd *abfd, struct bfd_link_info *info) #define elf_info_to_howto spu_elf_info_to_howto #define elf_backend_count_relocs spu_elf_count_relocs #define elf_backend_relocate_section spu_elf_relocate_section +#define elf_backend_finish_dynamic_sections spu_elf_finish_dynamic_sections #define elf_backend_symbol_processing spu_elf_backend_symbol_processing #define elf_backend_link_output_symbol_hook spu_elf_output_symbol_hook #define elf_backend_object_p spu_elf_object_p