X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=bfd%2Felfxx-mips.c;h=e2f47499e9349ecbcb727c0c2ce27efd352888c1;hb=de5b02b698cb34f1a7f7f0be87d140f88297da0e;hp=3e7b48845be9c25cdf83073018808c3b2a3a4c26;hpb=ed53407eec9eba3b55a3a00fb7eaa7eddbf01363;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 3e7b48845b..e2f47499e9 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -2215,6 +2215,15 @@ jal_reloc_p (int r_type) || r_type == R_MICROMIPS_26_S1); } +static inline bfd_boolean +b_reloc_p (int r_type) +{ + return (r_type == R_MIPS_PC26_S2 + || r_type == R_MIPS_PC21_S2 + || r_type == R_MIPS_PC16 + || r_type == R_MIPS_GNU_REL16_S2); +} + static inline bfd_boolean aligned_pcrel_reloc_p (int r_type) { @@ -5247,6 +5256,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, /* TRUE if the symbol referred to by this relocation is a local symbol. */ bfd_boolean local_p, was_local_p; + /* TRUE if the symbol referred to by this relocation is a section + symbol. */ + bfd_boolean section_p = FALSE; /* TRUE if the symbol referred to by this relocation is "_gp_disp". */ bfd_boolean gp_disp_p = FALSE; /* TRUE if the symbol referred to by this relocation is @@ -5302,12 +5314,12 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, sym = local_syms + r_symndx; sec = local_sections[r_symndx]; + section_p = ELF_ST_TYPE (sym->st_info) == STT_SECTION; + symbol = sec->output_section->vma + sec->output_offset; - if (ELF_ST_TYPE (sym->st_info) != STT_SECTION - || (sec->flags & SEC_MERGE)) + if (!section_p || (sec->flags & SEC_MERGE)) symbol += sym->st_value; - if ((sec->flags & SEC_MERGE) - && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + if ((sec->flags & SEC_MERGE) && section_p) { addend = _bfd_elf_rel_local_sym (abfd, sym, &sec, addend); addend -= symbol; @@ -5322,7 +5334,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, *namep = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name); - if (*namep == '\0') + if (*namep == NULL || **namep == '\0') *namep = bfd_section_name (input_bfd, sec); target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (sym->st_other); @@ -5410,17 +5422,14 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf */ symbol = 0; } - else if ((*info->callbacks->undefined_symbol) - (info, h->root.root.root.string, input_bfd, - input_section, relocation->r_offset, - (info->unresolved_syms_in_objects == RM_GENERATE_ERROR) - || ELF_ST_VISIBILITY (h->root.other))) - { - return bfd_reloc_undefined; - } else { - return bfd_reloc_notsupported; + (*info->callbacks->undefined_symbol) + (info, h->root.root.root.string, input_bfd, + input_section, relocation->r_offset, + (info->unresolved_syms_in_objects == RM_GENERATE_ERROR) + || ELF_ST_VISIBILITY (h->root.other)); + return bfd_reloc_undefined; } target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (h->root.other); @@ -5773,22 +5782,22 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, { unsigned int shift; - /* Make sure the target of JALX is word-aligned. Bit 0 must be - the correct ISA mode selector and bit 1 must be 0. */ - if (*cross_mode_jump_p && (symbol & 3) != (r_type == R_MIPS_26)) - return bfd_reloc_outofrange; - /* Shift is 2, unusually, for microMIPS JALX. */ shift = (!*cross_mode_jump_p && r_type == R_MICROMIPS_26_S1) ? 1 : 2; - if (was_local_p) - value = addend | ((p + 4) & (0xfc000000 << shift)); - else if (howto->partial_inplace) + if (howto->partial_inplace && !section_p) value = _bfd_mips_elf_sign_extend (addend, 26 + shift); else value = addend; - value = (value + symbol) >> shift; - if (!was_local_p && h->root.root.type != bfd_link_hash_undefweak) + value += symbol; + + /* Make sure the target of JALX is word-aligned. Bit 0 must be + the correct ISA mode selector and bit 1 must be 0. */ + if (*cross_mode_jump_p && (value & 3) != (r_type == R_MIPS_26)) + return bfd_reloc_outofrange; + + value >>= shift; + if (was_local_p || h->root.root.type != bfd_link_hash_undefweak) overflowed_p = (value >> 26) != ((p + 4) >> (26 + shift)); value &= howto->dst_mask; } @@ -10248,10 +10257,9 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, htab->small_data_overflow_reported = TRUE; (*info->callbacks->einfo) ("%P: %s\n", msg); } - if (! ((*info->callbacks->reloc_overflow) - (info, NULL, name, howto->name, (bfd_vma) 0, - input_bfd, input_section, rel->r_offset))) - return FALSE; + (*info->callbacks->reloc_overflow) + (info, NULL, name, howto->name, (bfd_vma) 0, + input_bfd, input_section, rel->r_offset); } break; @@ -10262,6 +10270,8 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, msg = NULL; if (jal_reloc_p (howto->type)) msg = _("JALX to a non-word-aligned address"); + else if (b_reloc_p (howto->type)) + msg = _("Branch to a non-instruction-aligned address"); else if (aligned_pcrel_reloc_p (howto->type)) msg = _("PC-relative load from unaligned address"); if (msg) @@ -12927,25 +12937,22 @@ _bfd_elf_mips_get_relocated_section_contents switch (r) { case bfd_reloc_undefined: - if (!((*link_info->callbacks->undefined_symbol) - (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), - input_bfd, input_section, (*parent)->address, TRUE))) - goto error_return; + (*link_info->callbacks->undefined_symbol) + (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr), + input_bfd, input_section, (*parent)->address, TRUE); break; case bfd_reloc_dangerous: BFD_ASSERT (error_message != NULL); - if (!((*link_info->callbacks->reloc_dangerous) - (link_info, error_message, input_bfd, input_section, - (*parent)->address))) - goto error_return; + (*link_info->callbacks->reloc_dangerous) + (link_info, error_message, + input_bfd, input_section, (*parent)->address); break; case bfd_reloc_overflow: - if (!((*link_info->callbacks->reloc_overflow) - (link_info, NULL, - bfd_asymbol_name (*(*parent)->sym_ptr_ptr), - (*parent)->howto->name, (*parent)->addend, - input_bfd, input_section, (*parent)->address))) - goto error_return; + (*link_info->callbacks->reloc_overflow) + (link_info, NULL, + bfd_asymbol_name (*(*parent)->sym_ptr_ptr), + (*parent)->howto->name, (*parent)->addend, + input_bfd, input_section, (*parent)->address); break; case bfd_reloc_outofrange: default: