aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/linux-low.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2002-04-20 17:04:09 +0000
committerDaniel Jacobowitz <drow@false.org>2002-04-20 17:04:09 +0000
commit611cb4a54268cbb8f25175dd4900fff87eae161b (patch)
tree36f338fc4e4b09e0b70a51d1f96e648090173ed2 /gdb/gdbserver/linux-low.c
parente1015982836dff64160d26425ef428997c1de624 (diff)
downloadgdb-611cb4a54268cbb8f25175dd4900fff87eae161b.zip
gdb-611cb4a54268cbb8f25175dd4900fff87eae161b.tar.gz
gdb-611cb4a54268cbb8f25175dd4900fff87eae161b.tar.bz2
2002-04-20 Daniel Jacobowitz <drow@mvista.com>
* gdbserver/mem-break.c: New file. * gdbserver/mem-break.h: New file. * gdbserver/Makefile.in: Add mem-break.o rule; update server.h dependencies. * gdbserver/inferiors.c (struct inferior_info): Add target_data member. (clear_inferiors): Free target_data member if set. (inferior_target_data, set_inferior_target_data): New functions. * gdbserver/linux-i386-low.c (i386_breakpoint, i386_breakpoint_len) (i386_stop_pc, i386_set_pc): New. Add to the_low_target. * gdbserver/linux-low.c (linux_bp_reinsert): New variable. (struct inferior_linux_data): New. (linux_create_inferior): Use set_inferior_target_data. (linux_attach): Likewise. Call add_inferior. (linux_wait_for_one_inferior): New function. (linux_wait): Call it. (linux_write_memory): Add const. (initialize_low): Call set_breakpoint_data. * gdbserver/linux-low.h (struct linux_target_ops): Add breakpoint handling members. * gdbserver/server.c (attach_inferior): Remove extra add_inferior call. * gdbserver/server.h: Include mem-break.h. Update inferior.c prototypes. * gdbserver/target.c (read_inferior_memory) (write_inferior_memory): New functions. * gdbserver/target.h (read_inferior_memory) (write_inferior_memory): Change macros to prototypes. (struct target_ops): Update comments. Add const to write_memory definition.
Diffstat (limited to 'gdb/gdbserver/linux-low.c')
-rw-r--r--gdb/gdbserver/linux-low.c88
1 files changed, 83 insertions, 5 deletions
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index bd1a876..10966e0 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -35,6 +35,10 @@
#include <stdlib.h>
#include <unistd.h>
+static CORE_ADDR linux_bp_reinsert;
+
+static void linux_resume (int step, int signal);
+
#define PTRACE_ARG3_TYPE long
#define PTRACE_XFER_TYPE long
@@ -46,12 +50,18 @@ extern int errno;
static int inferior_pid;
+struct inferior_linux_data
+{
+ int pid;
+};
+
/* Start an inferior process and returns its pid.
ALLARGS is a vector of program-name and args. */
static int
linux_create_inferior (char *program, char **allargs)
{
+ struct inferior_linux_data *tdata;
int pid;
pid = fork ();
@@ -71,6 +81,10 @@ linux_create_inferior (char *program, char **allargs)
}
add_inferior (pid);
+ tdata = (struct inferior_linux_data *) malloc (sizeof (*tdata));
+ tdata->pid = pid;
+ set_inferior_target_data (current_inferior, tdata);
+
/* FIXME remove */
inferior_pid = pid;
return 0;
@@ -81,6 +95,8 @@ linux_create_inferior (char *program, char **allargs)
static int
linux_attach (int pid)
{
+ struct inferior_linux_data *tdata;
+
if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
{
fprintf (stderr, "Cannot attach to process %d: %s (%d)\n", pid,
@@ -90,6 +106,10 @@ linux_attach (int pid)
_exit (0177);
}
+ add_inferior (pid);
+ tdata = (struct inferior_linux_data *) malloc (sizeof (*tdata));
+ tdata->pid = pid;
+ set_inferior_target_data (current_inferior, tdata);
return 0;
}
@@ -112,19 +132,75 @@ linux_thread_alive (int pid)
return 1;
}
+static int
+linux_wait_for_one_inferior (struct inferior_info *child)
+{
+ struct inferior_linux_data *child_data = inferior_target_data (child);
+ int pid, wstat;
+
+ while (1)
+ {
+ pid = waitpid (child_data->pid, &wstat, 0);
+
+ if (pid != child_data->pid)
+ perror_with_name ("wait");
+
+ /* If this target supports breakpoints, see if we hit one. */
+ if (the_low_target.stop_pc != NULL
+ && WIFSTOPPED (wstat)
+ && WSTOPSIG (wstat) == SIGTRAP)
+ {
+ CORE_ADDR stop_pc;
+
+ if (linux_bp_reinsert != 0)
+ {
+ reinsert_breakpoint (linux_bp_reinsert);
+ linux_bp_reinsert = 0;
+ linux_resume (0, 0);
+ continue;
+ }
+
+ fetch_inferior_registers (0);
+ stop_pc = (*the_low_target.stop_pc) ();
+
+ if (check_breakpoints (stop_pc) != 0)
+ {
+ if (the_low_target.set_pc != NULL)
+ (*the_low_target.set_pc) (stop_pc);
+
+ if (the_low_target.breakpoint_reinsert_addr == NULL)
+ {
+ linux_bp_reinsert = stop_pc;
+ uninsert_breakpoint (stop_pc);
+ linux_resume (1, 0);
+ }
+ else
+ {
+ reinsert_breakpoint_by_bp
+ (stop_pc, (*the_low_target.breakpoint_reinsert_addr) ());
+ linux_resume (0, 0);
+ }
+
+ continue;
+ }
+ }
+
+ return wstat;
+ }
+ /* NOTREACHED */
+ return 0;
+}
+
/* Wait for process, returns status */
static unsigned char
linux_wait (char *status)
{
- int pid;
int w;
enable_async_io ();
- pid = waitpid (inferior_pid, &w, 0);
+ w = linux_wait_for_one_inferior (current_inferior);
disable_async_io ();
- if (pid != inferior_pid)
- perror_with_name ("wait");
if (WIFEXITED (w))
{
@@ -440,7 +516,7 @@ linux_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
returns the value of errno. */
static int
-linux_write_memory (CORE_ADDR memaddr, char *myaddr, int len)
+linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
{
register int i;
/* Round starting address down to longword boundary. */
@@ -508,5 +584,7 @@ void
initialize_low (void)
{
set_target_ops (&linux_target_ops);
+ set_breakpoint_data (the_low_target.breakpoint,
+ the_low_target.breakpoint_len);
init_registers ();
}