X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-xtensa.c;h=b223424cce4e0c36b787aab144e7a28486fa3e65;hb=ebe84f23d2f3c0cb145cc7b3acfb011a4c7df1c9;hp=5e31e73a6fcccb32487a4ec02821b2e6d4eadf1b;hpb=dc1e8a474f904419abaa27da4be5b0f735a87255;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c index 5e31e73a6f..b223424cce 100644 --- a/bfd/elf32-xtensa.c +++ b/bfd/elf32-xtensa.c @@ -37,6 +37,22 @@ #define XTENSA_NO_NOP_REMOVAL 0 +#ifndef XSHAL_ABI +#define XSHAL_ABI 0 +#endif + +#ifndef XTHAL_ABI_UNDEFINED +#define XTHAL_ABI_UNDEFINED -1 +#endif + +#ifndef XTHAL_ABI_WINDOWED +#define XTHAL_ABI_WINDOWED 0 +#endif + +#ifndef XTHAL_ABI_CALL0 +#define XTHAL_ABI_CALL0 1 +#endif + /* Local helper functions. */ static bfd_boolean add_extra_plt_sections (struct bfd_link_info *, int); @@ -164,6 +180,10 @@ int elf32xtensa_no_literal_movement = 1; bfd_boolean elf32xtensa_separate_props = FALSE; +/* Xtensa ABI. It affects PLT entry code. */ + +int elf32xtensa_abi = XTHAL_ABI_UNDEFINED; + /* Rename one of the generic section flags to better document how it is used here. */ /* Whether relocations have been processed. */ @@ -325,6 +345,20 @@ static reloc_howto_type elf_howto_table[] = HOWTO (R_XTENSA_TLS_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont, bfd_elf_xtensa_reloc, "R_XTENSA_TLS_CALL", FALSE, 0, 0, FALSE), + + HOWTO (R_XTENSA_PDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, + bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF8", FALSE, 0, 0xff, FALSE), + HOWTO (R_XTENSA_PDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, + bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF16", FALSE, 0, 0xffff, FALSE), + HOWTO (R_XTENSA_PDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF32", FALSE, 0, 0xffffffff, FALSE), + + HOWTO (R_XTENSA_NDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, + bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF8", FALSE, 0, 0xff, FALSE), + HOWTO (R_XTENSA_NDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, + bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF16", FALSE, 0, 0xffff, FALSE), + HOWTO (R_XTENSA_NDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF32", FALSE, 0, 0xffffffff, FALSE), }; #if DEBUG_GEN_RELOC @@ -364,6 +398,30 @@ elf_xtensa_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, TRACE ("BFD_RELOC_XTENSA_DIFF32"); return &elf_howto_table[(unsigned) R_XTENSA_DIFF32 ]; + case BFD_RELOC_XTENSA_PDIFF8: + TRACE ("BFD_RELOC_XTENSA_PDIFF8"); + return &elf_howto_table[(unsigned) R_XTENSA_PDIFF8 ]; + + case BFD_RELOC_XTENSA_PDIFF16: + TRACE ("BFD_RELOC_XTENSA_PDIFF16"); + return &elf_howto_table[(unsigned) R_XTENSA_PDIFF16 ]; + + case BFD_RELOC_XTENSA_PDIFF32: + TRACE ("BFD_RELOC_XTENSA_PDIFF32"); + return &elf_howto_table[(unsigned) R_XTENSA_PDIFF32 ]; + + case BFD_RELOC_XTENSA_NDIFF8: + TRACE ("BFD_RELOC_XTENSA_NDIFF8"); + return &elf_howto_table[(unsigned) R_XTENSA_NDIFF8 ]; + + case BFD_RELOC_XTENSA_NDIFF16: + TRACE ("BFD_RELOC_XTENSA_NDIFF16"); + return &elf_howto_table[(unsigned) R_XTENSA_NDIFF16 ]; + + case BFD_RELOC_XTENSA_NDIFF32: + TRACE ("BFD_RELOC_XTENSA_NDIFF32"); + return &elf_howto_table[(unsigned) R_XTENSA_NDIFF32 ]; + case BFD_RELOC_XTENSA_RTLD: TRACE ("BFD_RELOC_XTENSA_RTLD"); return &elf_howto_table[(unsigned) R_XTENSA_RTLD ]; @@ -1001,7 +1059,7 @@ elf_xtensa_check_relocs (bfd *abfd, const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; - if (bfd_link_relocatable (info) || (sec->flags & SEC_ALLOC) == 0) + if (bfd_link_relocatable (info)) return TRUE; BFD_ASSERT (is_xtensa_elf (abfd)); @@ -1851,6 +1909,12 @@ elf_xtensa_do_reloc (reloc_howto_type *howto, case R_XTENSA_DIFF8: case R_XTENSA_DIFF16: case R_XTENSA_DIFF32: + case R_XTENSA_PDIFF8: + case R_XTENSA_PDIFF16: + case R_XTENSA_PDIFF32: + case R_XTENSA_NDIFF8: + case R_XTENSA_NDIFF16: + case R_XTENSA_NDIFF32: case R_XTENSA_TLS_FUNC: case R_XTENSA_TLS_ARG: case R_XTENSA_TLS_CALL: @@ -2203,6 +2267,13 @@ bfd_elf_xtensa_reloc (bfd *abfd, return flag; } +int xtensa_abi_choice (void) +{ + if (elf32xtensa_abi == XTHAL_ABI_UNDEFINED) + return XSHAL_ABI; + else + return elf32xtensa_abi; +} /* Set up an entry in the procedure linkage table. */ @@ -2215,6 +2286,7 @@ elf_xtensa_create_plt_entry (struct bfd_link_info *info, bfd_vma plt_base, got_base; bfd_vma code_offset, lit_offset, abi_offset; int chunk; + int abi = xtensa_abi_choice (); chunk = reloc_index / PLT_ENTRIES_PER_CHUNK; splt = elf_xtensa_get_plt_section (info, chunk); @@ -2235,10 +2307,10 @@ elf_xtensa_create_plt_entry (struct bfd_link_info *info, /* Fill in the entry in the procedure linkage table. */ memcpy (splt->contents + code_offset, (bfd_big_endian (output_bfd) - ? elf_xtensa_be_plt_entry[XSHAL_ABI != XTHAL_ABI_WINDOWED] - : elf_xtensa_le_plt_entry[XSHAL_ABI != XTHAL_ABI_WINDOWED]), + ? elf_xtensa_be_plt_entry[abi != XTHAL_ABI_WINDOWED] + : elf_xtensa_le_plt_entry[abi != XTHAL_ABI_WINDOWED]), PLT_ENTRY_SIZE); - abi_offset = XSHAL_ABI == XTHAL_ABI_WINDOWED ? 3 : 0; + abi_offset = abi == XTHAL_ABI_WINDOWED ? 3 : 0; bfd_put_16 (output_bfd, l32r_offset (got_base + 0, plt_base + code_offset + abi_offset), splt->contents + code_offset + abi_offset + 1); @@ -3004,9 +3076,7 @@ elf_xtensa_relocate_section (bfd *output_bfd, } } - if (lit_table) - free (lit_table); - + free (lit_table); input_section->reloc_done = TRUE; return TRUE; @@ -3086,8 +3156,7 @@ elf_xtensa_combine_prop_entries (bfd *output_bfd, if (!bfd_malloc_and_get_section (output_bfd, sxtlit, &contents)) { - if (contents != 0) - free (contents); + free (contents); free (table); return -1; } @@ -6251,8 +6320,7 @@ free_section_cache (section_cache_t *sec_cache) { release_contents (sec_cache->sec, sec_cache->contents); release_internal_relocs (sec_cache->sec, sec_cache->relocs); - if (sec_cache->ptbl) - free (sec_cache->ptbl); + free (sec_cache->ptbl); } } @@ -6309,8 +6377,7 @@ section_cache_section (section_cache_t *sec_cache, err: release_contents (sec, contents); release_internal_relocs (sec, internal_relocs); - if (prop_table) - free (prop_table); + free (prop_table); return FALSE; } @@ -6429,8 +6496,7 @@ init_ebb_constraint (ebb_constraint *c) static void free_ebb_constraint (ebb_constraint *c) { - if (c->actions) - free (c->actions); + free (c->actions); } @@ -6664,8 +6730,7 @@ ebb_propose_action (ebb_constraint *c, for (i = 0; i < c->action_count; i++) new_actions[i] = c->actions[i]; - if (c->actions) - free (c->actions); + free (c->actions); c->actions = new_actions; c->action_allocated = new_allocated; } @@ -6717,8 +6782,7 @@ pin_internal_relocs (asection *sec, Elf_Internal_Rela *internal_relocs) static void release_internal_relocs (asection *sec, Elf_Internal_Rela *internal_relocs) { - if (internal_relocs - && elf_section_data (sec)->relocs != internal_relocs) + if (elf_section_data (sec)->relocs != internal_relocs) free (internal_relocs); } @@ -6736,8 +6800,7 @@ retrieve_contents (bfd *abfd, asection *sec, bfd_boolean keep_memory) { if (!bfd_malloc_and_get_section (abfd, sec, &contents)) { - if (contents) - free (contents); + free (contents); return NULL; } if (keep_memory) @@ -6757,7 +6820,7 @@ pin_contents (asection *sec, bfd_byte *contents) static void release_contents (asection *sec, bfd_byte *contents) { - if (contents && elf_section_data (sec)->this_hdr.contents != contents) + if (elf_section_data (sec)->this_hdr.contents != contents) free (contents); } @@ -7842,10 +7905,8 @@ compute_text_actions (bfd *abfd, error_return: release_contents (sec, contents); release_internal_relocs (sec, internal_relocs); - if (prop_table) - free (prop_table); - if (reloc_opcodes) - free (reloc_opcodes); + free (prop_table); + free (reloc_opcodes); return ok; } @@ -8445,10 +8506,11 @@ build_xlate_map (asection *sec, xtensa_relax_info *relax_info) static void free_xlate_map (xlate_map_t *map) { - if (map && map->entry) - free (map->entry); if (map) - free (map); + { + free (map->entry); + free (map); + } } @@ -8632,8 +8694,7 @@ check_section_ebb_pcrels_fit (bfd *abfd, } } - if (xmap) - free_xlate_map (xmap); + free_xlate_map (xmap); return ok; } @@ -8845,8 +8906,7 @@ compute_removed_literals (bfd *abfd, #endif /* DEBUG */ error_return: - if (prop_table) - free (prop_table); + free (prop_table); free_section_cache (&target_sec_cache); release_contents (sec, contents); @@ -9604,7 +9664,13 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info) if (r_type == R_XTENSA_DIFF8 || r_type == R_XTENSA_DIFF16 - || r_type == R_XTENSA_DIFF32) + || r_type == R_XTENSA_DIFF32 + || r_type == R_XTENSA_PDIFF8 + || r_type == R_XTENSA_PDIFF16 + || r_type == R_XTENSA_PDIFF32 + || r_type == R_XTENSA_NDIFF8 + || r_type == R_XTENSA_NDIFF16 + || r_type == R_XTENSA_NDIFF32) { bfd_signed_vma diff_value = 0; bfd_vma new_end_offset, diff_mask = 0; @@ -9620,19 +9686,45 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info) switch (r_type) { case R_XTENSA_DIFF8: + diff_mask = 0x7f; diff_value = bfd_get_signed_8 (abfd, &contents[old_source_offset]); break; case R_XTENSA_DIFF16: + diff_mask = 0x7fff; diff_value = bfd_get_signed_16 (abfd, &contents[old_source_offset]); break; case R_XTENSA_DIFF32: + diff_mask = 0x7fffffff; diff_value = bfd_get_signed_32 (abfd, &contents[old_source_offset]); break; + case R_XTENSA_PDIFF8: + case R_XTENSA_NDIFF8: + diff_mask = 0xff; + diff_value = + bfd_get_8 (abfd, &contents[old_source_offset]); + break; + case R_XTENSA_PDIFF16: + case R_XTENSA_NDIFF16: + diff_mask = 0xffff; + diff_value = + bfd_get_16 (abfd, &contents[old_source_offset]); + break; + case R_XTENSA_PDIFF32: + case R_XTENSA_NDIFF32: + diff_mask = 0xffffffff; + diff_value = + bfd_get_32 (abfd, &contents[old_source_offset]); + break; } + if (r_type >= R_XTENSA_NDIFF8 + && r_type <= R_XTENSA_NDIFF32 + && diff_value) + diff_value |= ~diff_mask; + new_end_offset = offset_with_removed_text_map (&target_relax_info->action_list, r_rel.target_offset + diff_value); @@ -9641,25 +9733,40 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info) switch (r_type) { case R_XTENSA_DIFF8: - diff_mask = 0x7f; bfd_put_signed_8 (abfd, diff_value, &contents[old_source_offset]); break; case R_XTENSA_DIFF16: - diff_mask = 0x7fff; bfd_put_signed_16 (abfd, diff_value, &contents[old_source_offset]); break; case R_XTENSA_DIFF32: - diff_mask = 0x7fffffff; bfd_put_signed_32 (abfd, diff_value, &contents[old_source_offset]); break; + case R_XTENSA_PDIFF8: + case R_XTENSA_NDIFF8: + bfd_put_8 (abfd, diff_value, + &contents[old_source_offset]); + break; + case R_XTENSA_PDIFF16: + case R_XTENSA_NDIFF16: + bfd_put_16 (abfd, diff_value, + &contents[old_source_offset]); + break; + case R_XTENSA_PDIFF32: + case R_XTENSA_NDIFF32: + bfd_put_32 (abfd, diff_value, + &contents[old_source_offset]); + break; } - /* Check for overflow. Sign bits must be all zeroes or all ones */ - if ((diff_value & ~diff_mask) != 0 && - (diff_value & ~diff_mask) != (-1 & ~diff_mask)) + /* Check for overflow. Sign bits must be all zeroes or + all ones. When sign bits are all ones diff_value + may not be zero. */ + if (((diff_value & ~diff_mask) != 0 + && (diff_value & ~diff_mask) != ~diff_mask) + || (diff_value && (bfd_vma) diff_value == ~diff_mask)) { (*link_info->callbacks->reloc_dangerous) (link_info, _("overflow after relaxation"), @@ -10148,10 +10255,9 @@ shrink_dynamic_reloc_sections (struct bfd_link_info *info, if ((r_type == R_XTENSA_32 || r_type == R_XTENSA_PLT) && (input_section->flags & SEC_ALLOC) != 0 - && (dynamic_symbol || bfd_link_pic (info)) - && (!h || h->root.type != bfd_link_hash_undefweak - || (dynamic_symbol - && (bfd_link_dll (info) || info->export_dynamic)))) + && (dynamic_symbol + || (bfd_link_pic (info) + && (!h || h->root.type != bfd_link_hash_undefweak)))) { asection *srel; bfd_boolean is_plt = FALSE;