Fix excessive memory allocation attempts and possible integer overfloaws when attempt...
[deliverable/binutils-gdb.git] / bfd / elf32-microblaze.c
index c1691f857ca308168eaca6fb87b0e4967510d45f..a54044fdb3c45327ddb4792223bb37a689c8f11b 100644 (file)
@@ -1,6 +1,6 @@
 /* Xilinx MicroBlaze-specific support for 32-bit ELF
 
-   Copyright (C) 2009-2016 Free Software Foundation, Inc.
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -730,10 +730,6 @@ struct elf32_mb_link_hash_table
 {
   struct elf_link_hash_table elf;
 
-  /* Short-cuts to get to dynamic linker sections.  */
-  asection *sdynbss;
-  asection *srelbss;
-
   /* Small local sym to section mapping cache.  */
   struct sym_cache sym_sec;
 
@@ -953,8 +949,8 @@ microblaze_elf_relocate_section (bfd *output_bfd,
       if (r_type < 0 || r_type >= (int) R_MICROBLAZE_max)
        {
          /* xgettext:c-format */
-         _bfd_error_handler (_("%s: unknown relocation type %d"),
-                             bfd_get_filename (input_bfd), (int) r_type);
+         _bfd_error_handler (_("%B: unknown relocation type %d"),
+                             input_bfd, (int) r_type);
          bfd_set_error (bfd_error_bad_value);
          ret = FALSE;
          continue;
@@ -1006,6 +1002,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
       else
        {
          bfd_vma relocation;
+         bfd_boolean resolved_to_zero;
 
          /* This is a final link.  */
          sym = NULL;
@@ -1045,6 +1042,9 @@ microblaze_elf_relocate_section (bfd *output_bfd,
              goto check_reloc;
            }
 
+         resolved_to_zero = (h != NULL
+                             && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+
          switch ((int) r_type)
            {
            case (int) R_MICROBLAZE_SRO32 :
@@ -1081,12 +1081,12 @@ microblaze_elf_relocate_section (bfd *output_bfd,
                      {
                        _bfd_error_handler
                          /* xgettext:c-format */
-                         (_("%s: The target (%s) of an %s relocation "
-                            "is in the wrong section (%s)"),
-                          bfd_get_filename (input_bfd),
+                         (_("%B: The target (%s) of an %s relocation"
+                            " is in the wrong section (%A)"),
+                          input_bfd,
                           sym_name,
                           microblaze_elf_howto_table[(int) r_type]->name,
-                          bfd_get_section_name (sec->owner, sec));
+                          sec);
                        /*bfd_set_error (bfd_error_bad_value); ??? why? */
                        ret = FALSE;
                        continue;
@@ -1129,12 +1129,12 @@ microblaze_elf_relocate_section (bfd *output_bfd,
                      {
                        _bfd_error_handler
                          /* xgettext:c-format */
-                         (_("%s: The target (%s) of an %s relocation "
-                            "is in the wrong section (%s)"),
-                          bfd_get_filename (input_bfd),
+                         (_("%B: The target (%s) of an %s relocation"
+                            " is in the wrong section (%A)"),
+                          input_bfd,
                           sym_name,
                           microblaze_elf_howto_table[(int) r_type]->name,
-                          bfd_get_section_name (sec->owner, sec));
+                          sec);
                        /*bfd_set_error (bfd_error_bad_value); ??? why? */
                        ret = FALSE;
                        continue;
@@ -1261,7 +1261,8 @@ microblaze_elf_relocate_section (bfd *output_bfd,
                /* Need to generate relocs ? */
                if ((bfd_link_pic (info) || indx != 0)
                    && (h == NULL
-                   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                   || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                       && !resolved_to_zero)
                    || h->root.type != bfd_link_hash_undefweak))
                  need_relocs = TRUE;
 
@@ -1436,7 +1437,8 @@ microblaze_elf_relocate_section (bfd *output_bfd,
 
                if ((bfd_link_pic (info)
                     && (h == NULL
-                        || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                        || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                            && !resolved_to_zero)
                         || h->root.type != bfd_link_hash_undefweak)
                     && (!howto->pc_relative
                         || (h != NULL
@@ -2222,17 +2224,6 @@ microblaze_elf_gc_mark_hook (asection *sec,
   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 
-/* Update the got entry reference counts for the section being removed.  */
-
-static bfd_boolean
-microblaze_elf_gc_sweep_hook (bfd * abfd ATTRIBUTE_UNUSED,
-                             struct bfd_link_info * info ATTRIBUTE_UNUSED,
-                             asection * sec ATTRIBUTE_UNUSED,
-                             const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
-{
-  return TRUE;
-}
-
 /* PIC support.  */
 
 #define PLT_ENTRY_SIZE 16
@@ -2316,10 +2307,13 @@ microblaze_elf_check_relocs (bfd * abfd,
       else
        {
          h = sym_hashes [r_symndx - symtab_hdr->sh_info];
+         while (h->root.type == bfd_link_hash_indirect
+                || h->root.type == bfd_link_hash_warning)
+           h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
          /* PR15323, ref flags aren't set for references in the same
             object.  */
-         h->root.non_ir_ref = 1;
+         h->root.non_ir_ref_regular = 1;
        }
 
       switch (r_type)
@@ -2377,6 +2371,17 @@ microblaze_elf_check_relocs (bfd * abfd,
            }
           break;
 
+       case R_MICROBLAZE_GOTOFF_64:
+       case R_MICROBLAZE_GOTOFF_32:
+         if (htab->elf.sgot == NULL)
+           {
+             if (htab->elf.dynobj == NULL)
+               htab->elf.dynobj = abfd;
+             if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
+               return FALSE;
+           }
+         break;
+
         case R_MICROBLAZE_64:
         case R_MICROBLAZE_64_PCREL:
         case R_MICROBLAZE_32:
@@ -2503,32 +2508,6 @@ microblaze_elf_check_relocs (bfd * abfd,
   return TRUE;
 }
 
-static bfd_boolean
-microblaze_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
-{
-  struct elf32_mb_link_hash_table *htab;
-
-  htab = elf32_mb_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
-
-  if (!htab->elf.sgot && !_bfd_elf_create_got_section (dynobj, info))
-    return FALSE;
-
-  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
-    return FALSE;
-
-  htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
-  if (!bfd_link_pic (info))
-    htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
-
-  if (!htab->elf.splt || !htab->elf.srelplt || !htab->sdynbss
-      || (!bfd_link_pic (info) && !htab->srelbss))
-    abort ();
-
-  return TRUE;
-}
-
 /* Copy the extra info we tack onto an elf_link_hash_entry.  */
 
 static void
@@ -2587,9 +2566,8 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   struct elf32_mb_link_hash_table *htab;
   struct elf32_mb_link_hash_entry * eh;
   struct elf32_mb_dyn_relocs *p;
-  asection *sdynbss, *s;
+  asection *s, *srel;
   unsigned int power_of_two;
-  bfd *dynobj;
 
   htab = elf32_mb_hash_table (info);
   if (htab == NULL)
@@ -2688,11 +2666,19 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
      to copy the initial value out of the dynamic object and into the
      runtime process image.  */
-  dynobj = elf_hash_table (info)->dynobj;
-  BFD_ASSERT (dynobj != NULL);
+  if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+    {
+      s = htab->elf.sdynrelro;
+      srel = htab->elf.sreldynrelro;
+    }
+  else
+    {
+      s = htab->elf.sdynbss;
+      srel = htab->elf.srelbss;
+    }
   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
     {
-      htab->srelbss->size += sizeof (Elf32_External_Rela);
+      srel->size += sizeof (Elf32_External_Rela);
       h->needs_copy = 1;
     }
 
@@ -2702,21 +2688,20 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   if (power_of_two > 3)
     power_of_two = 3;
 
-  sdynbss = htab->sdynbss;
   /* Apply the required alignment.  */
-  sdynbss->size = BFD_ALIGN (sdynbss->size, (bfd_size_type) (1 << power_of_two));
-  if (power_of_two > bfd_get_section_alignment (dynobj, sdynbss))
+  s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
+  if (power_of_two > s->alignment_power)
     {
-      if (! bfd_set_section_alignment (dynobj, sdynbss, power_of_two))
+      if (!bfd_set_section_alignment (s->owner, s, power_of_two))
        return FALSE;
     }
 
   /* Define the symbol as being at this point in the section.  */
-  h->root.u.def.section = sdynbss;
-  h->root.u.def.value = sdynbss->size;
+  h->root.u.def.section = s;
+  h->root.u.def.value = s->size;
 
   /* Increment the section size to make room for the symbol.  */
-  sdynbss->size += h->size;
+  s->size += h->size;
   return TRUE;
 }
 
@@ -2874,6 +2859,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
                pp = &p->next;
            }
        }
+      else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+       eh->dyn_relocs = NULL;
     }
   else
     {
@@ -3080,7 +3067,9 @@ microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         }
       else if (s != htab->elf.splt
               && s != htab->elf.sgot
-              && s != htab->elf.sgotplt)
+              && s != htab->elf.sgotplt
+              && s != htab->elf.sdynbss
+              && s != htab->elf.sdynrelro)
         {
           /* It's not one of our sections, so don't allocate space.  */
           continue;
@@ -3255,13 +3244,20 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
              || h->dynindx == -1))
         {
           asection *sec = h->root.u.def.section;
+         bfd_vma value;
+
+         value = h->root.u.def.value;
+         if (sec->output_section != NULL)
+           /* PR 21180: If the output section is NULL, then the symbol is no
+              longer needed, and in theory the GOT entry is redundant.  But
+              it is too late to change our minds now...  */
+           value += sec->output_section->vma + sec->output_offset;
+
           microblaze_elf_output_dynamic_relocation (output_bfd,
                                                     srela, srela->reloc_count++,
                                                     /* symindex= */ 0,
                                                     R_MICROBLAZE_REL, offset,
-                                                    h->root.u.def.value
-                                                    + sec->output_section->vma
-                                                    + sec->output_offset);
+                                                    value);
         }
       else
         {
@@ -3286,14 +3282,15 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
 
       BFD_ASSERT (h->dynindx != -1);
 
-      s = bfd_get_linker_section (htab->elf.dynobj, ".rela.bss");
-      BFD_ASSERT (s != NULL);
-
       rela.r_offset = (h->root.u.def.value
                        + h->root.u.def.section->output_section->vma
                        + h->root.u.def.section->output_offset);
       rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
       rela.r_addend = 0;
+      if (h->root.u.def.section == htab->elf.sdynrelro)
+       s = htab->elf.sreldynrelro;
+      else
+       s = htab->elf.srelbss;
       loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
       bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
     }
@@ -3460,7 +3457,6 @@ microblaze_elf_add_symbol_hook (bfd *abfd,
 #define bfd_elf32_bfd_reloc_name_lookup                microblaze_elf_reloc_name_lookup
 
 #define elf_backend_gc_mark_hook               microblaze_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook              microblaze_elf_gc_sweep_hook
 #define elf_backend_check_relocs                microblaze_elf_check_relocs
 #define elf_backend_copy_indirect_symbol        microblaze_elf_copy_indirect_symbol
 #define bfd_elf32_bfd_link_hash_table_create    microblaze_elf_link_hash_table_create
@@ -3469,11 +3465,12 @@ microblaze_elf_add_symbol_hook (bfd *abfd,
 #define elf_backend_want_got_plt               1
 #define elf_backend_plt_readonly               1
 #define elf_backend_got_header_size            12
+#define elf_backend_want_dynrelro              1
 #define elf_backend_rela_normal                1
 #define elf_backend_dtrel_excludes_plt         1
 
 #define elf_backend_adjust_dynamic_symbol       microblaze_elf_adjust_dynamic_symbol
-#define elf_backend_create_dynamic_sections     microblaze_elf_create_dynamic_sections
+#define elf_backend_create_dynamic_sections     _bfd_elf_create_dynamic_sections
 #define elf_backend_finish_dynamic_sections     microblaze_elf_finish_dynamic_sections
 #define elf_backend_finish_dynamic_symbol       microblaze_elf_finish_dynamic_symbol
 #define elf_backend_size_dynamic_sections       microblaze_elf_size_dynamic_sections
This page took 0.027808 seconds and 4 git commands to generate.