From b6d00b165afddb67c9170412bbc4ac90fd6ded5b73e26956f370fd223a1be921 Mon Sep 17 00:00:00 2001 From: OBS User unknown Date: Fri, 9 Mar 2007 00:45:10 +0000 Subject: [PATCH] OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/gdb?expand=0&rev=7 --- atomic-single-step.diff | 631 ++++++++++++++++++++++++++++++++++++++++ gdb.changes | 5 + gdb.spec | 8 +- 3 files changed, 643 insertions(+), 1 deletion(-) create mode 100644 atomic-single-step.diff diff --git a/atomic-single-step.diff b/atomic-single-step.diff new file mode 100644 index 0000000..f9bc193 --- /dev/null +++ b/atomic-single-step.diff @@ -0,0 +1,631 @@ +20006-06-22 Paul Gilliam + + * gdbarch.sh: Change the return type of software_single_step from + void to int and reformatted some comments to <= 80 columns. + * gdbarch.c, gdbarch.h: Regenerated. + * alpha-tdep.c (alpha_software_single_step): Change the return type + from void to int and always return 1. + * alpha-tdep.h: Change the return type of alpha_software_single_step + from void to int. + * arm-tdep.c (arm_software_single_step): Change the return type from + void to int and always return 1. + * cris-tdep.c (cris_software_single_step): Change the return type + from void to int and always return 1. + * mips-tdep.c (mips_software_single_step): Change the return type + from void to int and always return 1. + * mips-tdep.h: Change the return type of mips_software_single_step + from void to int. + * rs6000-tdep.c (rs6000_software_single_step): Change the return type + from void to int and always return 1. + *rs6000-tdep.h: Change the return type of rs6000_software_single_step + from void to int. + * sparc-tdep.c (sparc_software_single_step): Change the return type + from void to int and always return 1. + * sparc-tdep.h: Change the return type of sparc_software_single_step + from void to int. + * wince.c (wince_software_single_step {three times}): Change the + return type from void to int and always return 1. + infrun.c (resume): Check the return value from SOFTWARE_SINGLE_STEP + and act accordingly. True means that the software_single_step + breakpoints where inserted; false means they where not. + +Index: alpha-tdep.c +================================================================================ +--- alpha-tdep.c ++++ alpha-tdep.c +@@ -1510,7 +1510,7 @@ + return (pc + 4); + } + +-void ++int + alpha_software_single_step (enum target_signal sig, int insert_breakpoints_p) + { + static CORE_ADDR next_pc; +@@ -1528,6 +1528,7 @@ + remove_single_step_breakpoints (); + write_pc (next_pc); + } ++ return 1; + } + + +--- alpha-tdep.h ++++ alpha-tdep.h +@@ -107,7 +107,7 @@ + }; + + extern unsigned int alpha_read_insn (CORE_ADDR pc); +-extern void alpha_software_single_step (enum target_signal, int); ++extern int alpha_software_single_step (enum target_signal, int); + extern CORE_ADDR alpha_after_prologue (CORE_ADDR pc); + + extern void alpha_mdebug_init_abi (struct gdbarch_info, struct gdbarch *); +--- arm-tdep.c ++++ arm-tdep.c +@@ -1840,7 +1840,7 @@ + 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 ++static int + arm_software_single_step (enum target_signal sig, int insert_bpt) + { + /* NOTE: This may insert the wrong breakpoint instruction when +@@ -1855,6 +1855,8 @@ + } + else + remove_single_step_breakpoints (); ++ ++ return 1 + } + + #include "bfd-in2.h" +--- cris-tdep.c ++++ cris-tdep.c +@@ -2117,7 +2117,7 @@ + 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 ++static int + cris_software_single_step (enum target_signal ignore, int insert_breakpoints) + { + inst_env_type inst_env; +@@ -2150,6 +2150,8 @@ + } + else + remove_single_step_breakpoints (); ++ ++ return 1; + } + + /* Calculates the prefix value for quick offset addressing mode. */ +--- gdbarch.c ++++ gdbarch.c +@@ -3273,14 +3273,14 @@ + return gdbarch->software_single_step != NULL; + } + +-void ++int + gdbarch_software_single_step (struct gdbarch *gdbarch, enum target_signal sig, int insert_breakpoints_p) + { + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->software_single_step != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_software_single_step called\n"); +- gdbarch->software_single_step (sig, insert_breakpoints_p); ++ return gdbarch->software_single_step (sig, insert_breakpoints_p); + } + + void +--- gdbarch.h ++++ gdbarch.h +@@ -1140,14 +1140,16 @@ + #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 */ +@@ -1164,8 +1166,8 @@ + #define SOFTWARE_SINGLE_STEP_P() (gdbarch_software_single_step_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); ++typedef int (gdbarch_software_single_step_ftype) (enum target_signal sig, int insert_breakpoints_p); ++extern int 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" +--- gdbarch.sh ++++ gdbarch.sh +@@ -601,15 +601,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:software_single_step: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 +--- infrun.c ++++ infrun.c +@@ -557,13 +557,15 @@ + if (SOFTWARE_SINGLE_STEP_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 (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 there were any forks/vforks/execs that were caught and are +@@ -1382,7 +1384,7 @@ + (LONGEST) ecs->ws.value.integer)); + gdb_flush (gdb_stdout); + target_mourn_inferior (); +- singlestep_breakpoints_inserted_p = 0; /*SOFTWARE_SINGLE_STEP_P() */ ++ singlestep_breakpoints_inserted_p = 0; /* SOFTWARE_SINGLE_STEP_P() */ + stop_print_frame = 0; + stop_stepping (ecs); + return; +@@ -1402,7 +1404,7 @@ + target_mourn_inferior (); + + print_stop_reason (SIGNAL_EXITED, stop_signal); +- singlestep_breakpoints_inserted_p = 0; /*SOFTWARE_SINGLE_STEP_P() */ ++ singlestep_breakpoints_inserted_p = 0; /* SOFTWARE_SINGLE_STEP_P() */ + stop_stepping (ecs); + return; + +@@ -1576,7 +1578,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) SOFTWARE_SINGLE_STEP (0, 0); + singlestep_breakpoints_inserted_p = 0; + + ecs->random_signal = 0; +@@ -1640,7 +1642,7 @@ + if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p) + { + /* Pull the single step breakpoints out of the target. */ +- SOFTWARE_SINGLE_STEP (0, 0); ++ (void) SOFTWARE_SINGLE_STEP (0, 0); + singlestep_breakpoints_inserted_p = 0; + } + +@@ -1713,7 +1715,7 @@ + if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p) + { + /* Pull the single step breakpoints out of the target. */ +- SOFTWARE_SINGLE_STEP (0, 0); ++ (void) SOFTWARE_SINGLE_STEP (0, 0); + singlestep_breakpoints_inserted_p = 0; + } + +--- mips-tdep.c ++++ mips-tdep.c +@@ -2185,7 +2185,7 @@ + single_step is also called just after the inferior stops. If we had + set up a simulated single-step, we undo our damage. */ + +-void ++int + mips_software_single_step (enum target_signal sig, int insert_breakpoints_p) + { + CORE_ADDR pc, next_pc; +@@ -2199,6 +2199,8 @@ + } + else + remove_single_step_breakpoints (); ++ ++ return 1; + } + + /* Test whether the PC points to the return instruction at the +--- mips-tdep.h ++++ mips-tdep.h +@@ -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_software_single_step (enum target_signal, int); + + /* Tell if the program counter value in MEMADDR is in a MIPS16 + function. */ +--- ppc-linux-tdep.c ++++ ppc-linux-tdep.c +@@ -931,6 +931,90 @@ + 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(insn) (((insn & ~3) << 16) >> 16) ++#define ABSOLUTE_P(insn) ((int) ((insn >> 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; ++ int insn = read_insn (loc); ++ int last_break = 0; ++ int i; ++ ++ ++ /* Assume all atomic sequences start with an lwarx instruction. */ ++ if ((insn & 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; ++ insn = read_insn (loc); ++ ++ /* Assume at most one conditional branch instruction between ++ the lwarx and stwcx instructions.*/ ++ if ((insn & BC_MASK) == BC_INSTRUCTION) ++ { ++ last_break = 1; ++ breaks[1] = IMMEDIATE_PART (insn); ++ if (! ABSOLUTE_P (insn)) ++ breaks[1] += loc; ++ continue; ++ } ++ ++ if ((insn & STWCX_MASK) == STWCX_INSTRUCTION) ++ break; ++ } ++ ++ /* Assume that the atomic sequence ends with a stwcx instruction ++ followed by a conditional branch instruction. */ ++ if ((insn & STWCX_MASK) != STWCX_INSTRUCTION) ++ { ++ warning (_("Tried to step over an atomic sequence of instructions but could not find the end of the sequence.")); ++ return 0; ++ } ++ ++ loc += PPC_INSN_SIZE; ++ insn = read_insn (loc); ++ ++ if ((insn & BC_MASK) != BC_INSTRUCTION) ++ { ++ warning (_("Tried to step over an atomic sequence of instructions but it did not end as expected.")); ++ return 0; ++ } ++ ++ 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\n"), ++ 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, +@@ -1086,6 +1170,10 @@ + /* Enable TLS support. */ + set_gdbarch_fetch_tls_load_module_address (gdbarch, + svr4_fetch_objfile_link_map); ++ ++ /* Enable software_single_step in case someone tries to sngle step a ++ sequence of instructions that should be atomic. */ ++ set_gdbarch_software_single_step (gdbarch, ppc_atomic_single_step); + } + + void +--- rs6000-tdep.c ++++ rs6000-tdep.c +@@ -702,10 +702,89 @@ + return little_breakpoint; + } + ++#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(insn) (((insn & ~3) << 16) >> 16) ++#define ABSOLUTE_P(insn) ((int) ((insn >> 1) & 1)) ++ ++static int ++deal_with_atomic_sequence (enum target_signal sig) ++{ ++ CORE_ADDR pc = read_pc (); ++ CORE_ADDR breaks[2] = {-1, -1}; ++ CORE_ADDR loc = pc; ++ int insn = read_memory_integer (loc, 4); ++ int last_break = 0; ++ int i; + +-/* AIX does not support PT_STEP. Simulate it. */ + +-void ++ /* Assume all atomic sequences start with an lwarx instruction. */ ++ if ((insn & 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; ++ insn = read_memory_integer (loc, 4); ++ ++ /* Assume at most one conditional branch instruction between ++ the lwarx and stwcx instructions.*/ ++ if ((insn & BC_MASK) == BC_INSTRUCTION) ++ { ++ last_break = 1; ++ breaks[1] = IMMEDIATE_PART (insn); ++ if (! ABSOLUTE_P (insn)) ++ breaks[1] += loc; ++ continue; ++ } ++ ++ if ((insn & STWCX_MASK) == STWCX_INSTRUCTION) ++ break; ++ } ++ ++ /* Assume that the atomic sequence ends with a stwcx instruction ++ followed by a conditional branch instruction. */ ++ if ((insn & STWCX_MASK) != STWCX_INSTRUCTION) ++ { ++ warning (_("Tried to step over an atomic sequence of instructions but could not find the end of the sequence.")); ++ return 0; ++ } ++ ++ loc += PPC_INSN_SIZE; ++ insn = read_memory_integer (loc, 4); ++ ++ if ((insn & BC_MASK) != BC_INSTRUCTION) ++ { ++ warning (_("Tried to step over an atomic sequence of instructions but it did not end as expected.")); ++ return 0; ++ } ++ ++ 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\n"), ++ core_addr_to_string (pc)); ++ gdb_flush (gdb_stdout); ++ ++ return 1; ++} ++ ++/* AIX does not support PT_STEP. Simulate it, dealing with any sequence of ++ instructions that must be atomic. */ ++ ++int + rs6000_software_single_step (enum target_signal signal, + int insert_breakpoints_p) + { +@@ -723,6 +802,9 @@ + + insn = read_memory_integer (loc, 4); + ++ if (deal_with_atomic_sequence (signal)) ++ return 1; ++ + breaks[0] = loc + breakp_sz; + opcode = insn >> 26; + breaks[1] = branch_dest (opcode, insn, loc, breaks[0]); +@@ -744,6 +826,8 @@ + + errno = 0; /* FIXME, don't ignore errors! */ + /* What errors? {read,write}_memory call error(). */ ++ ++ return 1; + } + + +--- rs6000-tdep.h ++++ rs6000-tdep.h +@@ -21,6 +21,6 @@ + + #include "defs.h" + +-extern void rs6000_software_single_step (enum target_signal signal, +- int insert_breakpoints_p); ++extern int rs6000_software_single_step (enum target_signal signal, ++ int insert_breakpoints_p); + +--- sparc-tdep.c ++++ sparc-tdep.c +@@ -1131,7 +1131,7 @@ + return 0; + } + +-void ++int + sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p) + { + struct gdbarch *arch = current_gdbarch; +@@ -1161,6 +1161,8 @@ + } + else + remove_single_step_breakpoints (); ++ ++ return 1; + } + + static void +--- sparc-tdep.h ++++ sparc-tdep.h +@@ -167,8 +167,8 @@ + + + +-extern void sparc_software_single_step (enum target_signal sig, +- int insert_breakpoints_p); ++extern int sparc_software_single_step (enum target_signal sig, ++ int insert_breakpoints_p); + + extern void sparc_supply_rwindow (struct regcache *regcache, + CORE_ADDR sp, int regnum); +--- wince.c ++++ wince.c +@@ -838,7 +838,7 @@ + } + } + +-void ++int + wince_software_single_step (enum target_signal ignore, + int insert_breakpoints_p) + { +@@ -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,7 +980,7 @@ + instruction and setting a breakpoint on the "next" instruction + which would be executed. This code hails from sh-stub.c. + */ +-void ++int + wince_software_single_step (enum target_signal ignore, + int insert_breakpoints_p) + { +@@ -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 +@@ -1026,7 +1028,7 @@ + } + } + +-void ++int + wince_software_single_step (enum target_signal ignore, + int insert_breakpoints_p) + { +@@ -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 + diff --git a/gdb.changes b/gdb.changes index 409ac7b..50195e8 100644 --- a/gdb.changes +++ b/gdb.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Thu Mar 8 15:04:28 CET 2007 - schwab@suse.de + +- Deal with stepping over sequence of atomic insns [#154486]. + ------------------------------------------------------------------- Wed Mar 7 14:05:16 CET 2007 - schwab@suse.de diff --git a/gdb.spec b/gdb.spec index ff4a8c0..db87072 100644 --- a/gdb.spec +++ b/gdb.spec @@ -21,7 +21,7 @@ Group: Development/Tools/Debuggers Autoreqprov: on PreReq: %{install_info_prereq} Version: 6.6 -Release: 15 +Release: 16 Summary: The GNU Debugger Source: gdb-%{version}.tar.bz2 Patch1: gdb-misc.patch @@ -40,6 +40,7 @@ Patch15: solib-extract-address.diff Patch16: pc-regnum.diff Patch17: show-endian.diff Patch18: elf-symtab-read.diff +Patch19: atomic-single-step.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -86,6 +87,9 @@ cd .. %patch16 %patch17 -p1 %patch18 +cd gdb +%patch19 +cd .. %build CFLAGS="$RPM_OPT_FLAGS" \ @@ -141,6 +145,8 @@ rm -rf $RPM_BUILD_ROOT %endif %changelog +* Thu Mar 08 2007 - schwab@suse.de +- Deal with stepping over sequence of atomic insns [#154486]. * Wed Mar 07 2007 - schwab@suse.de - Improve last change. * Tue Mar 06 2007 - schwab@suse.de