From: Nick Clifton Date: Tue, 27 Aug 2019 15:28:55 +0000 (+0100) Subject: Improve the DWARF decoder's ability to describe the DW_AT_discr_list attribute. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ec1b0fbb8dffc09f64f65b6459b786c35218803a;p=binutils-gdb.git Improve the DWARF decoder's ability to describe the DW_AT_discr_list attribute. 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. --- diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 15160763870..4de9a9302c9 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,26 @@ +2019-08-27 Nick Clifton + + 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 PR 24938 diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 27685183e01..19ae1edca76 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -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 ("\n"); + warn (_("corrupt discr_list - not using a block form\n")); + return; + } + + if (uvalue < 2) + { + printf ("\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 ("\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; } diff --git a/binutils/testsuite/binutils-all/dwarf-attributes.S b/binutils/testsuite/binutils-all/dwarf-attributes.S index ef250342e13..39a7258a9be 100644 --- a/binutils/testsuite/binutils-all/dwarf-attributes.S +++ b/binutils/testsuite/binutils-all/dwarf-attributes.S @@ -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. */ @@ -107,7 +107,7 @@ .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) */ diff --git a/binutils/testsuite/binutils-all/dwarf-attributes.W b/binutils/testsuite/binutils-all/dwarf-attributes.W index d10e0c64f0d..3a4e7409889 100644 --- a/binutils/testsuite/binutils-all/dwarf-attributes.W +++ b/binutils/testsuite/binutils-all/dwarf-attributes.W @@ -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\)