aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r--gdb/infrun.c182
1 files changed, 172 insertions, 10 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 596e17c..67b0c17 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -29,7 +29,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <stdio.h>
#include <signal.h>
#include <a.out.h>
-#include <sys/file.h>
#ifdef UMAX_PTRACE
#include <sys/param.h>
@@ -117,6 +116,14 @@ static int running_in_shell;
static int stop_print_frame;
+#ifdef NO_SINGLE_STEP
+/* Non-zero if we just simulated a single-step ptrace call. This is
+ needed because we cannot remove the breakpoints in the inferior
+ process until after the `wait' in `wait_for_inferior'.
+ Used for sun4. */
+int one_stepped;
+#endif /* NO_SINGLE_STEP */
+
static void insert_step_breakpoint ();
static void remove_step_breakpoint ();
static void wait_for_inferior ();
@@ -178,7 +185,12 @@ proceed (addr, signal, step)
oneproc = 1;
}
else
- write_register (PC_REGNUM, addr);
+ {
+ write_register (PC_REGNUM, addr);
+#ifdef NPC_REGNUM
+ write_register (NPC_REGNUM, addr+4);
+#endif
+ }
if (trap_expected_after_continue)
{
@@ -351,6 +363,13 @@ wait_for_inferior ()
continue;
}
+#ifdef NO_SINGLE_STEP
+ if (one_stepped)
+ {
+ single_step (0);
+ }
+#endif /* NO_SINGLE_STEP */
+
pc_changed = 0;
fetch_inferior_registers ();
stop_pc = read_pc ();
@@ -451,6 +470,9 @@ wait_for_inferior ()
{
stop_pc -= DECR_PC_AFTER_BREAK;
write_register (PC_REGNUM, stop_pc);
+#ifdef NPC_REGNUM
+ write_register (NPC_REGNUM, stop_pc + 4);
+#endif
pc_changed = 0;
}
}
@@ -463,6 +485,9 @@ wait_for_inferior ()
{
stop_pc -= DECR_PC_AFTER_BREAK;
write_register (PC_REGNUM, stop_pc);
+#ifdef NPC_REGNUM
+ write_register (PC_REGNUM, stop_pc + 4);
+#endif
pc_changed = 0;
}
}
@@ -766,13 +791,7 @@ Further execution is probably impossible.\n");
if (running_in_shell)
{
if (stop_signal == SIGSEGV)
- {
- char *exec_file = (char *) get_exec_file (1);
-
- if (access (exec_file, X_OK) != 0)
- printf ("The file \"%s\" is not executable.\n", exec_file);
- else
- printf ("\
+ printf ("\
You have just encountered a bug in \"sh\". GDB starts your program\n\
by running \"sh\" with a command to exec your program.\n\
This is so that \"sh\" will process wildcards and I/O redirection.\n\
@@ -784,7 +803,6 @@ some variables whose values are large; then do \"run\" again.\n\
\n\
If that works, you might want to put those \"unset-env\" commands\n\
into a \".gdbinit\" file in this directory so they will happen every time.\n");
- }
/* Don't confuse user with his program's symbols on sh's data. */
stop_print_frame = 0;
}
@@ -1026,4 +1044,148 @@ Pass and Stop may be combined.");
#endif /* SIGURG */
}
+#ifdef NO_SINGLE_STEP
+/* This code was written by Gary Beihl (beihl@mcc.com).
+ It was modified by Michael Tiemann (tiemann@corto.inria.fr). */
+
+/* Simulate single-step ptrace call for sun4. */
+
+typedef enum
+{
+ b_error, not_branch, bicc, bicca, ba, baa, ticc, ta,
+} branch_type;
+
+static CORE_ADDR next_pc, pc8, target;
+static int brkpc8, brktrg;
+typedef char binsn_quantum[sizeof break_insn];
+static binsn_quantum break_mem[3];
+
+int
+single_step (signal)
+ int signal;
+{
+ branch_type br, isabranch();
+
+ next_pc = read_register (NPC_REGNUM);
+ pc8 = read_register (PC_REGNUM) + 8; /* branch not taken */
+
+ if (!one_stepped)
+ {
+ /* Always set breakpoint for NPC. */
+ read_memory (next_pc, break_mem[0], sizeof break_insn);
+ write_memory (next_pc, break_insn, sizeof break_insn);
+
+ /* printf ("set break at %x\n",next_pc); */
+ br = isabranch (pc8 - 8, &target);
+ brkpc8 = brktrg = 0;
+
+ if (br == bicca && pc8 != next_pc)
+ {
+ /* Handle branches with care */
+ brkpc8 = 1;
+ read_memory (pc8, break_mem[1], sizeof break_insn);
+ write_memory (pc8, break_insn, sizeof break_insn);
+ }
+ else if (br == baa && target != next_pc)
+ {
+ brktrg = 1;
+ read_memory (target, break_mem[2], sizeof break_insn);
+ write_memory (target, break_insn, sizeof break_insn);
+ }
+
+ /* Let it go */
+ ptrace (7, inferior_pid, 1, signal);
+ one_stepped = 1;
+ return;
+ }
+ else
+ {
+ /* Remove breakpoints */
+ write_memory (next_pc, break_mem[0], sizeof break_insn);
+
+ if (brkpc8)
+ {
+ write_memory (pc8, break_mem[1], sizeof break_insn);
+ }
+ if (brktrg)
+ {
+ write_memory (target, break_mem[2], sizeof break_insn);
+ }
+ one_stepped = 0;
+ }
+}
+
+#endif /* NO_SINGLE_STEP */
+
+static int save_insn_opcodes[] = { 0x03000000, 0x82007ee0, 0x9de38001, 0x03000000, 0x82007ee0, 0x91d02001, 0x01000000 };
+
+void
+do_save_insn (size)
+ int size;
+{
+ int g1 = read_register (1);
+ CORE_ADDR sp = read_register (SP_REGNUM);
+ CORE_ADDR pc = read_register (PC_REGNUM);
+#ifdef NPC_REGNUM
+ CORE_ADDR npc = read_register (NPC_REGNUM);
+#endif
+ CORE_ADDR fake_pc = sp - sizeof (save_insn_opcodes);
+ save_insn_opcodes[0] = 0x03000000 | ((-size >> 12) & 0x3fffff);
+ save_insn_opcodes[1] = 0x82006000 | (-size & 0x3ff);
+ save_insn_opcodes[3] = 0x03000000 | ((g1 >> 12) & 0x3fffff);
+ save_insn_opcodes[4] = 0x82006000 | (g1 & 0x3ff);
+ write_memory (fake_pc, save_insn_opcodes, sizeof (save_insn_opcodes));
+ clear_proceed_status ();
+ stop_after_trap = 1;
+
+ proceed (fake_pc, 0, 0);
+
+ write_register (PC_REGNUM, pc);
+#ifdef NPC_REGNUM
+ write_register (NPC_REGNUM, npc);
+#endif
+}
+
+static int restore_insn_opcodes[] = { 0x81e80000, 0x91d02001, 0x01000000 };
+
+void
+do_restore_insn (raw_buffer)
+ char raw_buffer[];
+{
+ CORE_ADDR pc = read_memory_integer (*(int *)&raw_buffer[REGISTER_BYTE (PC_REGNUM)], 4);
+ CORE_ADDR sp = read_register (SP_REGNUM);
+#ifdef NPC_REGNUM
+ CORE_ADDR npc = *(int *)&raw_buffer[REGISTER_BYTE (NPC_REGNUM)] != 0
+ ? read_memory_integer (*(int *)&raw_buffer[REGISTER_BYTE (NPC_REGNUM)], 4) : pc + 4;
+#endif
+ CORE_ADDR fake_pc = sp - sizeof (restore_insn_opcodes);
+ int saved_stop_stack_dummy = stop_stack_dummy;
+
+ if (*(int *)&raw_buffer[REGISTER_BYTE (PC_REGNUM)] == 0)
+ abort ();
+
+ write_memory (fake_pc, restore_insn_opcodes, sizeof (restore_insn_opcodes));
+ clear_proceed_status ();
+ stop_after_trap = 1;
+
+ proceed (fake_pc, 0, 0);
+
+ stop_stack_dummy = saved_stop_stack_dummy;
+ write_register (PC_REGNUM, pc);
+#ifdef NPC_REGNUM
+ write_register (NPC_REGNUM, npc);
+#endif
+
+ /* Select innermost stack frame except on return from a stack dummy routine,
+ or if the program has exited. */
+ if (!stop_stack_dummy)
+ {
+ select_frame (stop_frame, 0);
+ }
+ else
+ {
+ select_frame (read_register (FP_REGNUM), 0);
+ }
+}
+
END_FILE