Line 1... |
Line 1... |
/* Matsushita 10300 specific support for 32-bit ELF
|
/* Matsushita 10300 specific support for 32-bit ELF
|
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
2006, 2007 Free Software Foundation, Inc.
|
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
|
|
This file is part of BFD, the Binary File Descriptor library.
|
This file is part of BFD, the Binary File Descriptor library.
|
|
|
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
Line 915... |
Line 915... |
/* When creating a shared object, we must copy these
|
/* When creating a shared object, we must copy these
|
reloc types into the output file. We create a reloc
|
reloc types into the output file. We create a reloc
|
section in dynobj and make room for this reloc. */
|
section in dynobj and make room for this reloc. */
|
if (sreloc == NULL)
|
if (sreloc == NULL)
|
{
|
{
|
const char * name;
|
sreloc = _bfd_elf_make_dynamic_reloc_section
|
|
(sec, dynobj, 2, abfd, /*rela?*/ TRUE);
|
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);
|
|
if (sreloc == NULL)
|
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);
|
sreloc->size += sizeof (Elf32_External_Rela);
|
}
|
}
|
}
|
}
|
|
|
Line 1106... |
Line 1084... |
/* When generating a shared object, these relocations are
|
/* When generating a shared object, these relocations are
|
copied into the output file to be resolved at run
|
copied into the output file to be resolved at run
|
time. */
|
time. */
|
if (sreloc == NULL)
|
if (sreloc == NULL)
|
{
|
{
|
const char * name;
|
sreloc = _bfd_elf_get_dynamic_reloc_section
|
|
(input_bfd, input_section, /*rela?*/ TRUE);
|
name = (bfd_elf_string_from_elf_section
|
if (sreloc == NULL)
|
(input_bfd,
|
|
elf_elfheader (input_bfd)->e_shstrndx,
|
|
elf_section_data (input_section)->rel_hdr.sh_name));
|
|
if (name == NULL)
|
|
return FALSE;
|
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;
|
skip = FALSE;
|
|
|
outrel.r_offset = _bfd_elf_section_offset (input_bfd, info,
|
outrel.r_offset = _bfd_elf_section_offset (input_bfd, info,
|
Line 1210... |
Line 1176... |
value -= (input_section->output_section->vma
|
value -= (input_section->output_section->vma
|
+ input_section->output_offset);
|
+ input_section->output_offset);
|
value -= offset;
|
value -= offset;
|
value += addend;
|
value += addend;
|
|
|
if ((long) value > 0xff || (long) value < -0x100)
|
if ((long) value > 0x7f || (long) value < -0x80)
|
return bfd_reloc_overflow;
|
return bfd_reloc_overflow;
|
|
|
bfd_put_8 (input_bfd, value, hit_data);
|
bfd_put_8 (input_bfd, value, hit_data);
|
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
|
|
Line 1222... |
Line 1188... |
value -= (input_section->output_section->vma
|
value -= (input_section->output_section->vma
|
+ input_section->output_offset);
|
+ input_section->output_offset);
|
value -= offset;
|
value -= offset;
|
value += addend;
|
value += addend;
|
|
|
if ((long) value > 0xffff || (long) value < -0x10000)
|
if ((long) value > 0x7fff || (long) value < -0x8000)
|
return bfd_reloc_overflow;
|
return bfd_reloc_overflow;
|
|
|
bfd_put_16 (input_bfd, value, hit_data);
|
bfd_put_16 (input_bfd, value, hit_data);
|
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
|
|
Line 1262... |
Line 1228... |
value -= (input_section->output_section->vma
|
value -= (input_section->output_section->vma
|
+ input_section->output_offset);
|
+ input_section->output_offset);
|
value -= offset;
|
value -= offset;
|
value += addend;
|
value += addend;
|
|
|
if ((long) value > 0xffff || (long) value < -0x10000)
|
if ((long) value > 0x7fff || (long) value < -0x8000)
|
return bfd_reloc_overflow;
|
return bfd_reloc_overflow;
|
|
|
bfd_put_16 (input_bfd, value, hit_data);
|
bfd_put_16 (input_bfd, value, hit_data);
|
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
|
|
Line 1294... |
Line 1260... |
case R_MN10300_GOTOFF16:
|
case R_MN10300_GOTOFF16:
|
value -= bfd_get_section_by_name (dynobj,
|
value -= bfd_get_section_by_name (dynobj,
|
".got")->output_section->vma;
|
".got")->output_section->vma;
|
value += addend;
|
value += addend;
|
|
|
if ((long) value > 0xffff || (long) value < -0x10000)
|
if ((long) value > 0x7fff || (long) value < -0x8000)
|
return bfd_reloc_overflow;
|
return bfd_reloc_overflow;
|
|
|
bfd_put_16 (input_bfd, value, hit_data);
|
bfd_put_16 (input_bfd, value, hit_data);
|
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
|
|
Line 1343... |
Line 1309... |
value -= (input_section->output_section->vma
|
value -= (input_section->output_section->vma
|
+ input_section->output_offset);
|
+ input_section->output_offset);
|
value -= offset;
|
value -= offset;
|
value += addend;
|
value += addend;
|
|
|
if ((long) value > 0xffff || (long) value < -0x10000)
|
if ((long) value > 0x7fff || (long) value < -0x8000)
|
return bfd_reloc_overflow;
|
return bfd_reloc_overflow;
|
|
|
bfd_put_16 (input_bfd, value, hit_data);
|
bfd_put_16 (input_bfd, value, hit_data);
|
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
|
|
Line 1431... |
Line 1397... |
bfd_put_8 (input_bfd, (value >> 16) & 0xff, hit_data + 2);
|
bfd_put_8 (input_bfd, (value >> 16) & 0xff, hit_data + 2);
|
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
}
|
}
|
else if (r_type == R_MN10300_GOT16)
|
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;
|
return bfd_reloc_overflow;
|
|
|
bfd_put_16 (input_bfd, value, hit_data);
|
bfd_put_16 (input_bfd, value, hit_data);
|
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
}
|
}
|
Line 2105... |
Line 2071... |
Elf_Internal_Sym *isymbuf = NULL;
|
Elf_Internal_Sym *isymbuf = NULL;
|
struct elf32_mn10300_link_hash_table *hash_table;
|
struct elf32_mn10300_link_hash_table *hash_table;
|
asection *section = sec;
|
asection *section = sec;
|
bfd_vma align_gap_adjustment;
|
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. */
|
/* Assume nothing changes. */
|
*again = FALSE;
|
*again = FALSE;
|
|
|
/* We need a pointer to the mn10300 specific hash table. */
|
/* We need a pointer to the mn10300 specific hash table. */
|
hash_table = elf32_mn10300_hash_table (link_info);
|
hash_table = elf32_mn10300_hash_table (link_info);
|
Line 2749... |
Line 2719... |
/* Walk through them looking for relaxing opportunities. */
|
/* Walk through them looking for relaxing opportunities. */
|
irelend = internal_relocs + sec->reloc_count;
|
irelend = internal_relocs + sec->reloc_count;
|
for (irel = internal_relocs; irel < irelend; irel++)
|
for (irel = internal_relocs; irel < irelend; irel++)
|
{
|
{
|
bfd_vma symval;
|
bfd_vma symval;
|
|
bfd_signed_vma jump_offset;
|
|
asection *sym_sec = NULL;
|
struct elf32_mn10300_link_hash_entry *h = NULL;
|
struct elf32_mn10300_link_hash_entry *h = NULL;
|
|
|
/* If this isn't something that can be relaxed, then ignore
|
/* If this isn't something that can be relaxed, then ignore
|
this reloc. */
|
this reloc. */
|
if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_NONE
|
if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_NONE
|
Line 2788... |
Line 2760... |
|
|
/* Get the value of the symbol referred to by the reloc. */
|
/* Get the value of the symbol referred to by the reloc. */
|
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
|
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
|
{
|
{
|
Elf_Internal_Sym *isym;
|
Elf_Internal_Sym *isym;
|
asection *sym_sec = NULL;
|
|
const char *sym_name;
|
const char *sym_name;
|
char *new_name;
|
char *new_name;
|
|
|
/* A local symbol. */
|
/* A local symbol. */
|
isym = isymbuf + ELF32_R_SYM (irel->r_info);
|
isym = isymbuf + ELF32_R_SYM (irel->r_info);
|
Line 2808... |
Line 2779... |
sym_name = bfd_elf_string_from_elf_section (abfd,
|
sym_name = bfd_elf_string_from_elf_section (abfd,
|
symtab_hdr->sh_link,
|
symtab_hdr->sh_link,
|
isym->st_name);
|
isym->st_name);
|
|
|
if ((sym_sec->flags & SEC_MERGE)
|
if ((sym_sec->flags & SEC_MERGE)
|
&& ELF_ST_TYPE (isym->st_info) == STT_SECTION
|
|
&& sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
|
&& sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
|
{
|
{
|
symval = isym->st_value + irel->r_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,
|
symval = _bfd_merged_section_offset (abfd, & sym_sec,
|
elf_section_data (sym_sec)->sec_info,
|
elf_section_data (sym_sec)->sec_info,
|
symval);
|
symval);
|
symval += sym_sec->output_section->vma + sym_sec->output_offset - irel->r_addend;
|
|
|
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
|
else
|
symval = (isym->st_value
|
symval = (isym->st_value
|
+ sym_sec->output_section->vma
|
+ sym_sec->output_section->vma
|
+ sym_sec->output_offset);
|
+ sym_sec->output_offset);
|
Line 2855... |
Line 2844... |
|
|
/* Check for a reference to a discarded symbol and ignore it. */
|
/* Check for a reference to a discarded symbol and ignore it. */
|
if (h->root.root.u.def.section->output_section == NULL)
|
if (h->root.root.u.def.section->output_section == NULL)
|
continue;
|
continue;
|
|
|
|
sym_sec = h->root.root.u.def.section->output_section;
|
|
|
symval = (h->root.root.u.def.value
|
symval = (h->root.root.u.def.value
|
+ h->root.root.u.def.section->output_section->vma
|
+ h->root.root.u.def.section->output_section->vma
|
+ h->root.root.u.def.section->output_offset);
|
+ h->root.root.u.def.section->output_offset);
|
}
|
}
|
|
|
Line 2957... |
Line 2948... |
value -= irel->r_offset;
|
value -= irel->r_offset;
|
value += irel->r_addend;
|
value += irel->r_addend;
|
|
|
/* See if the value will fit in 16 bits, note the high value is
|
/* 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
|
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
|
/* Account for jumps across alignment boundaries using
|
align_gap_adjustment. */
|
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))
|
&& ((bfd_signed_vma) value > -0x8000 + (bfd_signed_vma) align_gap_adjustment))
|
{
|
{
|
unsigned char code;
|
unsigned char code;
|
|
|
/* Get the opcode. */
|
/* Get the opcode. */
|