From f13a9a0cf7d13b9ea51b0df4b9fa469652f92338 Mon Sep 17 00:00:00 2001 From: Yao Qi Date: Wed, 25 Jan 2017 16:24:44 +0000 Subject: [PATCH] Use dwarf assembler in gdb.dwarf2/implptr-64bit.exp This patch adds a DW_OP_implicit_value in dwarf assembler, and uses dwarf assembler in implptr-64bit.exp. Using dwarf assembler in implptr-64bit.exp exposes some limitations in dwarf assembler, - some variables are not evaluated in the caller's context, so we can not pass variable to assembler, like this Dwarf::assemble $asm_file { cu { version $dwarf_version addr_size $addr_size is_64 $is_64 } { } and {DW_AT_type :$struct_label "DW_FORM_ref$ref_addr_size"} this limitation is fixed by adding "uplevel" and "subst". - dwarf assembler doesn't emit DW_FORM_ref_addr for label referencing. this limitation is fixed by adding a new character "%", { type %$int_label } this means we want to emit DW_FORM_ref_addr for label referencing. - we can't set the form of label referencing offset in dwarf assembler. Nowadays, dwarf assembler guesses the form of labels, which is DW_FORM_ref4. However, in implptr-64bit.exp, both DW_FORM_ref4 and DW_FORM_ref8 is used (see REF_ADDR in implptr-64bit.S). This patch adds the flexibility of setting the form of label reference. Both of them below are valid, {DW_AT_type :$struct_label} {DW_AT_type :$struct_label DW_FORM_ref8} the former form is the default DW_FORM_ref4. I compared the .debug_info of objects without and with this patch applied. There is no changes except abbrev numbers. gdb/testsuite: 2017-01-25 Andreas Arnez Yao Qi * gdb.dwarf2/implptr-64bit.exp: Use dwarf assembler. * gdb.dwarf2/implptr-64bit.S: Remove. * lib/dwarf.exp (Dwarf): Handle character "%". Evaluate some variables in caller's context. Add DW_OP_implicit_value. --- gdb/testsuite/ChangeLog | 8 + gdb/testsuite/gdb.dwarf2/implptr-64bit.S | 226 --------------------- gdb/testsuite/gdb.dwarf2/implptr-64bit.exp | 118 ++++++++++- gdb/testsuite/lib/dwarf.exp | 38 +++- 4 files changed, 154 insertions(+), 236 deletions(-) delete mode 100644 gdb/testsuite/gdb.dwarf2/implptr-64bit.S diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index aa272e345de..28e337a9553 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2017-01-25 Andreas Arnez + Yao Qi + + * gdb.dwarf2/implptr-64bit.exp: Use dwarf assembler. + * gdb.dwarf2/implptr-64bit.S: Remove. + * lib/dwarf.exp (Dwarf): Handle character "%". Evaluate some + variables in caller's context. Add DW_OP_implicit_value. + 2017-01-25 Yao Qi * lib/dwarf.exp (Dwarf::_location): Handle diff --git a/gdb/testsuite/gdb.dwarf2/implptr-64bit.S b/gdb/testsuite/gdb.dwarf2/implptr-64bit.S deleted file mode 100644 index 003bf201de6..00000000000 --- a/gdb/testsuite/gdb.dwarf2/implptr-64bit.S +++ /dev/null @@ -1,226 +0,0 @@ -/* Copyright 2010-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 . */ - - .section .debug_info -d: - /* Length of Compilation Unit Info */ -#if OFFSET_SIZE == 4 -# define OFFSET .4byte -# define HEADER_LINE1 -# define HEADER_LINE2(END) .4byte END - 1f -#elif OFFSET_SIZE == 8 -# define OFFSET .8byte -# define HEADER_LINE1 .4byte 0xffffffff -# define HEADER_LINE2(END) .8byte END - 1f -#else -# error -#endif -#if ADDR_SIZE == 4 -# define ADDR .4byte -#elif ADDR_SIZE == 8 -# define ADDR .8byte -#else -# error -#endif -#if REF_ADDR_SIZE == 4 -# define REF_ADDR .4byte -#elif REF_ADDR_SIZE == 8 -# define REF_ADDR .8byte -#else -# error -#endif - -#if TWO_CU -# define END1 .Lcu_end_1 -#else -# define END1 debug_end -#endif - - HEADER_LINE1 - HEADER_LINE2(END1) - -1: - .2byte DWARF_VERSION /* DWARF version number */ - OFFSET .Ldebug_abbrev0 /* Offset Into Abbrev. Section */ - .byte ADDR_SIZE /* Pointer Size (in bytes) */ - - .uleb128 0x1 /* (DIE (0xb) DW_TAG_compile_unit) */ - .ascii "GNU C 4.4.3\0" /* DW_AT_producer */ - .byte 0x1 /* DW_AT_language */ - .ascii "1.c\0" /* DW_AT_name */ - -.Ltype_int: - .uleb128 0x7 /* DW_TAG_base_type */ - .byte 0x4 /* DW_AT_byte_size */ - .byte 0x5 /* DW_AT_encoding */ - .ascii "int\0" /* DW_AT_name */ - -.Ltype_struct: - .uleb128 0x2 /* DW_TAG_structure_type */ - .ascii "s\0" /* DW_AT_name */ - .byte 4 /* DW_AT_byte_size */ - - .uleb128 0x3 /* DW_TAG_member */ - .ascii "f\0" /* DW_AT_name */ - .4byte .Ltype_int - d /* DW_AT_type */ - .byte 0 /* DW_AT_data_member_location */ - - .byte 0x0 /* end of children of DW_TAG_structure_type */ - -.Ltype_structptr: - .uleb128 0x5 /* DW_TAG_pointer_type */ - .byte ADDR_SIZE /* DW_AT_byte_size */ - .4byte .Ltype_struct - d /* DW_AT_type */ - -.Lvar_out: - .uleb128 0x4 /* (DW_TAG_variable) */ - .ascii "v\0" /* DW_AT_name */ - .byte 2f - 1f /* DW_AT_location: DW_FORM_block1 */ -1: - .byte 0x9e /* DW_OP_implicit_value */ - .uleb128 2f - 3f -3: - .byte 1, 1, 1, 1 -2: - REF_ADDR .Ltype_struct - d /* DW_AT_type */ - -#if TWO_CU - .byte 0x0 /* end of children of CU */ -.Lcu_end_1: - - HEADER_LINE1 - HEADER_LINE2 (debug_end) - -1: - .2byte DWARF_VERSION /* DWARF version number */ - OFFSET .Ldebug_abbrev0 /* Offset Into Abbrev. Section */ - .byte ADDR_SIZE /* Pointer Size (in bytes) */ - - .uleb128 0x1 /* (DIE (0xb) DW_TAG_compile_unit) */ - .ascii "GNU C 4.4.3\0" /* DW_AT_producer */ - .byte 0x1 /* DW_AT_language */ - .ascii "1.c\0" /* DW_AT_name */ -#endif - - .uleb128 6 /* Abbrev: DW_TAG_subprogram */ - .ascii "main\0" /* DW_AT_name */ - ADDR main /* DW_AT_low_pc */ - ADDR main + 0x100 /* DW_AT_high_pc */ - REF_ADDR .Ltype_int - d /* DW_AT_type */ - .byte 1 /* DW_AT_external */ - - .uleb128 0x4 /* (DW_TAG_variable) */ - .ascii "p\0" /* DW_AT_name */ - .byte 2f - 1f /* DW_AT_location: DW_FORM_block1 */ -1: - .byte 0xf2 /* DW_OP_GNU_implicit_pointer */ - REF_ADDR .Lvar_out - d /* referenced DIE */ - .sleb128 0 /* offset */ -2: - REF_ADDR .Ltype_structptr - d /* DW_AT_type */ - - .byte 0x0 /* end of children of main */ - - .byte 0x0 /* end of children of CU */ -debug_end: - - .section .debug_abbrev -.Ldebug_abbrev0: - - .uleb128 0x1 /* (abbrev code) */ - .uleb128 0x11 /* (TAG: DW_TAG_compile_unit) */ - .byte 0x1 /* DW_children_yes */ - .uleb128 0x25 /* (DW_AT_producer) */ - .uleb128 0x8 /* (DW_FORM_string) */ - .uleb128 0x13 /* (DW_AT_language) */ - .uleb128 0xb /* (DW_FORM_data1) */ - .uleb128 0x3 /* (DW_AT_name) */ - .uleb128 0x8 /* (DW_FORM_string) */ - .byte 0x0 - .byte 0x0 - - .uleb128 0x2 /* (abbrev code) */ - .uleb128 0x13 /* (TAG: DW_TAG_structure_type) */ - .byte 0x1 /* DW_children_yes */ - .uleb128 0x3 /* (DW_AT_name) */ - .uleb128 0x8 /* (DW_FORM_string) */ - .uleb128 0xb /* (DW_AT_byte_size) */ - .uleb128 0xb /* (DW_FORM_data1) */ - .byte 0 - .byte 0 - - .uleb128 0x3 /* (abbrev code) */ - .uleb128 0xd /* (TAG: DW_TAG_member) */ - .byte 0 /* DW_children_no */ - .uleb128 0x3 /* (DW_AT_name) */ - .uleb128 0x8 /* (DW_FORM_string) */ - .uleb128 0x49 /* (DW_AT_type) */ - .uleb128 0x13 /* (DW_FORM_ref4) */ - .uleb128 0x38 /* (DW_AT_data_member_location) */ - .uleb128 0xb /* (DW_FORM_data1) */ - .byte 0 - .byte 0 - - .uleb128 0x4 /* (abbrev code) */ - .uleb128 0x34 /* (TAG: DW_TAG_variable) */ - .byte 0x0 /* DW_children_yes */ - .uleb128 0x3 /* (DW_AT_name) */ - .uleb128 0x8 /* (DW_FORM_string) */ - .uleb128 0x02 /* (DW_AT_location) */ - .uleb128 0xa /* (DW_FORM_block1) */ - .uleb128 0x49 /* (DW_AT_type) */ - .uleb128 0x10 /* (DW_FORM_ref_addr) */ - .byte 0x0 - .byte 0x0 - - .uleb128 0x5 /* (abbrev code) */ - .uleb128 0xf /* (TAG: DW_TAG_pointer_type) */ - .byte 0x0 /* DW_children_no */ - .uleb128 0xb /* (DW_AT_byte_size) */ - .uleb128 0xb /* (DW_FORM_data1) */ - .uleb128 0x49 /* (DW_AT_type) */ - .uleb128 0x13 /* (DW_FORM_ref4) */ - .byte 0x0 - .byte 0x0 - - .uleb128 6 /* Abbrev code */ - .uleb128 0x2e /* DW_TAG_subprogram */ - .byte 1 /* has_children */ - .uleb128 0x3 /* DW_AT_name */ - .uleb128 0x8 /* DW_FORM_string */ - .uleb128 0x11 /* DW_AT_low_pc */ - .uleb128 0x1 /* DW_FORM_addr */ - .uleb128 0x12 /* DW_AT_high_pc */ - .uleb128 0x1 /* DW_FORM_addr */ - .uleb128 0x49 /* DW_AT_type */ - .uleb128 0x10 /* DW_FORM_ref_addr */ - .uleb128 0x3f /* DW_AT_external */ - .uleb128 0xc /* DW_FORM_flag */ - .byte 0x0 /* Terminator */ - .byte 0x0 /* Terminator */ - - .uleb128 0x7 /* (abbrev code) */ - .uleb128 0x24 /* (TAG: DW_TAG_base_type) */ - .byte 0 /* DW_children_no */ - .uleb128 0xb /* (DW_AT_byte_size) */ - .uleb128 0xb /* (DW_FORM_data1) */ - .uleb128 0x3e /* (DW_AT_encoding) */ - .uleb128 0xb /* (DW_FORM_data1) */ - .uleb128 0x3 /* (DW_AT_name) */ - .uleb128 0x8 /* (DW_FORM_string) */ - .byte 0 - .byte 0 - - .byte 0x0 diff --git a/gdb/testsuite/gdb.dwarf2/implptr-64bit.exp b/gdb/testsuite/gdb.dwarf2/implptr-64bit.exp index b4dcbdeb802..963cdc68ef2 100644 --- a/gdb/testsuite/gdb.dwarf2/implptr-64bit.exp +++ b/gdb/testsuite/gdb.dwarf2/implptr-64bit.exp @@ -19,21 +19,121 @@ if {![dwarf2_support]} { return 0 } -standard_testfile .S -set mainfile main.c +standard_testfile main.c proc test { dwarf_version offset_size addr_size ref_addr_size two_cu } { - global testfile srcfile mainfile + global testfile srcfile - # 32-bit targets do not support any of the testcases; keep quiet there. - set opts {quiet} - foreach n { dwarf_version offset_size addr_size ref_addr_size two_cu } { - lappend opts "additional_flags=-D[string toupper $n]=[expr "\$$n"]" + set name "d${dwarf_version}o${offset_size}a${addr_size}r${ref_addr_size}t${two_cu}" + + # Make some DWARF for the test. + set asm_file [standard_output_file ${testfile}-${name}.S] + Dwarf::assemble $asm_file { + upvar dwarf_version dwarf_version + upvar addr_size addr_size + upvar offset_size offset_size + upvar ref_addr_size ref_addr_size + upvar two_cu two_cu + + set is_64 [expr { $offset_size == 4 ? 0 : 1 }] + + cu { + version $dwarf_version + addr_size $addr_size + is_64 $is_64 + } { + compile_unit { + { producer "GNU C 4.4.3" } + { language @DW_LANG_C89 } + { name 1.c } + } { + declare_labels struct_label variable_label int_label pointer_label + + int_label: base_type { + { byte_size 4 DW_FORM_sdata } + { DW_AT_encoding @DW_ATE_signed } + { name int } + } + + struct_label: structure_type { + { name s } + { byte_size 4 sdata } + } { + member { + { name f } + { type :$int_label } + { data_member_location 0 data1 } + } + } + + pointer_label: pointer_type { + { byte_size $Dwarf::_cu_addr_size sdata } + { type :$struct_label } + } + + variable_label: DW_TAG_variable { + { name v } + { location { + DW_OP_implicit_value 0x1 0x1 0x1 0x1 + } SPECIAL_expr} + { type :$struct_label "DW_FORM_ref$ref_addr_size" } + } + + if { !$two_cu } { + subprogram { + { name main } + { low_pc main addr } + { high_pc "main+0x100" addr } + { type %$int_label } + { external 1 flag } + } { + DW_TAG_variable { + { name p } + { location { + GNU_implicit_pointer $variable_label 0 + } SPECIAL_expr } + { type :$pointer_label "DW_FORM_ref$ref_addr_size" } + } + } + } + } + } + + if { $two_cu } { + cu { + version $dwarf_version + addr_size $addr_size + is_64 $is_64 + } { + compile_unit { + { producer "GNU C 4.4.3" } + { language @DW_LANG_C89 } + { name 1.c } + } { + subprogram { + { name main } + { low_pc main addr } + { high_pc "main+0x100" addr } + { type %$int_label } + { external 1 flag } + } { + DW_TAG_variable { + { name p } + { location { + GNU_implicit_pointer $variable_label 0 + } SPECIAL_expr } + { type %$pointer_label } + } + } + } + } + } } - set name "d${dwarf_version}o${offset_size}a${addr_size}r${ref_addr_size}t${two_cu}" + # 32-bit targets do not support any of the testcases; keep quiet there. + set opts {quiet} set executable ${testfile}-${name} - if [prepare_for_testing "failed to prepare" $executable "${srcfile} ${mainfile}" $opts] { + if [prepare_for_testing "failed to prepare" $executable "${asm_file} ${srcfile}" $opts] { return -1 } diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index 03ae63746cb..149038c91e9 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -229,6 +229,8 @@ proc function_range { func src } { # * If VALUE starts with the ":" character, then it is a label # reference. The rest of VALUE is taken to be the name of a label, # and DW_FORM_ref4 is used. See 'new_label' and 'define_label'. +# * If VALUE starts with the "%" character, then it is a label +# reference too, but DW_FORM_ref_addr is used. # * Otherwise, VALUE is taken to be a string and DW_FORM_string is # used. In order to prevent bugs where a numeric value is given but # no form is specified, it is an error if the value looks like a number @@ -554,6 +556,15 @@ namespace eval Dwarf { return DW_FORM_ref4 } + % { + # Label reference, an offset from .debug_info. Assuming + # .Lcu1_begin is on .debug_info. + set cu1_label [_compute_label "cu1_begin"] + set new_value "[string range $value 1 end] - $cu1_label" + + return DW_FORM_ref_addr + } + default { return DW_FORM_string } @@ -649,7 +660,12 @@ namespace eval Dwarf { _handle_macro_at_range $attr_value } else { if {[llength $attr] > 2} { - set attr_form [lindex $attr end] + set attr_form [uplevel 2 [list subst [lindex $attr end]]] + + if { [string index $attr_value 0] == ":" } { + # It is a label, get its value. + _guess_form $attr_value attr_value + } } else { # If the value looks like an integer, a form is required. if [string is integer $attr_value] { @@ -907,6 +923,25 @@ namespace eval Dwarf { _op .2byte [lindex $line 1] } + DW_OP_implicit_value { + set l1 [new_label "value_start"] + set l2 [new_label "value_end"] + _op .uleb128 "$l2 - $l1" + define_label $l1 + foreach value [lrange $line 1 end] { + switch -regexp -- $value { + {^0x[[:xdigit:]]{1,2}$} {_op .byte $value} + {^0x[[:xdigit:]]{4}$} {_op .2byte $value} + {^0x[[:xdigit:]]{8}$} {_op .4byte $value} + {^0x[[:xdigit:]]{16}$} {_op .8byte $value} + default { + error "bad value '$value' in DW_OP_implicit_value" + } + } + } + define_label $l2 + } + DW_OP_GNU_implicit_pointer { if {[llength $line] != 3} { error "usage: DW_OP_GNU_implicit_pointer LABEL OFFSET" @@ -976,6 +1011,7 @@ namespace eval Dwarf { set _abbrev_section ".debug_abbrev" foreach { name value } $options { + set value [uplevel 1 "subst \"$value\""] switch -exact -- $name { is_64 { set is_64 $value } version { set _cu_version $value } -- 2.30.2