/* Matsushita 10300 specific support for 32-bit ELF
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007 Free Software Foundation, Inc.
+ 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
/* Get the MN10300 ELF linker hash table from a link_info structure. */
#define elf32_mn10300_hash_table(p) \
- ((struct elf32_mn10300_link_hash_table *) ((p)->hash))
+ (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
+ == MN10300_ELF_DATA ? ((struct elf32_mn10300_link_hash_table *) ((p)->hash)) : NULL)
#define elf32_mn10300_link_hash_traverse(table, func, info) \
(elf_link_hash_traverse \
section in dynobj and make room for this reloc. */
if (sreloc == NULL)
{
- const char * name;
-
- name = (bfd_elf_string_from_elf_section
- (abfd,
- elf_elfheader (abfd)->e_shstrndx,
- elf_section_data (sec)->rel_hdr.sh_name));
- if (name == NULL)
- goto fail;
-
- BFD_ASSERT (CONST_STRNEQ (name, ".rela")
- && streq (bfd_get_section_name (abfd, sec), name + 5));
-
- sreloc = bfd_get_section_by_name (dynobj, name);
+ sreloc = _bfd_elf_make_dynamic_reloc_section
+ (sec, dynobj, 2, abfd, /*rela?*/ TRUE);
if (sreloc == NULL)
- {
- flagword flags;
-
- flags = (SEC_HAS_CONTENTS | SEC_READONLY
- | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- if ((sec->flags & SEC_ALLOC) != 0)
- flags |= SEC_ALLOC | SEC_LOAD;
- sreloc = bfd_make_section_with_flags (dynobj, name, flags);
- if (sreloc == NULL
- || ! bfd_set_section_alignment (dynobj, sreloc, 2))
- goto fail;
- }
+ goto fail;
}
sreloc->size += sizeof (Elf32_External_Rela);
unsigned long r_type = howto->type;
bfd_byte * hit_data = contents + offset;
bfd * dynobj;
- bfd_vma * local_got_offsets;
asection * sgot;
asection * splt;
asection * sreloc;
dynobj = elf_hash_table (info)->dynobj;
- local_got_offsets = elf_local_got_offsets (input_bfd);
-
sgot = NULL;
splt = NULL;
sreloc = NULL;
time. */
if (sreloc == NULL)
{
- const char * name;
-
- name = (bfd_elf_string_from_elf_section
- (input_bfd,
- elf_elfheader (input_bfd)->e_shstrndx,
- elf_section_data (input_section)->rel_hdr.sh_name));
- if (name == NULL)
+ sreloc = _bfd_elf_get_dynamic_reloc_section
+ (input_bfd, input_section, /*rela?*/ TRUE);
+ if (sreloc == NULL)
return FALSE;
-
- BFD_ASSERT (CONST_STRNEQ (name, ".rela")
- && streq (bfd_get_section_name (input_bfd,
- input_section),
- name + 5));
-
- sreloc = bfd_get_section_by_name (dynobj, name);
- BFD_ASSERT (sreloc != NULL);
}
skip = FALSE;
value -= offset;
value += addend;
- if ((long) value > 0xff || (long) value < -0x100)
+ if ((long) value > 0x7f || (long) value < -0x80)
return bfd_reloc_overflow;
bfd_put_8 (input_bfd, value, hit_data);
value -= offset;
value += addend;
- if ((long) value > 0xffff || (long) value < -0x10000)
+ if ((long) value > 0x7fff || (long) value < -0x8000)
return bfd_reloc_overflow;
bfd_put_16 (input_bfd, value, hit_data);
value -= offset;
value += addend;
- if ((long) value > 0xffff || (long) value < -0x10000)
+ if ((long) value > 0x7fff || (long) value < -0x8000)
return bfd_reloc_overflow;
bfd_put_16 (input_bfd, value, hit_data);
".got")->output_section->vma;
value += addend;
- if ((long) value > 0xffff || (long) value < -0x10000)
+ if ((long) value > 0x7fff || (long) value < -0x8000)
return bfd_reloc_overflow;
bfd_put_16 (input_bfd, value, hit_data);
&& ELF_ST_VISIBILITY (h->other) != STV_HIDDEN
&& h->plt.offset != (bfd_vma) -1)
{
- asection * splt;
-
splt = bfd_get_section_by_name (dynobj, ".plt");
value = (splt->output_section->vma
&& ELF_ST_VISIBILITY (h->other) != STV_HIDDEN
&& h->plt.offset != (bfd_vma) -1)
{
- asection * splt;
-
splt = bfd_get_section_by_name (dynobj, ".plt");
value = (splt->output_section->vma
value -= offset;
value += addend;
- if ((long) value > 0xffff || (long) value < -0x10000)
+ if ((long) value > 0x7fff || (long) value < -0x8000)
return bfd_reloc_overflow;
bfd_put_16 (input_bfd, value, hit_data);
case R_MN10300_GOT24:
case R_MN10300_GOT16:
{
- asection * sgot;
-
sgot = bfd_get_section_by_name (dynobj, ".got");
if (h != NULL)
}
else if (r_type == R_MN10300_GOT16)
{
- if ((long) value > 0xffff || (long) value < -0x10000)
+ if ((long) value > 0x7fff || (long) value < -0x8000)
return bfd_reloc_overflow;
bfd_put_16 (input_bfd, value, hit_data);
/* _32 relocs in executables force _COPY relocs,
such that the address of the symbol ends up
being local. */
- && !info->executable
+ && !info->executable
&& !SYMBOL_REFERENCES_LOCAL (info, hh)
&& ((input_section->flags & SEC_ALLOC) != 0
/* DWARF will emit R_MN10300_32 relocations
}
if (sec != NULL && elf_discarded_section (sec))
- {
- /* For relocs against symbols from removed linkonce sections,
- or sections discarded by a linker script, we just want the
- section contents zeroed. Avoid any special processing. */
- _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
- rel->r_info = 0;
- rel->r_addend = 0;
- continue;
- }
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, relend, howto, contents);
if (info->relocatable)
continue;
asection *section = sec;
bfd_vma align_gap_adjustment;
+ if (link_info->relocatable)
+ (*link_info->callbacks->einfo)
+ (_("%P%F: --relax and -r may not be used together\n"));
+
/* Assume nothing changes. */
*again = FALSE;
/* We need a pointer to the mn10300 specific hash table. */
hash_table = elf32_mn10300_hash_table (link_info);
+ if (hash_table == NULL)
+ return FALSE;
/* Initialize fields in each hash table entry the first time through. */
if ((hash_table->flags & MN10300_HASH_ENTRIES_INITIALIZED) == 0)
section = section->next)
{
struct elf32_mn10300_link_hash_entry *hash;
- Elf_Internal_Sym *sym;
asection *sym_sec = NULL;
const char *sym_name;
char *new_name;
/* We need the name and hash table entry of the target
symbol! */
hash = NULL;
- sym = NULL;
sym_sec = NULL;
if (r_index < symtab_hdr->sh_info)
for (irel = internal_relocs; irel < irelend; irel++)
{
bfd_vma symval;
+ bfd_signed_vma jump_offset;
+ asection *sym_sec = NULL;
struct elf32_mn10300_link_hash_entry *h = NULL;
/* If this isn't something that can be relaxed, then ignore
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
{
Elf_Internal_Sym *isym;
- asection *sym_sec = NULL;
const char *sym_name;
char *new_name;
isym->st_name);
if ((sym_sec->flags & SEC_MERGE)
- && ELF_ST_TYPE (isym->st_info) == STT_SECTION
&& sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
{
- bfd_vma saved_addend;
-
- saved_addend = irel->r_addend;
- symval = _bfd_elf_rela_local_sym (abfd, isym, & sym_sec, irel);
- symval += irel->r_addend;
- irel->r_addend = saved_addend;
+ symval = isym->st_value;
+
+ /* GAS may reduce relocations against symbols in SEC_MERGE
+ sections to a relocation against the section symbol when
+ the original addend was zero. When the reloc is against
+ a section symbol we should include the addend in the
+ offset passed to _bfd_merged_section_offset, since the
+ location of interest is the original symbol. On the
+ other hand, an access to "sym+addend" where "sym" is not
+ a section symbol should not include the addend; Such an
+ access is presumed to be an offset from "sym"; The
+ location of interest is just "sym". */
+ if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+ symval += irel->r_addend;
+
+ symval = _bfd_merged_section_offset (abfd, & sym_sec,
+ elf_section_data (sym_sec)->sec_info,
+ symval);
+
+ if (ELF_ST_TYPE (isym->st_info) != STT_SECTION)
+ symval += irel->r_addend;
+
+ symval += sym_sec->output_section->vma
+ + sym_sec->output_offset - irel->r_addend;
}
else
symval = (isym->st_value
if (h->root.root.u.def.section->output_section == NULL)
continue;
+ sym_sec = h->root.root.u.def.section->output_section;
+
symval = (h->root.root.u.def.value
+ h->root.root.u.def.section->output_section->vma
+ h->root.root.u.def.section->output_offset);
/* See if the value will fit in 16 bits, note the high value is
0x7fff + 2 as the target will be two bytes closer if we are
- able to relax. */
+ able to relax, if it's in the same section. */
+ if (sec->output_section == sym_sec->output_section)
+ jump_offset = 0x8001;
+ else
+ jump_offset = 0x7fff;
+
/* Account for jumps across alignment boundaries using
align_gap_adjustment. */
- if ((bfd_signed_vma) value < 0x8001 - (bfd_signed_vma) align_gap_adjustment
+ if ((bfd_signed_vma) value < jump_offset - (bfd_signed_vma) align_gap_adjustment
&& ((bfd_signed_vma) value > -0x8000 + (bfd_signed_vma) align_gap_adjustment))
{
unsigned char code;
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
elf32_mn10300_link_hash_newfunc,
- sizeof (struct elf32_mn10300_link_hash_entry)))
+ sizeof (struct elf32_mn10300_link_hash_entry),
+ MN10300_ELF_DATA))
{
free (ret);
return NULL;
if (!_bfd_elf_link_hash_table_init (&ret->static_hash_table->root, abfd,
elf32_mn10300_link_hash_newfunc,
- sizeof (struct elf32_mn10300_link_hash_entry)))
+ sizeof (struct elf32_mn10300_link_hash_entry),
+ MN10300_ELF_DATA))
{
free (ret->static_hash_table);
free (ret);
#define TARGET_LITTLE_SYM bfd_elf32_mn10300_vec
#define TARGET_LITTLE_NAME "elf32-mn10300"
#define ELF_ARCH bfd_arch_mn10300
+#define ELF_TARGET_ID MN10300_ELF_DATA
#define ELF_MACHINE_CODE EM_MN10300
#define ELF_MACHINE_ALT1 EM_CYGNUS_MN10300
#define ELF_MAXPAGESIZE 0x1000