From 9a5aca8c9ced16f613ccff18ee5356fbfd13804a Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 29 Sep 2000 13:51:49 +0000 Subject: [PATCH] (arm_add_to_rel): Fix R_ARM_THM_PC22 relocations. --- bfd/ChangeLog | 5 ++ bfd/elf32-arm.h | 155 +++++++++++++++++++++++++++--------------------- 2 files changed, 94 insertions(+), 66 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b454dc841b0..046387c24ab 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2000-09-29 Momchil Velikov + + * elf32-arm.h (arm_add_to_rel): Correctly adjust the addend for + R_ARM_THM_PC22 relocations. + 2000-09-29 NIIBE Yutaka * elflink.h (elf_link_add_object_symbols): Don't bfd_release runpath. diff --git a/bfd/elf32-arm.h b/bfd/elf32-arm.h index 46f8ff62370..1baee0fc24d 100644 --- a/bfd/elf32-arm.h +++ b/bfd/elf32-arm.h @@ -544,7 +544,7 @@ bfd_elf32_arm_get_bfd_for_interworking (abfd, info) || !bfd_set_section_flags (abfd, sec, flags) || !bfd_set_section_alignment (abfd, sec, 2)) return false; - + /* Set the gc mark to prevent the section from being removed by garbage collection, despite the fact that no relocs refer to this section. */ sec->gc_mark = 1; @@ -562,7 +562,7 @@ bfd_elf32_arm_get_bfd_for_interworking (abfd, info) || !bfd_set_section_flags (abfd, sec, flags) || !bfd_set_section_alignment (abfd, sec, 2)) return false; - + sec->gc_mark = 1; } @@ -724,7 +724,7 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge) } return true; - + error_return: if (free_relocs != NULL) free (free_relocs); @@ -732,7 +732,7 @@ error_return: free (free_contents); if (free_extsyms != NULL) free (free_extsyms); - + return false; } @@ -979,7 +979,7 @@ elf32_arm_to_thumb_stub (info, name, input_bfd, output_bfd, input_section, + input_section->output_section->vma + offset + addend) - 8; - + tmp = tmp | ((ret_offset >> 2) & 0x00FFFFFF); bfd_put_32 (output_bfd, tmp, hit_data @@ -1154,13 +1154,13 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, sreloc->contents) + sreloc->reloc_count)); ++sreloc->reloc_count; - + /* If this reloc is against an external symbol, we do not want to fiddle with the addend. Otherwise, we need to include the symbol value so that it becomes an addend for the dynamic reloc. */ if (! relocate) return bfd_reloc_ok; - + return _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, value, (bfd_vma) 0); @@ -1252,11 +1252,11 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, signed_addend = value; signed_addend >>= howto->rightshift; - + /* It is not an error for an undefined weak reference to be out of range. Any program that branches to such a symbol - is going to crash anyway, so there is no point worrying - about getting the destination exactly right. */ + is going to crash anyway, so there is no point worrying + about getting the destination exactly right. */ if (! h || h->root.type != bfd_link_hash_undefweak) { /* Perform a signed range check. */ @@ -1264,7 +1264,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, || signed_addend < - ((bfd_signed_vma) ((howto->dst_mask + 1) >> 1))) return bfd_reloc_overflow; } - + #ifndef OLD_ARM_ABI /* If necessary set the H bit in the BLX instruction. */ if (r_type == R_ARM_XPC25 && ((value & 2) == 2)) @@ -1401,11 +1401,11 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, relocation -= (input_section->output_section->vma + input_section->output_offset + rel->r_offset); - + if (! globals->no_pipeline_knowledge) { Elf_Internal_Ehdr * i_ehdrp; /* Elf file header, internal form. */ - + i_ehdrp = elf_elfheader (input_bfd); /* Previous versions of this code also used to add in the pipline @@ -1467,7 +1467,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, BFD_ASSERT (sgot != NULL); if (sgot == NULL) return bfd_reloc_notsupported; - + /* Note that sgot->output_offset is not involved in this calculation. We always want the start of .got. If we define _GLOBAL_OFFSET_TABLE in a different way, as is @@ -1569,7 +1569,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, value = sgot->output_offset + off; } - + return _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, value, (bfd_vma) 0); @@ -1642,44 +1642,67 @@ arm_add_to_rel (abfd, address, howto, increment) reloc_howto_type * howto; bfd_signed_vma increment; { - bfd_vma contents; bfd_signed_vma addend; - contents = bfd_get_32 (abfd, address); - - /* Get the (signed) value from the instruction. */ - addend = contents & howto->src_mask; - if (addend & ((howto->src_mask + 1) >> 1)) + if (howto->type == R_ARM_THM_PC22) { - bfd_signed_vma mask; - - mask = -1; - mask &= ~ howto->src_mask; - addend |= mask; - } + int upper_insn, lower_insn; + int upper, lower; - /* Add in the increment, (which is a byte value). */ - switch (howto->type) - { - case R_ARM_THM_PC22: - default: + upper_insn = bfd_get_16 (abfd, address); + lower_insn = bfd_get_16 (abfd, address + 2); + upper = upper_insn & 0x7ff; + lower = lower_insn & 0x7ff; + + addend = (upper << 12) | (lower << 1); addend += increment; - break; - - case R_ARM_PC24: - addend <<= howto->size; - addend += increment; - - /* Should we check for overflow here ? */ + addend >>= 1; - /* Drop any undesired bits. */ - addend >>= howto->rightshift; - break; + upper_insn = (upper_insn & 0xf800) | ((addend >> 11) & 0x7ff); + lower_insn = (lower_insn & 0xf800) | (addend & 0x7ff); + + bfd_put_16 (abfd, upper_insn, address); + bfd_put_16 (abfd, lower_insn, address + 2); + } + else + { + bfd_vma contents; + + contents = bfd_get_32 (abfd, address); + + /* Get the (signed) value from the instruction. */ + addend = contents & howto->src_mask; + if (addend & ((howto->src_mask + 1) >> 1)) + { + bfd_signed_vma mask; + + mask = -1; + mask &= ~ howto->src_mask; + addend |= mask; + } + + /* Add in the increment, (which is a byte value). */ + switch (howto->type) + { + default: + addend += increment; + break; + + case R_ARM_PC24: + addend <<= howto->size; + addend += increment; + + /* Should we check for overflow here ? */ + + /* Drop any undesired bits. */ + addend >>= howto->rightshift; + break; + } + + contents = (contents & ~ howto->dst_mask) | (addend & howto->dst_mask); + + bfd_put_32 (abfd, contents, address); } - - contents = (contents & ~ howto->dst_mask) | (addend & howto->dst_mask); - - bfd_put_32 (abfd, contents, address); } #endif /* USE_REL */ @@ -2144,42 +2167,42 @@ elf32_arm_print_private_bfd_data (abfd, ptr) the EABI version is not set. */ if (flags & EF_INTERWORK) fprintf (file, _(" [interworking enabled]")); - + if (flags & EF_APCS_26) fprintf (file, _(" [APCS-26]")); else fprintf (file, _(" [APCS-32]")); - + if (flags & EF_APCS_FLOAT) fprintf (file, _(" [floats passed in float registers]")); - + if (flags & EF_PIC) fprintf (file, _(" [position independent]")); if (flags & EF_NEW_ABI) fprintf (file, _(" [new ABI]")); - + if (flags & EF_OLD_ABI) fprintf (file, _(" [old ABI]")); - + if (flags & EF_SOFT_FLOAT) fprintf (file, _(" [software FP]")); - + flags &= ~(EF_INTERWORK | EF_APCS_26 | EF_APCS_FLOAT | EF_PIC | EF_NEW_ABI | EF_OLD_ABI | EF_SOFT_FLOAT); break; - + case EF_ARM_EABI_VER1: fprintf (file, _(" [Version1 EABI]")); - + if (flags & EF_ARM_SYMSARESORTED) fprintf (file, _(" [sorted symbol table]")); else fprintf (file, _(" [unsorted symbol table]")); - + flags &= ~ EF_ARM_SYMSARESORTED; break; - + default: fprintf (file, _(" ")); break; @@ -2197,7 +2220,7 @@ elf32_arm_print_private_bfd_data (abfd, ptr) if (flags) fprintf (file, _("")); - + fputc ('\n', file); return true; @@ -2221,7 +2244,7 @@ elf32_arm_get_symbol_type (elf_sym, type) if (type != STT_OBJECT) return ELF_ST_TYPE (elf_sym->st_info); break; - + default: break; } @@ -2303,12 +2326,12 @@ elf32_arm_check_relocs (abfd, info, sec, relocs) bfd * dynobj; asection * sgot, *srelgot, *sreloc; bfd_vma * local_got_offsets; - + if (info->relocateable) return true; - + sgot = srelgot = sreloc = NULL; - + dynobj = elf_hash_table (info)->dynobj; local_got_offsets = elf_local_got_offsets (abfd); @@ -2325,13 +2348,13 @@ elf32_arm_check_relocs (abfd, info, sec, relocs) { struct elf_link_hash_entry *h; unsigned long r_symndx; - + r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) h = NULL; else h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - + /* Some relocs require a global offset table. */ if (dynobj == NULL) { @@ -2365,7 +2388,7 @@ elf32_arm_check_relocs (abfd, info, sec, relocs) && (h != NULL || info->shared)) { srelgot = bfd_get_section_by_name (dynobj, ".rel.got"); - + /* If no got relocation section, make one and initialize. */ if (srelgot == NULL) { @@ -2550,7 +2573,7 @@ elf32_arm_check_relocs (abfd, info, sec, relocs) if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) return false; break; - + /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_ARM_GNU_VTENTRY: @@ -2930,7 +2953,7 @@ elf32_arm_size_dynamic_sections (output_bfd, info) outname = bfd_get_section_name (output_bfd, s->output_section); target = bfd_get_section_by_name (output_bfd, outname + 4); - + if (target != NULL && (target->flags & SEC_READONLY) != 0 && (target->flags & SEC_ALLOC) != 0) -- 2.30.2