From patchwork Mon Feb 23 14:46:27 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Machata X-Patchwork-Id: 5243 Received: (qmail 31738 invoked by alias); 23 Feb 2015 14:46:45 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 31065 invoked by uid 89); 23 Feb 2015 14:46:32 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Mon, 23 Feb 2015 14:46:31 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t1NEkU4i012539 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Mon, 23 Feb 2015 09:46:30 -0500 Received: from t540p (ovpn-116-86.ams2.redhat.com [10.36.116.86]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t1NEkRf3023229 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 23 Feb 2015 09:46:29 -0500 From: Petr Machata To: gdb-patches@sourceware.org Subject: [PATCH V2] dwarf.exp: Allow generating a stub .debug_line section Date: Mon, 23 Feb 2015 15:46:27 +0100 Message-ID: <87h9uc1y9o.fsf@redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.4 (gnu/linux) MIME-Version: 1.0 Hello, this is half ping, half V2 of the patch that I sent last week. I fixed a bug in generating the header since V1. This is what I wrote last week, and it all still holds: like GDB itself, dwgrep uses dwarf.exp to fabricate Dwarfs for its test cases. For one test case, I need to create a stub .debug_line section and reference files defined therein from DW_AT_decl_file. Hence this patch, which implements generating barest minimum of .debug_line. I suspect this could be useful for GDB as well, git grep showed me some .exp's creating .debug_line by hand, but I didn't really take a close look. There were no regressions on x86_64. Example of use: Dwarf::assemble "foo.s" { build_id 0102030405060708 cu {is_64 0 version 4 addr_size 8} { DW_TAG_compile_unit { {MACRO_AT_stmt_list { {include "foo"} {file_name "foo.c" 1} }} } { DW_TAG_subprogram { # We can now reference the source file. {DW_AT_decl_file 1 DW_FORM_data1} } } } } I do not have commit rights, so if this patch is acceptable, I will need someone to commit this for me. Let me know what you think. Thanks, --8<------------------------------------------------------------------ Signed-off-by: Petr Machata --- gdb/testsuite/ChangeLog | 6 +++ gdb/testsuite/lib/dwarf.exp | 112 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 1e36b45..47fc450 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-02-17 Petr Machata + + * lib/dwarf.exp (Dwarf::_handle_DW_FORM): Handle DW_FORM_sec_offset. + (Dwarf::_handle_macro_at_stmt_list): New function. + (Dwarf::_handle_DW_TAG): Handle new macro MACRO_AT_stmt_list. + 2015-02-17 Jose E. Marchesi * lib/dtrace.exp: New file. diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index 8ea7a0f..bfcccbc 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -205,6 +205,19 @@ proc function_range { func src } { # - MACRO_AT_func { FUNC FILE } # It is substituted by DW_AT_name with FUNC and MACRO_AT_range. # +# - MACRO_AT_stmt_list { LIST_OF_DIRECTIVES } +# It is substituted by DW_AT_stmt_list with value referencing a +# newly-created .debug_line section with data as described by the +# directives. Individual directives can be: +# +# - {include NAME} +# defines a new include directory +# +# - {file_name NAME DIRIDX} +# defines a new file with NAME, defined in the directory +# specified by DIRIDX-th include directive (numbered from 1, with +# 0 meaning current directory, as specified in Dwarf standard). +# # If FORM is given, it should name a DW_FORM_ constant. # This can either be the short form, like 'DW_FORM_addr', or a # shortened version, like 'addr'. If the form is given, VALUE @@ -422,6 +435,11 @@ namespace eval Dwarf { _op .${size}byte $value } + DW_FORM_sec_offset { + variable _cu_offset_size + _op .${_cu_offset_size}byte $value + } + DW_FORM_ref1 - DW_FORM_flag - DW_FORM_data1 { @@ -494,7 +512,6 @@ namespace eval Dwarf { DW_FORM_ref2 - DW_FORM_indirect - - DW_FORM_sec_offset - DW_FORM_exprloc - DW_FORM_GNU_addr_index - @@ -586,6 +603,97 @@ namespace eval Dwarf { _handle_macro_at_range $attr_value } + # Handle macro attribute MACRO_AT_stmt_list. + + proc _handle_macro_at_stmt_list { attr_value } { + variable _cu_count + + set dirlist [list ""] + set filelist {} + proc include { dirname } { + upvar 1 dirlist dirlist + lappend dirlist $dirname + } + proc file_name { filename diridx } { + upvar 1 dirlist dirlist + if {![expr $diridx >= 0 && $diridx < [llength $dirlist]]} { + error [concat "Directory index out of bounds: $diridx." \ + "Use \"include\" to define directories."] + } + + upvar 1 filelist filelist + lappend filelist [list $filename $diridx 0 0] + } + + foreach cmd $attr_value { + {*}$cmd + } + + set unit_label [_compute_label "line${_cu_count}"] + set unit_len_label [_compute_label "line${_cu_count}_start"] + set unit_end_label [_compute_label "line${_cu_count}_end"] + set header_len_label [_compute_label "line${_cu_count}_header_start"] + set header_end_label [_compute_label "line${_cu_count}_header_end"] + + _defer_output ".debug_line" { + define_label $unit_label + _op .4byte "$unit_end_label - $unit_len_label" "unit_length" + define_label $unit_len_label + _op .2byte 0x2 version + _op .4byte "$header_end_label - $header_len_label" "header_length" + define_label $header_len_label + _op .byte 1 "minimum_instruction_length" + _op .byte 0 "default_is_stmt" + _op .byte 1 "line_base" + _op .byte 1 "line_range" + _op .byte 1 "opcode_base" + # Since we emit opcode_base==1, we skip + # standard_opcode_length table altogether. + } + + # Ignore the first dummy entry in DIRLIST when emitting. + foreach dirname [lrange $dirlist 1 end] { + _defer_output ".debug_line" { + _op .ascii [_quote $dirname] "include" + } + } + + _defer_output ".debug_line" { + _op .byte 0 "Terminator." + } + + foreach entry $filelist { + set fn [lindex $entry 0] + set diridx [lindex $entry 1] + set mtime [lindex $entry 2] + set length [lindex $entry 3] + + set dir [lindex $dirlist $diridx] + set full_fn [file join $dir $fn] + + _defer_output ".debug_line" { + _op .ascii [_quote $fn] $full_fn + _op .sleb128 $diridx + _op .sleb128 $mtime + _op .sleb128 $length + } + } + + variable _cu_version + if {[expr $_cu_version > 3]} { + set form DW_FORM_sec_offset + } else { + set form DW_FORM_data4 + } + _handle_attribute DW_AT_stmt_list "$unit_label" $form + + _defer_output ".debug_line" { + _op .byte 0 "Terminator." + define_label $header_end_label + define_label $unit_end_label + } + } + proc _handle_DW_TAG {tag_name {attrs {}} {children {}}} { variable _abbrev_section variable _abbrev_num @@ -612,6 +720,8 @@ namespace eval Dwarf { _handle_macro_at_func $attr_value } elseif { [string equal "MACRO_AT_range" $attr_name] } { _handle_macro_at_range $attr_value + } elseif { [string equal "MACRO_AT_stmt_list" $attr_name] } { + _handle_macro_at_stmt_list $attr_value } else { if {[llength $attr] > 2} { set attr_form [lindex $attr 2]