1 /* GNU/Linux/MIPS specific low level interface, for the remote server for GDB.
2    Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2005, 2006, 2007,
3    2008, 2009, 2010, 2011 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 "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
mips_cannot_fetch_register(int regno)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
mips_cannot_store_register(int regno)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
mips_get_pc(struct regcache * regcache)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
mips_set_pc(struct regcache * regcache,CORE_ADDR pc)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
mips_reinsert_addr(void)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
mips_breakpoint_at(CORE_ADDR where)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
ps_get_thread_area(const struct ps_prochandle * ph,lwpid_t lwpid,int idx,void ** base)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
mips_collect_register(struct regcache * regcache,int use_64bit,int regno,union mips_register * reg)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
mips_supply_register(struct regcache * regcache,int use_64bit,int regno,const union mips_register * reg)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
mips_collect_register_32bit(struct regcache * regcache,int use_64bit,int regno,unsigned char * buf)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
mips_supply_register_32bit(struct regcache * regcache,int use_64bit,int regno,const unsigned char * buf)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
mips_fill_gregset(struct regcache * regcache,void * buf)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
mips_store_gregset(struct regcache * regcache,const void * buf)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
mips_fill_fpregset(struct regcache * regcache,void * buf)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
mips_store_fpregset(struct regcache * regcache,const void * buf)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 };
372