From patchwork Wed Mar 30 18:19:56 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 88949 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id BD8B2B6F10 for ; Thu, 31 Mar 2011 05:20:18 +1100 (EST) Received: (qmail 15879 invoked by alias); 30 Mar 2011 18:20:13 -0000 Received: (qmail 15865 invoked by uid 22791); 30 Mar 2011 18:20:10 -0000 X-SWARE-Spam-Status: No, hits=-5.7 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_TM, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 30 Mar 2011 18:20:00 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p2UIJxGt007631 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 30 Mar 2011 14:19:59 -0400 Received: from localhost.localdomain (ovpn-113-100.phx2.redhat.com [10.3.113.100]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p2UIJv2H004949 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 30 Mar 2011 14:19:59 -0400 Received: by localhost.localdomain (Postfix, from userid 500) id 5A04B8E604B; Wed, 30 Mar 2011 20:19:56 +0200 (CEST) From: Dodji Seketeli To: Richard Henderson Cc: Jan Kratochvil , GCC Patches Subject: [PATCH] PR debug/47471 (set prologue_end in .debug_line) X-URL: http://www.redhat.com Date: Wed, 30 Mar 2011 20:19:56 +0200 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hello, This is about the line program emitted by the compiler into the .debug_line section, without optimization. In the example accompanying the patch below, at the beginning of the function f, the compiler emits two .loc asm directives that are identical. The first one is right before the .cfi_startproc that starts the prologue. The second one is before the instructions that copy the variable length parameters into f's frame. Both directives do locate instructions that are in the prologue. Unfortunately, GDB uses an heuristic that basically considers that the first opcode of the line program that increments the line register (even with an increment of zero) marks the end of the prologue. Effectively, setting a breakpoint to the beginning of f (e.g, "break f") won't work anymore when we emit this because GDB would then try to set the breakpoint inside the prologue. This patch does two things. First, it avoids emitting two consecutive .loc that are identical. Strictly speaking that should fix this issue in this particular case. Second, it emits a '.loc 0 prologue_end' directive on the first instruction that doesn't belong to the prologue (i.e, when the end_prologue debug hook is called). This sets the prologue_end register in the .debug_line state machine to true. After discussing this with Jan (in CC), it appears that setting the prologue_end register to true will help GDB to drop the somewhat non-reliable heuristic it uses to detect the end of the prologue. I have noticed that the end_prologue debug hook was being called, but the dwarf back-end hasn't implemented it (on non-vms platforms). Is there a particular reason for not implementing this? Also, I have noticed that the patch causes the prologue_end directive to be emitted even when we compile with optimizations. I am not sure how right that would be. Tested on x86_64-unknown-linux-gnu against trunk. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index efd30ea..6f8285c 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -94,6 +94,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-flow.h" #include "cfglayout.h" +static void output_source_line_asm_info (unsigned int, const char *, + int, bool, bool); static void dwarf2out_source_line (unsigned int, const char *, int, bool); static rtx last_var_location_insn; @@ -465,6 +467,7 @@ static void output_call_frame_info (int); static void dwarf2out_note_section_used (void); static bool clobbers_queued_reg_save (const_rtx); static void dwarf2out_frame_debug_expr (rtx, const char *); +static void dwarf2out_end_prologue (unsigned int, const char*); /* Support for complex CFA locations. */ static void output_cfa_loc (dw_cfi_ref, int); @@ -4125,6 +4128,21 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED, } } +/* Implementation of the gcc_debug_hooks::end_prologue hook. + + If the underlying assembler supports it, emit a .loc asm directive + with a 'end_prologue' argument, effectively marking the point where + debugger should set a breakpoint when requested to set one on a + function. */ + +static void +dwarf2out_end_prologue (unsigned int line, const char *filename) +{ + output_source_line_asm_info (line, filename, 0, + /*is_stmt=*/true, + /*is_prologue_end*/true); +} + /* Output a marker (i.e. a label) for the end of the generated code for a function prologue. This gets called *after* the prologue code has been generated. */ @@ -5767,7 +5785,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = dwarf2out_vms_end_prologue, dwarf2out_vms_begin_epilogue, #else - debug_nothing_int_charstar, + dwarf2out_end_prologue, debug_nothing_int_charstar, #endif dwarf2out_end_epilogue, @@ -22129,14 +22147,22 @@ dwarf2out_begin_function (tree fun) /* Output a label to mark the beginning of a source code line entry and record information relating to this source line, in - 'line_info_table' for later output of the .debug_line section. */ + 'line_info_table' for later output of the .debug_line section. + + If the underlying assembler supports the .loc directive, use it + instead of emiting .debug_line state machine operations ourselves. + + The arguments of the functions set their counterpart into the + .debug_line state machine registers. + + This is a subroutine of dwarf2out_source_line and and + dwarf2out_end_prologue. */ static void -dwarf2out_source_line (unsigned int line, const char *filename, - int discriminator, bool is_stmt) +output_source_line_asm_info (unsigned int line, const char *filename, + int discriminator, bool is_stmt, + bool is_prologue_end) { - static bool last_is_stmt = true; - if (debug_info_level >= DINFO_LEVEL_NORMAL && line != 0) { @@ -22151,19 +22177,42 @@ dwarf2out_source_line (unsigned int line, const char *filename, if (DWARF2_ASM_LINE_DEBUG_INFO) { - /* Emit the .loc directive understood by GNU as. */ - fprintf (asm_out_file, "\t.loc %d %d 0", file_num, line); - if (is_stmt != last_is_stmt) + static int last_file_num = -1; + static unsigned last_line = 0; + static int last_discriminator = -1; + static bool last_is_stmt = true; + static int last_is_prologue_end = -1; + + if (last_file_num != file_num + || last_line != line + || last_is_stmt != is_stmt + || last_discriminator != discriminator + || last_is_prologue_end != is_prologue_end) { - fprintf (asm_out_file, " is_stmt %d", is_stmt ? 1 : 0); - last_is_stmt = is_stmt; - } - if (SUPPORTS_DISCRIMINATOR && discriminator != 0) - fprintf (asm_out_file, " discriminator %d", discriminator); - fputc ('\n', asm_out_file); + /* Emit the .loc directive understood by GNU as. */ + fprintf (asm_out_file, "\t.loc %d %d 0", file_num, line); - /* Indicate that line number info exists. */ - line_info_table_in_use++; + if (is_stmt != last_is_stmt) + { + fprintf (asm_out_file, " is_stmt %d", is_stmt ? 1 : 0); + last_is_stmt = is_stmt; + } + + if (is_prologue_end) + fprintf (asm_out_file, " prologue_end"); + + if (SUPPORTS_DISCRIMINATOR && discriminator != 0) + fprintf (asm_out_file, " discriminator %d", discriminator); + fputc ('\n', asm_out_file); + + /* Indicate that line number info exists. */ + line_info_table_in_use++; + + last_file_num = file_num; + last_line = line; + last_discriminator = discriminator; + last_is_prologue_end = is_prologue_end; + } } else if (function_section (current_function_decl) != text_section) { @@ -22245,6 +22294,18 @@ dwarf2out_start_source_file (unsigned int lineno, const char *filename) } } +/* Output a label to mark the beginning of a source code line entry + and record information relating to this source line, in + 'line_info_table' for later output of the .debug_line section. */ + +static void +dwarf2out_source_line (unsigned int line, const char *filename, + int discriminator, bool is_stmt) +{ + output_source_line_asm_info (line, filename, discriminator, + is_stmt, /*is_prolog_end=*/false); +} + /* Record the end of a source file. */ static void