gdb: fix vfork with multiple threads
[deliverable/binutils-gdb.git] / gdb / arc-linux-nat.c
CommitLineData
04c9f85e
AK
1/* Native-dependent code for GNU/Linux ARC.
2
3666a048 3 Copyright 2020-2021 Free Software Foundation, Inc.
04c9f85e
AK
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#include "frame.h"
22#include "inferior.h"
23#include "gdbcore.h"
24#include "regcache.h"
25#include "gdbsupport/gdb_assert.h"
26#include "target.h"
27#include "linux-nat.h"
28#include "nat/gdb_ptrace.h"
29
30#include <stdint.h>
31#include <sys/types.h>
32#include <sys/param.h>
33#include <signal.h>
34#include <sys/user.h>
35#include <sys/ioctl.h>
36#include "gdbsupport/gdb_wait.h"
37#include <fcntl.h>
38#include <sys/procfs.h>
39#include <linux/elf.h>
40
41#include "gregset.h"
42#include "arc-tdep.h"
43#include "arc-linux-tdep.h"
44#include "arch/arc.h"
45
46/* Defines ps_err_e, struct ps_prochandle. */
47#include "gdb_proc_service.h"
48
d8d1feb4
SM
49/* Print an "arc-linux-nat" debug statement. */
50
51#define arc_linux_nat_debug_printf(fmt, ...) \
52 debug_prefixed_printf_cond (arc_debug, "arc-linux-nat", fmt, ##__VA_ARGS__)
53
04c9f85e
AK
54/* Linux starting with 4.12 supports NT_ARC_V2 note type, which adds R30,
55 R58 and R59 registers, which are specific to ARC HS and aren't
56 available in ARC 700. */
57#if defined (NT_ARC_V2) && defined (__ARCHS__)
58#define ARC_HAS_V2_REGSET
59#endif
60
61class arc_linux_nat_target final : public linux_nat_target
62{
63public:
64 /* Add ARC register access methods. */
65 void fetch_registers (struct regcache *, int) override;
66 void store_registers (struct regcache *, int) override;
67
68 const struct target_desc *read_description () override;
69
70 /* Handle threads */
71 void low_prepare_to_resume (struct lwp_info *lp) override;
72};
73
74static arc_linux_nat_target the_arc_linux_nat_target;
75
76/* Read general registers from target process/thread (via ptrace)
77 into REGCACHE. */
78
79static void
80fetch_gregs (struct regcache *regcache, int regnum)
81{
82 const int tid = get_ptrace_pid (regcache->ptid ());
83 struct iovec iov;
84 gdb_gregset_t regs;
85
86 iov.iov_base = &regs;
87 iov.iov_len = sizeof (gdb_gregset_t);
88
89 if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
90 perror_with_name (_("Couldn't get general registers"));
91 else
92 arc_linux_supply_gregset (NULL, regcache, regnum, &regs, 0);
93}
94
95#ifdef ARC_HAS_V2_REGSET
96/* Read ARC v2 registers from target process/thread (via ptrace)
97 into REGCACHE. */
98
99static void
100fetch_v2_regs (struct regcache *regcache, int regnum)
101{
102 const int tid = get_ptrace_pid (regcache->ptid ());
103 struct iovec iov;
104 bfd_byte v2_buffer[ARC_LINUX_SIZEOF_V2_REGSET];
105
106 iov.iov_base = &v2_buffer;
107 iov.iov_len = ARC_LINUX_SIZEOF_V2_REGSET;
108
109 if (ptrace (PTRACE_GETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
110 perror_with_name (_("Couldn't get ARC HS registers"));
111 else
112 arc_linux_supply_v2_regset (NULL, regcache, regnum, v2_buffer, 0);
113}
114#endif
115
116/* Store general registers from REGCACHE into the target process/thread. */
117
118static void
119store_gregs (const struct regcache *regcache, int regnum)
120{
121 const int tid = get_ptrace_pid (regcache->ptid ());
122 struct iovec iov;
123 gdb_gregset_t regs;
124
125 iov.iov_base = &regs;
126 iov.iov_len = sizeof (gdb_gregset_t);
127
128 if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
129 perror_with_name (_("Couldn't get general registers"));
130 else
131 {
132 arc_linux_collect_gregset (NULL, regcache, regnum, regs, 0);
133
134 if (ptrace (PTRACE_SETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
135 perror_with_name (_("Couldn't write general registers"));
136 }
137}
138
139#ifdef ARC_HAS_V2_REGSET
140/* Store ARC v2 registers from REGCACHE into the target process/thread. */
141
142static void
143store_v2_regs (const struct regcache *regcache, int regnum)
144{
145 const int tid = get_ptrace_pid (regcache->ptid ());
146 struct iovec iov;
147 bfd_byte v2_buffer[ARC_LINUX_SIZEOF_V2_REGSET];
148
149 iov.iov_base = &v2_buffer;
150 iov.iov_len = ARC_LINUX_SIZEOF_V2_REGSET;
151
152 if (ptrace (PTRACE_GETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
153 perror_with_name (_("Couldn't get ARC HS registers"));
154 else
155 {
156 arc_linux_collect_v2_regset (NULL, regcache, regnum, v2_buffer, 0);
157
158 if (ptrace (PTRACE_SETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
159 perror_with_name (_("Couldn't write ARC HS registers"));
160 }
161}
162#endif
163
164/* Target operation: Read REGNUM register (all registers if REGNUM == -1)
165 from target process into REGCACHE. */
166
167void
168arc_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
169{
170
171 if (regnum == -1 || regnum <= ARC_LAST_REGNUM)
172 fetch_gregs (regcache, regnum);
173
174#ifdef ARC_HAS_V2_REGSET
175 if (regnum == -1
176 || regnum == ARC_R30_REGNUM
177 || regnum == ARC_R58_REGNUM
178 || regnum == ARC_R59_REGNUM)
179 fetch_v2_regs (regcache, regnum);
180#endif
181}
182
183/* Target operation: Store REGNUM register (all registers if REGNUM == -1)
184 to the target process from REGCACHE. */
185
186void
187arc_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
188{
189 if (regnum == -1 || regnum <= ARC_LAST_REGNUM)
190 store_gregs (regcache, regnum);
191
192#ifdef ARC_HAS_V2_REGSET
193 if (regnum == -1
194 || regnum == ARC_R30_REGNUM
195 || regnum == ARC_R58_REGNUM
196 || regnum == ARC_R59_REGNUM)
197 store_v2_regs (regcache, regnum);
198#endif
199}
200
201/* Copy general purpose register(s) from REGCACHE into regset GREGS.
202 This function is exported to proc-service.c */
203
204void
205fill_gregset (const struct regcache *regcache,
206 gdb_gregset_t *gregs, int regnum)
207{
208 arc_linux_collect_gregset (NULL, regcache, regnum, gregs, 0);
209}
210
211/* Copy all the general purpose registers from regset GREGS into REGCACHE.
212 This function is exported to proc-service.c. */
213
214void
215supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregs)
216{
217 arc_linux_supply_gregset (NULL, regcache, -1, gregs, 0);
218}
219
220/* ARC doesn't have separate FP registers. This function is exported
221 to proc-service.c. */
222
223void
224fill_fpregset (const struct regcache *regcache,
225 gdb_fpregset_t *fpregsetp, int regnum)
226{
d8d1feb4 227 arc_linux_nat_debug_printf ("called");
04c9f85e
AK
228}
229
230/* ARC doesn't have separate FP registers. This function is exported
231 to proc-service.c. */
232
233void
234supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
235{
d8d1feb4 236 arc_linux_nat_debug_printf ("called");
04c9f85e
AK
237}
238
239/* Implement the "read_description" method of linux_nat_target. */
240
241const struct target_desc *
242arc_linux_nat_target::read_description ()
243{
244 /* This is a native target, hence description is hardcoded. */
245#ifdef __ARCHS__
246 arc_arch_features features (4, ARC_ISA_ARCV2);
247#else
248 arc_arch_features features (4, ARC_ISA_ARCV1);
249#endif
250 return arc_lookup_target_description (features);
251}
252
253/* As described in arc_linux_collect_gregset(), we need to write resume-PC
254 to ERET. However by default GDB for native targets doesn't write
255 registers if they haven't been changed. This is a callback called by
256 generic GDB, and in this callback we have to rewrite PC value so it
257 would force rewrite of register on target. It seems that the only
258 other arch that utilizes this hook is x86/x86-64 for HW breakpoint
259 support. But then, AFAIK no other arch has this stop_pc/eret
260 complexity.
261
262 No better way was found, other than this fake write of register value,
263 to force GDB into writing register to target. Is there any? */
264
265void
266arc_linux_nat_target::low_prepare_to_resume (struct lwp_info *lwp)
267{
268 /* When new processes and threads are created we do not have the address
269 space for them and calling get_thread_regcache will cause an internal
270 error in GDB. It looks like that checking for last_resume_kind is the
271 sensible way to determine processes for which we cannot get regcache.
272 Ultimately, a better way would be removing the need for
273 low_prepare_to_resume in the first place. */
274 if (lwp->last_resume_kind == resume_stop)
275 return;
276
277 struct regcache *regcache = get_thread_regcache (this, lwp->ptid);
278 struct gdbarch *gdbarch = regcache->arch ();
279
280 /* Read current PC value, then write it back. It is required to call
281 invalidate(), otherwise GDB will note that new value is equal to old
282 value and will skip write. */
283 ULONGEST new_pc;
284 regcache_cooked_read_unsigned (regcache, gdbarch_pc_regnum (gdbarch),
285 &new_pc);
286 regcache->invalidate (gdbarch_pc_regnum (gdbarch));
287 regcache_cooked_write_unsigned (regcache, gdbarch_pc_regnum (gdbarch),
288 new_pc);
289}
290
291/* Fetch the thread-local storage pointer for libthread_db. Note that
292 this function is not called from GDB, but is called from libthread_db.
293 This is required to debug multithreaded applications with NPTL. */
294
295ps_err_e
296ps_get_thread_area (struct ps_prochandle *ph, lwpid_t lwpid, int idx,
297 void **base)
298{
d8d1feb4 299 arc_linux_nat_debug_printf ("called");
04c9f85e
AK
300
301 if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
302 return PS_ERR;
303
304 /* IDX is the bias from the thread pointer to the beginning of the
305 thread descriptor. It has to be subtracted due to implementation
306 quirks in libthread_db. */
307 *base = (void *) ((char *) *base - idx);
308
309 return PS_OK;
310}
311
312/* Suppress warning from -Wmissing-prototypes. */
313void _initialize_arc_linux_nat ();
314void
315_initialize_arc_linux_nat ()
316{
317 /* Register the target. */
318 linux_target = &the_arc_linux_nat_target;
319 add_inf_child_target (&the_arc_linux_nat_target);
320}
This page took 0.077309 seconds and 4 git commands to generate.