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