+2020-10-21  Nick Clifton  <nickc@redhat.com>
+
+       * dwarf.c (skip_attr_bytes): Accept DWARF versions higher than 4
+       when processing the DW_FORM_ref_addr form.
+       Skip bytes in DW_FORM_block and DW_FORM_exprloc forms.
+       Handle DW_FORM_indirect.
+       (get_type_signedness): Allow a limited amount of recursion.
+       Do not attempt to decode types that use the DW_FORM_ref_addr form.
+       (read_and_display_attr_value):  Do not attempt to decode types
+       that use the DW_FORM_ref_addr form.
+
 2020-10-20  Alan Modra  <amodra@gmail.com>
 
        * readelf.c: Delete whitespace at end of line throughout.
 
     case DW_FORM_ref_addr:
       if (dwarf_version == 2)
        SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
-      else if (dwarf_version == 3 || dwarf_version == 4)
+      else if (dwarf_version > 2)
        SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
       else
        return NULL;
 
     case DW_FORM_ref8:
     case DW_FORM_data8:
+    case DW_FORM_ref_sig8:
       data += 8;
       break;
 
     case DW_FORM_block:
     case DW_FORM_exprloc:
       READ_ULEB (uvalue, data, end);
+      data += uvalue;
       break;
 
     case DW_FORM_block1:
       data += 4 + uvalue;
       break;
 
-    case DW_FORM_ref_sig8:
-      data += 8;
-      break;
-
     case DW_FORM_indirect:
-      /* FIXME: Handle this form.  */
+      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);
+
     default:
       return NULL;
     }
                     dwarf_vma              offset_size,
                     int                    dwarf_version,
                     bfd_boolean *          is_signed,
-                    bfd_boolean            is_nested)
+                    unsigned int           nesting)
 {
   unsigned long   abbrev_number;
   abbrev_entry *  entry;
     /* FIXME: Issue a warning ?  */
     return;
 
+#define MAX_NESTING 20
+  if (nesting > MAX_NESTING)
+    {
+      /* FIXME: Warn - or is this expected ?
+        NB/ We need to avoid infinite recursion.  */
+      return;
+    }
+
   for (attr = entry->first_attr;
        attr != NULL && attr->attribute;
        attr = attr->next)
 #endif
        case DW_AT_type:
          /* Recurse.  */
-         if (is_nested)
-           {
-             /* FIXME: Warn - or is this expected ?
-                NB/ We need to avoid infinite recursion.  */
-             return;
-           }
          if (uvalue >= (size_t) (end - start))
            return;
-         get_type_signedness (start, start + uvalue, end, pointer_size,
-                              offset_size, dwarf_version, is_signed, TRUE);
+         /* We cannot correctly process DW_FORM_ref_addr at the moment.  */
+         if (attr->form != DW_FORM_ref_addr)
+           get_type_signedness (start, start + uvalue, end, pointer_size,
+                                offset_size, dwarf_version, is_signed, nesting + 1);
          break;
 
        case DW_AT_encoding:
        SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
       else
        error (_("Internal error: DW_FORM_ref_addr is not supported in DWARF version 1.\n"));
-
       break;
 
     case DW_FORM_addr:
        {
          bfd_boolean is_signed = FALSE;
 
-         get_type_signedness (start, start + uvalue, end, pointer_size,
-                              offset_size, dwarf_version, & is_signed, FALSE);
+         /* We cannot correctly process DW_FORM_ref_addr at the moment.  */
+         if (form != DW_FORM_ref_addr)
+           get_type_signedness (start, start + uvalue, end, pointer_size,
+                                offset_size, dwarf_version, & is_signed, 0);
          level_type_signed[level] = is_signed;
        }
       break;