GDB (xrefs)
/tmp/gdb-8.1/gdb/xtensa-linux-nat.c
Go to the documentation of this file.
1 /* Xtensa GNU/Linux native support.
2 
3  Copyright (C) 2007-2018 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 #include "frame.h"
22 #include "inferior.h"
23 #include "gdbcore.h"
24 #include "regcache.h"
25 #include "target.h"
26 #include "linux-nat.h"
27 #include <sys/types.h>
28 #include <signal.h>
29 #include <sys/user.h>
30 #include <sys/ioctl.h>
31 #include "gdb_wait.h"
32 #include <fcntl.h>
33 #include <sys/procfs.h>
34 #include "nat/gdb_ptrace.h"
35 #include <asm/ptrace.h>
36 
37 #include "gregset.h"
38 #include "xtensa-tdep.h"
39 
40 /* Defines ps_err_e, struct ps_prochandle. */
41 #include "gdb_proc_service.h"
42 
43 /* Extended register set depends on hardware configs.
44  Keeping these definitions separately allows to introduce
45  hardware-specific overlays. */
46 #include "xtensa-xtregs.c"
47 
48 void
50  gdb_gregset_t *gregsetp, int regnum)
51 {
52  int i;
53  xtensa_elf_gregset_t *regs = (xtensa_elf_gregset_t *) gregsetp;
54  struct gdbarch *gdbarch = regcache->arch ();
55 
56  if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
58  if (regnum == gdbarch_ps_regnum (gdbarch) || regnum == -1)
60 
61  if (regnum == gdbarch_tdep (gdbarch)->wb_regnum || regnum == -1)
63  gdbarch_tdep (gdbarch)->wb_regnum,
64  &regs->windowbase);
65  if (regnum == gdbarch_tdep (gdbarch)->ws_regnum || regnum == -1)
67  gdbarch_tdep (gdbarch)->ws_regnum,
68  &regs->windowstart);
69  if (regnum == gdbarch_tdep (gdbarch)->lbeg_regnum || regnum == -1)
71  gdbarch_tdep (gdbarch)->lbeg_regnum,
72  &regs->lbeg);
73  if (regnum == gdbarch_tdep (gdbarch)->lend_regnum || regnum == -1)
75  gdbarch_tdep (gdbarch)->lend_regnum,
76  &regs->lend);
77  if (regnum == gdbarch_tdep (gdbarch)->lcount_regnum || regnum == -1)
79  gdbarch_tdep (gdbarch)->lcount_regnum,
80  &regs->lcount);
81  if (regnum == gdbarch_tdep (gdbarch)->sar_regnum || regnum == -1)
83  gdbarch_tdep (gdbarch)->sar_regnum,
84  &regs->sar);
85  if (regnum == gdbarch_tdep (gdbarch)->threadptr_regnum || regnum == -1)
87  gdbarch_tdep (gdbarch)->threadptr_regnum,
88  &regs->threadptr);
89  if (regnum >=gdbarch_tdep (gdbarch)->ar_base
90  && regnum < gdbarch_tdep (gdbarch)->ar_base
91  + gdbarch_tdep (gdbarch)->num_aregs)
93  &regs->ar[regnum - gdbarch_tdep (gdbarch)->ar_base]);
94  else if (regnum == -1)
95  {
96  for (i = 0; i < gdbarch_tdep (gdbarch)->num_aregs; ++i)
99  &regs->ar[i]);
100  }
104  &regs->ar[(4 * regs->windowbase + regnum
105  - gdbarch_tdep (gdbarch)->a0_base)
107  else if (regnum == -1)
108  {
109  for (i = 0; i < C0_NREGS; ++i)
112  &regs->ar[(4 * regs->windowbase + i)
114  }
115 }
116 
117 static void
119  const gdb_gregset_t *gregsetp, int regnum)
120 {
121  int i;
122  xtensa_elf_gregset_t *regs = (xtensa_elf_gregset_t *) gregsetp;
123 
124  struct gdbarch *gdbarch = regcache->arch ();
125 
126  if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
128  if (regnum == gdbarch_ps_regnum (gdbarch) || regnum == -1)
130 
131  if (regnum == gdbarch_tdep (gdbarch)->wb_regnum || regnum == -1)
133  gdbarch_tdep (gdbarch)->wb_regnum,
134  &regs->windowbase);
135  if (regnum == gdbarch_tdep (gdbarch)->ws_regnum || regnum == -1)
137  gdbarch_tdep (gdbarch)->ws_regnum,
138  &regs->windowstart);
139  if (regnum == gdbarch_tdep (gdbarch)->lbeg_regnum || regnum == -1)
141  gdbarch_tdep (gdbarch)->lbeg_regnum,
142  &regs->lbeg);
143  if (regnum == gdbarch_tdep (gdbarch)->lend_regnum || regnum == -1)
145  gdbarch_tdep (gdbarch)->lend_regnum,
146  &regs->lend);
147  if (regnum == gdbarch_tdep (gdbarch)->lcount_regnum || regnum == -1)
149  gdbarch_tdep (gdbarch)->lcount_regnum,
150  &regs->lcount);
151  if (regnum == gdbarch_tdep (gdbarch)->sar_regnum || regnum == -1)
153  gdbarch_tdep (gdbarch)->sar_regnum,
154  &regs->sar);
155  if (regnum == gdbarch_tdep (gdbarch)->threadptr_regnum || regnum == -1)
157  gdbarch_tdep (gdbarch)->threadptr_regnum,
158  &regs->threadptr);
159  if (regnum >=gdbarch_tdep (gdbarch)->ar_base
160  && regnum < gdbarch_tdep (gdbarch)->ar_base
161  + gdbarch_tdep (gdbarch)->num_aregs)
163  &regs->ar[regnum - gdbarch_tdep (gdbarch)->ar_base]);
164  else if (regnum == -1)
165  {
166  for (i = 0; i < gdbarch_tdep (gdbarch)->num_aregs; ++i)
169  &regs->ar[i]);
170  }
174  &regs->ar[(4 * regs->windowbase + regnum
175  - gdbarch_tdep (gdbarch)->a0_base)
177  else if (regnum == -1)
178  {
179  for (i = 0; i < C0_NREGS; ++i)
182  &regs->ar[(4 * regs->windowbase + i)
184  }
185 }
186 
187 void
188 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
189 {
190  supply_gregset_reg (regcache, gregsetp, -1);
191 }
192 
193 void
195  gdb_fpregset_t *fpregsetp, int regnum)
196 {
197  return;
198 }
199 
200 void
202  const gdb_fpregset_t *fpregsetp)
203 {
204  return;
205 }
206 
207 /* Fetch greg-register(s) from process/thread TID
208  and store value(s) in GDB's register array. */
209 
210 static void
212 {
214  gdb_gregset_t regs;
215  int areg;
216 
217  if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
218  {
219  perror_with_name (_("Couldn't get registers"));
220  return;
221  }
222 
224 }
225 
226 /* Store greg-register(s) in GDB's register
227  array into the process/thread specified by TID. */
228 
229 static void
231 {
233  gdb_gregset_t regs;
234  int areg;
235 
236  if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
237  {
238  perror_with_name (_("Couldn't get registers"));
239  return;
240  }
241 
242  fill_gregset (regcache, &regs, regnum);
243 
244  if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
245  {
246  perror_with_name (_("Couldn't write registers"));
247  return;
248  }
249 }
250 
251 static int xtreg_lo;
252 static int xtreg_high;
253 
254 /* Fetch/Store Xtensa TIE registers. Xtensa GNU/Linux PTRACE
255  interface provides special requests for this. */
256 
257 static void
259 {
261  const xtensa_regtable_t *ptr;
262  char xtregs [XTENSA_ELF_XTREG_SIZE];
263 
264  if (ptrace (PTRACE_GETXTREGS, tid, 0, (long)&xtregs) < 0)
265  perror_with_name (_("Couldn't get extended registers"));
266 
267  for (ptr = xtensa_regmap_table; ptr->name; ptr++)
268  if (regnum == ptr->gdb_regnum || regnum == -1)
270  xtregs + ptr->ptrace_offset);
271 }
272 
273 static void
275 {
277  const xtensa_regtable_t *ptr;
278  char xtregs [XTENSA_ELF_XTREG_SIZE];
279 
280  if (ptrace (PTRACE_GETXTREGS, tid, 0, (long)&xtregs) < 0)
281  perror_with_name (_("Couldn't get extended registers"));
282 
283  for (ptr = xtensa_regmap_table; ptr->name; ptr++)
284  if (regnum == ptr->gdb_regnum || regnum == -1)
286  xtregs + ptr->ptrace_offset);
287 
288  if (ptrace (PTRACE_SETXTREGS, tid, 0, (long)&xtregs) < 0)
289  perror_with_name (_("Couldn't write extended registers"));
290 }
291 
292 static void
294  struct regcache *regcache, int regnum)
295 {
296  if (regnum == -1)
297  {
300  }
301  else if ((regnum < xtreg_lo) || (regnum > xtreg_high))
303  else
305 }
306 
307 static void
309  struct regcache *regcache, int regnum)
310 {
311  if (regnum == -1)
312  {
315  }
316  else if ((regnum < xtreg_lo) || (regnum > xtreg_high))
318  else
320 }
321 
322 /* Called by libthread_db. */
323 
324 ps_err_e
326  lwpid_t lwpid, int idx, void **base)
327 {
329 
330  if (ptrace (PTRACE_GETREGS, lwpid, NULL, &regs) != 0)
331  return PS_ERR;
332 
333  /* IDX is the bias from the thread pointer to the beginning of the
334  thread descriptor. It has to be subtracted due to implementation
335  quirks in libthread_db. */
336  *base = (void *) ((char *) regs.threadptr - idx);
337 
338  return PS_OK;
339 }
340 
341 void
343 {
344  struct target_ops *t;
345  const xtensa_regtable_t *ptr;
346 
347  /* Calculate the number range for extended registers. */
348  xtreg_lo = 1000000000;
349  xtreg_high = -1;
350  for (ptr = xtensa_regmap_table; ptr->name; ptr++)
351  {
352  if (ptr->gdb_regnum < xtreg_lo)
353  xtreg_lo = ptr->gdb_regnum;
354  if (ptr->gdb_regnum > xtreg_high)
355  xtreg_high = ptr->gdb_regnum;
356  }
357 
358  /* Fill in the generic GNU/Linux methods. */
359  t = linux_target ();
360 
361  /* Add our register access methods. */
364 
366 }
unsigned int lwpid_t
const xtensa_regtable_t xtensa_regmap_table[]
Definition: xtensa-xtregs.c:34
static void fetch_gregs(struct regcache *regcache, int regnum)
static constexpr ptid_t tid
static int xtreg_high
const char * name
Definition: xtensa-xtregs.c:29
xtensa_elf_greg_t ar[64]
Definition: xtensa.h:40
#define XTENSA_ELF_XTREG_SIZE
Definition: xtensa-xtregs.c:32
xtensa_elf_greg_t ps
Definition: xtensa.h:31
ptid_t regcache_get_ptid(const struct regcache *regcache)
Definition: regcache.c:229
ps_err_e
xtensa_elf_greg_t lbeg
Definition: xtensa.h:32
xtensa_elf_greg_t lend
Definition: xtensa.h:33
#define _(String)
Definition: gdb_locale.h:35
struct gdbarch_tdep * gdbarch_tdep(struct gdbarch *gdbarch)
Definition: gdbarch.c:1491
void _initialize_xtensa_linux_nat(void)
int gdbarch_ps_regnum(struct gdbarch *gdbarch)
Definition: gdbarch.c:2180
static void fetch_xtregs(struct regcache *regcache, int regnum)
PTRACE_TYPE_RET ptrace()
static void store_xtregs(struct regcache *regcache, int regnum)
void supply_fpregset(struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
ps_err_e ps_get_thread_area(struct ps_prochandle *ph, lwpid_t lwpid, int idx, void **base)
static void store_gregs(struct regcache *regcache, int regnum)
void fill_gregset(const struct regcache *regcache, gdb_gregset_t *gregsetp, int regnum)
static void supply_gregset_reg(struct regcache *regcache, const gdb_gregset_t *gregsetp, int regnum)
unsigned int num_aregs
Definition: xtensa-tdep.h:193
void supply_gregset(struct regcache *regcache, const gdb_gregset_t *gregsetp)
GDB_GREGSET_T gdb_gregset_t
Definition: gregset.h:34
xtensa_elf_greg_t windowstart
Definition: xtensa.h:36
GDB_FPREGSET_T gdb_fpregset_t
Definition: gregset.h:35
xtensa_elf_greg_t threadptr
Definition: xtensa.h:38
#define C0_NREGS
Definition: xtensa.h:46
void linux_nat_add_target(struct target_ops *t)
Definition: linux-nat.c:4804
xtensa_elf_greg_t windowbase
Definition: xtensa.h:37
int regnum
Definition: aarch64-tdep.c:77
struct target_ops * linux_target(void)
Definition: linux-nat.c:4377
long ptid_get_lwp(const ptid_t &ptid)
Definition: ptid.c:55
static void xtensa_linux_fetch_inferior_registers(struct target_ops *ops, struct regcache *regcache, int regnum)
xtensa_elf_greg_t lcount
Definition: xtensa.h:34
void(* to_fetch_registers)(struct target_ops *, struct regcache *, int) TARGET_DEFAULT_IGNORE()
Definition: target.h:457
void fill_fpregset(const struct regcache *regcache, gdb_fpregset_t *fpregsetp, int regnum)
void void void void void void void void void perror_with_name(const char *string) ATTRIBUTE_NORETURN
Definition: utils.c:692
static int xtreg_lo
gdbarch * arch() const
Definition: regcache.c:221
xtensa_elf_greg_t sar
Definition: xtensa.h:35
#define PTRACE_SETREGS
static void xtensa_linux_store_inferior_registers(struct target_ops *ops, struct regcache *regcache, int regnum)
xtensa_elf_greg_t pc
Definition: xtensa.h:30
void regcache_raw_supply(struct regcache *regcache, int regnum, const void *buf)
Definition: regcache.c:1004
void regcache_raw_collect(const struct regcache *regcache, int regnum, void *buf)
Definition: regcache.c:1085
int gdbarch_pc_regnum(struct gdbarch *gdbarch)
Definition: gdbarch.c:2163
void(* to_store_registers)(struct target_ops *, struct regcache *, int) TARGET_DEFAULT_NORETURN(noprocess())
Definition: target.h:459
#define PTRACE_GETREGS