1/* Native-dependent code for GNU/Linux on MIPS processors.
2
3   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
4   Free Software Foundation, Inc.
5
6   This file is part of GDB.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21#include "defs.h"
22#include "inferior.h"
23#include "mips-tdep.h"
24#include "target.h"
25#include "regcache.h"
26#include "linux-nat.h"
27#include "mips-linux-tdep.h"
28#include "target-descriptions.h"
29#include "xml-support.h"
30
31#include "gdb_proc_service.h"
32#include "gregset.h"
33
34#include <sgidefs.h>
35#include <sys/ptrace.h>
36
37#ifndef PTRACE_GET_THREAD_AREA
38#define PTRACE_GET_THREAD_AREA 25
39#endif
40
41/* Assume that we have PTRACE_GETREGS et al. support.  If we do not,
42   we'll clear this and use PTRACE_PEEKUSER instead.  */
43static int have_ptrace_regsets = 1;
44
45/* Saved function pointers to fetch and store a single register using
46   PTRACE_PEEKUSER and PTRACE_POKEUSER.  */
47
48void (*super_fetch_registers) (struct regcache *, int);
49void (*super_store_registers) (struct regcache *, int);
50
51/* Map gdb internal register number to ptrace ``address''.
52   These ``addresses'' are normally defined in <asm/ptrace.h>.
53
54   ptrace does not provide a way to read (or set) MIPS_PS_REGNUM,
55   and there's no point in reading or setting MIPS_ZERO_REGNUM.
56   We also can not set BADVADDR, CAUSE, or FCRIR via ptrace().  */
57
58static CORE_ADDR
59mips_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
60{
61  CORE_ADDR regaddr;
62
63  if (regno < 0 || regno >= gdbarch_num_regs (current_gdbarch))
64    error (_("Bogon register number %d."), regno);
65
66  if (regno > MIPS_ZERO_REGNUM && regno < MIPS_ZERO_REGNUM + 32)
67    regaddr = regno;
68  else if ((regno >= mips_regnum (gdbarch)->fp0)
69	   && (regno < mips_regnum (gdbarch)->fp0 + 32))
70    regaddr = FPR_BASE + (regno - mips_regnum (gdbarch)->fp0);
71  else if (regno == mips_regnum (gdbarch)->pc)
72    regaddr = PC;
73  else if (regno == mips_regnum (gdbarch)->cause)
74    regaddr = store? (CORE_ADDR) -1 : CAUSE;
75  else if (regno == mips_regnum (gdbarch)->badvaddr)
76    regaddr = store? (CORE_ADDR) -1 : BADVADDR;
77  else if (regno == mips_regnum (gdbarch)->lo)
78    regaddr = MMLO;
79  else if (regno == mips_regnum (gdbarch)->hi)
80    regaddr = MMHI;
81  else if (regno == mips_regnum (gdbarch)->fp_control_status)
82    regaddr = FPC_CSR;
83  else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
84    regaddr = store? (CORE_ADDR) -1 : FPC_EIR;
85  else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
86    regaddr = 0;
87  else
88    regaddr = (CORE_ADDR) -1;
89
90  return regaddr;
91}
92
93static CORE_ADDR
94mips64_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
95{
96  CORE_ADDR regaddr;
97
98  if (regno < 0 || regno >= gdbarch_num_regs (current_gdbarch))
99    error (_("Bogon register number %d."), regno);
100
101  if (regno > MIPS_ZERO_REGNUM && regno < MIPS_ZERO_REGNUM + 32)
102    regaddr = regno;
103  else if ((regno >= mips_regnum (gdbarch)->fp0)
104	   && (regno < mips_regnum (gdbarch)->fp0 + 32))
105    regaddr = MIPS64_FPR_BASE + (regno - gdbarch_fp0_regnum (current_gdbarch));
106  else if (regno == mips_regnum (gdbarch)->pc)
107    regaddr = MIPS64_PC;
108  else if (regno == mips_regnum (gdbarch)->cause)
109    regaddr = store? (CORE_ADDR) -1 : MIPS64_CAUSE;
110  else if (regno == mips_regnum (gdbarch)->badvaddr)
111    regaddr = store? (CORE_ADDR) -1 : MIPS64_BADVADDR;
112  else if (regno == mips_regnum (gdbarch)->lo)
113    regaddr = MIPS64_MMLO;
114  else if (regno == mips_regnum (gdbarch)->hi)
115    regaddr = MIPS64_MMHI;
116  else if (regno == mips_regnum (gdbarch)->fp_control_status)
117    regaddr = MIPS64_FPC_CSR;
118  else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
119    regaddr = store? (CORE_ADDR) -1 : MIPS64_FPC_EIR;
120  else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
121    regaddr = 0;
122  else
123    regaddr = (CORE_ADDR) -1;
124
125  return regaddr;
126}
127
128/* Fetch the thread-local storage pointer for libthread_db.  */
129
130ps_err_e
131ps_get_thread_area (const struct ps_prochandle *ph,
132                    lwpid_t lwpid, int idx, void **base)
133{
134  if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
135    return PS_ERR;
136
137  /* IDX is the bias from the thread pointer to the beginning of the
138     thread descriptor.  It has to be subtracted due to implementation
139     quirks in libthread_db.  */
140  *base = (void *) ((char *)*base - idx);
141
142  return PS_OK;
143}
144
145/* Wrapper functions.  These are only used by libthread_db.  */
146
147void
148supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
149{
150  if (mips_isa_regsize (current_gdbarch) == 4)
151    mips_supply_gregset (regcache, (const mips_elf_gregset_t *) gregsetp);
152  else
153    mips64_supply_gregset (regcache, (const mips64_elf_gregset_t *) gregsetp);
154}
155
156void
157fill_gregset (const struct regcache *regcache,
158	      gdb_gregset_t *gregsetp, int regno)
159{
160  if (mips_isa_regsize (current_gdbarch) == 4)
161    mips_fill_gregset (regcache, (mips_elf_gregset_t *) gregsetp, regno);
162  else
163    mips64_fill_gregset (regcache, (mips64_elf_gregset_t *) gregsetp, regno);
164}
165
166void
167supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
168{
169  if (mips_isa_regsize (current_gdbarch) == 4)
170    mips_supply_fpregset (regcache, (const mips_elf_fpregset_t *) fpregsetp);
171  else
172    mips64_supply_fpregset (regcache, (const mips64_elf_fpregset_t *) fpregsetp);
173}
174
175void
176fill_fpregset (const struct regcache *regcache,
177	       gdb_fpregset_t *fpregsetp, int regno)
178{
179  if (mips_isa_regsize (current_gdbarch) == 4)
180    mips_fill_fpregset (regcache, (mips_elf_fpregset_t *) fpregsetp, regno);
181  else
182    mips64_fill_fpregset (regcache, (mips64_elf_fpregset_t *) fpregsetp, regno);
183}
184
185
186/* Fetch REGNO (or all registers if REGNO == -1) from the target
187   using PTRACE_GETREGS et al.  */
188
189static void
190mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno)
191{
192  int is_fp;
193  int tid;
194
195  if (regno >= mips_regnum (current_gdbarch)->fp0
196      && regno <= mips_regnum (current_gdbarch)->fp0 + 32)
197    is_fp = 1;
198  else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
199    is_fp = 1;
200  else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
201    is_fp = 1;
202  else
203    is_fp = 0;
204
205  tid = ptid_get_lwp (inferior_ptid);
206  if (tid == 0)
207    tid = ptid_get_pid (inferior_ptid);
208
209  if (regno == -1 || !is_fp)
210    {
211      mips64_elf_gregset_t regs;
212
213      if (ptrace (PTRACE_GETREGS, tid, 0L, (PTRACE_TYPE_ARG3) &regs) == -1)
214	{
215	  if (errno == EIO)
216	    {
217	      have_ptrace_regsets = 0;
218	      return;
219	    }
220	  perror_with_name (_("Couldn't get registers"));
221	}
222
223      mips64_supply_gregset (regcache,
224			     (const mips64_elf_gregset_t *) &regs);
225    }
226
227  if (regno == -1 || is_fp)
228    {
229      mips64_elf_fpregset_t fp_regs;
230
231      if (ptrace (PTRACE_GETFPREGS, tid, 0L,
232		  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
233	{
234	  if (errno == EIO)
235	    {
236	      have_ptrace_regsets = 0;
237	      return;
238	    }
239	  perror_with_name (_("Couldn't get FP registers"));
240	}
241
242      mips64_supply_fpregset (regcache,
243			      (const mips64_elf_fpregset_t *) &fp_regs);
244    }
245}
246
247/* Store REGNO (or all registers if REGNO == -1) to the target
248   using PTRACE_SETREGS et al.  */
249
250static void
251mips64_linux_regsets_store_registers (const struct regcache *regcache, int regno)
252{
253  int is_fp;
254  int tid;
255
256  if (regno >= mips_regnum (current_gdbarch)->fp0
257      && regno <= mips_regnum (current_gdbarch)->fp0 + 32)
258    is_fp = 1;
259  else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
260    is_fp = 1;
261  else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
262    is_fp = 1;
263  else
264    is_fp = 0;
265
266  tid = ptid_get_lwp (inferior_ptid);
267  if (tid == 0)
268    tid = ptid_get_pid (inferior_ptid);
269
270  if (regno == -1 || !is_fp)
271    {
272      mips64_elf_gregset_t regs;
273
274      if (ptrace (PTRACE_GETREGS, tid, 0L, (PTRACE_TYPE_ARG3) &regs) == -1)
275	perror_with_name (_("Couldn't get registers"));
276
277      mips64_fill_gregset (regcache, &regs, regno);
278
279      if (ptrace (PTRACE_SETREGS, tid, 0L, (PTRACE_TYPE_ARG3) &regs) == -1)
280	perror_with_name (_("Couldn't set registers"));
281    }
282
283  if (regno == -1 || is_fp)
284    {
285      mips64_elf_fpregset_t fp_regs;
286
287      if (ptrace (PTRACE_GETFPREGS, tid, 0L,
288		  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
289	perror_with_name (_("Couldn't get FP registers"));
290
291      mips64_fill_fpregset (regcache, &fp_regs, regno);
292
293      if (ptrace (PTRACE_SETFPREGS, tid, 0L,
294		  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
295	perror_with_name (_("Couldn't set FP registers"));
296    }
297}
298
299/* Fetch REGNO (or all registers if REGNO == -1) from the target
300   using any working method.  */
301
302static void
303mips64_linux_fetch_registers (struct regcache *regcache, int regnum)
304{
305  /* Unless we already know that PTRACE_GETREGS does not work, try it.  */
306  if (have_ptrace_regsets)
307    mips64_linux_regsets_fetch_registers (regcache, regnum);
308
309  /* If we know, or just found out, that PTRACE_GETREGS does not work, fall
310     back to PTRACE_PEEKUSER.  */
311  if (!have_ptrace_regsets)
312    super_fetch_registers (regcache, regnum);
313}
314
315/* Store REGNO (or all registers if REGNO == -1) to the target
316   using any working method.  */
317
318static void
319mips64_linux_store_registers (struct regcache *regcache, int regnum)
320{
321  /* Unless we already know that PTRACE_GETREGS does not work, try it.  */
322  if (have_ptrace_regsets)
323    mips64_linux_regsets_store_registers (regcache, regnum);
324
325  /* If we know, or just found out, that PTRACE_GETREGS does not work, fall
326     back to PTRACE_PEEKUSER.  */
327  if (!have_ptrace_regsets)
328    super_store_registers (regcache, regnum);
329}
330
331/* Return the address in the core dump or inferior of register
332   REGNO.  */
333
334static CORE_ADDR
335mips_linux_register_u_offset (struct gdbarch *gdbarch, int regno, int store_p)
336{
337  if (mips_abi_regsize (gdbarch) == 8)
338    return mips64_linux_register_addr (gdbarch, regno, store_p);
339  else
340    return mips_linux_register_addr (gdbarch, regno, store_p);
341}
342
343static LONGEST (*super_xfer_partial) (struct target_ops *, enum target_object,
344				      const char *, gdb_byte *, const gdb_byte *,
345				      ULONGEST, LONGEST);
346
347static LONGEST
348mips_linux_xfer_partial (struct target_ops *ops,
349			 enum target_object object,
350			 const char *annex,
351			 gdb_byte *readbuf, const gdb_byte *writebuf,
352			 ULONGEST offset, LONGEST len)
353{
354  if (object == TARGET_OBJECT_AVAILABLE_FEATURES)
355    {
356      if (annex != NULL && strcmp (annex, "target.xml") == 0)
357	{
358	  /* Report that target registers are a size we know for sure
359	     that we can get from ptrace.  */
360	  if (_MIPS_SIM == _ABIO32)
361	    annex = "mips-linux.xml";
362	  else
363	    annex = "mips64-linux.xml";
364	}
365
366      return xml_builtin_xfer_partial (annex, readbuf, writebuf, offset, len);
367    }
368
369  return super_xfer_partial (ops, object, annex, readbuf, writebuf,
370			     offset, len);
371}
372
373void _initialize_mips_linux_nat (void);
374
375void
376_initialize_mips_linux_nat (void)
377{
378  struct target_ops *t = linux_trad_target (mips_linux_register_u_offset);
379
380  super_fetch_registers = t->to_fetch_registers;
381  super_store_registers = t->to_store_registers;
382
383  t->to_fetch_registers = mips64_linux_fetch_registers;
384  t->to_store_registers = mips64_linux_store_registers;
385
386  /* Override the default to_xfer_partial.  */
387  super_xfer_partial = t->to_xfer_partial;
388  t->to_xfer_partial = mips_linux_xfer_partial;
389
390  linux_nat_add_target (t);
391}
392