* eliminate deprecated_insert_raw_breakpoint. what's left.
@ 2014-09-08 17:46 Pedro Alves
2014-09-08 19:24 ` Joel Brobecker
2014-09-09 17:33 ` Pedro Alves
0 siblings, 2 replies; 31+ messages in thread
From: Pedro Alves @ 2014-09-08 17:46 UTC (permalink / raw)
To: GDB Patches
Hey,
I'm working on a patch that converts software single-step breakpoints
to real breakpoints. It's largely done, but needs a bit of cleaning up
before I'll post it. One issue is that software single-step breakpoints
were implemented on top of deprecated_insert_raw_breakpoint. They no
longer are after my patch, but we're still left with some ugly code in
breakpoint.c related to deprecated_insert_raw_breakpoints on top of other
breakpoints that I'd like to eliminate completely, but that can only
be done once all users of deprecated_insert_raw_breakpoint are either converted
to some more modern mechanism, or eliminated.
Before I go spend some effort blindly trying to do these remaining
conversions, I thought I'd run them through the list first, in case some
of this code can be considered dead already, or in case someone can
lend a hand (which would be awesome).
The remaining users are:
procfs.c: dbx_link_bpt = deprecated_insert_raw_breakpoint (target_gdbarch (), NULL,
This is only compiled if SYS_syssgi is defined, which I believe means
MIPS IRIX. Do we still care about MIPS IRIX?
solib-irix.c: base_breakpoint = deprecated_insert_raw_breakpoint (target_gdbarch (),
This could/should probably be converted to use create_solib_event_breakpoint.
Though see above.
rs6000-nat.c: bp = deprecated_insert_raw_breakpoint (gdbarch, NULL, DUMMY_INSN_ADDR);
This is AIX code. Looks like this can easily be converted to a momentary breakpoint?
AFAIR, I have no way to test either AIX or IRIX.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-08 17:46 eliminate deprecated_insert_raw_breakpoint. what's left Pedro Alves
@ 2014-09-08 19:24 ` Joel Brobecker
2014-09-08 21:34 ` Joel Brobecker
2014-09-09 21:48 ` Ulrich Weigand
2014-09-09 17:33 ` Pedro Alves
1 sibling, 2 replies; 31+ messages in thread
From: Joel Brobecker @ 2014-09-08 19:24 UTC (permalink / raw)
To: Pedro Alves; +Cc: GDB Patches
Hi Pedro,
> The remaining users are:
>
> procfs.c: dbx_link_bpt = deprecated_insert_raw_breakpoint (target_gdbarch (), NULL,
>
> This is only compiled if SYS_syssgi is defined, which I believe means
> MIPS IRIX. Do we still care about MIPS IRIX?
>
> solib-irix.c: base_breakpoint = deprecated_insert_raw_breakpoint (target_gdbarch (),
I would be surprised if anyone still cared about IRIX anymore.
I enjoyed working on that system, but I no longer have access
to it, so can't support it anymore.
> This could/should probably be converted to use create_solib_event_breakpoint.
> Though see above.
>
> rs6000-nat.c: bp = deprecated_insert_raw_breakpoint (gdbarch, NULL, DUMMY_INSN_ADDR);
>
> This is AIX code. Looks like this can easily be converted to a
> momentary breakpoint?
I am actually wondering whether this is still needed. It could!
So, the first thing I wanted to do was to run the testsuite without.
I'm currently building GDB, which is taking forever, and will then
run AdaCore's testsuite.
I can certainly assist in making the change regardless!
In terms of testing, I can only run AdaCore's testsuite because
expect isn't working for me on AIX, and I lack the time to
research it further. Although not ideal, it's been good enough
for us.
--
Joel
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-08 19:24 ` Joel Brobecker
@ 2014-09-08 21:34 ` Joel Brobecker
2014-09-08 22:50 ` Pedro Alves
2014-09-09 0:16 ` Peter Schauer
2014-09-09 21:48 ` Ulrich Weigand
1 sibling, 2 replies; 31+ messages in thread
From: Joel Brobecker @ 2014-09-08 21:34 UTC (permalink / raw)
To: Pedro Alves; +Cc: GDB Patches
> > This is AIX code. Looks like this can easily be converted to a
> > momentary breakpoint?
>
> I am actually wondering whether this is still needed. It could!
> So, the first thing I wanted to do was to run the testsuite without.
> I'm currently building GDB, which is taking forever, and will then
> run AdaCore's testsuite.
Looking at the code, it should be executed each time the SP register
gets changed, which means it should trigger when calling functions
from GDB. Deactivating exec_one_dummy_insn entirely did not result
in any regression I could notice. That was on AIX 7.1.
That being said, I'm hesitant of removing the code regardless,
since this could only be needed in specific situations which might
not be covered by the testsuites we have.
I was looking at how to replace that call, but I am not sure
how to fix the code up, though. Perhaps we could just write
the breakpoint instruction in by hand, rather than go through
the breakpoint module? After all, it is already doing almost
everything else by hand!
In fact, looking at the code again now, I'm a little more tempted
to see what happens if we remove it ;-).
--
Joel
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-08 21:34 ` Joel Brobecker
@ 2014-09-08 22:50 ` Pedro Alves
2014-09-09 0:25 ` Peter Schauer
2014-09-09 0:16 ` Peter Schauer
1 sibling, 1 reply; 31+ messages in thread
From: Pedro Alves @ 2014-09-08 22:50 UTC (permalink / raw)
To: Joel Brobecker; +Cc: GDB Patches
On 09/08/2014 10:34 PM, Joel Brobecker wrote:
> I was looking at how to replace that call, but I am not sure
> how to fix the code up, though. Perhaps we could just write
> the breakpoint instruction in by hand, rather than go through
> the breakpoint module? After all, it is already doing almost
> everything else by hand!
Indeed.
> In fact, looking at the code again now, I'm a little more tempted
> to see what happens if we remove it ;-).
Me too. And seriously. :-)
I traced it back to I think the original rs6000 port, in 1991...
commit 41abdfbd2de07837ba8088092765154eaa66351d
Author: John Gilmore <gnu@cygnus>
Date: Tue Nov 12 15:50:47 1991 +0000
* rs6000-pinsn.c, rs6000-tdep.c, rs6000-xdep.c, tm-rs6000.h,
xm-rs6000.h: New files.
* xcoffexec.c: New file for handling AIX shared libraries.
We already see this then, in rs6000-xdep.c:
+ /* execute one dummy instruction (which is a breakpoint) in inferior
+ process. So give kernel a chance to do internal house keeping.
+ Otherwise the following ptrace(2) calls will mess up user stack
+ since kernel will get confused about the bottom of the stack (%sp) */
+
+ exec_one_dummy_insn ();
This sounds like working around a (very) old kernel bug...
I can't believe anything resembling a modern system would need
such a monstrosity! :-) I vote just removing all that.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-08 21:34 ` Joel Brobecker
2014-09-08 22:50 ` Pedro Alves
@ 2014-09-09 0:16 ` Peter Schauer
2014-09-09 11:39 ` Ulrich Weigand
1 sibling, 1 reply; 31+ messages in thread
From: Peter Schauer @ 2014-09-09 0:16 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Pedro Alves, GDB Patches
>
> > > This is AIX code. Looks like this can easily be converted to a
> > > momentary breakpoint?
> >
> > I am actually wondering whether this is still needed. It could!
> > So, the first thing I wanted to do was to run the testsuite without.
> > I'm currently building GDB, which is taking forever, and will then
> > run AdaCore's testsuite.
>
> Looking at the code, it should be executed each time the SP register
> gets changed, which means it should trigger when calling functions
> from GDB. Deactivating exec_one_dummy_insn entirely did not result
> in any regression I could notice. That was on AIX 7.1.
>
> That being said, I'm hesitant of removing the code regardless,
> since this could only be needed in specific situations which might
> not be covered by the testsuites we have.
>
> I was looking at how to replace that call, but I am not sure
> how to fix the code up, though. Perhaps we could just write
> the breakpoint instruction in by hand, rather than go through
> the breakpoint module? After all, it is already doing almost
> everything else by hand!
>
> In fact, looking at the code again now, I'm a little more tempted
> to see what happens if we remove it ;-).
I hope to be able to shed some light on this problem, although it
is more than fifteen years ago that I did some work for GDB on AIX.
From my notes back then, AIX 3 and AIX 4 had a very peculiar ptrace
implementation, where the current ptrace state of the inferior process
(including the current process registers) was maintained approximately
512 bytes below the current user stack pointer of the process.
This resulted in problems with AIX inferior function calls.
If the called function takes one or more large aggregate parameters
by value, or if you pass a large amount of parameters, the ptrace
area gets corrupted, when the dummy function call parameters are
pushed on the user stack, due to this awkward AIX stack layout.
To work around this problem, the execution of a dummy instruction
(when altering the stack pointer) caused the kernel to move the ptrace
state area further below on the user stack, allowing GDB to write below
the current user stack safely.
In GDB 6.x, rs6000_push_dummy_call even secured the stack partially during
pushing of the arguments, via an additional call of
regcache_raw_write_signed to gdbarch_sp_regnum (gdbarch), which is
no longer present in current versions of GDB.
Executing the dummy instruction is very fragile, especially if signals
get involved during the execution, and it didn't even help, if more
than ~100 bytes of parameters were pushed on the user stack on AIX 4.
Back then, there was no other choice though.
Unfortunately I do not know, if this peculiar AIX stack layout is still
used in AIX 5 or later, maybe Ulrich Weigand could tell you more about it.
I think you could/should zap exec_one_dummy_insn, provided that you test
a dummy function call on the oldest AIX version that GDB has to support,
with a large aggregate parameter, which is passed by value.
--
Peter Schauer Peter.Schauer@mytum.de
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-08 22:50 ` Pedro Alves
@ 2014-09-09 0:25 ` Peter Schauer
0 siblings, 0 replies; 31+ messages in thread
From: Peter Schauer @ 2014-09-09 0:25 UTC (permalink / raw)
To: Pedro Alves; +Cc: Joel Brobecker, GDB Patches
>
> On 09/08/2014 10:34 PM, Joel Brobecker wrote:
>
> > I was looking at how to replace that call, but I am not sure
> > how to fix the code up, though. Perhaps we could just write
> > the breakpoint instruction in by hand, rather than go through
> > the breakpoint module? After all, it is already doing almost
> > everything else by hand!
>
> Indeed.
>
> > In fact, looking at the code again now, I'm a little more tempted
> > to see what happens if we remove it ;-).
>
> Me too. And seriously. :-)
>
> I traced it back to I think the original rs6000 port, in 1991...
>
> commit 41abdfbd2de07837ba8088092765154eaa66351d
> Author: John Gilmore <gnu@cygnus>
> Date: Tue Nov 12 15:50:47 1991 +0000
>
> * rs6000-pinsn.c, rs6000-tdep.c, rs6000-xdep.c, tm-rs6000.h,
> xm-rs6000.h: New files.
> * xcoffexec.c: New file for handling AIX shared libraries.
>
>
>
> We already see this then, in rs6000-xdep.c:
>
> + /* execute one dummy instruction (which is a breakpoint) in inferior
> + process. So give kernel a chance to do internal house keeping.
> + Otherwise the following ptrace(2) calls will mess up user stack
> + since kernel will get confused about the bottom of the stack (%sp) */
> +
> + exec_one_dummy_insn ();
>
>
> This sounds like working around a (very) old kernel bug...
No, not a bug, but consequences of a very peculiar ptrace implementation,
at least up until and including AIX 4.3.
See my other post for a more detailed explanation.
> I can't believe anything resembling a modern system would need
> such a monstrosity! :-) I vote just removing all that.
Me too, provided that newer AIX versions have a better ptrace implementation,
making this monstrosity unnecessary.
--
Peter Schauer Peter.Schauer@mytum.de
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-09 0:16 ` Peter Schauer
@ 2014-09-09 11:39 ` Ulrich Weigand
2014-09-09 12:38 ` Peter Schauer
0 siblings, 1 reply; 31+ messages in thread
From: Ulrich Weigand @ 2014-09-09 11:39 UTC (permalink / raw)
To: Peter Schauer; +Cc: Joel Brobecker, Pedro Alves, GDB Patches
Peter Schauer wrote:
> I hope to be able to shed some light on this problem, although it
> is more than fifteen years ago that I did some work for GDB on AIX.
>
> From my notes back then, AIX 3 and AIX 4 had a very peculiar ptrace
> implementation, where the current ptrace state of the inferior process
> (including the current process registers) was maintained approximately
> 512 bytes below the current user stack pointer of the process.
>
> This resulted in problems with AIX inferior function calls.
> If the called function takes one or more large aggregate parameters
> by value, or if you pass a large amount of parameters, the ptrace
> area gets corrupted, when the dummy function call parameters are
> pushed on the user stack, due to this awkward AIX stack layout.
Thanks for providing this background!
> To work around this problem, the execution of a dummy instruction
> (when altering the stack pointer) caused the kernel to move the ptrace
> state area further below on the user stack, allowing GDB to write below
> the current user stack safely.
> In GDB 6.x, rs6000_push_dummy_call even secured the stack partially during
> pushing of the arguments, via an additional call of
> regcache_raw_write_signed to gdbarch_sp_regnum (gdbarch), which is
> no longer present in current versions of GDB.
Well, I still see this:
/* Set the stack pointer. According to the ABI, the SP is meant to
be set _before_ the corresponding stack space is used. On AIX,
this even applies when the target has been completely stopped!
Not doing this can lead to conflicts with the kernel which thinks
that it still has control over this not-yet-allocated stack
region. */
regcache_raw_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp);
and:
/* This is another instance we need to be concerned about
securing our stack space. If we write anything underneath %sp
(r1), we might conflict with the kernel who thinks he is free
to use this area. So, update %sp first before doing anything
else. */
regcache_raw_write_signed (regcache,
gdbarch_sp_regnum (gdbarch), sp);
Are there other instances where this is missing?
> Executing the dummy instruction is very fragile, especially if signals
> get involved during the execution, and it didn't even help, if more
> than ~100 bytes of parameters were pushed on the user stack on AIX 4.
> Back then, there was no other choice though.
>
> Unfortunately I do not know, if this peculiar AIX stack layout is still
> used in AIX 5 or later, maybe Ulrich Weigand could tell you more about it.
I don't know off-hand. I'll try to find out.
> I think you could/should zap exec_one_dummy_insn, provided that you test
> a dummy function call on the oldest AIX version that GDB has to support,
> with a large aggregate parameter, which is passed by value.
The only version I have ready access to is AIX 7.1, and on this there
are no testsuite regression (and in fact, quite a number of failures
seem to go away!) when zapping exec_one_dummy_insn.
I'm not sure which versions we need to / should support in GDB; I guess
the oldest version where the OS itself is still supported by IBM is 6.1.
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-09 11:39 ` Ulrich Weigand
@ 2014-09-09 12:38 ` Peter Schauer
2014-09-09 21:25 ` Ulrich Weigand
0 siblings, 1 reply; 31+ messages in thread
From: Peter Schauer @ 2014-09-09 12:38 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: Joel Brobecker, Pedro Alves, GDB Patches
> Peter Schauer wrote:
>
> > I hope to be able to shed some light on this problem, although it
> > is more than fifteen years ago that I did some work for GDB on AIX.
> >
> > From my notes back then, AIX 3 and AIX 4 had a very peculiar ptrace
> > implementation, where the current ptrace state of the inferior process
> > (including the current process registers) was maintained approximately
> > 512 bytes below the current user stack pointer of the process.
> >
> > This resulted in problems with AIX inferior function calls.
> > If the called function takes one or more large aggregate parameters
> > by value, or if you pass a large amount of parameters, the ptrace
> > area gets corrupted, when the dummy function call parameters are
> > pushed on the user stack, due to this awkward AIX stack layout.
>
> Thanks for providing this background!
>
> > To work around this problem, the execution of a dummy instruction
> > (when altering the stack pointer) caused the kernel to move the ptrace
> > state area further below on the user stack, allowing GDB to write below
> > the current user stack safely.
> > In GDB 6.x, rs6000_push_dummy_call even secured the stack partially during
> > pushing of the arguments, via an additional call of
> > regcache_raw_write_signed to gdbarch_sp_regnum (gdbarch), which is
> > no longer present in current versions of GDB.
>
> Well, I still see this:
> /* Set the stack pointer. According to the ABI, the SP is meant to
> be set _before_ the corresponding stack space is used. On AIX,
> this even applies when the target has been completely stopped!
> Not doing this can lead to conflicts with the kernel which thinks
> that it still has control over this not-yet-allocated stack
> region. */
> regcache_raw_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp);
>
> and:
> /* This is another instance we need to be concerned about
> securing our stack space. If we write anything underneath %sp
> (r1), we might conflict with the kernel who thinks he is free
> to use this area. So, update %sp first before doing anything
> else. */
>
> regcache_raw_write_signed (regcache,
> gdbarch_sp_regnum (gdbarch), sp);
>
> Are there other instances where this is missing?
Ok, my bad, I was looking at the wrong push_dummy_call implementation
in the current GDB source.
rs6000_push_dummy_call in the new rs6000-aix-tdep.c file in the current GDB
source still contains the code in question from GDB 6.x, there is
nothing missing.
> > Executing the dummy instruction is very fragile, especially if signals
> > get involved during the execution, and it didn't even help, if more
> > than ~100 bytes of parameters were pushed on the user stack on AIX 4.
> > Back then, there was no other choice though.
> >
> > Unfortunately I do not know, if this peculiar AIX stack layout is still
> > used in AIX 5 or later, maybe Ulrich Weigand could tell you more about it.
>
> I don't know off-hand. I'll try to find out.
>
> > I think you could/should zap exec_one_dummy_insn, provided that you test
> > a dummy function call on the oldest AIX version that GDB has to support,
> > with a large aggregate parameter, which is passed by value.
>
> The only version I have ready access to is AIX 7.1, and on this there
> are no testsuite regression (and in fact, quite a number of failures
> seem to go away!) when zapping exec_one_dummy_insn.
+1 for zapping exec_one_dummy_insn.
> I'm not sure which versions we need to / should support in GDB; I guess
> the oldest version where the OS itself is still supported by IBM is 6.1.
Maybe somebody could test if zapping exec_one_dummy_insn on AIX 6.1
has any negative effect, and then be done with it.
But even if that can't be tested, I am all in favour of getting rid
of it, perhaps with a detailed comment in the commit message for the
removal (or adding a link to this thread).
--
Peter Schauer Peter.Schauer@mytum.de
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-08 17:46 eliminate deprecated_insert_raw_breakpoint. what's left Pedro Alves
2014-09-08 19:24 ` Joel Brobecker
@ 2014-09-09 17:33 ` Pedro Alves
1 sibling, 0 replies; 31+ messages in thread
From: Pedro Alves @ 2014-09-09 17:33 UTC (permalink / raw)
To: GDB Patches
On 09/08/2014 06:46 PM, Pedro Alves wrote:
> Hey,
>
> I'm working on a patch that converts software single-step breakpoints
> to real breakpoints. It's largely done, but needs a bit of cleaning up
> before I'll post it. One issue is that software single-step breakpoints
> were implemented on top of deprecated_insert_raw_breakpoint. They no
> longer are after my patch, but we're still left with some ugly code in
> breakpoint.c related to deprecated_insert_raw_breakpoints on top of other
> breakpoints that I'd like to eliminate completely, but that can only
> be done once all users of deprecated_insert_raw_breakpoint are either converted
> to some more modern mechanism, or eliminated.
Here's my current WIP patch. This runs regression free on x86_64 Fedora 20,
and also on top of my software-single-step-on-x86 series. I've tested this on
ppc64 F18 as well, to cover the step-over-watchpoints changes.
The ultimate goal was to eliminate a bunch of globals and make it possible
to have multiple threads in parallel doing software single-steps (it works!).
Currently in non-stop, on software single-step targets, we force all
single-steps as displaced-stepping operations, which means single-step requests
are serialized, because there's only one scratch pad.
Note this also removes the limitation that you can only have at most two
software single-step breakpoints, because each thread's single sss
breakpoint can hold an arbitrary number of locations.
As mentioned before, this removes deprecated_insert_raw_breakpoint
completely, which we can't so while AIX and IRIX aren't cleaned up.
Or maybe we can. :-)
If something horrible jumps back at you, please shout! :-)
---
From c62b21283aef99bd495aea9b6c6680a4219ca2b2 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Tue, 9 Sep 2014 17:28:45 +0100
Subject: [PATCH] make single-step breakpoints real breakpoints
---
gdb/breakpoint.c | 418 ++++++++++++++----------------------------------------
gdb/breakpoint.h | 33 ++---
gdb/gdbthread.h | 25 ++++
gdb/infrun.c | 360 +++++++++++++++++++++++-----------------------
gdb/infrun.h | 4 +
gdb/record-full.c | 8 +-
gdb/thread.c | 73 +++++++---
7 files changed, 387 insertions(+), 534 deletions(-)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 683ed2b..93f4ad2 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -226,11 +226,6 @@ static void stopat_command (char *arg, int from_tty);
static void tcatch_command (char *arg, int from_tty);
-static void detach_single_step_breakpoints (void);
-
-static int find_single_step_breakpoint (struct address_space *aspace,
- CORE_ADDR pc);
-
static void free_bp_location (struct bp_location *loc);
static void incref_bp_location (struct bp_location *loc);
static void decref_bp_location (struct bp_location **loc);
@@ -296,12 +291,6 @@ static struct breakpoint_ops bkpt_probe_breakpoint_ops;
/* Dynamic printf class type. */
struct breakpoint_ops dprintf_breakpoint_ops;
-/* One (or perhaps two) breakpoints used for software single
- stepping. */
-
-static void *single_step_breakpoints[2];
-static struct gdbarch *single_step_gdbarch[2];
-
/* The style in which to perform a dynamic printf. This is a user
option because different output options have different tradeoffs;
if GDB does the printing, there is better error handling if there
@@ -1616,21 +1605,6 @@ breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
one_breakpoint_xfer_memory (readbuf, writebuf, writebuf_org,
memaddr, len, &bl->target_info, bl->gdbarch);
}
-
- /* Now process single-step breakpoints. These are not found in the
- bp_location array. */
- for (i = 0; i < 2; i++)
- {
- struct bp_target_info *bp_tgt = single_step_breakpoints[i];
-
- if (bp_tgt != NULL)
- {
- struct gdbarch *gdbarch = single_step_gdbarch[i];
-
- one_breakpoint_xfer_memory (readbuf, writebuf, writebuf_org,
- memaddr, len, bp_tgt, gdbarch);
- }
- }
}
\f
@@ -2089,7 +2063,32 @@ should_be_inserted (struct bp_location *bl)
|| bl->loc_type == bp_loc_hardware_breakpoint)
&& stepping_past_instruction_at (bl->pspace->aspace,
bl->address))
- return 0;
+ {
+ if (debug_infrun)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: skipping breakpoint: "
+ "stepping past insn at: %s\n",
+ paddress (bl->gdbarch, bl->address));
+ }
+ return 0;
+ }
+
+ /* Don't insert watchpoints if we're trying to step past the
+ instruction that triggered one. */
+ if ((bl->loc_type == bp_loc_hardware_watchpoint)
+ && stepping_past_nonsteppable_watchpoint ())
+ {
+ if (debug_infrun)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: stepping past non-steppable watchpoint. "
+ "skipping watchpoint at %s:%d\n",
+ paddress (bl->gdbarch, bl->address),
+ bl->length);
+ }
+ return 0;
+ }
return 1;
}
@@ -3753,9 +3752,6 @@ detach_breakpoints (ptid_t ptid)
val |= remove_breakpoint_1 (bl, mark_inserted);
}
- /* Detach single-step breakpoints as well. */
- detach_single_step_breakpoints ();
-
do_cleanups (old_chain);
return val;
}
@@ -4025,6 +4021,10 @@ breakpoint_init_inferior (enum inf_context context)
/* Also remove step-resume breakpoints. */
+ case bp_single_step:
+
+ /* Also remove single-step breakpoints. */
+
delete_breakpoint (b);
break;
@@ -4121,14 +4121,10 @@ moribund_breakpoint_here_p (struct address_space *aspace, CORE_ADDR pc)
return 0;
}
-/* Returns non-zero if there's a breakpoint inserted at PC, which is
- inserted using regular breakpoint_chain / bp_location array
- mechanism. This does not check for single-step breakpoints, which
- are inserted and removed using direct target manipulation. */
+/* Returns non-zero iff there's a breakpoint inserted at PC. */
int
-regular_breakpoint_inserted_here_p (struct address_space *aspace,
- CORE_ADDR pc)
+breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc)
{
struct bp_location *bl, **blp_tmp;
@@ -4152,27 +4148,12 @@ regular_breakpoint_inserted_here_p (struct address_space *aspace,
return 0;
}
-/* Returns non-zero iff there's either regular breakpoint
- or a single step breakpoint inserted at PC. */
+/* This function returns non-zero iff there is a software breakpoint
+ inserted at PC. */
int
-breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc)
-{
- if (regular_breakpoint_inserted_here_p (aspace, pc))
- return 1;
-
- if (single_step_breakpoint_inserted_here_p (aspace, pc))
- return 1;
-
- return 0;
-}
-
-/* Ignoring deprecated raw breakpoints, return non-zero iff there is a
- software breakpoint inserted at PC. */
-
-static struct bp_location *
-find_non_raw_software_breakpoint_inserted_here (struct address_space *aspace,
- CORE_ADDR pc)
+software_breakpoint_inserted_here_p (struct address_space *aspace,
+ CORE_ADDR pc)
{
struct bp_location *bl, **blp_tmp;
@@ -4190,27 +4171,10 @@ find_non_raw_software_breakpoint_inserted_here (struct address_space *aspace,
&& !section_is_mapped (bl->section))
continue; /* unmapped overlay -- can't be a match */
else
- return bl;
+ return 1;
}
}
- return NULL;
-}
-
-/* This function returns non-zero iff there is a software breakpoint
- inserted at PC. */
-
-int
-software_breakpoint_inserted_here_p (struct address_space *aspace,
- CORE_ADDR pc)
-{
- if (find_non_raw_software_breakpoint_inserted_here (aspace, pc) != NULL)
- return 1;
-
- /* Also check for software single-step breakpoints. */
- if (single_step_breakpoint_inserted_here_p (aspace, pc))
- return 1;
-
return 0;
}
@@ -5498,6 +5462,7 @@ bpstat_stop_status (struct address_space *aspace,
}
}
+ /* Check if a moribund breakpoint explains the stop. */
for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
{
if (breakpoint_location_address_match (loc, aspace, bp_addr))
@@ -5653,6 +5618,7 @@ bpstat_what (bpstat bs_head)
break;
case bp_breakpoint:
case bp_hardware_breakpoint:
+ case bp_single_step:
case bp_until:
case bp_finish:
case bp_shlib_event:
@@ -6011,6 +5977,7 @@ bptype_string (enum bptype type)
{bp_none, "?deleted?"},
{bp_breakpoint, "breakpoint"},
{bp_hardware_breakpoint, "hw breakpoint"},
+ {bp_single_step, "sw single-step"},
{bp_until, "until"},
{bp_finish, "finish"},
{bp_watchpoint, "watchpoint"},
@@ -6202,6 +6169,7 @@ print_one_breakpoint_location (struct breakpoint *b,
case bp_breakpoint:
case bp_hardware_breakpoint:
+ case bp_single_step:
case bp_until:
case bp_finish:
case bp_longjmp:
@@ -7080,6 +7048,7 @@ init_bp_location (struct bp_location *loc, const struct bp_location_ops *ops,
switch (owner->type)
{
case bp_breakpoint:
+ case bp_single_step:
case bp_until:
case bp_finish:
case bp_longjmp:
@@ -9020,10 +8989,31 @@ enable_breakpoints_after_startup (void)
breakpoint_re_set ();
}
+/* Create a new single-step breakpoint for thread THREAD, with no
+ locations. */
+
+static struct breakpoint *
+new_single_step_breakpoint (int thread, struct gdbarch *gdbarch)
+{
+ struct breakpoint *b = XNEW (struct breakpoint);
+
+ init_raw_breakpoint_without_location (b, gdbarch, bp_single_step,
+ &momentary_breakpoint_ops);
-/* Set a breakpoint that will evaporate an end of command
- at address specified by SAL.
- Restrict it to frame FRAME if FRAME is nonzero. */
+ b->disposition = disp_donttouch;
+ b->frame_id = null_frame_id;
+
+ b->thread = thread;
+ gdb_assert (b->thread != 0);
+
+ add_to_breakpoint_chain (b);
+
+ return b;
+}
+
+/* Set a momentary breakpoint of type TYPE at address specified by
+ SAL. If FRAME_ID is valid, the breakpoint is restricted to that
+ frame. */
struct breakpoint *
set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal,
@@ -13129,45 +13119,13 @@ bkpt_re_set (struct breakpoint *b)
breakpoint_re_set_default (b);
}
-/* Copy SRC's shadow buffer and whatever else we'd set if we actually
- inserted DEST, so we can remove it later, in case SRC is removed
- first. */
-
-static void
-bp_target_info_copy_insertion_state (struct bp_target_info *dest,
- const struct bp_target_info *src)
-{
- dest->shadow_len = src->shadow_len;
- memcpy (dest->shadow_contents, src->shadow_contents, src->shadow_len);
- dest->placed_size = src->placed_size;
-}
-
static int
bkpt_insert_location (struct bp_location *bl)
{
if (bl->loc_type == bp_loc_hardware_breakpoint)
- return target_insert_hw_breakpoint (bl->gdbarch,
- &bl->target_info);
+ return target_insert_hw_breakpoint (bl->gdbarch, &bl->target_info);
else
- {
- struct bp_target_info *bp_tgt = &bl->target_info;
- int ret;
- int sss_slot;
-
- /* There is no need to insert a breakpoint if an unconditional
- raw/sss breakpoint is already inserted at that location. */
- sss_slot = find_single_step_breakpoint (bp_tgt->placed_address_space,
- bp_tgt->placed_address);
- if (sss_slot >= 0)
- {
- struct bp_target_info *sss_bp_tgt = single_step_breakpoints[sss_slot];
-
- bp_target_info_copy_insertion_state (bp_tgt, sss_bp_tgt);
- return 0;
- }
-
- return target_insert_breakpoint (bl->gdbarch, bp_tgt);
- }
+ return target_insert_breakpoint (bl->gdbarch, &bl->target_info);
}
static int
@@ -13176,19 +13134,7 @@ bkpt_remove_location (struct bp_location *bl)
if (bl->loc_type == bp_loc_hardware_breakpoint)
return target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info);
else
- {
- struct bp_target_info *bp_tgt = &bl->target_info;
- struct address_space *aspace = bp_tgt->placed_address_space;
- CORE_ADDR address = bp_tgt->placed_address;
-
- /* Only remove the breakpoint if there is no raw/sss breakpoint
- still inserted at this location. Otherwise, we would be
- effectively disabling the raw/sss breakpoint. */
- if (single_step_breakpoint_inserted_here_p (aspace, address))
- return 0;
-
- return target_remove_breakpoint (bl->gdbarch, bp_tgt);
- }
+ return target_remove_breakpoint (bl->gdbarch, &bl->target_info);
}
static int
@@ -15186,217 +15132,73 @@ invalidate_bp_value_on_memory_change (struct inferior *inferior,
}
}
-/* Create and insert a raw software breakpoint at PC. Return an
- identifier, which should be used to remove the breakpoint later.
- In general, places which call this should be using something on the
- breakpoint chain instead; this function should be eliminated
- someday. */
-
-void *
-deprecated_insert_raw_breakpoint (struct gdbarch *gdbarch,
- struct address_space *aspace, CORE_ADDR pc)
-{
- struct bp_target_info *bp_tgt;
- struct bp_location *bl;
-
- bp_tgt = XCNEW (struct bp_target_info);
-
- bp_tgt->placed_address_space = aspace;
- bp_tgt->placed_address = pc;
-
- /* If an unconditional non-raw breakpoint is already inserted at
- that location, there's no need to insert another. However, with
- target-side evaluation of breakpoint conditions, if the
- breakpoint that is currently inserted on the target is
- conditional, we need to make it unconditional. Note that a
- breakpoint with target-side commands is not reported even if
- unconditional, so we need to remove the commands from the target
- as well. */
- bl = find_non_raw_software_breakpoint_inserted_here (aspace, pc);
- if (bl != NULL
- && VEC_empty (agent_expr_p, bl->target_info.conditions)
- && VEC_empty (agent_expr_p, bl->target_info.tcommands))
- {
- bp_target_info_copy_insertion_state (bp_tgt, &bl->target_info);
- return bp_tgt;
- }
-
- if (target_insert_breakpoint (gdbarch, bp_tgt) != 0)
- {
- /* Could not insert the breakpoint. */
- xfree (bp_tgt);
- return NULL;
- }
-
- return bp_tgt;
-}
-
-/* Remove a breakpoint BP inserted by
- deprecated_insert_raw_breakpoint. */
-
-int
-deprecated_remove_raw_breakpoint (struct gdbarch *gdbarch, void *bp)
-{
- struct bp_target_info *bp_tgt = bp;
- struct address_space *aspace = bp_tgt->placed_address_space;
- CORE_ADDR address = bp_tgt->placed_address;
- struct bp_location *bl;
- int ret;
-
- bl = find_non_raw_software_breakpoint_inserted_here (aspace, address);
-
- /* Only remove the raw breakpoint if there are no other non-raw
- breakpoints still inserted at this location. Otherwise, we would
- be effectively disabling those breakpoints. */
- if (bl == NULL)
- ret = target_remove_breakpoint (gdbarch, bp_tgt);
- else if (!VEC_empty (agent_expr_p, bl->target_info.conditions)
- || !VEC_empty (agent_expr_p, bl->target_info.tcommands))
- {
- /* The target is evaluating conditions, and when we inserted the
- software single-step breakpoint, we had made the breakpoint
- unconditional and command-less on the target side. Reinsert
- to restore the conditions/commands. */
- ret = target_insert_breakpoint (bl->gdbarch, &bl->target_info);
- }
- else
- ret = 0;
-
- xfree (bp_tgt);
-
- return ret;
-}
-
-/* Create and insert a breakpoint for software single step. */
+/* See breakpoint.h. */
void
insert_single_step_breakpoint (struct gdbarch *gdbarch,
struct address_space *aspace,
CORE_ADDR next_pc)
{
- void **bpt_p;
+ struct thread_info *tp = inferior_thread ();
+ struct symtab_and_line sal;
+ CORE_ADDR pc = next_pc;
- if (single_step_breakpoints[0] == NULL)
- {
- bpt_p = &single_step_breakpoints[0];
- single_step_gdbarch[0] = gdbarch;
- }
- else
+ if (tp->control.single_step_breakpoints == NULL)
{
- gdb_assert (single_step_breakpoints[1] == NULL);
- bpt_p = &single_step_breakpoints[1];
- single_step_gdbarch[1] = gdbarch;
+ tp->control.single_step_breakpoints
+ = new_single_step_breakpoint (tp->num, gdbarch);
}
- /* NOTE drow/2006-04-11: A future improvement to this function would
- be to only create the breakpoints once, and actually put them on
- the breakpoint chain. That would let us use set_raw_breakpoint.
- We could adjust the addresses each time they were needed. Doing
- this requires corresponding changes elsewhere where single step
- breakpoints are handled, however. So, for now, we use this. */
-
- *bpt_p = deprecated_insert_raw_breakpoint (gdbarch, aspace, next_pc);
- if (*bpt_p == NULL)
- error (_("Could not insert single-step breakpoint at %s"),
- paddress (gdbarch, next_pc));
-}
-
-/* Check if the breakpoints used for software single stepping
- were inserted or not. */
-
-int
-single_step_breakpoints_inserted (void)
-{
- return (single_step_breakpoints[0] != NULL
- || single_step_breakpoints[1] != NULL);
-}
-
-/* Remove and delete any breakpoints used for software single step. */
-
-void
-remove_single_step_breakpoints (void)
-{
- gdb_assert (single_step_breakpoints[0] != NULL);
+ sal = find_pc_line (pc, 0);
+ sal.pc = pc;
+ sal.section = find_pc_overlay (pc);
+ sal.explicit_pc = 1;
+ add_location_to_breakpoint (tp->control.single_step_breakpoints, &sal);
- /* See insert_single_step_breakpoint for more about this deprecated
- call. */
- deprecated_remove_raw_breakpoint (single_step_gdbarch[0],
- single_step_breakpoints[0]);
- single_step_gdbarch[0] = NULL;
- single_step_breakpoints[0] = NULL;
+ update_global_location_list_nothrow (1);
- if (single_step_breakpoints[1] != NULL)
- {
- deprecated_remove_raw_breakpoint (single_step_gdbarch[1],
- single_step_breakpoints[1]);
- single_step_gdbarch[1] = NULL;
- single_step_breakpoints[1] = NULL;
- }
+ /* update_global_location_list does not insert breakpoints when
+ always_inserted_mode is not enabled. Explicitly insert them
+ now. */
+ if (!breakpoints_always_inserted_mode ())
+ insert_breakpoint_locations ();
}
-/* Delete software single step breakpoints without removing them from
- the inferior. This is intended to be used if the inferior's address
- space where they were inserted is already gone, e.g. after exit or
- exec. */
+/* See breakpoint.h. */
-void
-cancel_single_step_breakpoints (void)
+int
+breakpoint_is_inserted_here (struct breakpoint *bp,
+ struct address_space *aspace, CORE_ADDR pc)
{
- int i;
-
- for (i = 0; i < 2; i++)
- if (single_step_breakpoints[i])
- {
- xfree (single_step_breakpoints[i]);
- single_step_breakpoints[i] = NULL;
- single_step_gdbarch[i] = NULL;
- }
-}
-
-/* Detach software single-step breakpoints from INFERIOR_PTID without
- removing them. */
+ struct bp_location *loc;
-static void
-detach_single_step_breakpoints (void)
-{
- int i;
+ for (loc = bp->loc; loc != NULL; loc = loc->next)
+ if (loc->inserted
+ && breakpoint_location_address_match (loc, aspace, pc))
+ return 1;
- for (i = 0; i < 2; i++)
- if (single_step_breakpoints[i])
- target_remove_breakpoint (single_step_gdbarch[i],
- single_step_breakpoints[i]);
+ return 0;
}
-/* Find the software single-step breakpoint that inserted at PC.
- Returns its slot if found, and -1 if not found. */
+/* See breakpoint.h. */
-static int
-find_single_step_breakpoint (struct address_space *aspace,
- CORE_ADDR pc)
+int
+single_step_breakpoint_inserted_here_p (struct address_space *aspace,
+ CORE_ADDR pc)
{
- int i;
+ struct breakpoint *bpt;
- for (i = 0; i < 2; i++)
+ ALL_BREAKPOINTS (bpt)
{
- struct bp_target_info *bp_tgt = single_step_breakpoints[i];
- if (bp_tgt
- && breakpoint_address_match (bp_tgt->placed_address_space,
- bp_tgt->placed_address,
- aspace, pc))
- return i;
- }
-
- return -1;
-}
+ struct bp_location *loc;
-/* Check whether a software single-step breakpoint is inserted at
- PC. */
+ if (bpt->type != bp_single_step)
+ continue;
-int
-single_step_breakpoint_inserted_here_p (struct address_space *aspace,
- CORE_ADDR pc)
-{
- return find_single_step_breakpoint (aspace, pc) >= 0;
+ if (breakpoint_is_inserted_here (bpt, aspace, pc))
+ return 1;
+ }
+ return 0;
}
/* Returns 0 if 'bp' is NOT a syscall catchpoint,
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index f6d06ce..5920181 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -47,18 +47,13 @@ struct linespec_sals;
\f
/* Type of breakpoint. */
-/* FIXME In the future, we should fold all other breakpoint-like
- things into here. This includes:
-
- * single-step (for machines where we have to simulate single
- stepping) (probably, though perhaps it is better for it to look as
- much as possible like a single-step to wait_for_inferior). */
enum bptype
{
bp_none = 0, /* Eventpoint has been deleted */
bp_breakpoint, /* Normal breakpoint */
bp_hardware_breakpoint, /* Hardware assisted breakpoint */
+ bp_single_step, /* Software single-step */
bp_until, /* used by until command */
bp_finish, /* used by finish command */
bp_watchpoint, /* Watchpoint */
@@ -1126,6 +1121,15 @@ extern int regular_breakpoint_inserted_here_p (struct address_space *,
extern int software_breakpoint_inserted_here_p (struct address_space *,
CORE_ADDR);
+/* Check whether any location of BP is inserted at PC. */
+
+extern int breakpoint_is_inserted_here (struct breakpoint *bp,
+ struct address_space *aspace,
+ CORE_ADDR pc);
+
+/* Check whether any software single-step breakpoint is inserted at
+ PC. */
+
extern int single_step_breakpoint_inserted_here_p (struct address_space *,
CORE_ADDR);
@@ -1442,22 +1446,13 @@ extern void add_solib_catchpoint (char *arg, int is_load, int is_temp,
deletes all breakpoints. */
extern void delete_command (char *arg, int from_tty);
-/* Manage a software single step breakpoint (or two). Insert may be
- called twice before remove is called. */
+/* Insert a new software single step breakpoint for the current
+ thread. Insert may be called multiple times; each time will add a
+ new location to the set of potential addresses the next instruction
+ is at. */
extern void insert_single_step_breakpoint (struct gdbarch *,
struct address_space *,
CORE_ADDR);
-extern int single_step_breakpoints_inserted (void);
-extern void remove_single_step_breakpoints (void);
-extern void cancel_single_step_breakpoints (void);
-
-/* Manage manual breakpoints, separate from the normal chain of
- breakpoints. These functions are used in murky target-specific
- ways. Please do not add more uses! */
-extern void *deprecated_insert_raw_breakpoint (struct gdbarch *,
- struct address_space *,
- CORE_ADDR);
-extern int deprecated_remove_raw_breakpoint (struct gdbarch *, void *);
/* Check if any hardware watchpoints have triggered, according to the
target. */
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 522b674..77bbbde 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -52,6 +52,13 @@ struct thread_control_state
/* Exception-resume breakpoint. */
struct breakpoint *exception_resume_breakpoint;
+ /* Breakpoints used for software single stepping. Plural, because
+ it may have multiple locations. E.g., if stepping over a
+ conditional branch instruction we can't decode the condition for,
+ we'll need to put a breakpoint at the branch destination, and
+ another at the instruction after the branch. */
+ struct breakpoint *single_step_breakpoints;
+
/* Range to single step within.
If this is nonzero, respond to a single-step signal by continuing
@@ -197,6 +204,11 @@ struct thread_info
/* Should we step over breakpoint next time keep_going is called? */
int stepping_over_breakpoint;
+ /* Should we step over a watchpoint next time keep_going is called?
+ This is needed on targets with non-continuable and non-steppable
+ watchpoints. */
+ int stepping_over_watchpoint;
+
/* Set to TRUE if we should finish single-stepping over a breakpoint
after hitting the current step-resume breakpoint. The context here
is that GDB is to do `next' or `step' while signal arrives.
@@ -280,6 +292,19 @@ extern void delete_step_resume_breakpoint (struct thread_info *);
/* Delete an exception_resume_breakpoint from the thread database. */
extern void delete_exception_resume_breakpoint (struct thread_info *);
+/* Delete the single-step breakpoints of thread TP, if any. */
+extern void delete_single_step_breakpoints (struct thread_info *tp);
+
+/* Check if the thread has software single stepping breakpoints
+ set. */
+extern int thread_has_single_step_breakpoints_set (struct thread_info *tp);
+
+/* Check whether the thread has software single stepping breakpoints
+ set at PC. */
+extern int thread_has_single_step_breakpoint_here (struct thread_info *tp,
+ struct address_space *aspace,
+ CORE_ADDR addr);
+
/* Translate the integer thread id (GDB's homegrown id, not the system's)
into a "pid" (which may be overloaded with extra thread information). */
extern ptid_t thread_id_to_pid (int);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index c18267f..2f3a848 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -373,8 +373,6 @@ static void context_switch (ptid_t ptid);
void init_thread_stepping_state (struct thread_info *tss);
-static void init_infwait_state (void);
-
static const char follow_fork_mode_child[] = "child";
static const char follow_fork_mode_parent[] = "parent";
@@ -844,6 +842,7 @@ follow_exec (ptid_t pid, char *execd_pathname)
statement through an exec(). */
th->control.step_resume_breakpoint = NULL;
th->control.exception_resume_breakpoint = NULL;
+ th->control.single_step_breakpoints = NULL;
th->control.step_range_start = 0;
th->control.step_range_end = 0;
@@ -957,17 +956,6 @@ follow_exec (ptid_t pid, char *execd_pathname)
matically get reset there in the new process.). */
}
-/* Non-zero if we just simulating a single-step. This is needed
- because we cannot remove the breakpoints in the inferior process
- until after the `wait' in `wait_for_inferior'. */
-static int singlestep_breakpoints_inserted_p = 0;
-
-/* The thread we inserted single-step breakpoints for. */
-static ptid_t singlestep_ptid;
-
-/* PC when we started this single-step. */
-static CORE_ADDR singlestep_pc;
-
/* Info about an instruction that is being stepped over. Invalid if
ASPACE is NULL. */
@@ -978,6 +966,10 @@ struct step_over_info
/* The instruction's address. */
CORE_ADDR address;
+
+ /* The instruction being stepped over triggers a nonsteppable
+ watchpoint. */
+ int nonsteppable_watchpoint;
};
/* The step-over info of the location that is being stepped over.
@@ -1010,10 +1002,12 @@ static struct step_over_info step_over_info;
stepping over. */
static void
-set_step_over_info (struct address_space *aspace, CORE_ADDR address)
+set_step_over_info (struct address_space *aspace, CORE_ADDR address,
+ int nonsteppable_watchpoint)
{
step_over_info.aspace = aspace;
step_over_info.address = address;
+ step_over_info.nonsteppable_watchpoint = nonsteppable_watchpoint;
}
/* Called when we're not longer stepping over a breakpoint / an
@@ -1024,6 +1018,7 @@ clear_step_over_info (void)
{
step_over_info.aspace = NULL;
step_over_info.address = 0;
+ step_over_info.nonsteppable_watchpoint = 0;
}
/* See inferior.h. */
@@ -1032,10 +1027,35 @@ int
stepping_past_instruction_at (struct address_space *aspace,
CORE_ADDR address)
{
+ if (step_over_info.aspace != NULL
+ && breakpoint_address_match (aspace, address,
+ step_over_info.aspace,
+ step_over_info.address))
+ {
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: stepping over breakpoint's address: %s\n",
+ paddress (target_gdbarch (), address));
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+stepping_past_nonsteppable_watchpoint (void)
+{
+ return step_over_info.nonsteppable_watchpoint;
+}
+
+/* Returns true if any breakpoint/watchpoint that would normally be
+ inserted can't be inserted due to run control. */
+
+static int
+any_breakpoint_lifted (void)
+{
return (step_over_info.aspace != NULL
- && breakpoint_address_match (aspace, address,
- step_over_info.aspace,
- step_over_info.address));
+ || stepping_past_nonsteppable_watchpoint ());
}
\f
@@ -1633,9 +1653,6 @@ infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
if (ptid_equal (inferior_ptid, old_ptid))
inferior_ptid = new_ptid;
- if (ptid_equal (singlestep_ptid, old_ptid))
- singlestep_ptid = new_ptid;
-
for (displaced = displaced_step_inferior_states;
displaced;
displaced = displaced->next)
@@ -1694,29 +1711,17 @@ set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
process. */
int sched_multi = 0;
-/* Try to setup for software single stepping over the specified location.
- Return 1 if target_resume() should use hardware single step.
-
- GDBARCH the current gdbarch.
- PC the location to step over. */
+/* Try to setup for software single stepping over the specified
+ location. Return 0 if target_resume() should use hardware single
+ step. GDBARCH is the current frame's gdbarch. PC is the location
+ to step over. */
static int
maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- int hw_step = 1;
-
- if (execution_direction == EXEC_FORWARD
- && gdbarch_software_single_step_p (gdbarch)
- && gdbarch_software_single_step (gdbarch, get_current_frame ()))
- {
- hw_step = 0;
- /* Do not pull these breakpoints until after a `wait' in
- `wait_for_inferior'. */
- singlestep_breakpoints_inserted_p = 1;
- singlestep_ptid = inferior_ptid;
- singlestep_pc = pc;
- }
- return hw_step;
+ return (execution_direction == EXEC_FORWARD
+ && gdbarch_software_single_step_p (gdbarch)
+ && gdbarch_software_single_step (gdbarch, get_current_frame ()));
}
ptid_t
@@ -1739,8 +1744,7 @@ user_visible_resume_ptid (int step)
resume_ptid = inferior_ptid;
}
else if ((scheduler_mode == schedlock_on)
- || (scheduler_mode == schedlock_step
- && (step || singlestep_breakpoints_inserted_p)))
+ || (scheduler_mode == schedlock_step && step))
{
/* User-settable 'scheduler' mode requires solo thread resume. */
resume_ptid = inferior_ptid;
@@ -1843,8 +1847,7 @@ a command like `return' or `jump' to continue execution."));
event, displaced stepping breaks the vfork child similarly as single
step software breakpoint. */
if (use_displaced_stepping (gdbarch)
- && (tp->control.trap_expected
- || (step && gdbarch_software_single_step_p (gdbarch)))
+ && tp->control.trap_expected
&& sig == GDB_SIGNAL_0
&& !current_inferior ()->waiting_for_vfork_done)
{
@@ -1877,7 +1880,7 @@ a command like `return' or `jump' to continue execution."));
/* Do we need to do it the hard way, w/temp breakpoints? */
else if (step)
- step = maybe_software_singlestep (gdbarch, pc);
+ step = !maybe_software_singlestep (gdbarch, pc);
/* Currently, our software single-step implementation leads to different
results than hardware single-stepping in one situation: when stepping
@@ -1903,9 +1906,17 @@ a command like `return' or `jump' to continue execution."));
at the current address, deliver the signal without stepping, and
once we arrive back at the step-resume breakpoint, actually step
over the breakpoint we originally wanted to step over. */
- if (singlestep_breakpoints_inserted_p
- && tp->control.trap_expected && sig != GDB_SIGNAL_0)
+ if (thread_has_single_step_breakpoints_set (tp)
+ && sig != GDB_SIGNAL_0
+ && any_breakpoint_lifted ())
{
+ if (debug_infrun)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: delivering signal with breakpoints lifted. "
+ "replacing sss bp and letting handler run\n");
+ }
+
/* If we have nested signals or a pending signal is delivered
immediately after a handler returns, might might already have
a step-resume breakpoint set on the earlier handler. We cannot
@@ -1917,8 +1928,7 @@ a command like `return' or `jump' to continue execution."));
tp->step_after_step_resume_breakpoint = 1;
}
- remove_single_step_breakpoints ();
- singlestep_breakpoints_inserted_p = 0;
+ delete_single_step_breakpoints (tp);
clear_step_over_info ();
tp->control.trap_expected = 0;
@@ -1929,7 +1939,7 @@ a command like `return' or `jump' to continue execution."));
/* If STEP is set, it's a request to use hardware stepping
facilities. But in that case, we should never
use singlestep breakpoint. */
- gdb_assert (!(singlestep_breakpoints_inserted_p && step));
+ gdb_assert (!(thread_has_single_step_breakpoints_set (tp) && step));
/* Decide the set of threads to ask the target to resume. Start
by assuming everything will be resumed, than narrow the set
@@ -1945,7 +1955,7 @@ a command like `return' or `jump' to continue execution."));
set_running (resume_ptid, 1);
/* Maybe resume a single thread after all. */
- if ((step || singlestep_breakpoints_inserted_p)
+ if ((step || thread_has_single_step_breakpoints_set (tp))
&& tp->control.trap_expected)
{
/* We're allowing a thread to run past a breakpoint it has
@@ -1998,13 +2008,10 @@ a command like `return' or `jump' to continue execution."));
tp->suspend.stop_signal = GDB_SIGNAL_0;
/* Advise target which signals may be handled silently. If we have
- removed breakpoints because we are stepping over one (which can
- happen only if we are not using displaced stepping), we need to
- receive all signals to avoid accidentally skipping a breakpoint
- during execution of a signal handler. */
- if ((step || singlestep_breakpoints_inserted_p)
- && tp->control.trap_expected
- && !use_displaced_stepping (gdbarch))
+ removed breakpoints, we need to receive all signals to avoid
+ accidentally skipping a breakpoint during execution of a signal
+ handler. */
+ if (any_breakpoint_lifted ())
target_pass_signals (0, NULL);
else
target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
@@ -2310,7 +2317,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
struct regcache *regcache = get_current_regcache ();
set_step_over_info (get_regcache_aspace (regcache),
- regcache_read_pc (regcache));
+ regcache_read_pc (regcache), 0);
}
else
clear_step_over_info ();
@@ -2350,9 +2357,6 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
correctly when the inferior is stopped. */
tp->prev_pc = regcache_read_pc (get_current_regcache ());
- /* Reset to normal state. */
- init_infwait_state ();
-
/* Resume inferior. */
resume (tp->control.trap_expected || step || bpstat_should_step (),
tp->suspend.stop_signal);
@@ -2417,13 +2421,9 @@ init_wait_for_inferior (void)
target_last_wait_ptid = minus_one_ptid;
previous_inferior_ptid = inferior_ptid;
- init_infwait_state ();
/* Discard any skipped inlined frames. */
clear_inline_frame_state (minus_one_ptid);
-
- singlestep_ptid = null_ptid;
- singlestep_pc = 0;
}
\f
@@ -2438,9 +2438,6 @@ enum infwait_states
infwait_nonstep_watch_state
};
-/* The PTID we'll do a target_wait on.*/
-ptid_t waiton_ptid;
-
/* Current inferior wait state. */
static enum infwait_states infwait_state;
@@ -2460,11 +2457,6 @@ struct execution_control_state
const char *stop_func_name;
int wait_some_more;
- /* We were in infwait_step_watch_state or
- infwait_nonstep_watch_state state, and the thread reported an
- event. */
- int stepped_after_stopped_by_watchpoint;
-
/* True if the event thread hit the single-step breakpoint of
another thread. Thus the event doesn't cause a stop, the thread
needs to be single-stepped past the single-step breakpoint before
@@ -2609,6 +2601,7 @@ delete_step_resume_breakpoint_callback (struct thread_info *info, void *data)
delete_step_resume_breakpoint (info);
delete_exception_resume_breakpoint (info);
+ delete_single_step_breakpoints (info);
return 0;
}
@@ -2634,6 +2627,7 @@ delete_step_thread_step_resume_breakpoint (void)
delete_step_resume_breakpoint (tp);
delete_exception_resume_breakpoint (tp);
+ delete_single_step_breakpoints (tp);
}
else
/* In all-stop mode, delete all step-resume and longjmp-resume
@@ -2641,6 +2635,39 @@ delete_step_thread_step_resume_breakpoint (void)
iterate_over_threads (delete_step_resume_breakpoint_callback, NULL);
}
+static void
+delete_stopped_threads_single_step_breakpoints (void)
+{
+ if (!target_has_execution
+ || ptid_equal (inferior_ptid, null_ptid))
+ {
+ /* If the inferior has exited, we have already deleted the
+ single-step breakpoints out of GDB's lists. */
+ return;
+ }
+
+ if (non_stop)
+ {
+ /* If in non-stop mode, only delete the step-resume or
+ longjmp-resume breakpoint of the thread that just stopped
+ stepping. */
+ struct thread_info *tp = inferior_thread ();
+
+ delete_single_step_breakpoints (tp);
+ }
+ else
+ {
+ struct thread_info *tp;
+
+ ALL_NON_EXITED_THREADS (tp)
+ {
+ /* In all-stop mode, delete single-step breakpoints of any
+ thread that had them. */
+ delete_single_step_breakpoints (tp);
+ }
+ }
+}
+
/* A cleanup wrapper. */
static void
@@ -2789,6 +2816,7 @@ wait_for_inferior (void)
struct execution_control_state ecss;
struct execution_control_state *ecs = &ecss;
struct cleanup *old_chain;
+ ptid_t waiton_ptid = minus_one_ptid;
memset (ecs, 0, sizeof (*ecs));
@@ -2844,6 +2872,7 @@ fetch_inferior_event (void *client_data)
struct cleanup *ts_old_chain;
int was_sync = sync_execution;
int cmd_done = 0;
+ ptid_t waiton_ptid = minus_one_ptid;
memset (ecs, 0, sizeof (*ecs));
@@ -2961,6 +2990,7 @@ void
init_thread_stepping_state (struct thread_info *tss)
{
tss->stepping_over_breakpoint = 0;
+ tss->stepping_over_watchpoint = 0;
tss->step_after_step_resume_breakpoint = 0;
}
@@ -3120,7 +3150,7 @@ adjust_pc_after_break (struct execution_control_state *ecs)
software breakpoint. In this case (prev_pc == breakpoint_pc),
we also need to back up to the breakpoint address. */
- if (singlestep_breakpoints_inserted_p
+ if (thread_has_single_step_breakpoints_set (ecs->event_thread)
|| !ptid_equal (ecs->ptid, inferior_ptid)
|| !currently_stepping (ecs->event_thread)
|| ecs->event_thread->prev_pc == breakpoint_pc)
@@ -3130,13 +3160,6 @@ adjust_pc_after_break (struct execution_control_state *ecs)
}
}
-static void
-init_infwait_state (void)
-{
- waiton_ptid = pid_to_ptid (-1);
- infwait_state = infwait_normal_state;
-}
-
static int
stepped_in_from (struct frame_info *frame, struct frame_id step_frame_id)
{
@@ -3357,40 +3380,6 @@ handle_inferior_event (struct execution_control_state *ecs)
&& ecs->ws.kind != TARGET_WAITKIND_EXITED)
set_executing (ecs->ptid, 0);
- switch (infwait_state)
- {
- case infwait_normal_state:
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: infwait_normal_state\n");
- break;
-
- case infwait_step_watch_state:
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: infwait_step_watch_state\n");
-
- ecs->stepped_after_stopped_by_watchpoint = 1;
- break;
-
- case infwait_nonstep_watch_state:
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: infwait_nonstep_watch_state\n");
- insert_breakpoints ();
-
- /* FIXME-maybe: is this cleaner than setting a flag? Does it
- handle things like signals arriving and other things happening
- in combination correctly? */
- ecs->stepped_after_stopped_by_watchpoint = 1;
- break;
-
- default:
- internal_error (__FILE__, __LINE__, _("bad switch"));
- }
-
- infwait_state = infwait_normal_state;
- waiton_ptid = pid_to_ptid (-1);
-
switch (ecs->ws.kind)
{
case TARGET_WAITKIND_LOADED:
@@ -3548,8 +3537,6 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
gdb_flush (gdb_stdout);
target_mourn_inferior ();
- singlestep_breakpoints_inserted_p = 0;
- cancel_single_step_breakpoints ();
stop_print_frame = 0;
stop_waiting (ecs);
return;
@@ -3642,12 +3629,7 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
detach_breakpoints (ecs->ws.value.related_pid);
}
- if (singlestep_breakpoints_inserted_p)
- {
- /* Pull the single step breakpoints out of the target. */
- remove_single_step_breakpoints ();
- singlestep_breakpoints_inserted_p = 0;
- }
+ delete_stopped_threads_single_step_breakpoints ();
/* In case the event is caught by a catchpoint, remember that
the event is to be followed at the next resume of the thread,
@@ -3734,9 +3716,6 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
if (!ptid_equal (ecs->ptid, inferior_ptid))
context_switch (ecs->ptid);
- singlestep_breakpoints_inserted_p = 0;
- cancel_single_step_breakpoints ();
-
stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
/* Do whatever is necessary to the parent branch of the vfork. */
@@ -3802,14 +3781,7 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_NO_HISTORY\n");
/* Reverse execution: target ran out of history info. */
- /* Pull the single step breakpoints out of the target. */
- if (singlestep_breakpoints_inserted_p)
- {
- if (!ptid_equal (ecs->ptid, inferior_ptid))
- context_switch (ecs->ptid);
- remove_single_step_breakpoints ();
- singlestep_breakpoints_inserted_p = 0;
- }
+ delete_stopped_threads_single_step_breakpoints ();
stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
observer_notify_no_history ();
stop_waiting (ecs);
@@ -3948,43 +3920,59 @@ handle_signal_stop (struct execution_control_state *ecs)
gdbarch = get_frame_arch (frame);
/* Pull the single step breakpoints out of the target. */
- if (singlestep_breakpoints_inserted_p)
+ if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
+ && gdbarch_software_single_step_p (gdbarch))
{
+ struct regcache *regcache;
+ struct address_space *aspace;
+ CORE_ADDR pc;
+
+ regcache = get_thread_regcache (ecs->ptid);
+ aspace = get_regcache_aspace (regcache);
+ pc = regcache_read_pc (regcache);
+
/* However, before doing so, if this single-step breakpoint was
actually for another thread, set this thread up for moving
past it. */
- if (!ptid_equal (ecs->ptid, singlestep_ptid)
- && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
+ if (!thread_has_single_step_breakpoint_here (ecs->event_thread,
+ aspace, pc))
{
- struct regcache *regcache;
- struct address_space *aspace;
- CORE_ADDR pc;
-
- regcache = get_thread_regcache (ecs->ptid);
- aspace = get_regcache_aspace (regcache);
- pc = regcache_read_pc (regcache);
if (single_step_breakpoint_inserted_here_p (aspace, pc))
{
if (debug_infrun)
{
fprintf_unfiltered (gdb_stdlog,
- "infrun: [%s] hit step over single-step"
- " breakpoint of [%s]\n",
- target_pid_to_str (ecs->ptid),
- target_pid_to_str (singlestep_ptid));
+ "infrun: [%s] hit another thread's "
+ "single-step breakpoint\n",
+ target_pid_to_str (ecs->ptid));
}
ecs->hit_singlestep_breakpoint = 1;
}
}
+ else
+ {
+ if (debug_infrun)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: [%s] hit its "
+ "single-step breakpoint\n",
+ target_pid_to_str (ecs->ptid));
+ }
+ }
- remove_single_step_breakpoints ();
- singlestep_breakpoints_inserted_p = 0;
+ delete_stopped_threads_single_step_breakpoints ();
}
- if (ecs->stepped_after_stopped_by_watchpoint)
- stopped_by_watchpoint = 0;
+ if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
+ && ecs->event_thread->control.trap_expected
+ && ecs->event_thread->stepping_over_watchpoint)
+ {
+ stopped_by_watchpoint = 0;
+ }
else
- stopped_by_watchpoint = watchpoints_triggered (&ecs->ws);
+ {
+ stopped_by_watchpoint = watchpoints_triggered (&ecs->ws);
+ }
/* If necessary, step over this watchpoint. We'll be back to display
it in a moment. */
@@ -4004,36 +3992,28 @@ handle_signal_stop (struct execution_control_state *ecs)
watchpoint expression. We do this by single-stepping the
target.
- It may not be necessary to disable the watchpoint to stop over
+ It may not be necessary to disable the watchpoint to step over
it. For example, the PA can (with some kernel cooperation)
single step over a watchpoint without disabling the watchpoint.
It is far more common to need to disable a watchpoint to step
the inferior over it. If we have non-steppable watchpoints,
we must disable the current watchpoint; it's simplest to
- disable all watchpoints and breakpoints. */
- int hw_step = 1;
-
- if (!target_have_steppable_watchpoint)
- {
- remove_breakpoints ();
- /* See comment in resume why we need to stop bypassing signals
- while breakpoints have been removed. */
- target_pass_signals (0, NULL);
- }
- /* Single step */
- hw_step = maybe_software_singlestep (gdbarch, stop_pc);
- target_resume (ecs->ptid, hw_step, GDB_SIGNAL_0);
- waiton_ptid = ecs->ptid;
- if (target_have_steppable_watchpoint)
- infwait_state = infwait_step_watch_state;
- else
- infwait_state = infwait_nonstep_watch_state;
- prepare_to_wait (ecs);
+ disable all watchpoints.
+
+ Any breakpoint at PC must also be stepped over -- if there's
+ one, it will have already triggered before the watchpoint
+ triggered, and we either already reported it to the user, or
+ it didn't cause a stop and we called keep_going. In either
+ case, if there was a breakpoint at PC, we must be trying to
+ step past it. */
+ ecs->event_thread->stepping_over_watchpoint = 1;
+ keep_going (ecs);
return;
}
ecs->event_thread->stepping_over_breakpoint = 0;
+ ecs->event_thread->stepping_over_watchpoint = 0;
bpstat_clear (&ecs->event_thread->control.stop_bpstat);
ecs->event_thread->control.stop_step = 0;
stop_print_frame = 1;
@@ -5311,15 +5291,21 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
- "infrun: expected thread advanced also\n");
+ "infrun: expected thread advanced also: prev_pc=%s, stop_pc=%s\n",
+ paddress (gdbarch, tp->prev_pc),
+ paddress (gdbarch, stop_pc));
+
+ /* Clear this before trying to insert the sss
+ breakpoint, in case we were previously trying to step
+ over this location in another thread, otherwise the
+ breakpoint ends up _not_ installed. It's what
+ keep_going would do too, if we called it. */
+ clear_step_over_info ();
insert_single_step_breakpoint (get_frame_arch (frame),
get_frame_address_space (frame),
stop_pc);
- singlestep_breakpoints_inserted_p = 1;
ecs->event_thread->control.trap_expected = 1;
- singlestep_ptid = inferior_ptid;
- singlestep_pc = stop_pc;
resume (0, GDB_SIGNAL_0);
prepare_to_wait (ecs);
@@ -5769,6 +5755,8 @@ keep_going (struct execution_control_state *ecs)
{
volatile struct gdb_exception e;
struct regcache *regcache = get_current_regcache ();
+ int remove_bp;
+ int remove_wps;
/* Either the trap was not expected, but we are continuing
anyway (if we got a signal, the user asked it be passed to
@@ -5788,13 +5776,19 @@ keep_going (struct execution_control_state *ecs)
(watchpoints, etc.) but the one we're stepping over, step one
instruction, and then re-insert the breakpoint when that step
is finished. */
- if ((ecs->hit_singlestep_breakpoint
- || thread_still_needs_step_over (ecs->event_thread))
- && !use_displaced_stepping (get_regcache_arch (regcache)))
+
+ remove_bp = (ecs->hit_singlestep_breakpoint
+ || thread_still_needs_step_over (ecs->event_thread));
+ remove_wps = (ecs->event_thread->stepping_over_watchpoint
+ && !target_have_steppable_watchpoint);
+
+ if (remove_bp && !use_displaced_stepping (get_regcache_arch (regcache)))
{
set_step_over_info (get_regcache_aspace (regcache),
- regcache_read_pc (regcache));
+ regcache_read_pc (regcache), remove_wps);
}
+ else if (remove_wps)
+ set_step_over_info (NULL, 0, remove_wps);
else
clear_step_over_info ();
@@ -5810,9 +5804,7 @@ keep_going (struct execution_control_state *ecs)
return;
}
- ecs->event_thread->control.trap_expected
- = (ecs->event_thread->stepping_over_breakpoint
- || ecs->hit_singlestep_breakpoint);
+ ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
/* Do not deliver GDB_SIGNAL_TRAP (except when the user
explicitly specifies that such a signal should be delivered
diff --git a/gdb/infrun.h b/gdb/infrun.h
index cc9cb33..13127ed 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -122,6 +122,10 @@ extern void follow_inferior_reset_breakpoints (void);
extern int stepping_past_instruction_at (struct address_space *aspace,
CORE_ADDR address);
+/* Returns true if we're trying to step past an instruction that
+ triggers a non-steppable watchpoint. */
+extern int stepping_past_nonsteppable_watchpoint (void);
+
extern void set_step_info (struct frame_info *frame,
struct symtab_and_line sal);
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 119361f..a2257ed 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -961,7 +961,7 @@ record_full_resume (struct target_ops *ops, ptid_t ptid, int step,
else
{
/* This arch support soft sigle step. */
- if (single_step_breakpoints_inserted ())
+ if (thread_has_single_step_breakpoints_set (inferior_thread ()))
{
/* This is a soft single step. */
record_full_resume_step = 1;
@@ -1085,6 +1085,8 @@ record_full_wait_1 (struct target_ops *ops,
while (1)
{
+ struct thread_info *tp;
+
ret = ops->beneath->to_wait (ops->beneath, ptid, status, options);
if (status->kind == TARGET_WAITKIND_IGNORE)
{
@@ -1095,8 +1097,8 @@ record_full_wait_1 (struct target_ops *ops,
return ret;
}
- if (single_step_breakpoints_inserted ())
- remove_single_step_breakpoints ();
+ ALL_NON_EXITED_THREADS (tp)
+ delete_single_step_breakpoints (tp);
if (record_full_resume_step)
return ret;
diff --git a/gdb/thread.c b/gdb/thread.c
index 65890e1..1cdbaf4 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -85,26 +85,68 @@ inferior_thread (void)
return tp;
}
-void
-delete_step_resume_breakpoint (struct thread_info *tp)
+/* Delete the breakpoint pointed at by BP_P, if there's one. */
+
+static void
+delete_thread_breakpoint (struct breakpoint **bp_p)
{
- if (tp && tp->control.step_resume_breakpoint)
+ if (*bp_p != NULL)
{
- delete_breakpoint (tp->control.step_resume_breakpoint);
- tp->control.step_resume_breakpoint = NULL;
+ delete_breakpoint (*bp_p);
+ *bp_p = NULL;
}
}
void
+delete_step_resume_breakpoint (struct thread_info *tp)
+{
+ if (tp != NULL)
+ delete_thread_breakpoint (&tp->control.step_resume_breakpoint);
+}
+
+void
delete_exception_resume_breakpoint (struct thread_info *tp)
{
- if (tp && tp->control.exception_resume_breakpoint)
+ if (tp != NULL)
+ delete_thread_breakpoint (&tp->control.exception_resume_breakpoint);
+}
+
+void
+delete_single_step_breakpoints (struct thread_info *tp)
+{
+ if (tp != NULL)
+ delete_thread_breakpoint (&tp->control.single_step_breakpoints);
+}
+
+/* Delete the breakpoint pointed at by BP_P at the next stop, if
+ there's one. */
+
+static void
+delete_at_next_stop (struct breakpoint **bp)
+{
+ if (*bp != NULL)
{
- delete_breakpoint (tp->control.exception_resume_breakpoint);
- tp->control.exception_resume_breakpoint = NULL;
+ (*bp)->disposition = disp_del_at_next_stop;
+ *bp = NULL;
}
}
+int
+thread_has_single_step_breakpoints_set (struct thread_info *tp)
+{
+ return tp->control.single_step_breakpoints != NULL;
+}
+
+int
+thread_has_single_step_breakpoint_here (struct thread_info *tp,
+ struct address_space *aspace,
+ CORE_ADDR addr)
+{
+ return (tp->control.single_step_breakpoints != NULL
+ && breakpoint_is_inserted_here (tp->control.single_step_breakpoints,
+ aspace, addr));
+}
+
static void
clear_thread_inferior_resources (struct thread_info *tp)
{
@@ -112,18 +154,9 @@ clear_thread_inferior_resources (struct thread_info *tp)
but not any user-specified thread-specific breakpoints. We can not
delete the breakpoint straight-off, because the inferior might not
be stopped at the moment. */
- if (tp->control.step_resume_breakpoint)
- {
- tp->control.step_resume_breakpoint->disposition = disp_del_at_next_stop;
- tp->control.step_resume_breakpoint = NULL;
- }
-
- if (tp->control.exception_resume_breakpoint)
- {
- tp->control.exception_resume_breakpoint->disposition
- = disp_del_at_next_stop;
- tp->control.exception_resume_breakpoint = NULL;
- }
+ delete_at_next_stop (&tp->control.step_resume_breakpoint);
+ delete_at_next_stop (&tp->control.exception_resume_breakpoint);
+ delete_at_next_stop (&tp->control.single_step_breakpoints);
delete_longjmp_breakpoint_at_next_stop (tp->num);
--
1.9.3
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-09 12:38 ` Peter Schauer
@ 2014-09-09 21:25 ` Ulrich Weigand
2014-09-10 12:21 ` Joel Brobecker
0 siblings, 1 reply; 31+ messages in thread
From: Ulrich Weigand @ 2014-09-09 21:25 UTC (permalink / raw)
To: Peter Schauer; +Cc: Joel Brobecker, Pedro Alves, GDB Patches
Peter Schauer wrote:
> > > I think you could/should zap exec_one_dummy_insn, provided that you test
> > > a dummy function call on the oldest AIX version that GDB has to support,
> > > with a large aggregate parameter, which is passed by value.
> >
> > The only version I have ready access to is AIX 7.1, and on this there
> > are no testsuite regression (and in fact, quite a number of failures
> > seem to go away!) when zapping exec_one_dummy_insn.
>
> +1 for zapping exec_one_dummy_insn.
>
> > I'm not sure which versions we need to / should support in GDB; I guess
> > the oldest version where the OS itself is still supported by IBM is 6.1.
>
> Maybe somebody could test if zapping exec_one_dummy_insn on AIX 6.1
> has any negative effect, and then be done with it.
>
> But even if that can't be tested, I am all in favour of getting rid
> of it, perhaps with a detailed comment in the commit message for the
> removal (or adding a link to this thread).
I've now got access to an AIX 6.1 machine and repeated the experiment --
with the same result. No regressions when zapping exec_one_dummy_insn,
and in fact about 100 FAILs fixed.
So I think we should probably just do it at this point.
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-08 19:24 ` Joel Brobecker
2014-09-08 21:34 ` Joel Brobecker
@ 2014-09-09 21:48 ` Ulrich Weigand
2014-09-10 12:29 ` Joel Brobecker
1 sibling, 1 reply; 31+ messages in thread
From: Ulrich Weigand @ 2014-09-09 21:48 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Pedro Alves, GDB Patches
Joel Brobecker wrote:
> > procfs.c: dbx_link_bpt = deprecated_insert_raw_breakpoint (target_gdbarch (), NULL,
> >
> > This is only compiled if SYS_syssgi is defined, which I believe means
> > MIPS IRIX. Do we still care about MIPS IRIX?
> >
> > solib-irix.c: base_breakpoint = deprecated_insert_raw_breakpoint (target_gdbarch (),
>
> I would be surprised if anyone still cared about IRIX anymore.
> I enjoyed working on that system, but I no longer have access
> to it, so can't support it anymore.
I see that IRIX seems to be in "Retired Mode" as of 12/31/2013:
http://www.sgi.com/tech/irix/?_mips_support.html
Do we have a current process to formally obsolete/remove support
for old systems?
[ I guess another candidate to remove might be Alpha OSF/1 ... ]
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-09 21:25 ` Ulrich Weigand
@ 2014-09-10 12:21 ` Joel Brobecker
2014-09-10 13:15 ` Ulrich Weigand
0 siblings, 1 reply; 31+ messages in thread
From: Joel Brobecker @ 2014-09-10 12:21 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: Peter Schauer, Pedro Alves, GDB Patches
> I've now got access to an AIX 6.1 machine and repeated the experiment --
> with the same result. No regressions when zapping exec_one_dummy_insn,
> and in fact about 100 FAILs fixed.
>
> So I think we should probably just do it at this point.
Agreed! Would you do the honors, or would you like me to?
Thanks for doing the testing, Ulrich.
--
Joel
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-09 21:48 ` Ulrich Weigand
@ 2014-09-10 12:29 ` Joel Brobecker
2014-09-10 14:45 ` Ulrich Weigand
0 siblings, 1 reply; 31+ messages in thread
From: Joel Brobecker @ 2014-09-10 12:29 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: Pedro Alves, GDB Patches
> > I would be surprised if anyone still cared about IRIX anymore.
> > I enjoyed working on that system, but I no longer have access
> > to it, so can't support it anymore.
>
> I see that IRIX seems to be in "Retired Mode" as of 12/31/2013:
> http://www.sgi.com/tech/irix/?_mips_support.html
And I saw yesterday on the binutils mailing-list that IRIX support
was removed from GCC already. I think these are all pretty strong
indicators.
> Do we have a current process to formally obsolete/remove support
> for old systems?
>
> [ I guess another candidate to remove might be Alpha OSF/1 ... ]
Here is what I found:
https://sourceware.org/gdb/wiki/Internals%20Obsoleting-code
I agree we can obsolete Alpha OSF/1 as well.
--
Joel
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-10 12:21 ` Joel Brobecker
@ 2014-09-10 13:15 ` Ulrich Weigand
2014-09-10 15:22 ` Pedro Alves
0 siblings, 1 reply; 31+ messages in thread
From: Ulrich Weigand @ 2014-09-10 13:15 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Peter Schauer, Pedro Alves, GDB Patches
Joel Brobecker wrote:
> > I've now got access to an AIX 6.1 machine and repeated the experiment --
> > with the same result. No regressions when zapping exec_one_dummy_insn,
> > and in fact about 100 FAILs fixed.
> >
> > So I think we should probably just do it at this point.
>
> Agreed! Would you do the honors, or would you like me to?
>
> Thanks for doing the testing, Ulrich.
I'll check it in shortly.
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-10 12:29 ` Joel Brobecker
@ 2014-09-10 14:45 ` Ulrich Weigand
2014-09-10 15:21 ` Pedro Alves
2014-10-07 0:25 ` eliminate deprecated_insert_raw_breakpoint. what's left Stan Shebs
0 siblings, 2 replies; 31+ messages in thread
From: Ulrich Weigand @ 2014-09-10 14:45 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Pedro Alves, GDB Patches
Joel Brobecker wrote:
> > > I would be surprised if anyone still cared about IRIX anymore.
> > > I enjoyed working on that system, but I no longer have access
> > > to it, so can't support it anymore.
> >
> > I see that IRIX seems to be in "Retired Mode" as of 12/31/2013:
> > http://www.sgi.com/tech/irix/?_mips_support.html
>
> And I saw yesterday on the binutils mailing-list that IRIX support
> was removed from GCC already. I think these are all pretty strong
> indicators.
>
> > Do we have a current process to formally obsolete/remove support
> > for old systems?
> >
> > [ I guess another candidate to remove might be Alpha OSF/1 ... ]
>
> Here is what I found:
> https://sourceware.org/gdb/wiki/Internals%20Obsoleting-code
>
> I agree we can obsolete Alpha OSF/1 as well.
Once OSF/1 and IRIX are gone, I hope all of the ECOFF/mdebug debug
format support can go as well (mipsread.c, mdebugread.c etc.) ...
The process documented in the Wiki is a bit weird (adding OBSOLETE
to *every line* of those files ???) and it seems we didn't follow
it in the last major round of obsoleting code either:
https://sourceware.org/ml/gdb-announce/2007/msg00000.html
I think using a process along similar lines might be best.
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-10 14:45 ` Ulrich Weigand
@ 2014-09-10 15:21 ` Pedro Alves
2014-09-10 15:50 ` Maciej W. Rozycki
2014-09-10 15:50 ` eliminate deprecated_insert_raw_breakpoint. what's left Joel Brobecker
2014-10-07 0:25 ` eliminate deprecated_insert_raw_breakpoint. what's left Stan Shebs
1 sibling, 2 replies; 31+ messages in thread
From: Pedro Alves @ 2014-09-10 15:21 UTC (permalink / raw)
To: Ulrich Weigand, Joel Brobecker; +Cc: GDB Patches
On 09/10/2014 03:45 PM, Ulrich Weigand wrote:
> Joel Brobecker wrote:
>>>> I would be surprised if anyone still cared about IRIX anymore.
>>>> I enjoyed working on that system, but I no longer have access
>>>> to it, so can't support it anymore.
>>>
>>> I see that IRIX seems to be in "Retired Mode" as of 12/31/2013:
>>> http://www.sgi.com/tech/irix/?_mips_support.html
>>
>> And I saw yesterday on the binutils mailing-list that IRIX support
>> was removed from GCC already. I think these are all pretty strong
>> indicators.
>>
>>> Do we have a current process to formally obsolete/remove support
>>> for old systems?
>>>
>>> [ I guess another candidate to remove might be Alpha OSF/1 ... ]
>>
>> Here is what I found:
>> https://sourceware.org/gdb/wiki/Internals%20Obsoleting-code
>>
>> I agree we can obsolete Alpha OSF/1 as well.
>
> Once OSF/1 and IRIX are gone, I hope all of the ECOFF/mdebug debug
> format support can go as well (mipsread.c, mdebugread.c etc.) ...
>
> The process documented in the Wiki is a bit weird (adding OBSOLETE
> to *every line* of those files ???)
Yeah, I recall seeing such OBSOLETE-marked files long ago. I agree
it's weird.
> and it seems we didn't follow
> it in the last major round of obsoleting code either:
> https://sourceware.org/ml/gdb-announce/2007/msg00000.html
>
> I think using a process along similar lines might be best.
Definitely agreed.
I think that obsoleting page is obsolete. :-)
Meanwhile, I'd prefer removing deprecated_insert_raw_breakpoint
now rather than keeping it just for IRIX. I may send a
best-effort-but-untested patch for IRIX. If things break, it'd be
the job of whoever shows up as wanting to maintain IRIX to
fix and modernize things further. WDYT?
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-10 13:15 ` Ulrich Weigand
@ 2014-09-10 15:22 ` Pedro Alves
0 siblings, 0 replies; 31+ messages in thread
From: Pedro Alves @ 2014-09-10 15:22 UTC (permalink / raw)
To: Ulrich Weigand, Joel Brobecker; +Cc: Peter Schauer, GDB Patches
On 09/10/2014 02:15 PM, Ulrich Weigand wrote:
> Joel Brobecker wrote:
>>> I've now got access to an AIX 6.1 machine and repeated the experiment --
>>> with the same result. No regressions when zapping exec_one_dummy_insn,
>>> and in fact about 100 FAILs fixed.
>>>
>>> So I think we should probably just do it at this point.
>>
>> Agreed! Would you do the honors, or would you like me to?
>>
>> Thanks for doing the testing, Ulrich.
>
> I'll check it in shortly.
Thanks guys!
One down, two to go. :-)
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-10 15:21 ` Pedro Alves
2014-09-10 15:50 ` Maciej W. Rozycki
@ 2014-09-10 15:50 ` Joel Brobecker
2014-09-10 16:00 ` Sergio Durigan Junior
2014-09-10 16:36 ` Ulrich Weigand
1 sibling, 2 replies; 31+ messages in thread
From: Joel Brobecker @ 2014-09-10 15:50 UTC (permalink / raw)
To: Pedro Alves; +Cc: Ulrich Weigand, GDB Patches
> > and it seems we didn't follow
> > it in the last major round of obsoleting code either:
> > https://sourceware.org/ml/gdb-announce/2007/msg00000.html
> >
> > I think using a process along similar lines might be best.
>
> Definitely agreed.
>
> I think that obsoleting page is obsolete. :-)
OK with me as well. I suspect this was to allow for easy reviving
if someone stepped up, but completely OBE now that we've moved
to git.
So let's discuss the new obsoleting procedure, so we can document it:
. I think that the first 4 steps (post email on gdb@, wait a week,
then on gdb-announce, wait another week) are fine. Anyone thinks
we should go straight to gdb-announce?
My thinking is that people interested in maintaining a port
with enough skills to do so are likely to already be on gdb@,
so we can avoid sending an extra mail to gdb-announce. But
the traffic on gdb-announce being very low, and the frequency
at which we deprecate targets being fairly small as well,
I wouldn't object to a simpler procedure where we email
gdb-announce directly.
. Remove steps 5 & 6 that mark the code as obsolete, only keeping
the last test, which removes the code. I'd add a note to add
a NEWS entry.
> Meanwhile, I'd prefer removing deprecated_insert_raw_breakpoint
> now rather than keeping it just for IRIX. I may send a
> best-effort-but-untested patch for IRIX. If things break, it'd be
> the job of whoever shows up as wanting to maintain IRIX to
> fix and modernize things further. WDYT?
Sounds like a plan.
--
Joel
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-10 15:21 ` Pedro Alves
@ 2014-09-10 15:50 ` Maciej W. Rozycki
2014-09-10 16:12 ` [IRIX] eliminate deprecated_insert_raw_breakpoint uses Pedro Alves
2014-09-10 15:50 ` eliminate deprecated_insert_raw_breakpoint. what's left Joel Brobecker
1 sibling, 1 reply; 31+ messages in thread
From: Maciej W. Rozycki @ 2014-09-10 15:50 UTC (permalink / raw)
To: Pedro Alves; +Cc: Ulrich Weigand, Joel Brobecker, GDB Patches
On Wed, 10 Sep 2014, Pedro Alves wrote:
> Meanwhile, I'd prefer removing deprecated_insert_raw_breakpoint
> now rather than keeping it just for IRIX. I may send a
> best-effort-but-untested patch for IRIX. If things break, it'd be
> the job of whoever shows up as wanting to maintain IRIX to
> fix and modernize things further. WDYT?
FWIW I have no objections to this plan. I wonder if there's anything
special here actually or if it's just that nobody bothered to convert this
code to using `create_internal_breakpoint' or suchlike.
Maciej
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-10 15:50 ` eliminate deprecated_insert_raw_breakpoint. what's left Joel Brobecker
@ 2014-09-10 16:00 ` Sergio Durigan Junior
2014-09-10 16:36 ` Ulrich Weigand
1 sibling, 0 replies; 31+ messages in thread
From: Sergio Durigan Junior @ 2014-09-10 16:00 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Pedro Alves, Ulrich Weigand, GDB Patches
On Wednesday, September 10 2014, Joel Brobecker wrote:
> So let's discuss the new obsoleting procedure, so we can document it:
>
> . I think that the first 4 steps (post email on gdb@, wait a week,
> then on gdb-announce, wait another week) are fine. Anyone thinks
> we should go straight to gdb-announce?
>
> My thinking is that people interested in maintaining a port
> with enough skills to do so are likely to already be on gdb@,
> so we can avoid sending an extra mail to gdb-announce. But
> the traffic on gdb-announce being very low, and the frequency
> at which we deprecate targets being fairly small as well,
> I wouldn't object to a simpler procedure where we email
> gdb-announce directly.
Not sure if it is implicit, but it would be good to send an email to
gdb-patches as well. I have a feeling that some people just read/pay
attention to gdb-patches...
Other than that, I totally agree with the plan.
Cheers,
--
Sergio
GPG key ID: 0x65FC5E36
Please send encrypted e-mail if possible
http://sergiodj.net/
^ permalink raw reply [flat|nested] 31+ messages in thread
* [IRIX] eliminate deprecated_insert_raw_breakpoint uses
2014-09-10 15:50 ` Maciej W. Rozycki
@ 2014-09-10 16:12 ` Pedro Alves
2014-09-10 22:44 ` Joel Brobecker
0 siblings, 1 reply; 31+ messages in thread
From: Pedro Alves @ 2014-09-10 16:12 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: Ulrich Weigand, Joel Brobecker, GDB Patches
On 09/10/2014 04:50 PM, Maciej W. Rozycki wrote:
> On Wed, 10 Sep 2014, Pedro Alves wrote:
>
>> Meanwhile, I'd prefer removing deprecated_insert_raw_breakpoint
>> now rather than keeping it just for IRIX. I may send a
>> best-effort-but-untested patch for IRIX. If things break, it'd be
>> the job of whoever shows up as wanting to maintain IRIX to
>> fix and modernize things further. WDYT?
>
> FWIW I have no objections to this plan. I wonder if there's anything
> special here actually or if it's just that nobody bothered to convert this
> code to using `create_internal_breakpoint' or suchlike.
There are definitely things here that could/should be modernized.
The loop in irix_solib_create_inferior_hook (and similars in other ports)
is something that's an old way of doing things and gotten in the way
before.
I think I understand this enough now. See patch below, which
gets rid of that loop completely.
Untested, of course.
--------
From 70c27f4a9a26c46d5ac356258ba2f76a6ac04269 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Wed, 10 Sep 2014 14:56:51 +0100
Subject: [PATCH] [IRIX] eliminate deprecated_insert_raw_breakpoint uses
The IRIX support wants to set a breakpoint to be hit when the startup
phase is complete, which is where shared libraries have been mapped
in. AFAIU, for most IRIX ports, that location is the entry point.
For MIPS IRIX however, GDB needs to set a breakpoint earlier, in
__dbx_link, as explained by:
#ifdef SYS_syssgi
/* On mips-irix, we need to stop the inferior early enough during
the startup phase in order to be able to load the shared library
symbols and insert the breakpoints that are located in these shared
libraries. Stopping at the program entry point is not good enough
because the -init code is executed before the execution reaches
that point.
So what we need to do is to insert a breakpoint in the runtime
loader (rld), more precisely in __dbx_link(). This procedure is
called by rld once all shared libraries have been mapped, but before
the -init code is executed. Unfortuantely, this is not straightforward,
as rld is not part of the executable we are running, and thus we need
the inferior to run until rld itself has been mapped in memory.
For this, we trace all syssgi() syscall exit events. Each time
we detect such an event, we iterate over each text memory maps,
get its associated fd, and scan the symbol table for __dbx_link().
When found, we know that rld has been mapped, and that we can insert
the breakpoint at the symbol address. Once the dbx_link() breakpoint
has been inserted, the syssgi() notifications are no longer necessary,
so they should be canceled. */
proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT, FLAG_SET, 0);
#endif
The loop in irix_solib_create_inferior_hook then runs until whichever
breakpoint is hit first, the one set by solib-irix.c or the one set by
procfs.c.
Note the comment in disable_break talks about __dbx_init, but I think
that's a typo for __dbx_link:
- /* Note that it is possible that we have stopped at a location that
- is different from the location where we inserted our breakpoint.
- On mips-irix, we can actually land in __dbx_init(), so we should
- not check the PC against our breakpoint address here. See procfs.c
- for more details. */
This looks very much like referring to the loop in
irix_solib_create_inferior_hook stopping at __dbx_link instead of at
the entry point.
What this patch does is convert these deprecated raw breakpoints to
standard solib_event breakpoints. When the first solib-event
breakpoint is hit, we delete all solib-event breakpoints. We do that
in the so_ops->handle_event hook.
This allows getting rid of the loop in irix_solib_create_inferior_hook
completely, which should allow properly handling signals and other
events in the early startup phase, like in SVR4.
Built on x86_64 Fedora 20 with --enable-targets=all (builds
solib-irix.c), but otherwise completely untested.
gdb/ChangeLog:
2014-09-10 Pedro Alves <palves@redhat.com>
* procfs.c (dbx_link_bpt_addr, dbx_link_bpt): Delete globals.
(remove_dbx_link_breakpoint): Delete function.
(insert_dbx_link_bpt_in_file): Use create_solib_event_breakpoint
instead of deprecated_insert_raw_breakpoint. Don't check whether
we hit __dbx_link here.
(procfs_mourn_inferior): Don't delete the __dbx_link breakpoint
here.
* solib-irix.c (base_breakpoint): Delete global.
(disable_break): Delete function.
(enable_break): Use create_solib_event_breakpoint
instead of deprecated_insert_raw_breakpoint.
(irix_solib_handle_event): New function.
(irix_solib_create_inferior_hook): Don't run the target or disable
the mapping-complete breakpoint here.
(_initialize_irix_solib): Install irix_solib_handle_event as
so_ops->handle_event hook.
---
gdb/procfs.c | 51 +++++----------------------
gdb/solib-irix.c | 104 +++++++++++++++----------------------------------------
2 files changed, 35 insertions(+), 120 deletions(-)
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 3465bc5..37ef05c 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -2902,13 +2902,6 @@ static void do_detach (int signo);
static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum,
int entry_or_exit, int mode, int from_tty);
-/* On mips-irix, we need to insert a breakpoint at __dbx_link during
- the startup phase. The following two variables are used to record
- the address of the breakpoint, and the code that was replaced by
- a breakpoint. */
-static int dbx_link_bpt_addr = 0;
-static void *dbx_link_bpt;
-
/* Sets up the inferior to be debugged. Registers to trace signals,
hardware faults, and syscalls. Note: does not set RLC flag: caller
may want to customize that. Returns zero for success (note!
@@ -3380,23 +3373,6 @@ syscall_is_lwp_create (procinfo *pi, int scall)
return 0;
}
-/* Remove the breakpoint that we inserted in __dbx_link().
- Does nothing if the breakpoint hasn't been inserted or has already
- been removed. */
-
-static void
-remove_dbx_link_breakpoint (void)
-{
- if (dbx_link_bpt_addr == 0)
- return;
-
- if (deprecated_remove_raw_breakpoint (target_gdbarch (), dbx_link_bpt) != 0)
- warning (_("Unable to remove __dbx_link breakpoint."));
-
- dbx_link_bpt_addr = 0;
- dbx_link_bpt = NULL;
-}
-
#ifdef SYS_syssgi
/* Return the address of the __dbx_link() function in the file
refernced by ABFD by scanning its symbol table. Return 0 if
@@ -3461,13 +3437,17 @@ insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
sym_addr = dbx_link_addr (abfd);
if (sym_addr != 0)
{
+ struct breakpoint *dbx_link_bpt;
+
/* Insert the breakpoint. */
- dbx_link_bpt_addr = sym_addr;
- dbx_link_bpt = deprecated_insert_raw_breakpoint (target_gdbarch (), NULL,
- sym_addr);
- if (dbx_link_bpt == NULL)
+ dbx_link_bpt = create_solib_event_breakpoint (target_gdbarch (), sym_addr);
+
+ if (!breakpoints_always_inserted_mode ())
+ insert_breakpoint_locations ();
+ if (!dbx_link_bpt->loc->inserted)
{
warning (_("Failed to insert dbx_link breakpoint."));
+ delete_breakpoint (dbx_link_bpt);
gdb_bfd_unref (abfd);
return 0;
}
@@ -3894,14 +3874,6 @@ wait_again:
#if (FLTTRACE != FLTBPT) /* Avoid "duplicate case" error. */
case FLTTRACE:
#endif
- /* If we hit our __dbx_link() internal breakpoint,
- then remove it. See comments in procfs_init_inferior()
- for more details. */
- if (dbx_link_bpt_addr != 0
- && dbx_link_bpt_addr
- == regcache_read_pc (get_current_regcache ()))
- remove_dbx_link_breakpoint ();
-
wstat = (SIGTRAP << 8) | 0177;
break;
case FLTSTACK:
@@ -4340,13 +4312,6 @@ procfs_mourn_inferior (struct target_ops *ops)
generic_mourn_inferior ();
- if (dbx_link_bpt != NULL)
- {
- deprecated_remove_raw_breakpoint (target_gdbarch (), dbx_link_bpt);
- dbx_link_bpt_addr = 0;
- dbx_link_bpt = NULL;
- }
-
inf_child_maybe_unpush_target (ops);
}
diff --git a/gdb/solib-irix.c b/gdb/solib-irix.c
index 12ed766..e6fada9 100644
--- a/gdb/solib-irix.c
+++ b/gdb/solib-irix.c
@@ -240,8 +240,6 @@ fetch_lm_info (CORE_ADDR addr)
/* The symbol which starts off the list of shared libraries. */
#define DEBUG_BASE "__rld_obj_head"
-static void *base_breakpoint;
-
static CORE_ADDR debug_base; /* Base of dynamic linker structures. */
/* Locate the base address of dynamic linker structs.
@@ -293,34 +291,6 @@ locate_base (void)
return (address);
}
-/* Remove the "mapping changed" breakpoint.
-
- Removes the breakpoint that gets hit when the dynamic linker
- completes a mapping change. */
-
-static int
-disable_break (void)
-{
- int status = 1;
-
- /* Note that breakpoint address and original contents are in our address
- space, so we just need to write the original contents back. */
-
- if (deprecated_remove_raw_breakpoint (target_gdbarch (), base_breakpoint) != 0)
- {
- status = 0;
- }
-
- base_breakpoint = NULL;
-
- /* Note that it is possible that we have stopped at a location that
- is different from the location where we inserted our breakpoint.
- On mips-irix, we can actually land in __dbx_init(), so we should
- not check the PC against our breakpoint address here. See procfs.c
- for more details. */
-
- return (status);
-}
/* Arrange for dynamic linker to hit breakpoint.
@@ -332,23 +302,35 @@ enable_break (void)
{
if (symfile_objfile != NULL && has_stack_frames ())
{
- struct frame_info *frame = get_current_frame ();
- struct address_space *aspace = get_frame_address_space (frame);
CORE_ADDR entry_point;
- if (!entry_point_address_query (&entry_point))
- return 0;
-
- base_breakpoint = deprecated_insert_raw_breakpoint (target_gdbarch (),
- aspace, entry_point);
-
- if (base_breakpoint != NULL)
- return 1;
+ if (entry_point_address_query (&entry_point))
+ {
+ create_solib_event_breakpoint (target_gdbarch (), entry_point);
+ return 1;
+ }
}
return 0;
}
+/* Implement the "handle_event" target_solib_ops method. */
+
+static void
+irix_solib_handle_event (void)
+{
+ /* We are now at the "mapping complete" breakpoint, we no longer
+ need it. Note that it is possible that we have stopped at a
+ location that is different from the location where we inserted
+ our breakpoint: On mips-irix, we can actually land in
+ __dbx_link(), so we should not check the PC against our
+ breakpoint address here. See procfs.c for more details. */
+ remove_solib_event_breakpoints ();
+
+ /* The caller calls solib_add, which will add any shared libraries
+ that were mapped in. */
+}
+
/* Implement the "create_inferior_hook" target_solib_ops method.
For SunOS executables, this first instruction is typically the
@@ -409,43 +391,10 @@ irix_solib_create_inferior_hook (int from_tty)
return;
}
- /* Now run the target. It will eventually hit the breakpoint, at
- which point all of the libraries will have been mapped in and we
- can go groveling around in the dynamic linker structures to find
- out what we need to know about them. */
-
- tp = inferior_thread ();
-
- clear_proceed_status (0);
-
- inf->control.stop_soon = STOP_QUIETLY;
- tp->suspend.stop_signal = GDB_SIGNAL_0;
-
- do
- {
- target_resume (pid_to_ptid (-1), 0, tp->suspend.stop_signal);
- wait_for_inferior ();
- }
- while (tp->suspend.stop_signal != GDB_SIGNAL_TRAP);
-
- /* We are now either at the "mapping complete" breakpoint (or somewhere
- else, a condition we aren't prepared to deal with anyway), so adjust
- the PC as necessary after a breakpoint, disable the breakpoint, and
- add any shared libraries that were mapped in. */
-
- if (!disable_break ())
- {
- warning (_("shared library handler failed to disable breakpoint"));
- }
-
- /* solib_add will call reinit_frame_cache.
- But we are stopped in the startup code and we might not have symbols
- for the startup code, so heuristic_proc_start could be called
- and will put out an annoying warning.
- Delaying the resetting of stop_soon until after symbol loading
- suppresses the warning. */
- solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
- inf->control.stop_soon = NO_STOP_QUIETLY;
+ /* The target will eventually hit the breakpoint, at which point all
+ of the libraries will have been mapped in and we can go groveling
+ around in the dynamic linker structures to find out what we need
+ to know about them. */
}
/* Implement the "current_sos" target_so_ops method. */
@@ -653,4 +602,5 @@ _initialize_irix_solib (void)
irix_so_ops.open_symbol_file_object = irix_open_symbol_file_object;
irix_so_ops.in_dynsym_resolve_code = irix_in_dynsym_resolve_code;
irix_so_ops.bfd_open = solib_bfd_open;
+ irix_so_ops.handle_event = irix_solib_handle_event;
}
--
1.9.3
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-10 15:50 ` eliminate deprecated_insert_raw_breakpoint. what's left Joel Brobecker
2014-09-10 16:00 ` Sergio Durigan Junior
@ 2014-09-10 16:36 ` Ulrich Weigand
2014-09-10 18:59 ` New deprecation procedure Pedro Alves
1 sibling, 1 reply; 31+ messages in thread
From: Ulrich Weigand @ 2014-09-10 16:36 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Pedro Alves, GDB Patches
Joel Brobecker wrote:
> So let's discuss the new obsoleting procedure, so we can document it:
>
> . I think that the first 4 steps (post email on gdb@, wait a week,
> then on gdb-announce, wait another week) are fine. Anyone thinks
> we should go straight to gdb-announce?
>
> My thinking is that people interested in maintaining a port
> with enough skills to do so are likely to already be on gdb@,
> so we can avoid sending an extra mail to gdb-announce. But
> the traffic on gdb-announce being very low, and the frequency
> at which we deprecate targets being fairly small as well,
> I wouldn't object to a simpler procedure where we email
> gdb-announce directly.
>
> . Remove steps 5 & 6 that mark the code as obsolete, only keeping
> the last test, which removes the code. I'd add a note to add
> a NEWS entry.
Sounds all good to me.
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* New deprecation procedure
2014-09-10 16:36 ` Ulrich Weigand
@ 2014-09-10 18:59 ` Pedro Alves
2014-09-11 19:03 ` Joel Brobecker
0 siblings, 1 reply; 31+ messages in thread
From: Pedro Alves @ 2014-09-10 18:59 UTC (permalink / raw)
To: Ulrich Weigand, Joel Brobecker; +Cc: GDB Patches
On 09/10/2014 05:35 PM, Ulrich Weigand wrote:
> Joel Brobecker wrote:
>
>> So let's discuss the new obsoleting procedure, so we can document it:
>>
>> . I think that the first 4 steps (post email on gdb@, wait a week,
>> then on gdb-announce, wait another week) are fine. Anyone thinks
>> we should go straight to gdb-announce?
>>
>> My thinking is that people interested in maintaining a port
>> with enough skills to do so are likely to already be on gdb@,
>> so we can avoid sending an extra mail to gdb-announce. But
>> the traffic on gdb-announce being very low, and the frequency
>> at which we deprecate targets being fairly small as well,
>> I wouldn't object to a simpler procedure where we email
>> gdb-announce directly.
>>
>> . Remove steps 5 & 6 that mark the code as obsolete, only keeping
>> the last test, which removes the code. I'd add a note to add
>> a NEWS entry.
>
> Sounds all good to me.
To me too.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [IRIX] eliminate deprecated_insert_raw_breakpoint uses
2014-09-10 16:12 ` [IRIX] eliminate deprecated_insert_raw_breakpoint uses Pedro Alves
@ 2014-09-10 22:44 ` Joel Brobecker
2014-09-10 23:02 ` Pedro Alves
0 siblings, 1 reply; 31+ messages in thread
From: Joel Brobecker @ 2014-09-10 22:44 UTC (permalink / raw)
To: Pedro Alves; +Cc: Maciej W. Rozycki, Ulrich Weigand, GDB Patches
> I think I understand this enough now. See patch below, which
> gets rid of that loop completely.
Thanks for walking me by memory lane :-)
> Untested, of course.
I found an IRIX machine that's still up and running, and I was able
to rebuild it. Unfortunately, two issues occured:
1. I had to make insert_breakpoint_locations non-static;
2. GDB now SIGSEGV-s when starting a program:
Program received signal SIGSEGV, Segmentation fault.
0x10163180 in bpstat_stop_status (aspace=0x108b97b0, bp_addr=268791248,
ptid=..., ws=0x7ffd7870)
at /nfs/nas/homes/brobecke/act/gdb-public/gdb/breakpoint.c:5536
5536 b->ops->check_status (bs);
The problem is that b->ops is NULL. I can continue investigating,
but I have this feeling that this is just a waste of time, since
I strongly suspect that IRIX support is going to be removed
a couple of weeks from now (I can start the procedure if you'd like).
--
Joel
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [IRIX] eliminate deprecated_insert_raw_breakpoint uses
2014-09-10 22:44 ` Joel Brobecker
@ 2014-09-10 23:02 ` Pedro Alves
2014-09-11 3:27 ` Joel Brobecker
0 siblings, 1 reply; 31+ messages in thread
From: Pedro Alves @ 2014-09-10 23:02 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Maciej W. Rozycki, Ulrich Weigand, GDB Patches
On 09/10/2014 11:43 PM, Joel Brobecker wrote:
>> I think I understand this enough now. See patch below, which
>> gets rid of that loop completely.
>
> Thanks for walking me by memory lane :-)
>
:-)
>> Untested, of course.
>
> I found an IRIX machine that's still up and running, and I was able
> to rebuild it. Unfortunately, two issues occured:
> 1. I had to make insert_breakpoint_locations non-static;
> 2. GDB now SIGSEGV-s when starting a program:
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x10163180 in bpstat_stop_status (aspace=0x108b97b0, bp_addr=268791248,
> ptid=..., ws=0x7ffd7870)
> at /nfs/nas/homes/brobecke/act/gdb-public/gdb/breakpoint.c:5536
> 5536 b->ops->check_status (bs);
>
> The problem is that b->ops is NULL.
Blah. Probably due to wiping the solib breakpoints in
the so_ops->handle_event() handler.
If you have the patience, could you try quickly commenting out
the remove_solib_event_breakpoints call in solib-irix.c and retrying?
> I can continue investigating,
> but I have this feeling that this is just a waste of time, since
Yeah...
> I strongly suspect that IRIX support is going to be removed
> a couple of weeks from now (I can start the procedure if you'd like).
That'd be super and much appreciated!
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [IRIX] eliminate deprecated_insert_raw_breakpoint uses
2014-09-10 23:02 ` Pedro Alves
@ 2014-09-11 3:27 ` Joel Brobecker
2014-09-12 19:34 ` Pedro Alves
0 siblings, 1 reply; 31+ messages in thread
From: Joel Brobecker @ 2014-09-11 3:27 UTC (permalink / raw)
To: Pedro Alves; +Cc: Maciej W. Rozycki, Ulrich Weigand, GDB Patches
> Blah. Probably due to wiping the solib breakpoints in
> the so_ops->handle_event() handler.
>
> If you have the patience, could you try quickly commenting out
> the remove_solib_event_breakpoints call in solib-irix.c and retrying?
Small glitch that got me kicked out of the machine, but I eventually
manage to run that experiment, and I was able to debug again.
"info shared" after starting a program gave the same list of
shared libraries.
> > I strongly suspect that IRIX support is going to be removed
> > a couple of weeks from now (I can start the procedure if you'd like).
>
> That'd be super and much appreciated!
OK - I will add that to my list and try to get to it tomorrow.
I don't think I'll be as specific as Dan was, if that's OK.
I think I'll just announce the impending removal of support
for mips-irix and alpha-tru64 in GDB. We can figure out what
to remove when we get there...
--
Joel
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: New deprecation procedure
2014-09-10 18:59 ` New deprecation procedure Pedro Alves
@ 2014-09-11 19:03 ` Joel Brobecker
2014-09-12 8:51 ` Ulrich Weigand
0 siblings, 1 reply; 31+ messages in thread
From: Joel Brobecker @ 2014-09-11 19:03 UTC (permalink / raw)
To: Pedro Alves; +Cc: Ulrich Weigand, GDB Patches
> >> So let's discuss the new obsoleting procedure, so we can document it:
> >>
> >> . I think that the first 4 steps (post email on gdb@, wait a week,
> >> then on gdb-announce, wait another week) are fine. Anyone thinks
> >> we should go straight to gdb-announce?
> >>
> >> My thinking is that people interested in maintaining a port
> >> with enough skills to do so are likely to already be on gdb@,
> >> so we can avoid sending an extra mail to gdb-announce. But
> >> the traffic on gdb-announce being very low, and the frequency
> >> at which we deprecate targets being fairly small as well,
> >> I wouldn't object to a simpler procedure where we email
> >> gdb-announce directly.
> >>
> >> . Remove steps 5 & 6 that mark the code as obsolete, only keeping
> >> the last test, which removes the code. I'd add a note to add
> >> a NEWS entry.
> >
> > Sounds all good to me.
>
> To me too.
OK, thanks all! Wiki page updated accordingly.
Sharing a thought that crossed my mind: I thought about increasing
the amount of time we wait between steps, from 1 week to say, 2 weeks,
giving anyone about a month to step up. I eventually dropped the idea
because someone stepping up late should easily be able to revert
the removal, particularly now that we've switched to git. In the
meantime, since we suspect no-one is usually going to step up,
waiting longer just defers the corresponding cleanups we want to do.
If you guys agree with that, I'll add something to the wiki page
to explain the thought process.
--
Joel
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: New deprecation procedure
2014-09-11 19:03 ` Joel Brobecker
@ 2014-09-12 8:51 ` Ulrich Weigand
0 siblings, 0 replies; 31+ messages in thread
From: Ulrich Weigand @ 2014-09-12 8:51 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Pedro Alves, GDB Patches
Joel Brobecker wrote:
> Sharing a thought that crossed my mind: I thought about increasing
> the amount of time we wait between steps, from 1 week to say, 2 weeks,
> giving anyone about a month to step up. I eventually dropped the idea
> because someone stepping up late should easily be able to revert
> the removal, particularly now that we've switched to git. In the
> meantime, since we suspect no-one is usually going to step up,
> waiting longer just defers the corresponding cleanups we want to do.
> If you guys agree with that, I'll add something to the wiki page
> to explain the thought process.
Makes sense to me.
Thanks,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [IRIX] eliminate deprecated_insert_raw_breakpoint uses
2014-09-11 3:27 ` Joel Brobecker
@ 2014-09-12 19:34 ` Pedro Alves
2014-09-12 20:23 ` Joel Brobecker
0 siblings, 1 reply; 31+ messages in thread
From: Pedro Alves @ 2014-09-12 19:34 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Maciej W. Rozycki, Ulrich Weigand, GDB Patches
On 09/11/2014 04:27 AM, Joel Brobecker wrote:
>> Blah. Probably due to wiping the solib breakpoints in
>> the so_ops->handle_event() handler.
>>
>> If you have the patience, could you try quickly commenting out
>> the remove_solib_event_breakpoints call in solib-irix.c and retrying?
>
> Small glitch that got me kicked out of the machine, but I eventually
> manage to run that experiment, and I was able to debug again.
> "info shared" after starting a program gave the same list of
> shared libraries.
Thanks Joel. I've addressed that issue by marking the breakpoints
as disp_del_at_next_stop instead of deleting them immediately.
Locally, I added a call to remove_solib_event_breakpoints_at_next_stop
to solib-svr4.c:svr4_handle_solib_event, to check that the breakpoint
does indeed end up removed, and that we don't crash. Adding a
call to remove_solib_event_breakpoints instead would crash in the
same way you saw on IRIX with the previous version of this patch.
I avoided exposing insert_breakpoint_locations out of breakpoint.c by
adding a new create_and_insert_solib_event_breakpoint function
that is like create_solib_event_breakpoint but tries to insert the
breakpoint immediately.
I figure that if someone wants to keep IRIX alive (either now, by
bringing it back from git), this will be a better base to start
from.
So in interest of not having to wait for IRIX to be dropped,
I've gone ahead and pushed the patch below.
Thanks.
---------
[IRIX] eliminate deprecated_insert_raw_breakpoint uses
The IRIX support wants to set a breakpoint to be hit when the startup
phase is complete, which is where shared libraries have been mapped
in. AFAIU, for most IRIX ports, that location is the entry point.
For MIPS IRIX however, GDB needs to set a breakpoint earlier, in
__dbx_link, as explained by:
#ifdef SYS_syssgi
/* On mips-irix, we need to stop the inferior early enough during
the startup phase in order to be able to load the shared library
symbols and insert the breakpoints that are located in these shared
libraries. Stopping at the program entry point is not good enough
because the -init code is executed before the execution reaches
that point.
So what we need to do is to insert a breakpoint in the runtime
loader (rld), more precisely in __dbx_link(). This procedure is
called by rld once all shared libraries have been mapped, but before
the -init code is executed. Unfortuantely, this is not straightforward,
as rld is not part of the executable we are running, and thus we need
the inferior to run until rld itself has been mapped in memory.
For this, we trace all syssgi() syscall exit events. Each time
we detect such an event, we iterate over each text memory maps,
get its associated fd, and scan the symbol table for __dbx_link().
When found, we know that rld has been mapped, and that we can insert
the breakpoint at the symbol address. Once the dbx_link() breakpoint
has been inserted, the syssgi() notifications are no longer necessary,
so they should be canceled. */
proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT, FLAG_SET, 0);
#endif
The loop in irix_solib_create_inferior_hook then runs until whichever
breakpoint is hit first, the one set by solib-irix.c or the one set by
procfs.c.
Note the comment in disable_break talks about __dbx_init, but I think
that's a typo for __dbx_link:
- /* Note that it is possible that we have stopped at a location that
- is different from the location where we inserted our breakpoint.
- On mips-irix, we can actually land in __dbx_init(), so we should
- not check the PC against our breakpoint address here. See procfs.c
- for more details. */
This looks very much like referring to the loop in
irix_solib_create_inferior_hook stopping at __dbx_link instead of at
the entry point.
What this patch does is convert these deprecated raw breakpoints to
standard solib_event breakpoints. When the first solib-event
breakpoint is hit, we delete all solib-event breakpoints. We do that
in the so_ops->handle_event hook.
This allows getting rid of the loop in irix_solib_create_inferior_hook
completely, which should allow properly handling signals and other
events in the early startup phase, like in SVR4.
Built on x86_64 Fedora 20 with --enable-targets=all (builds
solib-irix.c).
Joel tested that with an earlier version of this patch "info shared"
after starting a program gave the same list of shared libraries as
before.
gdb/ChangeLog:
2014-09-12 Pedro Alves <palves@redhat.com>
* breakpoint.c (remove_solib_event_breakpoints_at_next_stop)
(create_and_insert_solib_event_breakpoint): New functions.
* breakpoint.h (create_and_insert_solib_event_breakpoint)
(remove_solib_event_breakpoints_at_next_stop): New declarations.
* procfs.c (dbx_link_bpt_addr, dbx_link_bpt): Delete globals.
(remove_dbx_link_breakpoint): Delete function.
(insert_dbx_link_bpt_in_file): Use
create_and_insert_solib_event_breakpoint instead of
deprecated_insert_raw_breakpoint.
(procfs_wait): Don't check whether we hit __dbx_link here.
(procfs_mourn_inferior): Don't delete the __dbx_link breakpoint
here.
* solib-irix.c (base_breakpoint): Delete global.
(disable_break): Delete function.
(enable_break): Use create_solib_event_breakpoint
instead of deprecated_insert_raw_breakpoint.
(irix_solib_handle_event): New function.
(irix_solib_create_inferior_hook): Don't run the target or disable
the mapping-complete breakpoint here.
(_initialize_irix_solib): Install irix_solib_handle_event as
so_ops->handle_event hook.
---
gdb/ChangeLog | 24 +++++++++++++
gdb/breakpoint.c | 31 ++++++++++++++++
gdb/breakpoint.h | 11 ++++++
gdb/procfs.c | 47 +++---------------------
gdb/solib-irix.c | 108 ++++++++++++++++---------------------------------------
5 files changed, 102 insertions(+), 119 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0ec71d4..0b9e140 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,27 @@
+2014-09-12 Pedro Alves <palves@redhat.com>
+
+ * breakpoint.c (remove_solib_event_breakpoints_at_next_stop)
+ (create_and_insert_solib_event_breakpoint): New functions.
+ * breakpoint.h (create_and_insert_solib_event_breakpoint)
+ (remove_solib_event_breakpoints_at_next_stop): New declarations.
+ * procfs.c (dbx_link_bpt_addr, dbx_link_bpt): Delete globals.
+ (remove_dbx_link_breakpoint): Delete function.
+ (insert_dbx_link_bpt_in_file): Use
+ create_and_insert_solib_event_breakpoint instead of
+ deprecated_insert_raw_breakpoint.
+ (procfs_wait): Don't check whether we hit __dbx_link here.
+ (procfs_mourn_inferior): Don't delete the __dbx_link breakpoint
+ here.
+ * solib-irix.c (base_breakpoint): Delete global.
+ (disable_break): Delete function.
+ (enable_break): Use create_solib_event_breakpoint
+ instead of deprecated_insert_raw_breakpoint.
+ (irix_solib_handle_event): New function.
+ (irix_solib_create_inferior_hook): Don't run the target or disable
+ the mapping-complete breakpoint here.
+ (_initialize_irix_solib): Install irix_solib_handle_event as
+ so_ops->handle_event hook.
+
2014-09-12 Edjunior Barbosa Machado <emachado@linux.vnet.ibm.com>
Ulrich Weigand <uweigand@de.ibm.com>
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 683ed2b..f990d97 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -7620,6 +7620,19 @@ remove_solib_event_breakpoints (void)
delete_breakpoint (b);
}
+/* See breakpoint.h. */
+
+void
+remove_solib_event_breakpoints_at_next_stop (void)
+{
+ struct breakpoint *b, *b_tmp;
+
+ ALL_BREAKPOINTS_SAFE (b, b_tmp)
+ if (b->type == bp_shlib_event
+ && b->loc->pspace == current_program_space)
+ b->disposition = disp_del_at_next_stop;
+}
+
struct breakpoint *
create_solib_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
{
@@ -7631,6 +7644,24 @@ create_solib_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
return b;
}
+/* See breakpoint.h. */
+
+struct breakpoint *
+create_and_insert_solib_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
+{
+ struct breakpoint *b;
+
+ b = create_solib_event_breakpoint (gdbarch, address);
+ if (!breakpoints_always_inserted_mode ())
+ insert_breakpoint_locations ();
+ if (!b->loc->inserted)
+ {
+ delete_breakpoint (b);
+ return NULL;
+ }
+ return b;
+}
+
/* Disable any breakpoints that are on code in shared libraries. Only
apply to enabled breakpoints, disabled ones can just stay disabled. */
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index f6d06ce..8abb5ea 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1419,6 +1419,13 @@ extern struct breakpoint *create_jit_event_breakpoint (struct gdbarch *,
extern struct breakpoint *create_solib_event_breakpoint (struct gdbarch *,
CORE_ADDR);
+/* Create an solib event breakpoint at ADDRESS in the current program
+ space, and immediately try to insert it. Returns a pointer to the
+ breakpoint on success. Deletes the new breakpoint and returns NULL
+ if inserting the breakpoint fails. */
+extern struct breakpoint *create_and_insert_solib_event_breakpoint
+ (struct gdbarch *gdbarch, CORE_ADDR address);
+
extern struct breakpoint *create_thread_event_breakpoint (struct gdbarch *,
CORE_ADDR);
@@ -1426,6 +1433,10 @@ extern void remove_jit_event_breakpoints (void);
extern void remove_solib_event_breakpoints (void);
+/* Mark solib event breakpoints of the current program space with
+ delete at next stop disposition. */
+extern void remove_solib_event_breakpoints_at_next_stop (void);
+
extern void remove_thread_event_breakpoints (void);
extern void disable_breakpoints_in_shlibs (void);
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 3465bc5..699fcd9 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -2902,13 +2902,6 @@ static void do_detach (int signo);
static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum,
int entry_or_exit, int mode, int from_tty);
-/* On mips-irix, we need to insert a breakpoint at __dbx_link during
- the startup phase. The following two variables are used to record
- the address of the breakpoint, and the code that was replaced by
- a breakpoint. */
-static int dbx_link_bpt_addr = 0;
-static void *dbx_link_bpt;
-
/* Sets up the inferior to be debugged. Registers to trace signals,
hardware faults, and syscalls. Note: does not set RLC flag: caller
may want to customize that. Returns zero for success (note!
@@ -3380,23 +3373,6 @@ syscall_is_lwp_create (procinfo *pi, int scall)
return 0;
}
-/* Remove the breakpoint that we inserted in __dbx_link().
- Does nothing if the breakpoint hasn't been inserted or has already
- been removed. */
-
-static void
-remove_dbx_link_breakpoint (void)
-{
- if (dbx_link_bpt_addr == 0)
- return;
-
- if (deprecated_remove_raw_breakpoint (target_gdbarch (), dbx_link_bpt) != 0)
- warning (_("Unable to remove __dbx_link breakpoint."));
-
- dbx_link_bpt_addr = 0;
- dbx_link_bpt = NULL;
-}
-
#ifdef SYS_syssgi
/* Return the address of the __dbx_link() function in the file
refernced by ABFD by scanning its symbol table. Return 0 if
@@ -3461,10 +3437,12 @@ insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
sym_addr = dbx_link_addr (abfd);
if (sym_addr != 0)
{
+ struct breakpoint *dbx_link_bpt;
+
/* Insert the breakpoint. */
- dbx_link_bpt_addr = sym_addr;
- dbx_link_bpt = deprecated_insert_raw_breakpoint (target_gdbarch (), NULL,
- sym_addr);
+ dbx_link_bpt
+ = create_and_insert_solib_event_breakpoint (target_gdbarch (),
+ sym_addr);
if (dbx_link_bpt == NULL)
{
warning (_("Failed to insert dbx_link breakpoint."));
@@ -3894,14 +3872,6 @@ wait_again:
#if (FLTTRACE != FLTBPT) /* Avoid "duplicate case" error. */
case FLTTRACE:
#endif
- /* If we hit our __dbx_link() internal breakpoint,
- then remove it. See comments in procfs_init_inferior()
- for more details. */
- if (dbx_link_bpt_addr != 0
- && dbx_link_bpt_addr
- == regcache_read_pc (get_current_regcache ()))
- remove_dbx_link_breakpoint ();
-
wstat = (SIGTRAP << 8) | 0177;
break;
case FLTSTACK:
@@ -4340,13 +4310,6 @@ procfs_mourn_inferior (struct target_ops *ops)
generic_mourn_inferior ();
- if (dbx_link_bpt != NULL)
- {
- deprecated_remove_raw_breakpoint (target_gdbarch (), dbx_link_bpt);
- dbx_link_bpt_addr = 0;
- dbx_link_bpt = NULL;
- }
-
inf_child_maybe_unpush_target (ops);
}
diff --git a/gdb/solib-irix.c b/gdb/solib-irix.c
index 12ed766..00236bf 100644
--- a/gdb/solib-irix.c
+++ b/gdb/solib-irix.c
@@ -240,8 +240,6 @@ fetch_lm_info (CORE_ADDR addr)
/* The symbol which starts off the list of shared libraries. */
#define DEBUG_BASE "__rld_obj_head"
-static void *base_breakpoint;
-
static CORE_ADDR debug_base; /* Base of dynamic linker structures. */
/* Locate the base address of dynamic linker structs.
@@ -293,34 +291,6 @@ locate_base (void)
return (address);
}
-/* Remove the "mapping changed" breakpoint.
-
- Removes the breakpoint that gets hit when the dynamic linker
- completes a mapping change. */
-
-static int
-disable_break (void)
-{
- int status = 1;
-
- /* Note that breakpoint address and original contents are in our address
- space, so we just need to write the original contents back. */
-
- if (deprecated_remove_raw_breakpoint (target_gdbarch (), base_breakpoint) != 0)
- {
- status = 0;
- }
-
- base_breakpoint = NULL;
-
- /* Note that it is possible that we have stopped at a location that
- is different from the location where we inserted our breakpoint.
- On mips-irix, we can actually land in __dbx_init(), so we should
- not check the PC against our breakpoint address here. See procfs.c
- for more details. */
-
- return (status);
-}
/* Arrange for dynamic linker to hit breakpoint.
@@ -332,23 +302,39 @@ enable_break (void)
{
if (symfile_objfile != NULL && has_stack_frames ())
{
- struct frame_info *frame = get_current_frame ();
- struct address_space *aspace = get_frame_address_space (frame);
CORE_ADDR entry_point;
- if (!entry_point_address_query (&entry_point))
- return 0;
-
- base_breakpoint = deprecated_insert_raw_breakpoint (target_gdbarch (),
- aspace, entry_point);
-
- if (base_breakpoint != NULL)
- return 1;
+ if (entry_point_address_query (&entry_point))
+ {
+ create_solib_event_breakpoint (target_gdbarch (), entry_point);
+ return 1;
+ }
}
return 0;
}
+/* Implement the "handle_event" target_solib_ops method. */
+
+static void
+irix_solib_handle_event (void)
+{
+ /* We are now at the "mapping complete" breakpoint, we no longer
+ need it. Note that it is possible that we have stopped at a
+ location that is different from the location where we inserted
+ our breakpoint: On mips-irix, we can actually land in
+ __dbx_link(), so we should not check the PC against our
+ breakpoint address here. See procfs.c for more details. Note
+ we're being called by the bpstat handling code, and so can't
+ delete the breakpoint immediately. Mark it for later deletion,
+ which has the same effect (it'll be removed before we next resume
+ or if we're stopping). */
+ remove_solib_event_breakpoints_at_next_stop ();
+
+ /* The caller calls solib_add, which will add any shared libraries
+ that were mapped in. */
+}
+
/* Implement the "create_inferior_hook" target_solib_ops method.
For SunOS executables, this first instruction is typically the
@@ -409,43 +395,10 @@ irix_solib_create_inferior_hook (int from_tty)
return;
}
- /* Now run the target. It will eventually hit the breakpoint, at
- which point all of the libraries will have been mapped in and we
- can go groveling around in the dynamic linker structures to find
- out what we need to know about them. */
-
- tp = inferior_thread ();
-
- clear_proceed_status (0);
-
- inf->control.stop_soon = STOP_QUIETLY;
- tp->suspend.stop_signal = GDB_SIGNAL_0;
-
- do
- {
- target_resume (pid_to_ptid (-1), 0, tp->suspend.stop_signal);
- wait_for_inferior ();
- }
- while (tp->suspend.stop_signal != GDB_SIGNAL_TRAP);
-
- /* We are now either at the "mapping complete" breakpoint (or somewhere
- else, a condition we aren't prepared to deal with anyway), so adjust
- the PC as necessary after a breakpoint, disable the breakpoint, and
- add any shared libraries that were mapped in. */
-
- if (!disable_break ())
- {
- warning (_("shared library handler failed to disable breakpoint"));
- }
-
- /* solib_add will call reinit_frame_cache.
- But we are stopped in the startup code and we might not have symbols
- for the startup code, so heuristic_proc_start could be called
- and will put out an annoying warning.
- Delaying the resetting of stop_soon until after symbol loading
- suppresses the warning. */
- solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
- inf->control.stop_soon = NO_STOP_QUIETLY;
+ /* The target will eventually hit the breakpoint, at which point all
+ of the libraries will have been mapped in and we can go groveling
+ around in the dynamic linker structures to find out what we need
+ to know about them. */
}
/* Implement the "current_sos" target_so_ops method. */
@@ -653,4 +606,5 @@ _initialize_irix_solib (void)
irix_so_ops.open_symbol_file_object = irix_open_symbol_file_object;
irix_so_ops.in_dynsym_resolve_code = irix_in_dynsym_resolve_code;
irix_so_ops.bfd_open = solib_bfd_open;
+ irix_so_ops.handle_event = irix_solib_handle_event;
}
--
1.9.3
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [IRIX] eliminate deprecated_insert_raw_breakpoint uses
2014-09-12 19:34 ` Pedro Alves
@ 2014-09-12 20:23 ` Joel Brobecker
0 siblings, 0 replies; 31+ messages in thread
From: Joel Brobecker @ 2014-09-12 20:23 UTC (permalink / raw)
To: Pedro Alves; +Cc: Maciej W. Rozycki, Ulrich Weigand, GDB Patches
> Thanks Joel. I've addressed that issue by marking the breakpoints
> as disp_del_at_next_stop instead of deleting them immediately.
>
> Locally, I added a call to remove_solib_event_breakpoints_at_next_stop
> to solib-svr4.c:svr4_handle_solib_event, to check that the breakpoint
> does indeed end up removed, and that we don't crash. Adding a
> call to remove_solib_event_breakpoints instead would crash in the
> same way you saw on IRIX with the previous version of this patch.
>
> I avoided exposing insert_breakpoint_locations out of breakpoint.c by
> adding a new create_and_insert_solib_event_breakpoint function
> that is like create_solib_event_breakpoint but tries to insert the
> breakpoint immediately.
>
> I figure that if someone wants to keep IRIX alive (either now, by
> bringing it back from git), this will be a better base to start
> from.
>
> So in interest of not having to wait for IRIX to be dropped,
> I've gone ahead and pushed the patch below.
I've just rebuilt GDB again, and I can confirm that the problem
is fixed. After starting a program, I can still see the same
list of shared libraries as before your change.
Cheers!
--
Joel
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: eliminate deprecated_insert_raw_breakpoint. what's left.
2014-09-10 14:45 ` Ulrich Weigand
2014-09-10 15:21 ` Pedro Alves
@ 2014-10-07 0:25 ` Stan Shebs
1 sibling, 0 replies; 31+ messages in thread
From: Stan Shebs @ 2014-10-07 0:25 UTC (permalink / raw)
To: gdb-patches
On 9/10/14, 7:45 AM, Ulrich Weigand wrote:
> The process documented in the Wiki is a bit weird (adding OBSOLETE
> to *every line* of those files ???) and it seems we didn't follow
> it in the last major round of obsoleting code either:
> https://sourceware.org/ml/gdb-announce/2007/msg00000.html
Well, my thought was to forestall grep'ers from being misled by the
presence of code that was slated to go away... it perhaps made more
sense in the pre-public-repo age, when many developers hacked on
copies of releases or snapshots, rather than a checkout.
Stan
stan@codesourcery.com
^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2014-10-07 0:25 UTC | newest]
Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-08 17:46 eliminate deprecated_insert_raw_breakpoint. what's left Pedro Alves
2014-09-08 19:24 ` Joel Brobecker
2014-09-08 21:34 ` Joel Brobecker
2014-09-08 22:50 ` Pedro Alves
2014-09-09 0:25 ` Peter Schauer
2014-09-09 0:16 ` Peter Schauer
2014-09-09 11:39 ` Ulrich Weigand
2014-09-09 12:38 ` Peter Schauer
2014-09-09 21:25 ` Ulrich Weigand
2014-09-10 12:21 ` Joel Brobecker
2014-09-10 13:15 ` Ulrich Weigand
2014-09-10 15:22 ` Pedro Alves
2014-09-09 21:48 ` Ulrich Weigand
2014-09-10 12:29 ` Joel Brobecker
2014-09-10 14:45 ` Ulrich Weigand
2014-09-10 15:21 ` Pedro Alves
2014-09-10 15:50 ` Maciej W. Rozycki
2014-09-10 16:12 ` [IRIX] eliminate deprecated_insert_raw_breakpoint uses Pedro Alves
2014-09-10 22:44 ` Joel Brobecker
2014-09-10 23:02 ` Pedro Alves
2014-09-11 3:27 ` Joel Brobecker
2014-09-12 19:34 ` Pedro Alves
2014-09-12 20:23 ` Joel Brobecker
2014-09-10 15:50 ` eliminate deprecated_insert_raw_breakpoint. what's left Joel Brobecker
2014-09-10 16:00 ` Sergio Durigan Junior
2014-09-10 16:36 ` Ulrich Weigand
2014-09-10 18:59 ` New deprecation procedure Pedro Alves
2014-09-11 19:03 ` Joel Brobecker
2014-09-12 8:51 ` Ulrich Weigand
2014-10-07 0:25 ` eliminate deprecated_insert_raw_breakpoint. what's left Stan Shebs
2014-09-09 17:33 ` Pedro Alves
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox