diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 25be68a69c..c01d4f3148 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,17 @@ +2017-10-11 Peeter Joot + Nick Clifton + + * dwarf.c (read_and_display_attr_value): Handle DW_AT_endianity, + DW_END_default, DW_END_big, DW_END_little, DW_ATE_UCS, + DW_ATE_ASCII, DW_CC_pass_by_reference, DW_CC_pass_by_value, + DW_CC_GNU_renesas_sh, DW_CC_GNU_borland_fastcall_i386, + DW_AT_decimal_sign, DW_AT_defaulted, DW_AT_discr_list. + (get_TAG_name): Report user generated tag values. + * testsuite/binutils-all/dwarf-attributes.S: New test. + * testsuite/binutils-all/dwarf-attributes.W. Expected output from + readelf. + * testsuite/binutils-all/readelf.exp: Run the new test. + 2017-10-10 Tom Tromey * dwarf-mode.el: Bump to version 1.4. diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 2506d533b6..06702ef42d 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -963,13 +963,16 @@ process_abbrev_section (unsigned char *start, unsigned char *end) static const char * get_TAG_name (unsigned long tag) { - const char *name = get_DW_TAG_name ((unsigned int)tag); + const char *name = get_DW_TAG_name ((unsigned int) tag); if (name == NULL) { static char buffer[100]; - snprintf (buffer, sizeof (buffer), _("Unknown TAG value: %lx"), tag); + if (tag >= DW_TAG_lo_user && tag <= DW_TAG_hi_user) + snprintf (buffer, sizeof (buffer), _("User TAG value: %#lx"), tag); + else + snprintf (buffer, sizeof (buffer), _("Unknown TAG value: %#lx"), tag); return buffer; } @@ -2238,6 +2241,12 @@ read_and_display_attr_value (unsigned long attribute, case DW_ATE_edited: printf ("(edited)"); break; case DW_ATE_signed_fixed: printf ("(signed_fixed)"); break; case DW_ATE_unsigned_fixed: printf ("(unsigned_fixed)"); break; + /* DWARF 4 values: */ + case DW_ATE_UTF: printf ("(unicode string)"); break; + /* DWARF 5 values: */ + case DW_ATE_UCS: printf ("(UCS)"); break; + case DW_ATE_ASCII: printf ("(ASCII)"); break; + /* HP extensions: */ case DW_ATE_HP_float80: printf ("(HP_float80)"); break; case DW_ATE_HP_complex_float80: printf ("(HP_complex_float80)"); break; @@ -2246,8 +2255,6 @@ read_and_display_attr_value (unsigned long attribute, case DW_ATE_HP_floathpintel: printf ("(HP_floathpintel)"); break; case DW_ATE_HP_imaginary_float80: printf ("(HP_imaginary_float80)"); break; case DW_ATE_HP_imaginary_float128: printf ("(HP_imaginary_float128)"); break; - /* DWARF 4 values: */ - case DW_ATE_UTF: printf ("(unicode string)"); break; default: if (uvalue >= DW_ATE_lo_user @@ -2283,6 +2290,22 @@ read_and_display_attr_value (unsigned long attribute, } break; + case DW_AT_endianity: + printf ("\t"); + switch (uvalue) + { + case DW_END_default: printf ("(default)"); break; + case DW_END_big: printf ("(big)"); break; + case DW_END_little: printf ("(little)"); break; + default: + if (uvalue >= DW_END_lo_user && uvalue <= DW_END_hi_user) + printf (_("(user specified)")); + else + printf (_("(unknown endianity)")); + break; + } + break; + case DW_AT_virtuality: printf ("\t"); switch (uvalue) @@ -2313,6 +2336,10 @@ read_and_display_attr_value (unsigned long attribute, case DW_CC_normal: printf ("(normal)"); break; case DW_CC_program: printf ("(program)"); break; case DW_CC_nocall: printf ("(nocall)"); break; + case DW_CC_pass_by_reference: printf ("(pass by ref)"); break; + case DW_CC_pass_by_value: printf ("(pass by value)"); break; + case DW_CC_GNU_renesas_sh: printf ("(Rensas SH)"); break; + case DW_CC_GNU_borland_fastcall_i386: printf ("(Borland fastcall i386)"); break; default: if (uvalue >= DW_CC_lo_user && uvalue <= DW_CC_hi_user) @@ -2326,12 +2353,47 @@ read_and_display_attr_value (unsigned long attribute, printf ("\t"); switch (uvalue) { + case 255: case -1: printf (_("(undefined)")); break; case 0: printf ("(row major)"); break; case 1: printf ("(column major)"); break; } break; + case DW_AT_decimal_sign: + printf ("\t"); + switch (uvalue) + { + case DW_DS_unsigned: printf (_("(unsigned)")); break; + case DW_DS_leading_overpunch: printf (_("(leading overpunch)")); break; + case DW_DS_trailing_overpunch: printf (_("(trailing overpunch)")); break; + case DW_DS_leading_separate: printf (_("(leading separate)")); break; + case DW_DS_trailing_separate: printf (_("(trailing separate)")); break; + default: printf (_("(unrecognised)")); break; + } + break; + + case DW_AT_defaulted: + printf ("\t"); + switch (uvalue) + { + case DW_DEFAULTED_no: printf (_("(no)")); break; + case DW_DEFAULTED_in_class: printf (_("(in class)")); break; + case DW_DEFAULTED_out_of_class: printf (_("(out of class)")); break; + default: printf (_("(unrecognised)")); break; + } + break; + + 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; + } + break; + case DW_AT_frame_base: have_frame_base = 1; /* Fall through. */ diff --git a/binutils/testsuite/binutils-all/dwarf-attributes.S b/binutils/testsuite/binutils-all/dwarf-attributes.S new file mode 100644 index 0000000000..1d88a7c0b1 --- /dev/null +++ b/binutils/testsuite/binutils-all/dwarf-attributes.S @@ -0,0 +1,133 @@ +/* Copyright (C) 2017 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +/* This file is intended to check the encoding and decoding of DWARF attributes. + Currently only numeric attributes are tested, but this file should be extended + to cover other types of attribute as well. */ + + .file "dwarf-attributes.S" + + .section .debug_info,"",%progbits + .4byte .Ldebug_info_end - .Ldebug_info_start /* Length of Compilation Unit Info. */ + +.Ldebug_info_start: + .2byte 0x5 /* DWARF version number. */ + .byte 0x1 /* DW_UT_compile. */ + .byte 0x4 /* Pointer Size (in bytes). */ + .4byte .Ldebug_abbrevs /* Offset Into Abbrev. Section. */ + + /* Start of DIE 0xc. */ + + .uleb128 0x1 /* Using abbrev #1 */ + .byte 1 /* Ordering: column major. */ + .2byte 1 /* Language: C89. */ + .byte 1 /* Visibility: local. */ + .byte 1 /* Inline: inlined. */ + .byte 1 /* Accessibility: public. */ + .byte 1 /* Calling convention: normal. */ + .byte 1 /* Discriminate list: range. */ + .byte 1 /* Encoding: address. */ + .byte 1 /* Identifier case: up. */ + .byte 1 /* Virtuality: virtual. */ + .byte 1 /* Decimal sign: unsigned. */ + .byte 1 /* Endianity: big. */ + .byte 1 /* Defaulted: in class. */ + + .uleb128 0x1 /* Using abbrev #1 */ + .byte 0 /* Ordering: row major */ + .2byte 0x0016 /* Language: Go. */ + .byte 2 /* Visibility: exported. */ + .byte 0 /* Inline: not. */ + .byte 2 /* Accessibility: protected. */ + .byte 5 /* Calling convention: pass by value. */ + .byte 0 /* Discriminate list: label. */ + .byte 0x12 /* Encoding: ASCII. */ + .byte 0 /* Identifier case: sensitive. */ + .byte 0 /* Virtuality: none. */ + .byte 2 /* Decimal sign: leading overpunch. */ + .byte 0 /* Endianity: default. */ + .byte 0 /* Defaulted: no. */ + + .uleb128 0x1 /* Using abbrev #1 */ + .byte -1 /* Ordering: undefined. */ + .2byte 0x8001 /* Language: MIPS Assembler. */ + .byte 3 /* Visibility: qualified. */ + .byte 3 /* Inline: declared. */ + .byte 3 /* Accessibility: private. */ + .byte 0x40 /* Calling convention: Renesas SH. */ + .byte 1 /* Discriminate list: range. */ + .byte 0x81 /* Encoding: user specified. */ + .byte 3 /* Identifier case: insensitive. */ + .byte 2 /* Virtuality: pure. */ + .byte 5 /* Decimal sign: trailing separate. */ + .byte 0x50 /* Endianity: user specified. */ + .byte 2 /* Defaulted: out of class. */ + + .byte 0 /* End of children of DIE 0xc. */ +.Ldebug_info_end: + + + .section .debug_abbrev,"",%progbits +.Ldebug_abbrevs: + .uleb128 0x1 /* (abbrev code) */ + .uleb128 0x5555 /* (TAG: DW_TAG_lo_user + 0x1555) */ + .byte 0 /* DW_children_no */ + + /* Attributes to be tested. Sorted by attribute value. */ + + .uleb128 0x9 /* (DW_AT_ordering) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .uleb128 0x13 /* (DW_AT_language) */ + .uleb128 0x05 /* (DW_FORM_data2) */ + + .uleb128 0x17 /* (DW_AT_visibility) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .uleb128 0x20 /* (DW_AT_inline) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .uleb128 0x32 /* (DW_AT_accessibility) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .uleb128 0x36 /* (DW_AT_calling_convention) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .uleb128 0x3d /* (DW_AT_discr_lists) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .uleb128 0x3e /* (DW_AT_encoding) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .uleb128 0x42 /* (DW_AT_identifier_case) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .uleb128 0x4c /* (DW_AT_virtuality) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .uleb128 0x5e /* (DW_AT_decimal_sign) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .uleb128 0x65 /* (DW_AT_endianity) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .uleb128 0x8b /* (DW_AT_defaulted) */ + .uleb128 0x0b /* (DW_FORM_data1) */ + + .byte 0 /* End of abbreviation. */ + .byte 0 + + .byte 0 /* End of abbreviations. */ diff --git a/binutils/testsuite/binutils-all/dwarf-attributes.W b/binutils/testsuite/binutils-all/dwarf-attributes.W new file mode 100644 index 0000000000..d10e0c64f0 --- /dev/null +++ b/binutils/testsuite/binutils-all/dwarf-attributes.W @@ -0,0 +1,49 @@ +Contents of the .debug_info section: + + Compilation Unit @ offset 0x0: + Length: 0x36 \(32-bit\) + Version: 5 + Abbrev Offset: 0x0 + Pointer Size: 4 + <0>: Abbrev Number: 1 \(User TAG value: 0x5555\) + DW_AT_ordering : 1 \(column major\) + DW_AT_language : 1 \(ANSI C\) + <10> DW_AT_visibility : 1 \(local\) + <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\) diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp index 81d1809225..10fd8d8da7 100644 --- a/binutils/testsuite/binutils-all/readelf.exp +++ b/binutils/testsuite/binutils-all/readelf.exp @@ -420,14 +420,15 @@ if {![binutils_assemble $srcdir/$subdir/z.s tmpdir/z.o]} then { readelf_test {--decompress --hex-dump .debug_loc} $tempfile readelf.z {} } -# Skip the next test for the RISCV architectures because they do not -# support .ULEB128 pseudo-ops with non-constant values. +# Skip the next test for the RISCV architectures because they +# do not support .ULEB128 pseudo-ops with non-constant values. if ![istarget "riscv*-*-*"] then { set hpux "" if [istarget "hppa*64*-*-hpux*"] { set hpux "--defsym HPUX=1" } + # Assemble the DWARF-5 test file. if {![binutils_assemble_flags $srcdir/$subdir/dw5.S tmpdir/dw5.o $hpux]} then { unresolved "readelf -wiaoRlL dw5 (failed to assemble)" @@ -447,3 +448,21 @@ if ![istarget "riscv*-*-*"] then { readelf_test -wiaoRlL $tempfile dw5.W { nds32*-elf } } } + +# Assemble the DWARF-5 attributes test file. +if {![binutils_assemble_flags $srcdir/$subdir/dwarf-attributes.S tmpdir/dwarf-attributes.o ""]} then { + unresolved "readelf -wi dwarf-attributes (failed to assemble)" +} else { + # Download it. + if ![is_remote host] { + set tempfile tmpdir/dwarf-attributes.o + } else { + set tempfile [remote_download host tmpdir/dwarf-attributes.o] + } + + # First, determine the size, so specific output matchers can be used. + readelf_find_size $tempfile + + # Make sure that readelf can decode the contents. + readelf_test -wi $tempfile dwarf-attributes.W {} +}