X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-xtensa.c;h=43163226f8848ac484c88440307d6aaa2823e151;hb=f6fbab7d1b396b1ee576937b53bb0858c8f895d5;hp=1740c355a66ed3f6ff35439e2710a74dcbd22682;hpb=91d6fa6a035cc7d0b7be5c99c194a64cb80924b0;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c index 1740c355a6..43163226f8 100644 --- a/bfd/elf32-xtensa.c +++ b/bfd/elf32-xtensa.c @@ -1,5 +1,5 @@ /* Xtensa-specific support for 32-bit ELF. - Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -155,6 +155,10 @@ static bfd_boolean relaxing_section = FALSE; int elf32xtensa_no_literal_movement = 1; +/* Rename one of the generic section flags to better document how it + is used here. */ +/* Whether relocations have been processed. */ +#define reloc_done sec_flg0 static reloc_howto_type elf_howto_table[] = { @@ -572,13 +576,13 @@ struct elf_xtensa_obj_tdata #define is_xtensa_elf(bfd) \ (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ && elf_tdata (bfd) != NULL \ - && elf_object_id (bfd) == XTENSA_ELF_TDATA) + && elf_object_id (bfd) == XTENSA_ELF_DATA) static bfd_boolean elf_xtensa_mkobject (bfd *abfd) { return bfd_elf_allocate_object (abfd, sizeof (struct elf_xtensa_obj_tdata), - XTENSA_ELF_TDATA); + XTENSA_ELF_DATA); } /* Xtensa ELF linker hash table. */ @@ -610,7 +614,8 @@ struct elf_xtensa_link_hash_table /* Get the Xtensa ELF linker hash table from a link_info structure. */ #define elf_xtensa_hash_table(p) \ - ((struct elf_xtensa_link_hash_table *) ((p)->hash)) + (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ + == XTENSA_ELF_DATA ? ((struct elf_xtensa_link_hash_table *) ((p)->hash)) : NULL) /* Create an entry in an Xtensa ELF linker hash table. */ @@ -656,7 +661,8 @@ elf_xtensa_link_hash_table_create (bfd *abfd) if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, elf_xtensa_link_hash_newfunc, - sizeof (struct elf_xtensa_link_hash_entry))) + sizeof (struct elf_xtensa_link_hash_entry), + XTENSA_ELF_DATA)) { free (ret); return NULL; @@ -977,6 +983,9 @@ elf_xtensa_check_relocs (bfd *abfd, BFD_ASSERT (is_xtensa_elf (abfd)); htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return FALSE; + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); @@ -1278,6 +1287,8 @@ elf_xtensa_gc_sweep_hook (bfd *abfd, struct elf_xtensa_link_hash_table *htab; htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return FALSE; if (info->relocatable) return TRUE; @@ -1397,15 +1408,17 @@ elf_xtensa_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) flagword flags, noalloc_flags; htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return FALSE; /* First do all the standard stuff. */ if (! _bfd_elf_create_dynamic_sections (dynobj, info)) return FALSE; - htab->splt = bfd_get_section_by_name (dynobj, ".plt"); - htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt"); - htab->sgot = bfd_get_section_by_name (dynobj, ".got"); - htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); - htab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); + htab->splt = bfd_get_linker_section (dynobj, ".plt"); + htab->srelplt = bfd_get_linker_section (dynobj, ".rela.plt"); + htab->sgot = bfd_get_linker_section (dynobj, ".got"); + htab->sgotplt = bfd_get_linker_section (dynobj, ".got.plt"); + htab->srelgot = bfd_get_linker_section (dynobj, ".rela.got"); /* Create any extra PLT sections in case check_relocs has already been called on all the non-dynamic input files. */ @@ -1422,14 +1435,15 @@ elf_xtensa_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) return FALSE; /* Create ".got.loc" (literal tables for use by dynamic linker). */ - htab->sgotloc = bfd_make_section_with_flags (dynobj, ".got.loc", flags); + htab->sgotloc = bfd_make_section_anyway_with_flags (dynobj, ".got.loc", + flags); if (htab->sgotloc == NULL || ! bfd_set_section_alignment (dynobj, htab->sgotloc, 2)) return FALSE; /* Create ".xt.lit.plt" (literal table for ".got.plt*"). */ - htab->spltlittbl = bfd_make_section_with_flags (dynobj, ".xt.lit.plt", - noalloc_flags); + htab->spltlittbl = bfd_make_section_anyway_with_flags (dynobj, ".xt.lit.plt", + noalloc_flags); if (htab->spltlittbl == NULL || ! bfd_set_section_alignment (dynobj, htab->spltlittbl, 2)) return FALSE; @@ -1461,14 +1475,14 @@ add_extra_plt_sections (struct bfd_link_info *info, int count) sname = (char *) bfd_malloc (10); sprintf (sname, ".plt.%u", chunk); - s = bfd_make_section_with_flags (dynobj, sname, flags | SEC_CODE); + s = bfd_make_section_anyway_with_flags (dynobj, sname, flags | SEC_CODE); if (s == NULL || ! bfd_set_section_alignment (dynobj, s, 2)) return FALSE; sname = (char *) bfd_malloc (14); sprintf (sname, ".got.plt.%u", chunk); - s = bfd_make_section_with_flags (dynobj, sname, flags); + s = bfd_make_section_anyway_with_flags (dynobj, sname, flags); if (s == NULL || ! bfd_set_section_alignment (dynobj, s, 2)) return FALSE; @@ -1518,11 +1532,10 @@ elf_xtensa_allocate_dynrelocs (struct elf_link_hash_entry *h, void *arg) if (h->root.type == bfd_link_hash_indirect) return TRUE; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - info = (struct bfd_link_info *) arg; htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return FALSE; /* If we saw any use of an IE model for this symbol, we can then optimize away GOT entries for any TLSDESC_FN relocs. */ @@ -1552,6 +1565,8 @@ elf_xtensa_allocate_local_got_size (struct bfd_link_info *info) bfd *i; htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return; for (i = info->input_bfds; i; i = i->link_next) { @@ -1602,6 +1617,9 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, plt_chunks = 0; htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return FALSE; + dynobj = elf_hash_table (info)->dynobj; if (dynobj == NULL) abort (); @@ -1619,7 +1637,7 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* Set the contents of the .interp section to the interpreter. */ if (info->executable) { - s = bfd_get_section_by_name (dynobj, ".interp"); + s = bfd_get_linker_section (dynobj, ".interp"); if (s == NULL) abort (); s->size = sizeof ELF_DYNAMIC_INTERPRETER; @@ -1695,7 +1713,7 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, continue; for (s = abfd->sections; s != NULL; s = s->next) { - if (! elf_discarded_section (s) + if (! discarded_section (s) && xtensa_is_littable_section (s) && s != spltlittbl) sgotloc->size += s->size; @@ -1835,6 +1853,9 @@ elf_xtensa_always_size_sections (bfd *output_bfd, asection *tls_sec; htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return FALSE; + tls_sec = htab->elf.tls_sec; if (tls_sec && (htab->tlsbase->tls_type & GOT_TLS_ANY) != 0) @@ -2546,6 +2567,9 @@ elf_xtensa_relocate_section (bfd *output_bfd, BFD_ASSERT (is_xtensa_elf (input_bfd)); htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return FALSE; + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); local_got_tls_types = elf_xtensa_local_got_tls_type (input_bfd); @@ -2633,19 +2657,15 @@ elf_xtensa_relocate_section (bfd *output_bfd, sym_type = h->type; } - 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) { + bfd_vma dest_addr; + asection * sym_sec = get_elf_r_symndx_section (input_bfd, r_symndx); + /* This is a relocatable link. 1) If the reloc is against a section symbol, adjust according to the output section. @@ -2662,6 +2682,9 @@ elf_xtensa_relocate_section (bfd *output_bfd, return FALSE; } + dest_addr = sym_sec->output_section->vma + sym_sec->output_offset + + get_elf_r_symndx_offset (input_bfd, r_symndx) + rel->r_addend; + if (r_type == R_XTENSA_ASM_SIMPLIFY) { error_message = NULL; @@ -2698,25 +2721,41 @@ elf_xtensa_relocate_section (bfd *output_bfd, to work around problems with DWARF in relocatable links with some previous version of BFD. Now we can't easily get rid of the hack without breaking backward compatibility.... */ - if (rel->r_addend) + r = bfd_reloc_ok; + howto = &elf_howto_table[r_type]; + if (howto->partial_inplace && rel->r_addend) + { + r = elf_xtensa_do_reloc (howto, input_bfd, input_section, + rel->r_addend, contents, + rel->r_offset, FALSE, + &error_message); + rel->r_addend = 0; + } + else { - howto = &elf_howto_table[r_type]; - if (howto->partial_inplace) + /* Put the correct bits in the target instruction, even + though the relocation will still be present in the output + file. This makes disassembly clearer, as well as + allowing loadable kernel modules to work without needing + relocations on anything other than calls and l32r's. */ + + /* If it is not in the same section, there is nothing we can do. */ + if (r_type >= R_XTENSA_SLOT0_OP && r_type <= R_XTENSA_SLOT14_OP && + sym_sec->output_section == input_section->output_section) { r = elf_xtensa_do_reloc (howto, input_bfd, input_section, - rel->r_addend, contents, + dest_addr, contents, rel->r_offset, FALSE, &error_message); - if (r != bfd_reloc_ok) - { - if (!((*info->callbacks->reloc_dangerous) - (info, error_message, input_bfd, input_section, - rel->r_offset))) - return FALSE; - } - rel->r_addend = 0; } } + if (r != bfd_reloc_ok) + { + if (!((*info->callbacks->reloc_dangerous) + (info, error_message, input_bfd, input_section, + rel->r_offset))) + return FALSE; + } /* Done with work for relocatable link; continue with next reloc. */ continue; @@ -2752,7 +2791,7 @@ elf_xtensa_relocate_section (bfd *output_bfd, name = bfd_section_name (input_bfd, sec); } - if (r_symndx != 0 + if (r_symndx != STN_UNDEF && r_type != R_XTENSA_NONE && (h == NULL || h->root.type == bfd_link_hash_defined @@ -3020,7 +3059,9 @@ elf_xtensa_relocate_section (bfd *output_bfd, not process them. */ if (unresolved_reloc && !((input_section->flags & SEC_DEBUGGING) != 0 - && h->def_dynamic)) + && h->def_dynamic) + && _bfd_elf_section_offset (output_bfd, info, input_section, + rel->r_offset) != (bfd_vma) -1) { (*_bfd_error_handler) (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), @@ -3094,7 +3135,7 @@ elf_xtensa_finish_dynamic_symbol (bfd *output_bfd ATTRIBUTE_UNUSED, } /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ - if (strcmp (h->root.root.string, "_DYNAMIC") == 0 + if (h == elf_hash_table (info)->hdynamic || h == elf_hash_table (info)->hgot) sym->st_shndx = SHN_ABS; @@ -3231,8 +3272,11 @@ elf_xtensa_finish_dynamic_sections (bfd *output_bfd, return TRUE; htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return FALSE; + dynobj = elf_hash_table (info)->dynobj; - sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + sdyn = bfd_get_linker_section (dynobj, ".dynamic"); BFD_ASSERT (sdyn != NULL); /* Set the first entry in the global offset table to the address of @@ -3422,7 +3466,7 @@ elf_xtensa_merge_private_bfd_data (bfd *ibfd, bfd *obfd) unsigned out_mach, in_mach; flagword out_flag, in_flag; - /* Check if we have the same endianess. */ + /* Check if we have the same endianness. */ if (!_bfd_generic_verify_endian_match (ibfd, obfd)) return FALSE; @@ -3751,7 +3795,7 @@ elf_xtensa_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); /* pr_pid */ - elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); + elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24); /* pr_reg */ offset = 72; @@ -5659,7 +5703,7 @@ print_action_list (FILE *fp, text_action_list *action_list) fprintf (fp, "%s: %s[0x%lx] \"%s\" %d\n", r->sec->owner->filename, - r->sec->name, r->offset, t, r->removed_bytes); + r->sec->name, (unsigned long) r->offset, t, r->removed_bytes); } } @@ -6023,7 +6067,7 @@ init_section_cache (section_cache_t *sec_cache) static void -clear_section_cache (section_cache_t *sec_cache) +free_section_cache (section_cache_t *sec_cache) { if (sec_cache->sec) { @@ -6031,7 +6075,6 @@ clear_section_cache (section_cache_t *sec_cache) release_internal_relocs (sec_cache->sec, sec_cache->relocs); if (sec_cache->ptbl) free (sec_cache->ptbl); - memset (sec_cache, 0, sizeof (sec_cache)); } } @@ -6072,8 +6115,8 @@ section_cache_section (section_cache_t *sec_cache, goto err; /* Fill in the new section cache. */ - clear_section_cache (sec_cache); - memset (sec_cache, 0, sizeof (sec_cache)); + free_section_cache (sec_cache); + init_section_cache (sec_cache); sec_cache->sec = sec; sec_cache->contents = contents; @@ -7778,7 +7821,6 @@ xlate_offset_with_removed_text (const xlate_map_t *map, text_action_list *action_list, bfd_vma offset) { - xlate_map_entry_t tmp; void *r; xlate_map_entry_t *e; @@ -7788,10 +7830,6 @@ xlate_offset_with_removed_text (const xlate_map_t *map, if (map->entry_count == 0) return offset; - tmp.orig_address = offset; - tmp.new_address = offset; - tmp.size = 1; - r = bsearch (&offset, map->entry, map->entry_count, sizeof (xlate_map_entry_t), &xlate_compare); e = (xlate_map_entry_t *) r; @@ -8233,8 +8271,9 @@ compute_removed_literals (bfd *abfd, #endif /* DEBUG */ error_return: - if (prop_table) free (prop_table); - clear_section_cache (&target_sec_cache); + if (prop_table) + free (prop_table); + free_section_cache (&target_sec_cache); release_contents (sec, contents); release_internal_relocs (sec, internal_relocs); @@ -8819,6 +8858,9 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info) internal_relocs = retrieve_internal_relocs (abfd, sec, link_info->keep_memory); + if (!internal_relocs && !relax_info->action_list.head) + return TRUE; + contents = retrieve_contents (abfd, sec, link_info->keep_memory); if (contents == NULL && sec_size != 0) { @@ -8921,9 +8963,9 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info) that here and adjust things accordingly. */ if (! elf_xtensa_ignore_discarded_relocs (sec) && elf_xtensa_action_discarded (sec) == PRETEND - && sec->sec_info_type != ELF_INFO_TYPE_STABS + && sec->sec_info_type != SEC_INFO_TYPE_STABS && target_sec != NULL - && elf_discarded_section (target_sec)) + && discarded_section (target_sec)) { /* It would be natural to call _bfd_elf_check_kept_section here, but it's not exported from elflink.c. It's also a @@ -9495,6 +9537,9 @@ shrink_dynamic_reloc_sections (struct bfd_link_info *info, bfd_boolean dynamic_symbol; htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return; + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); @@ -9603,12 +9648,10 @@ move_literal (bfd *abfd, { int r_type; unsigned i; - asection *target_sec; reloc_bfd_fix *fix; unsigned insert_at; r_type = ELF32_R_TYPE (r_rel->rela.r_info); - target_sec = r_reloc_get_section (r_rel); /* This is the difficult case. We have to create a fix up. */ this_rela.r_offset = offset; @@ -10225,12 +10268,15 @@ elf_xtensa_get_plt_section (struct bfd_link_info *info, int chunk) if (chunk == 0) { htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return NULL; + return htab->splt; } dynobj = elf_hash_table (info)->dynobj; sprintf (plt_name, ".plt.%u", chunk); - return bfd_get_section_by_name (dynobj, plt_name); + return bfd_get_linker_section (dynobj, plt_name); } @@ -10244,12 +10290,14 @@ elf_xtensa_get_gotplt_section (struct bfd_link_info *info, int chunk) if (chunk == 0) { htab = elf_xtensa_hash_table (info); + if (htab == NULL) + return NULL; return htab->sgotplt; } dynobj = elf_hash_table (info)->dynobj; sprintf (got_name, ".got.plt.%u", chunk); - return bfd_get_section_by_name (dynobj, got_name); + return bfd_get_linker_section (dynobj, got_name); } @@ -10628,7 +10676,7 @@ xtensa_callback_required_dependence (bfd *abfd, /* Find the corresponding ".got.plt*" section. */ if (sec->name[4] == '\0') - sgotplt = bfd_get_section_by_name (sec->owner, ".got.plt"); + sgotplt = bfd_get_linker_section (sec->owner, ".got.plt"); else { char got_name[14]; @@ -10638,7 +10686,7 @@ xtensa_callback_required_dependence (bfd *abfd, chunk = strtol (&sec->name[5], NULL, 10); sprintf (got_name, ".got.plt.%u", chunk); - sgotplt = bfd_get_section_by_name (sec->owner, got_name); + sgotplt = bfd_get_linker_section (sec->owner, got_name); } BFD_ASSERT (sgotplt); @@ -10711,6 +10759,7 @@ static const struct bfd_elf_special_section elf_xtensa_special_sections[] = { NULL, 0, 0, 0, 0 } }; +#define ELF_TARGET_ID XTENSA_ELF_DATA #ifndef ELF_ARCH #define TARGET_LITTLE_SYM bfd_elf32_xtensa_le_vec #define TARGET_LITTLE_NAME "elf32-xtensa-le"