Fix elf64-ppc.c electric fence warning
[deliverable/binutils-gdb.git] / bfd / elf.c
index d3a1bb490422258f06e079ce3f7f49f3c460bc4b..13d4272c93620442d15d24fd612af16179a32510 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,6 +1,6 @@
 /* ELF executable support for BFD.
 
-   Copyright (C) 1993-2014 Free Software Foundation, Inc.
+   Copyright (C) 1993-2015 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -297,13 +297,14 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
       /* Allocate and clear an extra byte at the end, to prevent crashes
         in case the string table is not terminated.  */
       if (shstrtabsize + 1 <= 1
-         || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL
-         || bfd_seek (abfd, offset, SEEK_SET) != 0)
+         || bfd_seek (abfd, offset, SEEK_SET) != 0
+         || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL)
        shstrtab = NULL;
       else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize)
        {
          if (bfd_get_error () != bfd_error_system_call)
            bfd_set_error (bfd_error_file_truncated);
+         bfd_release (abfd, shstrtab);
          shstrtab = NULL;
          /* Once we've failed to read it, make sure we don't keep
             trying.  Otherwise, we'll keep allocating space for
@@ -332,9 +333,19 @@ bfd_elf_string_from_elf_section (bfd *abfd,
 
   hdr = elf_elfsections (abfd)[shindex];
 
-  if (hdr->contents == NULL
-      && bfd_elf_get_str_section (abfd, shindex) == NULL)
-    return NULL;
+  if (hdr->contents == NULL)
+    {
+      if (hdr->sh_type != SHT_STRTAB && hdr->sh_type < SHT_LOOS)
+       {
+         /* PR 17512: file: f057ec89.  */
+         _bfd_error_handler (_("%B: attempt to load strings from a non-string section (number %d)"),
+                             abfd, shindex);
+         return NULL;
+       }
+  
+      if (bfd_elf_get_str_section (abfd, shindex) == NULL)
+       return NULL;
+    }
 
   if (strindex >= hdr->sh_size)
     {
@@ -636,6 +647,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                     pointers.  */
                  src = shdr->contents + shdr->sh_size;
                  dest = (Elf_Internal_Group *) (shdr->contents + amt);
+
                  while (1)
                    {
                      unsigned int idx;
@@ -1253,8 +1265,13 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
       swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
 
       extdyn = dynbuf;
+      /* PR 17512: file: 6f427532.  */
+      if (s->size < extdynsize)
+       goto error_return;
       extdynend = extdyn + s->size;
-      for (; extdyn < extdynend; extdyn += extdynsize)
+      /* PR 17512: file: id:000006,sig:06,src:000000,op:flip4,pos:5664.
+         Fix range check.  */
+      for (; extdyn <= (extdynend - extdynsize); extdyn += extdynsize)
        {
          Elf_Internal_Dyn dyn;
          const char *name = "";
@@ -1605,7 +1622,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
   if (++ nesting > 3)
     {
       /* PR17512: A corrupt ELF binary might contain a recursive group of
-        sections, each the string indicies pointing to the next in the
+        sections, with each the string indicies pointing to the next in the
         loop.  Detect this here, by refusing to load a section that we are
         already in the process of loading.  We only trigger this test if
         we have nested at least three sections deep as normal ELF binaries
@@ -1972,7 +1989,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        else
          p_hdr = &esdt->rel.hdr;
 
-       BFD_ASSERT (*p_hdr == NULL);
+       /* PR 17512: file: 0b4f81b7.  */
+       if (*p_hdr != NULL)
+         goto fail;
        amt = sizeof (*hdr2);
        hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
        if (hdr2 == NULL)
@@ -2029,15 +2048,18 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       if (hdr->contents != NULL)
        {
          Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
-         unsigned int n_elt = hdr->sh_size / GRP_ENTRY_SIZE;
+         unsigned int n_elt = hdr->sh_size / sizeof (* idx);
          asection *s;
 
+         if (n_elt == 0)
+           goto fail;
          if (idx->flags & GRP_COMDAT)
            hdr->bfd_section->flags
              |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
 
          /* We try to keep the same section order as it comes in.  */
          idx += n_elt;
+
          while (--n_elt != 0)
            {
              --idx;
@@ -2736,6 +2758,15 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
   this_hdr->sh_offset = 0;
   this_hdr->sh_size = asect->size;
   this_hdr->sh_link = 0;
+  /* PR 17512: file: 0eb809fe, 8b0535ee.  */
+  if (asect->alignment_power >= (sizeof (bfd_vma) * 8) - 1)
+    {
+      (*_bfd_error_handler)
+       (_("%B: error: Alignment power %d of section `%A' is too big"),
+        abfd, asect, asect->alignment_power);
+      arg->failed = TRUE;
+      return;
+    }
   this_hdr->sh_addralign = (bfd_vma) 1 << asect->alignment_power;
   /* The sh_entsize and sh_info fields may have been set already by
      copy_private_section_data.  */
@@ -3989,6 +4020,11 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       last_size = 0;
       phdr_index = 0;
       maxpagesize = bed->maxpagesize;
+      /* PR 17512: file: c8455299.
+        Avoid divide-by-zero errors later on.
+        FIXME: Should we abort if the maxpagesize is zero ?  */
+      if (maxpagesize == 0)
+       maxpagesize = 1;
       writable = FALSE;
       dynsec = bfd_get_section_by_name (abfd, ".dynamic");
       if (dynsec != NULL
@@ -5184,7 +5220,14 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
              && (p->p_type != PT_NOTE
                  || bfd_get_format (abfd) != bfd_core))
            {
-             BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
+             if (m->includes_filehdr || m->includes_phdrs)
+               {
+                 /* PR 17512: file: 2195325e.  */ 
+                 (*_bfd_error_handler)
+                   (_("%B: warning: non-load segment includes file header and/or program header"),
+                    abfd);
+                 return FALSE;
+               }
 
              p->p_filesz = 0;
              p->p_offset = m->sections[0]->filepos;
@@ -5925,8 +5968,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
             something.  They are allowed by the ELF spec however, so only
             a warning is produced.  */
          if (segment->p_type == PT_LOAD)
-           (*_bfd_error_handler) (_("%B: warning: Empty loadable segment"
-                                    " detected, is this intentional ?\n"),
+           (*_bfd_error_handler) (_("\
+%B: warning: Empty loadable segment detected, is this intentional ?"),
                                   ibfd);
 
          map->count = 0;
@@ -6539,7 +6582,15 @@ rewrite:
           i++, segment++)
        if (segment->p_type == PT_LOAD
            && maxpagesize < segment->p_align)
-         maxpagesize = segment->p_align;
+         {
+           /* PR 17512: file: f17299af.  */
+           if (segment->p_align > (bfd_vma) 1 << ((sizeof (bfd_vma) * 8) - 2))
+             (*_bfd_error_handler) (_("\
+%B: warning: segment alignment of 0x%llx is too large"),
+                                    ibfd, (long long) segment->p_align);
+           else
+             maxpagesize = segment->p_align;
+         }
 
       if (maxpagesize != get_elf_backend_data (obfd)->maxpagesize)
        bfd_emul_set_maxpagesize (bfd_get_target (obfd), maxpagesize);
@@ -7305,7 +7356,6 @@ error_return_verref:
          || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
        goto error_return_verref;
 
-      elf_tdata (abfd)->cverrefs = hdr->sh_info;
       elf_tdata (abfd)->verref = (Elf_Internal_Verneed *)
        bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed));
 
@@ -7361,10 +7411,17 @@ error_return_verref:
              if (ivernaux->vna_nodename == NULL)
                goto error_return_bad_verref;
 
+             if (ivernaux->vna_other > freeidx)
+               freeidx = ivernaux->vna_other;
+
+             ivernaux->vna_nextptr = NULL;
+             if (ivernaux->vna_next == 0)
+               {
+                 iverneed->vn_cnt = j + 1;
+                 break;
+               }
              if (j + 1 < iverneed->vn_cnt)
                ivernaux->vna_nextptr = ivernaux + 1;
-             else
-               ivernaux->vna_nextptr = NULL;
 
              if (ivernaux->vna_next
                  > (size_t) (contents_end - (bfd_byte *) evernaux))
@@ -7372,15 +7429,13 @@ error_return_verref:
 
              evernaux = ((Elf_External_Vernaux *)
                          ((bfd_byte *) evernaux + ivernaux->vna_next));
-
-             if (ivernaux->vna_other > freeidx)
-               freeidx = ivernaux->vna_other;
            }
 
+         iverneed->vn_nextref = NULL;
+         if (iverneed->vn_next == 0)
+           break;
          if (i + 1 < hdr->sh_info)
            iverneed->vn_nextref = iverneed + 1;
-         else
-           iverneed->vn_nextref = NULL;
 
          if (iverneed->vn_next
              > (size_t) (contents_end - (bfd_byte *) everneed))
@@ -7389,6 +7444,7 @@ error_return_verref:
          everneed = ((Elf_External_Verneed *)
                      ((bfd_byte *) everneed + iverneed->vn_next));
        }
+      elf_tdata (abfd)->cverrefs = i;
 
       free (contents);
       contents = NULL;
@@ -7447,6 +7503,9 @@ error_return_verref:
          if ((iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION)) > maxidx)
            maxidx = iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION);
 
+         if (iverdefmem.vd_next == 0)
+           break;
+
          if (iverdefmem.vd_next
              > (size_t) (contents_end_def - (bfd_byte *) everdef))
            goto error_return_bad_verdef;
@@ -7516,10 +7575,14 @@ error_return_verref:
              if (iverdaux->vda_nodename == NULL)
                goto error_return_bad_verdef;
 
+             iverdaux->vda_nextptr = NULL;
+             if (iverdaux->vda_next == 0)
+               {
+                 iverdef->vd_cnt = j + 1;
+                 break;
+               }
              if (j + 1 < iverdef->vd_cnt)
                iverdaux->vda_nextptr = iverdaux + 1;
-             else
-               iverdaux->vda_nextptr = NULL;
 
              if (iverdaux->vda_next
                  > (size_t) (contents_end_aux - (bfd_byte *) everdaux))
@@ -7532,10 +7595,11 @@ error_return_verref:
          if (iverdef->vd_cnt)
            iverdef->vd_nodename = iverdef->vd_auxptr->vda_nodename;
 
+         iverdef->vd_nextdef = NULL;
+         if (iverdef->vd_next == 0)
+           break;
          if ((size_t) (iverdef - iverdefarr) + 1 < maxidx)
            iverdef->vd_nextdef = iverdef + 1;
-         else
-           iverdef->vd_nextdef = NULL;
 
          everdef = ((Elf_External_Verdef *)
                     ((bfd_byte *) everdef + iverdef->vd_next));
@@ -7667,109 +7731,6 @@ _bfd_elf_set_arch_mach (bfd *abfd,
   return bfd_default_set_arch_mach (abfd, arch, machine);
 }
 
-/* Find the function to a particular section and offset,
-   for error reporting.  */
-
-static bfd_boolean
-elf_find_function (bfd *abfd,
-                  asymbol **symbols,
-                  asection *section,
-                  bfd_vma offset,
-                  const char **filename_ptr,
-                  const char **functionname_ptr)
-{
-  struct elf_find_function_cache
-  {
-    asection *last_section;
-    asymbol *func;
-    const char *filename;
-    bfd_size_type func_size;
-  } *cache;
-
-  if (symbols == NULL)
-    return FALSE;
-
-  cache = elf_tdata (abfd)->elf_find_function_cache;
-  if (cache == NULL)
-    {
-      cache = bfd_zalloc (abfd, sizeof (*cache));
-      elf_tdata (abfd)->elf_find_function_cache = cache;
-      if (cache == NULL)
-       return FALSE;
-    }
-  if (cache->last_section != section
-      || cache->func == NULL
-      || offset < cache->func->value
-      || offset >= cache->func->value + cache->func_size)
-    {
-      asymbol *file;
-      bfd_vma low_func;
-      asymbol **p;
-      /* ??? Given multiple file symbols, it is impossible to reliably
-        choose the right file name for global symbols.  File symbols are
-        local symbols, and thus all file symbols must sort before any
-        global symbols.  The ELF spec may be interpreted to say that a
-        file symbol must sort before other local symbols, but currently
-        ld -r doesn't do this.  So, for ld -r output, it is possible to
-        make a better choice of file name for local symbols by ignoring
-        file symbols appearing after a given local symbol.  */
-      enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
-      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
-      file = NULL;
-      low_func = 0;
-      state = nothing_seen;
-      cache->filename = NULL;
-      cache->func = NULL;
-      cache->func_size = 0;
-      cache->last_section = section;
-
-      for (p = symbols; *p != NULL; p++)
-       {
-         asymbol *sym = *p;
-         bfd_vma code_off;
-         bfd_size_type size;
-
-         if ((sym->flags & BSF_FILE) != 0)
-           {
-             file = sym;
-             if (state == symbol_seen)
-               state = file_after_symbol_seen;
-             continue;
-           }
-
-         size = bed->maybe_function_sym (sym, section, &code_off);
-         if (size != 0
-             && code_off <= offset
-             && (code_off > low_func
-                 || (code_off == low_func
-                     && size > cache->func_size)))
-           {
-             cache->func = sym;
-             cache->func_size = size;
-             cache->filename = NULL;
-             low_func = code_off;
-             if (file != NULL
-                 && ((sym->flags & BSF_LOCAL) != 0
-                     || state != file_after_symbol_seen))
-               cache->filename = bfd_asymbol_name (file);
-           }
-         if (state == nothing_seen)
-           state = symbol_seen;
-       }
-    }
-
-  if (cache->func == NULL)
-    return FALSE;
-
-  if (filename_ptr)
-    *filename_ptr = cache->filename;
-  if (functionname_ptr)
-    *functionname_ptr = bfd_asymbol_name (cache->func);
-
-  return TRUE;
-}
-
 /* Find the nearest line to a particular section and offset,
    for error reporting.  */
 
@@ -7789,24 +7750,15 @@ _bfd_elf_find_nearest_line (bfd *abfd,
                                     filename_ptr, functionname_ptr,
                                     line_ptr, discriminator_ptr,
                                     dwarf_debug_sections, 0,
-                                    &elf_tdata (abfd)->dwarf2_find_line_info))
+                                    &elf_tdata (abfd)->dwarf2_find_line_info)
+      || _bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
+                                       filename_ptr, functionname_ptr,
+                                       line_ptr))
     {
       if (!*functionname_ptr)
-       elf_find_function (abfd, symbols, section, offset,
-                          *filename_ptr ? NULL : filename_ptr,
-                          functionname_ptr);
-
-      return TRUE;
-    }
-
-  if (_bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
-                                    filename_ptr, functionname_ptr, line_ptr))
-    {
-      if (!*functionname_ptr)
-       elf_find_function (abfd, symbols, section, offset,
-                          *filename_ptr ? NULL : filename_ptr,
-                          functionname_ptr);
-
+       _bfd_elf_find_function (abfd, symbols, section, offset,
+                               *filename_ptr ? NULL : filename_ptr,
+                               functionname_ptr);
       return TRUE;
     }
 
@@ -7821,8 +7773,8 @@ _bfd_elf_find_nearest_line (bfd *abfd,
   if (symbols == NULL)
     return FALSE;
 
-  if (! elf_find_function (abfd, symbols, section, offset,
-                          filename_ptr, functionname_ptr))
+  if (! _bfd_elf_find_function (abfd, symbols, section, offset,
+                               filename_ptr, functionname_ptr))
     return FALSE;
 
   *line_ptr = 0;
@@ -8322,6 +8274,18 @@ elfcore_grok_s390_tdb (bfd *abfd, Elf_Internal_Note *note)
   return elfcore_make_note_pseudosection (abfd, ".reg-s390-tdb", note);
 }
 
+static bfd_boolean
+elfcore_grok_s390_vxrs_low (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-s390-vxrs-low", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_vxrs_high (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-s390-vxrs-high", note);
+}
+
 static bfd_boolean
 elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note)
 {
@@ -8786,6 +8750,20 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
       else
         return TRUE;
 
+    case NT_S390_VXRS_LOW:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_s390_vxrs_low (abfd, note);
+      else
+       return TRUE;
+
+    case NT_S390_VXRS_HIGH:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_s390_vxrs_high (abfd, note);
+      else
+       return TRUE;
+
     case NT_ARM_VFP:
       if (note->namesz == 6
          && strcmp (note->namedata, "LINUX") == 0)
@@ -9651,6 +9629,31 @@ elfcore_write_s390_tdb (bfd *abfd,
                              note_name, NT_S390_TDB, s390_tdb, size);
 }
 
+char *
+elfcore_write_s390_vxrs_low (bfd *abfd,
+                            char *buf,
+                            int *bufsiz,
+                            const void *s390_vxrs_low,
+                            int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_S390_VXRS_LOW, s390_vxrs_low, size);
+}
+
+char *
+elfcore_write_s390_vxrs_high (bfd *abfd,
+                            char *buf,
+                            int *bufsiz,
+                            const void *s390_vxrs_high,
+                            int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_S390_VXRS_HIGH,
+                            s390_vxrs_high, size);
+}
+
 char *
 elfcore_write_arm_vfp (bfd *abfd,
                       char *buf,
@@ -9735,6 +9738,10 @@ elfcore_write_register_note (bfd *abfd,
     return elfcore_write_s390_system_call (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-s390-tdb") == 0)
     return elfcore_write_s390_tdb (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-s390-vxrs-low") == 0)
+    return elfcore_write_s390_vxrs_low (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-s390-vxrs-high") == 0)
+    return elfcore_write_s390_vxrs_high (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-arm-vfp") == 0)
     return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-aarch-tls") == 0)
@@ -9782,32 +9789,38 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
          return TRUE;
 
        case bfd_core:
-         if (CONST_STRNEQ (in.namedata, "NetBSD-CORE"))
-           {
-             if (! elfcore_grok_netbsd_note (abfd, &in))
-               return FALSE;
-           }
-         else if (CONST_STRNEQ (in.namedata, "OpenBSD"))
-           {
-             if (! elfcore_grok_openbsd_note (abfd, &in))
-               return FALSE;
-           }
-         else if (CONST_STRNEQ (in.namedata, "QNX"))
-           {
-             if (! elfcore_grok_nto_note (abfd, &in))
-               return FALSE;
-           }
-         else if (CONST_STRNEQ (in.namedata, "SPU/"))
+         {
+#define GROKER_ELEMENT(S,F) {S, sizeof (S) - 1, F}
+           struct
            {
-             if (! elfcore_grok_spu_note (abfd, &in))
-               return FALSE;
+             const char * string;
+             size_t len;
+             bfd_boolean (* func)(bfd *, Elf_Internal_Note *);
            }
-         else
+           grokers[] =
            {
-             if (! elfcore_grok_note (abfd, &in))
-               return FALSE;
-           }
-         break;
+             GROKER_ELEMENT ("", elfcore_grok_note),
+             GROKER_ELEMENT ("NetBSD-CORE", elfcore_grok_netbsd_note),
+             GROKER_ELEMENT ( "OpenBSD", elfcore_grok_openbsd_note),
+             GROKER_ELEMENT ("QNX", elfcore_grok_nto_note),
+             GROKER_ELEMENT ("SPU/", elfcore_grok_spu_note)
+           };
+#undef GROKER_ELEMENT
+           int i;
+
+           for (i = ARRAY_SIZE (grokers); i--;)
+             {
+               if (in.namesz >= grokers[i].len
+                   && strncmp (in.namedata, grokers[i].string,
+                               grokers[i].len) == 0)
+                 {
+                   if (! grokers[i].func (abfd, & in))
+                     return FALSE;
+                   break;
+                 }
+             }
+           break;
+         }
 
        case bfd_object:
          if (in.namesz == sizeof "GNU" && strcmp (in.namedata, "GNU") == 0)
@@ -9841,10 +9854,14 @@ elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size)
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
     return FALSE;
 
-  buf = (char *) bfd_malloc (size);
+  buf = (char *) bfd_malloc (size + 1);
   if (buf == NULL)
     return FALSE;
 
+  /* PR 17512: file: ec08f814
+     0-termintate the buffer so that string searches will not overflow.  */
+  buf[size] = 0;
+
   if (bfd_bread (buf, size, abfd) != size
       || !elf_parse_notes (abfd, buf, size, offset))
     {
This page took 0.031474 seconds and 4 git commands to generate.