Mirror of the gdb mailing list
 help / color / mirror / Atom feed
From: Ross Morley <ross@tensilica.com>
Cc: gdb@sourceware.org
Subject: Re: RFC: Program Breakpoints
Date: Tue, 31 Mar 2009 00:44:00 -0000	[thread overview]
Message-ID: <49D16764.2040706@tensilica.com> (raw)
In-Reply-To: <49C7BDD6.3060305@tensilica.com>

I'm preparing the simplified version I described earlier for submission.

In stepping over a program break I increment the PC without running the
inferior (in step_1 of infcmd.c - see trimmed post below for context).
Then I update the frame cache and report the stop reason, new PC, etc.
My old pre-6.x implementation used a function that was deprecated in
6.x and recently removed.

What is the proper way to update the frame without the call to
   deprecated_update_frame_pc_hack (get_current_frame (), read_pc ());

I tried calling get_frame_pc (get_current_frame ()) and ignoring the result.
That should call frame_pc_unwind (). But the subsequent
    print_stack_frame (get_selected_frame (NULL), -1, LOC_AND_ADDRESS);
reports the address of the break to MI, not the incremented PC.

I also tried reinit_frame_cache () and it works OK. Seems drastic though.

For convenience, here's the code snippet from step_1 of infcmd.c:

  else if (STOPPED_BY_PROGRAM_BREAKPOINT (&program_break_size) &&
           program_break_size != 0 && read_pc() == stop_pc && count > 0)
    {
      /* "stepi" off program breakpoint: the first step is to just increment
         the PC past the break, then there are count-1 steps to go.
         Note proceed() won't be called the first time, and on subsequent
         steps the PC will already be off the break, so the entire handling
         of "stepi" off a program breakpoint is done here. If stopping 
after
         the break, display location information as for normal_stop.  */
      count--;
      write_pc (read_pc () + program_break_size);
      if (count == 0)
        {
          deprecated_update_frame_pc_hack (get_current_frame (), read_pc 
());
          if (ui_out_is_mi_like_p (uiout))
            {
              ui_out_field_string
                (uiout, "reason",
                 async_reason_lookup (EXEC_ASYNC_END_STEPPING_RANGE));
              ui_out_field_int (uiout, "thread-id",
                                pid_to_thread_id (inferior_ptid));
              print_stack_frame (get_selected_frame (NULL), -1, 
LOC_AND_ADDRESS);
            }
          else
            print_stack_frame (get_selected_frame (NULL), -1, SRC_LINE);
        }
    }


Thanks,
Ross


Ross Morley wrote:


>
> The Problem
> -----------
>
> When the target program hits a breakpoint of any kind, GDB receives
> a SIGTRAP event. As Aleksander pointed out, if the PC is not in the
> breakpoint table GDB stops because it doesn't know what to do with
> this event. In fact it doesn't always stop. When GDB is stepping
> (for example when a software watchpoint is set) it sees the SIGTRAP
> as a normal step event, so it continues stepping. If the break
> instruction didn't increment the PC, it keeps executing the same
> break instruction forever. This is very frustrating for users (who
> reported this as a bug) because when you have a s/w watchpoint and
> are stepping, execution is expected to be slow, so you wait a long
> time before you realize it's hung.
>
<stuff deleted>

> The Solution
> ------------
>
> The first part is to recognize when you hit a program break.
> The second is to step over it when you want to resume.
>
<stuff deleted>

> Having discovered that it stopped for a program breakpoint, GDB
> is able to report the fact to both the CLI and MI. I also defined
> a gdbarch function to report the meaning of "kind" in an arch-
> specific way. This improves the debugging experience when the
> target uses different kinds of breakpoints to denote different
> reasons for stopping. (However, in the interest of simplicity,
> my revised proposal won't report all that - it is anyway obvious
> from a disassembly if not a symbol associated with the PC; GDB
> itself only needs to know the size to skip the breakpoint).
>
> When the user elects to continue after a program breakpoint,
> GDB increments the PC by the size of the break that was reported
> in the "kind" argument. A gdbarch function handles this. Of
> course it might do nothing if the PC was already advanced.
>
> I haven't discussed all the implementation details here.
> Please see the attached 6.8 based patch for the actual code.
> Note this patch does not pretend to be ready for submission!
>
<stuff deleted>

> Proposed Improved, Simplified Solution
> --------------------------------------
>
> The remote protocol extension would be:
>    TAAtrap[:size]
> where ":size" is optional and may only be provided to GDB by the
> target agent if the PC is in fact pointing to the instruction
> that caused the break, and if omitted is taken to be 0.
> GDB will skip the break by PC += size (no effect if size is 0).
> Note it is not necessary to call gdbarch_breakpoint_from_pc().
>
> The gdbarch functions to extract the size and decipher "kind"
> are not needed. The target interface function
>    STOPPED_BY_PROGRAM_BREAKPOINT(k)
> becomes
>    STOPPED_BY_PROGRAM_BREAKPOINT(size)
> where 'size' is an address in which the size is returned.
>
> We might also want to consider calling it "program trap" and
> keep the term "breakpoint" for things that GDB knows about.
>
>
> Comments are welcome. We at Tensilica would like to see this
> refined and incorporated into mainline GDB.
>
> This can certainly coexist with permanent breakpoints,
> however it is (I think) a bit more general. If the people
> who use permanent breakpoints would care to comment,
> perhaps we can somehow reconcile these into one feature.
>
> Thanks,
> Ross Morley
> Tensilca, Inc.
> ross@tensilica.com
>
>
>diff -urN gdb-6.8-orig/gdb/infcmd.c gdb-6.8-new/gdb/infcmd.c
>--- gdb-6.8-orig/gdb/infcmd.c	2009-03-19 17:29:48.000000000 -0700
>+++ gdb-6.8-new/gdb/infcmd.c	2009-03-20 11:33:21.000000000 -0700
>@@ -696,6 +696,9 @@
>   struct frame_info *frame;
>   struct cleanup *cleanups = 0;
>   int async_exec = 0;
>+/* TENSILICA_LOCAL */
>+  int program_break_kind;
>+/* END TENSILICA_LOCAL */
> 
>   ERROR_NO_INFERIOR;
> 
>@@ -725,6 +728,33 @@
>       else
>         make_exec_cleanup (disable_longjmp_breakpoint_cleanup, 0 /*ignore*/);
>     }
>+/* TENSILICA_LOCAL */
>+  else if (STOPPED_BY_PROGRAM_BREAKPOINT (&program_break_kind) && 
>+	   read_pc() == stop_pc && count > 0)
>+    {
>+      /* "stepi" off program breakpoint: the first step is to just increment
>+	 the PC past the break, then there are count-1 steps to go.
>+	 Note proceed() won't be called the first time, and on subsequent
>+	 steps the PC will already be off the break, so the entire handling
>+	 of "stepi" off a program breakpoint is done here. If stopping after 
>+	 the break, display location information as for normal_stop.  */
>+      count--;
>+      gdbarch_skip_program_breakpoint (current_gdbarch, program_break_kind);
>+      if (count == 0)
>+	{
>+	  deprecated_update_frame_pc_hack (get_current_frame (), read_pc ());
>+	  if (ui_out_is_mi_like_p (uiout))
>+	    {
>+	      ui_out_field_string (uiout, "reason", "end-stepping-range");
>+	      ui_out_field_int (uiout, "thread-id",
>+				pid_to_thread_id (inferior_ptid));
>+	      print_stack_frame (get_selected_frame (NULL), -1, LOC_AND_ADDRESS);
>+	    }
>+	  else 
>+	    print_stack_frame (get_selected_frame (NULL), -1, SRC_LINE);
>+	}
>+    }
>+/* END TENSILICA_LOCAL */
> 
>
>  
>


  parent reply	other threads:[~2009-03-31  0:44 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-16 17:41 [RFC] stepping over permanent breakpoint Aleksandar Ristovski
2009-03-16 18:22 ` Pedro Alves
2009-03-16 18:55   ` Aleksandar Ristovski
2009-03-16 19:38     ` Pedro Alves
2009-03-16 20:37       ` Aleksandar Ristovski
2009-03-16 18:50 ` Mark Kettenis
2009-03-16 19:04   ` Aleksandar Ristovski
2009-03-23 16:50 ` RFC: Program Breakpoints (was: [RFC] stepping over permanent breakpoint) Ross Morley
2009-03-24 16:57   ` Daniel Jacobowitz
2009-03-24 20:33     ` RFC: Program Breakpoints Ross Morley
2009-03-24 20:40       ` Daniel Jacobowitz
2009-03-24 23:48         ` Pedro Alves
2009-03-25  7:58           ` Mark Kettenis
2009-03-25 13:17             ` Pedro Alves
2009-03-24 23:59         ` Ross Morley
2009-03-31  0:44   ` Ross Morley [this message]
2009-03-31  3:17     ` Daniel Jacobowitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=49D16764.2040706@tensilica.com \
    --to=ross@tensilica.com \
    --cc=gdb@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox