/* 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 **);
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);
- if (! _bfd_generic_verify_endian_match (ibfd, obfd))
- return FALSE;
+ return sh_elf_get_flags_from_mach (bfd_mach);
+}
+
+
+/* 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 */
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