Handle R_X86_64_64 properly for x32
[deliverable/binutils-gdb.git] / bfd / elf32-h8300.c
index 0990e04c815f247021b5f67a4d5f8e095ea344c2..758dc75c1a191eae7dceb0fedacbf31ce9057456 100644 (file)
@@ -1,12 +1,12 @@
 /* BFD back-end for Renesas H8/300 ELF binaries.
    Copyright 1993, 1995, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006,
 /* 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
 
    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,
    (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
 
    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 "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/h8.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/h8.h"
@@ -251,6 +252,22 @@ elf32_h8_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return NULL;
 }
 
   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)
 static void
 elf32_h8_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc,
                        Elf_Internal_Rela *elf_reloc)
@@ -443,16 +460,9 @@ elf32_h8_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                                   unresolved_reloc, warned);
        }
 
                                   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;
 
       if (info->relocatable)
        continue;
@@ -705,6 +715,11 @@ elf32_h8_relax_section (bfd *abfd, asection *sec,
     {
       bfd_vma symval;
 
     {
       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)
       /* Keep track of the previous reloc so that we can delete
         some long jumps created by the compiler.  */
       if (irel != internal_relocs)
@@ -977,7 +992,8 @@ elf32_h8_relax_section (bfd *abfd, asection *sec,
                  /* This is bsr.  */
                  bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 2);
                else
                  /* 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),
 
                /* Fix the relocation's type.  */
                irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
@@ -1190,6 +1206,8 @@ elf32_h8_relax_section (bfd *abfd, asection *sec,
            if (value <= 0x7fff || value >= 0xffff8000u)
              {
                unsigned char code;
            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.  */
 
                /* Note that we've changed the relocs, section contents,
                   etc.  */
@@ -1197,6 +1215,87 @@ elf32_h8_relax_section (bfd *abfd, asection *sec,
                elf_section_data (sec)->this_hdr.contents = contents;
                symtab_hdr->contents = (unsigned char *) isymbuf;
 
                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);
 
                /* Get the opcode.  */
                code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
 
@@ -1207,6 +1306,7 @@ elf32_h8_relax_section (bfd *abfd, asection *sec,
 
                bfd_put_8 (abfd, code, 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);
                /* Fix the relocation's type.  */
                irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                             R_H8_DIR16);
@@ -1277,7 +1377,6 @@ elf32_h8_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count)
   unsigned int sec_shndx;
   bfd_byte *contents;
   Elf_Internal_Rela *irel, *irelend;
   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;
   Elf_Internal_Sym *isym;
   Elf_Internal_Sym *isymend;
   bfd_vma toaddr;
@@ -1289,10 +1388,6 @@ elf32_h8_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count)
 
   contents = elf_section_data (sec)->this_hdr.contents;
 
 
   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;
   toaddr = sec->size;
 
   irel = elf_section_data (sec)->relocs;
@@ -1502,6 +1597,7 @@ elf32_h8_get_relocated_section_contents (bfd *output_bfd,
 #define ELF_MACHINE_CODE               EM_H8_300
 #define ELF_MAXPAGESIZE                        0x1
 #define bfd_elf32_bfd_reloc_type_lookup elf32_h8_reloc_type_lookup
 #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 elf_info_to_howto              elf32_h8_info_to_howto
 #define elf_info_to_howto_rel          elf32_h8_info_to_howto_rel
 
@@ -1531,5 +1627,6 @@ elf32_h8_get_relocated_section_contents (bfd *output_bfd,
 #define bfd_elf32_bfd_get_relocated_section_contents \
                                 elf32_h8_get_relocated_section_contents
 
 #define bfd_elf32_bfd_get_relocated_section_contents \
                                 elf32_h8_get_relocated_section_contents
 
+#define elf_symbol_leading_char '_'
 
 #include "elf32-target.h"
 
 #include "elf32-target.h"
This page took 0.028993 seconds and 4 git commands to generate.