Remove save_inferior_ptid
[external/binutils.git] / gdb / proc-service.c
1 /* <proc_service.h> implementation.
2
3    Copyright (C) 1999-2017 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21
22 #include "gdbcore.h"
23 #include "inferior.h"
24 #include "symtab.h"
25 #include "target.h"
26 #include "regcache.h"
27 #include "objfiles.h"
28
29 #include "gdb_proc_service.h"
30
31 #include <sys/procfs.h>
32
33 /* Prototypes for supply_gregset etc.  */
34 #include "gregset.h"
35 \f
36
37 /* Fix-up some broken systems.  */
38
39 /* The prototypes in <proc_service.h> are slightly different on older
40    systems.  Compensate for the discrepancies.  */
41
42 #ifdef PROC_SERVICE_IS_OLD
43 typedef const struct ps_prochandle *gdb_ps_prochandle_t;
44 typedef char *gdb_ps_read_buf_t;
45 typedef char *gdb_ps_write_buf_t;
46 typedef int gdb_ps_size_t;
47 #else
48 typedef struct ps_prochandle *gdb_ps_prochandle_t;
49 typedef void *gdb_ps_read_buf_t;
50 typedef const void *gdb_ps_write_buf_t;
51 typedef size_t gdb_ps_size_t;
52 #endif
53 \f
54
55 /* Helper functions.  */
56
57 /* Convert a psaddr_t to a CORE_ADDR.  */
58
59 static CORE_ADDR
60 ps_addr_to_core_addr (psaddr_t addr)
61 {
62   if (exec_bfd && bfd_get_sign_extend_vma (exec_bfd))
63     return (intptr_t) addr;
64   else
65     return (uintptr_t) addr;
66 }
67
68 /* Convert a CORE_ADDR to a psaddr_t.  */
69
70 static psaddr_t
71 core_addr_to_ps_addr (CORE_ADDR addr)
72 {
73   if (exec_bfd && bfd_get_sign_extend_vma (exec_bfd))
74     return (psaddr_t) (intptr_t) addr;
75   else
76     return (psaddr_t) (uintptr_t) addr;
77 }
78
79 /* Transfer LEN bytes of memory between BUF and address ADDR in the
80    process specified by PH.  If WRITE, transfer them to the process,
81    else transfer them from the process.  Returns PS_OK for success,
82    PS_ERR on failure.
83
84    This is a helper function for ps_pdread and ps_pdwrite.  */
85
86 static ps_err_e
87 ps_xfer_memory (const struct ps_prochandle *ph, psaddr_t addr,
88                 gdb_byte *buf, size_t len, int write)
89 {
90   scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
91   int ret;
92   CORE_ADDR core_addr = ps_addr_to_core_addr (addr);
93
94   inferior_ptid = ph->ptid;
95
96   if (write)
97     ret = target_write_memory (core_addr, buf, len);
98   else
99     ret = target_read_memory (core_addr, buf, len);
100
101   return (ret == 0 ? PS_OK : PS_ERR);
102 }
103 \f
104
105 /* Search for the symbol named NAME within the object named OBJ within
106    the target process PH.  If the symbol is found the address of the
107    symbol is stored in SYM_ADDR.  */
108
109 ps_err_e
110 ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *obj,
111                    const char *name, psaddr_t *sym_addr)
112 {
113   struct inferior *inf = find_inferior_ptid (ph->ptid);
114
115   scoped_restore_current_program_space restore_pspace;
116
117   set_current_program_space (inf->pspace);
118
119   /* FIXME: kettenis/2000-09-03: What should we do with OBJ?  */
120   bound_minimal_symbol ms = lookup_minimal_symbol (name, NULL, NULL);
121   if (ms.minsym == NULL)
122     return PS_NOSYM;
123
124   *sym_addr = core_addr_to_ps_addr (BMSYMBOL_VALUE_ADDRESS (ms));
125   return PS_OK;
126 }
127
128 /* Read SIZE bytes from the target process PH at address ADDR and copy
129    them into BUF.  */
130
131 ps_err_e
132 ps_pdread (gdb_ps_prochandle_t ph, psaddr_t addr,
133            gdb_ps_read_buf_t buf, gdb_ps_size_t size)
134 {
135   return ps_xfer_memory (ph, addr, (gdb_byte *) buf, size, 0);
136 }
137
138 /* Write SIZE bytes from BUF into the target process PH at address ADDR.  */
139
140 ps_err_e
141 ps_pdwrite (gdb_ps_prochandle_t ph, psaddr_t addr,
142             gdb_ps_write_buf_t buf, gdb_ps_size_t size)
143 {
144   return ps_xfer_memory (ph, addr, (gdb_byte *) buf, size, 1);
145 }
146
147 /* Get the general registers of LWP LWPID within the target process PH
148    and store them in GREGSET.  */
149
150 ps_err_e
151 ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
152 {
153   ptid_t ptid = ptid_build (ptid_get_pid (ph->ptid), lwpid, 0);
154   struct regcache *regcache
155     = get_thread_arch_regcache (ptid, target_gdbarch ());
156
157   target_fetch_registers (regcache, -1);
158   fill_gregset (regcache, (gdb_gregset_t *) gregset, -1);
159
160   return PS_OK;
161 }
162
163 /* Set the general registers of LWP LWPID within the target process PH
164    from GREGSET.  */
165
166 ps_err_e
167 ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, const prgregset_t gregset)
168 {
169   ptid_t ptid = ptid_build (ptid_get_pid (ph->ptid), lwpid, 0);
170   struct regcache *regcache
171     = get_thread_arch_regcache (ptid, target_gdbarch ());
172
173   supply_gregset (regcache, (const gdb_gregset_t *) gregset);
174   target_store_registers (regcache, -1);
175
176   return PS_OK;
177 }
178
179 /* Get the floating-point registers of LWP LWPID within the target
180    process PH and store them in FPREGSET.  */
181
182 ps_err_e
183 ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
184                gdb_prfpregset_t *fpregset)
185 {
186   ptid_t ptid = ptid_build (ptid_get_pid (ph->ptid), lwpid, 0);
187   struct regcache *regcache
188     = get_thread_arch_regcache (ptid, target_gdbarch ());
189
190   target_fetch_registers (regcache, -1);
191   fill_fpregset (regcache, (gdb_fpregset_t *) fpregset, -1);
192
193   return PS_OK;
194 }
195
196 /* Set the floating-point registers of LWP LWPID within the target
197    process PH from FPREGSET.  */
198
199 ps_err_e
200 ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
201                const gdb_prfpregset_t *fpregset)
202 {
203   ptid_t ptid = ptid_build (ptid_get_pid (ph->ptid), lwpid, 0);
204   struct regcache *regcache
205     = get_thread_arch_regcache (ptid, target_gdbarch ());
206
207   supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset);
208   target_store_registers (regcache, -1);
209
210   return PS_OK;
211 }
212
213 /* Return overall process id of the target PH.  Special for GNU/Linux
214    -- not used on Solaris.  */
215
216 pid_t
217 ps_getpid (gdb_ps_prochandle_t ph)
218 {
219   return ptid_get_pid (ph->ptid);
220 }
221
222 /* Provide a prototype to silence -Wmissing-prototypes.  */
223 extern initialize_file_ftype _initialize_proc_service;
224
225 void
226 _initialize_proc_service (void)
227 {
228   /* This function solely exists to make sure this module is linked
229      into the final binary.  */
230 }