/* Renesas / SuperH SH specific support for 32-bit ELF
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Contributed by Ian Lance Taylor, Cygnus Support.
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/sh.h"
+#include "libiberty.h"
static bfd_reloc_status_type sh_elf_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
TRUE), /* pcrel_offset */
/* The assembler will generate this reloc before a block of
- instructions. A section should be processed as assumining it
+ instructions. A section should be processed as assuming it
contains data, unless this reloc is seen. */
HOWTO (R_SH_CODE, /* type */
0, /* rightshift */
/* The addend will be against the section symbol, thus
for adjusting the addend, the relevant start is the
start of the section.
- N.B. If we want to abandom in-place changes here and
+ N.B. If we want to abandon in-place changes here and
test directly using symbol + addend, we have to take into
account that the addend has already been adjusted by -4. */
if (stop > addr && stop < toaddr)
#if 1
/* Note - this code has been "optimised" not to use r2. r2 is used by
- GCC to return the address of large strutcures, so it should not be
+ GCC to return the address of large structures, so it should not be
corrupted here. This does mean however, that this PLT does not conform
to the SH PIC ABI. That spec says that r0 contains the type of the PLT
and r2 contains the GOT id. This version stores the GOT id in r0 and
/* Return offset of the GOT id in PLT0 entry. */
#define elf_sh_plt0_gotid_offset(info) 24
-/* Return offset of the tempoline in PLT entry */
+/* Return offset of the temporary in PLT entry */
#define elf_sh_plt_temp_offset(info) 8
/* Return offset of the symbol in PLT entry. */
h->type = STT_OBJECT;
if (info->shared
- && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
return TRUE;
}
-/* This is the condition under which sh_elf_finish_dynamic_symbol
- will be called from elflink.h. If elflink.h doesn't call our
- finish_dynamic_symbol routine, we'll need to do something about
- initializing any .plt and .got entries in sh_elf_relocate_section. */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
- ((DYN) \
- && ((SHARED) \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
- && ((H)->dynindx != -1 \
- || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
-
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs. */
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
the .dynamic section. The DT_DEBUG entry is filled in by the
dynamic linker and used by the debugger. */
#define add_dynamic_entry(TAG, VAL) \
- bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+ _bfd_elf_add_dynamic_entry (info, TAG, VAL)
if (info->executable)
{
}
else if (h->root.type == bfd_link_hash_undefweak)
relocation = 0;
- else if (! info->executable
- && info->unresolved_syms_in_objects == RM_IGNORE
+ else if (info->unresolved_syms_in_objects == RM_IGNORE
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
relocation = 0;
else
if (! info->callbacks->undefined_symbol
(info, h->root.root.string, input_bfd,
input_section, rel->r_offset,
- ((info->shared && info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR)
- || (!info->shared && info->unresolved_syms_in_objects == RM_GENERATE_ERROR)
+ (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
|| ELF_ST_VISIBILITY (h->other))))
return FALSE;
relocation = 0;
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_SH_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_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_SH_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
#ifndef sh_elf_set_mach_from_flags
+static unsigned int sh_ef_bfd_table[] = { EF_SH_BFD_TABLE };
+
static bfd_boolean
sh_elf_set_mach_from_flags (bfd *abfd)
{
- flagword flags = elf_elfheader (abfd)->e_flags;
+ flagword flags = elf_elfheader (abfd)->e_flags & EF_SH_MACH_MASK;
+
+ if (flags >= sizeof(sh_ef_bfd_table))
+ return FALSE;
+
+ if (sh_ef_bfd_table[flags] == 0)
+ return FALSE;
+
+ bfd_default_set_arch_mach (abfd, bfd_arch_sh, sh_ef_bfd_table[flags]);
- switch (flags & EF_SH_MACH_MASK)
- {
- case EF_SH1:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh);
- break;
- case EF_SH2:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh2);
- break;
- case EF_SH2E:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh2e);
- break;
- case EF_SH_DSP:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh_dsp);
- break;
- case EF_SH3:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3);
- break;
- case EF_SH3_DSP:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3_dsp);
- break;
- case EF_SH3E:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3e);
- break;
- case EF_SH_UNKNOWN:
- case EF_SH4:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh4);
- break;
- case EF_SH4_NOFPU:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh4_nofpu);
- break;
- case EF_SH4A:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh4a);
- break;
- case EF_SH4A_NOFPU:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh4a_nofpu);
- break;
- case EF_SH4AL_DSP:
- bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh4al_dsp);
- break;
- default:
- return FALSE;
- }
return TRUE;
}
+
+
+/* Reverse table lookup for sh_ef_bfd_table[].
+ Given a bfd MACH value from archures.c
+ return the equivalent ELF flags from the table.
+ Return -1 if no match is found. */
+
+int
+sh_elf_get_flags_from_mach (unsigned long mach)
+{
+ int i = ARRAY_SIZE (sh_ef_bfd_table);
+
+ for (; i>0; i--)
+ if (sh_ef_bfd_table[i] == mach)
+ return i;
+
+ /* shouldn't get here */
+ BFD_FAIL();
+
+ return -1;
+}
#endif /* not sh_elf_set_mach_from_flags */
#ifndef sh_elf_set_private_flags
#endif /* not sh_elf_copy_private_data */
#ifndef sh_elf_merge_private_data
-/* This routine checks for linking big and little endian objects
- together, and for linking sh-dsp with sh3e / sh4 objects. */
-static bfd_boolean
-sh_elf_merge_private_data (bfd *ibfd, bfd *obfd)
+/* This function returns the ELF architecture number that
+ corresponds to the given arch_sh* flags. */
+int
+sh_find_elf_flags (unsigned int arch_set)
{
- flagword old_flags, new_flags;
+ unsigned long bfd_mach = sh_get_bfd_mach_from_arch_set (arch_set);
+
+ return sh_elf_get_flags_from_mach (bfd_mach);
+}
- if (! _bfd_generic_verify_endian_match (ibfd, obfd))
- return FALSE;
+/* This routine initialises the elf flags when required and
+ calls sh_merge_bfd_arch() to check dsp/fpu compatibility. */
+
+static bfd_boolean
+sh_elf_merge_private_data (bfd *ibfd, bfd *obfd)
+{
if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
/* This happens when ld starts out with a 'blank' output file. */
elf_flags_init (obfd) = TRUE;
elf_elfheader (obfd)->e_flags = EF_SH1;
+ sh_elf_set_mach_from_flags (obfd);
}
- old_flags = elf_elfheader (obfd)->e_flags;
- new_flags = elf_elfheader (ibfd)->e_flags;
- if ((EF_SH_HAS_DSP (old_flags) && EF_SH_HAS_FP (new_flags))
- || (EF_SH_HAS_DSP (new_flags) && EF_SH_HAS_FP (old_flags)))
- {
- (*_bfd_error_handler)
- ("%s: uses %s instructions while previous modules use %s instructions",
- bfd_archive_filename (ibfd),
- EF_SH_HAS_DSP (new_flags) ? "dsp" : "floating point",
- EF_SH_HAS_DSP (new_flags) ? "floating point" : "dsp");
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
- elf_elfheader (obfd)->e_flags = EF_SH_MERGE_MACH (old_flags, new_flags);
- return sh_elf_set_mach_from_flags (obfd);
+ if ( ! sh_merge_bfd_arch (ibfd, obfd) )
+ return FALSE;
+
+ elf_elfheader (obfd)->e_flags =
+ sh_elf_get_flags_from_mach (bfd_get_mach (obfd));
+
+ return TRUE;
}
#endif /* not sh_elf_merge_private_data */
static bfd_boolean
sh_elf_object_p (bfd *abfd)
{
- struct sh_elf_obj_tdata *new_tdata;
- bfd_size_type amt = sizeof (struct sh_elf_obj_tdata);
-
- if (!sh_elf_set_mach_from_flags (abfd))
- return FALSE;
-
- /* Allocate our special target data. */
- new_tdata = bfd_zalloc (abfd, amt);
- if (new_tdata == NULL)
- return FALSE;
- new_tdata->root = *abfd->tdata.elf_obj_data;
- abfd->tdata.any = new_tdata;
- return TRUE;
+ return sh_elf_set_mach_from_flags (abfd);
}
/* Finish up dynamic symbol handling. We set the contents of various
return TRUE;
}
+
+/* Return address for Ith PLT stub in section PLT, for relocation REL
+ or (bfd_vma) -1 if it should not be included. */
+
+static bfd_vma
+sh_elf_plt_sym_val (bfd_vma i, const asection *plt,
+ const arelent *rel ATTRIBUTE_UNUSED)
+{
+ return plt->vma + (i + 1) * PLT_ENTRY_SIZE;
+}
+
#define TARGET_BIG_SYM bfd_elf32_sh_vec
#define TARGET_BIG_NAME "elf32-sh"
#define TARGET_LITTLE_SYM bfd_elf32_shl_vec
#define elf_backend_finish_dynamic_sections \
sh_elf_finish_dynamic_sections
#define elf_backend_reloc_type_class sh_elf_reloc_type_class
+#define elf_backend_plt_sym_val sh_elf_plt_sym_val
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1