* bfd-in.h (bfd_elf32_arm_set_target_relocs): Add prototype.
	(bfd_elf32_arm_process_before_allocation): Update prototype.
	* bfd-in2.h: Regenerate.
	* bfd/elf32-arm.h (elf32_arm_link_hash_table): Add target2_reloc.
	(elf32_arm_link_hash_table_create): Set it.
	(bfd_elf32_arm_process_before_allocation): Remove target1_is_rel.
	(bfd_elf32_arm_set_target_relocs): New function.
	(arm_real_reloc_type): New function.
	(elf32_arm_final_link_relocate): Use it.  Handle R_ARM_PREL31 and
	R_ARM_GOT_PREL.  Remove R_ARM_TARGET1.
	(elf32_arm_gc_sweep_hook): Ditto.
	(elf32_arm_check_relocs): Ditto.
	(elf32_arm_relocate_section): Handle R_ARM_GOT_PREL.
	* elfarm-nabi.c (elf32_arm_howto_table): Add R_ARM_PREL31 and
	R_ARM_GOT_TARGET2.
	(elf32_arm_got_prel): New variable.
	(elf32_arm_howto_from_type): New function.
	(elf32_arm_info_to_howto): Use it.
	(elf32_arm_reloc_map): Add BFD_RELOC_ARM_PREL31 and
	BFD_RELOC_ARM_TARGET2.
	* libbfd.h: Regenerate.
	* reloc.c: Add BFD_RELOC_ARM_TARGET2 and BFD_RELOC_ARM_PREL31.
gas/
	* config/tc-arm.c (s_arm_rel31): New funciton.
	(md_pseudo_table): Add .rel31.
	(md_apply_fix3): Handle BFD_RELOC_ARM_TARGET2,
	BFD_RELOC_32_PCREL and BFD_RELOC_ARM_PREL31.
	(tc_gen_reloc): Handle BFD_RELOC_ARM_PREL31 and BFD_RELOC_ARM_TARGET2.
	(arm_fix_adjustable): Return 0 for BFD_RELOC_ARM_TARGET2.
	(arm_parse_reloc): Add (target2).
gas/testsuite/
	* gas/arm/pic.s: Add (target2).
	* gas/arm/pic.d: Ditto.
include/
	* elf/arm.h: Remove R_ARM_STKCHK and R_ARM_THM_STKCHK.
	Add R_ARM_TARGET2, R_ARM_PREL31, R_ARM_GOT_ABS, R_ARM_GOT_PREL,
	R_ARM_GOT_BREL12, R_ARM_GOTOFF12 and R_ARM_GOTRELAX.
ld/
	* ld.texinfo: Rename arm-specific section.  Document --target*
	* emulparams/armelf_fbsd.sh: Set TARGET2_TYPE.
	* emulparams/armelf_linux.sh: Ditto.
	* emulparams/armelf_nbsd.sh: Ditto.
	* emultempl/armelf.em: Set default for TARGET2_TYPE.
	(target2_type): New variable.
	(arm_elf_before_allocation): Don't pass target1_type.
	(arm_elf_create_output_section_statements): New function.
	(PARSE_AND_LIST_PROLOGUE): Add OPTION_TARGET2.
	(PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Add --target=.
	(PARSE_AND_LIST_ARGS_CASES): Handle OPTION_TARGET2.
	(LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS): Set.
	* emultempl/armelf_oabi.em (_before_allocation): Remove extra
	argument to bfd_elf32_arm_process_before_allocation.
ld/testsuite/
	* ld-arm/arm-target1-{abs,rel}.d}: New files.
	* ld-arm/arm-target1.s: New file.
	* ld-arm/arm-target2-{,got-}rel.d: New files.
	* ld-arm/arm-target2.s: New file.
	* ld-arm/arm-rel31.d: New files.
	* ld-arm/arm-rel31.s: New files.
	* ld-arm/arm.ld: New file.
	* ld-arm/arm-elf.exp: Add new tests.
This commit is contained in:
Paul Brook 2004-09-17 12:35:00 +00:00
parent 3674e28ad0
commit eb043451b1
14 changed files with 418 additions and 121 deletions

View File

@ -1,3 +1,28 @@
2004-09-17 Paul Brook <paul@codesourcery.com>
* bfd-in.h (bfd_elf32_arm_set_target_relocs): Add prototype.
(bfd_elf32_arm_process_before_allocation): Update prototype.
* bfd-in2.h: Regenerate.
* bfd/elf32-arm.h (elf32_arm_link_hash_table): Add target2_reloc.
(elf32_arm_link_hash_table_create): Set it.
(bfd_elf32_arm_process_before_allocation): Remove target1_is_rel.
(bfd_elf32_arm_set_target_relocs): New function.
(arm_real_reloc_type): New function.
(elf32_arm_final_link_relocate): Use it. Handle R_ARM_PREL31 and
R_ARM_GOT_PREL. Remove R_ARM_TARGET1.
(elf32_arm_gc_sweep_hook): Ditto.
(elf32_arm_check_relocs): Ditto.
(elf32_arm_relocate_section): Handle R_ARM_GOT_PREL.
* elfarm-nabi.c (elf32_arm_howto_table): Add R_ARM_PREL31 and
R_ARM_GOT_TARGET2.
(elf32_arm_got_prel): New variable.
(elf32_arm_howto_from_type): New function.
(elf32_arm_info_to_howto): Use it.
(elf32_arm_reloc_map): Add BFD_RELOC_ARM_PREL31 and
BFD_RELOC_ARM_TARGET2.
* libbfd.h: Regenerate.
* reloc.c: Add BFD_RELOC_ARM_TARGET2 and BFD_RELOC_ARM_PREL31.
2004-09-17 Alan Modra <amodra@bigpond.net.au> 2004-09-17 Alan Modra <amodra@bigpond.net.au>
* ecoff.c: Update u.undef.next refs. * ecoff.c: Update u.undef.next refs.

View File

@ -814,7 +814,10 @@ extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections
(struct bfd_link_info *); (struct bfd_link_info *);
extern bfd_boolean bfd_elf32_arm_process_before_allocation extern bfd_boolean bfd_elf32_arm_process_before_allocation
(bfd *, struct bfd_link_info *, int, int, int); (bfd *, struct bfd_link_info *, int, int);
void bfd_elf32_arm_set_target_relocs
(struct bfd_link_info *, int, char *);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *); (bfd *, struct bfd_link_info *);

View File

@ -821,7 +821,10 @@ extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections
(struct bfd_link_info *); (struct bfd_link_info *);
extern bfd_boolean bfd_elf32_arm_process_before_allocation extern bfd_boolean bfd_elf32_arm_process_before_allocation
(bfd *, struct bfd_link_info *, int, int, int); (bfd *, struct bfd_link_info *, int, int);
void bfd_elf32_arm_set_target_relocs
(struct bfd_link_info *, int, char *);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *); (bfd *, struct bfd_link_info *);
@ -2649,6 +2652,14 @@ entries in .init_array sections. */
/* Data segment base relative address. */ /* Data segment base relative address. */
BFD_RELOC_ARM_SBREL32, BFD_RELOC_ARM_SBREL32,
/* This reloc is used for References to RTTI dta from exception handling
tables. The actual definition depends on the target. It may be a
pc-relative or some form of GOT-indirect relocation. */
BFD_RELOC_ARM_TARGET2,
/* 31-bit PC relative address. */
BFD_RELOC_ARM_PREL31,
/* Renesas / SuperH SH relocs. Not all of these appear in object files. */ /* Renesas / SuperH SH relocs. Not all of these appear in object files. */
BFD_RELOC_SH_PCDISP8BY2, BFD_RELOC_SH_PCDISP8BY2,
BFD_RELOC_SH_PCDISP12BY2, BFD_RELOC_SH_PCDISP12BY2,

View File

@ -186,6 +186,9 @@ struct elf32_arm_link_hash_table
Nonzero if R_ARM_TARGET1 means R_ARM_ABS32. */ Nonzero if R_ARM_TARGET1 means R_ARM_ABS32. */
int target1_is_rel; int target1_is_rel;
/* The relocation to use for R_ARM_TARGET2 relocations. */
int target2_reloc;
/* The number of bytes in the initial entry in the PLT. */ /* The number of bytes in the initial entry in the PLT. */
bfd_size_type plt_header_size; bfd_size_type plt_header_size;
@ -378,6 +381,7 @@ elf32_arm_link_hash_table_create (bfd *abfd)
ret->no_pipeline_knowledge = 0; ret->no_pipeline_knowledge = 0;
ret->byteswap_code = 0; ret->byteswap_code = 0;
ret->target1_is_rel = 0; ret->target1_is_rel = 0;
ret->target2_reloc = R_ARM_NONE;
#ifdef FOUR_WORD_PLT #ifdef FOUR_WORD_PLT
ret->plt_header_size = 16; ret->plt_header_size = 16;
ret->plt_entry_size = 16; ret->plt_entry_size = 16;
@ -757,8 +761,7 @@ bfd_boolean
bfd_elf32_arm_process_before_allocation (bfd *abfd, bfd_elf32_arm_process_before_allocation (bfd *abfd,
struct bfd_link_info *link_info, struct bfd_link_info *link_info,
int no_pipeline_knowledge, int no_pipeline_knowledge,
int byteswap_code, int byteswap_code)
int target1_is_rel)
{ {
Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *internal_relocs = NULL;
@ -781,7 +784,7 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
BFD_ASSERT (globals->bfd_of_glue_owner != NULL); BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
globals->no_pipeline_knowledge = no_pipeline_knowledge; globals->no_pipeline_knowledge = no_pipeline_knowledge;
globals->target1_is_rel = target1_is_rel;
if (byteswap_code && !bfd_big_endian (abfd)) if (byteswap_code && !bfd_big_endian (abfd))
{ {
_bfd_error_handler (_("%B: BE8 images only valid in big-endian mode."), _bfd_error_handler (_("%B: BE8 images only valid in big-endian mode."),
@ -906,6 +909,32 @@ error_return:
} }
#endif #endif
#ifndef OLD_ARM_ABI
/* Set target relocation values needed during linking. */
void
bfd_elf32_arm_set_target_relocs (struct bfd_link_info *link_info,
int target1_is_rel,
char * target2_type)
{
struct elf32_arm_link_hash_table *globals;
globals = elf32_arm_hash_table (link_info);
globals->target1_is_rel = target1_is_rel;
if (strcmp (target2_type, "rel") == 0)
globals->target2_reloc = R_ARM_REL32;
else if (strcmp (target2_type, "got-rel") == 0)
globals->target2_reloc = R_ARM_GOT_PREL;
else
{
_bfd_error_handler (_("Invalid TARGET2 relocation type '%s'."),
target2_type);
}
}
#endif
/* The thumb form of a long branch is a bit finicky, because the offset /* The thumb form of a long branch is a bit finicky, because the offset
encoding is split over two fields, each in it's own instruction. They encoding is split over two fields, each in it's own instruction. They
can occur in any order. So given a thumb form of long branch, and an can occur in any order. So given a thumb form of long branch, and an
@ -1151,6 +1180,32 @@ elf32_arm_to_thumb_stub (struct bfd_link_info * info,
return TRUE; return TRUE;
} }
#ifndef OLD_ARM_ABI
/* Some relocations map to different relocations depending on the
target. Return the real relocation. */
static int
arm_real_reloc_type (struct elf32_arm_link_hash_table * globals,
int r_type)
{
switch (r_type)
{
case R_ARM_TARGET1:
if (globals->target1_is_rel)
return R_ARM_REL32;
else
return R_ARM_ABS32;
case R_ARM_TARGET2:
return globals->target2_reloc;
default:
return r_type;
}
}
#endif /* OLD_ARM_ABI */
/* Perform a relocation as part of a final link. */ /* Perform a relocation as part of a final link. */
static bfd_reloc_status_type static bfd_reloc_status_type
@ -1186,15 +1241,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
#ifndef OLD_ARM_ABI #ifndef OLD_ARM_ABI
/* Some relocation type map to different relocations depending on the /* Some relocation type map to different relocations depending on the
target. We pick the right one here. */ target. We pick the right one here. */
if (r_type == R_ARM_TARGET1) r_type = arm_real_reloc_type (globals, r_type);
{ if (r_type != howto->type)
if (globals->target1_is_rel) howto = elf32_arm_howto_from_type (r_type);
r_type = R_ARM_REL32;
else
r_type = R_ARM_ABS32;
howto = &elf32_arm_howto_table[r_type];
}
#endif /* OLD_ARM_ABI */ #endif /* OLD_ARM_ABI */
/* If the start address has been set, then set the EF_ARM_HASENTRY /* If the start address has been set, then set the EF_ARM_HASENTRY
@ -1245,6 +1294,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
case R_ARM_REL32: case R_ARM_REL32:
#ifndef OLD_ARM_ABI #ifndef OLD_ARM_ABI
case R_ARM_XPC25: case R_ARM_XPC25:
case R_ARM_PREL31:
#endif #endif
case R_ARM_PLT32: case R_ARM_PLT32:
/* r_symndx will be zero only for relocs against symbols /* r_symndx will be zero only for relocs against symbols
@ -1257,7 +1307,11 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
will use the symbol's value, which may point to a PLT entry, but we will use the symbol's value, which may point to a PLT entry, but we
don't need to handle that here. If we created a PLT entry, all don't need to handle that here. If we created a PLT entry, all
branches in this object should go to it. */ branches in this object should go to it. */
if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32) if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32
#ifndef OLD_ARM_ABI
&& r_type != R_ARM_PREL31
#endif
)
&& h != NULL && h != NULL
&& splt != NULL && splt != NULL
&& h->plt.offset != (bfd_vma) -1) && h->plt.offset != (bfd_vma) -1)
@ -1279,8 +1333,11 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
into the output file to be resolved at run time. */ into the output file to be resolved at run time. */
if (info->shared if (info->shared
&& (input_section->flags & SEC_ALLOC) && (input_section->flags & SEC_ALLOC)
&& (r_type != R_ARM_REL32 && ((r_type != R_ARM_REL32
|| !SYMBOL_CALLS_LOCAL (info, h)) #ifndef OLD_ARM_ABI
&& r_type != R_ARM_PREL31
#endif
) || !SYMBOL_CALLS_LOCAL (info, h))
&& (h == NULL && (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak) || h->root.type != bfd_link_hash_undefweak)
@ -1480,6 +1537,24 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
+ input_section->output_offset + rel->r_offset); + input_section->output_offset + rel->r_offset);
value += addend; value += addend;
break; break;
#ifndef OLD_ARM_ABI
case R_ARM_PREL31:
value -= (input_section->output_section->vma
+ input_section->output_offset + rel->r_offset);
value += signed_addend;
if (! h || h->root.type != bfd_link_hash_undefweak)
{
/* Check for overflow */
if ((value ^ (value >> 1)) & (1 << 30))
return bfd_reloc_overflow;
}
value &= 0x7fffffff;
value |= (bfd_get_32 (input_bfd, hit_data) & 0x80000000);
if (sym_flags == STT_ARM_TFUNC)
value |= 1;
break;
#endif
} }
bfd_put_32 (input_bfd, value, hit_data); bfd_put_32 (input_bfd, value, hit_data);
@ -1769,6 +1844,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
(bfd_vma) 0); (bfd_vma) 0);
case R_ARM_GOT32: case R_ARM_GOT32:
#ifndef OLD_ARM_ABI
case R_ARM_GOT_PREL:
#endif
/* Relocation is to the entry for this symbol in the /* Relocation is to the entry for this symbol in the
global offset table. */ global offset table. */
if (sgot == NULL) if (sgot == NULL)
@ -1857,6 +1935,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
value = sgot->output_offset + off; value = sgot->output_offset + off;
} }
if (r_type != R_ARM_GOT32)
value += sgot->output_section->vma;
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,
@ -2130,6 +2210,9 @@ elf32_arm_relocate_section (bfd * output_bfd,
break; break;
case R_ARM_GOT32: case R_ARM_GOT32:
#ifndef OLD_ARM_ABI
case R_ARM_GOT_PREL:
#endif
if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL
(elf_hash_table (info)->dynamic_sections_created, (elf_hash_table (info)->dynamic_sections_created,
info->shared, h)) info->shared, h))
@ -2726,6 +2809,9 @@ elf32_arm_gc_sweep_hook (bfd * abfd ATTRIBUTE_UNUSED,
const Elf_Internal_Rela *rel, *relend; const Elf_Internal_Rela *rel, *relend;
unsigned long r_symndx; unsigned long r_symndx;
struct elf_link_hash_entry *h; struct elf_link_hash_entry *h;
struct elf32_arm_link_hash_table * globals;
globals = elf32_arm_hash_table (info);
elf_section_data (sec)->local_dynrel = NULL; elf_section_data (sec)->local_dynrel = NULL;
@ -2735,66 +2821,77 @@ elf32_arm_gc_sweep_hook (bfd * abfd ATTRIBUTE_UNUSED,
relend = relocs + sec->reloc_count; relend = relocs + sec->reloc_count;
for (rel = relocs; rel < relend; rel++) for (rel = relocs; rel < relend; rel++)
switch (ELF32_R_TYPE (rel->r_info)) {
{ int r_type;
case R_ARM_GOT32:
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info)
{
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
if (h->got.refcount > 0)
h->got.refcount -= 1;
}
else if (local_got_refcounts != NULL)
{
if (local_got_refcounts[r_symndx] > 0)
local_got_refcounts[r_symndx] -= 1;
}
break;
case R_ARM_ABS32: r_type = ELF32_R_TYPE (rel->r_info);
case R_ARM_REL32:
#ifndef OLD_ARM_ABI #ifndef OLD_ARM_ABI
case R_ARM_TARGET1: r_type = arm_real_reloc_type (globals, r_type);
#endif #endif
case R_ARM_PC24: switch (r_type)
case R_ARM_PLT32: {
r_symndx = ELF32_R_SYM (rel->r_info); case R_ARM_GOT32:
if (r_symndx >= symtab_hdr->sh_info)
{
struct elf32_arm_link_hash_entry *eh;
struct elf32_arm_relocs_copied **pp;
struct elf32_arm_relocs_copied *p;
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
if (h->plt.refcount > 0)
h->plt.refcount -= 1;
if (ELF32_R_TYPE (rel->r_info) == R_ARM_ABS32
#ifndef OLD_ARM_ABI #ifndef OLD_ARM_ABI
|| ELF32_R_TYPE (rel->r_info) == R_ARM_TARGET1 case R_ARM_GOT_PREL:
#endif #endif
|| ELF32_R_TYPE (rel->r_info) == R_ARM_REL32) r_symndx = ELF32_R_SYM (rel->r_info);
{ if (r_symndx >= symtab_hdr->sh_info)
eh = (struct elf32_arm_link_hash_entry *) h; {
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
if (h->got.refcount > 0)
h->got.refcount -= 1;
}
else if (local_got_refcounts != NULL)
{
if (local_got_refcounts[r_symndx] > 0)
local_got_refcounts[r_symndx] -= 1;
}
break;
for (pp = &eh->relocs_copied; (p = *pp) != NULL; case R_ARM_ABS32:
pp = &p->next) case R_ARM_REL32:
if (p->section == sec) case R_ARM_PC24:
{ case R_ARM_PLT32:
p->count -= 1; #ifndef OLD_ARM_ABI
if (p->count == 0) case R_ARM_PREL31:
*pp = p->next; #endif
break; r_symndx = ELF32_R_SYM (rel->r_info);
} if (r_symndx >= symtab_hdr->sh_info)
} {
} struct elf32_arm_link_hash_entry *eh;
break; struct elf32_arm_relocs_copied **pp;
struct elf32_arm_relocs_copied *p;
default: h = sym_hashes[r_symndx - symtab_hdr->sh_info];
break;
} if (h->plt.refcount > 0)
h->plt.refcount -= 1;
if (r_type == R_ARM_ABS32
#ifndef OLD_ARM_ABI
|| r_type == R_ARM_PREL31
#endif
|| r_type == R_ARM_REL32)
{
eh = (struct elf32_arm_link_hash_entry *) h;
for (pp = &eh->relocs_copied; (p = *pp) != NULL;
pp = &p->next)
if (p->section == sec)
{
p->count -= 1;
if (p->count == 0)
*pp = p->next;
break;
}
}
}
break;
default:
break;
}
}
return TRUE; return TRUE;
} }
@ -2837,16 +2934,24 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
{ {
struct elf_link_hash_entry *h; struct elf_link_hash_entry *h;
unsigned long r_symndx; unsigned long r_symndx;
int r_type;
r_symndx = ELF32_R_SYM (rel->r_info); r_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
#ifndef OLD_ARM_ABI
r_type = arm_real_reloc_type (htab, r_type);
#endif
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];
switch (ELF32_R_TYPE (rel->r_info)) switch (r_type)
{ {
case R_ARM_GOT32: case R_ARM_GOT32:
#ifndef OLD_ARM_ABI
case R_ARM_GOT_PREL:
#endif
/* This symbol requires a global offset table entry. */ /* This symbol requires a global offset table entry. */
if (h != NULL) if (h != NULL)
{ {
@ -2871,7 +2976,9 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
} }
local_got_refcounts[r_symndx] += 1; local_got_refcounts[r_symndx] += 1;
} }
break; if (r_type == R_ARM_GOT32)
break;
/* Fall through. */
case R_ARM_GOTOFF: case R_ARM_GOTOFF:
case R_ARM_GOTPC: case R_ARM_GOTPC:
@ -2886,11 +2993,11 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_ARM_ABS32: case R_ARM_ABS32:
case R_ARM_REL32: case R_ARM_REL32:
#ifndef OLD_ARM_ABI
case R_ARM_TARGET1:
#endif
case R_ARM_PC24: case R_ARM_PC24:
case R_ARM_PLT32: case R_ARM_PLT32:
#ifndef OLD_ARM_ABI
case R_ARM_PREL31:
#endif
if (h != NULL) if (h != NULL)
{ {
/* If this reloc is in a read-only section, we might /* If this reloc is in a read-only section, we might
@ -2906,8 +3013,8 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
refers to is in a different object. We can't tell for refers to is in a different object. We can't tell for
sure yet, because something later might force the sure yet, because something later might force the
symbol local. */ symbol local. */
if (ELF32_R_TYPE (rel->r_info) == R_ARM_PC24 if (r_type == R_ARM_PC24
|| ELF32_R_TYPE (rel->r_info) == R_ARM_PLT32) || r_type == R_ARM_PLT32)
h->needs_plt = 1; h->needs_plt = 1;
/* If we create a PLT entry, this relocation will reference /* If we create a PLT entry, this relocation will reference
@ -2929,12 +3036,12 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
relocs_copied field of the hash table entry. */ relocs_copied field of the hash table entry. */
if (info->shared if (info->shared
&& (sec->flags & SEC_ALLOC) != 0 && (sec->flags & SEC_ALLOC) != 0
&& ((ELF32_R_TYPE (rel->r_info) != R_ARM_PC24 && ((r_type != R_ARM_PC24
&& ELF32_R_TYPE (rel->r_info) != R_ARM_PLT32 && r_type != R_ARM_PLT32
#ifndef OLD_ARM_ABI #ifndef OLD_ARM_ABI
&& ELF32_R_TYPE (rel->r_info) != R_ARM_TARGET1 && r_type != R_ARM_PREL31
#endif #endif
&& ELF32_R_TYPE (rel->r_info) != R_ARM_REL32) && r_type != R_ARM_REL32)
|| (h != NULL || (h != NULL
&& (! info->symbolic && (! info->symbolic
|| !h->def_regular)))) || !h->def_regular))))
@ -3017,11 +3124,11 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
p->count = 0; p->count = 0;
} }
if (ELF32_R_TYPE (rel->r_info) == R_ARM_ABS32 if (r_type == R_ARM_ABS32
#ifndef OLD_ARM_ABI #ifndef OLD_ARM_ABI
|| ELF32_R_TYPE (rel->r_info) == R_ARM_TARGET1 || r_type == R_ARM_PREL31
#endif #endif
|| ELF32_R_TYPE (rel->r_info) == R_ARM_REL32) || r_type == R_ARM_REL32)
p->count += 1; p->count += 1;
} }
break; break;

View File

@ -636,6 +636,34 @@ static reloc_howto_type elf32_arm_howto_table[] =
0xffffffff, /* src_mask */ 0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */ FALSE), /* pcrel_offset */
HOWTO (R_ARM_TARGET2, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TARGET2", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_PREL31, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
31, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_PREL31", /* name */
FALSE, /* partial_inplace */
0x7fffffff, /* src_mask */
0x7fffffff, /* dst_mask */
TRUE), /* pcrel_offset */
}; };
/* GNU extension to record C++ vtable hierarchy */ /* GNU extension to record C++ vtable hierarchy */
@ -702,44 +730,58 @@ static reloc_howto_type elf32_arm_thm_pc9_howto =
0x000000ff, /* dst_mask */ 0x000000ff, /* dst_mask */
TRUE); /* pcrel_offset */ TRUE); /* pcrel_offset */
static void elf32_arm_info_to_howto /* Place relative GOT-indirect. */
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); static reloc_howto_type elf32_arm_got_prel =
HOWTO (R_ARM_GOT_PREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_GOT_PREL", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE); /* pcrel_offset */
static reloc_howto_type *
elf32_arm_howto_from_type (unsigned int r_type)
{
if (r_type < NUM_ELEM (elf32_arm_howto_table))
return &elf32_arm_howto_table[r_type];
switch (r_type)
{
case R_ARM_GOT_PREL:
return &elf32_arm_got_prel;
case R_ARM_GNU_VTINHERIT:
return &elf32_arm_vtinherit_howto;
case R_ARM_GNU_VTENTRY:
return &elf32_arm_vtentry_howto;
case R_ARM_THM_PC11:
return &elf32_arm_thm_pc11_howto;
case R_ARM_THM_PC9:
return &elf32_arm_thm_pc9_howto;
default:
return NULL;
}
}
static void static void
elf32_arm_info_to_howto (abfd, bfd_reloc, elf_reloc) elf32_arm_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, arelent * bfd_reloc,
bfd * abfd ATTRIBUTE_UNUSED; Elf_Internal_Rela * elf_reloc)
arelent * bfd_reloc;
Elf_Internal_Rela * elf_reloc;
{ {
unsigned int r_type; unsigned int r_type;
r_type = ELF32_R_TYPE (elf_reloc->r_info); r_type = ELF32_R_TYPE (elf_reloc->r_info);
bfd_reloc->howto = elf32_arm_howto_from_type (r_type);
switch (r_type)
{
case R_ARM_GNU_VTINHERIT:
bfd_reloc->howto = & elf32_arm_vtinherit_howto;
break;
case R_ARM_GNU_VTENTRY:
bfd_reloc->howto = & elf32_arm_vtentry_howto;
break;
case R_ARM_THM_PC11:
bfd_reloc->howto = & elf32_arm_thm_pc11_howto;
break;
case R_ARM_THM_PC9:
bfd_reloc->howto = & elf32_arm_thm_pc9_howto;
break;
default:
if (r_type >= NUM_ELEM (elf32_arm_howto_table))
bfd_reloc->howto = NULL;
else
bfd_reloc->howto = & elf32_arm_howto_table[r_type];
break;
}
} }
struct elf32_arm_reloc_map struct elf32_arm_reloc_map
@ -748,6 +790,7 @@ struct elf32_arm_reloc_map
unsigned char elf_reloc_val; unsigned char elf_reloc_val;
}; };
/* All entries in this list must also be present in elf32_arm_howto_table. */
static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] = static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
{ {
{BFD_RELOC_NONE, R_ARM_NONE}, {BFD_RELOC_NONE, R_ARM_NONE},
@ -771,7 +814,9 @@ static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
{BFD_RELOC_ARM_PLT32, R_ARM_PLT32}, {BFD_RELOC_ARM_PLT32, R_ARM_PLT32},
{BFD_RELOC_ARM_TARGET1, R_ARM_TARGET1}, {BFD_RELOC_ARM_TARGET1, R_ARM_TARGET1},
{BFD_RELOC_ARM_ROSEGREL32, R_ARM_ROSEGREL32}, {BFD_RELOC_ARM_ROSEGREL32, R_ARM_ROSEGREL32},
{BFD_RELOC_ARM_SBREL32, R_ARM_SBREL32} {BFD_RELOC_ARM_SBREL32, R_ARM_SBREL32},
{BFD_RELOC_ARM_PREL31, R_ARM_PREL31},
{BFD_RELOC_ARM_TARGET2, R_ARM_TARGET2}
}; };
static reloc_howto_type * static reloc_howto_type *

View File

@ -1137,6 +1137,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_ARM_TARGET1", "BFD_RELOC_ARM_TARGET1",
"BFD_RELOC_ARM_ROSEGREL32", "BFD_RELOC_ARM_ROSEGREL32",
"BFD_RELOC_ARM_SBREL32", "BFD_RELOC_ARM_SBREL32",
"BFD_RELOC_ARM_TARGET2",
"BFD_RELOC_ARM_PREL31",
"BFD_RELOC_SH_PCDISP8BY2", "BFD_RELOC_SH_PCDISP8BY2",
"BFD_RELOC_SH_PCDISP12BY2", "BFD_RELOC_SH_PCDISP12BY2",
"BFD_RELOC_SH_IMM3", "BFD_RELOC_SH_IMM3",

View File

@ -2621,6 +2621,16 @@ ENUM
BFD_RELOC_ARM_SBREL32 BFD_RELOC_ARM_SBREL32
ENUMDOC ENUMDOC
Data segment base relative address. Data segment base relative address.
ENUM
BFD_RELOC_ARM_TARGET2
ENUMDOC
This reloc is used for References to RTTI dta from exception handling
tables. The actual definition depends on the target. It may be a
pc-relative or some form of GOT-indirect relocation.
ENUM
BFD_RELOC_ARM_PREL31
ENUMDOC
31-bit PC relative address.
ENUM ENUM
BFD_RELOC_SH_PCDISP8BY2 BFD_RELOC_SH_PCDISP8BY2

View File

@ -1,3 +1,13 @@
2004-09-17 Paul Brook <paul@codesourcery.com>
* config/tc-arm.c (s_arm_rel31): New funciton.
(md_pseudo_table): Add .rel31.
(md_apply_fix3): Handle BFD_RELOC_ARM_TARGET2,
BFD_RELOC_32_PCREL and BFD_RELOC_ARM_PREL31.
(tc_gen_reloc): Handle BFD_RELOC_ARM_PREL31 and BFD_RELOC_ARM_TARGET2.
(arm_fix_adjustable): Return 0 for BFD_RELOC_ARM_TARGET2.
(arm_parse_reloc): Add (target2).
2004-09-17 Alan Modra <amodra@bigpond.net.au> 2004-09-17 Alan Modra <amodra@bigpond.net.au>
* Makefile.am: Run "make dep-am". * Makefile.am: Run "make dep-am".

View File

@ -2445,6 +2445,7 @@ static void s_thumb_func PARAMS ((int));
static void s_thumb_set PARAMS ((int)); static void s_thumb_set PARAMS ((int));
#ifdef OBJ_ELF #ifdef OBJ_ELF
static void s_arm_elf_cons PARAMS ((int)); static void s_arm_elf_cons PARAMS ((int));
static void s_arm_rel31 (int nbytes);
#endif #endif
static int my_get_expression PARAMS ((expressionS *, char **)); static int my_get_expression PARAMS ((expressionS *, char **));
@ -2468,6 +2469,7 @@ const pseudo_typeS md_pseudo_table[] =
#ifdef OBJ_ELF #ifdef OBJ_ELF
{ "word", s_arm_elf_cons, 4 }, { "word", s_arm_elf_cons, 4 },
{ "long", s_arm_elf_cons, 4 }, { "long", s_arm_elf_cons, 4 },
{ "rel31", s_arm_rel31, 0 },
#else #else
{ "word", cons, 4}, { "word", cons, 4},
#endif #endif
@ -12481,6 +12483,7 @@ md_apply_fix3 (fixP, valP, seg)
#ifdef OBJ_ELF #ifdef OBJ_ELF
case BFD_RELOC_ARM_GOT32: case BFD_RELOC_ARM_GOT32:
case BFD_RELOC_ARM_GOTOFF: case BFD_RELOC_ARM_GOTOFF:
case BFD_RELOC_ARM_TARGET2:
md_number_to_chars (buf, 0, 4); md_number_to_chars (buf, 0, 4);
break; break;
#endif #endif
@ -12490,6 +12493,7 @@ md_apply_fix3 (fixP, valP, seg)
case BFD_RELOC_ARM_TARGET1: case BFD_RELOC_ARM_TARGET1:
case BFD_RELOC_ARM_ROSEGREL32: case BFD_RELOC_ARM_ROSEGREL32:
case BFD_RELOC_ARM_SBREL32: case BFD_RELOC_ARM_SBREL32:
case BFD_RELOC_32_PCREL:
if (fixP->fx_done || fixP->fx_pcrel) if (fixP->fx_done || fixP->fx_pcrel)
md_number_to_chars (buf, value, 4); md_number_to_chars (buf, value, 4);
#ifdef OBJ_ELF #ifdef OBJ_ELF
@ -12502,6 +12506,20 @@ md_apply_fix3 (fixP, valP, seg)
break; break;
#ifdef OBJ_ELF #ifdef OBJ_ELF
case BFD_RELOC_ARM_PREL31:
if (fixP->fx_done || fixP->fx_pcrel)
{
newval = md_chars_to_number (buf, 4) & 0x80000000;
if ((value ^ (value >> 1)) & 0x40000000)
{
as_bad_where (fixP->fx_file, fixP->fx_line,
_("rel31 relocation overflow"));
}
newval |= value & 0x7fffffff;
md_number_to_chars (buf, newval, 4);
}
break;
case BFD_RELOC_ARM_PLT32: case BFD_RELOC_ARM_PLT32:
/* It appears the instruction is fully prepared at this point. */ /* It appears the instruction is fully prepared at this point. */
break; break;
@ -12780,6 +12798,8 @@ tc_gen_reloc (section, fixp)
case BFD_RELOC_ARM_TARGET1: case BFD_RELOC_ARM_TARGET1:
case BFD_RELOC_ARM_ROSEGREL32: case BFD_RELOC_ARM_ROSEGREL32:
case BFD_RELOC_ARM_SBREL32: case BFD_RELOC_ARM_SBREL32:
case BFD_RELOC_ARM_PREL31:
case BFD_RELOC_ARM_TARGET2:
code = fixp->fx_r_type; code = fixp->fx_r_type;
break; break;
#endif #endif
@ -14090,7 +14110,8 @@ arm_fix_adjustable (fixP)
/* Don't allow symbols to be discarded on GOT related relocs. */ /* Don't allow symbols to be discarded on GOT related relocs. */
if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
|| fixP->fx_r_type == BFD_RELOC_ARM_GOT32 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
|| fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF) || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
|| fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
return 0; return 0;
return 1; return 1;
@ -14151,6 +14172,7 @@ arm_parse_reloc ()
MAP ("(plt)", BFD_RELOC_ARM_PLT32), MAP ("(plt)", BFD_RELOC_ARM_PLT32),
MAP ("(target1)", BFD_RELOC_ARM_TARGET1), MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32), MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
{ NULL, 0, BFD_RELOC_UNUSED } { NULL, 0, BFD_RELOC_UNUSED }
#undef MAP #undef MAP
}; };
@ -14225,6 +14247,50 @@ s_arm_elf_cons (nbytes)
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
} }
/* Parse a .rel31 directive. */
static void
s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
{
expressionS exp;
char *p;
valueT highbit;
SKIP_WHITESPACE ();
highbit = 0;
if (*input_line_pointer == '1')
highbit = 0x80000000;
else if (*input_line_pointer != '0')
as_bad (_("expected 0 or 1"));
input_line_pointer++;
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
as_bad (_("missing comma"));
input_line_pointer++;
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
#ifdef md_cons_align
md_cons_align (4);
#endif
mapping_state (MAP_DATA);
expression (&exp);
p = frag_more (4);
md_number_to_chars (p, highbit, 4);
fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
BFD_RELOC_ARM_PREL31);
demand_empty_rest_of_line ();
}
#endif /* OBJ_ELF */ #endif /* OBJ_ELF */
/* This is called from HANDLE_ALIGN in write.c. Fill in the contents /* This is called from HANDLE_ALIGN in write.c. Fill in the contents

View File

@ -1,3 +1,8 @@
2004-09-17 Paul Brook <paul@codesourcery.com>
* gas/arm/pic.s: Add (target2).
* gas/arm/pic.d: Ditto.
2004-09-13 Paul Brook <paul@codesourcery.com> 2004-09-13 Paul Brook <paul@codesourcery.com>
* gas/arm/pic.d: Rename RELABS to TARGET1. * gas/arm/pic.d: Rename RELABS to TARGET1.

View File

@ -17,3 +17,4 @@ Disassembly of section .text:
14: R_ARM_GOTPC _GLOBAL_OFFSET_TABLE_ 14: R_ARM_GOTPC _GLOBAL_OFFSET_TABLE_
18: R_ARM_TARGET1 foo2 18: R_ARM_TARGET1 foo2
1c: R_ARM_SBREL32 foo3 1c: R_ARM_SBREL32 foo3
20: R_ARM_TARGET2 foo4

View File

@ -11,3 +11,4 @@
.word _GLOBAL_OFFSET_TABLE_ - 1b .word _GLOBAL_OFFSET_TABLE_ - 1b
.word foo2(TARGET1) .word foo2(TARGET1)
.word foo3(SBREL) .word foo3(SBREL)
.word foo4(TARGET2)

View File

@ -1,3 +1,9 @@
2004-09-17 Paul Brook <paul@codesourcery.com>
* elf/arm.h: Remove R_ARM_STKCHK and R_ARM_THM_STKCHK.
Add R_ARM_TARGET2, R_ARM_PREL31, R_ARM_GOT_ABS, R_ARM_GOT_PREL,
R_ARM_GOT_BREL12, R_ARM_GOTOFF12 and R_ARM_GOTRELAX.
2004-09-17 Alan Modra <amodra@bigpond.net.au> 2004-09-17 Alan Modra <amodra@bigpond.net.au>
* bfdlink.h (struct bfd_link_hash_entry): Move und_next into elements * bfdlink.h (struct bfd_link_hash_entry): Move und_next into elements

View File

@ -130,10 +130,15 @@ START_RELOC_NUMBERS (elf_arm_reloc_type)
RELOC_NUMBER (R_ARM_TARGET1, 38) RELOC_NUMBER (R_ARM_TARGET1, 38)
RELOC_NUMBER (R_ARM_ROSEGREL32, 39) RELOC_NUMBER (R_ARM_ROSEGREL32, 39)
RELOC_NUMBER (R_ARM_V4BX, 40) RELOC_NUMBER (R_ARM_V4BX, 40)
RELOC_NUMBER (R_ARM_STKCHK, 41) RELOC_NUMBER (R_ARM_TARGET2, 41)
RELOC_NUMBER (R_ARM_THM_STKCHK, 42) RELOC_NUMBER (R_ARM_PREL31, 42)
FAKE_RELOC (FIRST_INVALID_RELOC2, 43) FAKE_RELOC (FIRST_INVALID_RELOC2, 43)
FAKE_RELOC (LAST_INVALID_RELOC2, 99) FAKE_RELOC (LAST_INVALID_RELOC2, 94)
RELOC_NUMBER (R_ARM_GOT_ABS, 95)
RELOC_NUMBER (R_ARM_GOT_PREL, 96)
RELOC_NUMBER (R_ARM_GOT_BREL12, 97)
RELOC_NUMBER (R_ARM_GOTOFF12, 98)
RELOC_NUMBER (R_ARM_GOTRELAX, 99)
RELOC_NUMBER (R_ARM_GNU_VTENTRY, 100) RELOC_NUMBER (R_ARM_GNU_VTENTRY, 100)
RELOC_NUMBER (R_ARM_GNU_VTINHERIT, 101) RELOC_NUMBER (R_ARM_GNU_VTINHERIT, 101)
RELOC_NUMBER (R_ARM_THM_PC11, 102) /* Cygnus extension to abi: Thumb unconditional branch. */ RELOC_NUMBER (R_ARM_THM_PC11, 102) /* Cygnus extension to abi: Thumb unconditional branch. */