sim: frv: fix up various missing prototype warnings
[binutils-gdb.git] / binutils / dwarf.c
index 08f8ccdee43fa5e6e8ced8cd7bd6bd6891c393b2..a57f0dab6b268c9326a18d9e9997544a4c74eb63 100644 (file)
 #define CHAR_BIT 8
 #endif
 
+#ifndef ENABLE_CHECKING
+#define ENABLE_CHECKING 0
+#endif
+
 #undef MAX
 #undef MIN
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -178,7 +182,7 @@ get_encoded_value (unsigned char **pdata,
   unsigned int size = size_of_encoded_value (encoding);
   dwarf_vma val;
 
-  if (data + size >= end)
+  if (data >= end || size > (size_t) (end - data))
     {
       warn (_("Encoded value extends past end of section\n"));
       * pdata = end;
@@ -368,73 +372,55 @@ read_leb128 (unsigned char *data,
   return result;
 }
 
-/* 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                                           \
-    {                                          \
-      unsigned int amount = (AMOUNT);          \
-      if (sizeof (VAL) < amount)               \
-       {                                       \
+/* Read AMOUNT bytes from PTR and store them in VAL.
+   Checks to make sure that the read will not reach or pass END.
+   FUNC chooses whether the value read is unsigned or signed, and may
+   be either byte_get or byte_get_signed.  If INC is true, PTR is
+   incremented after reading the value.
+   This macro cannot protect against PTR values derived from user input.
+   The C standard sections 6.5.6 and 6.5.8 say attempts to do so using
+   pointers is undefined behaviour.  */
+#define SAFE_BYTE_GET_INTERNAL(VAL, PTR, AMOUNT, END, FUNC, INC)       \
+  do                                                                   \
+    {                                                                  \
+      size_t amount = (AMOUNT);                                                \
+      if (sizeof (VAL) < amount)                                       \
+       {                                                               \
          error (ngettext ("internal error: attempt to read %d byte "   \
                           "of data in to %d sized variable",           \
                           "internal error: attempt to read %d bytes "  \
                           "of data in to %d sized variable",           \
                           amount),                                     \
-                amount, (int) sizeof (VAL));   \
-         amount = sizeof (VAL);                \
-       }                                       \
-      if ((PTR) >= (END) - amount)             \
-       {                                       \
-         if ((PTR) < (END))                    \
-           amount = (END) - (PTR);             \
-         else                                  \
-           amount = 0;                         \
-       }                                       \
-      if (amount == 0 || amount > 8)           \
-       VAL = 0;                                \
-      else                                     \
-       VAL = byte_get ((PTR), amount);         \
-    }                                          \
+                (int) amount, (int) sizeof (VAL));                     \
+         amount = sizeof (VAL);                                        \
+       }                                                               \
+      if (ENABLE_CHECKING)                                             \
+       assert ((PTR) <= (END));                                        \
+      size_t avail = (END) - (PTR);                                    \
+      if ((PTR) > (END))                                               \
+       avail = 0;                                                      \
+      if (amount > avail)                                              \
+       amount = avail;                                                 \
+      if (amount == 0)                                                 \
+       (VAL) = 0;                                                      \
+      else                                                             \
+       (VAL) = (FUNC) ((PTR), amount);                                 \
+      if (INC)                                                         \
+       (PTR) += amount;                                                \
+    }                                                                  \
   while (0)
 
-/* Like SAFE_BYTE_GET, but also increments PTR by AMOUNT.  */
+#define SAFE_BYTE_GET(VAL, PTR, AMOUNT, END)   \
+  SAFE_BYTE_GET_INTERNAL (VAL, PTR, AMOUNT, END, byte_get, false)
+
 #define SAFE_BYTE_GET_AND_INC(VAL, PTR, AMOUNT, END)   \
-  do                                                   \
-    {                                                  \
-      SAFE_BYTE_GET (VAL, PTR, AMOUNT, END);           \
-      PTR += AMOUNT;                                   \
-    }                                                  \
-  while (0)
+  SAFE_BYTE_GET_INTERNAL (VAL, PTR, AMOUNT, END, byte_get, true)
 
-/* Like SAFE_BYTE_GET, but reads a signed value.  */
 #define SAFE_SIGNED_BYTE_GET(VAL, PTR, AMOUNT, END)    \
-  do                                                   \
-    {                                                  \
-      unsigned int amount = (AMOUNT);                  \
-      if ((PTR) >= (END) - amount)                     \
-       {                                               \
-         if ((PTR) < (END))                            \
-           amount = (END) - (PTR);                     \
-         else                                          \
-           amount = 0;                                 \
-       }                                               \
-      if (amount)                                      \
-       VAL = byte_get_signed ((PTR), amount);          \
-      else                                             \
-       VAL = 0;                                        \
-    }                                                  \
-  while (0)
+  SAFE_BYTE_GET_INTERNAL (VAL, PTR, AMOUNT, END, byte_get_signed, false)
 
-/* Like SAFE_SIGNED_BYTE_GET, but also increments PTR by AMOUNT.  */
 #define SAFE_SIGNED_BYTE_GET_AND_INC(VAL, PTR, AMOUNT, END)    \
-  do                                                           \
-    {                                                          \
-      SAFE_SIGNED_BYTE_GET (VAL, PTR, AMOUNT, END);            \
-      PTR += AMOUNT;                                           \
-    }                                                          \
-  while (0)
+  SAFE_BYTE_GET_INTERNAL (VAL, PTR, AMOUNT, END, byte_get_signed, true)
 
 typedef struct State_Machine_Registers
 {
@@ -529,7 +515,9 @@ process_extended_line_op (unsigned char * data,
 
        name = data;
        l = strnlen ((char *) data, end - data);
-       data += l + 1;
+       data += l;
+       if (data < end)
+         data++;
        READ_ULEB (val, data, end);
        printf ("%s\t", dwarf_vmatoa ("u", val));
        READ_ULEB (val, data, end);
@@ -835,7 +823,7 @@ typedef struct abbrev_attr
 {
   unsigned long          attribute;
   unsigned long          form;
-  bfd_signed_vma         implicit_const;
+  dwarf_signed_vma       implicit_const;
   struct abbrev_attr *   next;
 }
 abbrev_attr;
@@ -1010,19 +998,19 @@ add_abbrev (unsigned long  number,
 }
 
 static void
-add_abbrev_attr (unsigned long   attribute,
-                unsigned long   form,
-                bfd_signed_vma  implicit_const,
-                abbrev_list *   list)
+add_abbrev_attr (unsigned long    attribute,
+                unsigned long    form,
+                dwarf_signed_vma implicit_const,
+                abbrev_list *    list)
 {
   abbrev_attr *attr;
 
   attr = (abbrev_attr *) xmalloc (sizeof (*attr));
 
-  attr->attribute = attribute;
-  attr->form      = form;
+  attr->attribute      = attribute;
+  attr->form           = form;
   attr->implicit_const = implicit_const;
-  attr->next      = NULL;
+  attr->next           = NULL;
 
   assert (list != NULL && list->last_abbrev != NULL);
 
@@ -1097,7 +1085,7 @@ process_abbrev_set (struct dwarf_section *section,
        {
          unsigned long form;
          /* Initialize it due to a false compiler warning.  */
-         bfd_signed_vma implicit_const = -1;
+         dwarf_signed_vma implicit_const = -1;
 
          READ_ULEB (attribute, start, end);
          if (start == end)
@@ -1633,8 +1621,6 @@ decode_location_expression (unsigned char * data,
            need_frame_base = 1;
          putchar (')');
          data += uvalue;
-         if (data > end)
-           data = end;
          break;
        case DW_OP_const_type:
        case DW_OP_GNU_const_type:
@@ -1934,16 +1920,17 @@ check_uvalue (const unsigned char * start,
 }
 
 static unsigned char *
-skip_attr_bytes (unsigned long          form,
-                unsigned char *        data,
-                unsigned const char *  end,
-                dwarf_vma              pointer_size,
-                dwarf_vma              offset_size,
-                int                    dwarf_version,
-                dwarf_vma *            value_return)
+skip_attr_bytes (unsigned long form,
+                unsigned char *data,
+                unsigned char *end,
+                dwarf_vma pointer_size,
+                dwarf_vma offset_size,
+                int dwarf_version,
+                dwarf_vma *value_return)
 {
   dwarf_signed_vma svalue;
   dwarf_vma uvalue = 0;
+  dwarf_vma inc = 0;
 
   * value_return = 0;
 
@@ -2021,51 +2008,54 @@ skip_attr_bytes (unsigned long          form,
 
     case DW_FORM_data8:
     case DW_FORM_ref_sig8:
-      data += 8;
+      inc = 8;
       break;
 
     case DW_FORM_data16:
-      data += 16;
+      inc = 16;
       break;
 
     case DW_FORM_string:
-      data += strnlen ((char *) data, end - data) + 1;
+      inc = strnlen ((char *) data, end - data) + 1;
       break;
 
     case DW_FORM_block:
     case DW_FORM_exprloc:
       READ_ULEB (uvalue, data, end);
-      data += uvalue;
+      inc = uvalue;
       break;
 
     case DW_FORM_block1:
-      SAFE_BYTE_GET (uvalue, data, 1, end);
-      data += 1 + uvalue;
+      SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+      inc = uvalue;
       break;
 
     case DW_FORM_block2:
-      SAFE_BYTE_GET (uvalue, data, 2, end);
-      data += 2 + uvalue;
+      SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
+      inc = uvalue;
       break;
 
     case DW_FORM_block4:
-      SAFE_BYTE_GET (uvalue, data, 4, end);
-      data += 4 + uvalue;
+      SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
+      inc = uvalue;
       break;
 
     case DW_FORM_indirect:
       READ_ULEB (form, data, end);
       if (form == DW_FORM_implicit_const)
        SKIP_ULEB (data, end);
-      return skip_attr_bytes (form, data, end, pointer_size, offset_size, dwarf_version, value_return);
+      return skip_attr_bytes (form, data, end, pointer_size, offset_size,
+                             dwarf_version, value_return);
 
     default:
       return NULL;
     }
 
   * value_return = uvalue;
-  if (data > end)
-    data = (unsigned char *) end;
+  if (inc <= (dwarf_vma) (end - data))
+    data += inc;
+  else
+    data = end;
   return data;
 }
 
@@ -2073,13 +2063,13 @@ skip_attr_bytes (unsigned long          form,
    associated with it.  */
 
 static abbrev_entry *
-get_type_abbrev_from_form (unsigned long                 form,
-                          unsigned long                 uvalue,
-                          dwarf_vma                     cu_offset,
-                          const struct dwarf_section *  section,
-                          unsigned long *               abbrev_num_return,
-                          unsigned char **              data_return,
-                          unsigned long *               cu_offset_return)
+get_type_abbrev_from_form (unsigned long form,
+                          unsigned long uvalue,
+                          dwarf_vma cu_offset,
+                          const struct dwarf_section *section,
+                          unsigned long *abbrev_num_return,
+                          unsigned char **data_return,
+                          abbrev_map **map_return)
 {
   unsigned long   abbrev_number;
   abbrev_map *    map;
@@ -2146,12 +2136,12 @@ get_type_abbrev_from_form (unsigned long                 form,
       return NULL;
     }
 
-  if (cu_offset_return != NULL)
+  if (map_return != NULL)
     {
       if (form == DW_FORM_ref_addr)
-       * cu_offset_return = map->start;
+       *map_return = map;
       else
-       * cu_offset_return = cu_offset;
+       *map_return = NULL;
     }
        
   READ_ULEB (abbrev_number, data, section->start + section->size);
@@ -2180,7 +2170,7 @@ static void
 get_type_signedness (abbrev_entry *entry,
                     const struct dwarf_section *section,
                     unsigned char *data,
-                    unsigned const char *end,
+                    unsigned char *end,
                     dwarf_vma cu_offset,
                     dwarf_vma pointer_size,
                     dwarf_vma offset_size,
@@ -2228,21 +2218,23 @@ get_type_signedness (abbrev_entry *entry,
        case DW_AT_type:
          /* Recurse.  */
          {
-           abbrev_entry *  type_abbrev;
-           unsigned char * type_data;
-           unsigned long   type_cu_offset;
+           abbrev_entry *type_abbrev;
+           unsigned char *type_data;
+           abbrev_map *map;
 
            type_abbrev = get_type_abbrev_from_form (attr->form,
                                                     uvalue,
                                                     cu_offset,
                                                     section,
                                                     NULL /* abbrev num return */,
-                                                    & type_data,
-                                                    & type_cu_offset);
+                                                    &type_data,
+                                                    &map);
            if (type_abbrev == NULL)
              break;
 
-           get_type_signedness (type_abbrev, section, type_data, end, type_cu_offset,
+           get_type_signedness (type_abbrev, section, type_data,
+                                map ? section->start + map->end : end,
+                                map ? map->start : cu_offset,
                                 pointer_size, offset_size, dwarf_version,
                                 is_signed, nesting + 1);
          }
@@ -2336,9 +2328,8 @@ display_discr_list (unsigned long          form,
       unsigned char     discriminant;
       unsigned int      bytes_read;
 
-      SAFE_BYTE_GET (discriminant, data, 1, end);
+      SAFE_BYTE_GET_AND_INC (discriminant, data, 1, end);
       -- uvalue;
-      data ++;
 
       assert (uvalue > 0);
       switch (discriminant)
@@ -2600,7 +2591,9 @@ read_and_display_attr_value (unsigned long           attribute,
     case DW_FORM_string:
       if (!do_loc)
        printf ("%c%.*s", delimiter, (int) (end - data), data);
-      data += strnlen ((char *) data, end - data) + 1;
+      data += strnlen ((char *) data, end - data);
+      if (data < end)
+       data++;
       break;
 
     case DW_FORM_block:
@@ -2964,13 +2957,15 @@ read_and_display_attr_value (unsigned long           attribute,
          bool is_signed = false;
          abbrev_entry *type_abbrev;
          unsigned char *type_data;
-         unsigned long type_cu_offset;
+         abbrev_map *map;
 
          type_abbrev = get_type_abbrev_from_form (form, uvalue, cu_offset,
-                                                  section, NULL, & type_data, & type_cu_offset);
+                                                  section, NULL, &type_data, &map);
          if (type_abbrev != NULL)
            {
-             get_type_signedness (type_abbrev, section, type_data, end, type_cu_offset,
+             get_type_signedness (type_abbrev, section, type_data,
+                                  map ? section->start + map->end : end,
+                                  map ? map->start : cu_offset,
                                   pointer_size, offset_size, dwarf_version,
                                   & is_signed, 0);
            }
@@ -3442,51 +3437,49 @@ process_debug_info (struct dwarf_section * section,
   unsigned int unit;
   unsigned int num_units = 0;
 
-  if ((do_loc || do_debug_loc || do_debug_ranges)
-      && num_debug_info_entries == 0
-      && ! do_types)
+  /* First scan the section to get the number of comp units.
+     Length sanity checks are done here.  */
+  for (section_begin = start, num_units = 0; section_begin < end;
+       num_units ++)
     {
       dwarf_vma length;
 
-      /* First scan the section to get the number of comp units.  */
-      for (section_begin = start, num_units = 0; section_begin < end;
-          num_units ++)
-       {
-         /* Read the first 4 bytes.  For a 32-bit DWARF section, this
-            will be the length.  For a 64-bit DWARF section, it'll be
-            the escape code 0xffffffff followed by an 8 byte length.  */
-         SAFE_BYTE_GET (length, section_begin, 4, end);
+      /* Read the first 4 bytes.  For a 32-bit DWARF section, this
+        will be the length.  For a 64-bit DWARF section, it'll be
+        the escape code 0xffffffff followed by an 8 byte length.  */
+      SAFE_BYTE_GET_AND_INC (length, section_begin, 4, end);
 
-         if (length == 0xffffffff)
-           {
-             SAFE_BYTE_GET (length, section_begin + 4, 8, end);
-             section_begin += length + 12;
-           }
-         else if (length >= 0xfffffff0 && length < 0xffffffff)
-           {
-             warn (_("Reserved length value (0x%s) found in section %s\n"),
-                   dwarf_vmatoa ("x", length), section->name);
-             return false;
-           }
-         else
-           section_begin += length + 4;
-
-         /* Negative values are illegal, they may even cause infinite
-            looping.  This can happen if we can't accurately apply
-            relocations to an object file, or if the file is corrupt.  */
-         if ((signed long) length <= 0 || section_begin < start)
-           {
-             warn (_("Corrupt unit length (0x%s) found in section %s\n"),
-                   dwarf_vmatoa ("x", length), section->name);
-             return false;
-           }
+      if (length == 0xffffffff)
+       SAFE_BYTE_GET_AND_INC (length, section_begin, 8, end);
+      else if (length >= 0xfffffff0 && length < 0xffffffff)
+       {
+         warn (_("Reserved length value (0x%s) found in section %s\n"),
+               dwarf_vmatoa ("x", length), section->name);
+         return false;
        }
 
-      if (num_units == 0)
+      /* Negative values are illegal, they may even cause infinite
+        looping.  This can happen if we can't accurately apply
+        relocations to an object file, or if the file is corrupt.  */
+      if (length > (size_t) (end - section_begin))
        {
-         error (_("No comp units in %s section ?\n"), section->name);
+         warn (_("Corrupt unit length (0x%s) found in section %s\n"),
+               dwarf_vmatoa ("x", length), section->name);
          return false;
        }
+      section_begin += length;
+    }
+
+  if (num_units == 0)
+    {
+      error (_("No comp units in %s section ?\n"), section->name);
+      return false;
+    }
+
+  if ((do_loc || do_debug_loc || do_debug_ranges)
+      && num_debug_info_entries == 0
+      && ! do_types)
+    {
 
       /* Then allocate an array to hold the information.  */
       debug_information = (debug_info *) cmalloc (num_units,
@@ -3547,11 +3540,12 @@ process_debug_info (struct dwarf_section * section,
       size_t                    abbrev_size;
       dwarf_vma                 cu_offset;
       unsigned int              offset_size;
-      unsigned int              initial_length_size;
       struct cu_tu_set *        this_set;
       abbrev_list *             list;
+      unsigned char *end_cu;
 
       hdrptr = start;
+      cu_offset = start - section_begin;
 
       SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 4, end);
 
@@ -3559,17 +3553,12 @@ process_debug_info (struct dwarf_section * section,
        {
          SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 8, end);
          offset_size = 8;
-         initial_length_size = 12;
        }
       else
-       {
-         offset_size = 4;
-         initial_length_size = 4;
-       }
+       offset_size = 4;
+      end_cu = hdrptr + compunit.cu_length;
 
-      SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end);
-
-      cu_offset = start - section_begin;
+      SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end_cu);
 
       this_set = find_cu_tu_set_v2 (cu_offset, do_types);
 
@@ -3581,19 +3570,20 @@ process_debug_info (struct dwarf_section * section,
        }
       else
        {
-         SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end);
+         SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end_cu);
          do_types = (compunit.cu_unit_type == DW_UT_type);
 
-         SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end);
+         SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end_cu);
        }
 
-      SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size, end);
+      SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size,
+                            end_cu);
 
       if (compunit.cu_unit_type == DW_UT_split_compile
          || compunit.cu_unit_type == DW_UT_skeleton)
        {
          uint64_t dwo_id;
-         SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, end);
+         SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, end_cu);
        }
 
       if (this_set == NULL)
@@ -3621,8 +3611,7 @@ process_debug_info (struct dwarf_section * section,
          list->start_of_next_abbrevs = next;
        }
 
-      start = section_begin + cu_offset + compunit.cu_length
-       + initial_length_size;
+      start = end_cu;
       record_abbrev_list_for_cu (cu_offset, start - section_begin, list);
     }
 
@@ -3633,17 +3622,17 @@ process_debug_info (struct dwarf_section * section,
       unsigned char *tags;
       int level, last_level, saved_level;
       dwarf_vma cu_offset;
-      unsigned long sec_off;
       unsigned int offset_size;
-      unsigned int initial_length_size;
       dwarf_vma signature = 0;
       dwarf_vma type_offset = 0;
       struct cu_tu_set *this_set;
       dwarf_vma abbrev_base;
       size_t abbrev_size;
       abbrev_list * list = NULL;
+      unsigned char *end_cu;
 
       hdrptr = start;
+      cu_offset = start - section_begin;
 
       SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 4, end);
 
@@ -3651,17 +3640,12 @@ process_debug_info (struct dwarf_section * section,
        {
          SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 8, end);
          offset_size = 8;
-         initial_length_size = 12;
        }
       else
-       {
-         offset_size = 4;
-         initial_length_size = 4;
-       }
-
-      SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end);
+       offset_size = 4;
+      end_cu = hdrptr + compunit.cu_length;
 
-      cu_offset = start - section_begin;
+      SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end_cu);
 
       this_set = find_cu_tu_set_v2 (cu_offset, do_types);
 
@@ -3673,13 +3657,13 @@ process_debug_info (struct dwarf_section * section,
        }
       else
        {
-         SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end);
+         SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end_cu);
          do_types = (compunit.cu_unit_type == DW_UT_type);
 
-         SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end);
+         SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end_cu);
        }
 
-      SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size, end);
+      SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size, end_cu);
 
       if (this_set == NULL)
        {
@@ -3693,14 +3677,14 @@ process_debug_info (struct dwarf_section * section,
        }
 
       if (compunit.cu_version < 5)
-       SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end);
+       SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end_cu);
 
       bool do_dwo_id = false;
       uint64_t dwo_id = 0;
       if (compunit.cu_unit_type == DW_UT_split_compile
          || compunit.cu_unit_type == DW_UT_skeleton)
        {
-         SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, end);
+         SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, end_cu);
          do_dwo_id = true;
        }
 
@@ -3714,15 +3698,13 @@ process_debug_info (struct dwarf_section * section,
 
       if (do_types)
        {
-         SAFE_BYTE_GET_AND_INC (signature, hdrptr, 8, end);
-         SAFE_BYTE_GET_AND_INC (type_offset, hdrptr, offset_size, end);
+         SAFE_BYTE_GET_AND_INC (signature, hdrptr, 8, end_cu);
+         SAFE_BYTE_GET_AND_INC (type_offset, hdrptr, offset_size, end_cu);
        }
 
-      if (dwarf_start_die > (cu_offset + compunit.cu_length
-                            + initial_length_size))
+      if (dwarf_start_die >= (size_t) (end_cu - section_begin))
        {
-         start = section_begin + cu_offset + compunit.cu_length
-           + initial_length_size;
+         start = end_cu;
          continue;
        }
 
@@ -3797,20 +3779,8 @@ process_debug_info (struct dwarf_section * section,
            }
        }
 
-      sec_off = cu_offset + initial_length_size;
-      if (sec_off + compunit.cu_length < sec_off
-         || sec_off + compunit.cu_length > section->size)
-       {
-         warn (_("Debug info is corrupted, %s header at %#lx has length %s\n"),
-               section->name,
-               (unsigned long) cu_offset,
-               dwarf_vmatoa ("x", compunit.cu_length));
-         num_units = unit;
-         break;
-       }
-
       tags = hdrptr;
-      start += compunit.cu_length + initial_length_size;
+      start = end_cu;
 
       if (compunit.cu_version < 2 || compunit.cu_version > 5)
        {
@@ -3984,7 +3954,7 @@ process_debug_info (struct dwarf_section * section,
                                            attr->implicit_const,
                                            section_begin,
                                            tags,
-                                           end,
+                                           start,
                                            cu_offset,
                                            compunit.cu_pointer_size,
                                            offset_size,
@@ -4091,7 +4061,6 @@ read_debug_line_header (struct dwarf_section * section,
                        unsigned char ** end_of_sequence)
 {
   unsigned char *hdrptr;
-  unsigned int initial_length_size;
 
   /* Extract information from the Line Number Program Header.
      (section 6.2.4 in the Dwarf3 doc).  */
@@ -4105,15 +4074,11 @@ read_debug_line_header (struct dwarf_section * section,
       /* This section is 64-bit DWARF 3.  */
       SAFE_BYTE_GET_AND_INC (linfo->li_length, hdrptr, 8, end);
       linfo->li_offset_size = 8;
-      initial_length_size = 12;
     }
   else
-    {
-      linfo->li_offset_size = 4;
-      initial_length_size = 4;
-    }
+    linfo->li_offset_size = 4;
 
-  if (linfo->li_length + initial_length_size > section->size)
+  if (linfo->li_length > (size_t) (end - hdrptr))
     {
       /* If the length field has a relocation against it, then we should
         not complain if it is inaccurate (and probably negative).  This
@@ -4123,7 +4088,7 @@ read_debug_line_header (struct dwarf_section * section,
         is used to compute the correct length once that is done.  */
       if (reloc_at (section, (hdrptr - section->start) - linfo->li_offset_size))
        {
-         linfo->li_length = (end - data) - initial_length_size;
+         linfo->li_length = end - hdrptr;
        }
       else
        {
@@ -4132,6 +4097,7 @@ read_debug_line_header (struct dwarf_section * section,
          return NULL;
        }
     }
+  end = hdrptr + linfo->li_length;
 
   /* Get and check the version number.  */
   SAFE_BYTE_GET_AND_INC (linfo->li_version, hdrptr, 2, end);
@@ -4182,16 +4148,7 @@ read_debug_line_header (struct dwarf_section * section,
   SAFE_BYTE_GET_AND_INC (linfo->li_line_range, hdrptr, 1, end);
   SAFE_BYTE_GET_AND_INC (linfo->li_opcode_base, hdrptr, 1, end);
 
-  * end_of_sequence = data + linfo->li_length + initial_length_size;
-  /* PR 17512: file:002-117414-0.004.  */
-  if (* end_of_sequence > end)
-    {
-      warn (_("Line length %s extends beyond end of section\n"),
-           dwarf_vmatoa ("u", linfo->li_length));
-      * end_of_sequence = end;
-      return NULL;
-    }
-
+  *end_of_sequence = end;
   return hdrptr;
 }
 
@@ -4519,7 +4476,9 @@ display_debug_lines_raw (struct dwarf_section *  section,
                    {
                      printf ("  %d\t%.*s\n", ++last_dir_entry, (int) (end - data), data);
 
-                     data += strnlen ((char *) data, end - data) + 1;
+                     data += strnlen ((char *) data, end - data);
+                     if (data < end)
+                       data++;
                    }
 
                  /* PR 17512: file: 002-132094-0.004.  */
@@ -4528,10 +4487,11 @@ display_debug_lines_raw (struct dwarf_section *  section,
                }
 
              /* Skip the NUL at the end of the table.  */
-             data++;
+             if (data < end)
+               data++;
 
              /* Display the contents of the File Name table.  */
-             if (*data == 0)
+             if (data >= end || *data == 0)
                printf (_("\n The File Name Table is empty.\n"));
              else
                {
@@ -4546,7 +4506,9 @@ display_debug_lines_raw (struct dwarf_section *  section,
 
                      printf ("  %d\t", ++state_machine_regs.last_file_entry);
                      name = data;
-                     data += strnlen ((char *) data, end - data) + 1;
+                     data += strnlen ((char *) data, end - data);
+                     if (data < end)
+                       data++;
 
                      READ_ULEB (val, data, end);
                      printf ("%s\t", dwarf_vmatoa ("u", val));
@@ -4565,7 +4527,8 @@ display_debug_lines_raw (struct dwarf_section *  section,
                }
 
              /* Skip the NUL at the end of the table.  */
-             data++;
+             if (data < end)
+               data++;
            }
 
          putchar ('\n');
@@ -5065,7 +5028,9 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 
                  while (data < end && *data != 0)
                    {
-                     data += strnlen ((char *) data, end - data) + 1;
+                     data += strnlen ((char *) data, end - data);
+                     if (data < end)
+                       data++;
                      n_directories++;
                    }
 
@@ -5085,8 +5050,8 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                  while (*ptr_directory_table != 0)
                    {
                      directory_table[i] = ptr_directory_table;
-                     ptr_directory_table += strnlen ((char *) ptr_directory_table,
-                                                     ptr_directory_table - end) + 1;
+                     ptr_directory_table
+                       += strlen ((char *) ptr_directory_table) + 1;
                      i++;
                    }
                }
@@ -5102,7 +5067,9 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                    {
                      /* Skip Name, directory index, last modification
                         time and length of file.  */
-                     data += strnlen ((char *) data, end - data) + 1;
+                     data += strnlen ((char *) data, end - data);
+                     if (data < end)
+                       data++;
                      SKIP_ULEB (data, end);
                      SKIP_ULEB (data, end);
                      SKIP_ULEB (data, end);
@@ -5123,8 +5090,8 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                  while (*ptr_file_name_table != 0)
                    {
                      file_table[i].name = ptr_file_name_table;
-                     ptr_file_name_table += strnlen ((char *) ptr_file_name_table,
-                                                     end - ptr_file_name_table) + 1;
+                     ptr_file_name_table
+                       += strlen ((char *) ptr_file_name_table) + 1;
 
                      /* We are not interested in directory, time or size.  */
                      READ_ULEB (file_table[i].directory_index,
@@ -5459,31 +5426,22 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                fileName = _("<unknown>");
 
              fileNameLength = strlen (fileName);
-
-             if ((fileNameLength > MAX_FILENAME_LENGTH) && (!do_wide))
+             newFileName = fileName;
+             if (fileNameLength > MAX_FILENAME_LENGTH && !do_wide)
                {
                  newFileName = (char *) xmalloc (MAX_FILENAME_LENGTH + 1);
                  /* Truncate file name */
-                 strncpy (newFileName,
-                          fileName + fileNameLength - MAX_FILENAME_LENGTH,
-                          MAX_FILENAME_LENGTH + 1);
-                 /* FIXME: This is to pacify gcc-10 which can warn that the
-                    strncpy above might leave a non-NUL terminated string
-                    in newFileName.  It won't, but gcc's analysis doesn't
-                    quite go far enough to discover this.  */
+                 memcpy (newFileName,
+                         fileName + fileNameLength - MAX_FILENAME_LENGTH,
+                         MAX_FILENAME_LENGTH);
                  newFileName[MAX_FILENAME_LENGTH] = 0;
                }
-             else
-               {
-                 newFileName = (char *) xmalloc (fileNameLength + 1);
-                 strncpy (newFileName, fileName, fileNameLength + 1);
-               }
 
              /* A row with end_seq set to true has a meaningful address, but
                 the other information in the same row is not significant.
                 In such a row, print line as "-", and don't print
                 view/is_stmt.  */
-             if (!do_wide || (fileNameLength <= MAX_FILENAME_LENGTH))
+             if (!do_wide || fileNameLength <= MAX_FILENAME_LENGTH)
                {
                  if (linfo.li_max_ops_per_insn == 1)
                    {
@@ -5558,7 +5516,8 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                  putchar ('\n');
                }
 
-             free (newFileName);
+             if (newFileName != fileName)
+               free (newFileName);
            }
        }
 
@@ -5657,29 +5616,23 @@ display_debug_pubnames_worker (struct dwarf_section *section,
   while (start < end)
     {
       unsigned char *data;
-      unsigned long sec_off;
-      unsigned int offset_size, initial_length_size;
+      unsigned long sec_off = start - section->start;
+      unsigned int offset_size;
 
       SAFE_BYTE_GET_AND_INC (names.pn_length, start, 4, end);
       if (names.pn_length == 0xffffffff)
        {
          SAFE_BYTE_GET_AND_INC (names.pn_length, start, 8, end);
          offset_size = 8;
-         initial_length_size = 12;
        }
       else
-       {
-         offset_size = 4;
-         initial_length_size = 4;
-       }
+       offset_size = 4;
 
-      sec_off = start - section->start;
-      if (sec_off + names.pn_length < sec_off
-         || sec_off + names.pn_length > section->size)
+      if (names.pn_length > (size_t) (end - start))
        {
          warn (_("Debug info is corrupted, %s header at %#lx has length %s\n"),
                section->name,
-               sec_off - initial_length_size,
+               sec_off,
                dwarf_vmatoa ("x", names.pn_length));
          break;
        }
@@ -5687,8 +5640,8 @@ display_debug_pubnames_worker (struct dwarf_section *section,
       data = start;
       start += names.pn_length;
 
-      SAFE_BYTE_GET_AND_INC (names.pn_version, data, 2, end);
-      SAFE_BYTE_GET_AND_INC (names.pn_offset, data, offset_size, end);
+      SAFE_BYTE_GET_AND_INC (names.pn_version, data, 2, start);
+      SAFE_BYTE_GET_AND_INC (names.pn_offset, data, offset_size, start);
 
       if (num_debug_info_entries != DEBUG_INFO_UNAVAILABLE
          && num_debug_info_entries > 0
@@ -5696,7 +5649,7 @@ display_debug_pubnames_worker (struct dwarf_section *section,
        warn (_(".debug_info offset of 0x%lx in %s section does not point to a CU header.\n"),
              (unsigned long) names.pn_offset, section->name);
 
-      SAFE_BYTE_GET_AND_INC (names.pn_size, data, offset_size, end);
+      SAFE_BYTE_GET_AND_INC (names.pn_size, data, offset_size, start);
 
       printf (_("  Length:                              %ld\n"),
              (long) names.pn_length);
@@ -5730,15 +5683,14 @@ display_debug_pubnames_worker (struct dwarf_section *section,
          bfd_size_type maxprint;
          dwarf_vma offset;
 
-         SAFE_BYTE_GET (offset, data, offset_size, end);
+         SAFE_BYTE_GET_AND_INC (offset, data, offset_size, start);
 
          if (offset == 0)
            break;
 
-         data += offset_size;
-         if (data >= end)
+         if (data >= start)
            break;
-         maxprint = (end - data) - 1;
+         maxprint = (start - data) - 1;
 
          if (is_gnu)
            {
@@ -5747,8 +5699,7 @@ display_debug_pubnames_worker (struct dwarf_section *section,
              const char *kind_name;
              int is_static;
 
-             SAFE_BYTE_GET (kind_data, data, 1, end);
-             data++;
+             SAFE_BYTE_GET_AND_INC (kind_data, data, 1, start);
              maxprint --;
              /* GCC computes the kind as the upper byte in the CU index
                 word, and then right shifts it by the CU index size.
@@ -5766,8 +5717,10 @@ display_debug_pubnames_worker (struct dwarf_section *section,
            printf ("    %-6lx\t%.*s\n",
                    (unsigned long) offset, (int) maxprint, data);
 
-         data += strnlen ((char *) data, maxprint) + 1;
-         if (data >= end)
+         data += strnlen ((char *) data, maxprint);
+         if (data < start)
+           data++;
+         if (data >= start)
            break;
        }
     }
@@ -5827,17 +5780,21 @@ display_debug_macinfo (struct dwarf_section *section,
        case DW_MACINFO_define:
          READ_ULEB (lineno, curr, end);
          string = curr;
-         curr += strnlen ((char *) string, end - string) + 1;
-         printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"),
-                 lineno, string);
+         curr += strnlen ((char *) string, end - string);
+         printf (_(" DW_MACINFO_define - lineno : %d macro : %*s\n"),
+                 lineno, (int) (curr - string), string);
+         if (curr < end)
+           curr++;
          break;
 
        case DW_MACINFO_undef:
          READ_ULEB (lineno, curr, end);
          string = curr;
-         curr += strnlen ((char *) string, end - string) + 1;
-         printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"),
-                 lineno, string);
+         curr += strnlen ((char *) string, end - string);
+         printf (_(" DW_MACINFO_undef - lineno : %d macro : %*s\n"),
+                 lineno, (int) (curr - string), string);
+         if (curr < end)
+           curr++;
          break;
 
        case DW_MACINFO_vendor_ext:
@@ -5846,9 +5803,11 @@ display_debug_macinfo (struct dwarf_section *section,
 
            READ_ULEB (constant, curr, end);
            string = curr;
-           curr += strnlen ((char *) string, end - string) + 1;
-           printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"),
-                   constant, string);
+           curr += strnlen ((char *) string, end - string);
+           printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %*s\n"),
+                   constant, (int) (curr - string), string);
+           if (curr < end)
+             curr++;
          }
          break;
        }
@@ -5868,7 +5827,7 @@ get_line_filename_and_dirname (dwarf_vma line_offset,
 {
   struct dwarf_section *section = &debug_displays [line].section;
   unsigned char *hdrptr, *dirtable, *file_name;
-  unsigned int offset_size, initial_length_size;
+  unsigned int offset_size;
   unsigned int version, opcode_base;
   dwarf_vma length, diridx;
   const unsigned char * end;
@@ -5888,16 +5847,14 @@ get_line_filename_and_dirname (dwarf_vma line_offset,
       /* This section is 64-bit DWARF 3.  */
       SAFE_BYTE_GET_AND_INC (length, hdrptr, 8, end);
       offset_size = 8;
-      initial_length_size = 12;
     }
   else
-    {
-      offset_size = 4;
-      initial_length_size = 4;
-    }
-  if (length + initial_length_size < length
-      || length + initial_length_size > section->size)
+    offset_size = 4;
+
+  if (length > (size_t) (end - hdrptr)
+      || length < 2 + offset_size + 1 + 3 + 1)
     return NULL;
+  end = hdrptr + length;
 
   SAFE_BYTE_GET_AND_INC (version, hdrptr, 2, end);
   if (version != 2 && version != 3 && version != 4)
@@ -5908,18 +5865,19 @@ get_line_filename_and_dirname (dwarf_vma line_offset,
   hdrptr += 3;             /* Skip default_is_stmt, line_base, line_range.  */
 
   SAFE_BYTE_GET_AND_INC (opcode_base, hdrptr, 1, end);
-  if (opcode_base == 0)
+  if (opcode_base == 0
+      || opcode_base - 1 >= (size_t) (end - hdrptr))
     return NULL;
 
   hdrptr += opcode_base - 1;
-  if (hdrptr >= end)
-    return NULL;
 
   dirtable = hdrptr;
   /* Skip over dirname table.  */
   while (*hdrptr != '\0')
     {
-      hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
+      hdrptr += strnlen ((char *) hdrptr, end - hdrptr);
+      if (hdrptr < end)
+       hdrptr++;
       if (hdrptr >= end)
        return NULL;
     }
@@ -5928,7 +5886,9 @@ get_line_filename_and_dirname (dwarf_vma line_offset,
   /* Now skip over preceding filename table entries.  */
   for (; hdrptr < end && *hdrptr != '\0' && fileidx > 1; fileidx--)
     {
-      hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
+      hdrptr += strnlen ((char *) hdrptr, end - hdrptr);
+      if (hdrptr < end)
+       hdrptr++;
       SKIP_ULEB (hdrptr, end);
       SKIP_ULEB (hdrptr, end);
       SKIP_ULEB (hdrptr, end);
@@ -5937,14 +5897,20 @@ get_line_filename_and_dirname (dwarf_vma line_offset,
     return NULL;
 
   file_name = hdrptr;
-  hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
+  hdrptr += strnlen ((char *) hdrptr, end - hdrptr);
+  if (hdrptr < end)
+    hdrptr++;
   if (hdrptr >= end)
     return NULL;
   READ_ULEB (diridx, hdrptr, end);
   if (diridx == 0)
     return file_name;
   for (; dirtable < end && *dirtable != '\0' && diridx > 1; diridx--)
-    dirtable += strnlen ((char *) dirtable, end - dirtable) + 1;
+    {
+      dirtable += strnlen ((char *) dirtable, end - dirtable);
+      if (dirtable < end)
+       dirtable++;
+    }
   if (dirtable >= end || *dirtable == '\0')
     return NULL;
   *dir_name = dirtable;
@@ -6076,17 +6042,21 @@ display_debug_macro (struct dwarf_section *section,
            case DW_MACRO_define:
              READ_ULEB (lineno, curr, end);
              string = curr;
-             curr += strnlen ((char *) string, end - string) + 1;
-             printf (_(" DW_MACRO_define - lineno : %d macro : %s\n"),
-                     lineno, string);
+             curr += strnlen ((char *) string, end - string);
+             printf (_(" DW_MACRO_define - lineno : %d macro : %*s\n"),
+                     lineno, (int) (curr - string), string);
+             if (curr < end)
+               curr++;
              break;
 
            case DW_MACRO_undef:
              READ_ULEB (lineno, curr, end);
              string = curr;
-             curr += strnlen ((char *) string, end - string) + 1;
-             printf (_(" DW_MACRO_undef - lineno : %d macro : %s\n"),
-                     lineno, string);
+             curr += strnlen ((char *) string, end - string);
+             printf (_(" DW_MACRO_undef - lineno : %d macro : %*s\n"),
+                     lineno, (int) (curr - string), string);
+             if (curr < end)
+               curr++;
              break;
 
            case DW_MACRO_start_file:
@@ -6277,7 +6247,7 @@ display_debug_abbrev (struct dwarf_section *section,
                      get_AT_name (attr->attribute),
                      get_FORM_name (attr->form));
              if (attr->form == DW_FORM_implicit_const)
-               printf (": %" BFD_VMA_FMT "d", attr->implicit_const);
+               printf (": %s", dwarf_vmatoa ("d", attr->implicit_const));
              putchar ('\n');
            }
        }
@@ -6385,7 +6355,7 @@ display_loc_list (struct dwarf_section *section,
       dwarf_vma off = offset + (start - *start_ptr);
       dwarf_vma vbegin = vm1, vend = vm1;
 
-      if (start + 2 * pointer_size > section_end)
+      if (2 * pointer_size > (size_t) (section_end - start))
        {
          warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
                (unsigned long) offset);
@@ -6438,7 +6408,7 @@ display_loc_list (struct dwarf_section *section,
                  (unsigned long) off, 8, "");
        }
 
-      if (start + 2 > section_end)
+      if (2 > (size_t) (section_end - start))
        {
          warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
                (unsigned long) offset);
@@ -6447,7 +6417,7 @@ display_loc_list (struct dwarf_section *section,
 
       SAFE_BYTE_GET_AND_INC (length, start, 2, section_end);
 
-      if (start + length > section_end)
+      if (length > (size_t) (section_end - start))
        {
          warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
                (unsigned long) offset);
@@ -6609,15 +6579,21 @@ display_loclists_list (struct dwarf_section *section,
          && llet != DW_LLE_start_length)
        continue;
 
-      if (start + 2 > section_end)
+      if (start == section_end)
        {
          warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
                (unsigned long) offset);
          break;
        }
-
       READ_ULEB (length, start, section_end);
 
+      if (length > (size_t) (section_end - start))
+       {
+         warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
+               (unsigned long) offset);
+         break;
+       }
+
       print_dwarf_vma (begin, pointer_size);
       print_dwarf_vma (end, pointer_size);
 
@@ -6781,7 +6757,7 @@ display_loc_list_dwo (struct dwarf_section *section,
          return;
        }
 
-      if (start + 2 > section_end)
+      if (2 > (size_t) (section_end - start))
        {
          warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
                (unsigned long) offset);
@@ -6789,7 +6765,7 @@ display_loc_list_dwo (struct dwarf_section *section,
        }
 
       SAFE_BYTE_GET_AND_INC (length, start, 2, section_end);
-      if (start + length > section_end)
+      if (length > (size_t) (section_end - start))
        {
          warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
                (unsigned long) offset);
@@ -7211,36 +7187,33 @@ display_debug_aranges (struct dwarf_section *section,
       unsigned char address_size;
       int excess;
       unsigned int offset_size;
-      unsigned int initial_length_size;
+      unsigned char *end_ranges;
 
       hdrptr = start;
+      sec_off = hdrptr - section->start;
 
       SAFE_BYTE_GET_AND_INC (arange.ar_length, hdrptr, 4, end);
       if (arange.ar_length == 0xffffffff)
        {
          SAFE_BYTE_GET_AND_INC (arange.ar_length, hdrptr, 8, end);
          offset_size = 8;
-         initial_length_size = 12;
        }
       else
-       {
-         offset_size = 4;
-         initial_length_size = 4;
-       }
+       offset_size = 4;
 
-      sec_off = hdrptr - section->start;
-      if (sec_off + arange.ar_length < sec_off
-         || sec_off + arange.ar_length > section->size)
+      if (arange.ar_length > (size_t) (end - hdrptr))
        {
          warn (_("Debug info is corrupted, %s header at %#lx has length %s\n"),
                section->name,
-               sec_off - initial_length_size,
+               sec_off,
                dwarf_vmatoa ("x", arange.ar_length));
          break;
        }
+      end_ranges = hdrptr + arange.ar_length;
 
-      SAFE_BYTE_GET_AND_INC (arange.ar_version, hdrptr, 2, end);
-      SAFE_BYTE_GET_AND_INC (arange.ar_info_offset, hdrptr, offset_size, end);
+      SAFE_BYTE_GET_AND_INC (arange.ar_version, hdrptr, 2, end_ranges);
+      SAFE_BYTE_GET_AND_INC (arange.ar_info_offset, hdrptr, offset_size,
+                            end_ranges);
 
       if (num_debug_info_entries != DEBUG_INFO_UNAVAILABLE
          && num_debug_info_entries > 0
@@ -7248,8 +7221,8 @@ display_debug_aranges (struct dwarf_section *section,
        warn (_(".debug_info offset of 0x%lx in %s section does not point to a CU header.\n"),
              (unsigned long) arange.ar_info_offset, section->name);
 
-      SAFE_BYTE_GET_AND_INC (arange.ar_pointer_size, hdrptr, 1, end);
-      SAFE_BYTE_GET_AND_INC (arange.ar_segment_size, hdrptr, 1, end);
+      SAFE_BYTE_GET_AND_INC (arange.ar_pointer_size, hdrptr, 1, end_ranges);
+      SAFE_BYTE_GET_AND_INC (arange.ar_segment_size, hdrptr, 1, end_ranges);
 
       if (arange.ar_version != 2 && arange.ar_version != 3)
        {
@@ -7301,12 +7274,12 @@ display_debug_aranges (struct dwarf_section *section,
       if (excess)
        addr_ranges += (2 * address_size) - excess;
 
-      start += arange.ar_length + initial_length_size;
+      start = end_ranges;
 
-      while (addr_ranges + 2 * address_size <= start)
+      while (2u * address_size <= (size_t) (start - addr_ranges))
        {
-         SAFE_BYTE_GET_AND_INC (address, addr_ranges, address_size, end);
-         SAFE_BYTE_GET_AND_INC (length, addr_ranges, address_size, end);
+         SAFE_BYTE_GET_AND_INC (address, addr_ranges, address_size, start);
+         SAFE_BYTE_GET_AND_INC (length, addr_ranges, address_size, start);
 
          printf ("    ");
          print_dwarf_vma (address, address_size);
@@ -7408,7 +7381,7 @@ display_debug_addr (struct dwarf_section *section,
 
          SAFE_BYTE_GET_AND_INC (length, curr_header, 4, entry);
          if (length == 0xffffffff)
-           SAFE_BYTE_GET (length, curr_header, 8, entry);
+           SAFE_BYTE_GET_AND_INC (length, curr_header, 8, entry);
          end = curr_header + length;
 
          SAFE_BYTE_GET_AND_INC (version, curr_header, 2, entry);
@@ -7477,7 +7450,7 @@ display_debug_str_offsets (struct dwarf_section *section,
       /* FIXME: We assume that this means 64-bit DWARF is being used.  */
       if (length == 0xffffffff)
        {
-         SAFE_BYTE_GET (length, curr, 8, end);
+         SAFE_BYTE_GET_AND_INC (length, curr, 8, end);
          entry_length = 8;
        }
       else
@@ -7497,15 +7470,22 @@ display_debug_str_offsets (struct dwarf_section *section,
        }
       else
        {
-         entries_end = curr + length;
+         if (length <= (dwarf_vma) (end - curr))
+           entries_end = curr + length;
+         else
+           {
+             warn (_("Section %s is too small %#lx\n"),
+                   section->name, (unsigned long) section->size);
+             entries_end = end;
+           }
 
          int version;
-         SAFE_BYTE_GET_AND_INC (version, curr, 2, end);
+         SAFE_BYTE_GET_AND_INC (version, curr, 2, entries_end);
          if (version != 5)
            warn (_("Unexpected version number in str_offset header: %#x\n"), version);
 
          int padding;
-         SAFE_BYTE_GET_AND_INC (padding, curr, 2, end);
+         SAFE_BYTE_GET_AND_INC (padding, curr, 2, entries_end);
          if (padding != 0)
            warn (_("Unexpected value in str_offset header's padding field: %#x\n"), padding);
 
@@ -7519,11 +7499,11 @@ display_debug_str_offsets (struct dwarf_section *section,
          dwarf_vma offset;
          const unsigned char * string;
 
-         if (curr + entry_length > entries_end)
+         if ((dwarf_vma) (entries_end - curr) < entry_length)
            /* Not enough space to read one entry_length, give up.  */
            return 0;
 
-         SAFE_BYTE_GET_AND_INC (offset, curr, entry_length, end);
+         SAFE_BYTE_GET_AND_INC (offset, curr, entry_length, entries_end);
          if (dwo)
            string = (const unsigned char *)
              fetch_indexed_string (idx, NULL, entry_length, dwo);
@@ -7623,7 +7603,7 @@ display_debug_rnglists_list (unsigned char *start, unsigned char *finish,
       /* Initialize it due to a false compiler warning.  */
       dwarf_vma begin = -1, length, end = -1;
 
-      if (start + 1 > finish)
+      if (start >= finish)
        {
          warn (_("Range list starting at offset 0x%lx is not terminated.\n"),
                offset);
@@ -7711,7 +7691,6 @@ display_debug_ranges (struct dwarf_section *section,
   if (is_rnglists)
     {
       dwarf_vma initial_length;
-      unsigned int initial_length_size;
       unsigned char segment_selector_size;
       unsigned int offset_size, offset_entry_count;
       unsigned short version;
@@ -7724,22 +7703,18 @@ display_debug_ranges (struct dwarf_section *section,
          /* This section is 64-bit DWARF 3.  */
          SAFE_BYTE_GET_AND_INC (initial_length, start, 8, finish);
          offset_size = 8;
-         initial_length_size = 12;
        }
       else
-       {
-         offset_size = 4;
-         initial_length_size = 4;
-       }
+       offset_size = 4;
 
-      if (initial_length + initial_length_size > section->size)
+      if (initial_length > (size_t) (finish - start))
        {
          /* If the length field has a relocation against it, then we should
             not complain if it is inaccurate (and probably negative).
             It is copied from .debug_line handling code.  */
          if (reloc_at (section, (start - section->start) - offset_size))
            {
-             initial_length = (finish - start) - initial_length_size;
+             initial_length = finish - start;
            }
          else
            {
@@ -7748,6 +7723,7 @@ display_debug_ranges (struct dwarf_section *section,
              return 0;
            }
        }
+      finish = start + initial_length;
 
       /* Get and check the version number.  */
       SAFE_BYTE_GET_AND_INC (version, start, 2, finish);
@@ -7853,7 +7829,6 @@ display_debug_ranges (struct dwarf_section *section,
 
       pointer_size = (is_rnglists ? address_size : debug_info_p->pointer_size);
       offset = range_entry->ranges_offset;
-      next = section_begin + offset;
       base_address = debug_info_p->base_address;
 
       /* PR 17512: file: 001-101485-0.001:0.1.  */
@@ -7864,12 +7839,13 @@ display_debug_ranges (struct dwarf_section *section,
          continue;
        }
 
-      if (next < section_begin || next >= finish)
+      if (offset > (size_t) (finish - section_begin))
        {
          warn (_("Corrupt offset (%#8.8lx) in range entry %u\n"),
                (unsigned long) offset, i);
          continue;
        }
+      next = section_begin + offset;
 
       /* If multiple DWARF entities reference the same range then we will
          have multiple entries in the `range_entries' list for the same
@@ -8433,10 +8409,16 @@ read_cie (unsigned char *start, unsigned char *end,
     }
 
   if (strcmp (fc->augmentation, "eh") == 0)
-    start += eh_addr_size;
+    {
+      if (eh_addr_size > (size_t) (end - start))
+       goto fail;
+      start += eh_addr_size;
+    }
 
   if (version >= 4)
     {
+      if (2 > (size_t) (end - start))
+       goto fail;
       GET (fc->ptr_size, 1);
       if (fc->ptr_size < 1 || fc->ptr_size > 8)
        {
@@ -8463,6 +8445,9 @@ read_cie (unsigned char *start, unsigned char *end,
   READ_ULEB (fc->code_factor, start, end);
   READ_SLEB (fc->data_factor, start, end);
 
+  if (start >= end)
+    goto fail;
+
   if (version == 1)
     {
       GET (fc->ra, 1);
@@ -8474,6 +8459,8 @@ read_cie (unsigned char *start, unsigned char *end,
 
   if (fc->augmentation[0] == 'z')
     {
+      if (start >= end)
+       goto fail;
       READ_ULEB (augmentation_data_len, start, end);
       augmentation_data = start;
       /* PR 17512: file: 11042-2589-0.004.  */
@@ -8600,7 +8587,6 @@ display_debug_frames (struct dwarf_section *section,
       bfd_size_type augmentation_data_len = 0;
       unsigned int encoded_ptr_size = saved_eh_addr_size;
       unsigned int offset_size;
-      unsigned int initial_length_size;
       bool all_nops;
       static Frame_Chunk fde_fc;
 
@@ -8625,24 +8611,21 @@ display_debug_frames (struct dwarf_section *section,
        {
          SAFE_BYTE_GET_AND_INC (length, start, 8, end);
          offset_size = 8;
-         initial_length_size = 12;
        }
       else
-       {
-         offset_size = 4;
-         initial_length_size = 4;
-       }
+       offset_size = 4;
 
-      block_end = saved_start + length + initial_length_size;
-      if (block_end > end || block_end < start)
+      if (length > (size_t) (end - start))
        {
          warn ("Invalid length 0x%s in FDE at %#08lx\n",
                dwarf_vmatoa_1 (NULL, length, offset_size),
                (unsigned long) (saved_start - section_start));
          block_end = end;
        }
+      else
+       block_end = start + length;
 
-      SAFE_BYTE_GET_AND_INC (cie_id, start, offset_size, end);
+      SAFE_BYTE_GET_AND_INC (cie_id, start, offset_size, block_end);
 
       if (is_eh ? (cie_id == 0) : ((offset_size == 4 && cie_id == DW_CIE_ID)
                                   || (offset_size == 8 && cie_id == DW64_CIE_ID)))
@@ -8650,7 +8633,7 @@ display_debug_frames (struct dwarf_section *section,
          int version;
          unsigned int mreg;
 
-         start = read_cie (start, end, &cie, &version,
+         start = read_cie (start, block_end, &cie, &version,
                            &augmentation_data_len, &augmentation_data);
          /* PR 17512: file: 027-135133-0.005.  */
          if (cie == NULL)
@@ -8718,6 +8701,8 @@ display_debug_frames (struct dwarf_section *section,
                if (cie->chunk_start == look_for)
                  break;
            }
+         else if (cie_off >= section->size)
+           cie = NULL;
          else
            {
              for (cie = forward_refs; cie ; cie = cie->next)
@@ -8736,11 +8721,13 @@ display_debug_frames (struct dwarf_section *section,
                      SAFE_BYTE_GET_AND_INC (length, cie_scan, 8, end);
                      off_size = 8;
                    }
-                 if (length != 0)
+                 if (length != 0 && length <= (size_t) (end - cie_scan))
                    {
                      dwarf_vma c_id;
+                     unsigned char *cie_end = cie_scan + length;
 
-                     SAFE_BYTE_GET_AND_INC (c_id, cie_scan, off_size, end);
+                     SAFE_BYTE_GET_AND_INC (c_id, cie_scan, off_size,
+                                            cie_end);
                      if (is_eh
                          ? c_id == 0
                          : ((off_size == 4 && c_id == DW_CIE_ID)
@@ -8749,7 +8736,7 @@ display_debug_frames (struct dwarf_section *section,
                          int version;
                          unsigned int mreg;
 
-                         read_cie (cie_scan, end, &cie, &version,
+                         read_cie (cie_scan, cie_end, &cie, &version,
                                    &augmentation_data_len, &augmentation_data);
                          /* PR 17512: file: 3450-2098-0.004.  */
                          if (cie == NULL)
@@ -8834,29 +8821,32 @@ display_debug_frames (struct dwarf_section *section,
                  warn (_("Probably corrupt segment size: %d - using 4 instead\n"), fc->segment_size);
                  fc->segment_size = 4;
                }
-             SAFE_BYTE_GET_AND_INC (segment_selector, start, fc->segment_size, end);
+             SAFE_BYTE_GET_AND_INC (segment_selector, start,
+                                    fc->segment_size, block_end);
            }
 
-         fc->pc_begin = get_encoded_value (&start, fc->fde_encoding, section, end);
+         fc->pc_begin = get_encoded_value (&start, fc->fde_encoding, section,
+                                           block_end);
 
          /* FIXME: It appears that sometimes the final pc_range value is
             encoded in less than encoded_ptr_size bytes.  See the x86_64
             run of the "objcopy on compressed debug sections" test for an
             example of this.  */
-         SAFE_BYTE_GET_AND_INC (fc->pc_range, start, encoded_ptr_size, end);
+         SAFE_BYTE_GET_AND_INC (fc->pc_range, start, encoded_ptr_size,
+                                block_end);
 
          if (cie->augmentation[0] == 'z')
            {
-             READ_ULEB (augmentation_data_len, start, end);
+             READ_ULEB (augmentation_data_len, start, block_end);
              augmentation_data = start;
              /* PR 17512 file: 722-8446-0.004 and PR 22386.  */
-             if (augmentation_data_len > (bfd_size_type) (end - start))
+             if (augmentation_data_len > (bfd_size_type) (block_end - start))
                {
                  warn (_("Augmentation data too long: 0x%s, "
                          "expected at most %#lx\n"),
                        dwarf_vmatoa ("x", augmentation_data_len),
-                       (unsigned long) (end - start));
-                 start = end;
+                       (unsigned long) (block_end - start));
+                 start = block_end;
                  augmentation_data = NULL;
                  augmentation_data_len = 0;
                }
@@ -8900,7 +8890,6 @@ display_debug_frames (struct dwarf_section *section,
            {
              unsigned int reg, op, opa;
              unsigned long temp;
-             unsigned char * new_start;
 
              op = *start++;
              opa = op & 0x3f;
@@ -8914,7 +8903,7 @@ display_debug_frames (struct dwarf_section *section,
                case DW_CFA_advance_loc:
                  break;
                case DW_CFA_offset:
-                 SKIP_ULEB (start, end);
+                 SKIP_ULEB (start, block_end);
                  if (frame_need_space (fc, opa) >= 0)
                    fc->col_type[opa] = DW_CFA_undefined;
                  break;
@@ -8923,105 +8912,111 @@ display_debug_frames (struct dwarf_section *section,
                    fc->col_type[opa] = DW_CFA_undefined;
                  break;
                case DW_CFA_set_loc:
-                 start += encoded_ptr_size;
+                 if ((size_t) (block_end - start) < encoded_ptr_size)
+                   start = block_end;
+                 else
+                   start += encoded_ptr_size;
                  break;
                case DW_CFA_advance_loc1:
-                 start += 1;
+                 if ((size_t) (block_end - start) < 1)
+                   start = block_end;
+                 else
+                   start += 1;
                  break;
                case DW_CFA_advance_loc2:
-                 start += 2;
+                 if ((size_t) (block_end - start) < 2)
+                   start = block_end;
+                 else
+                   start += 2;
                  break;
                case DW_CFA_advance_loc4:
-                 start += 4;
+                 if ((size_t) (block_end - start) < 4)
+                   start = block_end;
+                 else
+                   start += 4;
                  break;
                case DW_CFA_offset_extended:
                case DW_CFA_val_offset:
-                 READ_ULEB (reg, start, end);
-                 SKIP_ULEB (start, end);
+                 READ_ULEB (reg, start, block_end);
+                 SKIP_ULEB (start, block_end);
                  if (frame_need_space (fc, reg) >= 0)
                    fc->col_type[reg] = DW_CFA_undefined;
                  break;
                case DW_CFA_restore_extended:
-                 READ_ULEB (reg, start, end);
+                 READ_ULEB (reg, start, block_end);
                  if (frame_need_space (fc, reg) >= 0)
                    fc->col_type[reg] = DW_CFA_undefined;
                  break;
                case DW_CFA_undefined:
-                 READ_ULEB (reg, start, end);
+                 READ_ULEB (reg, start, block_end);
                  if (frame_need_space (fc, reg) >= 0)
                    fc->col_type[reg] = DW_CFA_undefined;
                  break;
                case DW_CFA_same_value:
-                 READ_ULEB (reg, start, end);
+                 READ_ULEB (reg, start, block_end);
                  if (frame_need_space (fc, reg) >= 0)
                    fc->col_type[reg] = DW_CFA_undefined;
                  break;
                case DW_CFA_register:
-                 READ_ULEB (reg, start, end);
-                 SKIP_ULEB (start, end);
+                 READ_ULEB (reg, start, block_end);
+                 SKIP_ULEB (start, block_end);
                  if (frame_need_space (fc, reg) >= 0)
                    fc->col_type[reg] = DW_CFA_undefined;
                  break;
                case DW_CFA_def_cfa:
-                 SKIP_ULEB (start, end);
-                 SKIP_ULEB (start, end);
+                 SKIP_ULEB (start, block_end);
+                 SKIP_ULEB (start, block_end);
                  break;
                case DW_CFA_def_cfa_register:
-                 SKIP_ULEB (start, end);
+                 SKIP_ULEB (start, block_end);
                  break;
                case DW_CFA_def_cfa_offset:
-                 SKIP_ULEB (start, end);
+                 SKIP_ULEB (start, block_end);
                  break;
                case DW_CFA_def_cfa_expression:
-                 READ_ULEB (temp, start, end);
-                 new_start = start + temp;
-                 if (new_start < start)
-                   {
-                     warn (_("Corrupt CFA_def expression value: %lu\n"), temp);
-                     start = block_end;
-                   }
+                 READ_ULEB (temp, start, block_end);
+                 if ((size_t) (block_end - start) < temp)
+                   start = block_end;
                  else
-                   start = new_start;
+                   start += temp;
                  break;
                case DW_CFA_expression:
                case DW_CFA_val_expression:
-                 READ_ULEB (reg, start, end);
-                 READ_ULEB (temp, start, end);
-                 new_start = start + temp;
-                 if (new_start < start)
-                   {
-                     /* PR 17512: file:306-192417-0.005.  */
-                     warn (_("Corrupt CFA expression value: %lu\n"), temp);
-                     start = block_end;
-                   }
+                 READ_ULEB (reg, start, block_end);
+                 READ_ULEB (temp, start, block_end);
+                 if ((size_t) (block_end - start) < temp)
+                   start = block_end;
                  else
-                   start = new_start;
+                   start += temp;
                  if (frame_need_space (fc, reg) >= 0)
                    fc->col_type[reg] = DW_CFA_undefined;
                  break;
                case DW_CFA_offset_extended_sf:
                case DW_CFA_val_offset_sf:
-                 READ_ULEB (reg, start, end);
-                 SKIP_SLEB (start, end);
+                 READ_ULEB (reg, start, block_end);
+                 SKIP_SLEB (start, block_end);
                  if (frame_need_space (fc, reg) >= 0)
                    fc->col_type[reg] = DW_CFA_undefined;
                  break;
                case DW_CFA_def_cfa_sf:
-                 SKIP_ULEB (start, end);
-                 SKIP_SLEB (start, end);
+                 SKIP_ULEB (start, block_end);
+                 SKIP_SLEB (start, block_end);
                  break;
                case DW_CFA_def_cfa_offset_sf:
-                 SKIP_SLEB (start, end);
+                 SKIP_SLEB (start, block_end);
                  break;
                case DW_CFA_MIPS_advance_loc8:
-                 start += 8;
+                 if ((size_t) (block_end - start) < 8)
+                   start = block_end;
+                 else
+                   start += 8;
                  break;
                case DW_CFA_GNU_args_size:
-                 SKIP_ULEB (start, end);
+                 SKIP_ULEB (start, block_end);
                  break;
                case DW_CFA_GNU_negative_offset_extended:
-                 READ_ULEB (reg, start, end);
-                 SKIP_ULEB (start, end);
+                 READ_ULEB (reg, start, block_end);
+                 SKIP_ULEB (start, block_end);
                  if (frame_need_space (fc, reg) >= 0)
                    fc->col_type[reg] = DW_CFA_undefined;
                  break;
@@ -9039,7 +9034,6 @@ display_debug_frames (struct dwarf_section *section,
 
       while (start < block_end)
        {
-         unsigned char * tmp;
          unsigned op, opa;
          unsigned long ul, roffs;
          /* Note: It is tempting to use an unsigned long for 'reg' but there
@@ -9077,7 +9071,7 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_offset:
-             READ_ULEB (roffs, start, end);
+             READ_ULEB (roffs, start, block_end);
              if (opa >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
@@ -9115,7 +9109,8 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_set_loc:
-             vma = get_encoded_value (&start, fc->fde_encoding, section, block_end);
+             vma = get_encoded_value (&start, fc->fde_encoding, section,
+                                      block_end);
              if (do_debug_frames_interp)
                frame_display_row (fc, &need_col_headers, &max_regs);
              else
@@ -9125,7 +9120,7 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_advance_loc1:
-             SAFE_BYTE_GET_AND_INC (ofs, start, 1, end);
+             SAFE_BYTE_GET_AND_INC (ofs, start, 1, block_end);
              if (do_debug_frames_interp)
                frame_display_row (fc, &need_col_headers, &max_regs);
              else
@@ -9164,8 +9159,8 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_offset_extended:
-             READ_ULEB (reg, start, end);
-             READ_ULEB (roffs, start, end);
+             READ_ULEB (reg, start, block_end);
+             READ_ULEB (roffs, start, block_end);
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
@@ -9180,8 +9175,8 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_val_offset:
-             READ_ULEB (reg, start, end);
-             READ_ULEB (roffs, start, end);
+             READ_ULEB (reg, start, block_end);
+             READ_ULEB (roffs, start, block_end);
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
@@ -9196,7 +9191,7 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_restore_extended:
-             READ_ULEB (reg, start, end);
+             READ_ULEB (reg, start, block_end);
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
@@ -9218,7 +9213,7 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_undefined:
-             READ_ULEB (reg, start, end);
+             READ_ULEB (reg, start, block_end);
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
@@ -9232,7 +9227,7 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_same_value:
-             READ_ULEB (reg, start, end);
+             READ_ULEB (reg, start, block_end);
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
@@ -9246,8 +9241,8 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_register:
-             READ_ULEB (reg, start, end);
-             READ_ULEB (roffs, start, end);
+             READ_ULEB (reg, start, block_end);
+             READ_ULEB (roffs, start, block_end);
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
@@ -9310,8 +9305,8 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_def_cfa:
-             READ_ULEB (fc->cfa_reg, start, end);
-             READ_ULEB (fc->cfa_offset, start, end);
+             READ_ULEB (fc->cfa_reg, start, block_end);
+             READ_ULEB (fc->cfa_offset, start, block_end);
              fc->cfa_exp = 0;
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa: %s ofs %d\n",
@@ -9319,7 +9314,7 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_def_cfa_register:
-             READ_ULEB (fc->cfa_reg, start, end);
+             READ_ULEB (fc->cfa_reg, start, block_end);
              fc->cfa_exp = 0;
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa_register: %s\n",
@@ -9327,7 +9322,7 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_def_cfa_offset:
-             READ_ULEB (fc->cfa_offset, start, end);
+             READ_ULEB (fc->cfa_offset, start, block_end);
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa_offset: %d\n", (int) fc->cfa_offset);
              break;
@@ -9338,8 +9333,8 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_def_cfa_expression:
-             READ_ULEB (ul, start, end);
-             if (start >= block_end || ul > (unsigned long) (block_end - start))
+             READ_ULEB (ul, start, block_end);
+             if (ul > (size_t) (block_end - start))
                {
                  printf (_("  DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
                  break;
@@ -9356,14 +9351,13 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_expression:
-             READ_ULEB (reg, start, end);
-             READ_ULEB (ul, start, end);
+             READ_ULEB (reg, start, block_end);
+             READ_ULEB (ul, start, block_end);
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              /* PR 17512: file: 069-133014-0.006.  */
              /* PR 17512: file: 98c02eb4.  */
-             tmp = start + ul;
-             if (start >= block_end || tmp > block_end || tmp < start)
+             if (ul > (size_t) (block_end - start))
                {
                  printf (_("  DW_CFA_expression: <corrupt len %lu>\n"), ul);
                  break;
@@ -9378,16 +9372,15 @@ display_debug_frames (struct dwarf_section *section,
                }
              if (*reg_prefix == '\0')
                fc->col_type[reg] = DW_CFA_expression;
-             start = tmp;
+             start += ul;
              break;
 
            case DW_CFA_val_expression:
-             READ_ULEB (reg, start, end);
-             READ_ULEB (ul, start, end);
+             READ_ULEB (reg, start, block_end);
+             READ_ULEB (ul, start, block_end);
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
-             tmp = start + ul;
-             if (start >= block_end || tmp > block_end || tmp < start)
+             if (ul > (size_t) (block_end - start))
                {
                  printf ("  DW_CFA_val_expression: <corrupt len %lu>\n", ul);
                  break;
@@ -9402,12 +9395,12 @@ display_debug_frames (struct dwarf_section *section,
                }
              if (*reg_prefix == '\0')
                fc->col_type[reg] = DW_CFA_val_expression;
-             start = tmp;
+             start += ul;
              break;
 
            case DW_CFA_offset_extended_sf:
-             READ_ULEB (reg, start, end);
-             READ_SLEB (l, start, end);
+             READ_ULEB (reg, start, block_end);
+             READ_SLEB (l, start, block_end);
              if (frame_need_space (fc, reg) < 0)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
@@ -9422,8 +9415,8 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_val_offset_sf:
-             READ_ULEB (reg, start, end);
-             READ_SLEB (l, start, end);
+             READ_ULEB (reg, start, block_end);
+             READ_SLEB (l, start, block_end);
              if (frame_need_space (fc, reg) < 0)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
@@ -9438,8 +9431,8 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_def_cfa_sf:
-             READ_ULEB (fc->cfa_reg, start, end);
-             READ_ULEB (fc->cfa_offset, start, end);
+             READ_ULEB (fc->cfa_reg, start, block_end);
+             READ_ULEB (fc->cfa_offset, start, block_end);
              fc->cfa_offset = fc->cfa_offset * fc->data_factor;
              fc->cfa_exp = 0;
              if (! do_debug_frames_interp)
@@ -9448,7 +9441,7 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_def_cfa_offset_sf:
-             READ_ULEB (fc->cfa_offset, start, end);
+             READ_ULEB (fc->cfa_offset, start, block_end);
              fc->cfa_offset *= fc->data_factor;
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_def_cfa_offset_sf: %d\n", (int) fc->cfa_offset);
@@ -9473,14 +9466,14 @@ display_debug_frames (struct dwarf_section *section,
              break;
 
            case DW_CFA_GNU_args_size:
-             READ_ULEB (ul, start, end);
+             READ_ULEB (ul, start, block_end);
              if (! do_debug_frames_interp)
                printf ("  DW_CFA_GNU_args_size: %ld\n", ul);
              break;
 
            case DW_CFA_GNU_negative_offset_extended:
-             READ_ULEB (reg, start, end);
-             READ_SLEB (l, start, end);
+             READ_ULEB (reg, start, block_end);
+             READ_SLEB (l, start, block_end);
              l = - l;
              if (frame_need_space (fc, reg) < 0)
                reg_prefix = bad_reg;
@@ -9578,12 +9571,12 @@ display_debug_names (struct dwarf_section *section, void *file)
       unsigned int offset_size;
       uint16_t dwarf_version, padding;
       uint32_t comp_unit_count, local_type_unit_count, foreign_type_unit_count;
-      uint32_t bucket_count, name_count, abbrev_table_size;
+      uint64_t bucket_count, name_count, abbrev_table_size;
       uint32_t augmentation_string_size;
       unsigned int i;
-      unsigned long sec_off;
       bool augmentation_printable;
       const char *augmentation_string;
+      size_t total;
 
       unit_start = hdrptr;
 
@@ -9598,18 +9591,18 @@ display_debug_names (struct dwarf_section *section, void *file)
        }
       else
        offset_size = 4;
-      unit_end = hdrptr + unit_length;
 
-      sec_off = hdrptr - section->start;
-      if (sec_off + unit_length < sec_off
-         || sec_off + unit_length > section->size)
+      if (unit_length > (size_t) (section_end - hdrptr)
+         || unit_length < 2 + 2 + 4 * 7)
        {
+       too_short:
          warn (_("Debug info is corrupted, %s header at %#lx has length %s\n"),
                section->name,
                (unsigned long) (unit_start - section->start),
                dwarf_vmatoa ("x", unit_length));
          return 0;
        }
+      unit_end = hdrptr + unit_length;
 
       /* Get and check the version number.  */
       SAFE_BYTE_GET_AND_INC (dwarf_version, hdrptr, 2, unit_end);
@@ -9647,6 +9640,8 @@ display_debug_names (struct dwarf_section *section, void *file)
                augmentation_string_size);
          augmentation_string_size += (-augmentation_string_size) & 3;
        }
+      if (augmentation_string_size > (size_t) (unit_end - hdrptr))
+       goto too_short;
 
       printf (_("Augmentation string:"));
 
@@ -9676,6 +9671,9 @@ display_debug_names (struct dwarf_section *section, void *file)
       putchar ('\n');
 
       printf (_("CU table:\n"));
+      if (_mul_overflow (comp_unit_count, offset_size, &total)
+         || total > (size_t) (unit_end - hdrptr))
+       goto too_short;
       for (i = 0; i < comp_unit_count; i++)
        {
          uint64_t cu_offset;
@@ -9686,6 +9684,9 @@ display_debug_names (struct dwarf_section *section, void *file)
       putchar ('\n');
 
       printf (_("TU table:\n"));
+      if (_mul_overflow (local_type_unit_count, offset_size, &total)
+         || total > (size_t) (unit_end - hdrptr))
+       goto too_short;
       for (i = 0; i < local_type_unit_count; i++)
        {
          uint64_t tu_offset;
@@ -9696,6 +9697,9 @@ display_debug_names (struct dwarf_section *section, void *file)
       putchar ('\n');
 
       printf (_("Foreign TU table:\n"));
+      if (_mul_overflow (foreign_type_unit_count, 8, &total)
+         || total > (size_t) (unit_end - hdrptr))
+       goto too_short;
       for (i = 0; i < foreign_type_unit_count; i++)
        {
          uint64_t signature;
@@ -9707,6 +9711,18 @@ display_debug_names (struct dwarf_section *section, void *file)
        }
       putchar ('\n');
 
+      uint64_t xtra = (bucket_count * sizeof (uint32_t)
+                      + name_count * (sizeof (uint32_t) + 2 * offset_size)
+                      + abbrev_table_size);
+      if (xtra > (size_t) (unit_end - hdrptr))
+       {
+         warn (_("Entry pool offset (0x%lx) exceeds unit size 0x%lx "
+                 "for unit 0x%lx in the debug_names\n"),
+               (long) xtra,
+               (long) (unit_end - unit_start),
+               (long) (unit_start - section->start));
+         return 0;
+       }
       const uint32_t *const hash_table_buckets = (uint32_t *) hdrptr;
       hdrptr += bucket_count * sizeof (uint32_t);
       const uint32_t *const hash_table_hashes = (uint32_t *) hdrptr;
@@ -9719,15 +9735,6 @@ display_debug_names (struct dwarf_section *section, void *file)
       hdrptr += abbrev_table_size;
       const unsigned char *const abbrev_table_end = hdrptr;
       unsigned char *const entry_pool = hdrptr;
-      if (hdrptr > unit_end)
-       {
-         warn (_("Entry pool offset (0x%lx) exceeds unit size 0x%lx "
-                 "for unit 0x%lx in the debug_names\n"),
-               (long) (hdrptr - section->start),
-               (long) (unit_end - section->start),
-               (long) (unit_start - section->start));
-         return 0;
-       }
 
       size_t buckets_filled = 0;
       size_t bucketi;
@@ -9829,13 +9836,12 @@ display_debug_names (struct dwarf_section *section, void *file)
       for (namei = 0; namei < name_count; ++namei)
        {
          uint64_t string_offset, entry_offset;
+         unsigned char *p;
 
-         SAFE_BYTE_GET (string_offset,
-                        name_table_string_offsets + namei * offset_size,
-                        offset_size, unit_end);
-         SAFE_BYTE_GET (entry_offset,
-                        name_table_entry_offsets + namei * offset_size,
-                        offset_size, unit_end);
+         p = name_table_string_offsets + namei * offset_size;
+         SAFE_BYTE_GET (string_offset, p, offset_size, unit_end);
+         p = name_table_entry_offsets + namei * offset_size;
+         SAFE_BYTE_GET (entry_offset, p, offset_size, unit_end);
 
          printf ("[%3u] #%08x %s:", namei, hash_table_hashes[namei],
                  fetch_indirect_string (string_offset));
@@ -10099,7 +10105,7 @@ display_gdb_index (struct dwarf_section *section,
   symbol_table = start + symbol_table_offset;
   constant_pool = start + constant_pool_offset;
 
-  if (address_table + address_table_size > section->start + section->size)
+  if (address_table_offset + address_table_size > section->size)
     {
       warn (_("Address table extends beyond end of section.\n"));
       return 0;
@@ -10154,11 +10160,9 @@ display_gdb_index (struct dwarf_section *section,
          || cu_vector_offset != 0)
        {
          unsigned int j;
-         unsigned char * adr;
 
-         adr = constant_pool + name_offset;
          /* PR 17531: file: 5b7b07ad.  */
-         if (adr < constant_pool || adr >= section->start + section->size)
+         if (name_offset >= section->size - constant_pool_offset)
            {
              printf (_("[%3u] <corrupt offset: %x>"), i, name_offset);
              warn (_("Corrupt name offset of 0x%x found for symbol table slot %d\n"),
@@ -10169,8 +10173,8 @@ display_gdb_index (struct dwarf_section *section,
                    (int) (section->size - (constant_pool_offset + name_offset)),
                    constant_pool + name_offset);
 
-         adr = constant_pool + cu_vector_offset;
-         if (adr < constant_pool || adr >= section->start + section->size - 3)
+         if (section->size - constant_pool_offset < 4
+             || cu_vector_offset > section->size - constant_pool_offset - 4)
            {
              printf (_("<invalid CU vector offset: %x>\n"), cu_vector_offset);
              warn (_("Corrupt CU vector offset of 0x%x found for symbol table slot %d\n"),
@@ -10178,12 +10182,10 @@ display_gdb_index (struct dwarf_section *section,
              continue;
            }
 
-         num_cus = byte_get_little_endian (adr, 4);
+         num_cus = byte_get_little_endian (constant_pool + cu_vector_offset, 4);
 
-         adr = constant_pool + cu_vector_offset + 4 + num_cus * 4;
-         if (num_cus * 4 < num_cus
-             || adr >= section->start + section->size
-             || adr < constant_pool)
+         if ((uint64_t) num_cus * 4 > section->size - (constant_pool_offset
+                                                       + cu_vector_offset + 4))
            {
              printf ("<invalid number of CUs: %d>\n", num_cus);
              warn (_("Invalid number of CUs (0x%x) for symbol table slot %d\n"),
@@ -10318,6 +10320,7 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
   unsigned int i;
   unsigned int j;
   dwarf_vma signature;
+  size_t total;
 
   /* PR 17512: file: 002-168123-0.004.  */
   if (phdr == NULL)
@@ -10333,13 +10336,13 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
       return 0;
     }
 
-  SAFE_BYTE_GET (version, phdr, 4, limit);
+  phash = phdr;
+  SAFE_BYTE_GET_AND_INC (version, phash, 4, limit);
   if (version >= 2)
-    SAFE_BYTE_GET (ncols, phdr + 4, 4, limit);
-  SAFE_BYTE_GET (nused, phdr + 8, 4, limit);
-  SAFE_BYTE_GET (nslots, phdr + 12, 4, limit);
+    SAFE_BYTE_GET_AND_INC (ncols, phash, 4, limit);
+  SAFE_BYTE_GET_AND_INC (nused, phash, 4, limit);
+  SAFE_BYTE_GET_AND_INC (nslots, phash, 4, limit);
 
-  phash = phdr + 16;
   pindex = phash + (size_t) nslots * 8;
   ppool = pindex + (size_t) nslots * 4;
 
@@ -10355,10 +10358,8 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
     }
 
   /* PR 17531: file: 45d69832.  */
-  if ((size_t) nslots * 8 / 8 != nslots
-      || phash < phdr || phash > limit
-      || pindex < phash || pindex > limit
-      || ppool < pindex || ppool > limit)
+  if (_mul_overflow ((size_t) nslots, 12, &total)
+      || total > (size_t) (limit - phash))
     {
       warn (ngettext ("Section %s is too small for %u slot\n",
                      "Section %s is too small for %u slots\n",
@@ -10425,23 +10426,21 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
       unsigned char *pi = pindex;
       unsigned char *poffsets = ppool + (size_t) ncols * 4;
       unsigned char *psizes = poffsets + (size_t) nused * ncols * 4;
-      unsigned char *pend = psizes + (size_t) nused * ncols * 4;
       bool is_tu_index;
       struct cu_tu_set *this_set = NULL;
       unsigned int row;
       unsigned char *prow;
+      size_t temp;
 
       is_tu_index = strcmp (section->name, ".debug_tu_index") == 0;
 
       /* PR 17531: file: 0dd159bf.
         Check for integer overflow (can occur when size_t is 32-bit)
         with overlarge ncols or nused values.  */
-      if (ncols > 0
-         && ((size_t) ncols * 4 / 4 != ncols
-             || (size_t) nused * ncols * 4 / ((size_t) ncols * 4) != nused
-             || poffsets < ppool || poffsets > limit
-             || psizes < poffsets || psizes > limit
-             || pend < psizes || pend > limit))
+      if (nused == -1u
+         || _mul_overflow ((size_t) ncols, 4, &temp)
+         || _mul_overflow ((size_t) nused + 1, temp, &total)
+         || total > (size_t) (limit - ppool))
        {
          warn (_("Section %s too small for offset and size tables\n"),
                section->name);
@@ -10474,7 +10473,8 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
        {
          for (j = 0; j < ncols; j++)
            {
-             SAFE_BYTE_GET (dw_sect, ppool + j * 4, 4, limit);
+             unsigned char *p = ppool + j * 4;
+             SAFE_BYTE_GET (dw_sect, p, 4, limit);
              printf (" %8s", get_DW_SECT_short_name (dw_sect));
            }
          printf ("\n");
@@ -10499,36 +10499,23 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
                {
                  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;
-                   }
+                 memcpy (&this_set[row - 1].signature, ph, num_copy);
                }
 
              prow = poffsets + (row - 1) * ncols * 4;
-             /* PR 17531: file: b8ce60a8.  */
-             if (prow < poffsets || prow > limit)
-               {
-                 warn (_("Row index (%u) * num columns (%u) > space remaining in section\n"),
-                       row, ncols);
-                 return 0;
-               }
-
              if (do_display)
                printf (_("  [%3d] 0x%s"),
                        i, dwarf_vmatoa ("x", signature));
              for (j = 0; j < ncols; j++)
                {
-                 SAFE_BYTE_GET (val, prow + j * 4, 4, limit);
+                 unsigned char *p = prow + j * 4;
+                 SAFE_BYTE_GET (val, p, 4, limit);
                  if (do_display)
                    printf (" %8d", val);
                  else
                    {
-                     SAFE_BYTE_GET (dw_sect, ppool + j * 4, 4, limit);
+                     p = ppool + j * 4;
+                     SAFE_BYTE_GET (dw_sect, p, 4, limit);
 
                      /* PR 17531: file: 10796eb3.  */
                      if (dw_sect >= DW_SECT_MAX)
@@ -10557,7 +10544,8 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
 
       for (j = 0; j < ncols; j++)
        {
-         SAFE_BYTE_GET (val, ppool + j * 4, 4, limit);
+         unsigned char *p = ppool + j * 4;
+         SAFE_BYTE_GET (val, p, 4, limit);
          if (do_display)
            printf (" %8s", get_DW_SECT_short_name (val));
        }
@@ -10580,12 +10568,14 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
 
              for (j = 0; j < ncols; j++)
                {
-                 SAFE_BYTE_GET (val, prow + j * 4, 4, limit);
+                 unsigned char *p = prow + j * 4;
+                 SAFE_BYTE_GET (val, p, 4, limit);
                  if (do_display)
                    printf (" %8d", val);
                  else
                    {
-                     SAFE_BYTE_GET (dw_sect, ppool + j * 4, 4, limit);
+                     p = ppool + j * 4;
+                     SAFE_BYTE_GET (dw_sect, p, 4, limit);
                      if (dw_sect >= DW_SECT_MAX)
                        warn (_("Overlarge Dwarf section index detected: %u\n"), dw_sect);
                      else