aboutsummaryrefslogtreecommitdiff
path: root/gdb/proc-service.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/proc-service.c')
-rw-r--r--gdb/proc-service.c333
1 files changed, 333 insertions, 0 deletions
diff --git a/gdb/proc-service.c b/gdb/proc-service.c
new file mode 100644
index 0000000..b69207e
--- /dev/null
+++ b/gdb/proc-service.c
@@ -0,0 +1,333 @@
+/* <proc_service.h> implementation.
+ Copyright 1999, 2000 Free Software Foundation, Inc.
+
+ 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 "defs.h"
+
+#include "gdb_proc_service.h"
+#include <sys/procfs.h>
+
+#include "inferior.h"
+#include "symtab.h"
+#include "target.h"
+
+/* Prototypes for supply_gregset etc. */
+#include "gregset.h"
+
+
+/* Fix-up some broken systems. */
+
+/* The prototypes in <proc_service.h> are slightly different on older
+ systems. Compensate for the discrepancies. */
+
+#ifdef PROC_SERVICE_IS_OLD
+typedef const struct ps_prochandle *gdb_ps_prochandle_t;
+typedef char *gdb_ps_read_buf_t;
+typedef char *gdb_ps_write_buf_t;
+typedef int gdb_ps_size_t;
+#else
+typedef struct ps_prochandle *gdb_ps_prochandle_t;
+typedef void *gdb_ps_read_buf_t;
+typedef const void *gdb_ps_write_buf_t;
+typedef size_t gdb_ps_size_t;
+#endif
+
+
+/* Building process ids. */
+
+#ifndef MERGEPID
+#define MERGEPID(PID, TID) (((PID) & 0xffff) | ((TID) << 16))
+#endif
+
+#define BUILD_LWP(tid, pid) MERGEPID (pid, tid)
+
+
+/* Helper functions. */
+
+static void
+restore_inferior_pid (void *arg)
+{
+ int *saved_pid_ptr = arg;
+ inferior_pid = *saved_pid_ptr;
+ free (arg);
+}
+
+static struct cleanup *
+save_inferior_pid (void)
+{
+ int *saved_pid_ptr;
+
+ saved_pid_ptr = xmalloc (sizeof (int));
+ *saved_pid_ptr = inferior_pid;
+ return make_cleanup (restore_inferior_pid, saved_pid_ptr);
+}
+
+/* Transfer LEN bytes of memory between BUF and address ADDR in the
+ process specified by PH. If WRITE, transfer them to the process,
+ else transfer them from the process. Returns PS_OK for success,
+ PS_ERR on failure.
+
+ This is a helper function for ps_pdread, ps_pdwrite, ps_ptread and
+ ps_ptwrite. */
+
+static ps_err_e
+ps_xfer_memory (const struct ps_prochandle *ph, paddr_t addr,
+ char *buf, size_t len, int write)
+{
+ struct cleanup *old_chain = save_inferior_pid ();
+ int ret;
+
+ inferior_pid = ph->pid;
+
+ if (write)
+ ret = target_write_memory (addr, buf, len);
+ else
+ ret = target_read_memory (addr, buf, len);
+
+ do_cleanups (old_chain);
+
+ return (ret == 0 ? PS_OK : PS_ERR);
+}
+
+
+/* Stop the target process PH. */
+
+ps_err_e
+ps_pstop (gdb_ps_prochandle_t ph)
+{
+ /* The process is always stopped when under control of GDB. */
+ return PS_OK;
+}
+
+/* Resume the target process PH. */
+
+ps_err_e
+ps_pcontinue (gdb_ps_prochandle_t ph)
+{
+ /* Pretend we did successfully continue the process. GDB will take
+ care of it later on. */
+ return PS_OK;
+}
+
+/* Stop the lightweight process LWPID within the target process PH. */
+
+ps_err_e
+ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid)
+{
+ /* All lightweight processes are stopped when under control of GDB. */
+ return PS_OK;
+}
+
+/* Resume the lightweight process (LWP) LWPID within the target
+ process PH. */
+
+ps_err_e
+ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid)
+{
+ /* Pretend we did successfully continue LWPID. GDB will take care
+ of it later on. */
+ return PS_OK;
+}
+
+/* Get the size of the architecture-dependent extra state registers
+ for LWP LWPID within the target process PH and return it in
+ *XREGSIZE. */
+
+ps_err_e
+ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
+{
+ /* FIXME: Not supported yet. */
+ return PS_OK;
+}
+
+/* Get the extra state registers of LWP LWPID within the target
+ process PH and store them in XREGSET. */
+
+ps_err_e
+ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
+{
+ /* FIXME: Not supported yet. */
+ return PS_OK;
+}
+
+/* Set the extra state registers of LWP LWPID within the target
+ process PH from XREGSET. */
+
+ps_err_e
+ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
+{
+ /* FIXME: Not supported yet. */
+ return PS_OK;
+}
+
+/* Log (additional) diognostic information. */
+
+void
+ps_plog (const char *fmt, ...)
+{
+ va_list args;
+
+ va_start (args, fmt);
+ vfprintf_filtered (gdb_stderr, fmt, args);
+}
+
+/* Search for the symbol named NAME within the object named OBJ within
+ the target process PH. If the symbol is found the address of the
+ symbol is stored in SYM_ADDR. */
+
+ps_err_e
+ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *obj,
+ const char *name, paddr_t *sym_addr)
+{
+ struct minimal_symbol *ms;
+
+ /* FIXME: kettenis/2000-09-03: What should we do with OBJ? */
+ ms = lookup_minimal_symbol (name, NULL, NULL);
+ if (ms == NULL)
+ return PS_NOSYM;
+
+ *sym_addr = SYMBOL_VALUE_ADDRESS (ms);
+ return PS_OK;
+}
+
+/* Read SIZE bytes from the target process PH at address ADDR and copy
+ them into BUF. */
+
+ps_err_e
+ps_pdread (gdb_ps_prochandle_t ph, paddr_t addr,
+ gdb_ps_read_buf_t buf, gdb_ps_size_t size)
+{
+ return ps_xfer_memory (ph, addr, buf, size, 0);
+}
+
+/* Write SIZE bytes from BUF into the target process PH at address ADDR. */
+
+ps_err_e
+ps_pdwrite (gdb_ps_prochandle_t ph, paddr_t addr,
+ gdb_ps_write_buf_t buf, gdb_ps_size_t size)
+{
+ return ps_xfer_memory (ph, addr, (char *) buf, size, 1);
+}
+
+/* Read SIZE bytes from the target process PH at address ADDR and copy
+ them into BUF. */
+
+ps_err_e
+ps_ptread (gdb_ps_prochandle_t ph, paddr_t addr,
+ gdb_ps_read_buf_t buf, gdb_ps_size_t size)
+{
+ return ps_xfer_memory (ph, addr, buf, size, 0);
+}
+
+/* Write SIZE bytes from BUF into the target process PH at address ADDR. */
+
+ps_err_e
+ps_ptwrite (gdb_ps_prochandle_t ph, paddr_t addr,
+ gdb_ps_write_buf_t buf, gdb_ps_size_t size)
+{
+ return ps_xfer_memory (ph, addr, (char *) buf, size, 1);
+}
+
+/* Get the general registers of LWP LWPID within the target process PH
+ and store them in GREGSET. */
+
+ps_err_e
+ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
+{
+ struct cleanup *old_chain = save_inferior_pid ();
+
+ inferior_pid = BUILD_LWP (lwpid, ph->pid);
+
+ target_fetch_registers (-1);
+ fill_gregset ((gdb_gregset_t *) gregset, -1);
+
+ do_cleanups (old_chain);
+ return PS_OK;
+}
+
+/* Set the general registers of LWP LWPID within the target process PH
+ from GREGSET. */
+
+ps_err_e
+ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, const prgregset_t gregset)
+{
+ struct cleanup *old_chain = save_inferior_pid ();
+
+ inferior_pid = BUILD_LWP (lwpid, ph->pid);
+
+ /* FIXME: We should really make supply_gregset const-correct. */
+ supply_gregset ((gdb_gregset_t *) gregset);
+ target_store_registers (-1);
+
+ do_cleanups (old_chain);
+ return PS_OK;
+}
+
+/* Get the floating-point registers of LWP LWPID within the target
+ process PH and store them in FPREGSET. */
+
+ps_err_e
+ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
+ gdb_prfpregset_t *fpregset)
+{
+ struct cleanup *old_chain = save_inferior_pid ();
+
+ inferior_pid = BUILD_LWP (lwpid, ph->pid);
+
+ target_fetch_registers (-1);
+ fill_fpregset ((gdb_fpregset_t *) fpregset, -1);
+
+ do_cleanups (old_chain);
+ return PS_OK;
+}
+
+/* Set the floating-point registers of LWP LWPID within the target
+ process PH from FPREGSET. */
+
+ps_err_e
+ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
+ const gdb_prfpregset_t *fpregset)
+{
+ struct cleanup *old_chain = save_inferior_pid ();
+
+ inferior_pid = BUILD_LWP (lwpid, ph->pid);
+
+ /* FIXME: We should really make supply_fpregset const-correct. */
+ supply_fpregset ((gdb_fpregset_t *) fpregset);
+ target_store_registers (-1);
+
+ do_cleanups (old_chain);
+ return PS_OK;
+}
+
+/* Return overall process id of the target PH.
+ Special for Linux -- not used on Solaris. */
+
+pid_t
+ps_getpid (gdb_ps_prochandle_t ph)
+{
+ return ph->pid;
+}
+
+void
+_initialize_proc_service (void)
+{
+ /* This function solely exists to make sure this module is linked
+ into the final binary. */
+}