1*b725ae77Skettenis /* <proc_service.h> implementation.
2*b725ae77Skettenis
3*b725ae77Skettenis Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
4*b725ae77Skettenis
5*b725ae77Skettenis This file is part of GDB.
6*b725ae77Skettenis
7*b725ae77Skettenis This program is free software; you can redistribute it and/or modify
8*b725ae77Skettenis it under the terms of the GNU General Public License as published by
9*b725ae77Skettenis the Free Software Foundation; either version 2 of the License, or
10*b725ae77Skettenis (at your option) any later version.
11*b725ae77Skettenis
12*b725ae77Skettenis This program is distributed in the hope that it will be useful,
13*b725ae77Skettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
14*b725ae77Skettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*b725ae77Skettenis GNU General Public License for more details.
16*b725ae77Skettenis
17*b725ae77Skettenis You should have received a copy of the GNU General Public License
18*b725ae77Skettenis along with this program; if not, write to the Free Software
19*b725ae77Skettenis Foundation, Inc., 59 Temple Place - Suite 330,
20*b725ae77Skettenis Boston, MA 02111-1307, USA. */
21*b725ae77Skettenis
22*b725ae77Skettenis #include "defs.h"
23*b725ae77Skettenis
24*b725ae77Skettenis #include "gdb_proc_service.h"
25*b725ae77Skettenis #include <sys/procfs.h>
26*b725ae77Skettenis
27*b725ae77Skettenis #include "inferior.h"
28*b725ae77Skettenis #include "symtab.h"
29*b725ae77Skettenis #include "target.h"
30*b725ae77Skettenis
31*b725ae77Skettenis /* Prototypes for supply_gregset etc. */
32*b725ae77Skettenis #include "gregset.h"
33*b725ae77Skettenis
34*b725ae77Skettenis
35*b725ae77Skettenis /* Fix-up some broken systems. */
36*b725ae77Skettenis
37*b725ae77Skettenis /* The prototypes in <proc_service.h> are slightly different on older
38*b725ae77Skettenis systems. Compensate for the discrepancies. */
39*b725ae77Skettenis
40*b725ae77Skettenis #ifdef PROC_SERVICE_IS_OLD
41*b725ae77Skettenis typedef const struct ps_prochandle *gdb_ps_prochandle_t;
42*b725ae77Skettenis typedef char *gdb_ps_read_buf_t;
43*b725ae77Skettenis typedef char *gdb_ps_write_buf_t;
44*b725ae77Skettenis typedef int gdb_ps_size_t;
45*b725ae77Skettenis #else
46*b725ae77Skettenis typedef struct ps_prochandle *gdb_ps_prochandle_t;
47*b725ae77Skettenis typedef void *gdb_ps_read_buf_t;
48*b725ae77Skettenis typedef const void *gdb_ps_write_buf_t;
49*b725ae77Skettenis typedef size_t gdb_ps_size_t;
50*b725ae77Skettenis #endif
51*b725ae77Skettenis
52*b725ae77Skettenis
53*b725ae77Skettenis /* Building process ids. */
54*b725ae77Skettenis
55*b725ae77Skettenis #define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0)
56*b725ae77Skettenis
57*b725ae77Skettenis
58*b725ae77Skettenis /* Helper functions. */
59*b725ae77Skettenis
60*b725ae77Skettenis /* Transfer LEN bytes of memory between BUF and address ADDR in the
61*b725ae77Skettenis process specified by PH. If WRITE, transfer them to the process,
62*b725ae77Skettenis else transfer them from the process. Returns PS_OK for success,
63*b725ae77Skettenis PS_ERR on failure.
64*b725ae77Skettenis
65*b725ae77Skettenis This is a helper function for ps_pdread, ps_pdwrite, ps_ptread and
66*b725ae77Skettenis ps_ptwrite. */
67*b725ae77Skettenis
68*b725ae77Skettenis static ps_err_e
ps_xfer_memory(const struct ps_prochandle * ph,paddr_t addr,char * buf,size_t len,int write)69*b725ae77Skettenis ps_xfer_memory (const struct ps_prochandle *ph, paddr_t addr,
70*b725ae77Skettenis char *buf, size_t len, int write)
71*b725ae77Skettenis {
72*b725ae77Skettenis struct cleanup *old_chain = save_inferior_ptid ();
73*b725ae77Skettenis int ret;
74*b725ae77Skettenis
75*b725ae77Skettenis inferior_ptid = pid_to_ptid (ph->pid);
76*b725ae77Skettenis
77*b725ae77Skettenis if (write)
78*b725ae77Skettenis ret = target_write_memory (addr, buf, len);
79*b725ae77Skettenis else
80*b725ae77Skettenis ret = target_read_memory (addr, buf, len);
81*b725ae77Skettenis
82*b725ae77Skettenis do_cleanups (old_chain);
83*b725ae77Skettenis
84*b725ae77Skettenis return (ret == 0 ? PS_OK : PS_ERR);
85*b725ae77Skettenis }
86*b725ae77Skettenis
87*b725ae77Skettenis
88*b725ae77Skettenis /* Stop the target process PH. */
89*b725ae77Skettenis
90*b725ae77Skettenis ps_err_e
ps_pstop(gdb_ps_prochandle_t ph)91*b725ae77Skettenis ps_pstop (gdb_ps_prochandle_t ph)
92*b725ae77Skettenis {
93*b725ae77Skettenis /* The process is always stopped when under control of GDB. */
94*b725ae77Skettenis return PS_OK;
95*b725ae77Skettenis }
96*b725ae77Skettenis
97*b725ae77Skettenis /* Resume the target process PH. */
98*b725ae77Skettenis
99*b725ae77Skettenis ps_err_e
ps_pcontinue(gdb_ps_prochandle_t ph)100*b725ae77Skettenis ps_pcontinue (gdb_ps_prochandle_t ph)
101*b725ae77Skettenis {
102*b725ae77Skettenis /* Pretend we did successfully continue the process. GDB will take
103*b725ae77Skettenis care of it later on. */
104*b725ae77Skettenis return PS_OK;
105*b725ae77Skettenis }
106*b725ae77Skettenis
107*b725ae77Skettenis /* Stop the lightweight process LWPID within the target process PH. */
108*b725ae77Skettenis
109*b725ae77Skettenis ps_err_e
ps_lstop(gdb_ps_prochandle_t ph,lwpid_t lwpid)110*b725ae77Skettenis ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid)
111*b725ae77Skettenis {
112*b725ae77Skettenis /* All lightweight processes are stopped when under control of GDB. */
113*b725ae77Skettenis return PS_OK;
114*b725ae77Skettenis }
115*b725ae77Skettenis
116*b725ae77Skettenis /* Resume the lightweight process (LWP) LWPID within the target
117*b725ae77Skettenis process PH. */
118*b725ae77Skettenis
119*b725ae77Skettenis ps_err_e
ps_lcontinue(gdb_ps_prochandle_t ph,lwpid_t lwpid)120*b725ae77Skettenis ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid)
121*b725ae77Skettenis {
122*b725ae77Skettenis /* Pretend we did successfully continue LWPID. GDB will take care
123*b725ae77Skettenis of it later on. */
124*b725ae77Skettenis return PS_OK;
125*b725ae77Skettenis }
126*b725ae77Skettenis
127*b725ae77Skettenis /* Get the size of the architecture-dependent extra state registers
128*b725ae77Skettenis for LWP LWPID within the target process PH and return it in
129*b725ae77Skettenis *XREGSIZE. */
130*b725ae77Skettenis
131*b725ae77Skettenis ps_err_e
ps_lgetxregsize(gdb_ps_prochandle_t ph,lwpid_t lwpid,int * xregsize)132*b725ae77Skettenis ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
133*b725ae77Skettenis {
134*b725ae77Skettenis /* FIXME: Not supported yet. */
135*b725ae77Skettenis return PS_OK;
136*b725ae77Skettenis }
137*b725ae77Skettenis
138*b725ae77Skettenis /* Get the extra state registers of LWP LWPID within the target
139*b725ae77Skettenis process PH and store them in XREGSET. */
140*b725ae77Skettenis
141*b725ae77Skettenis ps_err_e
ps_lgetxregs(gdb_ps_prochandle_t ph,lwpid_t lwpid,caddr_t xregset)142*b725ae77Skettenis ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
143*b725ae77Skettenis {
144*b725ae77Skettenis /* FIXME: Not supported yet. */
145*b725ae77Skettenis return PS_OK;
146*b725ae77Skettenis }
147*b725ae77Skettenis
148*b725ae77Skettenis /* Set the extra state registers of LWP LWPID within the target
149*b725ae77Skettenis process PH from XREGSET. */
150*b725ae77Skettenis
151*b725ae77Skettenis ps_err_e
ps_lsetxregs(gdb_ps_prochandle_t ph,lwpid_t lwpid,caddr_t xregset)152*b725ae77Skettenis ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
153*b725ae77Skettenis {
154*b725ae77Skettenis /* FIXME: Not supported yet. */
155*b725ae77Skettenis return PS_OK;
156*b725ae77Skettenis }
157*b725ae77Skettenis
158*b725ae77Skettenis /* Log (additional) diognostic information. */
159*b725ae77Skettenis
160*b725ae77Skettenis void
ps_plog(const char * fmt,...)161*b725ae77Skettenis ps_plog (const char *fmt, ...)
162*b725ae77Skettenis {
163*b725ae77Skettenis va_list args;
164*b725ae77Skettenis
165*b725ae77Skettenis va_start (args, fmt);
166*b725ae77Skettenis vfprintf_filtered (gdb_stderr, fmt, args);
167*b725ae77Skettenis }
168*b725ae77Skettenis
169*b725ae77Skettenis /* Search for the symbol named NAME within the object named OBJ within
170*b725ae77Skettenis the target process PH. If the symbol is found the address of the
171*b725ae77Skettenis symbol is stored in SYM_ADDR. */
172*b725ae77Skettenis
173*b725ae77Skettenis ps_err_e
ps_pglobal_lookup(gdb_ps_prochandle_t ph,const char * obj,const char * name,paddr_t * sym_addr)174*b725ae77Skettenis ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *obj,
175*b725ae77Skettenis const char *name, paddr_t *sym_addr)
176*b725ae77Skettenis {
177*b725ae77Skettenis struct minimal_symbol *ms;
178*b725ae77Skettenis
179*b725ae77Skettenis /* FIXME: kettenis/2000-09-03: What should we do with OBJ? */
180*b725ae77Skettenis ms = lookup_minimal_symbol (name, NULL, NULL);
181*b725ae77Skettenis if (ms == NULL)
182*b725ae77Skettenis return PS_NOSYM;
183*b725ae77Skettenis
184*b725ae77Skettenis *sym_addr = SYMBOL_VALUE_ADDRESS (ms);
185*b725ae77Skettenis return PS_OK;
186*b725ae77Skettenis }
187*b725ae77Skettenis
188*b725ae77Skettenis /* Read SIZE bytes from the target process PH at address ADDR and copy
189*b725ae77Skettenis them into BUF. */
190*b725ae77Skettenis
191*b725ae77Skettenis ps_err_e
ps_pdread(gdb_ps_prochandle_t ph,paddr_t addr,gdb_ps_read_buf_t buf,gdb_ps_size_t size)192*b725ae77Skettenis ps_pdread (gdb_ps_prochandle_t ph, paddr_t addr,
193*b725ae77Skettenis gdb_ps_read_buf_t buf, gdb_ps_size_t size)
194*b725ae77Skettenis {
195*b725ae77Skettenis return ps_xfer_memory (ph, addr, buf, size, 0);
196*b725ae77Skettenis }
197*b725ae77Skettenis
198*b725ae77Skettenis /* Write SIZE bytes from BUF into the target process PH at address ADDR. */
199*b725ae77Skettenis
200*b725ae77Skettenis ps_err_e
ps_pdwrite(gdb_ps_prochandle_t ph,paddr_t addr,gdb_ps_write_buf_t buf,gdb_ps_size_t size)201*b725ae77Skettenis ps_pdwrite (gdb_ps_prochandle_t ph, paddr_t addr,
202*b725ae77Skettenis gdb_ps_write_buf_t buf, gdb_ps_size_t size)
203*b725ae77Skettenis {
204*b725ae77Skettenis return ps_xfer_memory (ph, addr, (char *) buf, size, 1);
205*b725ae77Skettenis }
206*b725ae77Skettenis
207*b725ae77Skettenis /* Read SIZE bytes from the target process PH at address ADDR and copy
208*b725ae77Skettenis them into BUF. */
209*b725ae77Skettenis
210*b725ae77Skettenis ps_err_e
ps_ptread(gdb_ps_prochandle_t ph,paddr_t addr,gdb_ps_read_buf_t buf,gdb_ps_size_t size)211*b725ae77Skettenis ps_ptread (gdb_ps_prochandle_t ph, paddr_t addr,
212*b725ae77Skettenis gdb_ps_read_buf_t buf, gdb_ps_size_t size)
213*b725ae77Skettenis {
214*b725ae77Skettenis return ps_xfer_memory (ph, addr, buf, size, 0);
215*b725ae77Skettenis }
216*b725ae77Skettenis
217*b725ae77Skettenis /* Write SIZE bytes from BUF into the target process PH at address ADDR. */
218*b725ae77Skettenis
219*b725ae77Skettenis ps_err_e
ps_ptwrite(gdb_ps_prochandle_t ph,paddr_t addr,gdb_ps_write_buf_t buf,gdb_ps_size_t size)220*b725ae77Skettenis ps_ptwrite (gdb_ps_prochandle_t ph, paddr_t addr,
221*b725ae77Skettenis gdb_ps_write_buf_t buf, gdb_ps_size_t size)
222*b725ae77Skettenis {
223*b725ae77Skettenis return ps_xfer_memory (ph, addr, (char *) buf, size, 1);
224*b725ae77Skettenis }
225*b725ae77Skettenis
226*b725ae77Skettenis /* Get the general registers of LWP LWPID within the target process PH
227*b725ae77Skettenis and store them in GREGSET. */
228*b725ae77Skettenis
229*b725ae77Skettenis ps_err_e
ps_lgetregs(gdb_ps_prochandle_t ph,lwpid_t lwpid,prgregset_t gregset)230*b725ae77Skettenis ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
231*b725ae77Skettenis {
232*b725ae77Skettenis struct cleanup *old_chain = save_inferior_ptid ();
233*b725ae77Skettenis
234*b725ae77Skettenis inferior_ptid = BUILD_LWP (lwpid, ph->pid);
235*b725ae77Skettenis
236*b725ae77Skettenis target_fetch_registers (-1);
237*b725ae77Skettenis fill_gregset ((gdb_gregset_t *) gregset, -1);
238*b725ae77Skettenis
239*b725ae77Skettenis do_cleanups (old_chain);
240*b725ae77Skettenis return PS_OK;
241*b725ae77Skettenis }
242*b725ae77Skettenis
243*b725ae77Skettenis /* Set the general registers of LWP LWPID within the target process PH
244*b725ae77Skettenis from GREGSET. */
245*b725ae77Skettenis
246*b725ae77Skettenis ps_err_e
ps_lsetregs(gdb_ps_prochandle_t ph,lwpid_t lwpid,const prgregset_t gregset)247*b725ae77Skettenis ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, const prgregset_t gregset)
248*b725ae77Skettenis {
249*b725ae77Skettenis struct cleanup *old_chain = save_inferior_ptid ();
250*b725ae77Skettenis
251*b725ae77Skettenis inferior_ptid = BUILD_LWP (lwpid, ph->pid);
252*b725ae77Skettenis
253*b725ae77Skettenis /* FIXME: We should really make supply_gregset const-correct. */
254*b725ae77Skettenis supply_gregset ((gdb_gregset_t *) gregset);
255*b725ae77Skettenis target_store_registers (-1);
256*b725ae77Skettenis
257*b725ae77Skettenis do_cleanups (old_chain);
258*b725ae77Skettenis return PS_OK;
259*b725ae77Skettenis }
260*b725ae77Skettenis
261*b725ae77Skettenis /* Get the floating-point registers of LWP LWPID within the target
262*b725ae77Skettenis process PH and store them in FPREGSET. */
263*b725ae77Skettenis
264*b725ae77Skettenis ps_err_e
ps_lgetfpregs(gdb_ps_prochandle_t ph,lwpid_t lwpid,gdb_prfpregset_t * fpregset)265*b725ae77Skettenis ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
266*b725ae77Skettenis gdb_prfpregset_t *fpregset)
267*b725ae77Skettenis {
268*b725ae77Skettenis struct cleanup *old_chain = save_inferior_ptid ();
269*b725ae77Skettenis
270*b725ae77Skettenis inferior_ptid = BUILD_LWP (lwpid, ph->pid);
271*b725ae77Skettenis
272*b725ae77Skettenis target_fetch_registers (-1);
273*b725ae77Skettenis fill_fpregset ((gdb_fpregset_t *) fpregset, -1);
274*b725ae77Skettenis
275*b725ae77Skettenis do_cleanups (old_chain);
276*b725ae77Skettenis return PS_OK;
277*b725ae77Skettenis }
278*b725ae77Skettenis
279*b725ae77Skettenis /* Set the floating-point registers of LWP LWPID within the target
280*b725ae77Skettenis process PH from FPREGSET. */
281*b725ae77Skettenis
282*b725ae77Skettenis ps_err_e
ps_lsetfpregs(gdb_ps_prochandle_t ph,lwpid_t lwpid,const gdb_prfpregset_t * fpregset)283*b725ae77Skettenis ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
284*b725ae77Skettenis const gdb_prfpregset_t *fpregset)
285*b725ae77Skettenis {
286*b725ae77Skettenis struct cleanup *old_chain = save_inferior_ptid ();
287*b725ae77Skettenis
288*b725ae77Skettenis inferior_ptid = BUILD_LWP (lwpid, ph->pid);
289*b725ae77Skettenis
290*b725ae77Skettenis /* FIXME: We should really make supply_fpregset const-correct. */
291*b725ae77Skettenis supply_fpregset ((gdb_fpregset_t *) fpregset);
292*b725ae77Skettenis target_store_registers (-1);
293*b725ae77Skettenis
294*b725ae77Skettenis do_cleanups (old_chain);
295*b725ae77Skettenis return PS_OK;
296*b725ae77Skettenis }
297*b725ae77Skettenis
298*b725ae77Skettenis /* Return overall process id of the target PH. Special for GNU/Linux
299*b725ae77Skettenis -- not used on Solaris. */
300*b725ae77Skettenis
301*b725ae77Skettenis pid_t
ps_getpid(gdb_ps_prochandle_t ph)302*b725ae77Skettenis ps_getpid (gdb_ps_prochandle_t ph)
303*b725ae77Skettenis {
304*b725ae77Skettenis return ph->pid;
305*b725ae77Skettenis }
306*b725ae77Skettenis
307*b725ae77Skettenis void
_initialize_proc_service(void)308*b725ae77Skettenis _initialize_proc_service (void)
309*b725ae77Skettenis {
310*b725ae77Skettenis /* This function solely exists to make sure this module is linked
311*b725ae77Skettenis into the final binary. */
312*b725ae77Skettenis }
313