[ARC] Update merging attributes.
[deliverable/binutils-gdb.git] / binutils / dwarf.c
index 71fdf3910807b629d37679f449234d17c1bccd50..81060bfa462a2f53bed78566660e6db1c2418101 100644 (file)
@@ -387,6 +387,9 @@ read_uleb128 (unsigned char * data,
     }                                                          \
   while (0)
 
+/* Read AMOUNT bytes from PTR and store them in VAL as an unsigned value.
+   Checks to make sure that the read will not reach or pass END
+   and that VAL is big enough to hold AMOUNT bytes.  */
 #define SAFE_BYTE_GET(VAL, PTR, AMOUNT, END)   \
   do                                           \
     {                                          \
@@ -415,6 +418,7 @@ read_uleb128 (unsigned char * data,
     }                                          \
   while (0)
 
+/* Like SAFE_BYTE_GET, but also increments PTR by AMOUNT.  */
 #define SAFE_BYTE_GET_AND_INC(VAL, PTR, AMOUNT, END)   \
   do                                                   \
     {                                                  \
@@ -423,6 +427,7 @@ read_uleb128 (unsigned char * data,
     }                                                  \
   while (0)
 
+/* Like SAFE_BYTE_GET, but reads a signed value.  */
 #define SAFE_SIGNED_BYTE_GET(VAL, PTR, AMOUNT, END)    \
   do                                                   \
     {                                                  \
@@ -441,6 +446,7 @@ read_uleb128 (unsigned char * data,
     }                                                  \
   while (0)
 
+/* Like SAFE_SIGNED_BYTE_GET, but also increments PTR by AMOUNT.  */
 #define SAFE_SIGNED_BYTE_GET_AND_INC(VAL, PTR, AMOUNT, END)    \
   do                                                           \
     {                                                          \
@@ -2168,19 +2174,28 @@ read_and_display_attr_value (unsigned long           attribute,
              debug_info_p->have_frame_base [num] = have_frame_base;
              if (attribute != DW_AT_GNU_locviews)
                {
-                 debug_info_p->loc_offsets [num] = uvalue;
-                 debug_info_p->num_loc_offsets++;
-                 assert (debug_info_p->num_loc_offsets
-                         - debug_info_p->num_loc_views <= 1);
+                 /* Corrupt DWARF info can produce more offsets than views.
+                    See PR 23062 for an example.  */
+                 if (debug_info_p->num_loc_offsets
+                     > debug_info_p->num_loc_views)
+                   warn (_("More location offset attributes than DW_AT_GNU_locview attributes\n"));
+                 else
+                   {
+                     debug_info_p->loc_offsets [num] = uvalue;
+                     debug_info_p->num_loc_offsets++;
+                   }
                }
              else
                {
                  assert (debug_info_p->num_loc_views <= num);
                  num = debug_info_p->num_loc_views;
-                 debug_info_p->loc_views [num] = uvalue;
-                 debug_info_p->num_loc_views++;
-                 assert (debug_info_p->num_loc_views
-                         - debug_info_p->num_loc_offsets <= 1);
+                 if (num > debug_info_p->num_loc_offsets)
+                   warn (_("More DW_AT_GNU_locview attributes than location offset attributes\n"));
+                 else
+                   {
+                     debug_info_p->loc_views [num] = uvalue;
+                     debug_info_p->num_loc_views++;
+                   }
                }
            }
          break;
@@ -2346,12 +2361,22 @@ read_and_display_attr_value (unsigned long           attribute,
          /* DWARF 4 values.  */
        case DW_LANG_Python:            printf ("(Python)"); break;
          /* DWARF 5 values.  */
+       case DW_LANG_OpenCL:            printf ("(OpenCL)"); break;
        case DW_LANG_Go:                printf ("(Go)"); break;
+       case DW_LANG_Modula3:           printf ("(Modula 3)"); break;
+       case DW_LANG_Haskell:           printf ("(Haskell)"); break;
+       case DW_LANG_C_plus_plus_03:    printf ("(C++03)"); break;
        case DW_LANG_C_plus_plus_11:    printf ("(C++11)"); break;
+       case DW_LANG_OCaml:             printf ("(OCaml)"); break;
+       case DW_LANG_Rust:              printf ("(Rust)"); break;
        case DW_LANG_C11:               printf ("(C11)"); break;
+       case DW_LANG_Swift:             printf ("(Swift)"); break;
+       case DW_LANG_Julia:             printf ("(Julia)"); break;
+       case DW_LANG_Dylan:             printf ("(Dylan)"); break;
        case DW_LANG_C_plus_plus_14:    printf ("(C++14)"); break;
        case DW_LANG_Fortran03:         printf ("(Fortran 03)"); break;
        case DW_LANG_Fortran08:         printf ("(Fortran 08)"); break;
+       case DW_LANG_RenderScript:      printf ("(RenderScript)"); break;
          /* MIPS extension.  */
        case DW_LANG_Mips_Assembler:    printf ("(MIPS assembler)"); break;
          /* UPC extension.  */
@@ -3399,7 +3424,7 @@ display_formatted_table (unsigned char *                   data,
                         unsigned char *                   end,
                         const DWARF2_Internal_LineInfo *  linfo,
                         struct dwarf_section *            section,
-                        const char *                      what)
+                        bfd_boolean                       is_dir)
 {
   unsigned char *format_start, format_count, *format, formati;
   dwarf_vma data_count, datai;
@@ -3415,7 +3440,10 @@ display_formatted_table (unsigned char *                   data,
       data += bytes_read;
       if (data == end)
        {
-         warn (_("Corrupt %s format table entry\n"), what);
+         if (is_dir)
+           warn (_("Corrupt directory format table entry\n"));
+         else
+           warn (_("Corrupt file name format table entry\n"));
          return data;
        }
     }
@@ -3424,18 +3452,28 @@ display_formatted_table (unsigned char *                   data,
   data += bytes_read;
   if (data == end)
     {
-      warn (_("Corrupt %s list\n"), what);
+      if (is_dir)
+       warn (_("Corrupt directory list\n"));
+      else
+       warn (_("Corrupt file name list\n"));
       return data;
     }
 
   if (data_count == 0)
     {
-      printf (_("\n The %s Table is empty.\n"), what);
+      if (is_dir)
+       printf (_("\n The Directory Table is empty.\n"));
+      else
+       printf (_("\n The File Name Table is empty.\n"));
       return data;
     }
 
-  printf (_("\n The %s Table (offset 0x%lx):\n"), what,
-         (long)(data - start));
+  if (is_dir)
+    printf (_("\n The Directory Table (offset 0x%lx):\n"),
+           (long) (data - start));
+  else
+    printf (_("\n The File Name Table (offset 0x%lx):\n"),
+           (long) (data - start));
 
   printf (_("  Entry"));
   /* Delay displaying name as the last entry for better screen layout.  */ 
@@ -3503,7 +3541,10 @@ display_formatted_table (unsigned char *                   data,
        }
       if (data == end)
        {
-         warn (_("Corrupt %s entries list\n"), what);
+         if (is_dir)
+           warn (_("Corrupt directory entries list\n"));
+         else
+           warn (_("Corrupt file name entries list\n"));
          return data;
        }
       putchar ('\n');
@@ -3611,9 +3652,9 @@ display_debug_lines_raw (struct dwarf_section *  section,
              load_debug_section_with_follow (line_str, file);
 
              data = display_formatted_table (data, start, end, &linfo, section,
-                                             _("Directory"));
+                                             TRUE);
              data = display_formatted_table (data, start, end, &linfo, section,
-                                             _("File name"));
+                                             FALSE);
            }
          else
            {
@@ -6543,6 +6584,7 @@ display_debug_ranges_list (unsigned char *start, unsigned char *finish,
        break;
       SAFE_SIGNED_BYTE_GET_AND_INC (end, start, pointer_size, finish);
 
+      
       printf ("    %8.8lx ", offset);
 
       if (begin == 0 && end == 0)
@@ -6810,6 +6852,13 @@ display_debug_ranges (struct dwarf_section *section,
          continue;
        }
 
+      if (next < section_begin || next >= finish)
+       {
+         warn (_("Corrupt offset (%#8.8lx) in range entry %u\n"),
+               (unsigned long) offset, i);
+         continue;
+       }
+
       if (dwarf_check != 0 && i > 0)
        {
          if (start < next)
@@ -6825,6 +6874,7 @@ display_debug_ranges (struct dwarf_section *section,
                    (unsigned long) (next - section_begin), section->name);
            }
        }
+
       start = next;
       last_start = next;
 
@@ -7249,7 +7299,7 @@ read_cie (unsigned char *start, unsigned char *end,
   if (start == end)
     {
       warn (_("No terminator for augmentation name\n"));
-      return start;
+      goto fail;
     }
 
   if (strcmp (fc->augmentation, "eh") == 0)
@@ -7261,7 +7311,7 @@ read_cie (unsigned char *start, unsigned char *end,
       if (fc->ptr_size < 1 || fc->ptr_size > 8)
        {
          warn (_("Invalid pointer size (%d) in CIE data\n"), fc->ptr_size);
-         return end;
+         goto fail;
        }
 
       GET (fc->segment_size, 1);
@@ -7269,7 +7319,7 @@ read_cie (unsigned char *start, unsigned char *end,
       if (fc->segment_size > 8 || fc->segment_size + fc->ptr_size > 8)
        {
          warn (_("Invalid segment size (%d) in CIE data\n"), fc->segment_size);
-         return end;
+         goto fail;
        }
 
       eh_addr_size = fc->ptr_size;
@@ -7279,8 +7329,10 @@ read_cie (unsigned char *start, unsigned char *end,
       fc->ptr_size = eh_addr_size;
       fc->segment_size = 0;
     }
+
   READ_ULEB (fc->code_factor);
   READ_SLEB (fc->data_factor);
+
   if (version == 1)
     {
       GET (fc->ra, 1);
@@ -7300,7 +7352,7 @@ read_cie (unsigned char *start, unsigned char *end,
          warn (_("Augmentation data too long: 0x%s, expected at most %#lx\n"),
                dwarf_vmatoa ("x", augmentation_data_len),
                (unsigned long) (end - start));
-         return end;
+         goto fail;
        }
       start += augmentation_data_len;
     }
@@ -7342,6 +7394,12 @@ read_cie (unsigned char *start, unsigned char *end,
       *p_aug = augmentation_data;
     }
   return start;
+
+ fail:
+  free (fc->col_offset);
+  free (fc->col_type);
+  free (fc);
+  return end;
 }
 
 /* Prints out the contents on the DATA array formatted as unsigned bytes.
@@ -7387,10 +7445,10 @@ display_debug_frames (struct dwarf_section *section,
   unsigned char *start = section->start;
   unsigned char *end = start + section->size;
   unsigned char *section_start = start;
-  Frame_Chunk *chunks = 0, *forward_refs = 0;
-  Frame_Chunk *remembered_state = 0;
+  Frame_Chunk *chunks = NULL, *forward_refs = NULL;
+  Frame_Chunk *remembered_state = NULL;
   Frame_Chunk *rs;
-  int is_eh = strcmp (section->name, ".eh_frame") == 0;
+  bfd_boolean is_eh = strcmp (section->name, ".eh_frame") == 0;
   unsigned int length_return;
   unsigned int max_regs = 0;
   const char *bad_reg = _("bad register: ");
@@ -8323,6 +8381,36 @@ display_debug_frames (struct dwarf_section *section,
 
   printf ("\n");
 
+  while (remembered_state != NULL)
+    {
+      rs = remembered_state;
+      remembered_state = rs->next;
+      free (rs->col_type);
+      free (rs->col_offset);
+      rs->next = NULL; /* Paranoia.  */
+      free (rs);
+    }
+
+  while (chunks != NULL)
+    {
+      rs = chunks;
+      chunks = rs->next;
+      free (rs->col_type);
+      free (rs->col_offset);
+      rs->next = NULL; /* Paranoia.  */
+      free (rs);
+    }
+
+  while (forward_refs != NULL)
+    {
+      rs = forward_refs;
+      forward_refs = rs->next;
+      free (rs->col_type);
+      free (rs->col_offset);
+      rs->next = NULL; /* Paranoia.  */
+      free (rs);
+    }
+
   return 1;
 }
 
@@ -9262,7 +9350,18 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
                }
 
              if (!do_display)
-               memcpy (&this_set[row - 1].signature, ph, sizeof (uint64_t));
+               {
+                 size_t num_copy = sizeof (uint64_t);
+
+                 /* PR 23064: Beware of buffer overflow.  */
+                 if (ph + num_copy < limit)
+                   memcpy (&this_set[row - 1].signature, ph, num_copy);
+                 else
+                   {
+                     warn (_("Signature (%p) extends beyond end of space in section\n"), ph);
+                     return 0;
+                   }
+               }
 
              prow = poffsets + (row - 1) * ncols * 4;
              /* PR 17531: file: b8ce60a8.  */
@@ -9740,6 +9839,7 @@ load_separate_debug_info (const char *            main_filename,
   if (debugfile == NULL)
     {
       warn (_("Out of memory"));
+      free (canon_dir);
       return NULL;
     }
 
@@ -9876,6 +9976,10 @@ load_dwo_file (const char * main_filename)
 void *
 load_separate_debug_file (void * file, const char * filename)
 {
+  /* Skip this operation if we are not interested in debug links.  */
+  if (! do_follow_links && ! do_debug_links)
+    return NULL;
+
   /* See if there is a dwo link.  */
   if (load_debug_section (str, file)
       && load_debug_section (abbrev, file)
@@ -9910,6 +10014,8 @@ load_separate_debug_file (void * file, const char * filename)
     }
 
   if (! do_follow_links)
+    /* The other debug links will be displayed by display_debug_links()
+       so we do not need to do any further processing here.  */
     return NULL;
 
   /* FIXME: We do not check for the presence of both link sections in the same file.  */
This page took 0.039571 seconds and 4 git commands to generate.