/* Matsushita 10200 specific support for 32-bit ELF
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
struct mn10200_reloc_map
{
- unsigned char bfd_reloc_val;
+ bfd_reloc_code_real_type bfd_reloc_val;
unsigned char elf_reloc_val;
};
static reloc_howto_type *
bfd_elf32_bfd_reloc_type_lookup (abfd, code)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
bfd_reloc_code_real_type code;
{
unsigned int i;
static void
mn10200_info_to_howto (abfd, cache_ptr, dst)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
arelent *cache_ptr;
Elf32_Internal_Rela *dst;
{
addend, info, sym_sec, is_local)
reloc_howto_type *howto;
bfd *input_bfd;
- bfd *output_bfd;
+ bfd *output_bfd ATTRIBUTE_UNUSED;
asection *input_section;
bfd_byte *contents;
bfd_vma offset;
bfd_vma value;
bfd_vma addend;
- struct bfd_link_info *info;
- asection *sym_sec;
- int is_local;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
+ asection *sym_sec ATTRIBUTE_UNUSED;
+ int is_local ATTRIBUTE_UNUSED;
{
unsigned long r_type = howto->type;
bfd_byte *hit_data = contents + offset;
case R_MN10200_8:
value += addend;
- if ((long)value > 0x7fff || (long)value < -0x8000)
+ if ((long)value > 0x7f || (long)value < -0x80)
return bfd_reloc_overflow;
bfd_put_8 (input_bfd, value, hit_data);
case R_MN10200_PCREL8:
value -= (input_section->output_section->vma
+ input_section->output_offset);
- value -= offset;
+ value -= (offset + 1);
value += addend;
if ((long)value > 0xff || (long)value < -0x100)
case R_MN10200_PCREL16:
value -= (input_section->output_section->vma
+ input_section->output_offset);
- value -= offset;
+ value -= (offset + 2);
value += addend;
if ((long)value > 0xffff || (long)value < -0x10000)
case R_MN10200_PCREL24:
value -= (input_section->output_section->vma
+ input_section->output_offset);
- value -= offset;
+ value -= (offset + 3);
value += addend;
if ((long)value > 0xffffff || (long)value < -0x1000000)
{
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd,
- input_section, rel->r_offset)))
+ input_section, rel->r_offset, true)))
return false;
relocation = 0;
}
case bfd_reloc_undefined:
if (! ((*info->callbacks->undefined_symbol)
(info, name, input_bfd, input_section,
- rel->r_offset)))
+ rel->r_offset, true)))
return false;
break;
case bfd_reloc_outofrange:
- msg = "internal error: out of range error";
+ msg = _("internal error: out of range error");
goto common_error;
case bfd_reloc_notsupported:
- msg = "internal error: unsupported relocation error";
+ msg = _("internal error: unsupported relocation error");
goto common_error;
case bfd_reloc_dangerous:
- msg = "internal error: dangerous error";
+ msg = _("internal error: dangerous error");
goto common_error;
default:
- msg = "internal error: unknown error";
+ msg = _("internal error: unknown error");
/* fall through */
common_error:
abs24, imm24, d24 all look the same at the reloc level. It
might make the code simpler if we had different relocs for
the various relaxable operand types.
-
+
We don't handle imm16->imm8 or d16->d8 as they're very rare
and somewhat more difficult to support. */
-static boolean
+static boolean
mn10200_elf_relax_section (abfd, sec, link_info, again)
bfd *abfd;
asection *sec;
}
}
- /* Read the local symbols if we haven't done so already. */
+ /* Read this BFD's symbols if we haven't done so already. */
if (extsyms == NULL)
{
/* Get cached copy if it exists. */
{
/* Go get them off disk. */
extsyms = ((Elf32_External_Sym *)
- bfd_malloc (symtab_hdr->sh_info
- * sizeof (Elf32_External_Sym)));
+ bfd_malloc (symtab_hdr->sh_size));
if (extsyms == NULL)
goto error_return;
free_extsyms = extsyms;
if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_read (extsyms, sizeof (Elf32_External_Sym),
- symtab_hdr->sh_info, abfd)
- != (symtab_hdr->sh_info * sizeof (Elf32_External_Sym))))
+ || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd)
+ != symtab_hdr->sh_size))
goto error_return;
}
}
that would be more work, but would require less memory when
the linker is run. */
-
/* Try to turn a 24bit pc-relative branch/call into a 16bit pc-relative
branch/call. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10200_PCREL24)
/* Deal with pc-relative gunk. */
value -= (sec->output_section->vma + sec->output_offset);
- value -= irel->r_offset;
+ value -= (irel->r_offset + 3);
value += irel->r_addend;
/* See if the value will fit in 16 bits, note the high value is
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
R_MN10200_PCREL16);
- /* The opcode got shorter too, so we have to fix the
- addend and offset too! */
- irel->r_addend -= 1;
+ /* The opcode got shorter too, so we have to fix the offset. */
irel->r_offset -= 1;
/* Delete two bytes of data. */
/* Deal with pc-relative gunk. */
value -= (sec->output_section->vma + sec->output_offset);
- value -= irel->r_offset;
+ value -= (irel->r_offset + 2);
value += irel->r_addend;
/* See if the value will fit in 8 bits, note the high value is
bra lab2
lab1: lab1:
-
This happens when the bCC can't reach lab2 at assembly time,
but due to other relaxations it can reach at link time. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10200_PCREL8)
/* Deal with pc-relative gunk. */
value -= (sec->output_section->vma + sec->output_offset);
- value -= irel->r_offset;
+ value -= (irel->r_offset + 1);
value += irel->r_addend;
/* Do nothing if this reloc is the last byte in the section. */
continue;
/* Now make sure we are a conditional branch. This may not
- be necessary, but why take the chance.
+ be necessary, but why take the chance.
Note these checks assume that R_MN10200_PCREL8 relocs
only occur on bCC and bCCx insns. If they occured
break;
}
bfd_put_8 (abfd, code, contents + irel->r_offset - 1);
-
+
/* Set the reloc type and symbol for the first branch
from the second branch. */
irel->r_info = nrel->r_info;
{
bfd_vma value = symval;
- /* See if the value will fit in 16 bits.
+ /* See if the value will fit in 16 bits.
We allow any 16bit match here. We prune those we can't
handle below. */
if ((long)value < 0x7fff && (long)value > -0x8000)
R_MN10200_16);
/* The opcode got shorter too, so we have to fix the
- addend and offset too! */
+ offset. */
irel->r_offset -= 1;
/* Delete two bytes of data. */
*again = true;
break;
- /* mov imm24,an -> mov imm16,an
+ /* mov imm24,an -> mov imm16,an
cmp imm24,an -> cmp imm16,an
mov (abs24),dn -> mov (abs16),dn
mov dn,(abs24) -> mov dn,(abs16)
R_MN10200_16);
/* The opcode got shorter too, so we have to fix the
- addend and offset too! */
+ offset. */
irel->r_offset -= 1;
/* Delete two bytes of data. */
add imm24,dn -> add imm16,dn
add imm24,an -> add imm16,an
sub imm24,dn -> sub imm16,dn
- sub imm24,an -> sub imm16,an
+ sub imm24,an -> sub imm16,an
And all d24->d16 in memory ops. */
case 0x78:
case 0xd0:
{
Elf_Internal_Shdr *symtab_hdr;
Elf32_External_Sym *extsyms;
- int shndx;
+ int shndx, index;
bfd_byte *contents;
Elf_Internal_Rela *irel, *irelend;
Elf_Internal_Rela *irelalign;
bfd_vma toaddr;
Elf32_External_Sym *esym, *esymend;
- struct elf_link_hash_entry **sym_hash, **sym_hash_end;
+ struct elf_link_hash_entry *sym_hash;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
irel->r_offset -= count;
}
- /* Adjust all the symbols. */
+ /* Adjust the local symbols defined in this section. */
esym = extsyms;
esymend = esym + symtab_hdr->sh_info;
for (; esym < esymend; esym++)
}
}
- sym_hash = elf_sym_hashes (abfd);
- sym_hash_end = (sym_hash
- + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
- - symtab_hdr->sh_info));
- for (; sym_hash < sym_hash_end; sym_hash++)
+ /* Now adjust the global symbols defined in this section. */
+ esym = extsyms + symtab_hdr->sh_info;
+ esymend = extsyms + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym));
+ for (index = 0; esym < esymend; esym++, index++)
{
- if (((*sym_hash)->root.type == bfd_link_hash_defined
- || (*sym_hash)->root.type == bfd_link_hash_defweak)
- && (*sym_hash)->root.u.def.section == sec
- && (*sym_hash)->root.u.def.value > addr
- && (*sym_hash)->root.u.def.value < toaddr)
+ Elf_Internal_Sym isym;
+
+ bfd_elf32_swap_symbol_in (abfd, esym, &isym);
+ sym_hash = elf_sym_hashes (abfd)[index];
+ if (isym.st_shndx == shndx
+ && ((sym_hash)->root.type == bfd_link_hash_defined
+ || (sym_hash)->root.type == bfd_link_hash_defweak)
+ && (sym_hash)->root.u.def.section == sec
+ && (sym_hash)->root.u.def.value > addr
+ && (sym_hash)->root.u.def.value < toaddr)
{
- (*sym_hash)->root.u.def.value -= count;
+ (sym_hash)->root.u.def.value -= count;
}
}
return NULL;
}
-
#define TARGET_LITTLE_SYM bfd_elf32_mn10200_vec
#define TARGET_LITTLE_NAME "elf32-mn10200"
#define ELF_ARCH bfd_arch_mn10200