198944Sobrien/* <proc_service.h> implementation.
298944Sobrien
398944Sobrien   Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
498944Sobrien
598944Sobrien   This file is part of GDB.
698944Sobrien
798944Sobrien   This program is free software; you can redistribute it and/or modify
898944Sobrien   it under the terms of the GNU General Public License as published by
998944Sobrien   the Free Software Foundation; either version 2 of the License, or
1098944Sobrien   (at your option) any later version.
1198944Sobrien
1298944Sobrien   This program is distributed in the hope that it will be useful,
1398944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1498944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1598944Sobrien   GNU General Public License for more details.
1698944Sobrien
1798944Sobrien   You should have received a copy of the GNU General Public License
1898944Sobrien   along with this program; if not, write to the Free Software
1998944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2098944Sobrien   Boston, MA 02111-1307, USA.  */
2198944Sobrien
2298944Sobrien#include "defs.h"
2398944Sobrien
2498944Sobrien#include "gdb_proc_service.h"
2598944Sobrien#include <sys/procfs.h>
2698944Sobrien
2798944Sobrien#include "inferior.h"
2898944Sobrien#include "symtab.h"
2998944Sobrien#include "target.h"
3098944Sobrien
3198944Sobrien/* Prototypes for supply_gregset etc.  */
3298944Sobrien#include "gregset.h"
3398944Sobrien
3498944Sobrien
3598944Sobrien/* Fix-up some broken systems.  */
3698944Sobrien
3798944Sobrien/* The prototypes in <proc_service.h> are slightly different on older
3898944Sobrien   systems.  Compensate for the discrepancies.  */
3998944Sobrien
4098944Sobrien#ifdef PROC_SERVICE_IS_OLD
4198944Sobrientypedef const struct ps_prochandle *gdb_ps_prochandle_t;
4298944Sobrientypedef char *gdb_ps_read_buf_t;
4398944Sobrientypedef char *gdb_ps_write_buf_t;
4498944Sobrientypedef int gdb_ps_size_t;
4598944Sobrien#else
4698944Sobrientypedef struct ps_prochandle *gdb_ps_prochandle_t;
4798944Sobrientypedef void *gdb_ps_read_buf_t;
4898944Sobrientypedef const void *gdb_ps_write_buf_t;
4998944Sobrientypedef size_t gdb_ps_size_t;
5098944Sobrien#endif
5198944Sobrien
5298944Sobrien
5398944Sobrien/* Building process ids.  */
5498944Sobrien
5598944Sobrien#define BUILD_LWP(lwp, pid)	ptid_build (pid, lwp, 0)
5698944Sobrien
5798944Sobrien
5898944Sobrien/* Helper functions.  */
5998944Sobrien
6098944Sobrien/* Transfer LEN bytes of memory between BUF and address ADDR in the
6198944Sobrien   process specified by PH.  If WRITE, transfer them to the process,
6298944Sobrien   else transfer them from the process.  Returns PS_OK for success,
6398944Sobrien   PS_ERR on failure.
6498944Sobrien
6598944Sobrien   This is a helper function for ps_pdread, ps_pdwrite, ps_ptread and
6698944Sobrien   ps_ptwrite.  */
6798944Sobrien
6898944Sobrienstatic ps_err_e
6998944Sobrienps_xfer_memory (const struct ps_prochandle *ph, paddr_t addr,
7098944Sobrien		char *buf, size_t len, int write)
7198944Sobrien{
7298944Sobrien  struct cleanup *old_chain = save_inferior_ptid ();
7398944Sobrien  int ret;
7498944Sobrien
7598944Sobrien  inferior_ptid = pid_to_ptid (ph->pid);
7698944Sobrien
7798944Sobrien  if (write)
7898944Sobrien    ret = target_write_memory (addr, buf, len);
7998944Sobrien  else
8098944Sobrien    ret = target_read_memory (addr, buf, len);
8198944Sobrien
8298944Sobrien  do_cleanups (old_chain);
8398944Sobrien
8498944Sobrien  return (ret == 0 ? PS_OK : PS_ERR);
8598944Sobrien}
8698944Sobrien
8798944Sobrien
8898944Sobrien/* Stop the target process PH.  */
8998944Sobrien
9098944Sobrienps_err_e
9198944Sobrienps_pstop (gdb_ps_prochandle_t ph)
9298944Sobrien{
9398944Sobrien  /* The process is always stopped when under control of GDB.  */
9498944Sobrien  return PS_OK;
9598944Sobrien}
9698944Sobrien
9798944Sobrien/* Resume the target process PH.  */
9898944Sobrien
9998944Sobrienps_err_e
10098944Sobrienps_pcontinue (gdb_ps_prochandle_t ph)
10198944Sobrien{
10298944Sobrien  /* Pretend we did successfully continue the process.  GDB will take
10398944Sobrien     care of it later on.  */
10498944Sobrien  return PS_OK;
10598944Sobrien}
10698944Sobrien
10798944Sobrien/* Stop the lightweight process LWPID within the target process PH.  */
10898944Sobrien
10998944Sobrienps_err_e
11098944Sobrienps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid)
11198944Sobrien{
11298944Sobrien  /* All lightweight processes are stopped when under control of GDB.  */
11398944Sobrien  return PS_OK;
11498944Sobrien}
11598944Sobrien
11698944Sobrien/* Resume the lightweight process (LWP) LWPID within the target
11798944Sobrien   process PH.  */
11898944Sobrien
11998944Sobrienps_err_e
12098944Sobrienps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid)
12198944Sobrien{
12298944Sobrien  /* Pretend we did successfully continue LWPID.  GDB will take care
12398944Sobrien     of it later on.  */
12498944Sobrien  return PS_OK;
12598944Sobrien}
12698944Sobrien
12798944Sobrien/* Get the size of the architecture-dependent extra state registers
12898944Sobrien   for LWP LWPID within the target process PH and return it in
12998944Sobrien   *XREGSIZE.  */
13098944Sobrien
13198944Sobrienps_err_e
13298944Sobrienps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
13398944Sobrien{
13498944Sobrien  /* FIXME: Not supported yet.  */
13598944Sobrien  return PS_OK;
13698944Sobrien}
13798944Sobrien
13898944Sobrien/* Get the extra state registers of LWP LWPID within the target
13998944Sobrien   process PH and store them in XREGSET.  */
14098944Sobrien
14198944Sobrienps_err_e
14298944Sobrienps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
14398944Sobrien{
14498944Sobrien  /* FIXME: Not supported yet.  */
14598944Sobrien  return PS_OK;
14698944Sobrien}
14798944Sobrien
14898944Sobrien/* Set the extra state registers of LWP LWPID within the target
14998944Sobrien   process PH from XREGSET.  */
15098944Sobrien
15198944Sobrienps_err_e
15298944Sobrienps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
15398944Sobrien{
15498944Sobrien  /* FIXME: Not supported yet.  */
15598944Sobrien  return PS_OK;
15698944Sobrien}
15798944Sobrien
15898944Sobrien/* Log (additional) diognostic information.  */
15998944Sobrien
16098944Sobrienvoid
16198944Sobrienps_plog (const char *fmt, ...)
16298944Sobrien{
16398944Sobrien  va_list args;
16498944Sobrien
16598944Sobrien  va_start (args, fmt);
16698944Sobrien  vfprintf_filtered (gdb_stderr, fmt, args);
16798944Sobrien}
16898944Sobrien
16998944Sobrien/* Search for the symbol named NAME within the object named OBJ within
17098944Sobrien   the target process PH.  If the symbol is found the address of the
17198944Sobrien   symbol is stored in SYM_ADDR.  */
17298944Sobrien
17398944Sobrienps_err_e
17498944Sobrienps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *obj,
17598944Sobrien		   const char *name, paddr_t *sym_addr)
17698944Sobrien{
17798944Sobrien  struct minimal_symbol *ms;
17898944Sobrien
17998944Sobrien  /* FIXME: kettenis/2000-09-03: What should we do with OBJ?  */
18098944Sobrien  ms = lookup_minimal_symbol (name, NULL, NULL);
18198944Sobrien  if (ms == NULL)
18298944Sobrien    return PS_NOSYM;
18398944Sobrien
18498944Sobrien  *sym_addr = SYMBOL_VALUE_ADDRESS (ms);
18598944Sobrien  return PS_OK;
18698944Sobrien}
18798944Sobrien
18898944Sobrien/* Read SIZE bytes from the target process PH at address ADDR and copy
18998944Sobrien   them into BUF.  */
19098944Sobrien
19198944Sobrienps_err_e
19298944Sobrienps_pdread (gdb_ps_prochandle_t ph, paddr_t addr,
19398944Sobrien	   gdb_ps_read_buf_t buf, gdb_ps_size_t size)
19498944Sobrien{
19598944Sobrien  return ps_xfer_memory (ph, addr, buf, size, 0);
19698944Sobrien}
19798944Sobrien
19898944Sobrien/* Write SIZE bytes from BUF into the target process PH at address ADDR.  */
19998944Sobrien
20098944Sobrienps_err_e
20198944Sobrienps_pdwrite (gdb_ps_prochandle_t ph, paddr_t addr,
20298944Sobrien	    gdb_ps_write_buf_t buf, gdb_ps_size_t size)
20398944Sobrien{
20498944Sobrien  return ps_xfer_memory (ph, addr, (char *) buf, size, 1);
20598944Sobrien}
20698944Sobrien
20798944Sobrien/* Read SIZE bytes from the target process PH at address ADDR and copy
20898944Sobrien   them into BUF.  */
20998944Sobrien
21098944Sobrienps_err_e
21198944Sobrienps_ptread (gdb_ps_prochandle_t ph, paddr_t addr,
21298944Sobrien	   gdb_ps_read_buf_t buf, gdb_ps_size_t size)
21398944Sobrien{
21498944Sobrien  return ps_xfer_memory (ph, addr, buf, size, 0);
21598944Sobrien}
21698944Sobrien
21798944Sobrien/* Write SIZE bytes from BUF into the target process PH at address ADDR.  */
21898944Sobrien
21998944Sobrienps_err_e
22098944Sobrienps_ptwrite (gdb_ps_prochandle_t ph, paddr_t addr,
22198944Sobrien	    gdb_ps_write_buf_t buf, gdb_ps_size_t size)
22298944Sobrien{
22398944Sobrien  return ps_xfer_memory (ph, addr, (char *) buf, size, 1);
22498944Sobrien}
22598944Sobrien
22698944Sobrien/* Get the general registers of LWP LWPID within the target process PH
22798944Sobrien   and store them in GREGSET.  */
22898944Sobrien
22998944Sobrienps_err_e
23098944Sobrienps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
23198944Sobrien{
23298944Sobrien  struct cleanup *old_chain = save_inferior_ptid ();
23398944Sobrien
23498944Sobrien  inferior_ptid = BUILD_LWP (lwpid, ph->pid);
23598944Sobrien
23698944Sobrien  target_fetch_registers (-1);
23798944Sobrien  fill_gregset ((gdb_gregset_t *) gregset, -1);
23898944Sobrien
23998944Sobrien  do_cleanups (old_chain);
24098944Sobrien  return PS_OK;
24198944Sobrien}
24298944Sobrien
24398944Sobrien/* Set the general registers of LWP LWPID within the target process PH
24498944Sobrien   from GREGSET.  */
24598944Sobrien
24698944Sobrienps_err_e
24798944Sobrienps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, const prgregset_t gregset)
24898944Sobrien{
24998944Sobrien  struct cleanup *old_chain = save_inferior_ptid ();
25098944Sobrien
25198944Sobrien  inferior_ptid = BUILD_LWP (lwpid, ph->pid);
25298944Sobrien
25398944Sobrien  /* FIXME: We should really make supply_gregset const-correct.  */
25498944Sobrien  supply_gregset ((gdb_gregset_t *) gregset);
25598944Sobrien  target_store_registers (-1);
25698944Sobrien
25798944Sobrien  do_cleanups (old_chain);
25898944Sobrien  return PS_OK;
25998944Sobrien}
26098944Sobrien
26198944Sobrien/* Get the floating-point registers of LWP LWPID within the target
26298944Sobrien   process PH and store them in FPREGSET.  */
26398944Sobrien
26498944Sobrienps_err_e
26598944Sobrienps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
26698944Sobrien	       gdb_prfpregset_t *fpregset)
26798944Sobrien{
26898944Sobrien  struct cleanup *old_chain = save_inferior_ptid ();
26998944Sobrien
27098944Sobrien  inferior_ptid = BUILD_LWP (lwpid, ph->pid);
27198944Sobrien
27298944Sobrien  target_fetch_registers (-1);
27398944Sobrien  fill_fpregset ((gdb_fpregset_t *) fpregset, -1);
27498944Sobrien
27598944Sobrien  do_cleanups (old_chain);
27698944Sobrien  return PS_OK;
27798944Sobrien}
27898944Sobrien
27998944Sobrien/* Set the floating-point registers of LWP LWPID within the target
28098944Sobrien   process PH from FPREGSET.  */
28198944Sobrien
28298944Sobrienps_err_e
28398944Sobrienps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
28498944Sobrien	       const gdb_prfpregset_t *fpregset)
28598944Sobrien{
28698944Sobrien  struct cleanup *old_chain = save_inferior_ptid ();
28798944Sobrien
28898944Sobrien  inferior_ptid = BUILD_LWP (lwpid, ph->pid);
28998944Sobrien
29098944Sobrien  /* FIXME: We should really make supply_fpregset const-correct.  */
29198944Sobrien  supply_fpregset ((gdb_fpregset_t *) fpregset);
29298944Sobrien  target_store_registers (-1);
29398944Sobrien
29498944Sobrien  do_cleanups (old_chain);
29598944Sobrien  return PS_OK;
29698944Sobrien}
29798944Sobrien
29898944Sobrien/* Return overall process id of the target PH.  Special for GNU/Linux
29998944Sobrien   -- not used on Solaris.  */
30098944Sobrien
30198944Sobrienpid_t
30298944Sobrienps_getpid (gdb_ps_prochandle_t ph)
30398944Sobrien{
30498944Sobrien  return ph->pid;
30598944Sobrien}
30698944Sobrien
30798944Sobrienvoid
30898944Sobrien_initialize_proc_service (void)
30998944Sobrien{
31098944Sobrien  /* This function solely exists to make sure this module is linked
31198944Sobrien     into the final binary.  */
31298944Sobrien}
313