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