OSDN Git Service

Merge branch 'binutils' into tmp
[pf3gnuchains/pf3gnuchains4x.git] / gdb / gdbserver / linux-mips-low.c
1 /* GNU/Linux/MIPS specific low level interface, for the remote server for GDB.
2    Copyright (C) 1995-1996, 1998-2002, 2005-2012 Free Software
3    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 "server.h"
21 #include "linux-low.h"
22
23 #include <sys/ptrace.h>
24 #include <endian.h>
25
26 #include "gdb_proc_service.h"
27
28 /* Defined in auto-generated file mips-linux.c.  */
29 void init_registers_mips_linux (void);
30 /* Defined in auto-generated file mips64-linux.c.  */
31 void init_registers_mips64_linux (void);
32
33 #ifndef PTRACE_GET_THREAD_AREA
34 #define PTRACE_GET_THREAD_AREA 25
35 #endif
36
37 #ifdef HAVE_SYS_REG_H
38 #include <sys/reg.h>
39 #endif
40
41 #define mips_num_regs 73
42
43 #include <asm/ptrace.h>
44
45 union mips_register
46 {
47   unsigned char buf[8];
48
49   /* Deliberately signed, for proper sign extension.  */
50   int reg32;
51   long long reg64;
52 };
53
54 /* Return the ptrace ``address'' of register REGNO. */
55
56 static int mips_regmap[] = {
57   -1,  1,  2,  3,  4,  5,  6,  7,
58   8,  9,  10, 11, 12, 13, 14, 15,
59   16, 17, 18, 19, 20, 21, 22, 23,
60   24, 25, 26, 27, 28, 29, 30, 31,
61
62   -1, MMLO, MMHI, BADVADDR, CAUSE, PC,
63
64   FPR_BASE,      FPR_BASE + 1,  FPR_BASE + 2,  FPR_BASE + 3,
65   FPR_BASE + 4,  FPR_BASE + 5,  FPR_BASE + 6,  FPR_BASE + 7,
66   FPR_BASE + 8,  FPR_BASE + 8,  FPR_BASE + 10, FPR_BASE + 11,
67   FPR_BASE + 12, FPR_BASE + 13, FPR_BASE + 14, FPR_BASE + 15,
68   FPR_BASE + 16, FPR_BASE + 17, FPR_BASE + 18, FPR_BASE + 19,
69   FPR_BASE + 20, FPR_BASE + 21, FPR_BASE + 22, FPR_BASE + 23,
70   FPR_BASE + 24, FPR_BASE + 25, FPR_BASE + 26, FPR_BASE + 27,
71   FPR_BASE + 28, FPR_BASE + 29, FPR_BASE + 30, FPR_BASE + 31,
72   FPC_CSR, FPC_EIR,
73
74   0
75 };
76
77 /* From mips-linux-nat.c.  */
78
79 /* Pseudo registers can not be read.  ptrace does not provide a way to
80    read (or set) PS_REGNUM, and there's no point in reading or setting
81    ZERO_REGNUM.  We also can not set BADVADDR, CAUSE, or FCRIR via
82    ptrace().  */
83
84 static int
85 mips_cannot_fetch_register (int regno)
86 {
87   if (mips_regmap[regno] == -1)
88     return 1;
89
90   if (find_regno ("r0") == regno)
91     return 1;
92
93   return 0;
94 }
95
96 static int
97 mips_cannot_store_register (int regno)
98 {
99   if (mips_regmap[regno] == -1)
100     return 1;
101
102   if (find_regno ("r0") == regno)
103     return 1;
104
105   if (find_regno ("cause") == regno)
106     return 1;
107
108   if (find_regno ("badvaddr") == regno)
109     return 1;
110
111   if (find_regno ("fir") == regno)
112     return 1;
113
114   return 0;
115 }
116
117 static CORE_ADDR
118 mips_get_pc (struct regcache *regcache)
119 {
120   union mips_register pc;
121   collect_register_by_name (regcache, "pc", pc.buf);
122   return register_size (0) == 4 ? pc.reg32 : pc.reg64;
123 }
124
125 static void
126 mips_set_pc (struct regcache *regcache, CORE_ADDR pc)
127 {
128   union mips_register newpc;
129   if (register_size (0) == 4)
130     newpc.reg32 = pc;
131   else
132     newpc.reg64 = pc;
133
134   supply_register_by_name (regcache, "pc", newpc.buf);
135 }
136
137 /* Correct in either endianness.  */
138 static const unsigned int mips_breakpoint = 0x0005000d;
139 #define mips_breakpoint_len 4
140
141 /* We only place breakpoints in empty marker functions, and thread locking
142    is outside of the function.  So rather than importing software single-step,
143    we can just run until exit.  */
144 static CORE_ADDR
145 mips_reinsert_addr (void)
146 {
147   struct regcache *regcache = get_thread_regcache (current_inferior, 1);
148   union mips_register ra;
149   collect_register_by_name (regcache, "r31", ra.buf);
150   return register_size (0) == 4 ? ra.reg32 : ra.reg64;
151 }
152
153 static int
154 mips_breakpoint_at (CORE_ADDR where)
155 {
156   unsigned int insn;
157
158   (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
159   if (insn == mips_breakpoint)
160     return 1;
161
162   /* If necessary, recognize more trap instructions here.  GDB only uses the
163      one.  */
164   return 0;
165 }
166
167 /* Fetch the thread-local storage pointer for libthread_db.  */
168
169 ps_err_e
170 ps_get_thread_area (const struct ps_prochandle *ph,
171                     lwpid_t lwpid, int idx, void **base)
172 {
173   if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
174     return PS_ERR;
175
176   /* IDX is the bias from the thread pointer to the beginning of the
177      thread descriptor.  It has to be subtracted due to implementation
178      quirks in libthread_db.  */
179   *base = (void *) ((char *)*base - idx);
180
181   return PS_OK;
182 }
183
184 #ifdef HAVE_PTRACE_GETREGS
185
186 static void
187 mips_collect_register (struct regcache *regcache,
188                        int use_64bit, int regno, union mips_register *reg)
189 {
190   union mips_register tmp_reg;
191
192   if (use_64bit)
193     {
194       collect_register (regcache, regno, &tmp_reg.reg64);
195       *reg = tmp_reg;
196     }
197   else
198     {
199       collect_register (regcache, regno, &tmp_reg.reg32);
200       reg->reg64 = tmp_reg.reg32;
201     }
202 }
203
204 static void
205 mips_supply_register (struct regcache *regcache,
206                       int use_64bit, int regno, const union mips_register *reg)
207 {
208   int offset = 0;
209
210   /* For big-endian 32-bit targets, ignore the high four bytes of each
211      eight-byte slot.  */
212   if (__BYTE_ORDER == __BIG_ENDIAN && !use_64bit)
213     offset = 4;
214
215   supply_register (regcache, regno, reg->buf + offset);
216 }
217
218 static void
219 mips_collect_register_32bit (struct regcache *regcache,
220                              int use_64bit, int regno, unsigned char *buf)
221 {
222   union mips_register tmp_reg;
223   int reg32;
224
225   mips_collect_register (regcache, use_64bit, regno, &tmp_reg);
226   reg32 = tmp_reg.reg64;
227   memcpy (buf, &reg32, 4);
228 }
229
230 static void
231 mips_supply_register_32bit (struct regcache *regcache,
232                             int use_64bit, int regno, const unsigned char *buf)
233 {
234   union mips_register tmp_reg;
235   int reg32;
236
237   memcpy (&reg32, buf, 4);
238   tmp_reg.reg64 = reg32;
239   mips_supply_register (regcache, use_64bit, regno, &tmp_reg);
240 }
241
242 static void
243 mips_fill_gregset (struct regcache *regcache, void *buf)
244 {
245   union mips_register *regset = buf;
246   int i, use_64bit;
247
248   use_64bit = (register_size (0) == 8);
249
250   for (i = 1; i < 32; i++)
251     mips_collect_register (regcache, use_64bit, i, regset + i);
252
253   mips_collect_register (regcache, use_64bit,
254                          find_regno ("lo"), regset + 32);
255   mips_collect_register (regcache, use_64bit,
256                          find_regno ("hi"), regset + 33);
257   mips_collect_register (regcache, use_64bit,
258                          find_regno ("pc"), regset + 34);
259   mips_collect_register (regcache, use_64bit,
260                          find_regno ("badvaddr"), regset + 35);
261   mips_collect_register (regcache, use_64bit,
262                          find_regno ("status"), regset + 36);
263   mips_collect_register (regcache, use_64bit,
264                          find_regno ("cause"), regset + 37);
265
266   mips_collect_register (regcache, use_64bit,
267                          find_regno ("restart"), regset + 0);
268 }
269
270 static void
271 mips_store_gregset (struct regcache *regcache, const void *buf)
272 {
273   const union mips_register *regset = buf;
274   int i, use_64bit;
275
276   use_64bit = (register_size (0) == 8);
277
278   for (i = 0; i < 32; i++)
279     mips_supply_register (regcache, use_64bit, i, regset + i);
280
281   mips_supply_register (regcache, use_64bit, find_regno ("lo"), regset + 32);
282   mips_supply_register (regcache, use_64bit, find_regno ("hi"), regset + 33);
283   mips_supply_register (regcache, use_64bit, find_regno ("pc"), regset + 34);
284   mips_supply_register (regcache, use_64bit,
285                         find_regno ("badvaddr"), regset + 35);
286   mips_supply_register (regcache, use_64bit,
287                         find_regno ("status"), regset + 36);
288   mips_supply_register (regcache, use_64bit,
289                         find_regno ("cause"), regset + 37);
290
291   mips_supply_register (regcache, use_64bit,
292                         find_regno ("restart"), regset + 0);
293 }
294
295 static void
296 mips_fill_fpregset (struct regcache *regcache, void *buf)
297 {
298   union mips_register *regset = buf;
299   int i, use_64bit, first_fp, big_endian;
300
301   use_64bit = (register_size (0) == 8);
302   first_fp = find_regno ("f0");
303   big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
304
305   /* See GDB for a discussion of this peculiar layout.  */
306   for (i = 0; i < 32; i++)
307     if (use_64bit)
308       collect_register (regcache, first_fp + i, regset[i].buf);
309     else
310       collect_register (regcache, first_fp + i,
311                         regset[i & ~1].buf + 4 * (big_endian != (i & 1)));
312
313   mips_collect_register_32bit (regcache, use_64bit,
314                                find_regno ("fcsr"), regset[32].buf);
315   mips_collect_register_32bit (regcache, use_64bit, find_regno ("fir"),
316                                regset[32].buf + 4);
317 }
318
319 static void
320 mips_store_fpregset (struct regcache *regcache, const void *buf)
321 {
322   const union mips_register *regset = buf;
323   int i, use_64bit, first_fp, big_endian;
324
325   use_64bit = (register_size (0) == 8);
326   first_fp = find_regno ("f0");
327   big_endian = (__BYTE_ORDER == __BIG_ENDIAN);
328
329   /* See GDB for a discussion of this peculiar layout.  */
330   for (i = 0; i < 32; i++)
331     if (use_64bit)
332       supply_register (regcache, first_fp + i, regset[i].buf);
333     else
334       supply_register (regcache, first_fp + i,
335                        regset[i & ~1].buf + 4 * (big_endian != (i & 1)));
336
337   mips_supply_register_32bit (regcache, use_64bit,
338                               find_regno ("fcsr"), regset[32].buf);
339   mips_supply_register_32bit (regcache, use_64bit, find_regno ("fir"),
340                               regset[32].buf + 4);
341 }
342 #endif /* HAVE_PTRACE_GETREGS */
343
344 struct regset_info target_regsets[] = {
345 #ifdef HAVE_PTRACE_GETREGS
346   { PTRACE_GETREGS, PTRACE_SETREGS, 0, 38 * 8, GENERAL_REGS,
347     mips_fill_gregset, mips_store_gregset },
348   { PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, 33 * 8, FP_REGS,
349     mips_fill_fpregset, mips_store_fpregset },
350 #endif /* HAVE_PTRACE_GETREGS */
351   { 0, 0, 0, -1, -1, NULL, NULL }
352 };
353
354 struct linux_target_ops the_low_target = {
355 #ifdef __mips64
356   init_registers_mips64_linux,
357 #else
358   init_registers_mips_linux,
359 #endif
360   mips_num_regs,
361   mips_regmap,
362   mips_cannot_fetch_register,
363   mips_cannot_store_register,
364   mips_get_pc,
365   mips_set_pc,
366   (const unsigned char *) &mips_breakpoint,
367   mips_breakpoint_len,
368   mips_reinsert_addr,
369   0,
370   mips_breakpoint_at,
371 };