Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <pedro@codesourcery.com>
To: gdb-patches@sourceware.org
Cc: Ross Morley <ross@tensilica.com>
Subject: Re: [Fwd: Re: [PATCH] Program Breakpoints]
Date: Tue, 19 May 2009 18:58:00 -0000	[thread overview]
Message-ID: <200905191958.35348.pedro@codesourcery.com> (raw)
In-Reply-To: <4A12EC43.3010107@tensilica.com>

Okay, first try.  Sorry for the delay...

On Tuesday 19 May 2009 18:28:35, Ross Morley wrote:
> +/* Returns non-zero if we were stopped by a trap or break instruction,
> +   whether or not it is a software break planted by GDB.  If size != 0,
> +   sets *size to that of the instruction or 0 if it need not be skipped.  */
> +
> +#ifndef STOPPED_BY_TRAP_INSTRUCTION
> +#define STOPPED_BY_TRAP_INSTRUCTION(size) \
> +  (*current_target.to_stopped_by_trap_instruction) (size)
> +#endif
>  #define target_get_ada_task_ptid(lwp, tid) \
>       (*current_target.to_get_ada_task_ptid) (lwp,tid)
>  

Please rename this to target_stopped_by_trap_instruction, and
make it unconditionally defined.  We don't support overriding
of these target macros anymore.

> +  if (target_has_execution && !ptid_equal (inferior_ptid, null_ptid))
> +    {
> +      struct thread_info *tp = inferior_thread ();
> +      if (tp->program_breakpoint_hit && tp->program_breakpoint_size != 0
> +         && execution_direction != EXEC_REVERSE && read_pc () == stop_pc
> +         && count > 0)

Sorry, `read_pc' is now gone from the sources.  Replace that by

regcache_read_pc (get_current_regcache ()), or get_frame_pc if there's a
frame handy.

+  /* "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.  */
+  if (target_has_execution && !ptid_equal (inferior_ptid, null_ptid))
+    {
+      struct thread_info *tp = inferior_thread ();
+      if (tp->program_breakpoint_hit && tp->program_breakpoint_size != 0
+         && execution_direction != EXEC_REVERSE && read_pc () == stop_pc
+         && count > 0)
+       {
+         count--;
+         write_pc (read_pc () + tp->program_breakpoint_size);
+         if (count == 0)
+           {
+             reinit_frame_cache ();
+             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);
+           }
+       }
+    }
+

This is broken for the !single_inst cases (step/next).  step N is mishandled.
It also doesn't take into account that there may be a
breakpoint at ORIG_PC + program_breakpoint_size.

What if a "program breakpoint" is reported for a GDB breakpoint?  You shouldn't
just move the PC in that case.  I don't see where that is handled.   See comment
on next hunk.   I suspect this short circuit should be done elsewhere, somewhere
where it will be possible to pass through handle_inferior_event after
moving the PC forward.

Shouldn't you do something in prepare_to_proceed as well?

  Use case is:

   <thread 1 hit program breakpoint>
   (gdb) thread 2
   (gdb) continue

  GDB is expected to make progress here, instead of reporting
  the same program breakpoint again.

> 
> +  /* Handle case of hitting a program breakpoint (break instruction
> +     in target program, not planted by or known to GDB).  */
> +  
> +  if (ecs->event_thread->program_breakpoint_hit)
> +    {
> +      stop_print_frame = 1;
> +      
> +      /* We are about to nuke the step_resume_breakpoint and
> +        through_sigtramp_breakpoint via the cleanup chain, so
> +        no need to worry about it here.  */
> +      
> +      stop_stepping (ecs);
> +      return;
> +    }
> +
>    /* Handle cases caused by hitting a breakpoint.  */
>    {

Hmmm, confused: can't the target report a program breakpoint hit
for a PC where there's a gdb breakpoint inserted as well?  Wouldn't
it better to have program breakpoints checked from inside
stop_bpstat/bpstop_status/bpstat_explains_signal/bpstat_print?
Then you wouldn't need to add
those if (program_breakpoint) do_this; else handle bpstat;

+static int
+linux_stopped_by_trap_instruction (int *size)
+{
+  CORE_ADDR stop_pc = get_stop_pc();
+  int trap_size = 0;
+
+  if (the_low_target.trap_size_at != NULL)
+    trap_size = (*the_low_target.trap_size_at) (stop_pc);
+  else if (the_low_target.breakpoint_at != NULL
+          && (*the_low_target.breakpoint_at) (stop_pc))
+    trap_size = the_low_target.breakpoint_len;
+
+  if (trap_size != 0)
+    {
+      *size = (the_low_target.get_pc != NULL 
+              && (*the_low_target.get_pc) () == stop_pc)
+             ? trap_size : 0;

I think I got this bit, but it would be nice to have a
comment here.

+      return 1;
+    }
+  else
+    return 0;
+}


Before we stick with this forever, it would be very
important to have tests covering corner cases like:

 single-stepping through consecutive
      "program breakpoint"->gdb breakpoint

 single-stepping through consecutive
      "program breakpoint"->"program breakpoint"

single- stepping through consecutive
       gdb breakpoint->"program breakpoint"

(step, stepi, stepi n)

     insn1
     "program breakpoint"
foo: gdb breakpoint
     insn2
     insn3
     jmp foo

"step" over this:

function ()

line 1:
     insn1
     "program breakpoint"
     insn2
     insn3
line 2:
     ...

... and have "program breakpoint" be reported, instead
of end-stepping-range at line 2.

From the looks of it, you don't have to do much, if anything
else at all, to have these cases covered on x86; I'd really
like to make sure this is sane on decr_pc_after_break archs, as
this is the way to fix the "step over range with trap
doesn't stop at trap" "bug".

If I read the code correctly, on x86, if you continue
this:

0001     insn1
0002     "program breakpoint"

... you'll report a "program breakpoint" hit at 0003, with
program breakpoint size 0.  If you instead stepi through that same
sequence, you'll get a "program breakpoint" hit at 0002, with
program breakpoint size 1.  That sounds good, but, if there's a
GDB breakpoint installed at "0002", gdb shouldn't be moving the PC
forward magically, without executing the instruction that
was under the breakpoint originally.

So, if I get this correctly, adjust_pc_after_break should
never try to roll back if program size > 0, even on
decr_pc_after_break archs, but we don't need to check this,
because this will only happen if single-stepping, and it
already does nothing in that case.  Right?

-- 
Pedro Alves


  reply	other threads:[~2009-05-19 18:58 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-19 17:30 Ross Morley
2009-05-19 18:58 ` Pedro Alves [this message]
2009-05-19 19:53   ` Ross Morley
2009-05-19 20:21     ` Pedro Alves
2009-05-19 21:33       ` Ross Morley
2009-05-27  1:49   ` [PATCH] Program Breakpoints Ross Morley

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=200905191958.35348.pedro@codesourcery.com \
    --to=pedro@codesourcery.com \
    --cc=gdb-patches@sourceware.org \
    --cc=ross@tensilica.com \
    /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