gdb/
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-mips-low.c
CommitLineData
0a30fbc4 1/* GNU/Linux/MIPS specific low level interface, for the remote server for GDB.
28e7fd62 2 Copyright (C) 1995-2013 Free Software Foundation, Inc.
0a30fbc4
DJ
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
a9762ec7 8 the Free Software Foundation; either version 3 of the License, or
0a30fbc4
DJ
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
a9762ec7 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
0a30fbc4
DJ
18
19#include "server.h"
58caa3dc 20#include "linux-low.h"
0a30fbc4 21
21b0f40c 22#include <sys/ptrace.h>
186947f7 23#include <endian.h>
21b0f40c
DJ
24
25#include "gdb_proc_service.h"
26
d05b4ac3
UW
27/* Defined in auto-generated file mips-linux.c. */
28void init_registers_mips_linux (void);
3aee8918
PA
29extern const struct target_desc *tdesc_mips_linux;
30
1faeff08
MR
31/* Defined in auto-generated file mips-dsp-linux.c. */
32void init_registers_mips_dsp_linux (void);
3aee8918
PA
33extern const struct target_desc *tdesc_mips_dsp_linux;
34
d05b4ac3
UW
35/* Defined in auto-generated file mips64-linux.c. */
36void init_registers_mips64_linux (void);
3aee8918
PA
37extern const struct target_desc *tdesc_mips64_linux;
38
1faeff08
MR
39/* Defined in auto-generated file mips64-dsp-linux.c. */
40void init_registers_mips64_dsp_linux (void);
3aee8918 41extern const struct target_desc *tdesc_mips64_dsp_linux;
1faeff08
MR
42
43#ifdef __mips64
3aee8918
PA
44#define tdesc_mips_linux tdesc_mips64_linux
45#define tdesc_mips_dsp_linux tdesc_mips64_dsp_linux
1faeff08 46#endif
d05b4ac3 47
21b0f40c
DJ
48#ifndef PTRACE_GET_THREAD_AREA
49#define PTRACE_GET_THREAD_AREA 25
50#endif
51
0a30fbc4
DJ
52#ifdef HAVE_SYS_REG_H
53#include <sys/reg.h>
54#endif
55
117ce543 56#define mips_num_regs 73
1faeff08 57#define mips_dsp_num_regs 80
0a30fbc4
DJ
58
59#include <asm/ptrace.h>
60
1faeff08
MR
61#ifndef DSP_BASE
62#define DSP_BASE 71
63#define DSP_CONTROL 77
64#endif
65
186947f7
DJ
66union mips_register
67{
68 unsigned char buf[8];
69
70 /* Deliberately signed, for proper sign extension. */
71 int reg32;
72 long long reg64;
73};
74
0a30fbc4
DJ
75/* Return the ptrace ``address'' of register REGNO. */
76
1faeff08
MR
77#define mips_base_regs \
78 -1, 1, 2, 3, 4, 5, 6, 7, \
79 8, 9, 10, 11, 12, 13, 14, 15, \
80 16, 17, 18, 19, 20, 21, 22, 23, \
81 24, 25, 26, 27, 28, 29, 30, 31, \
82 \
83 -1, MMLO, MMHI, BADVADDR, CAUSE, PC, \
84 \
85 FPR_BASE, FPR_BASE + 1, FPR_BASE + 2, FPR_BASE + 3, \
86 FPR_BASE + 4, FPR_BASE + 5, FPR_BASE + 6, FPR_BASE + 7, \
87 FPR_BASE + 8, FPR_BASE + 9, FPR_BASE + 10, FPR_BASE + 11, \
88 FPR_BASE + 12, FPR_BASE + 13, FPR_BASE + 14, FPR_BASE + 15, \
89 FPR_BASE + 16, FPR_BASE + 17, FPR_BASE + 18, FPR_BASE + 19, \
90 FPR_BASE + 20, FPR_BASE + 21, FPR_BASE + 22, FPR_BASE + 23, \
91 FPR_BASE + 24, FPR_BASE + 25, FPR_BASE + 26, FPR_BASE + 27, \
92 FPR_BASE + 28, FPR_BASE + 29, FPR_BASE + 30, FPR_BASE + 31, \
93 FPC_CSR, FPC_EIR
94
95#define mips_dsp_regs \
96 DSP_BASE, DSP_BASE + 1, DSP_BASE + 2, DSP_BASE + 3, \
97 DSP_BASE + 4, DSP_BASE + 5, \
98 DSP_CONTROL
99
100static int mips_regmap[mips_num_regs] = {
101 mips_base_regs,
102 0
103};
0a30fbc4 104
1faeff08
MR
105static int mips_dsp_regmap[mips_dsp_num_regs] = {
106 mips_base_regs,
107 mips_dsp_regs,
108 0
109};
0a30fbc4 110
1faeff08
MR
111/* DSP registers are not in any regset and can only be accessed
112 individually. */
0a30fbc4 113
1faeff08
MR
114static unsigned char mips_dsp_regset_bitmap[(mips_dsp_num_regs + 7) / 8] = {
115 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x80
0a30fbc4
DJ
116};
117
3aee8918
PA
118static int have_dsp = -1;
119
1faeff08
MR
120/* Try peeking at an arbitrarily chosen DSP register and pick the available
121 user register set accordingly. */
122
3aee8918
PA
123static const struct target_desc *
124mips_read_description (void)
1faeff08 125{
3aee8918 126 if (have_dsp < 0)
1faeff08
MR
127 {
128 int pid = lwpid_of (get_thread_lwp (current_inferior));
129
130 ptrace (PTRACE_PEEKUSER, pid, DSP_CONTROL, 0);
131 switch (errno)
132 {
133 case 0:
3aee8918 134 have_dsp = 1;
1faeff08
MR
135 break;
136 case EIO:
3aee8918 137 have_dsp = 0;
1faeff08
MR
138 break;
139 default:
140 perror_with_name ("ptrace");
141 break;
142 }
143 }
3aee8918
PA
144
145 return have_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
146}
147
148static void
149mips_arch_setup (void)
150{
151 current_process ()->tdesc = mips_read_description ();
152}
153
154static struct usrregs_info *
155get_usrregs_info (void)
156{
157 const struct regs_info *regs_info = the_low_target.regs_info ();
158
159 return regs_info->usrregs;
1faeff08
MR
160}
161
0a30fbc4
DJ
162/* From mips-linux-nat.c. */
163
164/* Pseudo registers can not be read. ptrace does not provide a way to
165 read (or set) PS_REGNUM, and there's no point in reading or setting
166 ZERO_REGNUM. We also can not set BADVADDR, CAUSE, or FCRIR via
167 ptrace(). */
168
2ec06d2e
DJ
169static int
170mips_cannot_fetch_register (int regno)
0a30fbc4 171{
3aee8918
PA
172 const struct target_desc *tdesc;
173
174 if (get_usrregs_info ()->regmap[regno] == -1)
0a30fbc4
DJ
175 return 1;
176
3aee8918
PA
177 tdesc = current_process ()->tdesc;
178
179 if (find_regno (tdesc, "r0") == regno)
0a30fbc4
DJ
180 return 1;
181
182 return 0;
183}
184
2ec06d2e
DJ
185static int
186mips_cannot_store_register (int regno)
0a30fbc4 187{
3aee8918
PA
188 const struct target_desc *tdesc;
189
190 if (get_usrregs_info ()->regmap[regno] == -1)
0a30fbc4
DJ
191 return 1;
192
3aee8918
PA
193 tdesc = current_process ()->tdesc;
194
195 if (find_regno (tdesc, "r0") == regno)
0a30fbc4
DJ
196 return 1;
197
3aee8918 198 if (find_regno (tdesc, "cause") == regno)
0a30fbc4
DJ
199 return 1;
200
3aee8918 201 if (find_regno (tdesc, "badvaddr") == regno)
0a30fbc4
DJ
202 return 1;
203
3aee8918 204 if (find_regno (tdesc, "fir") == regno)
0a30fbc4
DJ
205 return 1;
206
207 return 0;
208}
2ec06d2e 209
0d62e5e8 210static CORE_ADDR
442ea881 211mips_get_pc (struct regcache *regcache)
0d62e5e8 212{
186947f7 213 union mips_register pc;
442ea881 214 collect_register_by_name (regcache, "pc", pc.buf);
3aee8918 215 return register_size (regcache->tdesc, 0) == 4 ? pc.reg32 : pc.reg64;
0d62e5e8
DJ
216}
217
218static void
442ea881 219mips_set_pc (struct regcache *regcache, CORE_ADDR pc)
0d62e5e8 220{
186947f7 221 union mips_register newpc;
3aee8918 222 if (register_size (regcache->tdesc, 0) == 4)
186947f7
DJ
223 newpc.reg32 = pc;
224 else
225 newpc.reg64 = pc;
226
442ea881 227 supply_register_by_name (regcache, "pc", newpc.buf);
0d62e5e8
DJ
228}
229
230/* Correct in either endianness. */
186947f7 231static const unsigned int mips_breakpoint = 0x0005000d;
0d62e5e8
DJ
232#define mips_breakpoint_len 4
233
234/* We only place breakpoints in empty marker functions, and thread locking
235 is outside of the function. So rather than importing software single-step,
236 we can just run until exit. */
237static CORE_ADDR
442ea881 238mips_reinsert_addr (void)
0d62e5e8 239{
442ea881 240 struct regcache *regcache = get_thread_regcache (current_inferior, 1);
186947f7 241 union mips_register ra;
442ea881 242 collect_register_by_name (regcache, "r31", ra.buf);
3aee8918 243 return register_size (regcache->tdesc, 0) == 4 ? ra.reg32 : ra.reg64;
0d62e5e8
DJ
244}
245
246static int
247mips_breakpoint_at (CORE_ADDR where)
248{
186947f7 249 unsigned int insn;
0d62e5e8 250
f450004a 251 (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
0d62e5e8
DJ
252 if (insn == mips_breakpoint)
253 return 1;
254
255 /* If necessary, recognize more trap instructions here. GDB only uses the
256 one. */
257 return 0;
258}
259
21b0f40c
DJ
260/* Fetch the thread-local storage pointer for libthread_db. */
261
262ps_err_e
263ps_get_thread_area (const struct ps_prochandle *ph,
1b3f6016 264 lwpid_t lwpid, int idx, void **base)
21b0f40c
DJ
265{
266 if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
267 return PS_ERR;
268
269 /* IDX is the bias from the thread pointer to the beginning of the
270 thread descriptor. It has to be subtracted due to implementation
271 quirks in libthread_db. */
272 *base = (void *) ((char *)*base - idx);
273
274 return PS_OK;
275}
276
186947f7
DJ
277#ifdef HAVE_PTRACE_GETREGS
278
279static void
442ea881
PA
280mips_collect_register (struct regcache *regcache,
281 int use_64bit, int regno, union mips_register *reg)
186947f7
DJ
282{
283 union mips_register tmp_reg;
284
285 if (use_64bit)
286 {
442ea881 287 collect_register (regcache, regno, &tmp_reg.reg64);
186947f7
DJ
288 *reg = tmp_reg;
289 }
290 else
291 {
442ea881 292 collect_register (regcache, regno, &tmp_reg.reg32);
186947f7
DJ
293 reg->reg64 = tmp_reg.reg32;
294 }
295}
296
297static void
442ea881
PA
298mips_supply_register (struct regcache *regcache,
299 int use_64bit, int regno, const union mips_register *reg)
186947f7
DJ
300{
301 int offset = 0;
302
303 /* For big-endian 32-bit targets, ignore the high four bytes of each
304 eight-byte slot. */
305 if (__BYTE_ORDER == __BIG_ENDIAN && !use_64bit)
306 offset = 4;
307
442ea881 308 supply_register (regcache, regno, reg->buf + offset);
186947f7
DJ
309}
310
311static void
442ea881
PA
312mips_collect_register_32bit (struct regcache *regcache,
313 int use_64bit, int regno, unsigned char *buf)
186947f7
DJ
314{
315 union mips_register tmp_reg;
316 int reg32;
317
442ea881 318 mips_collect_register (regcache, use_64bit, regno, &tmp_reg);
186947f7
DJ
319 reg32 = tmp_reg.reg64;
320 memcpy (buf, &reg32, 4);
321}
322
323static void
442ea881
PA
324mips_supply_register_32bit (struct regcache *regcache,
325 int use_64bit, int regno, const unsigned char *buf)
186947f7
DJ
326{
327 union mips_register tmp_reg;
328 int reg32;
329
330 memcpy (&reg32, buf, 4);
331 tmp_reg.reg64 = reg32;
442ea881 332 mips_supply_register (regcache, use_64bit, regno, &tmp_reg);
186947f7
DJ
333}
334
335static void
442ea881 336mips_fill_gregset (struct regcache *regcache, void *buf)
186947f7
DJ
337{
338 union mips_register *regset = buf;
339 int i, use_64bit;
3aee8918 340 const struct target_desc *tdesc = regcache->tdesc;
186947f7 341
3aee8918 342 use_64bit = (register_size (tdesc, 0) == 8);
186947f7 343
117ce543 344 for (i = 1; i < 32; i++)
442ea881
PA
345 mips_collect_register (regcache, use_64bit, i, regset + i);
346
347 mips_collect_register (regcache, use_64bit,
3aee8918 348 find_regno (tdesc, "lo"), regset + 32);
442ea881 349 mips_collect_register (regcache, use_64bit,
3aee8918 350 find_regno (tdesc, "hi"), regset + 33);
442ea881 351 mips_collect_register (regcache, use_64bit,
3aee8918 352 find_regno (tdesc, "pc"), regset + 34);
442ea881 353 mips_collect_register (regcache, use_64bit,
3aee8918 354 find_regno (tdesc, "badvaddr"), regset + 35);
442ea881 355 mips_collect_register (regcache, use_64bit,
3aee8918 356 find_regno (tdesc, "status"), regset + 36);
442ea881 357 mips_collect_register (regcache, use_64bit,
3aee8918 358 find_regno (tdesc, "cause"), regset + 37);
442ea881
PA
359
360 mips_collect_register (regcache, use_64bit,
3aee8918 361 find_regno (tdesc, "restart"), regset + 0);
186947f7
DJ
362}
363
364static void
442ea881 365mips_store_gregset (struct regcache *regcache, const void *buf)
186947f7
DJ
366{
367 const union mips_register *regset = buf;
368 int i, use_64bit;
369
3aee8918 370 use_64bit = (register_size (regcache->tdesc, 0) == 8);
186947f7
DJ
371
372 for (i = 0; i < 32; i++)
442ea881
PA
373 mips_supply_register (regcache, use_64bit, i, regset + i);
374
442ea881 375 mips_supply_register (regcache, use_64bit,
3aee8918
PA
376 find_regno (regcache->tdesc, "lo"), regset + 32);
377 mips_supply_register (regcache, use_64bit,
378 find_regno (regcache->tdesc, "hi"), regset + 33);
442ea881 379 mips_supply_register (regcache, use_64bit,
3aee8918 380 find_regno (regcache->tdesc, "pc"), regset + 34);
442ea881 381 mips_supply_register (regcache, use_64bit,
3aee8918
PA
382 find_regno (regcache->tdesc, "badvaddr"), regset + 35);
383 mips_supply_register (regcache, use_64bit,
384 find_regno (regcache->tdesc, "status"), regset + 36);
385 mips_supply_register (regcache, use_64bit,
386 find_regno (regcache->tdesc, "cause"), regset + 37);
442ea881
PA
387
388 mips_supply_register (regcache, use_64bit,
3aee8918 389 find_regno (regcache->tdesc, "restart"), regset + 0);
186947f7
DJ
390}
391
392static void
442ea881 393mips_fill_fpregset (struct regcache *regcache, void *buf)
186947f7
DJ
394{
395 union mips_register *regset = buf;
396 int i, use_64bit, first_fp, big_endian;
397
3aee8918
PA
398 use_64bit = (register_size (regcache->tdesc, 0) == 8);
399 first_fp = find_regno (regcache->tdesc, "f0");
186947f7
DJ
400 big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
401
402 /* See GDB for a discussion of this peculiar layout. */
403 for (i = 0; i < 32; i++)
404 if (use_64bit)
442ea881 405 collect_register (regcache, first_fp + i, regset[i].buf);
186947f7 406 else
442ea881 407 collect_register (regcache, first_fp + i,
186947f7
DJ
408 regset[i & ~1].buf + 4 * (big_endian != (i & 1)));
409
442ea881 410 mips_collect_register_32bit (regcache, use_64bit,
3aee8918
PA
411 find_regno (regcache->tdesc, "fcsr"), regset[32].buf);
412 mips_collect_register_32bit (regcache, use_64bit,
413 find_regno (regcache->tdesc, "fir"),
186947f7
DJ
414 regset[32].buf + 4);
415}
416
417static void
442ea881 418mips_store_fpregset (struct regcache *regcache, const void *buf)
186947f7
DJ
419{
420 const union mips_register *regset = buf;
421 int i, use_64bit, first_fp, big_endian;
422
3aee8918
PA
423 use_64bit = (register_size (regcache->tdesc, 0) == 8);
424 first_fp = find_regno (regcache->tdesc, "f0");
186947f7
DJ
425 big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
426
427 /* See GDB for a discussion of this peculiar layout. */
428 for (i = 0; i < 32; i++)
429 if (use_64bit)
442ea881 430 supply_register (regcache, first_fp + i, regset[i].buf);
186947f7 431 else
442ea881 432 supply_register (regcache, first_fp + i,
186947f7
DJ
433 regset[i & ~1].buf + 4 * (big_endian != (i & 1)));
434
442ea881 435 mips_supply_register_32bit (regcache, use_64bit,
3aee8918
PA
436 find_regno (regcache->tdesc, "fcsr"),
437 regset[32].buf);
438 mips_supply_register_32bit (regcache, use_64bit,
439 find_regno (regcache->tdesc, "fir"),
186947f7
DJ
440 regset[32].buf + 4);
441}
442#endif /* HAVE_PTRACE_GETREGS */
443
3aee8918 444static struct regset_info mips_regsets[] = {
186947f7 445#ifdef HAVE_PTRACE_GETREGS
1570b33e 446 { PTRACE_GETREGS, PTRACE_SETREGS, 0, 38 * 8, GENERAL_REGS,
186947f7 447 mips_fill_gregset, mips_store_gregset },
1570b33e 448 { PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, 33 * 8, FP_REGS,
186947f7
DJ
449 mips_fill_fpregset, mips_store_fpregset },
450#endif /* HAVE_PTRACE_GETREGS */
1570b33e 451 { 0, 0, 0, -1, -1, NULL, NULL }
186947f7
DJ
452};
453
3aee8918
PA
454static struct regsets_info mips_regsets_info =
455 {
456 mips_regsets, /* regsets */
457 0, /* num_regsets */
458 NULL, /* disabled_regsets */
459 };
460
461static struct usrregs_info mips_dsp_usrregs_info =
462 {
463 mips_dsp_num_regs,
464 mips_dsp_regmap,
465 };
466
467static struct usrregs_info mips_usrregs_info =
468 {
469 mips_num_regs,
470 mips_regmap,
471 };
472
473static struct regs_info dsp_regs_info =
474 {
475 mips_dsp_regset_bitmap,
476 &mips_dsp_usrregs_info,
477 &mips_regsets_info
478 };
479
480static struct regs_info regs_info =
481 {
482 NULL, /* regset_bitmap */
483 &mips_usrregs_info,
484 &mips_regsets_info
485 };
486
487static const struct regs_info *
488mips_regs_info (void)
489{
490 if (have_dsp)
491 return &dsp_regs_info;
492 else
493 return &regs_info;
494}
495
2ec06d2e 496struct linux_target_ops the_low_target = {
1faeff08 497 mips_arch_setup,
3aee8918 498 mips_regs_info,
2ec06d2e
DJ
499 mips_cannot_fetch_register,
500 mips_cannot_store_register,
c14dfd32 501 NULL, /* fetch_register */
0d62e5e8
DJ
502 mips_get_pc,
503 mips_set_pc,
f450004a 504 (const unsigned char *) &mips_breakpoint,
0d62e5e8
DJ
505 mips_breakpoint_len,
506 mips_reinsert_addr,
507 0,
508 mips_breakpoint_at,
2ec06d2e 509};
3aee8918
PA
510
511void
512initialize_low_arch (void)
513{
514 /* Initialize the Linux target descriptions. */
515 init_registers_mips_linux ();
516 init_registers_mips_dsp_linux ();
517 init_registers_mips64_linux ();
518 init_registers_mips64_dsp_linux ();
519
520 initialize_regsets_info (&mips_regsets_info);
521}
This page took 0.859518 seconds and 4 git commands to generate.