Improve the DWARF decoder's ability to describe the DW_AT_discr_list attribute.
authorNick Clifton <nickc@redhat.com>
Tue, 27 Aug 2019 15:28:55 +0000 (16:28 +0100)
committerNick Clifton <nickc@redhat.com>
Tue, 27 Aug 2019 15:28:55 +0000 (16:28 +0100)
PR 24510
* dwarf.c (MAX_CU_NESTING): New constant.
(level_type_signed): New static array.
(skip_attr_bytes): New function.
(get_type_signedness): New function.
(read_and_print_leb128): New function.
(display_discr_list): New function.
(read_and_display_attr_value): Add start parameter.
Use new functions when handling DW_AT_type and DW_AT_discr_list.
(read_and_display_attr): Add start parameter.  Pass to
read_and_display_attr_value.
(process_debug_info): Update call to read_and_display_attr.
(display_formatted_table): Likewise.
(display_debug_lines_decoded): Likewise.  Also add start
parameter.
(display_debug_lines): Likewise.
* testsuite/binutils-all/dwarf-attributes.S: Update discrimination
lists.
* testsuite/binutils-all/dwarf-attributes.W: Update expected
output.

binutils/ChangeLog
binutils/dwarf.c
binutils/testsuite/binutils-all/dwarf-attributes.S
binutils/testsuite/binutils-all/dwarf-attributes.W

index 15160763870083e80d5cdf3f71ef1003aea5abbd..4de9a9302c9f8e2306b0a9ea7071c81f066a49df 100644 (file)
@@ -1,3 +1,26 @@
+2019-08-27  Nick Clifton  <nickc@redhat.com>
+
+       PR 24510
+       * dwarf.c (MAX_CU_NESTING): New constant.
+       (level_type_signed): New static array.
+       (skip_attr_bytes): New function.
+       (get_type_signedness): New function.
+       (read_and_print_leb128): New function.
+       (display_discr_list): New function.
+       (read_and_display_attr_value): Add start parameter.
+       Use new functions when handling DW_AT_type and DW_AT_discr_list.
+       (read_and_display_attr): Add start parameter.  Pass to
+       read_and_display_attr_value.
+       (process_debug_info): Update call to read_and_display_attr.
+       (display_formatted_table): Likewise.
+       (display_debug_lines_decoded): Likewise.  Also add start
+       parameter.
+       (display_debug_lines): Likewise.
+       * testsuite/binutils-all/dwarf-attributes.S: Update discrimination
+       lists.
+       * testsuite/binutils-all/dwarf-attributes.W: Update expected
+       output.
+
 2019-08-26  Alan Modra  <amodra@gmail.com>
 
        PR 24938
index 27685183e0188918ea2308e4b3848e8546c9a478..19ae1edca7649ec8572cc86cd7818f63b5d81872 100644 (file)
@@ -120,9 +120,9 @@ static unsigned int shndx_pool_used = 0;
 
 struct cu_tu_set
 {
-  uint64_t signature;
-  dwarf_vma section_offsets[DW_SECT_MAX];
-  size_t section_sizes[DW_SECT_MAX];
+  uint64_t   signature;
+  dwarf_vma  section_offsets[DW_SECT_MAX];
+  size_t     section_sizes[DW_SECT_MAX];
 };
 
 static int cu_count = 0;
@@ -132,6 +132,12 @@ static struct cu_tu_set *tu_sets = NULL;
 
 static bfd_boolean load_cu_tu_indexes (void *);
 
+/* An array that indicates for a given level of CU nesting whether
+   the latest DW_AT_type seen for that level was a signed type or
+   an unsigned type.  */
+#define MAX_CU_NESTING (1 << 8)
+static bfd_boolean level_type_signed[MAX_CU_NESTING];
+
 /* Values for do_debug_lines.  */
 #define FLAG_DEBUG_LINES_RAW    1
 #define FLAG_DEBUG_LINES_DECODED 2
@@ -1860,10 +1866,336 @@ check_uvalue (const unsigned char * start,
   return uvalue;
 }
 
+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)
+{
+  unsigned int  bytes_read;
+  dwarf_vma     uvalue = 0;
+
+  * value_return = 0;
+
+  switch (form)
+    {
+    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)
+       SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+      else
+       return NULL;
+      break;
+
+    case DW_FORM_addr:
+      SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+      break;
+
+    case DW_FORM_strp:
+    case DW_FORM_line_strp:
+    case DW_FORM_sec_offset:
+    case DW_FORM_GNU_ref_alt:
+    case DW_FORM_GNU_strp_alt:
+      SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+      break;
+
+    case DW_FORM_flag_present:
+      uvalue = 1;
+      break;
+
+    case DW_FORM_ref1:
+    case DW_FORM_flag:
+    case DW_FORM_data1:
+      SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+      break;
+
+    case DW_FORM_ref2:
+    case DW_FORM_data2:
+      SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
+      break;
+
+    case DW_FORM_ref4:
+    case DW_FORM_data4:
+      SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
+      break;
+
+    case DW_FORM_sdata:
+      uvalue = read_sleb128 (data, & bytes_read, end);
+      data += bytes_read;
+      break;
+
+    case DW_FORM_ref_udata:
+    case DW_FORM_udata:
+    case DW_FORM_GNU_str_index:
+    case DW_FORM_GNU_addr_index:
+      uvalue = read_uleb128 (data, & bytes_read, end);
+      data += bytes_read;
+      break;
+
+    case DW_FORM_ref8:
+    case DW_FORM_data8:
+      data += 8;
+      break;
+
+    case DW_FORM_data16:
+      data += 16;
+      break;
+
+    case DW_FORM_string:
+      data += strnlen ((char *) data, end - data) + 1;
+      break;
+
+    case DW_FORM_block:
+    case DW_FORM_exprloc:
+      uvalue = read_uleb128 (data, & bytes_read, end);
+      data += bytes_read + uvalue;
+      break;
+
+    case DW_FORM_block1:
+      SAFE_BYTE_GET (uvalue, data, 1, end);
+      data += 1 + uvalue;
+      break;
+
+    case DW_FORM_block2:
+      SAFE_BYTE_GET (uvalue, data, 2, end);
+      data += 2 + uvalue;
+      break;
+
+    case DW_FORM_block4:
+      SAFE_BYTE_GET (uvalue, data, 4, end);
+      data += 4 + uvalue;
+      break;
+
+    case DW_FORM_ref_sig8:
+      data += 8;
+      break;
+
+    case DW_FORM_indirect:
+      /* FIXME: Handle this form.  */
+    default:
+      return NULL;
+    }
+
+  * value_return = uvalue;
+  if (data > end)
+    data = (unsigned char *) end;
+  return data;
+}
+
+/* Return IS_SIGNED set to TRUE if the type at
+   DATA can be determined to be a signed type.  */
+
+static void
+get_type_signedness (unsigned char *        start,
+                    unsigned char *        data,
+                    unsigned const char *  end,
+                    dwarf_vma              pointer_size,
+                    dwarf_vma              offset_size,
+                    int                    dwarf_version,
+                    bfd_boolean *          is_signed,
+                    bfd_boolean            is_nested)
+{
+  unsigned long   abbrev_number;
+  unsigned int    bytes_read;
+  abbrev_entry *  entry;
+  abbrev_attr *   attr;
+
+  * is_signed = FALSE;
+
+  if (data >= end)
+    return;
+
+  abbrev_number = read_uleb128 (data, & bytes_read, end);
+  data += bytes_read;
+
+  for (entry = first_abbrev;
+       entry != NULL && entry->entry != abbrev_number;
+       entry = entry->next)
+    continue;
+
+  if (entry == NULL)
+    /* FIXME: Issue a warning ?  */
+    return;
+
+  for (attr = entry->first_attr;
+       attr != NULL && attr->attribute;
+       attr = attr->next)
+    {
+      dwarf_vma uvalue = 0;
+
+      data = skip_attr_bytes (attr->form, data, end, pointer_size,
+                             offset_size, dwarf_version, & uvalue);
+      if (data == NULL)
+       return;
+
+      switch (attr->attribute)
+       {
+#if 0 /* FIXME: It would be nice to print the name of the type,
+        but this would mean updating a lot of binutils tests.  */
+       case DW_AT_name:
+         if (attr->form == DW_FORM_strp)
+           printf ("%s", fetch_indirect_string (uvalue));
+         break;
+#endif
+       case DW_AT_type:
+         /* Recurse.  */
+         if (is_nested)
+           {
+             /* FIXME: Warn - or is this expected ?
+                NB/ We need to avoid infinite recursion.  */
+             return;
+           }
+         get_type_signedness (start, start + uvalue, end, pointer_size,
+                              offset_size, dwarf_version, is_signed, TRUE);
+         break;
+
+       case DW_AT_encoding:
+         /* Determine signness.  */
+         switch (uvalue)
+           {
+           case DW_ATE_address:
+             /* FIXME - some architectures have signed addresses.  */
+           case DW_ATE_boolean:
+           case DW_ATE_unsigned:
+           case DW_ATE_unsigned_char:
+           case DW_ATE_unsigned_fixed:
+             * is_signed = FALSE;
+             break;
+
+           default:
+           case DW_ATE_complex_float:
+           case DW_ATE_float:
+           case DW_ATE_signed:
+           case DW_ATE_signed_char:
+           case DW_ATE_imaginary_float:
+           case DW_ATE_decimal_float:
+           case DW_ATE_signed_fixed:
+             * is_signed = TRUE;
+             break;
+           }
+         break;
+       }
+    }
+}
+
+static void
+read_and_print_leb128 (unsigned char *        data,
+                      unsigned int *         bytes_read,
+                      unsigned const char *  end,
+                      bfd_boolean            is_signed)
+{
+  if (is_signed)
+    {
+      dwarf_signed_vma sval = read_sleb128 (data, bytes_read, end);
+      printf ("%ld", (long) sval);
+    }
+  else
+    {
+      dwarf_vma uval = read_uleb128 (data, bytes_read, end);
+      printf ("%lu", (unsigned long) uval);
+    }
+}
+
+static void
+display_discr_list (unsigned long          form,
+                   dwarf_vma              uvalue,
+                   unsigned char *        data,
+                   unsigned const char *  end,
+                   int                    level)
+{
+  if (uvalue == 0)
+    {
+      printf ("[default]");
+      return;
+    }
+  
+  switch (form)
+    {
+    case DW_FORM_block:
+    case DW_FORM_block1:
+    case DW_FORM_block2:
+    case DW_FORM_block4:
+      /* Move data pointer back to the start of the byte array.  */
+      data -= uvalue;
+      break;
+    default:
+      printf ("<corrupt>\n");
+      warn (_("corrupt discr_list - not using a block form\n"));
+      return;
+    }
+
+  if (uvalue < 2)
+    {
+      printf ("<corrupt>\n");
+      warn (_("corrupt discr_list - block not long enough\n"));
+      return;
+    }
+
+  bfd_boolean is_signed =
+    (level > 0 && level <= MAX_CU_NESTING)
+    ? level_type_signed [level - 1] : FALSE;
+    
+  printf ("(");
+  while (uvalue)
+    {
+      unsigned char     discriminant;
+      unsigned int      bytes_read;
+
+      SAFE_BYTE_GET (discriminant, data, 1, end);
+      -- uvalue;
+      data ++;
+
+      assert (uvalue > 0);
+      switch (discriminant)
+       {
+       case DW_DSC_label:
+         printf ("label ");
+         read_and_print_leb128 (data, & bytes_read, end, is_signed);
+         assert (bytes_read <= uvalue && bytes_read > 0);
+         uvalue -= bytes_read;
+         data += bytes_read;
+         break;
+
+       case DW_DSC_range:
+         printf ("range ");
+         read_and_print_leb128 (data, & bytes_read, end, is_signed);
+         assert (bytes_read <= uvalue && bytes_read > 0);
+         uvalue -= bytes_read;
+         data += bytes_read;
+
+         printf ("..");
+         read_and_print_leb128 (data, & bytes_read, end, is_signed);
+         assert (bytes_read <= uvalue && bytes_read > 0);
+         uvalue -= bytes_read;
+         data += bytes_read;
+         break;
+
+       default:
+         printf ("<corrupt>\n");
+         warn (_("corrupt discr_list - unrecognised discriminant byte %#x\n"),
+               discriminant);
+         return;
+       }
+
+      if (uvalue)
+       printf (", ");
+    }
+
+  if (is_signed)
+    printf (")(signed)");
+  else
+    printf (")(unsigned)");
+}
+
 static unsigned char *
 read_and_display_attr_value (unsigned long           attribute,
                             unsigned long           form,
                             dwarf_signed_vma        implicit_const,
+                            unsigned char *         start,
                             unsigned char *         data,
                             unsigned char *         end,
                             dwarf_vma               cu_offset,
@@ -1874,12 +2206,13 @@ read_and_display_attr_value (unsigned long           attribute,
                             int                     do_loc,
                             struct dwarf_section *  section,
                             struct cu_tu_set *      this_set,
-                            char                    delimiter)
+                            char                    delimiter,
+                            int                     level)
 {
-  dwarf_vma uvalue = 0;
-  unsigned char *block_start = NULL;
-  unsigned char * orig_data = data;
-  unsigned int bytes_read;
+  dwarf_vma        uvalue = 0;
+  unsigned char *  block_start = NULL;
+  unsigned char *  orig_data = data;
+  unsigned int     bytes_read;
 
   if (data > end || (data == end && form != DW_FORM_flag_present))
     {
@@ -1960,11 +2293,12 @@ read_and_display_attr_value (unsigned long           attribute,
          implicit_const = read_sleb128 (data, & bytes_read, end);
          data += bytes_read;
        }
-      return read_and_display_attr_value (attribute, form, implicit_const, data,
-                                         end, cu_offset, pointer_size,
+      return read_and_display_attr_value (attribute, form, implicit_const,
+                                         start, data, end,
+                                         cu_offset, pointer_size,
                                          offset_size, dwarf_version,
                                          debug_info_p, do_loc,
-                                         section, this_set, delimiter);
+                                         section, this_set, delimiter, level);
     case DW_FORM_GNU_addr_index:
       uvalue = read_uleb128 (data, & bytes_read, end);
       data += bytes_read;
@@ -2397,6 +2731,17 @@ read_and_display_attr_value (unsigned long           attribute,
   /* For some attributes we can display further information.  */
   switch (attribute)
     {
+    case DW_AT_type:
+      if (level >= 0 && level < MAX_CU_NESTING)
+       {
+         bfd_boolean is_signed = FALSE;
+
+         get_type_signedness (start, start + uvalue, end, pointer_size,
+                              offset_size, dwarf_version, & is_signed, FALSE);
+         level_type_signed[level] = is_signed;
+       }
+      break;
+      
     case DW_AT_inline:
       printf ("\t");
       switch (uvalue)
@@ -2646,12 +2991,7 @@ read_and_display_attr_value (unsigned long           attribute,
 
     case DW_AT_discr_list:
       printf ("\t");
-      switch (uvalue)
-       {
-       case DW_DSC_label:  printf (_("(label)")); break;
-       case DW_DSC_range:  printf (_("(range)")); break;
-       default:            printf (_("(unrecognised)")); break;
-       }
+      display_discr_list (form, uvalue, data, end, level);
       break;
       
     case DW_AT_frame_base:
@@ -2768,6 +3108,7 @@ static unsigned char *
 read_and_display_attr (unsigned long           attribute,
                       unsigned long           form,
                       dwarf_signed_vma        implicit_const,
+                      unsigned char *         start,
                       unsigned char *         data,
                       unsigned char *         end,
                       dwarf_vma               cu_offset,
@@ -2777,14 +3118,16 @@ read_and_display_attr (unsigned long           attribute,
                       debug_info *            debug_info_p,
                       int                     do_loc,
                       struct dwarf_section *  section,
-                      struct cu_tu_set *      this_set)
+                      struct cu_tu_set *      this_set,
+                      int                     level)
 {
   if (!do_loc)
     printf ("   %-18s:", get_AT_name (attribute));
-  data = read_and_display_attr_value (attribute, form, implicit_const, data, end,
+  data = read_and_display_attr_value (attribute, form, implicit_const,
+                                     start, data, end,
                                      cu_offset, pointer_size, offset_size,
                                      dwarf_version, debug_info_p,
-                                     do_loc, section, this_set, ' ');
+                                     do_loc, section, this_set, ' ', level);
   if (!do_loc)
     printf ("\n");
   return data;
@@ -3310,6 +3653,7 @@ process_debug_info (struct dwarf_section *           section,
              tags = read_and_display_attr (attr->attribute,
                                            attr->form,
                                            attr->implicit_const,
+                                           section_begin,
                                            tags,
                                            end,
                                            cu_offset,
@@ -3319,7 +3663,8 @@ process_debug_info (struct dwarf_section *           section,
                                            debug_info_p,
                                            do_loc || ! do_printing,
                                            section,
-                                           this_set);
+                                           this_set,
+                                           level);
            }
 
          /* If a locview attribute appears before a location one,
@@ -3636,11 +3981,11 @@ display_formatted_table (unsigned char *                   data,
              format += bytes_read;
              form = read_uleb128 (format, & bytes_read, end);
              format += bytes_read;
-             data = read_and_display_attr_value (0, form, 0, data, end, 0, 0,
+             data = read_and_display_attr_value (0, form, 0, start, data, end, 0, 0,
                                                  linfo->li_offset_size,
                                                  linfo->li_version, NULL,
                            ((content_type == DW_LNCT_path) != (namepass == 1)),
-                                                 section, NULL, '\t');
+                                                 section, NULL, '\t', -1);
            }
        }
       if (data == end)
@@ -4080,6 +4425,7 @@ typedef struct
 
 static int
 display_debug_lines_decoded (struct dwarf_section *  section,
+                            unsigned char *         start,
                             unsigned char *         data,
                             unsigned char *         end,
                             void *                  fileptr)
@@ -4213,12 +4559,12 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                            }
                          break;
                        }
-                     data = read_and_display_attr_value (0, form, 0, data, end,
+                     data = read_and_display_attr_value (0, form, 0, start, data, end,
                                                          0, 0,
                                                          linfo.li_offset_size,
                                                          linfo.li_version,
                                                          NULL, 1, section,
-                                                         NULL, '\t');
+                                                         NULL, '\t', -1);
                    }
                  if (data == end)
                    {
@@ -4303,12 +4649,12 @@ display_debug_lines_decoded (struct dwarf_section *  section,
                            }
                          break;
                        }
-                     data = read_and_display_attr_value (0, form, 0, data, end,
+                     data = read_and_display_attr_value (0, form, 0, start, data, end,
                                                          0, 0,
                                                          linfo.li_offset_size,
                                                          linfo.li_version,
                                                          NULL, 1, section,
-                                                         NULL, '\t');
+                                                         NULL, '\t', -1);
                    }
                  if (data == end)
                    {
@@ -4835,7 +5181,7 @@ display_debug_lines (struct dwarf_section *section, void *file)
     retValRaw = display_debug_lines_raw (section, data, end, file);
 
   if (do_debug_lines & FLAG_DEBUG_LINES_DECODED)
-    retValDecoded = display_debug_lines_decoded (section, data, end, file);
+    retValDecoded = display_debug_lines_decoded (section, data, data, end, file);
 
   if (!retValRaw || !retValDecoded)
     return 0;
@@ -5440,9 +5786,9 @@ display_debug_macro (struct dwarf_section *section,
                      SAFE_BYTE_GET_AND_INC (val, desc, 1, end);
                      curr
                        = read_and_display_attr_value (0, val, 0,
-                                                      curr, end, 0, 0, offset_size,
+                                                      start, curr, end, 0, 0, offset_size,
                                                       version, NULL, 0, NULL,
-                                                      NULL, ' ');
+                                                      NULL, ' ', -1);
                      if (n != nargs - 1)
                        printf (",");
                    }
@@ -8880,12 +9226,12 @@ display_debug_names (struct dwarf_section *section, void *file)
 
                  if (tagno >= 0)
                    printf (" %s", get_IDX_name (xindex));
-                 entryptr = read_and_display_attr_value (0, form, 0, entryptr,
-                                                         unit_end, 0, 0,
-                                                         offset_size,
+                 entryptr = read_and_display_attr_value (0, form, 0,
+                                                         unit_start, entryptr, unit_end,
+                                                         0, 0, offset_size,
                                                          dwarf_version, NULL,
                                                          (tagno < 0), NULL,
-                                                         NULL, '=');
+                                                         NULL, '=', -1);
                }
              ++tagno;
            }
index ef250342e13ee77101d40401777b2ae18ca6a586..39a7258a9be1354cf1f6d6736eb49a9d63e65377 100644 (file)
@@ -38,7 +38,7 @@
        .byte  1        /* Inline: inlined.  */
        .byte  1        /* Accessibility: public.  */
        .byte  1        /* Calling convention: normal.  */
-       .byte  1        /* Discriminate list: range.  */
+       .byte  3,1,1,2  /* Discriminate list: range.  */
        .byte  1        /* Encoding: address.  */
        .byte  1        /* Identifier case: up.  */
        .byte  1        /* Virtuality: virtual.  */
@@ -53,7 +53,7 @@
        .byte  0        /* Inline: not.  */
        .byte  2        /* Accessibility: protected.  */
        .byte  5        /* Calling convention: pass by value.  */
-       .byte  0        /* Discriminate list: label.  */
+       .byte  2,0,1    /* Discriminate list: label.  */
        .byte  0x12     /* Encoding: ASCII.  */
        .byte  0        /* Identifier case: sensitive.  */
        .byte  0        /* Virtuality: none.  */
@@ -68,7 +68,7 @@
        .byte  3        /* Inline: declared.  */
        .byte  3        /* Accessibility: private.  */
        .byte  0x40     /* Calling convention: Renesas SH.  */
-       .byte  1        /* Discriminate list: range.  */
+       .byte  5,1,2,3,0,4      /* Discriminate list: range and label.  */
        .byte  0x81     /* Encoding: user specified.  */
        .byte  3        /* Identifier case: insensitive.  */
        .byte  2        /* Virtuality: pure.  */
        .uleb128 0x0b   /* (DW_FORM_data1) */
        
        .uleb128 0x3d   /* (DW_AT_discr_lists) */
-       .uleb128 0x0b   /* (DW_FORM_data1) */
+       .uleb128 0x0a   /* (DW_FORM_block1) */
        
        .uleb128 0x3e   /* (DW_AT_encoding) */
        .uleb128 0x0b   /* (DW_FORM_data1) */
index d10e0c64f0d16ba49c546eb873b28ebc3c2477e1..3a4e7409889a91f9fc7a5b77b0581bc54dc75ee7 100644 (file)
@@ -1,7 +1,7 @@
 Contents of the .debug_info section:
 
   Compilation Unit @ offset 0x0:
-   Length:        0x36 \(32-bit\)
+   Length:        0x40 \(32-bit\)
    Version:       5
    Abbrev Offset: 0x0
    Pointer Size:  4
@@ -12,38 +12,38 @@ Contents of the .debug_info section:
     <11>   DW_AT_inline      : 1       \(inlined\)
     <12>   DW_AT_accessibility: 1      \(public\)
     <13>   DW_AT_calling_convention: 1 \(normal\)
-    <14>   DW_AT_discr_list  : 1       \(range\)
-    <15>   DW_AT_encoding    : 1       \(machine address\)
-    <16>   DW_AT_identifier_case: 1    \(up_case\)
-    <17>   DW_AT_virtuality  : 1       \(virtual\)
-    <18>   DW_AT_decimal_sign: 1       \(unsigned\)
-    <19>   DW_AT_endianity   : 1       \(big\)
-    <1a>   DW_AT_defaulted   : 1       \(in class\)
- <0><1b>: Abbrev Number: 1 \(User TAG value: 0x5555\)
-    <1c>   DW_AT_ordering    : 0       \(row major\)
-    <1d>   DW_AT_language    : 22      \(Go\)
-    <1f>   DW_AT_visibility  : 2       \(exported\)
-    <20>   DW_AT_inline      : 0       \(not inlined\)
-    <21>   DW_AT_accessibility: 2      \(protected\)
-    <22>   DW_AT_calling_convention: 5 \(pass by value\)
-    <23>   DW_AT_discr_list  : 0       \(label\)
-    <24>   DW_AT_encoding    : 18      \(ASCII\)
-    <25>   DW_AT_identifier_case: 0    \(case_sensitive\)
-    <26>   DW_AT_virtuality  : 0       \(none\)
-    <27>   DW_AT_decimal_sign: 2       \(leading overpunch\)
-    <28>   DW_AT_endianity   : 0       \(default\)
-    <29>   DW_AT_defaulted   : 0       \(no\)
- <0><2a>: Abbrev Number: 1 \(User TAG value: 0x5555\)
-    <2b>   DW_AT_ordering    : 255     \(undefined\)
-    <2c>   DW_AT_language    : 32769   \(MIPS assembler\)
-    <2e>   DW_AT_visibility  : 3       \(qualified\)
-    <2f>   DW_AT_inline      : 3       \(declared as inline and inlined\)
-    <30>   DW_AT_accessibility: 3      \(private\)
-    <31>   DW_AT_calling_convention: 64        \(Rensas SH\)
-    <32>   DW_AT_discr_list  : 1       \(range\)
-    <33>   DW_AT_encoding    : 129     \(HP_complex_float80\)
-    <34>   DW_AT_identifier_case: 3    \(case_insensitive\)
-    <35>   DW_AT_virtuality  : 2       \(pure_virtual\)
-    <36>   DW_AT_decimal_sign: 5       \(trailing separate\)
-    <37>   DW_AT_endianity   : 80      \(user specified\)
-    <38>   DW_AT_defaulted   : 2       \(out of class\)
+    <14>   DW_AT_discr_list  : 3 byte block: 1 1 2     \(range 1..2\)\(unsigned\)
+    <18>   DW_AT_encoding    : 1       \(machine address\)
+    <19>   DW_AT_identifier_case: 1    \(up_case\)
+    <1a>   DW_AT_virtuality  : 1       \(virtual\)
+    <1b>   DW_AT_decimal_sign: 1       \(unsigned\)
+    <1c>   DW_AT_endianity   : 1       \(big\)
+    <1d>   DW_AT_defaulted   : 1       \(in class\)
+ <0><1e>: Abbrev Number: 1 \(User TAG value: 0x5555\)
+    <1f>   DW_AT_ordering    : 0       \(row major\)
+    <20>   DW_AT_language    : 22      \(Go\)
+    <22>   DW_AT_visibility  : 2       \(exported\)
+    <23>   DW_AT_inline      : 0       \(not inlined\)
+    <24>   DW_AT_accessibility: 2      \(protected\)
+    <25>   DW_AT_calling_convention: 5 \(pass by value\)
+    <26>   DW_AT_discr_list  : 2 byte block: 0 1       \(label 1\)\(unsigned\)
+    <29>   DW_AT_encoding    : 18      \(ASCII\)
+    <2a>   DW_AT_identifier_case: 0    \(case_sensitive\)
+    <2b>   DW_AT_virtuality  : 0       \(none\)
+    <2c>   DW_AT_decimal_sign: 2       \(leading overpunch\)
+    <2d>   DW_AT_endianity   : 0       \(default\)
+    <2e>   DW_AT_defaulted   : 0       \(no\)
+ <0><2f>: Abbrev Number: 1 \(User TAG value: 0x5555\)
+    <30>   DW_AT_ordering    : 255     \(undefined\)
+    <31>   DW_AT_language    : 32769   \(MIPS assembler\)
+    <33>   DW_AT_visibility  : 3       \(qualified\)
+    <34>   DW_AT_inline      : 3       \(declared as inline and inlined\)
+    <35>   DW_AT_accessibility: 3      \(private\)
+    <36>   DW_AT_calling_convention: 64        \(Rensas SH\)
+    <37>   DW_AT_discr_list  : 5 byte block: 1 2 3 0 4         \(range 2..3, label 4\)\(unsigned\)
+    <3d>   DW_AT_encoding    : 129     \(HP_complex_float80\)
+    <3e>   DW_AT_identifier_case: 3    \(case_insensitive\)
+    <3f>   DW_AT_virtuality  : 2       \(pure_virtual\)
+    <40>   DW_AT_decimal_sign: 5       \(trailing separate\)
+    <41>   DW_AT_endianity   : 80      \(user specified\)
+    <42>   DW_AT_defaulted   : 2       \(out of class\)