More fixes for memory access violations exposed by fuzzed binaries.
authorNick Clifton <nickc@redhat.com>
Mon, 1 Dec 2014 16:43:46 +0000 (16:43 +0000)
committerNick Clifton <nickc@redhat.com>
Mon, 1 Dec 2014 16:43:46 +0000 (16:43 +0000)
PR binutils/17512
* dwarf.h (struct dwarf_section): Add user_data field.
* dwarf.c (frame_need_space): Check for an over large register
number.
(display_debug_frames): Check the return value from
frame_need_space.  Check for a CFA expression that is so long the
start address wraps around.
(debug_displays): Initialise the user_data field.
* objdump.c (load_specific_debug_section): Save the BFD section
pointer in the user_data field of the dwarf_section structure.
(free_debug_section): Update BFD section data when freeing section
contents.
* readelf.c (load_specific_debug_section): Initialise the
user_data field.

* archive.c (do_slurp_coff_armap): Add range checks to prevent
running off the end of the string table.
* compress.c (bfd_get_full_section_contents): Return a NULL
pointer for zero sized sections.  Do not attempt to copy a buffer
onto itself.
* elf-attrs.c (_bfd_elf_parse_attributes): Check for an empty
header.  Add range checks to avoid running off the end of the
section.
* elf.c (bfd_elf_get_str_section): Seek before allocating so that
if the seek fails, no memory is allocated.
(bfd_elf_string_from_elf_section): Do not allocate a string from a
non string section.  It only leads to trouble later on.
(_bfd_elf_print_private_bfd_data): Check for there being too
little external dynamic data.
(bfd_section_from_shdr): Replace assertion with a failure mode.
(bfd_section_from_shdr): When walking a loaded group section use
the internal structure size, not the external size.  Check for the
group section being empty.
* elf32-i386.c (elf_i386_rtype_to_howto): Replace assertion with a
failure mode.
* elfcode.h (elf_slurp_reloc_table): Likewise.
* reloc.c (bfd_perform_relocation): Avoid seg-fault if the howto
parameter is NULL.

13 files changed:
bfd/ChangeLog
bfd/archive.c
bfd/compress.c
bfd/elf-attrs.c
bfd/elf.c
bfd/elf32-i386.c
bfd/elfcode.h
bfd/reloc.c
binutils/ChangeLog
binutils/dwarf.c
binutils/dwarf.h
binutils/objdump.c
binutils/readelf.c

index 8bcbc1184e30d843585e69f87d7613eb9eb188a6..0489b79b06681854bb849661bab9241769854b8a 100644 (file)
@@ -1,3 +1,30 @@
+2014-12-01  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/17512
+       * archive.c (do_slurp_coff_armap): Add range checks to prevent
+       running off the end of the string table.
+       * compress.c (bfd_get_full_section_contents): Return a NULL
+       pointer for zero sized sections.  Do not attempt to copy a buffer
+       onto itself.
+       * elf-attrs.c (_bfd_elf_parse_attributes): Check for an empty
+       header.  Add range checks to avoid running off the end of the
+       section.
+       * elf.c (bfd_elf_get_str_section): Seek before allocating so that
+       if the seek fails, no memory is allocated.
+       (bfd_elf_string_from_elf_section): Do not allocate a string from a
+       non string section.  It only leads to trouble later on.
+       (_bfd_elf_print_private_bfd_data): Check for there being too
+       little external dynamic data.
+       (bfd_section_from_shdr): Replace assertion with a failure mode.
+       (bfd_section_from_shdr): When walking a loaded group section use
+       the internal structure size, not the external size.  Check for the
+       group section being empty.
+       * elf32-i386.c (elf_i386_rtype_to_howto): Replace assertion with a
+       failure mode.
+       * elfcode.h (elf_slurp_reloc_table): Likewise.
+       * reloc.c (bfd_perform_relocation): Avoid seg-fault if the howto
+       parameter is NULL.
+
 2014-11-30  Alan Modra  <amodra@gmail.com>
 
        PR 16452, 16457
index df37996d74b41bb31c270616868cbc9787585d70..0ab4f6e103c293cd526498846548bbfe0e27aae9 100644 (file)
@@ -1038,12 +1038,19 @@ do_slurp_coff_armap (bfd *abfd)
     }
 
   /* OK, build the carsyms.  */
-  for (i = 0; i < nsymz; i++)
+  for (i = 0; i < nsymz && stringsize > 0; i++)
     {
+      bfd_size_type len;
+
       rawptr = raw_armap + i;
       carsyms->file_offset = swap ((bfd_byte *) rawptr);
       carsyms->name = stringbase;
-      stringbase += strlen (stringbase) + 1;
+      /* PR 17512: file: 4a1d50c1.  */
+      len = strnlen (stringbase, stringsize);
+      if (len < stringsize)
+       len ++;
+      stringbase += len;
+      stringsize -= len;
       carsyms++;
     }
   *stringbase = 0;
index 20eef9528265e905e9b7220e38520625cfb15dea..3fcbd783ee40255f3c72a5d0f555c66496432041 100644 (file)
@@ -152,7 +152,8 @@ DESCRIPTION
        return @var{*ptr} with memory malloc'd by this function.
 
        Return @code{TRUE} if the full section contents is retrieved
-       successfully.
+       successfully.  If the section has no contents then this function
+       returns @code{TRUE} but @var{*ptr} is set to NULL.
 */
 
 bfd_boolean
@@ -172,7 +173,10 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
   else
     sz = sec->size;
   if (sz == 0)
-    return TRUE;
+    {
+      *ptr = NULL;
+      return TRUE;
+    }
 
   switch (sec->compress_status)
     {
@@ -183,6 +187,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
          if (p == NULL)
            return FALSE;
        }
+
       if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
        {
          if (*ptr != p)
@@ -246,7 +251,9 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
            return FALSE;
          *ptr = p;
        }
-      memcpy (p, sec->contents, sz);
+      /* PR 17512; file: 5bc29788.  */
+      if (p != sec->contents)
+       memcpy (p, sec->contents, sz);
       return TRUE;
 
     default:
index 6bc2944c7bffec0a31a60c3899a267582202ca24..25f7e2672d7956c72c2e155c2f258773fab4f647 100644 (file)
@@ -430,9 +430,13 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
 {
   bfd_byte *contents;
   bfd_byte *p;
+  bfd_byte *p_end;
   bfd_vma len;
   const char *std_sec;
 
+  /* PR 17512: file: 2844a11d.  */
+  if (hdr->sh_size == 0)
+    return;
   contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
   if (!contents)
     return;
@@ -443,11 +447,14 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
       return;
     }
   p = contents;
+  p_end = p + hdr->sh_size;
   std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor;
+  
   if (*(p++) == 'A')
     {
       len = hdr->sh_size - 1;
-      while (len > 0)
+
+      while (len > 0 && p < p_end - 4)
        {
          unsigned namelen;
          bfd_vma section_len;
@@ -477,7 +484,7 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
            }
 
          p += namelen;
-         while (section_len > 0)
+         while (section_len > 0 && p < p_end)
            {
              int tag;
              unsigned int n;
@@ -487,7 +494,10 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
 
              tag = read_unsigned_leb128 (abfd, p, &n);
              p += n;
-             subsection_len = bfd_get_32 (abfd, p);
+             if (p < p_end - 4)
+               subsection_len = bfd_get_32 (abfd, p);
+             else
+               subsection_len = 0;
              p += 4;
              if (subsection_len == 0)
                break;
index 07cb80441817a1e89109f0a5dfd772b2acb5b3c9..405ec332b37f023f276589edffe611756e2ef0fa 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -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,6 +1265,9 @@ _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;
       /* PR 17512: file: id:000006,sig:06,src:000000,op:flip4,pos:5664.
          Fix range check.  */
@@ -1607,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
@@ -1974,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)
@@ -2031,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;
index 5c35d6509d1e9c3aa63d901b40b9528b9fa15dd1..dcf37b14a86ca0372a4a588d4d1daab61bfdcb39 100644 (file)
@@ -379,7 +379,9 @@ elf_i386_rtype_to_howto (bfd *abfd, unsigned r_type)
                             abfd, (int) r_type);
       indx = R_386_NONE;
     }
-  BFD_ASSERT (elf_howto_table [indx].type == r_type);
+  /* PR 17512: file: 0f67f69d.  */
+  if (elf_howto_table [indx].type != r_type)
+    return NULL;
   return &elf_howto_table[indx];
 }
 
index ec53c3bbd8f65ba6f655293759a8357196e885b0..d34e18ed080057eea951c6c9f92c84e553063963 100644 (file)
@@ -1501,7 +1501,9 @@ elf_slurp_reloc_table (bfd *abfd,
       rel_hdr2 = d->rela.hdr;
       reloc_count2 = rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0;
 
-      BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
+      /* PR 17512: file: 0b4f81b7.  */
+      if (asect->reloc_count != reloc_count + reloc_count2)
+       return FALSE;
       BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset)
                  || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
 
index dedfb6a4f984ef03fa05eae5bf82ce4dcca680d1..89e46f39d393cc5ee431ba412eb7944ba1351470 100644 (file)
@@ -592,6 +592,10 @@ bfd_perform_relocation (bfd *abfd,
       return bfd_reloc_ok;
     }
 
+  /* PR 17512: file: 0f67f69d.  */
+  if (howto == NULL)
+    return bfd_reloc_undefined;
+
   /* If we are not producing relocatable output, return an error if
      the symbol is not defined.  An undefined weak symbol is
      considered to have a value of zero (SVR4 ABI, p. 4-27).  */
index ecb7c8bf8e90f8548fd4bf0ed0a7d1b19097e835..597e52a28ee95ff16699e8c16b8bcd7b43f91d91 100644 (file)
@@ -1,3 +1,20 @@
+2014-12-01  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/17512
+       * dwarf.h (struct dwarf_section): Add user_data field.
+       * dwarf.c (frame_need_space): Check for an over large register
+       number.
+       (display_debug_frames): Check the return value from
+       frame_need_space.  Check for a CFA expression that is so long the
+       start address wraps around.
+       (debug_displays): Initialise the user_data field.
+       * objdump.c (load_specific_debug_section): Save the BFD section
+       pointer in the user_data field of the dwarf_section structure.
+       (free_debug_section): Update BFD section data when freeing section
+       contents.
+       * readelf.c (load_specific_debug_section): Initialise the
+       user_data field.
+
 2014-12-01  Nick Clifton  <nickc@redhat.com>
 
        PR binutils/17531
index 5f953d5118703ec85aa374376223fcef313a1339..d744929c02d79cb363b9261d62659434395b4b2a 100644 (file)
@@ -5157,6 +5157,16 @@ frame_need_space (Frame_Chunk *fc, unsigned int reg)
   if (fc->ncols == 0)
     return -1;
 
+  /* PR 17512: file: 2844a11d.  */
+  if (fc->ncols > 1024)
+    {
+      error (_("Unfeasibly large register number: %u\n"), reg);
+      fc->ncols = 0;
+      /* FIXME: 1024 is an arbitrary limit.  Increase it if
+        we ever encounter a valid binary that exceeds it.  */
+      return -1;
+    }
+
   fc->col_type = (short int *) xcrealloc (fc->col_type, fc->ncols,
                                           sizeof (short int));
   fc->col_offset = (int *) xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
@@ -5590,7 +5600,8 @@ display_debug_frames (struct dwarf_section *section,
          mreg = max_regs > 0 ? max_regs - 1 : 0;
          if (mreg < fc->ra)
            mreg = fc->ra;
-         frame_need_space (fc, mreg);
+         if (frame_need_space (fc, mreg) < 0)
+           break;
          if (fc->fde_encoding)
            encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
 
@@ -5696,7 +5707,11 @@ display_debug_frames (struct dwarf_section *section,
                          mreg = max_regs > 0 ? max_regs - 1 : 0;
                          if (mreg < cie->ra)
                            mreg = cie->ra;
-                         frame_need_space (cie, mreg);
+                         if (frame_need_space (cie, mreg) < 0)
+                           {
+                             warn (_("Invalid max register\n"));
+                             break;
+                           }
                          if (cie->fde_encoding)
                            encoded_ptr_size
                              = size_of_encoded_value (cie->fde_encoding);
@@ -5716,7 +5731,11 @@ display_debug_frames (struct dwarf_section *section,
              fc->ncols = 0;
              fc->col_type = (short int *) xmalloc (sizeof (short int));
              fc->col_offset = (int *) xmalloc (sizeof (int));
-             frame_need_space (fc, max_regs > 0 ? max_regs - 1 : 0);
+             if (frame_need_space (fc, max_regs > 0 ? max_regs - 1 : 0) < 0)
+               {
+                 warn (_("Invalid max register\n"));
+                 break;
+               }
              cie = fc;
              fc->augmentation = "";
              fc->fde_encoding = 0;
@@ -5739,7 +5758,11 @@ display_debug_frames (struct dwarf_section *section,
              fc->cfa_reg = cie->cfa_reg;
              fc->cfa_offset = cie->cfa_offset;
              fc->ra = cie->ra;
-             frame_need_space (fc, max_regs > 0 ? max_regs - 1: 0);
+             if (frame_need_space (fc, max_regs > 0 ? max_regs - 1: 0) < 0)
+               {
+                 warn (_("Invalid max register\n"));
+                 break;
+               }
              fc->fde_encoding = cie->fde_encoding;
            }
 
@@ -5857,7 +5880,6 @@ display_debug_frames (struct dwarf_section *section,
                  break;
                case DW_CFA_restore_extended:
                  reg = LEB ();
-                 frame_need_space (fc, reg);
                  if (frame_need_space (fc, reg) >= 0)
                    fc->col_type[reg] = DW_CFA_undefined;
                  break;
@@ -6176,7 +6198,12 @@ display_debug_frames (struct dwarf_section *section,
                  fc->cfa_reg = rs->cfa_reg;
                  fc->ra = rs->ra;
                  fc->cfa_exp = rs->cfa_exp;
-                 frame_need_space (fc, rs->ncols - 1);
+                 if (frame_need_space (fc, rs->ncols - 1) < 0)
+                   {
+                     warn (_("Invalid column number in saved frame state"));
+                     fc->ncols = 0;
+                     break;
+                   }
                  memcpy (fc->col_type, rs->col_type, rs->ncols * sizeof (* rs->col_type));
                  memcpy (fc->col_offset, rs->col_offset,
                          rs->ncols * sizeof (* rs->col_offset));
@@ -6218,7 +6245,7 @@ display_debug_frames (struct dwarf_section *section,
 
            case DW_CFA_def_cfa_expression:
              ul = LEB ();
-             if (start >= block_end || start + ul > block_end)
+             if (start >= block_end || start + ul > block_end || start + ul < start)
                {
                  printf (_("  DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
                  break;
@@ -6240,7 +6267,8 @@ display_debug_frames (struct dwarf_section *section,
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              /* PR 17512: file: 069-133014-0.006.  */
-             if (start >= block_end || start + ul > block_end)
+             /* PR 17512: file: 98c02eb4.  */
+             if (start >= block_end || start + ul > block_end || start + ul < start)
                {
                  printf (_("  DW_CFA_expression: <corrupt len %lu>\n"), ul);
                  break;
@@ -6263,7 +6291,7 @@ display_debug_frames (struct dwarf_section *section,
              ul = LEB ();
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
-             if (start >= block_end || start + ul > block_end)
+             if (start >= block_end || start + ul > block_end || start + ul < start)
                {
                  printf ("  DW_CFA_val_expression: <corrupt len %lu>\n", ul);
                  break;
@@ -7189,76 +7217,76 @@ dwarf_select_sections_all (void)
 
 struct dwarf_section_display debug_displays[] =
 {
-  { { ".debug_abbrev",     ".zdebug_abbrev",   NULL, NULL, 0, 0, 0 },
+  { { ".debug_abbrev",     ".zdebug_abbrev",   NULL, NULL, 0, 0, 0, NULL },
     display_debug_abbrev,   &do_debug_abbrevs, 0 },
-  { { ".debug_aranges",            ".zdebug_aranges",  NULL, NULL, 0, 0, 0 },
+  { { ".debug_aranges",            ".zdebug_aranges",  NULL, NULL, 0, 0, 0, NULL },
     display_debug_aranges,  &do_debug_aranges, 1 },
-  { { ".debug_frame",       ".zdebug_frame",   NULL, NULL, 0, 0, 0 },
+  { { ".debug_frame",       ".zdebug_frame",   NULL, NULL, 0, 0, 0, NULL },
     display_debug_frames,   &do_debug_frames,  1 },
-  { { ".debug_info",       ".zdebug_info",     NULL, NULL, 0, 0, abbrev },
+  { { ".debug_info",       ".zdebug_info",     NULL, NULL, 0, 0, abbrev, NULL },
     display_debug_info,            &do_debug_info,     1 },
-  { { ".debug_line",       ".zdebug_line",     NULL, NULL, 0, 0, 0 },
+  { { ".debug_line",       ".zdebug_line",     NULL, NULL, 0, 0, 0, NULL },
     display_debug_lines,    &do_debug_lines,   1 },
-  { { ".debug_pubnames",    ".zdebug_pubnames",        NULL, NULL, 0, 0, 0 },
+  { { ".debug_pubnames",    ".zdebug_pubnames",        NULL, NULL, 0, 0, 0, NULL },
     display_debug_pubnames, &do_debug_pubnames,        0 },
-  { { ".debug_gnu_pubnames", ".zdebug_gnu_pubnames", NULL, NULL, 0, 0, 0 },
+  { { ".debug_gnu_pubnames", ".zdebug_gnu_pubnames", NULL, NULL, 0, 0, 0, NULL },
     display_debug_gnu_pubnames, &do_debug_pubnames, 0 },
-  { { ".eh_frame",         "",                 NULL, NULL, 0, 0, 0 },
+  { { ".eh_frame",         "",                 NULL, NULL, 0, 0, 0, NULL },
     display_debug_frames,   &do_debug_frames,  1 },
-  { { ".debug_macinfo",            ".zdebug_macinfo",  NULL, NULL, 0, 0, 0 },
+  { { ".debug_macinfo",            ".zdebug_macinfo",  NULL, NULL, 0, 0, 0, NULL },
     display_debug_macinfo,  &do_debug_macinfo, 0 },
-  { { ".debug_macro",      ".zdebug_macro",    NULL, NULL, 0, 0, 0 },
+  { { ".debug_macro",      ".zdebug_macro",    NULL, NULL, 0, 0, 0, NULL },
     display_debug_macro,    &do_debug_macinfo, 1 },
-  { { ".debug_str",        ".zdebug_str",      NULL, NULL, 0, 0, 0 },
+  { { ".debug_str",        ".zdebug_str",      NULL, NULL, 0, 0, 0, NULL },
     display_debug_str,     &do_debug_str,      0 },
-  { { ".debug_loc",        ".zdebug_loc",      NULL, NULL, 0, 0, 0 },
+  { { ".debug_loc",        ".zdebug_loc",      NULL, NULL, 0, 0, 0, NULL },
     display_debug_loc,     &do_debug_loc,      1 },
-  { { ".debug_pubtypes",    ".zdebug_pubtypes",        NULL, NULL, 0, 0, 0 },
+  { { ".debug_pubtypes",    ".zdebug_pubtypes",        NULL, NULL, 0, 0, 0, NULL },
     display_debug_pubnames, &do_debug_pubtypes,        0 },
-  { { ".debug_gnu_pubtypes", ".zdebug_gnu_pubtypes", NULL, NULL, 0, 0, 0 },
+  { { ".debug_gnu_pubtypes", ".zdebug_gnu_pubtypes", NULL, NULL, 0, 0, 0, NULL },
     display_debug_gnu_pubnames, &do_debug_pubtypes, 0 },
-  { { ".debug_ranges",     ".zdebug_ranges",   NULL, NULL, 0, 0, 0 },
+  { { ".debug_ranges",     ".zdebug_ranges",   NULL, NULL, 0, 0, 0, NULL },
     display_debug_ranges,   &do_debug_ranges,  1 },
-  { { ".debug_static_func", ".zdebug_static_func", NULL, NULL, 0, 0, 0 },
+  { { ".debug_static_func", ".zdebug_static_func", NULL, NULL, 0, 0, 0, NULL },
     display_debug_not_supported, NULL,         0 },
-  { { ".debug_static_vars", ".zdebug_static_vars", NULL, NULL, 0, 0, 0 },
+  { { ".debug_static_vars", ".zdebug_static_vars", NULL, NULL, 0, 0, 0, NULL },
     display_debug_not_supported, NULL,         0 },
-  { { ".debug_types",      ".zdebug_types",    NULL, NULL, 0, 0, abbrev },
+  { { ".debug_types",      ".zdebug_types",    NULL, NULL, 0, 0, abbrev, NULL },
     display_debug_types,    &do_debug_info,    1 },
-  { { ".debug_weaknames",   ".zdebug_weaknames", NULL, NULL, 0, 0, 0 },
+  { { ".debug_weaknames",   ".zdebug_weaknames", NULL, NULL, 0, 0, 0, NULL },
     display_debug_not_supported, NULL,         0 },
-  { { ".gdb_index",        "",                 NULL, NULL, 0, 0, 0 },
+  { { ".gdb_index",        "",                 NULL, NULL, 0, 0, 0, NULL },
     display_gdb_index,      &do_gdb_index,     0 },
-  { { ".trace_info",       "",                 NULL, NULL, 0, 0, trace_abbrev },
+  { { ".trace_info",       "",                 NULL, NULL, 0, 0, trace_abbrev, NULL },
     display_trace_info,            &do_trace_info,     1 },
-  { { ".trace_abbrev",     "",                 NULL, NULL, 0, 0, 0 },
+  { { ".trace_abbrev",     "",                 NULL, NULL, 0, 0, 0, NULL },
     display_debug_abbrev,   &do_trace_abbrevs, 0 },
-  { { ".trace_aranges",            "",                 NULL, NULL, 0, 0, 0 },
+  { { ".trace_aranges",            "",                 NULL, NULL, 0, 0, 0, NULL },
     display_debug_aranges,  &do_trace_aranges, 0 },
-  { { ".debug_info.dwo",    ".zdebug_info.dwo",        NULL, NULL, 0, 0, abbrev_dwo },
+  { { ".debug_info.dwo",    ".zdebug_info.dwo",        NULL, NULL, 0, 0, abbrev_dwo, NULL },
     display_debug_info,            &do_debug_info,     1 },
-  { { ".debug_abbrev.dwo",  ".zdebug_abbrev.dwo", NULL, NULL, 0, 0, 0 },
+  { { ".debug_abbrev.dwo",  ".zdebug_abbrev.dwo", NULL, NULL, 0, 0, 0, NULL },
     display_debug_abbrev,   &do_debug_abbrevs, 0 },
-  { { ".debug_types.dwo",   ".zdebug_types.dwo", NULL, NULL, 0, 0, abbrev_dwo },
+  { { ".debug_types.dwo",   ".zdebug_types.dwo", NULL, NULL, 0, 0, abbrev_dwo, NULL },
     display_debug_types,    &do_debug_info,    1 },
-  { { ".debug_line.dwo",    ".zdebug_line.dwo", NULL, NULL, 0, 0, 0 },
+  { { ".debug_line.dwo",    ".zdebug_line.dwo", NULL, NULL, 0, 0, 0, NULL },
     display_debug_lines,    &do_debug_lines,   1 },
-  { { ".debug_loc.dwo",            ".zdebug_loc.dwo",  NULL, NULL, 0, 0, 0 },
+  { { ".debug_loc.dwo",            ".zdebug_loc.dwo",  NULL, NULL, 0, 0, 0, NULL },
     display_debug_loc,     &do_debug_loc,      1 },
-  { { ".debug_macro.dwo",   ".zdebug_macro.dwo", NULL, NULL, 0, 0, 0 },
+  { { ".debug_macro.dwo",   ".zdebug_macro.dwo", NULL, NULL, 0, 0, 0, NULL },
     display_debug_macro,    &do_debug_macinfo, 1 },
-  { { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo", NULL, NULL, 0, 0, 0 },
+  { { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo", NULL, NULL, 0, 0, 0, NULL },
     display_debug_macinfo,  &do_debug_macinfo, 0 },
-  { { ".debug_str.dwo",     ".zdebug_str.dwo",  NULL, NULL, 0, 0, 0 },
+  { { ".debug_str.dwo",     ".zdebug_str.dwo",  NULL, NULL, 0, 0, 0, NULL },
     display_debug_str,      &do_debug_str,     1 },
-  { { ".debug_str_offsets", ".zdebug_str_offsets", NULL, NULL, 0, 0, 0 },
+  { { ".debug_str_offsets", ".zdebug_str_offsets", NULL, NULL, 0, 0, 0, NULL },
     display_debug_str_offsets, NULL,           0 },
-  { { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo", NULL, NULL, 0, 0, 0 },
+  { { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo", NULL, NULL, 0, 0, 0, NULL },
     display_debug_str_offsets, NULL,           0 },
-  { { ".debug_addr",       ".zdebug_addr",     NULL, NULL, 0, 0, 0 },
+  { { ".debug_addr",       ".zdebug_addr",     NULL, NULL, 0, 0, 0, NULL },
     display_debug_addr,     &do_debug_addr,    1 },
-  { { ".debug_cu_index",    "",                        NULL, NULL, 0, 0, 0 },
+  { { ".debug_cu_index",    "",                        NULL, NULL, 0, 0, 0, NULL },
     display_cu_index,       &do_debug_cu_index,        0 },
-  { { ".debug_tu_index",    "",                        NULL, NULL, 0, 0, 0 },
+  { { ".debug_tu_index",    "",                        NULL, NULL, 0, 0, 0, NULL },
     display_cu_index,       &do_debug_cu_index,        0 },
 };
index 124d9d6d3583277d7b48514f34fdaf8835945d5f..bd62892c4f5fc74dbee36b533ad193df3f2fdd0b 100644 (file)
@@ -164,6 +164,8 @@ struct dwarf_section
   dwarf_vma address;
   dwarf_size_type size;
   enum dwarf_section_display_enum abbrev_sec;
+  /* A spare field for random use.  */
+  void *user_data;
 };
 
 /* A structure containing the name of a debug section
index fdfa60250c2c4ddc035e4003bae9e27202407a01..b13bf00e699c7522ed1b22bd165e331ac5cb0b61 100644 (file)
@@ -2280,6 +2280,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
   section->address = bfd_get_section_vma (abfd, sec);
   section->size = bfd_get_section_size (sec);
   section->start = NULL;
+  section->user_data = sec;
   ret = bfd_get_full_section_contents (abfd, sec, &section->start);
 
   if (! ret)
@@ -2346,6 +2347,22 @@ free_debug_section (enum dwarf_section_display_enum debug)
   if (section->start == NULL)
     return;
 
+  /* PR 17512: file: 0f67f69d.  */
+  if (section->user_data != NULL)
+    {
+      asection * sec = (asection *) section->user_data;
+
+      /* If we are freeing contents that are also pointed to by the BFD
+        library's section structure then make sure to update those pointers
+        too.  Otherwise, the next time we try to load data for this section
+        we can end up using a stale pointer.  */
+      if (section->start == sec->contents)
+       {
+         sec->contents = NULL;
+         sec->flags &= ~ SEC_IN_MEMORY;
+       }
+    }
+
   free ((char *) section->start);
   section->start = NULL;
   section->address = 0;
index 4e16bd62bc93952eb758daf0a5e3190babe1ef6e..200475232a85339b7ab90498eedfe8211991bf06 100644 (file)
@@ -11713,6 +11713,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
 
   snprintf (buf, sizeof (buf), _("%s section data"), section->name);
   section->address = sec->sh_addr;
+  section->user_data = NULL;
   section->start = (unsigned char *) get_data (NULL, (FILE *) file,
                                                sec->sh_offset, 1,
                                                sec->sh_size, buf);