xref: /openbsd-src/gnu/usr.bin/binutils/gdb/proc-service.c (revision b725ae7711052a2233e31a66fefb8a752c388d7a)
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