* gdbserver/inferiors.c: New file.
* gdbserver/target.c: New file.
* gdbserver/target.h: New file.
* gdbserver/Makefile.in: Add target.o and inferiors.o. Update
dependencies.
* gdbserver/linux-low.c (inferior_pid): New static variable,
moved from server.c.
(linux_create_inferior): Renamed from create_inferior.
Call add_inferior. Return 0 on success instead of a PID.
(linux_attach): Renamed from myattach.
(linux_kill): Renamed from kill_inferior. Call clear_inferiors ().
(linux_thread_alive): Renamed from mythread_alive.
(linux_wait): Renamed from mywait. Call clear_inferiors () if the
child dies.
(linux_resume): Renamed from myresume. Add missing ``return 0''.
(regsets_store_inferior_registers): Correct error message.
Add missing ``return 0''.
(linux_fetch_registers): Renamed from fetch_inferior_registers.
(linux_store_registers): Renamed from store_inferior_registers.
(linux_read_memory): Renamed from read_inferior_memory.
(linux_write_memory): Renamed from write_inferior_memory.
(linux_target_ops): New structure.
(initialize_low): Call set_target_ops ().
* gdbserver/remote-utils.c (unhexify): New function.
(hexify): New function.
(input_interrupt): Send signals to ``signal_pid''.
* gdbserver/server.c (inferior_pid): Remove.
(start_inferior): Update create_inferior call.
(attach_inferior): Call add_inferior.
(handle_query): New function.
(main): Call handle_query for `q' packets.
* gdbserver/server.h: Include "target.h". Remove obsolete prototypes.
Add prototypes for "inferiors.c", "target.c", hexify, and unhexify.
+2002-04-09 Daniel Jacobowitz <drow@mvista.com>
+
+ * gdbserver/inferiors.c: New file.
+ * gdbserver/target.c: New file.
+ * gdbserver/target.h: New file.
+ * gdbserver/Makefile.in: Add target.o and inferiors.o. Update
+ dependencies.
+ * gdbserver/linux-low.c (inferior_pid): New static variable,
+ moved from server.c.
+ (linux_create_inferior): Renamed from create_inferior.
+ Call add_inferior. Return 0 on success instead of a PID.
+ (linux_attach): Renamed from myattach.
+ (linux_kill): Renamed from kill_inferior. Call clear_inferiors ().
+ (linux_thread_alive): Renamed from mythread_alive.
+ (linux_wait): Renamed from mywait. Call clear_inferiors () if the
+ child dies.
+ (linux_resume): Renamed from myresume. Add missing ``return 0''.
+ (regsets_store_inferior_registers): Correct error message.
+ Add missing ``return 0''.
+ (linux_fetch_registers): Renamed from fetch_inferior_registers.
+ (linux_store_registers): Renamed from store_inferior_registers.
+ (linux_read_memory): Renamed from read_inferior_memory.
+ (linux_write_memory): Renamed from write_inferior_memory.
+ (linux_target_ops): New structure.
+ (initialize_low): Call set_target_ops ().
+ * gdbserver/remote-utils.c (unhexify): New function.
+ (hexify): New function.
+ (input_interrupt): Send signals to ``signal_pid''.
+ * gdbserver/server.c (inferior_pid): Remove.
+ (start_inferior): Update create_inferior call.
+ (attach_inferior): Call add_inferior.
+ (handle_query): New function.
+ (main): Call handle_query for `q' packets.
+ * gdbserver/server.h: Include "target.h". Remove obsolete prototypes.
+ Add prototypes for "inferiors.c", "target.c", hexify, and unhexify.
+
2002-04-09 Daniel Jacobowitz <drow@mvista.com>
* gdbserver/Makefile.in: Add WARN_CFLAGS. Update configury
SOURCES = $(SFILES)
TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
-OBS = utils.o $(DEPFILES) server.o remote-utils.o regcache.o signals.o
+OBS = inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
+ utils.o \
+ $(DEPFILES)
# Prevent Sun make from putting in the machine type. Setting
# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
regdat_sh = $(srcdir)/../regformats/regdat.sh
regdef_h = $(srcdir)/../regformats/regdef.h
regcache_h = $(srcdir)/regcache.h
-server_h = $(srcdir)/server.h $(regcache_h) config.h
+server_h = $(srcdir)/server.h $(regcache_h) config.h $(srcdir)/target.h
-server.o: server.c $(server_h)
+inferiors.o: inferiors.c $(server_h)
+regcache.o: regcache.c $(server_h) $(regdef_h)
remote-utils.o: remote-utils.c terminal.h $(server_h)
+server.o: server.c $(server_h)
+target.o: target.c $(server_h)
utils.o: utils.c $(server_h)
-regcache.o: regcache.c $(server_h) $(regdef_h)
signals.o: ../signals/signals.c $(server_h)
$(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER
--- /dev/null
+/* Inferior process information for the remote server for GDB.
+ Copyright 2002
+ Free Software Foundation, Inc.
+
+ Contributed by MontaVista Software.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdlib.h>
+
+#include "server.h"
+
+struct inferior_info
+{
+ int pid;
+ struct inferior_info *next;
+};
+
+static struct inferior_info *inferiors;
+struct inferior_info *current_inferior;
+int signal_pid;
+
+void
+add_inferior (int pid)
+{
+ struct inferior_info *new_inferior
+ = (struct inferior_info *) malloc (sizeof (*new_inferior));
+
+ memset (new_inferior, 0, sizeof (*new_inferior));
+
+ new_inferior->pid = pid;
+
+ new_inferior->next = inferiors;
+ inferiors = new_inferior;
+
+ if (current_inferior == NULL)
+ current_inferior = inferiors;
+
+ if (signal_pid == 0)
+ signal_pid = pid;
+}
+
+void
+clear_inferiors (void)
+{
+ struct inferior_info *inf = inferiors, *next_inf;
+
+ while (inf)
+ {
+ next_inf = inf->next;
+ free (inf);
+ inf = next_inf;
+ }
+
+ inferiors = NULL;
+}
extern int regmap[];
#endif
+static int inferior_pid;
+
/* Start an inferior process and returns its pid.
ALLARGS is a vector of program-name and args. */
-int
-create_inferior (char *program, char **allargs)
+static int
+linux_create_inferior (char *program, char **allargs)
{
int pid;
_exit (0177);
}
- return pid;
+ add_inferior (pid);
+ /* FIXME remove */
+ inferior_pid = pid;
+ return 0;
}
/* Attach to an inferior process. */
-int
-myattach (int pid)
+static int
+linux_attach (int pid)
{
if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
{
/* Kill the inferior process. Make us have no inferior. */
-void
-kill_inferior (void)
+static void
+linux_kill (void)
{
if (inferior_pid == 0)
return;
ptrace (PTRACE_KILL, inferior_pid, 0, 0);
wait (0);
+ clear_inferiors ();
}
/* Return nonzero if the given thread is still alive. */
-int
-mythread_alive (int pid)
+static int
+linux_thread_alive (int pid)
{
return 1;
}
/* Wait for process, returns status */
-unsigned char
-mywait (char *status)
+static unsigned char
+linux_wait (char *status)
{
int pid;
int w;
{
fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
*status = 'W';
+ clear_inferiors ();
return ((unsigned char) WEXITSTATUS (w));
}
else if (!WIFSTOPPED (w))
{
fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+ clear_inferiors ();
*status = 'X';
return ((unsigned char) WTERMSIG (w));
}
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
-void
-myresume (int step, int signal)
+static void
+linux_resume (int step, int signal)
{
errno = 0;
ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
regset->store_function (buf);
regset ++;
}
+ return 0;
}
static int
}
else
{
- perror ("Warning: ptrace(regsets_fetch_inferior_registers)");
+ perror ("Warning: ptrace(regsets_store_inferior_registers)");
}
}
regset ++;
}
+ return 0;
}
#endif /* HAVE_LINUX_REGSETS */
void
-fetch_inferior_registers (int regno)
+linux_fetch_registers (int regno)
{
#ifdef HAVE_LINUX_REGSETS
if (use_regsets_p)
}
void
-store_inferior_registers (int regno)
+linux_store_registers (int regno)
{
#ifdef HAVE_LINUX_REGSETS
if (use_regsets_p)
/* Copy LEN bytes from inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR. */
-void
-read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
+static void
+linux_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
register int i;
/* Round starting address down to longword boundary. */
On failure (cannot write the inferior)
returns the value of errno. */
-int
-write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
+static int
+linux_write_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
register int i;
/* Round starting address down to longword boundary. */
return 0;
}
\f
+static struct target_ops linux_target_ops = {
+ linux_create_inferior,
+ linux_attach,
+ linux_kill,
+ linux_thread_alive,
+ linux_resume,
+ linux_wait,
+ linux_fetch_registers,
+ linux_store_registers,
+ linux_read_memory,
+ linux_write_memory,
+};
+
void
initialize_low (void)
{
+ set_target_ops (&linux_target_ops);
init_registers ();
}
return 0;
}
+int
+unhexify (char *bin, const char *hex, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ if (hex[0] == 0 || hex[1] == 0)
+ {
+ /* Hex string is short, or of uneven length.
+ Return the count that has been converted so far. */
+ return i;
+ }
+ *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]);
+ hex += 2;
+ }
+ return i;
+}
+
/* Convert number NIB to a hex digit. */
static int
return 'a' + nib - 10;
}
+int
+hexify (char *hex, const char *bin, int count)
+{
+ int i;
+
+ /* May use a length, or a nul-terminated string as input. */
+ if (count == 0)
+ count = strlen (bin);
+
+ for (i = 0; i < count; i++)
+ {
+ *hex++ = tohex ((*bin >> 4) & 0xf);
+ *hex++ = tohex (*bin++ & 0xf);
+ }
+ *hex = 0;
+ return i;
+}
+
/* Send a packet to the remote machine, with error checking.
The data of the packet is in BUF. Returns >= 0 on success, -1 otherwise. */
return;
}
- kill (inferior_pid, SIGINT);
+ kill (signal_pid, SIGINT);
}
}
int old_thread_from_wait;
int extended_protocol;
jmp_buf toplevel;
-int inferior_pid;
static unsigned char
start_inferior (char *argv[], char *statusptr)
{
- inferior_pid = create_inferior (argv[0], argv);
- fprintf (stderr, "Process %s created; pid = %d\n", argv[0], inferior_pid);
+ /* FIXME Check error? Or turn to void. */
+ create_inferior (argv[0], argv);
+ /* FIXME Print pid properly. */
+ fprintf (stderr, "Process %s created; pid = %d\n", argv[0], signal_pid);
/* Wait till we are at 1st instruction in program, return signal number. */
return mywait (statusptr);
if (myattach (pid) != 0)
return -1;
- inferior_pid = pid;
+ add_inferior (pid);
*sigptr = mywait (statusptr);
}
extern int remote_debug;
+
+/* Handle all of the extended 'q' packets. */
+void
+handle_query (char *own_buf)
+{
+ if (strcmp ("qSymbol::", own_buf) == 0)
+ {
+#if 0
+ strcpy (own_buf, "qSymbol:");
+ hexify (own_buf + strlen ("qSymbol:"), "main", 4);
+ putpkt (own_buf);
+ getpkt (own_buf);
+ fprintf (stderr, "Got %s", own_buf);
+#endif
+ strcpy (own_buf, "OK");
+ return;
+ }
+
+ /* Otherwise we didn't know what packet it was. Say we didn't
+ understand it. */
+ own_buf[0] = 0;
+}
+
static int attached;
int
ch = own_buf[i++];
switch (ch)
{
+ case 'q':
+ handle_query (own_buf);
+ break;
case 'd':
remote_debug = !remote_debug;
break;
#include "regcache.h"
#include "gdb/signals.h"
+#include "target.h"
/* Target-specific functions */
-int create_inferior (char *program, char **allargs);
-void kill_inferior (void);
-void fetch_inferior_registers (int regno);
-void store_inferior_registers (int regno);
-int mythread_alive (int pid);
-void myresume (int step, int signo);
-unsigned char mywait (char *status);
-void read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len);
-int write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len);
-int create_inferior ();
void initialize_low ();
/* Target-specific variables */
extern char *registers;
+/* From inferiors.c. */
+
+struct inferior_info;
+extern struct inferior_info *current_inferior;
+extern int signal_pid;
+void add_inferior (int pid);
+void clear_inferiors (void);
+
/* Public variables in server.c */
extern int cont_thread;
extern int old_thread_from_wait;
extern jmp_buf toplevel;
-extern int inferior_pid;
/* Functions from remote-utils.c */
void decode_M_packet (char *from, CORE_ADDR * mem_addr_ptr,
unsigned int *len_ptr, char *to);
+int unhexify (char *bin, const char *hex, int count);
+int hexify (char *hex, const char *bin, int count);
+
+
/* Functions from ``signals.c''. */
enum target_signal target_signal_from_host (int hostsig);
int target_signal_to_host_p (enum target_signal oursig);
--- /dev/null
+/* Target operations for the remote server for GDB.
+ Copyright 2002
+ Free Software Foundation, Inc.
+
+ Contributed by MontaVista Software.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "server.h"
+
+struct target_ops *the_target;
+
+void
+set_target_ops (struct target_ops *target)
+{
+ the_target = (struct target_ops *) malloc (sizeof (*the_target));
+ memcpy (the_target, target, sizeof (*the_target));
+}
--- /dev/null
+/* Target operations for the remote server for GDB.
+ Copyright 2002
+ Free Software Foundation, Inc.
+
+ Contributed by MontaVista Software.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TARGET_H
+#define TARGET_H
+
+struct target_ops
+{
+ /* Start a new process.
+
+ PROGRAM is a path to the program to execute.
+ ARGS is a standard NULL-terminated array of arguments,
+ to be passed to the inferior as ``argv''.
+
+ Returns 0 on success, -1 on failure. Registers the new
+ process with the process list. */
+
+ int (*create_inferior) (char *program, char **args);
+
+ /* Attach to a running process.
+
+ PID is the process ID to attach to, specified by the user
+ or a higher layer. */
+
+ int (*attach) (int pid);
+
+ /* Kill all inferiors. */
+
+ void (*kill) (void);
+
+ /* Return 1 iff the thread with process ID PID is alive. */
+
+ int (*thread_alive) (int pid);
+
+ /* Resume the inferior process.
+
+ If STEP is non-zero, we want to single-step.
+
+ If SIGNAL is nonzero, send the process that signal as we resume it.
+ */
+
+ void (*resume) (int step, int signo);
+
+ /* Wait for the inferior process to change state.
+
+ STATUSP will be filled in with a response code to send to GDB.
+
+ Returns the signal which caused the process to stop. */
+
+ unsigned char (*wait) (char *status);
+
+ /* Fetch registers from the inferior process.
+
+ If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO. */
+
+ void (*fetch_registers) (int regno);
+
+ /* Store registers to the inferior process.
+
+ If REGNO is -1, store all registers; otherwise, store at least REGNO. */
+
+ void (*store_registers) (int regno);
+
+ /* Read memory from the inferior process.
+
+ Read LEN bytes at MEMADDR into a buffer at MYADDR. */
+
+ void (*read_memory) (CORE_ADDR memaddr, char *myaddr, int len);
+
+ /* Write memory to the inferior process.
+
+ Write LEN bytes from the buffer at MYADDR to MEMADDR.
+
+ Returns 0 on success and errno on failure. */
+
+ int (*write_memory) (CORE_ADDR memaddr, char *myaddr, int len);
+};
+
+extern struct target_ops *the_target;
+
+void set_target_ops (struct target_ops *);
+
+#define create_inferior(program, args) \
+ (*the_target->create_inferior) (program, args)
+
+#define myattach(pid) \
+ (*the_target->attach) (pid)
+
+#define kill_inferior() \
+ (*the_target->kill) ()
+
+#define mythread_alive(pid) \
+ (*the_target->thread_alive) (pid)
+
+#define myresume(step,signo) \
+ (*the_target->resume) (step, signo)
+
+#define mywait(statusp) \
+ (*the_target->wait) (statusp)
+
+#define fetch_inferior_registers(regno) \
+ (*the_target->fetch_registers) (regno)
+
+#define store_inferior_registers(regno) \
+ (*the_target->store_registers) (regno)
+
+#define read_inferior_memory(memaddr,myaddr,len) \
+ (*the_target->read_memory) (memaddr, myaddr, len)
+
+#define write_inferior_memory(memaddr,myaddr,len) \
+ (*the_target->write_memory) (memaddr, myaddr, len)
+
+#endif /* TARGET_H */