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