* server.c (get_features_xml): Check if target implemented
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-arm-low.c
CommitLineData
0a30fbc4 1/* GNU/Linux/ARM specific low level interface, for the remote server for GDB.
9308fc88 2 Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
6aba47ca 3 2006, 2007 Free Software Foundation, Inc.
0a30fbc4
DJ
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 2 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, write to the Free Software
6f0f660e
EZ
19 Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
0a30fbc4
DJ
21
22#include "server.h"
58caa3dc 23#include "linux-low.h"
0a30fbc4 24
9308fc88
DJ
25#include <sys/ptrace.h>
26
27#include "gdb_proc_service.h"
28
29#ifndef PTRACE_GET_THREAD_AREA
30#define PTRACE_GET_THREAD_AREA 22
31#endif
32
fb1e4ffc
DJ
33#ifndef PTRACE_GETWMMXREGS
34# define PTRACE_GETWMMXREGS 18
35# define PTRACE_SETWMMXREGS 19
36#endif
37
0a30fbc4
DJ
38#ifdef HAVE_SYS_REG_H
39#include <sys/reg.h>
40#endif
41
23ce3b1c 42#define arm_num_regs 26
0a30fbc4 43
2ec06d2e 44static int arm_regmap[] = {
0a30fbc4
DJ
45 0, 4, 8, 12, 16, 20, 24, 28,
46 32, 36, 40, 44, 48, 52, 56, 60,
23ce3b1c
DJ
47 -1, -1, -1, -1, -1, -1, -1, -1, -1,
48 64
0a30fbc4
DJ
49};
50
2ec06d2e
DJ
51static int
52arm_cannot_store_register (int regno)
0a30fbc4 53{
2ec06d2e 54 return (regno >= arm_num_regs);
0a30fbc4
DJ
55}
56
2ec06d2e
DJ
57static int
58arm_cannot_fetch_register (int regno)
0a30fbc4 59{
2ec06d2e 60 return (regno >= arm_num_regs);
0a30fbc4
DJ
61}
62
fb1e4ffc
DJ
63static void
64arm_fill_gregset (void *buf)
65{
66 int i;
67
68 for (i = 0; i < arm_num_regs; i++)
69 if (arm_regmap[i] != -1)
70 collect_register (i, ((char *) buf) + arm_regmap[i]);
71}
72
73static void
74arm_store_gregset (const void *buf)
75{
76 int i;
77 char zerobuf[8];
78
79 memset (zerobuf, 0, 8);
80 for (i = 0; i < arm_num_regs; i++)
81 if (arm_regmap[i] != -1)
82 supply_register (i, ((char *) buf) + arm_regmap[i]);
83 else
84 supply_register (i, zerobuf);
85}
86
87#ifdef __IWMMXT__
88
89static void
90arm_fill_wmmxregset (void *buf)
91{
92 int i;
93
94 for (i = 0; i < 16; i++)
95 collect_register (arm_num_regs + i, (char *) buf + i * 8);
96
97 /* We only have access to wcssf, wcasf, and wcgr0-wcgr3. */
98 for (i = 0; i < 6; i++)
99 collect_register (arm_num_regs + i + 16, (char *) buf + 16 * 8 + i * 4);
100}
101
102static void
103arm_store_wmmxregset (const void *buf)
104{
105 int i;
106
107 for (i = 0; i < 16; i++)
108 supply_register (arm_num_regs + i, (char *) buf + i * 8);
109
110 /* We only have access to wcssf, wcasf, and wcgr0-wcgr3. */
111 for (i = 0; i < 6; i++)
112 supply_register (arm_num_regs + i + 16, (char *) buf + 16 * 8 + i * 4);
113}
114
115#endif /* __IWMMXT__ */
116
d677d77d
DJ
117extern int debug_threads;
118
0d62e5e8
DJ
119static CORE_ADDR
120arm_get_pc ()
121{
122 unsigned long pc;
123 collect_register_by_name ("pc", &pc);
d677d77d
DJ
124 if (debug_threads)
125 fprintf (stderr, "stop pc is %08lx\n", pc);
0d62e5e8
DJ
126 return pc;
127}
128
129static void
130arm_set_pc (CORE_ADDR pc)
131{
132 unsigned long newpc = pc;
133 supply_register_by_name ("pc", &newpc);
134}
135
136/* Correct in either endianness. We do not support Thumb yet. */
137static const unsigned long arm_breakpoint = 0xef9f0001;
138#define arm_breakpoint_len 4
139
9d1fb177
DJ
140/* For new EABI binaries. We recognize it regardless of which ABI
141 is used for gdbserver, so single threaded debugging should work
142 OK, but for multi-threaded debugging we only insert the current
143 ABI's breakpoint instruction. For now at least. */
144static const unsigned long arm_eabi_breakpoint = 0xe7f001f0;
145
0d62e5e8
DJ
146static int
147arm_breakpoint_at (CORE_ADDR where)
148{
149 unsigned long insn;
150
f450004a 151 (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
0d62e5e8
DJ
152 if (insn == arm_breakpoint)
153 return 1;
154
9d1fb177
DJ
155 if (insn == arm_eabi_breakpoint)
156 return 1;
157
0d62e5e8 158 /* If necessary, recognize more trap instructions here. GDB only uses the
9d1fb177
DJ
159 two. */
160
0d62e5e8
DJ
161 return 0;
162}
163
3b2fc2ea
DJ
164/* We only place breakpoints in empty marker functions, and thread locking
165 is outside of the function. So rather than importing software single-step,
166 we can just run until exit. */
167static CORE_ADDR
168arm_reinsert_addr ()
169{
170 unsigned long pc;
171 collect_register_by_name ("lr", &pc);
172 return pc;
173}
174
9308fc88
DJ
175/* Fetch the thread-local storage pointer for libthread_db. */
176
177ps_err_e
178ps_get_thread_area (const struct ps_prochandle *ph,
179 lwpid_t lwpid, int idx, void **base)
180{
181 if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
182 return PS_ERR;
183
184 /* IDX is the bias from the thread pointer to the beginning of the
185 thread descriptor. It has to be subtracted due to implementation
186 quirks in libthread_db. */
187 *base = (void *) ((char *)*base - idx);
188
189 return PS_OK;
190}
191
fb1e4ffc
DJ
192struct regset_info target_regsets[] = {
193 { PTRACE_GETREGS, PTRACE_SETREGS, 18 * 4,
194 GENERAL_REGS,
195 arm_fill_gregset, arm_store_gregset },
196#ifdef __IWMMXT__
197 { PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 16 * 8 + 6 * 4,
198 EXTENDED_REGS,
199 arm_fill_wmmxregset, arm_store_wmmxregset },
200#endif
201 { 0, 0, -1, -1, NULL, NULL }
202};
203
2ec06d2e
DJ
204struct linux_target_ops the_low_target = {
205 arm_num_regs,
206 arm_regmap,
207 arm_cannot_fetch_register,
208 arm_cannot_store_register,
0d62e5e8
DJ
209 arm_get_pc,
210 arm_set_pc,
9d1fb177 211#ifndef __ARM_EABI__
f450004a 212 (const unsigned char *) &arm_breakpoint,
9d1fb177
DJ
213#else
214 (const unsigned char *) &arm_eabi_breakpoint,
215#endif
0d62e5e8 216 arm_breakpoint_len,
3b2fc2ea 217 arm_reinsert_addr,
0d62e5e8
DJ
218 0,
219 arm_breakpoint_at,
2ec06d2e 220};
This page took 0.396238 seconds and 4 git commands to generate.