* Instrcutions that must not be stepped.
@ 2006-06-08 2:27 PAUL GILLIAM
2006-06-08 3:50 ` Daniel Jacobowitz
0 siblings, 1 reply; 12+ messages in thread
From: PAUL GILLIAM @ 2006-06-08 2:27 UTC (permalink / raw)
To: gdb
On the PowerPC, there is a provision for an atomic read-modify-right
sequence that is implemented using the "lwarx" and "stwcx" instructions.
These do not guarantee an atomic operation, but will detect its failure.
If threads are being used, then glibc functions use this sequence to
implement a lock by looping back to the start of the sequence if it was
not atomic.
When gdb is stepping through a library function, which it does under
some circumstances if there is no source for the function, it gets stuck
in this loop because the sequence will never be recognized as atomic.
The only solution is to check each instruction about to be stepped to
see if it's an "lwarx". If not, step as usual. If it is, then analyze
the instructions that follow; set a temporary breakpoint after the loop,
do a 'continue' and then continue stepping normally after it's been hit.
Does there currently exist an arch. independent way to detect
instruction sequences that must not be single stepped? Failing that, is
there some hook I can use to implement this for just the PowerPC?
Should there be a new gdbarch member like 'single_step_nonstepable' that
will detect and handle non-stepable sequences?. Or maybe a gdbarch
member like 'find_end_of_nonstepable_sequence' that returns 0 if the
instruction about be be stepped is not the the start of a non-stepable
sequence and the address of the end of the sequence (where to set a
temp. break) if it is.
Thanks for your help,
-=# Paul #=-
PS: The following hack prevents single-stepping a "lwarx" instruction.
The user can then manually find the end of the sequence, put a temp.
break there, continue, and then go back to stepping as normal. Before
you get upset, remember I did say it was a hack and it actually allowed
a teammate to make progress on an unrelated glibc bug.
--- inf-ptrace.c 2006-01-24 14:34:34.000000000 -0800
+++ new.inf-ptrace.c 2006-06-07 13:59:02.000000000 -0700
@@ -326,6 +326,14 @@
if (step)
{
+ /* Horrible hack: See if we are about to step an "lwarx"
+ instruction and abort with an error message if so. */
+ long pc = (long) read_register (PC_REGNUM);
+ long inst = ptrace (PT_READ_I, pid, pc, 0);
+
+ if ((inst & 0xfc0007fe) == 0x7C000028)
+ perror_with_name (("(barf) lwarx (barf)"));
+
/* If this system does not support PT_STEP, a higher level
function will have called single_step() to transmute the step
request into a continue request (by setting breakpoints on
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Instrcutions that must not be stepped.
2006-06-08 2:27 Instrcutions that must not be stepped PAUL GILLIAM
@ 2006-06-08 3:50 ` Daniel Jacobowitz
2006-06-16 4:36 ` PAUL GILLIAM
0 siblings, 1 reply; 12+ messages in thread
From: Daniel Jacobowitz @ 2006-06-08 3:50 UTC (permalink / raw)
To: PAUL GILLIAM; +Cc: gdb
On Wed, Jun 07, 2006 at 05:19:59PM -0700, PAUL GILLIAM wrote:
> Does there currently exist an arch. independent way to detect
> instruction sequences that must not be single stepped? Failing that, is
> there some hook I can use to implement this for just the PowerPC?
Nope. You'd have to add one. And, you'd have to be able to tell
whether you were in the middle of a GDB-automated step or a user stepi;
stepping multiple instructions when the user asked for one is probably
just confusing.
Reading the instruction before stepping is going to slow down single
stepping. Is there some other way we can handle this?
The same problem applies to many other architectures, e.g. MIPS and ARM.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Instrcutions that must not be stepped.
2006-06-08 3:50 ` Daniel Jacobowitz
@ 2006-06-16 4:36 ` PAUL GILLIAM
2006-06-17 12:26 ` PAUL GILLIAM
0 siblings, 1 reply; 12+ messages in thread
From: PAUL GILLIAM @ 2006-06-16 4:36 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb
On Wed, 2006-06-07 at 22:26 -0400, Daniel Jacobowitz wrote:
> On Wed, Jun 07, 2006 at 05:19:59PM -0700, PAUL GILLIAM wrote:
> > Does there currently exist an arch. independent way to detect
> > instruction sequences that must not be single stepped? Failing that, is
> > there some hook I can use to implement this for just the PowerPC?
>
> Nope. You'd have to add one.
The closer I look at this, the more it looks like a special case of
software single step. The difference is that it may not have to be for
*every* single step: just those that are trying to step "atomic"
sequences.
I propose changing the meaning of SOFTWARE_SINGLE_STEP_P () from "This
arch has no hardware to do single step and must use software." to "There
may be circumstances where this arch will have to do single stepping
with out hardware support." And make SOFTWARE_SINGLE_STEP return 1 if a
software single step was needed and 0 if it was not. This would require
a minor change for those arches currently using SOFTWARE_SINGLE_STEP and
a little tweeking in "infrun.c".
The only difference between doing a software single step as it is now
and doing an "atomic single step" is how the decision of where to place
temporary breakpoints is made.
> Reading the instruction before stepping is going to slow down single
> stepping. Is there some other way we can handle this?
I can't think of any way. I did some timing runs, with and without
reading the next instruction from the target and in my native ppc64
case, it wasn't too bad. Any way, it would only be a hit on arches that
needed it. And if it was real bad, we could let the user decide.
-=# Paul #=-
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Instrcutions that must not be stepped.
2006-06-16 4:36 ` PAUL GILLIAM
@ 2006-06-17 12:26 ` PAUL GILLIAM
2006-06-18 4:57 ` Mark Kettenis
0 siblings, 1 reply; 12+ messages in thread
From: PAUL GILLIAM @ 2006-06-17 12:26 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb
On Thu, 2006-06-15 at 16:54 -0700, PAUL GILLIAM wrote:
> I propose changing the meaning of SOFTWARE_SINGLE_STEP_P () from "This
> arch has no hardware to do single step and must use software." to "There
> may be circumstances where this arch will have to do single stepping
> with out hardware support." And make SOFTWARE_SINGLE_STEP return 1 if a
> software single step was needed and 0 if it was not. This would require
> a minor change for those arches currently using SOFTWARE_SINGLE_STEP and
> a little tweeking in "infrun.c".
>
> The only difference between doing a software single step as it is now
> and doing an "atomic single step" is how the decision of where to place
> temporary breakpoints is made.
I have attached two diff's: "change_software_single_step.diff" makes the
change I proposed above. I changed the name "software_single_step" to
"possibly_single_step_with_software".
"ppc-atomic-series.diff" should be applied after the previous patch. It
adds the code for PowerPC on native linux that uses the new scheme and
checks for an atomic sequence. If it find one, it prints a message to
that effect does the same type of thing as
"rs6000_possibly_single_step_with_software" after finding where to set
the breakpoints.
I have a clean compile with this, but have not done any testing yet. I
will send these patches to gdb-patches after a bit of testing (unless I
get a huge out-cry here 8-)
-=# Paul #=-
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Instrcutions that must not be stepped.
2006-06-17 12:26 ` PAUL GILLIAM
@ 2006-06-18 4:57 ` Mark Kettenis
2006-06-20 20:13 ` PAUL GILLIAM
0 siblings, 1 reply; 12+ messages in thread
From: Mark Kettenis @ 2006-06-18 4:57 UTC (permalink / raw)
To: pgilliam; +Cc: drow, gdb
> From: PAUL GILLIAM <pgilliam@us.ibm.com>
> Date: Fri, 16 Jun 2006 15:26:01 -0700
>
> On Thu, 2006-06-15 at 16:54 -0700, PAUL GILLIAM wrote:
> > I propose changing the meaning of SOFTWARE_SINGLE_STEP_P () from "This
> > arch has no hardware to do single step and must use software." to "There
> > may be circumstances where this arch will have to do single stepping
> > with out hardware support." And make SOFTWARE_SINGLE_STEP return 1 if a
> > software single step was needed and 0 if it was not. This would require
> > a minor change for those arches currently using SOFTWARE_SINGLE_STEP and
> > a little tweeking in "infrun.c".
> >
> > The only difference between doing a software single step as it is now
> > and doing an "atomic single step" is how the decision of where to place
> > temporary breakpoints is made.
>
> I have attached two diff's: "change_software_single_step.diff" makes the
> change I proposed above.
No you didn't :(.
> I changed the name "software_single_step" to
> "possibly_single_step_with_software".
Hmm, I don't really see the benefit of renaming the function. I mean,
that name is kinda long, and it means we get the evn longer:
set_gdbarch_possibly_single_step_with_software().
By the way, if stepping these atomic sequences proves to be a
performance problem, you might want to consider implementing stepping
them in the (Linux) kernel.
Mark
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Instrcutions that must not be stepped.
2006-06-18 4:57 ` Mark Kettenis
@ 2006-06-20 20:13 ` PAUL GILLIAM
2006-06-20 22:53 ` Paul Koning
0 siblings, 1 reply; 12+ messages in thread
From: PAUL GILLIAM @ 2006-06-20 20:13 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb, drow
[-- Attachment #1: Type: text/plain, Size: 1137 bytes --]
On Sun, 2006-06-18 at 05:41 +0200, Mark Kettenis wrote:
> > From: PAUL GILLIAM <pgilliam@us.ibm.com>
> > Date: Fri, 16 Jun 2006 15:26:01 -0700
. . .
> > I have attached two diff's: "change_software_single_step.diff" makes the
> > change I proposed above.
>
> No you didn't :(.
>
This time for sure.
> > I changed the name "software_single_step" to
> > "possibly_single_step_with_software".
>
> Hmm, I don't really see the benefit of renaming the function. I mean,
> that name is kinda long, and it means we get the evn longer:
>
> set_gdbarch_possibly_single_step_with_software().
Yea, I agree. The only reason I changed it to to emphasize that
function of the routine has changed a little bit. When I submit it to
gdb-patches, I think I'll leave the name alone.
> By the way, if stepping these atomic sequences proves to be a
> performance problem, you might want to consider implementing stepping
> them in the (Linux) kernel.
This would be cool. It would be nice to be able to tell if the kernel
has support for this and let it handle atomic sequences if it does. Let
GDB handle it if the kernel doesn't.
>
> Mark
[-- Attachment #2: change_software_single_step.diff --]
[-- Type: text/x-patch, Size: 33790 bytes --]
Index: alpha-osf1-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/alpha-osf1-tdep.c,v
retrieving revision 1.20
diff -a -u -r1.20 alpha-osf1-tdep.c
--- alpha-osf1-tdep.c 17 Dec 2005 22:33:59 -0000 1.20
+++ alpha-osf1-tdep.c 19 Jun 2006 21:39:59 -0000
@@ -54,7 +54,8 @@
/* The next/step support via procfs on OSF1 is broken when running
on multi-processor machines. We need to use software single stepping
instead. */
- set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
+ set_gdbarch_possibly_single_step_with_software (gdbarch,
+ alpha_possibly_single_step_with_software);
tdep->sigcontext_addr = alpha_osf1_sigcontext_addr;
tdep->pc_in_sigtramp = alpha_osf1_pc_in_sigtramp;
Index: alpha-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/alpha-tdep.c,v
retrieving revision 1.154
diff -a -u -r1.154 alpha-tdep.c
--- alpha-tdep.c 18 Apr 2006 19:20:05 -0000 1.154
+++ alpha-tdep.c 19 Jun 2006 21:39:59 -0000
@@ -1359,8 +1359,8 @@
return ((reg & sign_mask) != 0);
}
-/* alpha_software_single_step() is called just before we want to resume
- the inferior, if we want to single-step it but there is no hardware
+/* alpha_possibly_single_step_with_software() is called just before we want to
+ resume the inferior, if we want to single-step it but there is no hardware
or kernel single-step support (NetBSD on Alpha, for example). We find
the target of the coming instruction and breakpoint it.
@@ -1489,8 +1489,9 @@
return (pc + 4);
}
-void
-alpha_software_single_step (enum target_signal sig, int insert_breakpoints_p)
+int
+alpha_possibly_single_step_with_software (enum target_signal sig,
+ int insert_breakpoints_p)
{
static CORE_ADDR next_pc;
CORE_ADDR pc;
@@ -1507,6 +1508,7 @@
remove_single_step_breakpoints ();
write_pc (next_pc);
}
+ return 1;
}
\f
Index: alpha-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/alpha-tdep.h,v
retrieving revision 1.23
diff -a -u -r1.23 alpha-tdep.h
--- alpha-tdep.h 17 Dec 2005 22:33:59 -0000 1.23
+++ alpha-tdep.h 19 Jun 2006 21:39:59 -0000
@@ -100,7 +100,7 @@
};
extern unsigned int alpha_read_insn (CORE_ADDR pc);
-extern void alpha_software_single_step (enum target_signal, int);
+extern int alpha_possibly_single_step_with_software (enum target_signal, int);
extern CORE_ADDR alpha_after_prologue (CORE_ADDR pc);
extern void alpha_mdebug_init_abi (struct gdbarch_info, struct gdbarch *);
Index: alphanbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/alphanbsd-tdep.c,v
retrieving revision 1.28
diff -a -u -r1.28 alphanbsd-tdep.c
--- alphanbsd-tdep.c 17 Dec 2005 22:33:59 -0000 1.28
+++ alphanbsd-tdep.c 19 Jun 2006 21:39:59 -0000
@@ -208,7 +208,8 @@
/* NetBSD/alpha does not provide single step support via ptrace(2); we
must use software single-stepping. */
- set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
+ set_gdbarch_possibly_single_step_with_software (gdbarch,
+ alpha_possibly_single_step_with_software);
set_solib_svr4_fetch_link_map_offsets (gdbarch,
nbsd_lp64_solib_svr4_fetch_link_map_offsets);
Index: arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.209
diff -a -u -r1.209 arm-tdep.c
--- arm-tdep.c 17 May 2006 14:40:39 -0000 1.209
+++ arm-tdep.c 19 Jun 2006 21:39:59 -0000
@@ -1846,8 +1846,8 @@
single_step() is also called just after the inferior stops. If we
had set up a simulated single-step, we undo our damage. */
-static void
-arm_software_single_step (enum target_signal sig, int insert_bpt)
+static int
+arm_possibly_single_step_with_software (enum target_signal sig, int insert_bpt)
{
/* NOTE: This may insert the wrong breakpoint instruction when
single-stepping over a mode-changing instruction, if the
@@ -1861,6 +1861,8 @@
}
else
remove_single_step_breakpoints ();
+
+ return 1
}
#include "bfd-in2.h"
@@ -2789,7 +2791,8 @@
/* Single stepping. */
/* XXX For an RDI target we should ask the target if it can single-step. */
- set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
+ set_gdbarch_possibly_single_step_with_software (gdbarch,
+ arm_possibly_single_step_with_software);
/* Disassembly. */
set_gdbarch_print_insn (gdbarch, gdb_print_insn_arm);
Index: cris-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/cris-tdep.c,v
retrieving revision 1.136
diff -a -u -r1.136 cris-tdep.c
--- cris-tdep.c 18 Apr 2006 19:20:06 -0000 1.136
+++ cris-tdep.c 19 Jun 2006 21:40:00 -0000
@@ -2117,8 +2117,9 @@
digs through the opcodes in order to find all possible targets.
Either one ordinary target or two targets for branches may be found. */
-static void
-cris_software_single_step (enum target_signal ignore, int insert_breakpoints)
+static int
+cris_possibly_single_step_with_software (enum target_signal ignore,
+ int insert_breakpoints)
{
inst_env_type inst_env;
@@ -2150,6 +2151,8 @@
}
else
remove_single_step_breakpoints ();
+
+ return 1;
}
/* Calculates the prefix value for quick offset addressing mode. */
@@ -4136,7 +4139,8 @@
set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register);
set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register);
- set_gdbarch_software_single_step (gdbarch, cris_software_single_step);
+ set_gdbarch_possibly_single_step_with_software (gdbarch,
+ cris_possibly_single_step_with_software);
break;
case 32:
Index: gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.329
diff -a -u -r1.329 gdbarch.c
--- gdbarch.c 18 Apr 2006 19:20:06 -0000 1.329
+++ gdbarch.c 19 Jun 2006 21:40:00 -0000
@@ -216,7 +216,7 @@
gdbarch_convert_from_func_ptr_addr_ftype *convert_from_func_ptr_addr;
gdbarch_addr_bits_remove_ftype *addr_bits_remove;
gdbarch_smash_text_address_ftype *smash_text_address;
- gdbarch_software_single_step_ftype *software_single_step;
+ gdbarch_possibly_single_step_with_software_ftype *possibly_single_step_with_software;
gdbarch_single_step_through_delay_ftype *single_step_through_delay;
gdbarch_print_insn_ftype *print_insn;
gdbarch_skip_trampoline_code_ftype *skip_trampoline_code;
@@ -342,7 +342,7 @@
convert_from_func_ptr_addr_identity, /* convert_from_func_ptr_addr */
0, /* addr_bits_remove */
0, /* smash_text_address */
- 0, /* software_single_step */
+ 0, /* possibly_single_step_with_software */
0, /* single_step_through_delay */
0, /* print_insn */
0, /* skip_trampoline_code */
@@ -595,7 +595,7 @@
/* Skip verify of convert_from_func_ptr_addr, invalid_p == 0 */
/* Skip verify of addr_bits_remove, invalid_p == 0 */
/* Skip verify of smash_text_address, invalid_p == 0 */
- /* Skip verify of software_single_step, has predicate */
+ /* Skip verify of possibly_single_step_with_software, has predicate */
/* Skip verify of single_step_through_delay, has predicate */
if (current_gdbarch->print_insn == 0)
fprintf_unfiltered (log, "\n\tprint_insn");
@@ -1314,6 +1314,24 @@
fprintf_unfiltered (file,
"gdbarch_dump: pointer_to_address = <0x%lx>\n",
(long) current_gdbarch->pointer_to_address);
+#ifdef POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P
+ fprintf_unfiltered (file,
+ "gdbarch_dump: %s # %s\n",
+ "POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P()",
+ XSTRING (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P ()));
+#endif
+ fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_possibly_single_step_with_software_p() = %d\n",
+ gdbarch_possibly_single_step_with_software_p (current_gdbarch));
+#ifdef POSSIBLY_SINGLE_STEP_WITH_SOFTWARE
+ fprintf_unfiltered (file,
+ "gdbarch_dump: %s # %s\n",
+ "POSSIBLY_SINGLE_STEP_WITH_SOFTWARE(sig, insert_breakpoints_p)",
+ XSTRING (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE (sig, insert_breakpoints_p)));
+#endif
+ fprintf_unfiltered (file,
+ "gdbarch_dump: possibly_single_step_with_software = <0x%lx>\n",
+ (long) current_gdbarch->possibly_single_step_with_software);
fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_print_float_info_p() = %d\n",
gdbarch_print_float_info_p (current_gdbarch));
@@ -1536,24 +1554,6 @@
fprintf_unfiltered (file,
"gdbarch_dump: smash_text_address = <0x%lx>\n",
(long) current_gdbarch->smash_text_address);
-#ifdef SOFTWARE_SINGLE_STEP_P
- fprintf_unfiltered (file,
- "gdbarch_dump: %s # %s\n",
- "SOFTWARE_SINGLE_STEP_P()",
- XSTRING (SOFTWARE_SINGLE_STEP_P ()));
-#endif
- fprintf_unfiltered (file,
- "gdbarch_dump: gdbarch_software_single_step_p() = %d\n",
- gdbarch_software_single_step_p (current_gdbarch));
-#ifdef SOFTWARE_SINGLE_STEP
- fprintf_unfiltered (file,
- "gdbarch_dump: %s # %s\n",
- "SOFTWARE_SINGLE_STEP(sig, insert_breakpoints_p)",
- XSTRING (SOFTWARE_SINGLE_STEP (sig, insert_breakpoints_p)));
-#endif
- fprintf_unfiltered (file,
- "gdbarch_dump: software_single_step = <0x%lx>\n",
- (long) current_gdbarch->software_single_step);
#ifdef SP_REGNUM
fprintf_unfiltered (file,
"gdbarch_dump: SP_REGNUM # %s\n",
@@ -3312,27 +3312,27 @@
}
int
-gdbarch_software_single_step_p (struct gdbarch *gdbarch)
+gdbarch_possibly_single_step_with_software_p (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
- return gdbarch->software_single_step != NULL;
+ return gdbarch->possibly_single_step_with_software != NULL;
}
-void
-gdbarch_software_single_step (struct gdbarch *gdbarch, enum target_signal sig, int insert_breakpoints_p)
+int
+gdbarch_possibly_single_step_with_software (struct gdbarch *gdbarch, enum target_signal sig, int insert_breakpoints_p)
{
gdb_assert (gdbarch != NULL);
- gdb_assert (gdbarch->software_single_step != NULL);
+ gdb_assert (gdbarch->possibly_single_step_with_software != NULL);
if (gdbarch_debug >= 2)
- fprintf_unfiltered (gdb_stdlog, "gdbarch_software_single_step called\n");
- gdbarch->software_single_step (sig, insert_breakpoints_p);
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_possibly_single_step_with_software called\n");
+ return gdbarch->possibly_single_step_with_software (sig, insert_breakpoints_p);
}
void
-set_gdbarch_software_single_step (struct gdbarch *gdbarch,
- gdbarch_software_single_step_ftype software_single_step)
+set_gdbarch_possibly_single_step_with_software (struct gdbarch *gdbarch,
+ gdbarch_possibly_single_step_with_software_ftype possibly_single_step_with_software)
{
- gdbarch->software_single_step = software_single_step;
+ gdbarch->possibly_single_step_with_software = possibly_single_step_with_software;
}
int
Index: gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.285
diff -a -u -r1.285 gdbarch.h
--- gdbarch.h 18 Apr 2006 19:20:06 -0000 1.285
+++ gdbarch.h 19 Jun 2006 21:40:00 -0000
@@ -1165,38 +1165,40 @@
#define SMASH_TEXT_ADDRESS(addr) (gdbarch_smash_text_address (current_gdbarch, addr))
#endif
-/* FIXME/cagney/2001-01-18: This should be split in two. A target method that indicates if
- the target needs software single step. An ISA method to implement it.
+/* FIXME/cagney/2001-01-18: This should be split in two. A target method that
+ indicates if the target needs software single step. An ISA method to
+ implement it.
- FIXME/cagney/2001-01-18: This should be replaced with something that inserts breakpoints
- using the breakpoint system instead of blatting memory directly (as with rs6000).
+ FIXME/cagney/2001-01-18: This should be replaced with something that inserts
+ breakpoints using the breakpoint system instead of blatting memory directly
+ (as with rs6000).
- FIXME/cagney/2001-01-18: The logic is backwards. It should be asking if the target can
- single step. If not, then implement single step using breakpoints. */
+ FIXME/cagney/2001-01-18: The logic is backwards. It should be asking if the
+ target can single step. If not, then implement single step using breakpoints. */
-#if defined (SOFTWARE_SINGLE_STEP)
-/* Legacy for systems yet to multi-arch SOFTWARE_SINGLE_STEP */
-#if !defined (SOFTWARE_SINGLE_STEP_P)
-#define SOFTWARE_SINGLE_STEP_P() (1)
+#if defined (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE)
+/* Legacy for systems yet to multi-arch POSSIBLY_SINGLE_STEP_WITH_SOFTWARE */
+#if !defined (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P)
+#define POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P() (1)
#endif
#endif
-extern int gdbarch_software_single_step_p (struct gdbarch *gdbarch);
-#if !defined (GDB_TM_FILE) && defined (SOFTWARE_SINGLE_STEP_P)
-#error "Non multi-arch definition of SOFTWARE_SINGLE_STEP"
+extern int gdbarch_possibly_single_step_with_software_p (struct gdbarch *gdbarch);
+#if !defined (GDB_TM_FILE) && defined (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P)
+#error "Non multi-arch definition of POSSIBLY_SINGLE_STEP_WITH_SOFTWARE"
#endif
-#if !defined (SOFTWARE_SINGLE_STEP_P)
-#define SOFTWARE_SINGLE_STEP_P() (gdbarch_software_single_step_p (current_gdbarch))
+#if !defined (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P)
+#define POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P() (gdbarch_possibly_single_step_with_software_p (current_gdbarch))
#endif
-typedef void (gdbarch_software_single_step_ftype) (enum target_signal sig, int insert_breakpoints_p);
-extern void gdbarch_software_single_step (struct gdbarch *gdbarch, enum target_signal sig, int insert_breakpoints_p);
-extern void set_gdbarch_software_single_step (struct gdbarch *gdbarch, gdbarch_software_single_step_ftype *software_single_step);
-#if !defined (GDB_TM_FILE) && defined (SOFTWARE_SINGLE_STEP)
-#error "Non multi-arch definition of SOFTWARE_SINGLE_STEP"
+typedef int (gdbarch_possibly_single_step_with_software_ftype) (enum target_signal sig, int insert_breakpoints_p);
+extern int gdbarch_possibly_single_step_with_software (struct gdbarch *gdbarch, enum target_signal sig, int insert_breakpoints_p);
+extern void set_gdbarch_possibly_single_step_with_software (struct gdbarch *gdbarch, gdbarch_possibly_single_step_with_software_ftype *possibly_single_step_with_software);
+#if !defined (GDB_TM_FILE) && defined (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE)
+#error "Non multi-arch definition of POSSIBLY_SINGLE_STEP_WITH_SOFTWARE"
#endif
-#if !defined (SOFTWARE_SINGLE_STEP)
-#define SOFTWARE_SINGLE_STEP(sig, insert_breakpoints_p) (gdbarch_software_single_step (current_gdbarch, sig, insert_breakpoints_p))
+#if !defined (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE)
+#define POSSIBLY_SINGLE_STEP_WITH_SOFTWARE(sig, insert_breakpoints_p) (gdbarch_possibly_single_step_with_software (current_gdbarch, sig, insert_breakpoints_p))
#endif
/* Return non-zero if the processor is executing a delay slot and a
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.364
diff -a -u -r1.364 gdbarch.sh
--- gdbarch.sh 18 Apr 2006 19:20:06 -0000 1.364
+++ gdbarch.sh 19 Jun 2006 21:40:00 -0000
@@ -602,15 +602,19 @@
# It is not at all clear why SMASH_TEXT_ADDRESS is not folded into
# ADDR_BITS_REMOVE.
f:=:CORE_ADDR:smash_text_address:CORE_ADDR addr:addr::core_addr_identity::0
-# FIXME/cagney/2001-01-18: This should be split in two. A target method that indicates if
-# the target needs software single step. An ISA method to implement it.
+
+# FIXME/cagney/2001-01-18: This should be split in two. A target method that
+# indicates if the target needs software single step. An ISA method to
+# implement it.
#
-# FIXME/cagney/2001-01-18: This should be replaced with something that inserts breakpoints
-# using the breakpoint system instead of blatting memory directly (as with rs6000).
+# FIXME/cagney/2001-01-18: This should be replaced with something that inserts
+# breakpoints using the breakpoint system instead of blatting memory directly
+# (as with rs6000).
#
-# FIXME/cagney/2001-01-18: The logic is backwards. It should be asking if the target can
-# single step. If not, then implement single step using breakpoints.
-F:=:void:software_single_step:enum target_signal sig, int insert_breakpoints_p:sig, insert_breakpoints_p
+# FIXME/cagney/2001-01-18: The logic is backwards. It should be asking if the
+# target can single step. If not, then implement single step using breakpoints.
+F:=:int:possibly_single_step_with_sofware:enum target_signal sig, int insert_breakpoints_p:sig, insert_breakpoints_p
+
# Return non-zero if the processor is executing a delay slot and a
# further single-step is needed before the instruction finishes.
M::int:single_step_through_delay:struct frame_info *frame:frame
Index: infptrace.c
===================================================================
RCS file: /cvs/src/src/gdb/infptrace.c,v
retrieving revision 1.56
diff -a -u -r1.56 infptrace.c
--- infptrace.c 17 Dec 2005 22:34:01 -0000 1.56
+++ infptrace.c 19 Jun 2006 21:40:00 -0000
@@ -133,7 +133,7 @@
all possible successor instructions), so we don't have to
worry about that here. */
- gdb_assert (!SOFTWARE_SINGLE_STEP_P ());
+ gdb_assert (!POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P ());
request = PT_STEP;
}
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.211
diff -a -u -r1.211 infrun.c
--- infrun.c 16 Jun 2006 01:12:58 -0000 1.211
+++ infrun.c 19 Jun 2006 21:40:00 -0000
@@ -553,16 +553,18 @@
if (breakpoint_here_p (read_pc ()) == permanent_breakpoint_here)
SKIP_PERMANENT_BREAKPOINT ();
- if (SOFTWARE_SINGLE_STEP_P () && step)
+ if (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P () && step)
{
/* Do it the hard way, w/temp breakpoints */
- SOFTWARE_SINGLE_STEP (sig, 1 /*insert-breakpoints */ );
- /* ...and don't ask hardware to do it. */
- step = 0;
- /* and do not pull these breakpoints until after a `wait' in
- `wait_for_inferior' */
- singlestep_breakpoints_inserted_p = 1;
- singlestep_ptid = inferior_ptid;
+ if (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE (sig, 1 /*insert-breakpoints */ ))
+ {
+ /* ...and don't ask hardware to do it. */
+ step = 0;
+ /* and do not pull these breakpoints until after a `wait' in
+ `wait_for_inferior' */
+ singlestep_breakpoints_inserted_p = 1;
+ singlestep_ptid = inferior_ptid;
+ }
}
/* If there were any forks/vforks/execs that were caught and are
@@ -1186,7 +1188,7 @@
breakpoint would be. */
breakpoint_pc = read_pc_pid (ecs->ptid) - DECR_PC_AFTER_BREAK;
- if (SOFTWARE_SINGLE_STEP_P ())
+ if (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P ())
{
/* When using software single-step, a SIGTRAP can only indicate
an inserted breakpoint. This actually makes things
@@ -1375,7 +1377,8 @@
(LONGEST) ecs->ws.value.integer));
gdb_flush (gdb_stdout);
target_mourn_inferior ();
- singlestep_breakpoints_inserted_p = 0; /*SOFTWARE_SINGLE_STEP_P() */
+ /* POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P() */
+ singlestep_breakpoints_inserted_p = 0;
stop_print_frame = 0;
stop_stepping (ecs);
return;
@@ -1395,7 +1398,8 @@
target_mourn_inferior ();
print_stop_reason (SIGNAL_EXITED, stop_signal);
- singlestep_breakpoints_inserted_p = 0; /*SOFTWARE_SINGLE_STEP_P() */
+ /* POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P() */
+ singlestep_breakpoints_inserted_p = 0;
stop_stepping (ecs);
return;
@@ -1542,7 +1546,7 @@
if (stepping_past_singlestep_breakpoint)
{
- gdb_assert (SOFTWARE_SINGLE_STEP_P ()
+ gdb_assert (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P ()
&& singlestep_breakpoints_inserted_p);
gdb_assert (ptid_equal (singlestep_ptid, ecs->ptid));
gdb_assert (!ptid_equal (singlestep_ptid, saved_singlestep_ptid));
@@ -1557,7 +1561,7 @@
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepping_past_singlestep_breakpoint\n");
/* Pull the single step breakpoints out of the target. */
- SOFTWARE_SINGLE_STEP (0, 0);
+ (void) POSSIBLY_SINGLE_STEP_WITH_SOFTWARE (0, 0);
singlestep_breakpoints_inserted_p = 0;
ecs->random_signal = 0;
@@ -1592,7 +1596,8 @@
if (!breakpoint_thread_match (stop_pc, ecs->ptid))
thread_hop_needed = 1;
}
- else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
+ else if (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P ()
+ && singlestep_breakpoints_inserted_p)
{
ecs->random_signal = 0;
/* The call to in_thread_list is necessary because PTIDs sometimes
@@ -1618,10 +1623,11 @@
/* Saw a breakpoint, but it was hit by the wrong thread.
Just continue. */
- if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
+ if (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P ()
+ && singlestep_breakpoints_inserted_p)
{
/* Pull the single step breakpoints out of the target. */
- SOFTWARE_SINGLE_STEP (0, 0);
+ (void) POSSIBLY_SINGLE_STEP_WITH_SOFTWARE (0, 0);
singlestep_breakpoints_inserted_p = 0;
}
@@ -1667,7 +1673,8 @@
return;
}
}
- else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
+ else if (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P ()
+ && singlestep_breakpoints_inserted_p)
{
sw_single_step_trap_p = 1;
ecs->random_signal = 0;
@@ -1691,10 +1698,11 @@
flush_cached_frames ();
}
- if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
+ if (POSSIBLY_SINGLE_STEP_WITH_SOFTWARE_P ()
+ && singlestep_breakpoints_inserted_p)
{
/* Pull the single step breakpoints out of the target. */
- SOFTWARE_SINGLE_STEP (0, 0);
+ (void) POSSIBLY_SINGLE_STEP_WITH_SOFTWARE (0, 0);
singlestep_breakpoints_inserted_p = 0;
}
Index: mips-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-linux-tdep.c,v
retrieving revision 1.45
diff -a -u -r1.45 mips-linux-tdep.c
--- mips-linux-tdep.c 15 Mar 2006 17:13:36 -0000 1.45
+++ mips-linux-tdep.c 19 Jun 2006 21:40:01 -0000
@@ -1180,7 +1180,8 @@
set_gdbarch_skip_solib_resolver (gdbarch, mips_linux_skip_resolver);
- set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
+ set_gdbarch_possibly_single_step_with_software (gdbarch,
+ mips_possibly_single_step_with_software);
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
Index: mips-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.c,v
retrieving revision 1.395
diff -a -u -r1.395 mips-tdep.c
--- mips-tdep.c 13 Jun 2006 18:17:20 -0000 1.395
+++ mips-tdep.c 19 Jun 2006 21:40:01 -0000
@@ -2177,16 +2177,17 @@
return addr;
}
-/* mips_software_single_step() is called just before we want to resume
- the inferior, if we want to single-step it but there is no hardware
+/* mips_possibly_single_step_with_software() is called just before we want to
+ resume the inferior, if we want to single-step it but there is no hardware
or kernel single-step support (MIPS on GNU/Linux for example). We find
the target of the coming instruction and breakpoint it.
single_step is also called just after the inferior stops. If we had
set up a simulated single-step, we undo our damage. */
-void
-mips_software_single_step (enum target_signal sig, int insert_breakpoints_p)
+int
+mips_possibly_single_step_with_software (enum target_signal sig,
+ int insert_breakpoints_p)
{
CORE_ADDR pc, next_pc;
@@ -2199,6 +2200,8 @@
}
else
remove_single_step_breakpoints ();
+
+ return 1;
}
/* Test whether the PC points to the return instruction at the
Index: mips-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.h,v
retrieving revision 1.18
diff -a -u -r1.18 mips-tdep.h
--- mips-tdep.h 17 Dec 2005 22:34:01 -0000 1.18
+++ mips-tdep.h 19 Jun 2006 21:40:01 -0000
@@ -103,7 +103,7 @@
};
/* Single step based on where the current instruction will take us. */
-extern void mips_software_single_step (enum target_signal, int);
+extern int mips_possibly_single_step_with_software (enum target_signal, int);
/* Tell if the program counter value in MEMADDR is in a MIPS16
function. */
Index: mipsnbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mipsnbsd-tdep.c,v
retrieving revision 1.22
diff -a -u -r1.22 mipsnbsd-tdep.c
--- mipsnbsd-tdep.c 28 Feb 2006 04:28:47 -0000 1.22
+++ mipsnbsd-tdep.c 19 Jun 2006 21:40:01 -0000
@@ -395,7 +395,8 @@
set_gdbarch_cannot_fetch_register (gdbarch, mipsnbsd_cannot_fetch_register);
set_gdbarch_cannot_store_register (gdbarch, mipsnbsd_cannot_store_register);
- set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
+ set_gdbarch_possibly_single_step_with_software (gdbarch,
+ mips_possibly_single_step_with_software);
/* NetBSD/mips has SVR4-style shared libraries. */
set_solib_svr4_fetch_link_map_offsets
Index: rs6000-aix-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-aix-tdep.c,v
retrieving revision 1.1
diff -a -u -r1.1 rs6000-aix-tdep.c
--- rs6000-aix-tdep.c 10 Feb 2006 20:56:14 -0000 1.1
+++ rs6000-aix-tdep.c 19 Jun 2006 21:40:01 -0000
@@ -39,7 +39,8 @@
rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
/* RS6000/AIX does not support PT_STEP. Has to be simulated. */
- set_gdbarch_software_single_step (gdbarch, rs6000_software_single_step);
+ set_gdbarch_possibly_single_step_with_software (gdbarch,
+ rs6000_possibly_single_step_with_software);
}
void
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.258
diff -a -u -r1.258 rs6000-tdep.c
--- rs6000-tdep.c 23 Apr 2006 14:15:01 -0000 1.258
+++ rs6000-tdep.c 19 Jun 2006 21:40:01 -0000
@@ -704,9 +704,9 @@
/* AIX does not support PT_STEP. Simulate it. */
-void
-rs6000_software_single_step (enum target_signal signal,
- int insert_breakpoints_p)
+int
+rs6000_possibly_single_step_with_software (enum target_signal signal,
+ int insert_breakpoints_p)
{
CORE_ADDR dummy;
int breakp_sz;
@@ -743,6 +743,8 @@
errno = 0; /* FIXME, don't ignore errors! */
/* What errors? {read,write}_memory call error(). */
+
+ return 1;
}
Index: rs6000-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.h,v
retrieving revision 1.1
diff -a -u -r1.1 rs6000-tdep.h
--- rs6000-tdep.h 10 Feb 2006 20:56:14 -0000 1.1
+++ rs6000-tdep.h 19 Jun 2006 21:40:01 -0000
@@ -21,6 +21,6 @@
#include "defs.h"
-extern void rs6000_software_single_step (enum target_signal signal,
- int insert_breakpoints_p);
+extern int rs6000_possibly_single_step_with_software (enum target_signal signal,
+ int insert_breakpoints_p);
Index: sparc-sol2-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc-sol2-tdep.c,v
retrieving revision 1.11
diff -a -u -r1.11 sparc-sol2-tdep.c
--- sparc-sol2-tdep.c 15 Jan 2006 00:22:50 -0000 1.11
+++ sparc-sol2-tdep.c 19 Jun 2006 21:40:01 -0000
@@ -188,7 +188,7 @@
tdep->plt_entry_size = 12;
/* Solaris has kernel-assisted single-stepping support. */
- set_gdbarch_software_single_step (gdbarch, NULL);
+ set_gdbarch_possibly_single_step_with_software (gdbarch, NULL);
frame_unwind_append_sniffer (gdbarch, sparc32_sol2_sigtramp_frame_sniffer);
}
Index: sparc-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc-tdep.c,v
retrieving revision 1.172
diff -a -u -r1.172 sparc-tdep.c
--- sparc-tdep.c 18 Apr 2006 19:20:06 -0000 1.172
+++ sparc-tdep.c 19 Jun 2006 21:40:01 -0000
@@ -1131,8 +1131,9 @@
return 0;
}
-void
-sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p)
+int
+sparc_possibly_single_step_with_software (enum target_signal sig,
+ int insert_breakpoints_p)
{
struct gdbarch *arch = current_gdbarch;
struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
@@ -1161,6 +1162,8 @@
}
else
remove_single_step_breakpoints ();
+
+ return 1;
}
static void
@@ -1282,7 +1285,8 @@
set_gdbarch_print_insn (gdbarch, print_insn_sparc);
- set_gdbarch_software_single_step (gdbarch, sparc_software_single_step);
+ set_gdbarch_possibly_single_step_with_software (gdbarch,
+ sparc_possibly_single_step_with_software);
set_gdbarch_write_pc (gdbarch, sparc_write_pc);
set_gdbarch_unwind_dummy_id (gdbarch, sparc_unwind_dummy_id);
Index: sparc-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/sparc-tdep.h,v
retrieving revision 1.11
diff -a -u -r1.11 sparc-tdep.h
--- sparc-tdep.h 22 Jan 2006 20:07:38 -0000 1.11
+++ sparc-tdep.h 19 Jun 2006 21:40:01 -0000
@@ -167,8 +167,8 @@
\f
-extern void sparc_software_single_step (enum target_signal sig,
- int insert_breakpoints_p);
+extern int sparc_possibly_single_step_with_software (enum target_signal sig,
+ int insert_breakpoints_p);
extern void sparc_supply_rwindow (struct regcache *regcache,
CORE_ADDR sp, int regnum);
Index: sparc64-sol2-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc64-sol2-tdep.c,v
retrieving revision 1.10
diff -a -u -r1.10 sparc64-sol2-tdep.c
--- sparc64-sol2-tdep.c 15 Jan 2006 00:22:50 -0000 1.10
+++ sparc64-sol2-tdep.c 19 Jun 2006 21:40:01 -0000
@@ -170,7 +170,7 @@
tdep->plt_entry_size = 16;
/* Solaris has kernel-assisted single-stepping support. */
- set_gdbarch_software_single_step (gdbarch, NULL);
+ set_gdbarch_possibly_single_step_with_software (gdbarch, NULL);
}
\f
Index: wince.c
===================================================================
RCS file: /cvs/src/src/gdb/wince.c,v
retrieving revision 1.45
diff -a -u -r1.45 wince.c
--- wince.c 18 Apr 2006 19:20:06 -0000 1.45
+++ wince.c 19 Jun 2006 21:40:01 -0000
@@ -838,9 +838,9 @@
}
}
-void
-wince_software_single_step (enum target_signal ignore,
- int insert_breakpoints_p)
+int
+wince_possibly_single_step_with_software (enum target_signal ignore,
+ int insert_breakpoints_p)
{
unsigned long pc;
/* Info on currently selected thread. */
@@ -850,14 +850,15 @@
if (!insert_breakpoints_p)
{
undoSStep (th);
- return;
+ return 1;
}
th->stepped = 1;
pc = read_register (PC_REGNUM);
th->step_pc = mips_next_pc (pc);
insert_single_step_breakpoint (th->step_pc);
- return;
+
+ return 1;
}
#elif SHx
/* Renesas SH architecture instruction encoding masks */
@@ -979,9 +980,9 @@
instruction and setting a breakpoint on the "next" instruction
which would be executed. This code hails from sh-stub.c.
*/
-void
-wince_software_single_step (enum target_signal ignore,
- int insert_breakpoints_p)
+int
+wince_possibly_single_step_with_software (enum target_signal ignore,
+ int insert_breakpoints_p)
{
/* Info on currently selected thread. */
thread_info *th = current_thread;
@@ -989,13 +990,14 @@
if (!insert_breakpoints_p)
{
undoSStep (th);
- return;
+ return 1;
}
th->stepped = 1;
th->step_pc = sh_get_next_pc (&th->context);
insert_single_step_breakpoint (th->step_pc);
- return;
+
+ return 1;
}
#elif defined (ARM)
#undef check_for_step
@@ -1027,8 +1029,8 @@
}
void
-wince_software_single_step (enum target_signal ignore,
- int insert_breakpoints_p)
+wince_possibly_single_step_with_software (enum target_signal ignore,
+ int insert_breakpoints_p)
{
unsigned long pc;
/* Info on currently selected thread. */
@@ -1038,14 +1040,15 @@
if (!insert_breakpoints_p)
{
undoSStep (th);
- return;
+ return 1;
}
th->stepped = 1;
pc = read_register (PC_REGNUM);
th->step_pc = arm_get_next_pc (pc);
insert_single_step_breakpoint (th->step_pc);
- return;
+
+ return 1;
}
#endif
[-- Attachment #3: ppc-atomic-series.diff --]
[-- Type: text/x-patch, Size: 3421 bytes --]
Index: ppc-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v
retrieving revision 1.78
diff -a -u -r1.78 ppc-linux-tdep.c
--- ppc-linux-tdep.c 18 Apr 2006 19:20:06 -0000 1.78
+++ ppc-linux-tdep.c 19 Jun 2006 21:40:01 -0000
@@ -927,6 +927,84 @@
trad_frame_set_id (this_cache, frame_id_build (base, func));
}
+#define LWARX_MASK 0xfc0007fe
+#define LWARX_INSTRUCTION 0x7C000028
+#define STWCX_MASK 0xfc0007ff
+#define STWCX_INSTRUCTION 0x7c00012d
+#define BC_MASK 0xfc000000
+#define BC_INSTRUCTION 0x40000000
+#define IMMEDIATE_PART(instr) (((instr & ~3) << 16) >> 16)
+#define ABSOLUTE_P(instr) ((int) ((instr >> 1) & 1))
+
+static int
+ppc_atomic_single_step (enum target_signal sig, int insert_breakpoints_p)
+{
+ if (insert_breakpoints_p)
+ {
+ CORE_ADDR pc = read_pc ();
+ CORE_ADDR breaks[2] = {-1, -1};
+ CORE_ADDR loc = pc;
+ long instr = read_memory_integer (loc, PPC_INSN_SIZE);
+ int last_break = 0;
+ int i;
+
+
+ /* Assume all atomic sequences start with an lwarx instruction. */
+ if ((instr & LWARX_MASK) != LWARX_INSTRUCTION)
+ return 0;
+
+ /* Assume that no atomic sequence is longer than 6 instructions. */
+ for (i= 1; i < 5; ++i)
+ {
+ loc += PPC_INSN_SIZE;
+ instr = read_memory_integer (loc, PPC_INSN_SIZE);
+
+ /* Assume at most one conditional branch instruction between
+ the lwarx and stwcx instructions.*/
+ if ((instr & BC_MASK) == BC_INSTRUCTION)
+ {
+ last_break = 1;
+ breaks[1] = IMMEDIATE_PART (instr);
+ if ( ! ABSOLUTE_P(instr))
+ breaks[1] += loc;
+ continue;
+ }
+
+ if ((instr & STWCX_MASK) == STWCX_INSTRUCTION)
+ break;
+ }
+
+ /* Assume that the atomic sequence ends with a stwcx instruction
+ followed by a conditional branch instruction. */
+ if ((instr & STWCX_MASK) != STWCX_INSTRUCTION)
+ error (_("Tried to step over an atomic sequence of instructions but could not find the end of the sequence."));
+
+ loc += PPC_INSN_SIZE;
+ instr = read_memory_integer (loc, PPC_INSN_SIZE);
+
+ if ((instr & BC_MASK) != BC_INSTRUCTION)
+ error (_("Tried to step over an atomic sequence of instructions but it did not end as expected."));
+
+ breaks[0] = loc;
+
+ /* This should never happen, but make sure we don't but
+ two breakpoints on the same address. */
+ if (last_break && breaks[1] == breaks[0])
+ last_break = 0;
+
+ for (i= 0; i < last_break; ++i)
+ insert_single_step_breakpoint (breaks[i]);
+
+ printf_unfiltered (_("Stepping over an atomic sequence of instructions beginning at %s"),
+ core_addr_to_string (pc));
+ gdb_flush (gdb_stdout);
+ }
+ else
+ remove_single_step_breakpoints ();
+
+ return 1;
+}
+
static void
ppc32_linux_sigaction_cache_init (const struct tramp_frame *self,
struct frame_info *next_frame,
@@ -1080,6 +1158,11 @@
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+
+ /* Enable possibly_single_step_with_software in case someone tries to
+ sngle step a sequence of instructions that should be atomic. */
+ set_gdbarch_possibly_single_step_with_software (gdbarch,
+ ppc_atomic_single_step);
}
void
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Instrcutions that must not be stepped.
2006-06-20 20:13 ` PAUL GILLIAM
@ 2006-06-20 22:53 ` Paul Koning
2006-06-20 23:34 ` PAUL GILLIAM
0 siblings, 1 reply; 12+ messages in thread
From: Paul Koning @ 2006-06-20 22:53 UTC (permalink / raw)
To: pgilliam; +Cc: mark.kettenis, gdb, drow
>>>>> "PAUL" == PAUL GILLIAM <pgilliam@us.ibm.com> writes:
>> By the way, if stepping these atomic sequences proves to be a
>> performance problem, you might want to consider implementing
>> stepping them in the (Linux) kernel.
PAUL> This would be cool. It would be nice to be able to tell if the
PAUL> kernel has support for this and let it handle atomic sequences
PAUL> if it does. Let GDB handle it if the kernel doesn't.
Similarly, in remote debugging, there should be a way to have the stub
handle it. That means you may need some extensions to the stub
protocol to encode some new information...
paul
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Instrcutions that must not be stepped.
2006-06-20 22:53 ` Paul Koning
@ 2006-06-20 23:34 ` PAUL GILLIAM
2006-06-21 1:17 ` Daniel Jacobowitz
0 siblings, 1 reply; 12+ messages in thread
From: PAUL GILLIAM @ 2006-06-20 23:34 UTC (permalink / raw)
To: Paul Koning; +Cc: drow, mark.kettenis, gdb, drow
On Tue, 2006-06-20 at 16:17 -0400, Paul Koning wrote:
> >>>>> "PAUL" == PAUL GILLIAM <pgilliam@us.ibm.com> writes:
>
> >> By the way, if stepping these atomic sequences proves to be a
> >> performance problem, you might want to consider implementing
> >> stepping them in the (Linux) kernel.
>
> PAUL> This would be cool. It would be nice to be able to tell if the
> PAUL> kernel has support for this and let it handle atomic sequences
> PAUL> if it does. Let GDB handle it if the kernel doesn't.
>
> Similarly, in remote debugging, there should be a way to have the stub
> handle it. That means you may need some extensions to the stub
> protocol to encode some new information...
Perhaps something in "qSupported" stuff Danial Jacobowitz is working on?
-=# Paul #=-
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Instrcutions that must not be stepped.
2006-06-20 23:34 ` PAUL GILLIAM
@ 2006-06-21 1:17 ` Daniel Jacobowitz
0 siblings, 0 replies; 12+ messages in thread
From: Daniel Jacobowitz @ 2006-06-21 1:17 UTC (permalink / raw)
To: PAUL GILLIAM; +Cc: Paul Koning, mark.kettenis, gdb
On Tue, Jun 20, 2006 at 03:23:51PM -0700, PAUL GILLIAM wrote:
> On Tue, 2006-06-20 at 16:17 -0400, Paul Koning wrote:
> > >>>>> "PAUL" == PAUL GILLIAM <pgilliam@us.ibm.com> writes:
> >
> > >> By the way, if stepping these atomic sequences proves to be a
> > >> performance problem, you might want to consider implementing
> > >> stepping them in the (Linux) kernel.
> >
> > PAUL> This would be cool. It would be nice to be able to tell if the
> > PAUL> kernel has support for this and let it handle atomic sequences
> > PAUL> if it does. Let GDB handle it if the kernel doesn't.
> >
> > Similarly, in remote debugging, there should be a way to have the stub
> > handle it. That means you may need some extensions to the stub
> > protocol to encode some new information...
>
> Perhaps something in "qSupported" stuff Danial Jacobowitz is working on?
No, that's unrelated. I think all you'll want is "step out of range"
on the GDB side, and let the stub handle everything else.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Instrcutions that must not be stepped.
2006-06-09 14:28 ` Daniel Jacobowitz
@ 2006-06-10 0:33 ` PAUL GILLIAM
0 siblings, 0 replies; 12+ messages in thread
From: PAUL GILLIAM @ 2006-06-10 0:33 UTC (permalink / raw)
To: gdb; +Cc: John Yates
On Fri, 2006-06-09 at 10:12 -0400, Daniel Jacobowitz wrote:
. . .
> There is no way to do this for most targets. Paul's probably talking
> about native PowerPC GDB, not any kind of remote stub. Even at that
> point, I think the performance impact here would be unacceptable; the
> repeated single step path is one of the few time-sensitive bits of
GDB.
Daniel is correct: my specific need is for native PowerPC, but the need
for dealing with atomic sequences is more universal. I would like to
come up with a solution for my need that would not hinder a more
universal solution at some later point.
_________
BAD NEWS:
~~~~~~~~~
I tried to measure the impact of reading the instruction about to be
stepped and stumbled across a *horrible* GDB bug. When the number of
instructions stepped in the "Single stepping until exit from function"
mode is large enough (haven't pinned it down yet), the system starts
thrashing until X freezes up and then, after a time, the system crashes.
This is with an un-modified GDB, both cvs-head and the 6.5 tarball.
Here is the setup:
I have a stripped shared library called libtest.so in a test directory.
Here is it's source, "libtest.c":
char *
slow_hello ()
{
char message[] = "Hello, World";
static char out_buf[sizeof(message)];
int i;
char *cp;
for (cp=message; *cp; ++cp)
for (i=0; i<10000; ++i)
out_buf[cp - message] = *cp;
return out_buf;
}
The main program, "testprog.c":
#include <stdio.h>
void slow_help ();
int
main ()
{
printf ("%s\n", slow_hello ());
return 0;
}
Here is how I built the executable:
cc -fPIC -c libtest.c
cc -shared libtest.o -o libtest.so
cc -c testprog.c
cc -L. -ltest testprog.o -o testprog
I used the following gdb script ("gdb-script"):
start
b slow_hello
c
s
c
q
Here is what it looks like when I run GDB:
[pgilliam@dufur]$ LD_LIBRARY_PATH=. gdb -x gdb-script testprog
GNU gdb 6.5.50.20060608-cvs
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License,
and you are
welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty"
for details.
This GDB was configured as "powerpc64-unknown-linux-gnu"...Using
host libthread_db library "/lib/libthread_db.so.1".
Breakpoint 1 at 0x100015a4: file testprog.c, line 8.
main () at testprog.c:8
8 printf ("%s\n", slow_hello ());
Breakpoint 2 at 0xffaf70c
Breakpoint 2, 0x0ffaf70c in slow_hello () from ./libtest.so
Single stepping until exit from function slow_hello,
which has no line number information.
Program received signal SIGINT, Interrupt.
0x0ffaf77c in slow_hello () from ./libtest.so
Hello, World
Program exited normally.
[pgilliam@dufur]$ cat libtest.c
If I didn't interrupt it with a <cntl-c> within a minute or so of it's
start, the system would start thrashing and, sometime overnight, it
crashed.
Again, both cvs-head and 6.5 exhibited this behavior, but
(HERE'S THE KICKER) the GDB distributed with the system did not.
Here is with the distributed GDB:
[pgilliam@dufur]$ time LD_LIBRARY_PATH=. gdb -x gdb-script
testprog
GNU gdb Red Hat Linux (6.3.0.0-1.21rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License,
and you are
welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty"
for details.
This GDB was configured as "ppc-redhat-linux-gnu"...Using host
libthread_db library "/lib/libthread_db.so.1".
Breakpoint 1 at 0x100015a4: file testprog.c, line 8.
main () at testprog.c:8
8 printf ("%s\n", slow_hello ());
Breakpoint 2 at 0xffaf70c
Breakpoint 2, 0x0ffaf70c in slow_hello () from ./libtest.so
Single stepping until exit from function slow_hello,
which has no line number information.
Hello, World
main () at testprog.c:9
9 return 0;
Program exited normally.
real 0m55.448s
user 0m12.933s
sys 0m30.534s
[pgilliam@dufur]$
I tried it with vanilla 6.4 with no problem.
I also tried it with cvs-head on an x86 system with no problem, but with
something strange:
here is with the distributed gdb on x86 (slight mod to gdb-script
needed):
pgilliam> time LD_LIBRARY_PATH=. gdb -x gdb-script ./testprog
GNU gdb 6.1
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License,
and you are
welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty"
for details.
This GDB was configured as "i586-suse-linux"...Using host
libthread_db library "/lib/tls/libthread_db.so.1".
Breakpoint 1 at 0x80484e2
Breakpoint 1, 0x080484e2 in main ()
Breakpoint 2 at 0x400186ae
Breakpoint 2, 0x400186ae in slow_hello () from ./libtest.so
Single stepping until exit from function slow_hello,
which has no line number information.
0x080484f7 in main ()
Hello, World
Program exited normally.
real 0m37.366s
user 0m14.006s
sys 0m25.242s
pgilliam>
And here it is with cvs-head on x86:
pgilliam> time LD_LIBRARY_PATH=. ../gdb -x gdb-script ./testprog
GNU gdb 6.5.50.20060609-cvs
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License,
and you are
welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty"
for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host
libthread_db library "/lib/tls/libthread_db.so.1".
Breakpoint 1 at 0x80484e2
Breakpoint 1, 0x080484e2 in main ()
Breakpoint 2 at 0x400186ae
Breakpoint 2, 0x400186ae in slow_hello () from ./libtest.so
Single stepping until exit from function slow_hello,
which has no line number information.
0x080484f7 in main ()
Hello, World
Program exited normally.
real 2m4.106s
user 0m42.448s
sys 1m25.191s
pgilliam>
Wow! Why did it take so much longer?
-=# Paul #=-
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Instrcutions that must not be stepped.
2006-06-09 14:12 John Yates
@ 2006-06-09 14:28 ` Daniel Jacobowitz
2006-06-10 0:33 ` PAUL GILLIAM
0 siblings, 1 reply; 12+ messages in thread
From: Daniel Jacobowitz @ 2006-06-09 14:28 UTC (permalink / raw)
To: John Yates; +Cc: PAUL GILLIAM, gdb
On Fri, Jun 09, 2006 at 09:49:54AM -0400, John Yates wrote:
> Daniel Jacobowitz writes:
>
> > Nope. You'd have to add one. And, you'd have to be able to tell
> > whether you were in the middle of a GDB-automated step or a user stepi;
> > stepping multiple instructions when the user asked for one is probably
> > just confusing.
>
> To whom or what? I would be quite happy if gdb did the right thing
> and output a message to the effect that an atomic sequence was indeed
> treated as atomic. That is the count of instructions stepped changed
> by one for any number of failed attempts and then one final successful
> execution of the entire atomic sequence.
If we warn about it, then it's not so confusing :-P
There are plenty of other potential issues here. For instance, we'd
need to check for branches inside the atomic sequence; otherwise we
could completely lose control.
> > Reading the instruction before stepping is going to slow down single
> > stepping. Is there some other way we can handle this?
>
> The overhead could be ameliorated by having the status returned from
> a completed single step include an optional assertion that if gdb were
> to step again without altering the pc or the contents of memory at the
> address referenced by the pc then that step would initiate an atomic
> sequence.
There is no way to do this for most targets. Paul's probably talking
about native PowerPC GDB, not any kind of remote stub. Even at that
point, I think the performance impact here would be unacceptable; the
repeated single step path is one of the few time-sensitive bits of GDB.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: Instrcutions that must not be stepped.
@ 2006-06-09 14:12 John Yates
2006-06-09 14:28 ` Daniel Jacobowitz
0 siblings, 1 reply; 12+ messages in thread
From: John Yates @ 2006-06-09 14:12 UTC (permalink / raw)
To: Daniel Jacobowitz, PAUL GILLIAM; +Cc: gdb
Daniel Jacobowitz writes:
> Nope. You'd have to add one. And, you'd have to be able to tell
> whether you were in the middle of a GDB-automated step or a user stepi;
> stepping multiple instructions when the user asked for one is probably
> just confusing.
To whom or what? I would be quite happy if gdb did the right thing
and output a message to the effect that an atomic sequence was indeed
treated as atomic. That is the count of instructions stepped changed
by one for any number of failed attempts and then one final successful
execution of the entire atomic sequence.
> Reading the instruction before stepping is going to slow down single
> stepping. Is there some other way we can handle this?
The overhead could be ameliorated by having the status returned from
a completed single step include an optional assertion that if gdb were
to step again without altering the pc or the contents of memory at the
address referenced by the pc then that step would initiate an atomic
sequence.
With this mechanism the first attempt to single step after a period of
non-single stepped execution would need to check the first instruction;
after that the process would be self sustaining without any addition
gdb initiated instruction inspection.
Admitted this mechanism does not absolve the greater gestalt of gdb +
stub + single step break handle from needing to retrieve and inspect
instructions. But it may push it to a point where the overhead becomes
acceptable.
/john
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2006-06-20 23:35 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-08 2:27 Instrcutions that must not be stepped PAUL GILLIAM
2006-06-08 3:50 ` Daniel Jacobowitz
2006-06-16 4:36 ` PAUL GILLIAM
2006-06-17 12:26 ` PAUL GILLIAM
2006-06-18 4:57 ` Mark Kettenis
2006-06-20 20:13 ` PAUL GILLIAM
2006-06-20 22:53 ` Paul Koning
2006-06-20 23:34 ` PAUL GILLIAM
2006-06-21 1:17 ` Daniel Jacobowitz
2006-06-09 14:12 John Yates
2006-06-09 14:28 ` Daniel Jacobowitz
2006-06-10 0:33 ` PAUL GILLIAM
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox