summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2000-09-29 13:51:49 +0000
committerAlan Modra <amodra@bigpond.net.au>2000-09-29 13:51:49 +0000
commit44da33e8805093f05cf5e20b499191bc02b1ea04 (patch)
treeef66f781ee24243c8e7a918ebc9bc49c3c028f14
parent5e86a3ed4e75bf0c5c3037dd0352dc660c8418ad (diff)
downloadbinutils-redhat-44da33e8805093f05cf5e20b499191bc02b1ea04.tar.gz
(arm_add_to_rel): Fix R_ARM_THM_PC22 relocations.
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/elf32-arm.h155
2 files changed, 94 insertions, 66 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index b454dc841b..046387c24a 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,8 @@
+2000-09-29 Momchil Velikov <velco@fadata.bg>
+
+ * elf32-arm.h (arm_add_to_rel): Correctly adjust the addend for
+ R_ARM_THM_PC22 relocations.
+
2000-09-29 NIIBE Yutaka <gniibe@chroot.org>
* 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 46f8ff6237..1baee0fc24 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, _(" <EABI version unrecognised>"));
break;
@@ -2197,7 +2220,7 @@ elf32_arm_print_private_bfd_data (abfd, ptr)
if (flags)
fprintf (file, _("<Unrecognised flag bits set>"));
-
+
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)