GDB (xrefs)
/tmp/gdb-7.10/gdb/xtensa-linux-nat.c
Go to the documentation of this file.
1 /* Xtensa GNU/Linux native support.
2 
3  Copyright (C) 2007-2015 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 <sys/ptrace.h>
35 #include <asm/ptrace.h>
36 
37 #include "gregset.h"
38 #include "xtensa-tdep.h"
39 
40 /* Extended register set depends on hardware configs.
41  Keeping these definitions separately allows to introduce
42  hardware-specific overlays. */
43 #include "xtensa-xtregs.c"
44 
45 static int
47 {
48  int tid = ptid_get_lwp (ptid);
49  if (0 == tid)
50  tid = ptid_get_pid (ptid);
51  return tid;
52 }
53 #define GET_THREAD_ID(PTID) get_thread_id (PTID)
54 
55 void
57  gdb_gregset_t *gregsetp, int regnum)
58 {
59  int i;
60  xtensa_elf_gregset_t *regs = (xtensa_elf_gregset_t *) gregsetp;
61  struct gdbarch *gdbarch = get_regcache_arch (regcache);
62 
63  if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
64  regcache_raw_collect (regcache, gdbarch_pc_regnum (gdbarch), &regs->pc);
65  if (regnum == gdbarch_ps_regnum (gdbarch) || regnum == -1)
66  regcache_raw_collect (regcache, gdbarch_ps_regnum (gdbarch), &regs->ps);
67 
68  if (regnum == gdbarch_tdep (gdbarch)->wb_regnum || regnum == -1)
69  regcache_raw_collect (regcache,
70  gdbarch_tdep (gdbarch)->wb_regnum,
71  &regs->windowbase);
72  if (regnum == gdbarch_tdep (gdbarch)->ws_regnum || regnum == -1)
73  regcache_raw_collect (regcache,
74  gdbarch_tdep (gdbarch)->ws_regnum,
75  &regs->windowstart);
76  if (regnum == gdbarch_tdep (gdbarch)->lbeg_regnum || regnum == -1)
77  regcache_raw_collect (regcache,
78  gdbarch_tdep (gdbarch)->lbeg_regnum,
79  &regs->lbeg);
80  if (regnum == gdbarch_tdep (gdbarch)->lend_regnum || regnum == -1)
81  regcache_raw_collect (regcache,
82  gdbarch_tdep (gdbarch)->lend_regnum,
83  &regs->lend);
84  if (regnum == gdbarch_tdep (gdbarch)->lcount_regnum || regnum == -1)
85  regcache_raw_collect (regcache,
86  gdbarch_tdep (gdbarch)->lcount_regnum,
87  &regs->lcount);
88  if (regnum == gdbarch_tdep (gdbarch)->sar_regnum || regnum == -1)
89  regcache_raw_collect (regcache,
90  gdbarch_tdep (gdbarch)->sar_regnum,
91  &regs->sar);
92  if (regnum >=gdbarch_tdep (gdbarch)->ar_base
93  && regnum < gdbarch_tdep (gdbarch)->ar_base
94  + gdbarch_tdep (gdbarch)->num_aregs)
95  regcache_raw_collect (regcache,regnum,
96  &regs->ar[regnum - gdbarch_tdep (gdbarch)->ar_base]);
97  else if (regnum == -1)
98  {
99  for (i = 0; i < gdbarch_tdep (gdbarch)->num_aregs; ++i)
100  regcache_raw_collect (regcache,
101  gdbarch_tdep (gdbarch)->ar_base + i,
102  &regs->ar[i]);
103  }
104 }
105 
106 void
108  const gdb_gregset_t *gregsetp, int regnum)
109 {
110  int i;
111  xtensa_elf_gregset_t *regs = (xtensa_elf_gregset_t *) gregsetp;
112 
113  struct gdbarch *gdbarch = get_regcache_arch (regcache);
114 
115  if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
116  regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch), &regs->pc);
117  if (regnum == gdbarch_ps_regnum (gdbarch) || regnum == -1)
118  regcache_raw_supply (regcache, gdbarch_ps_regnum (gdbarch), &regs->ps);
119 
120  if (regnum == gdbarch_tdep (gdbarch)->wb_regnum || regnum == -1)
121  regcache_raw_supply (regcache,
122  gdbarch_tdep (gdbarch)->wb_regnum,
123  &regs->windowbase);
124  if (regnum == gdbarch_tdep (gdbarch)->ws_regnum || regnum == -1)
125  regcache_raw_supply (regcache,
126  gdbarch_tdep (gdbarch)->ws_regnum,
127  &regs->windowstart);
128  if (regnum == gdbarch_tdep (gdbarch)->lbeg_regnum || regnum == -1)
129  regcache_raw_supply (regcache,
130  gdbarch_tdep (gdbarch)->lbeg_regnum,
131  &regs->lbeg);
132  if (regnum == gdbarch_tdep (gdbarch)->lend_regnum || regnum == -1)
133  regcache_raw_supply (regcache,
134  gdbarch_tdep (gdbarch)->lend_regnum,
135  &regs->lend);
136  if (regnum == gdbarch_tdep (gdbarch)->lcount_regnum || regnum == -1)
137  regcache_raw_supply (regcache,
138  gdbarch_tdep (gdbarch)->lcount_regnum,
139  &regs->lcount);
140  if (regnum == gdbarch_tdep (gdbarch)->sar_regnum || regnum == -1)
141  regcache_raw_supply (regcache,
142  gdbarch_tdep (gdbarch)->sar_regnum,
143  &regs->sar);
144  if (regnum >=gdbarch_tdep (gdbarch)->ar_base
145  && regnum < gdbarch_tdep (gdbarch)->ar_base
146  + gdbarch_tdep (gdbarch)->num_aregs)
147  regcache_raw_supply (regcache,regnum,
148  &regs->ar[regnum - gdbarch_tdep (gdbarch)->ar_base]);
149  else if (regnum == -1)
150  {
151  for (i = 0; i < gdbarch_tdep (gdbarch)->num_aregs; ++i)
152  regcache_raw_supply (regcache,
153  gdbarch_tdep (gdbarch)->ar_base + i,
154  &regs->ar[i]);
155  }
156 }
157 
158 void
159 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
160 {
161  supply_gregset_reg (regcache, gregsetp, -1);
162 }
163 
164 void
166  gdb_fpregset_t *fpregsetp, int regnum)
167 {
168  return;
169 }
170 
171 void
173  const gdb_fpregset_t *fpregsetp)
174 {
175  return;
176 }
177 
178 /* Fetch greg-register(s) from process/thread TID
179  and store value(s) in GDB's register array. */
180 
181 static void
183 {
184  int tid = GET_THREAD_ID (inferior_ptid);
185  const gdb_gregset_t regs;
186  int areg;
187 
188  if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
189  {
190  perror_with_name (_("Couldn't get registers"));
191  return;
192  }
193 
194  supply_gregset_reg (regcache, &regs, regnum);
195 }
196 
197 /* Store greg-register(s) in GDB's register
198  array into the process/thread specified by TID. */
199 
200 static void
202 {
203  int tid = GET_THREAD_ID (inferior_ptid);
204  gdb_gregset_t regs;
205  int areg;
206 
207  if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
208  {
209  perror_with_name (_("Couldn't get registers"));
210  return;
211  }
212 
213  fill_gregset (regcache, &regs, regnum);
214 
215  if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
216  {
217  perror_with_name (_("Couldn't write registers"));
218  return;
219  }
220 }
221 
222 static int xtreg_lo;
223 static int xtreg_high;
224 
225 /* Fetch/Store Xtensa TIE registers. Xtensa GNU/Linux PTRACE
226  interface provides special requests for this. */
227 
228 static void
230 {
231  int tid = GET_THREAD_ID (inferior_ptid);
232  const xtensa_regtable_t *ptr;
233  char xtregs [XTENSA_ELF_XTREG_SIZE];
234 
235  if (ptrace (PTRACE_GETXTREGS, tid, 0, (long)&xtregs) < 0)
236  perror_with_name (_("Couldn't get extended registers"));
237 
238  for (ptr = xtensa_regmap_table; ptr->name; ptr++)
239  if (regnum == ptr->gdb_regnum || regnum == -1)
240  regcache_raw_supply (regcache, ptr->gdb_regnum,
241  xtregs + ptr->ptrace_offset);
242 }
243 
244 static void
246 {
247  int tid = GET_THREAD_ID (inferior_ptid);
248  const xtensa_regtable_t *ptr;
249  char xtregs [XTENSA_ELF_XTREG_SIZE];
250 
251  if (ptrace (PTRACE_GETXTREGS, tid, 0, (long)&xtregs) < 0)
252  perror_with_name (_("Couldn't get extended registers"));
253 
254  for (ptr = xtensa_regmap_table; ptr->name; ptr++)
255  if (regnum == ptr->gdb_regnum || regnum == -1)
256  regcache_raw_collect (regcache, ptr->gdb_regnum,
257  xtregs + ptr->ptrace_offset);
258 
259  if (ptrace (PTRACE_SETXTREGS, tid, 0, (long)&xtregs) < 0)
260  perror_with_name (_("Couldn't write extended registers"));
261 }
262 
263 void
265  struct regcache *regcache, int regnum)
266 {
267  if (regnum == -1)
268  {
269  fetch_gregs (regcache, regnum);
270  fetch_xtregs (regcache, regnum);
271  }
272  else if ((regnum < xtreg_lo) || (regnum > xtreg_high))
273  fetch_gregs (regcache, regnum);
274  else
275  fetch_xtregs (regcache, regnum);
276 }
277 
278 void
280  struct regcache *regcache, int regnum)
281 {
282  if (regnum == -1)
283  {
284  store_gregs (regcache, regnum);
285  store_xtregs (regcache, regnum);
286  }
287  else if ((regnum < xtreg_lo) || (regnum > xtreg_high))
288  store_gregs (regcache, regnum);
289  else
290  store_xtregs (regcache, regnum);
291 }
292 
293 void _initialize_xtensa_linux_nat (void);
294 
295 void
297 {
298  struct target_ops *t;
299  const xtensa_regtable_t *ptr;
300 
301  /* Calculate the number range for extended registers. */
302  xtreg_lo = 1000000000;
303  xtreg_high = -1;
304  for (ptr = xtensa_regmap_table; ptr->name; ptr++)
305  {
306  if (ptr->gdb_regnum < xtreg_lo)
307  xtreg_lo = ptr->gdb_regnum;
308  if (ptr->gdb_regnum > xtreg_high)
309  xtreg_high = ptr->gdb_regnum;
310  }
311 
312  /* Fill in the generic GNU/Linux methods. */
313  t = linux_target ();
314 
315  /* Add our register access methods. */
318 
320 }
const xtensa_regtable_t xtensa_regmap_table[]
Definition: xtensa-xtregs.c:33
static void fetch_gregs(struct regcache *regcache, int regnum)
static int xtreg_high
struct gdbarch * get_regcache_arch(const struct regcache *regcache)
Definition: regcache.c:297
xtensa_elf_greg_t ar[64]
Definition: xtensa-tdep.h:100
#define XTENSA_ELF_XTREG_SIZE
Definition: xtensa-xtregs.c:31
xtensa_elf_greg_t ps
Definition: xtensa-tdep.h:92
xtensa_elf_greg_t lbeg
Definition: xtensa-tdep.h:93
xtensa_elf_greg_t lend
Definition: xtensa-tdep.h:94
#define _(String)
Definition: gdb_locale.h:40
struct gdbarch_tdep * gdbarch_tdep(struct gdbarch *gdbarch)
Definition: gdbarch.c:1402
void _initialize_xtensa_linux_nat(void)
int gdbarch_ps_regnum(struct gdbarch *gdbarch)
Definition: gdbarch.c:2015
static void fetch_xtregs(struct regcache *regcache, int regnum)
PTRACE_TYPE_RET ptrace()
Definition: ptid.h:35
static void store_xtregs(struct regcache *regcache, int regnum)
void supply_fpregset(struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
static void store_gregs(struct regcache *regcache, int regnum)
#define GET_THREAD_ID(PTID)
void fill_gregset(const struct regcache *regcache, gdb_gregset_t *gregsetp, int regnum)
unsigned int num_aregs
Definition: xtensa-tdep.h:209
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-tdep.h:97
GDB_FPREGSET_T gdb_fpregset_t
Definition: gregset.h:35
void linux_nat_add_target(struct target_ops *t)
Definition: linux-nat.c:4972
xtensa_elf_greg_t windowbase
Definition: xtensa-tdep.h:98
int regnum
Definition: aarch64-tdep.c:69
void xtensa_linux_fetch_inferior_registers(struct target_ops *ops, struct regcache *regcache, int regnum)
struct target_ops * linux_target(void)
Definition: linux-nat.c:4544
void xtensa_linux_store_inferior_registers(struct target_ops *ops, struct regcache *regcache, int regnum)
xtensa_elf_greg_t lcount
Definition: xtensa-tdep.h:95
int ptid_get_pid(ptid_t ptid)
Definition: ptid.c:52
void(* to_fetch_registers)(struct target_ops *, struct regcache *, int) TARGET_DEFAULT_IGNORE()
Definition: target.h:472
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:979
ptid_t inferior_ptid
Definition: infcmd.c:124
static int xtreg_lo
xtensa_elf_greg_t sar
Definition: xtensa-tdep.h:96
#define PTRACE_SETREGS
static int get_thread_id(ptid_t ptid)
xtensa_elf_greg_t pc
Definition: xtensa-tdep.h:91
void regcache_raw_supply(struct regcache *regcache, int regnum, const void *buf)
Definition: regcache.c:1041
long ptid_get_lwp(ptid_t ptid)
Definition: ptid.c:60
void regcache_raw_collect(const struct regcache *regcache, int regnum, void *buf)
Definition: regcache.c:1071
int gdbarch_pc_regnum(struct gdbarch *gdbarch)
Definition: gdbarch.c:1998
void supply_gregset_reg(struct regcache *regcache, const gdb_gregset_t *gregsetp, int regnum)
void(* to_store_registers)(struct target_ops *, struct regcache *, int) TARGET_DEFAULT_NORETURN(noprocess())
Definition: target.h:474
#define PTRACE_GETREGS