(arm_add_to_rel): Fix R_ARM_THM_PC22 relocations.

This commit is contained in:
Alan Modra 2000-09-29 13:51:49 +00:00
parent 5cc18311d9
commit 9a5aca8c9c
2 changed files with 94 additions and 66 deletions

View File

@ -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> 2000-09-29 NIIBE Yutaka <gniibe@chroot.org>
* elflink.h (elf_link_add_object_symbols): Don't bfd_release runpath. * elflink.h (elf_link_add_object_symbols): Don't bfd_release runpath.

View File

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