* ChangeLog: Fix typos.
[deliverable/binutils-gdb.git] / bfd / elf32-d10v.c
index 5b6ed270890c519cfd335a288a65bef2e67b706d..f9454ffe9f32e8ea32928a792fe5028d8f20e276 100644 (file)
@@ -1,5 +1,6 @@
 /* D10V-specific support for 32-bit ELF
-   Copyright 1996, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003
+   Free Software Foundation, Inc.
    Contributed by Martin Hunt (hunt@cygnus.com).
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -27,23 +28,27 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
 static void d10v_info_to_howto_rel
-  PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
+  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
 static asection * elf32_d10v_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
-static boolean elf32_d10v_gc_sweep_hook
+static bfd_boolean elf32_d10v_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           const Elf_Internal_Rela *));
-static boolean elf32_d10v_check_relocs
+static bfd_boolean elf32_d10v_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           const Elf_Internal_Rela *));
-static boolean elf32_d10v_relocate_section
+static bfd_vma extract_rel_addend
+  PARAMS ((bfd *, bfd_byte *, reloc_howto_type *));
+static void insert_rel_addend
+  PARAMS ((bfd *, bfd_byte *, reloc_howto_type *, bfd_vma));
+static bfd_boolean elf32_d10v_relocate_section
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
           bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *,
           asection **));
 
 /* Use REL instead of RELA to save space.  */
-#define USE_REL
+#define USE_REL        1
 
 static reloc_howto_type elf_d10v_howto_table[] =
   {
@@ -52,137 +57,137 @@ static reloc_howto_type elf_d10v_howto_table[] =
           0,                   /* rightshift */
           2,                   /* size (0 = byte, 1 = short, 2 = long) */
           32,                  /* bitsize */
-          false,                       /* pc_relative */
+          FALSE,               /* pc_relative */
           0,                   /* bitpos */
-          complain_overflow_bitfield, /* complain_on_overflow */
-          bfd_elf_generic_reloc,       /* special_function */
-          "R_D10V_NONE",               /* name */
-          false,                       /* partial_inplace */
+          complain_overflow_dont, /* complain_on_overflow */
+          bfd_elf_generic_reloc, /* special_function */
+          "R_D10V_NONE",       /* name */
+          FALSE,               /* partial_inplace */
           0,                   /* src_mask */
           0,                   /* dst_mask */
-          false),              /* pcrel_offset */
+          FALSE),              /* pcrel_offset */
 
     /* An PC Relative 10-bit relocation, shifted by 2  */
     /* right container */
     HOWTO (R_D10V_10_PCREL_R,  /* type */
           2,                   /* rightshift */
           2,                   /* size (0 = byte, 1 = short, 2 = long) */
-          10,                  /* bitsize */
-          true,                        /* pc_relative */
+          7,                   /* bitsize */
+          TRUE,                /* pc_relative */
           0,                   /* bitpos */
           complain_overflow_bitfield, /* complain_on_overflow */
           bfd_elf_generic_reloc, /* special_function */
           "R_D10V_10_PCREL_R", /* name */
-          false,                       /* partial_inplace */
-          0xff,                        /* src_mask */
+          FALSE,               /* partial_inplace */
+          0xff,                /* src_mask */
           0xff,                /* dst_mask */
-          true),                       /* pcrel_offset */
+          TRUE),               /* pcrel_offset */
 
     /* An PC Relative 10-bit relocation, shifted by 2  */
     /* left container */
     HOWTO (R_D10V_10_PCREL_L,  /* type */
           2,                   /* rightshift */
           2,                   /* size (0 = byte, 1 = short, 2 = long) */
-          10,                  /* bitsize */
-          true,                        /* pc_relative */
+          7,                   /* bitsize */
+          TRUE,                /* pc_relative */
           15,                  /* bitpos */
           complain_overflow_bitfield, /* complain_on_overflow */
           bfd_elf_generic_reloc, /* special_function */
           "R_D10V_10_PCREL_L", /* name */
-          false,                       /* partial_inplace */
-          0x07f8000,                   /* src_mask */
-          0x07f8000,                   /* dst_mask */
-          true),                       /* pcrel_offset */
+          FALSE,               /* partial_inplace */
+          0x07f8000,           /* src_mask */
+          0x07f8000,           /* dst_mask */
+          TRUE),               /* pcrel_offset */
 
     /* A 16 bit absolute relocation */
     HOWTO (R_D10V_16,          /* type */
           0,                   /* rightshift */
           1,                   /* size (0 = byte, 1 = short, 2 = long) */
           16,                  /* bitsize */
-          false,                       /* pc_relative */
+          FALSE,               /* pc_relative */
           0,                   /* bitpos */
           complain_overflow_dont, /* complain_on_overflow */
-          bfd_elf_generic_reloc,       /* special_function */
+          bfd_elf_generic_reloc, /* special_function */
           "R_D10V_16",         /* name */
-          false,                       /* partial_inplace */
+          FALSE,               /* partial_inplace */
           0xffff,              /* src_mask */
           0xffff,              /* dst_mask */
-          false),              /* pcrel_offset */
+          FALSE),              /* pcrel_offset */
 
     /* An 18 bit absolute relocation, right shifted 2 */
     HOWTO (R_D10V_18,          /* type */
           2,                   /* rightshift */
           1,                   /* size (0 = byte, 1 = short, 2 = long) */
-          18,                  /* bitsize */
-          false,                       /* pc_relative */
+          16,                  /* bitsize */
+          FALSE,               /* pc_relative */
           0,                   /* bitpos */
           complain_overflow_dont, /* complain_on_overflow */
-          bfd_elf_generic_reloc,       /* special_function */
+          bfd_elf_generic_reloc, /* special_function */
           "R_D10V_18",         /* name */
-          false,                       /* partial_inplace */
+          FALSE,               /* partial_inplace */
           0xffff,              /* src_mask */
           0xffff,              /* dst_mask */
-          false),              /* pcrel_offset */
+          FALSE),              /* pcrel_offset */
 
     /* A relative 18 bit relocation, right shifted by 2  */
     HOWTO (R_D10V_18_PCREL,    /* type */
           2,                   /* rightshift */
           2,                   /* size (0 = byte, 1 = short, 2 = long) */
-          18,                  /* bitsize */
-          true,                        /* pc_relative */
+          15,                  /* bitsize */
+          TRUE,                /* pc_relative */
           0,                   /* bitpos */
-          complain_overflow_signed, /* complain_on_overflow */
-          bfd_elf_generic_reloc,       /* special_function */
+          complain_overflow_bitfield, /* complain_on_overflow */
+          bfd_elf_generic_reloc, /* special_function */
           "R_D10V_18_PCREL",   /* name */
-          false,                       /* partial_inplace */
+          FALSE,               /* partial_inplace */
           0xffff,              /* src_mask */
           0xffff,              /* dst_mask */
-          true),                       /* pcrel_offset */
+          TRUE),                       /* pcrel_offset */
 
     /* A 32 bit absolute relocation */
     HOWTO (R_D10V_32,          /* type */
           0,                   /* rightshift */
           2,                   /* size (0 = byte, 1 = short, 2 = long) */
           32,                  /* bitsize */
-          false,                       /* pc_relative */
+          FALSE,               /* pc_relative */
           0,                   /* bitpos */
-          complain_overflow_bitfield, /* complain_on_overflow */
-          bfd_elf_generic_reloc,       /* special_function */
+          complain_overflow_dont, /* complain_on_overflow */
+          bfd_elf_generic_reloc, /* special_function */
           "R_D10V_32",         /* name */
-          false,                       /* partial_inplace */
+          FALSE,               /* partial_inplace */
           0xffffffff,          /* src_mask */
           0xffffffff,          /* dst_mask */
-          false),              /* pcrel_offset */
+          FALSE),              /* pcrel_offset */
 
     /* GNU extension to record C++ vtable hierarchy */
     HOWTO (R_D10V_GNU_VTINHERIT, /* type */
           0,                     /* rightshift */
           2,                     /* size (0 = byte, 1 = short, 2 = long) */
           0,                     /* bitsize */
-          false,                 /* pc_relative */
+          FALSE,                 /* pc_relative */
           0,                     /* bitpos */
           complain_overflow_dont, /* complain_on_overflow */
           NULL,                  /* special_function */
           "R_D10V_GNU_VTINHERIT", /* name */
-          false,                 /* partial_inplace */
+          FALSE,                 /* partial_inplace */
           0,                     /* src_mask */
           0,                     /* dst_mask */
-          false),                /* pcrel_offset */
+          FALSE),                /* pcrel_offset */
 
     /* GNU extension to record C++ vtable member usage */
     HOWTO (R_D10V_GNU_VTENTRY,     /* type */
           0,                     /* rightshift */
           2,                     /* size (0 = byte, 1 = short, 2 = long) */
           0,                     /* bitsize */
-          false,                 /* pc_relative */
+          FALSE,                 /* pc_relative */
           0,                     /* bitpos */
           complain_overflow_dont, /* complain_on_overflow */
           _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
           "R_D10V_GNU_VTENTRY",   /* name */
-          false,                 /* partial_inplace */
+          FALSE,                 /* partial_inplace */
           0,                     /* src_mask */
           0,                     /* dst_mask */
-          false),                /* pcrel_offset */
+          FALSE),                /* pcrel_offset */
   };
 
 /* Map BFD reloc types to D10V ELF reloc types.  */
@@ -230,7 +235,7 @@ static void
 d10v_info_to_howto_rel (abfd, cache_ptr, dst)
      bfd *abfd ATTRIBUTE_UNUSED;
      arelent *cache_ptr;
-     Elf32_Internal_Rel *dst;
+     Elf_Internal_Rela *dst;
 {
   unsigned int r_type;
 
@@ -240,12 +245,12 @@ d10v_info_to_howto_rel (abfd, cache_ptr, dst)
 }
 
 static asection *
-elf32_d10v_gc_mark_hook (abfd, info, rel, h, sym)
-       bfd *abfd;
-       struct bfd_link_info *info ATTRIBUTE_UNUSED;
-       Elf_Internal_Rela *rel;
-       struct elf_link_hash_entry *h;
-       Elf_Internal_Sym *sym;
+elf32_d10v_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     Elf_Internal_Rela *rel;
+     struct elf_link_hash_entry *h;
+     Elf_Internal_Sym *sym;
 {
   if (h != NULL)
     {
@@ -271,19 +276,12 @@ elf32_d10v_gc_mark_hook (abfd, info, rel, h, sym)
        }
      }
    else
-     {
-       if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-                && sym->st_shndx != SHN_COMMON))
-          {
-            return bfd_section_from_elf_index (abfd, sym->st_shndx);
-          }
-      }
+     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+
   return NULL;
 }
 
-static boolean
+static bfd_boolean
 elf32_d10v_gc_sweep_hook (abfd, info, sec, relocs)
      bfd *abfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
@@ -291,14 +289,14 @@ elf32_d10v_gc_sweep_hook (abfd, info, sec, relocs)
      const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
 {
   /* we don't use got and plt entries for d10v */
-  return true;
+  return TRUE;
 }
 
 /* Look through the relocs for a section during the first phase.
    Since we don't do .gots or .plts, we just need to consider the
    virtual table relocs for gc.  */
 
-static boolean
+static bfd_boolean
 elf32_d10v_check_relocs (abfd, info, sec, relocs)
      bfd *abfd;
      struct bfd_link_info *info;
@@ -310,8 +308,8 @@ elf32_d10v_check_relocs (abfd, info, sec, relocs)
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
 
-  if (info->relocateable)
-    return true;
+  if (info->relocatable)
+    return TRUE;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
@@ -337,26 +335,95 @@ elf32_d10v_check_relocs (abfd, info, sec, relocs)
            Reconstruct it for later use during GC.  */
         case R_D10V_GNU_VTINHERIT:
           if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
-            return false;
+            return FALSE;
           break;
 
         /* This relocation describes which C++ vtable entries are actually
            used.  Record for later use during GC.  */
         case R_D10V_GNU_VTENTRY:
           if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
-            return false;
+            return FALSE;
           break;
         }
     }
 
-  return true;
+  return TRUE;
+}
+
+static bfd_vma
+extract_rel_addend (abfd, where, howto)
+     bfd *abfd;
+     bfd_byte *where;
+     reloc_howto_type *howto;
+{
+  bfd_vma insn, val;
+
+  switch (howto->size)
+    {
+    case 0:
+      insn = bfd_get_8 (abfd, where);
+      break;
+    case 1:
+      insn = bfd_get_16 (abfd, where);
+      break;
+    case 2:
+      insn = bfd_get_32 (abfd, where);
+      break;
+    default:
+      abort ();
+    }
+
+  val = (insn & howto->dst_mask) >> howto->bitpos << howto->rightshift;
+  /* We should really be testing for signed addends here, but we don't
+     have that info directly in the howto.  */
+  if (howto->pc_relative)
+    {
+      bfd_vma sign;
+      sign = howto->dst_mask & (~howto->dst_mask >> 1 | ~(-(bfd_vma) 1 >> 1));
+      sign = sign >> howto->bitpos << howto->rightshift;
+      val = (val ^ sign) - sign;
+    }
+  return val;
+}
+
+static void
+insert_rel_addend (abfd, where, howto, addend)
+     bfd *abfd;
+     bfd_byte *where;
+     reloc_howto_type *howto;
+     bfd_vma addend;
+{
+  bfd_vma insn;
+
+  addend = (addend >> howto->rightshift << howto->bitpos) & howto->dst_mask;
+  insn = ~howto->dst_mask;
+  switch (howto->size)
+    {
+    case 0:
+      insn &= bfd_get_8 (abfd, where);
+      insn |= addend;
+      bfd_put_8 (abfd, insn, where);
+      break;
+    case 1:
+      insn &= bfd_get_16 (abfd, where);
+      insn |= addend;
+      bfd_put_16 (abfd, insn, where);
+      break;
+    case 2:
+      insn &= bfd_get_32 (abfd, where);
+      insn |= addend;
+      bfd_put_32 (abfd, insn, where);
+      break;
+    default:
+      abort ();
+    }
 }
 
 /* Relocate a D10V ELF section.  */
-static boolean
+static bfd_boolean
 elf32_d10v_relocate_section (output_bfd, info, input_bfd, input_section,
                            contents, relocs, local_syms, local_sections)
-     bfd *output_bfd ATTRIBUTE_UNUSED;
+     bfd *output_bfd;
      struct bfd_link_info *info;
      bfd *input_bfd;
      asection *input_section;
@@ -395,22 +462,30 @@ elf32_d10v_relocate_section (output_bfd, info, input_bfd, input_section,
 
       howto = elf_d10v_howto_table + r_type;
 
-      if (info->relocateable)
+      if (info->relocatable)
        {
-         /* This is a relocateable link.  We don't have to change
+         bfd_vma val;
+         bfd_byte *where;
+
+         /* This is a relocatable link.  We don't have to change
             anything, unless the reloc is against a section symbol,
             in which case we have to adjust according to where the
             section symbol winds up in the output section.  */
-         if (r_symndx < symtab_hdr->sh_info)
-           {
-             sym = local_syms + r_symndx;
-             if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-               {
-                 sec = local_sections[r_symndx];
-                 rel->r_addend += sec->output_offset + sym->st_value;
-               }
-           }
+         if (r_symndx >= symtab_hdr->sh_info)
+           continue;
+
+         sym = local_syms + r_symndx;
+         if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
+           continue;
+
+         sec = local_sections[r_symndx];
+         val = sec->output_offset;
+         if (val == 0)
+           continue;
 
+         where = contents + rel->r_offset;
+         val += extract_rel_addend (input_bfd, where, howto);
+         insert_rel_addend (input_bfd, where, howto, val);
          continue;
        }
 
@@ -425,6 +500,20 @@ elf32_d10v_relocate_section (output_bfd, info, input_bfd, input_section,
          relocation = (sec->output_section->vma
                        + sec->output_offset
                        + sym->st_value);
+         if ((sec->flags & SEC_MERGE)
+             && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+           {
+             asection *msec;
+             bfd_vma addend;
+             bfd_byte *where = contents + rel->r_offset;
+
+             addend = extract_rel_addend (input_bfd, where, howto);
+             msec = sec;
+             addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
+             addend -= relocation;
+             addend += msec->output_section->vma + msec->output_offset;
+             insert_rel_addend (input_bfd, where, howto, addend);
+           }
        }
       else
        {
@@ -446,8 +535,8 @@ elf32_d10v_relocate_section (output_bfd, info, input_bfd, input_section,
            {
              if (!((*info->callbacks->undefined_symbol)
                    (info, h->root.root.string, input_bfd,
-                    input_section, rel->r_offset, true)))
-               return false;
+                    input_section, rel->r_offset, TRUE)))
+               return FALSE;
              relocation = 0;
            }
        }
@@ -464,7 +553,7 @@ elf32_d10v_relocate_section (output_bfd, info, input_bfd, input_section,
 
       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
                                     contents, rel->r_offset,
-                                    relocation, rel->r_addend);
+                                    relocation, (bfd_vma) 0);
 
       if (r != bfd_reloc_ok)
        {
@@ -476,43 +565,43 @@ elf32_d10v_relocate_section (output_bfd, info, input_bfd, input_section,
              if (!((*info->callbacks->reloc_overflow)
                    (info, name, howto->name, (bfd_vma) 0,
                     input_bfd, input_section, rel->r_offset)))
-               return false;
+               return FALSE;
              break;
 
            case bfd_reloc_undefined:
              if (!((*info->callbacks->undefined_symbol)
                    (info, name, input_bfd, input_section,
-                    rel->r_offset, true)))
-               return false;
+                    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:
              if (!((*info->callbacks->warning)
                    (info, msg, name, input_bfd, input_section,
                     rel->r_offset)))
-               return false;
+               return FALSE;
              break;
            }
        }
     }
 
-  return true;
+  return TRUE;
 }
 #define ELF_ARCH               bfd_arch_d10v
 #define ELF_MACHINE_CODE       EM_D10V
This page took 0.032613 seconds and 4 git commands to generate.