/* BFD back-end for Renesas H8/300 ELF binaries.
Copyright 1993, 1995, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007 Free Software Foundation, Inc.
+ 2007, 2008, 2009, 2010, 2012 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
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
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/h8.h"
return NULL;
}
+static reloc_howto_type *
+elf32_h8_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (h8_elf_howto_table) / sizeof (h8_elf_howto_table[0]);
+ i++)
+ if (h8_elf_howto_table[i].name != NULL
+ && strcasecmp (h8_elf_howto_table[i].name, r_name) == 0)
+ return &h8_elf_howto_table[i];
+
+ return NULL;
+}
+
static void
elf32_h8_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc,
Elf_Internal_Rela *elf_reloc)
unresolved_reloc, warned);
}
- 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;
- }
+ if (sec != NULL && discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, 1, relend, howto, 0, contents);
if (info->relocatable)
continue;
{
bfd_vma symval;
+ {
+ arelent bfd_reloc;
+
+ elf32_h8_info_to_howto (abfd, &bfd_reloc, irel);
+ }
/* Keep track of the previous reloc so that we can delete
some long jumps created by the compiler. */
if (irel != internal_relocs)
/* This is bsr. */
bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 2);
else
- abort ();
+ /* Might be MOVSD. */
+ break;
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
if (value <= 0x7fff || value >= 0xffff8000u)
{
unsigned char code;
+ unsigned char op0, op1, op2, op3;
+ unsigned char *op_ptr;
/* Note that we've changed the relocs, section contents,
etc. */
elf_section_data (sec)->this_hdr.contents = contents;
symtab_hdr->contents = (unsigned char *) isymbuf;
+ if (irel->r_offset >= 4)
+ {
+ /* Check for 4-byte MOVA relaxation. */
+ int second_reloc = 0;
+
+ op_ptr = contents + irel->r_offset - 4;
+
+ if (last_reloc)
+ {
+ arelent bfd_reloc;
+ reloc_howto_type *h;
+ bfd_vma last_reloc_size;
+
+ elf32_h8_info_to_howto (abfd, &bfd_reloc, last_reloc);
+ h = bfd_reloc.howto;
+ last_reloc_size = 1 << h->size;
+ if (last_reloc->r_offset + last_reloc_size
+ == irel->r_offset)
+ {
+ op_ptr -= last_reloc_size;
+ second_reloc = 1;
+ }
+ }
+ if (irel < irelend)
+ {
+ Elf_Internal_Rela *next_reloc = irel + 1;
+ arelent bfd_reloc;
+ reloc_howto_type *h;
+ bfd_vma next_reloc_size;
+
+ elf32_h8_info_to_howto (abfd, &bfd_reloc, next_reloc);
+ h = bfd_reloc.howto;
+ next_reloc_size = 1 << h->size;
+ if (next_reloc->r_offset + next_reloc_size
+ == irel->r_offset)
+ {
+ op_ptr -= next_reloc_size;
+ second_reloc = 1;
+ }
+ }
+
+ op0 = bfd_get_8 (abfd, op_ptr + 0);
+ op1 = bfd_get_8 (abfd, op_ptr + 1);
+ op2 = bfd_get_8 (abfd, op_ptr + 2);
+ op3 = bfd_get_8 (abfd, op_ptr + 3);
+
+ if (op0 == 0x01
+ && (op1 & 0xdf) == 0x5f
+ && (op2 & 0x40) == 0x40
+ && (op3 & 0x80) == 0x80)
+ {
+ if ((op2 & 0x08) == 0)
+ second_reloc = 1;
+
+ if (second_reloc)
+ {
+ op3 &= ~0x08;
+ bfd_put_8 (abfd, op3, op_ptr + 3);
+ }
+ else
+ {
+ op2 &= ~0x08;
+ bfd_put_8 (abfd, op2, op_ptr + 2);
+ }
+ goto r_h8_dir32a16_common;
+ }
+ }
+
+ /* Now check for short version of MOVA. */
+ op_ptr = contents + irel->r_offset - 2;
+ op0 = bfd_get_8 (abfd, op_ptr + 0);
+ op1 = bfd_get_8 (abfd, op_ptr + 1);
+
+ if (op0 == 0x7a
+ && (op1 & 0x88) == 0x80)
+ {
+ op1 |= 0x08;
+ bfd_put_8 (abfd, op1, op_ptr + 1);
+ goto r_h8_dir32a16_common;
+ }
+
/* Get the opcode. */
code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
bfd_put_8 (abfd, code, contents + irel->r_offset - 1);
+ r_h8_dir32a16_common:
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
R_H8_DIR16);
unsigned int sec_shndx;
bfd_byte *contents;
Elf_Internal_Rela *irel, *irelend;
- Elf_Internal_Rela *irelalign;
Elf_Internal_Sym *isym;
Elf_Internal_Sym *isymend;
bfd_vma toaddr;
contents = elf_section_data (sec)->this_hdr.contents;
- /* The deletion must stop at the next ALIGN reloc for an aligment
- power larger than the number of bytes we are deleting. */
-
- irelalign = NULL;
toaddr = sec->size;
irel = elf_section_data (sec)->relocs;
#define ELF_MACHINE_CODE EM_H8_300
#define ELF_MAXPAGESIZE 0x1
#define bfd_elf32_bfd_reloc_type_lookup elf32_h8_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup elf32_h8_reloc_name_lookup
#define elf_info_to_howto elf32_h8_info_to_howto
#define elf_info_to_howto_rel elf32_h8_info_to_howto_rel
#define bfd_elf32_bfd_get_relocated_section_contents \
elf32_h8_get_relocated_section_contents
+#define elf_symbol_leading_char '_'
#include "elf32-target.h"