* elf32-arm.h (elf32_arm_final_link_relocate): Don't copy STN_UNDEF
[deliverable/binutils-gdb.git] / bfd / elf32-sh.c
index 11ea3a5d4f42a9dbbf08c7096bbf5272692ebc85..35ebf1ab6e622270274f8550d64f7773e91260c3 100644 (file)
@@ -83,6 +83,8 @@ static asection * sh_elf_gc_mark_hook
 static boolean sh_elf_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           const Elf_Internal_Rela *));
+static enum elf_reloc_type_class sh_elf_reloc_type_class
+  PARAMS ((const Elf_Internal_Rela *));
 
 /* The name of the dynamic interpreter.  This is put in the .interp
    section.  */
@@ -132,8 +134,8 @@ static reloc_howto_type sh_elf_howto_table[] =
         complain_overflow_signed, /* complain_on_overflow */
         sh_elf_ignore_reloc,   /* special_function */
         "R_SH_REL32",          /* name */
-        false,                 /* partial_inplace */
-        0,                     /* src_mask */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
         true),                 /* pcrel_offset */
 
@@ -765,10 +767,10 @@ sh_elf_reloc_loop (r_type, input_bfd, input_section, contents, addr,
        contents = elf_section_data (symbol_section)->this_hdr.contents;
       else
        {
-         free_contents = contents
-           = (bfd_byte *) bfd_malloc (symbol_section->_raw_size);
+         contents = (bfd_byte *) bfd_malloc (symbol_section->_raw_size);
          if (contents == NULL)
            return bfd_reloc_outofrange;
+         free_contents = contents;
          if (! bfd_get_section_contents (input_bfd, symbol_section, contents,
                                          (file_ptr) 0,
                                          symbol_section->_raw_size))
@@ -823,7 +825,7 @@ sh_elf_reloc_loop (r_type, input_bfd, input_section, contents, addr,
     return bfd_reloc_overflow;
 
   x = (insn & ~0xff) | (x & 0xff);
-  bfd_put_16 (input_bfd, x, contents + addr);
+  bfd_put_16 (input_bfd, (bfd_vma) x, contents + addr);
 
   return bfd_reloc_ok;
 }
@@ -878,7 +880,7 @@ sh_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
     case R_SH_DIR32:
       insn = bfd_get_32 (abfd, hit_data);
       insn += sym_value + reloc_entry->addend;
-      bfd_put_32 (abfd, insn, hit_data);
+      bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
       break;
     case R_SH_IND12W:
       insn = bfd_get_16 (abfd, hit_data);
@@ -891,7 +893,7 @@ sh_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
       if (insn & 0x800)
        sym_value -= 0x1000;
       insn = (insn & 0xf000) | (sym_value & 0xfff);
-      bfd_put_16 (abfd, insn, hit_data);
+      bfd_put_16 (abfd, (bfd_vma) insn, hit_data);
       if (sym_value < (bfd_vma) -0x1000 || sym_value >= 0x1000)
        return bfd_reloc_overflow;
       break;
@@ -1094,7 +1096,7 @@ sh_elf_relax_section (abfd, sec, link_info, again)
       if (laddr >= sec->_raw_size)
        {
          (*_bfd_error_handler) (_("%s: 0x%lx: warning: bad R_SH_USES offset"),
-                                bfd_get_filename (abfd),
+                                bfd_archive_filename (abfd),
                                 (unsigned long) irel->r_offset);
          continue;
        }
@@ -1106,24 +1108,24 @@ sh_elf_relax_section (abfd, sec, link_info, again)
        {
          ((*_bfd_error_handler)
           (_("%s: 0x%lx: warning: R_SH_USES points to unrecognized insn 0x%x"),
-           bfd_get_filename (abfd), (unsigned long) irel->r_offset, insn));
+           bfd_archive_filename (abfd), (unsigned long) irel->r_offset, insn));
          continue;
        }
 
       /* Get the address from which the register is being loaded.  The
-        displacement in the mov.l instruction is quadrupled.  It is a
-        displacement from four bytes after the movl instruction, but,
-        before adding in the PC address, two least significant bits
-        of the PC are cleared.  We assume that the section is aligned
-        on a four byte boundary.  */
+        displacement in the mov.l instruction is quadrupled.  It is a
+        displacement from four bytes after the movl instruction, but,
+        before adding in the PC address, two least significant bits
+        of the PC are cleared.  We assume that the section is aligned
+        on a four byte boundary.  */
       paddr = insn & 0xff;
       paddr *= 4;
-      paddr += (laddr + 4) & ~3;
+      paddr += (laddr + 4) &~ (bfd_vma) 3;
       if (paddr >= sec->_raw_size)
        {
          ((*_bfd_error_handler)
           (_("%s: 0x%lx: warning: bad R_SH_USES load offset"),
-           bfd_get_filename (abfd), (unsigned long) irel->r_offset));
+           bfd_archive_filename (abfd), (unsigned long) irel->r_offset));
          continue;
        }
 
@@ -1138,7 +1140,7 @@ sh_elf_relax_section (abfd, sec, link_info, again)
        {
          ((*_bfd_error_handler)
           (_("%s: 0x%lx: warning: could not find expected reloc"),
-           bfd_get_filename (abfd), (unsigned long) paddr));
+           bfd_archive_filename (abfd), (unsigned long) paddr));
          continue;
        }
 
@@ -1149,13 +1151,12 @@ sh_elf_relax_section (abfd, sec, link_info, again)
            extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
          else
            {
-             extsyms = ((Elf32_External_Sym *)
-                        bfd_malloc (symtab_hdr->sh_size));
+             extsyms = (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, 1, symtab_hdr->sh_size, abfd)
+                 || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd)
                      != symtab_hdr->sh_size))
                goto error_return;
            }
@@ -1175,7 +1176,7 @@ sh_elf_relax_section (abfd, sec, link_info, again)
            {
              ((*_bfd_error_handler)
               (_("%s: 0x%lx: warning: symbol in unexpected section"),
-               bfd_get_filename (abfd), (unsigned long) paddr));
+               bfd_archive_filename (abfd), (unsigned long) paddr));
              continue;
            }
 
@@ -1249,7 +1250,7 @@ sh_elf_relax_section (abfd, sec, link_info, again)
              it will be handled here like other internal IND12W
              relocs.  */
          bfd_put_16 (abfd,
-                     0xb000 | ((foff >> 1) & 0xfff),
+                     (bfd_vma) 0xb000 | ((foff >> 1) & 0xfff),
                      contents + irel->r_offset);
        }
       else
@@ -1257,7 +1258,7 @@ sh_elf_relax_section (abfd, sec, link_info, again)
          /* We can't fully resolve this yet, because the external
              symbol value may be changed by future relaxing.  We let
              the final link phase handle it.  */
-         bfd_put_16 (abfd, 0xb000, contents + irel->r_offset);
+         bfd_put_16 (abfd, (bfd_vma) 0xb000, contents + irel->r_offset);
        }
 
       /* See if there is another R_SH_USES reloc referring to the same
@@ -1297,7 +1298,7 @@ sh_elf_relax_section (abfd, sec, link_info, again)
        {
          ((*_bfd_error_handler)
           (_("%s: 0x%lx: warning: could not find expected COUNT reloc"),
-           bfd_get_filename (abfd), (unsigned long) paddr));
+           bfd_archive_filename (abfd), (unsigned long) paddr));
          continue;
        }
 
@@ -1306,7 +1307,7 @@ sh_elf_relax_section (abfd, sec, link_info, again)
       if (irelcount->r_addend == 0)
        {
          ((*_bfd_error_handler) (_("%s: 0x%lx: warning: bad count"),
-                                 bfd_get_filename (abfd),
+                                 bfd_archive_filename (abfd),
                                  (unsigned long) paddr));
          continue;
        }
@@ -1391,7 +1392,7 @@ sh_elf_relax_section (abfd, sec, link_info, again)
       else
        {
          /* Cache the symbols for elf_link_input_bfd.  */
-         symtab_hdr->contents = extsyms;
+         symtab_hdr->contents = (unsigned char *) extsyms;
        }
       free_extsyms = NULL;
     }
@@ -1458,7 +1459,8 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
     }
 
   /* Actually delete the bytes.  */
-  memmove (contents + addr, contents + addr + count, toaddr - addr - count);
+  memmove (contents + addr, contents + addr + count,
+          (size_t) (toaddr - addr - count));
   if (irelalign == NULL)
     sec->_cooked_size -= count;
   else
@@ -1469,7 +1471,7 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
 
       BFD_ASSERT ((count & 1) == 0);
       for (i = 0; i < count; i += 2)
-       bfd_put_16 (abfd, NOP_OPCODE, contents + toaddr - count + i);
+       bfd_put_16 (abfd, (bfd_vma) NOP_OPCODE, contents + toaddr - count + i);
     }
 
   /* Adjust all the relocs.  */
@@ -1647,14 +1649,14 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
              insn += adjust / 2;
              if ((oinsn & 0xff00) != (insn & 0xff00))
                overflow = true;
-             bfd_put_16 (abfd, insn, contents + nraddr);
+             bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
              break;
 
            case R_SH_IND12W:
              insn += adjust / 2;
              if ((oinsn & 0xf000) != (insn & 0xf000))
                overflow = true;
-             bfd_put_16 (abfd, insn, contents + nraddr);
+             bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
              break;
 
            case R_SH_DIR8WPL:
@@ -1668,7 +1670,7 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
                }
              if ((oinsn & 0xff00) != (insn & 0xff00))
                overflow = true;
-             bfd_put_16 (abfd, insn, contents + nraddr);
+             bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
              break;
 
            case R_SH_SWITCH8:
@@ -1682,12 +1684,12 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
              voff += adjust;
              if (voff < - 0x8000 || voff >= 0x8000)
                overflow = true;
-             bfd_put_signed_16 (abfd, voff, contents + nraddr);
+             bfd_put_signed_16 (abfd, (bfd_vma) voff, contents + nraddr);
              break;
 
            case R_SH_SWITCH32:
              voff += adjust;
-             bfd_put_signed_32 (abfd, voff, contents + nraddr);
+             bfd_put_signed_32 (abfd, (bfd_vma) voff, contents + nraddr);
              break;
 
            case R_SH_USES:
@@ -1699,7 +1701,7 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
            {
              ((*_bfd_error_handler)
               (_("%s: 0x%lx: fatal: reloc overflow while relaxing"),
-               bfd_get_filename (abfd), (unsigned long) irel->r_offset));
+               bfd_archive_filename (abfd), (unsigned long) irel->r_offset));
              bfd_set_error (bfd_error_bad_value);
              return false;
            }
@@ -1778,12 +1780,12 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
              if (start > addr
                  && start < toaddr
                  && (stop <= addr || stop >= toaddr))
-               bfd_put_signed_32 (abfd, voff + count,
+               bfd_put_signed_32 (abfd, (bfd_vma) voff + count,
                                   ocontents + irelscan->r_offset);
              else if (stop > addr
                       && stop < toaddr
                       && (start <= addr || start >= toaddr))
-               bfd_put_signed_32 (abfd, voff - count,
+               bfd_put_signed_32 (abfd, (bfd_vma) voff - count,
                                   ocontents + irelscan->r_offset);
            }
 
@@ -1884,7 +1886,7 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
        {
          /* Tail recursion.  */
          return sh_elf_relax_delete_bytes (abfd, sec, alignaddr,
-                                           alignto - alignaddr);
+                                           (int) (alignto - alignaddr));
        }
     }
 
@@ -1905,13 +1907,16 @@ sh_elf_align_loads (abfd, sec, internal_relocs, contents, pswapped)
   Elf_Internal_Rela *irel, *irelend;
   bfd_vma *labels = NULL;
   bfd_vma *label, *label_end;
+  bfd_size_type amt;
 
   *pswapped = false;
 
   irelend = internal_relocs + sec->reloc_count;
 
   /* Get all the addresses with labels on them.  */
-  labels = (bfd_vma *) bfd_malloc (sec->reloc_count * sizeof (bfd_vma));
+  amt = sec->reloc_count;
+  amt *= sizeof (bfd_vma);
+  labels = (bfd_vma *) bfd_malloc (amt);
   if (labels == NULL)
     goto error_return;
   label_end = labels;
@@ -1980,8 +1985,8 @@ sh_elf_swap_insns (abfd, sec, relocs, contents, addr)
   /* Swap the instructions themselves.  */
   i1 = bfd_get_16 (abfd, contents + addr);
   i2 = bfd_get_16 (abfd, contents + addr + 2);
-  bfd_put_16 (abfd, i2, contents + addr);
-  bfd_put_16 (abfd, i1, contents + addr + 2);
+  bfd_put_16 (abfd, (bfd_vma) i2, contents + addr);
+  bfd_put_16 (abfd, (bfd_vma) i1, contents + addr + 2);
 
   /* Adjust all reloc addresses.  */
   irelend = internal_relocs + sec->reloc_count;
@@ -2050,7 +2055,7 @@ sh_elf_swap_insns (abfd, sec, relocs, contents, addr)
              insn += add / 2;
              if ((oinsn & 0xff00) != (insn & 0xff00))
                overflow = true;
-             bfd_put_16 (abfd, insn, loc);
+             bfd_put_16 (abfd, (bfd_vma) insn, loc);
              break;
 
            case R_SH_IND12W:
@@ -2059,7 +2064,7 @@ sh_elf_swap_insns (abfd, sec, relocs, contents, addr)
              insn += add / 2;
              if ((oinsn & 0xf000) != (insn & 0xf000))
                overflow = true;
-             bfd_put_16 (abfd, insn, loc);
+             bfd_put_16 (abfd, (bfd_vma) insn, loc);
              break;
 
            case R_SH_DIR8WPL:
@@ -2076,7 +2081,7 @@ sh_elf_swap_insns (abfd, sec, relocs, contents, addr)
                  insn += add / 2;
                  if ((oinsn & 0xff00) != (insn & 0xff00))
                    overflow = true;
-                 bfd_put_16 (abfd, insn, loc);
+                 bfd_put_16 (abfd, (bfd_vma) insn, loc);
                }
 
              break;
@@ -2086,7 +2091,7 @@ sh_elf_swap_insns (abfd, sec, relocs, contents, addr)
            {
              ((*_bfd_error_handler)
               (_("%s: 0x%lx: fatal: reloc overflow while relaxing"),
-               bfd_get_filename (abfd), (unsigned long) irel->r_offset));
+               bfd_archive_filename (abfd), (unsigned long) irel->r_offset));
              bfd_set_error (bfd_error_bad_value);
              return false;
            }
@@ -2429,9 +2434,9 @@ sh_elf_link_hash_table_create (abfd)
      bfd *abfd;
 {
   struct elf_sh_link_hash_table *ret;
+  bfd_size_type amt = sizeof (struct elf_sh_link_hash_table);
 
-  ret = ((struct elf_sh_link_hash_table *)
-        bfd_alloc (abfd, sizeof (struct elf_sh_link_hash_table)));
+  ret = (struct elf_sh_link_hash_table *) bfd_alloc (abfd, amt);
   if (ret == (struct elf_sh_link_hash_table *) NULL)
     return NULL;
 
@@ -2533,7 +2538,7 @@ sh_elf_create_dynamic_sections (abfd, info)
            || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS))
          continue;
        secname = bfd_get_section_name (abfd, sec);
-       relname = (char *) bfd_malloc (strlen (secname) + 6);
+       relname = (char *) bfd_malloc ((bfd_size_type) strlen (secname) + 6);
        strcpy (relname, ".rela");
        strcat (relname, secname);
        s = bfd_make_section (abfd, relname);
@@ -2761,14 +2766,13 @@ sh_elf_adjust_dynamic_symbol (info, h)
 
 static boolean
 sh_elf_size_dynamic_sections (output_bfd, info)
-     bfd *output_bfd;
+     bfd *output_bfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info;
 {
   bfd *dynobj;
   asection *s;
   boolean plt;
   boolean relocs;
-  boolean reltext;
 
   dynobj = elf_hash_table (info)->dynobj;
   BFD_ASSERT (dynobj != NULL);
@@ -2810,7 +2814,6 @@ sh_elf_size_dynamic_sections (output_bfd, info)
      memory for them.  */
   plt = false;
   relocs = false;
-  reltext = false;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       const char *name;
@@ -2856,29 +2859,10 @@ sh_elf_size_dynamic_sections (output_bfd, info)
            }
          else
            {
-             asection *target;
-
              /* Remember whether there are any reloc sections other
                 than .rela.plt.  */
              if (strcmp (name, ".rela.plt") != 0)
-               {
-                 const char *outname;
-
-                 relocs = true;
-
-                 /* If this relocation section applies to a read only
-                    section, then we probably need a DT_TEXTREL
-                    entry.  The entries in the .rela.plt section
-                    really apply to the .got section, which we
-                    created ourselves and so know is not readonly.  */
-                 outname = bfd_get_section_name (output_bfd,
-                                                 s->output_section);
-                 target = bfd_get_section_by_name (output_bfd, outname + 5);
-                 if (target != NULL
-                     && (target->flags & SEC_READONLY) != 0
-                     && (target->flags & SEC_ALLOC) != 0)
-                   reltext = true;
-               }
+               relocs = true;
 
              /* We use the reloc_count field as a counter if we need
                 to copy relocs into the output file.  */
@@ -2910,36 +2894,39 @@ sh_elf_size_dynamic_sections (output_bfd, info)
         must add the entries now so that we get the correct size for
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
+#define add_dynamic_entry(TAG, VAL) \
+  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
       if (! info->shared)
        {
-         if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
+         if (!add_dynamic_entry (DT_DEBUG, 0))
            return false;
        }
 
       if (plt)
        {
-         if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
-             || ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
-             || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
-             || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
+         if (!add_dynamic_entry (DT_PLTGOT, 0)
+             || !add_dynamic_entry (DT_PLTRELSZ, 0)
+             || !add_dynamic_entry (DT_PLTREL, DT_RELA)
+             || !add_dynamic_entry (DT_JMPREL, 0))
            return false;
        }
 
       if (relocs)
        {
-         if (! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
-             || ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
-             || ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
-                                               sizeof (Elf32_External_Rela)))
+         if (!add_dynamic_entry (DT_RELA, 0)
+             || !add_dynamic_entry (DT_RELASZ, 0)
+             || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
            return false;
        }
 
-      if (reltext)
+      if ((info->flags & DF_TEXTREL) != 0)
        {
-         if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
+         if (!add_dynamic_entry (DT_TEXTREL, 0))
            return false;
        }
     }
+#undef add_dynamic_entry
 
   return true;
 }
@@ -3039,7 +3026,11 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
       howto = sh_elf_howto_table + r_type;
 
-      /* This is a final link.  */
+      /* For relocs that aren't partial_inplace, we get the addend from
+         the relocation.  */
+      if (! howto->partial_inplace)
+       addend = rel->r_addend;
+
       h = NULL;
       sym = NULL;
       sec = NULL;
@@ -3059,7 +3050,32 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                 section symbol winds up in the output section.  */
              sym = local_syms + r_symndx;
              if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-               goto final_link_relocate;
+               {
+                 if (! howto->partial_inplace)
+                   {
+                     /* For relocations with the addend in the
+                        relocation, we need just to update the addend.
+                        All real relocs are of type partial_inplace; this
+                        code is mostly for completeness.  */
+                     rel->r_addend += sec->output_offset + sym->st_value;
+
+                     continue;
+                   }
+
+                 /* Relocs of type partial_inplace need to pick up the
+                    contents in the contents and add the offset resulting
+                    from the changed location of the section symbol.
+                    Using _bfd_final_link_relocate (e.g. goto
+                    final_link_relocate) here would be wrong, because
+                    relocations marked pc_relative would get the current
+                    location subtracted, and we must only do that at the
+                    final link.  */
+                 r = _bfd_relocate_contents (howto, input_bfd,
+                                             sec->output_offset
+                                             + sym->st_value,
+                                             contents + rel->r_offset);
+                 goto relocation_done;
+               }
 
              continue;
            }
@@ -3116,7 +3132,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                {
                  (*_bfd_error_handler)
                    (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"),
-                    bfd_get_filename (input_bfd), h->root.root.string,
+                    bfd_archive_filename (input_bfd), h->root.root.string,
                     bfd_get_section_name (input_bfd, input_section));
                  relocation = 0;
                }
@@ -3127,7 +3143,9 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            }
          else if (h->root.type == bfd_link_hash_undefweak)
            relocation = 0;
-         else if (info->shared && !info->symbolic && !info->no_undefined)
+         else if (info->shared
+              && (!info->symbolic || info->allow_shlib_undefined)
+              && !info->no_undefined)
            relocation = 0;
          else
            {
@@ -3180,7 +3198,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                {
                  ((*_bfd_error_handler)
                   (_("%s: 0x%lx: fatal: unaligned branch target for relax-support relocation"),
-                   bfd_get_filename (input_section->owner),
+                   bfd_archive_filename (input_section->owner),
                    (unsigned long) rel->r_offset));
                  bfd_set_error (bfd_error_bad_value);
                  return false;
@@ -3198,6 +3216,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_SH_DIR32:
        case R_SH_REL32:
          if (info->shared
+             && r_symndx != 0
              && (input_section->flags & SEC_ALLOC) != 0
              && (r_type != R_SH_REL32
                  || (h != NULL
@@ -3264,7 +3283,8 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  BFD_ASSERT (h != NULL && h->dynindx != -1);
                  relocate = false;
                  outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_REL32);
-                 outrel.r_addend = rel->r_addend;
+                 outrel.r_addend
+                   = bfd_get_32 (input_bfd, contents + rel->r_offset);
                }
              else
                {
@@ -3277,14 +3297,18 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                    {
                      relocate = true;
                      outrel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
-                     outrel.r_addend = relocation + rel->r_addend;
+                     outrel.r_addend
+                       = relocation + bfd_get_32 (input_bfd,
+                                                  contents + rel->r_offset);
                    }
                  else
                    {
                      BFD_ASSERT (h->dynindx != -1);
                      relocate = false;
                      outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_DIR32);
-                     outrel.r_addend = relocation + rel->r_addend;
+                     outrel.r_addend
+                       = relocation + bfd_get_32 (input_bfd,
+                                                  contents + rel->r_offset);
                    }
                }
 
@@ -3301,8 +3325,6 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              if (! relocate)
                continue;
            }
-         else if (r_type == R_SH_DIR32)
-           addend = rel->r_addend;
          goto final_link_relocate;
 
        case R_SH_GOT32:
@@ -3482,6 +3504,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          }
        }
 
+    relocation_done:
       if (r != bfd_reloc_ok)
        {
          switch (r)
@@ -3550,7 +3573,7 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
-         input_section->_raw_size);
+         (size_t) input_section->_raw_size);
 
   if ((input_section->flags & SEC_RELOC) != 0
       && input_section->reloc_count > 0)
@@ -3558,20 +3581,19 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       Elf_Internal_Sym *isymp;
       asection **secpp;
       Elf32_External_Sym *esym, *esymend;
+      bfd_size_type size;
 
       if (symtab_hdr->contents != NULL)
        external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
       else
        {
-         external_syms = ((Elf32_External_Sym *)
-                          bfd_malloc (symtab_hdr->sh_info
-                                      * sizeof (Elf32_External_Sym)));
-         if (external_syms == NULL && symtab_hdr->sh_info > 0)
+         size = symtab_hdr->sh_info;
+         size *= sizeof (Elf32_External_Sym);
+         external_syms = (Elf32_External_Sym *) bfd_malloc (size);
+         if (external_syms == NULL && size != 0)
            goto error_return;
          if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-             || (bfd_read (external_syms, sizeof (Elf32_External_Sym),
-                           symtab_hdr->sh_info, input_bfd)
-                 != (symtab_hdr->sh_info * sizeof (Elf32_External_Sym))))
+             || bfd_bread (external_syms, size, input_bfd) != size)
            goto error_return;
        }
 
@@ -3581,14 +3603,15 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       if (internal_relocs == NULL)
        goto error_return;
 
-      internal_syms = ((Elf_Internal_Sym *)
-                      bfd_malloc (symtab_hdr->sh_info
-                                  * sizeof (Elf_Internal_Sym)));
+      size = symtab_hdr->sh_info;
+      size *= sizeof (Elf_Internal_Sym);
+      internal_syms = (Elf_Internal_Sym *) bfd_malloc (size);
       if (internal_syms == NULL && symtab_hdr->sh_info > 0)
        goto error_return;
 
-      sections = (asection **) bfd_malloc (symtab_hdr->sh_info
-                                          * sizeof (asection *));
+      size = symtab_hdr->sh_info;
+      size *= sizeof (asection *);
+      sections = (asection **) bfd_malloc (size);
       if (sections == NULL && symtab_hdr->sh_info > 0)
        goto error_return;
 
@@ -3847,10 +3870,11 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
                 symbol.  */
              if (local_got_offsets == NULL)
                {
-                 size_t size;
+                 bfd_size_type size;
                  register unsigned int i;
 
-                 size = symtab_hdr->sh_info * sizeof (bfd_vma);
+                 size = symtab_hdr->sh_info;
+                 size *= sizeof (bfd_vma);
                  local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
                  if (local_got_offsets == NULL)
                    return false;
@@ -3957,6 +3981,8 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
                          || ! bfd_set_section_alignment (dynobj, sreloc, 2))
                        return false;
                    }
+                 if (sec->flags & SEC_READONLY)
+                   info->flags |= DF_TEXTREL;
                }
 
              sreloc->_raw_size += sizeof (Elf32_External_Rela);
@@ -3984,7 +4010,7 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
                  if (p == NULL)
                    {
                      p = ((struct elf_sh_pcrel_relocs_copied *)
-                          bfd_alloc (dynobj, sizeof *p));
+                          bfd_alloc (dynobj, (bfd_size_type) sizeof *p));
                      if (p == NULL)
                        return false;
                      p->next = eh->pcrel_relocs_copied;
@@ -4099,7 +4125,7 @@ sh_elf_merge_private_data (ibfd, obfd)
     {
       (*_bfd_error_handler)
        ("%s: uses %s instructions while previous modules use %s instructions",
-        bfd_get_filename (ibfd),
+        bfd_archive_filename (ibfd),
         EF_SH_HAS_DSP (new_flags) ? "dsp" : "floating point",
         EF_SH_HAS_DSP (new_flags) ? "floating point" : "dsp");
       bfd_set_error (bfd_error_bad_value);
@@ -4237,7 +4263,7 @@ sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
 
       rel.r_offset = (sgot->output_section->vma
                      + sgot->output_offset
-                     + (h->got.offset &~ 1));
+                     + (h->got.offset &~ (bfd_vma) 1));
 
       /* If this is a -Bsymbolic link, and the symbol is defined
         locally, we just want to emit a RELATIVE reloc.  Likewise if
@@ -4441,6 +4467,23 @@ sh_elf_finish_dynamic_sections (output_bfd, info)
   return true;
 }
 
+static enum elf_reloc_type_class
+sh_elf_reloc_type_class (rela)
+     const Elf_Internal_Rela *rela;
+{
+  switch ((int) ELF32_R_TYPE (rela->r_info))
+    {
+    case R_SH_RELATIVE:
+      return reloc_class_relative;
+    case R_SH_JMP_SLOT:
+      return reloc_class_plt;
+    case R_SH_COPY:
+      return reloc_class_copy;
+    default:
+      return reloc_class_normal;
+    }
+}
+
 #ifndef ELF_ARCH
 #define TARGET_BIG_SYM         bfd_elf32_sh_vec
 #define TARGET_BIG_NAME                "elf32-sh"
@@ -4484,6 +4527,7 @@ sh_elf_finish_dynamic_sections (output_bfd, info)
                                        sh_elf_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
                                        sh_elf_finish_dynamic_sections
+#define elf_backend_reloc_type_class   sh_elf_reloc_type_class
 
 #define elf_backend_want_got_plt       1
 #define elf_backend_plt_readonly       1
This page took 0.034937 seconds and 4 git commands to generate.