gdb/testsuite/
[deliverable/binutils-gdb.git] / gdb / gdbserver / regcache.c
CommitLineData
0a30fbc4 1/* Register support routines for the remote server for GDB.
4c38e0a4 2 Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008, 2009, 2010
9b254dd1 3 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"
21#include "regdef.h"
22
23#include <stdlib.h>
24#include <string.h>
25
a7f48742
DJ
26/* The private data for the register cache. Note that we have one
27 per inferior; this is primarily for simplicity, as the performance
28 benefit is minimal. */
29
c04a1aa8
DJ
30struct inferior_regcache_data
31{
0d62e5e8 32 int registers_valid;
f450004a 33 unsigned char *registers;
c04a1aa8
DJ
34};
35
0a30fbc4
DJ
36static int register_bytes;
37
38static struct reg *reg_defs;
39static int num_registers;
40
41const char **gdbserver_expedite_regs;
42
c04a1aa8 43static struct inferior_regcache_data *
0d62e5e8 44get_regcache (struct thread_info *inf, int fetch)
c04a1aa8
DJ
45{
46 struct inferior_regcache_data *regcache;
47
48 regcache = (struct inferior_regcache_data *) inferior_regcache_data (inf);
49
50 if (regcache == NULL)
51 fatal ("no register cache");
52
0d62e5e8
DJ
53 /* FIXME - fetch registers for INF */
54 if (fetch && regcache->registers_valid == 0)
55 {
4463ce24 56 fetch_inferior_registers (-1);
0d62e5e8
DJ
57 regcache->registers_valid = 1;
58 }
59
c04a1aa8
DJ
60 return regcache;
61}
62
0d62e5e8
DJ
63void
64regcache_invalidate_one (struct inferior_list_entry *entry)
65{
66 struct thread_info *thread = (struct thread_info *) entry;
67 struct inferior_regcache_data *regcache;
68
69 regcache = (struct inferior_regcache_data *) inferior_regcache_data (thread);
70
71 if (regcache->registers_valid)
72 {
73 struct thread_info *saved_inferior = current_inferior;
74
75 current_inferior = thread;
76 store_inferior_registers (-1);
77 current_inferior = saved_inferior;
78 }
79
80 regcache->registers_valid = 0;
81}
82
83void
84regcache_invalidate ()
85{
86 for_each_inferior (&all_threads, regcache_invalidate_one);
87}
88
0d62e5e8
DJ
89void *
90new_register_cache (void)
c04a1aa8
DJ
91{
92 struct inferior_regcache_data *regcache;
93
5822d809
PA
94 if (register_bytes == 0)
95 return NULL; /* The architecture hasn't been initialized yet. */
96
bca929d3 97 regcache = xmalloc (sizeof (*regcache));
c04a1aa8 98
2a68b70e
DJ
99 /* Make sure to zero-initialize the register cache when it is created,
100 in case there are registers the target never fetches. This way they'll
101 read as zero instead of garbage. */
bca929d3 102 regcache->registers = xcalloc (1, register_bytes);
c04a1aa8 103
0d62e5e8
DJ
104 regcache->registers_valid = 0;
105
106 return regcache;
c04a1aa8
DJ
107}
108
109void
0d62e5e8 110free_register_cache (void *regcache_p)
c04a1aa8 111{
0d62e5e8
DJ
112 struct inferior_regcache_data *regcache
113 = (struct inferior_regcache_data *) regcache_p;
114
5822d809
PA
115 if (regcache)
116 {
117 free (regcache->registers);
118 free (regcache);
119 }
c04a1aa8
DJ
120}
121
d61ddec4
UW
122static void
123realloc_register_cache (struct inferior_list_entry *thread_p)
124{
125 struct thread_info *thread = (struct thread_info *) thread_p;
126
127 free_register_cache (inferior_regcache_data (thread));
128 set_inferior_regcache_data (thread, new_register_cache ());
129}
130
0a30fbc4
DJ
131void
132set_register_cache (struct reg *regs, int n)
133{
134 int offset, i;
1b3f6016 135
0a30fbc4
DJ
136 reg_defs = regs;
137 num_registers = n;
138
139 offset = 0;
140 for (i = 0; i < n; i++)
141 {
142 regs[i].offset = offset;
143 offset += regs[i].size;
144 }
145
146 register_bytes = offset / 8;
d61ddec4 147
bb9c3d36
UW
148 /* Make sure PBUFSIZ is large enough to hold a full register packet. */
149 if (2 * register_bytes + 32 > PBUFSIZ)
150 fatal ("Register packet size exceeds PBUFSIZ.");
151
d61ddec4
UW
152 /* Re-allocate all pre-existing register caches. */
153 for_each_inferior (&all_threads, realloc_register_cache);
0a30fbc4
DJ
154}
155
156void
157registers_to_string (char *buf)
158{
f450004a 159 unsigned char *registers = get_regcache (current_inferior, 1)->registers;
c04a1aa8 160
0a30fbc4
DJ
161 convert_int_to_ascii (registers, buf, register_bytes);
162}
163
164void
165registers_from_string (char *buf)
166{
167 int len = strlen (buf);
f450004a 168 unsigned char *registers = get_regcache (current_inferior, 1)->registers;
0a30fbc4
DJ
169
170 if (len != register_bytes * 2)
171 {
1b3f6016
PA
172 warning ("Wrong sized register packet (expected %d bytes, got %d)",
173 2*register_bytes, len);
0a30fbc4
DJ
174 if (len > register_bytes * 2)
175 len = register_bytes * 2;
176 }
177 convert_ascii_to_int (buf, registers, len / 2);
178}
179
180struct reg *
181find_register_by_name (const char *name)
182{
183 int i;
184
185 for (i = 0; i < num_registers; i++)
186 if (!strcmp (name, reg_defs[i].name))
187 return &reg_defs[i];
188 fatal ("Unknown register %s requested", name);
189 return 0;
190}
191
192int
193find_regno (const char *name)
194{
195 int i;
196
197 for (i = 0; i < num_registers; i++)
198 if (!strcmp (name, reg_defs[i].name))
199 return i;
200 fatal ("Unknown register %s requested", name);
201 return -1;
202}
203
204struct reg *
205find_register_by_number (int n)
206{
207 return &reg_defs[n];
208}
209
210int
211register_size (int n)
212{
213 return reg_defs[n].size / 8;
214}
215
f450004a 216static unsigned char *
0d62e5e8 217register_data (int n, int fetch)
0a30fbc4 218{
f450004a
DJ
219 unsigned char *registers
220 = get_regcache (current_inferior, fetch)->registers;
c04a1aa8 221
0a30fbc4
DJ
222 return registers + (reg_defs[n].offset / 8);
223}
224
58caa3dc 225void
0729219d 226supply_register (int n, const void *buf)
58caa3dc 227{
0d62e5e8 228 memcpy (register_data (n, 0), buf, register_size (n));
58caa3dc
DJ
229}
230
231void
0729219d 232supply_register_by_name (const char *name, const void *buf)
58caa3dc
DJ
233{
234 supply_register (find_regno (name), buf);
235}
236
237void
0729219d 238collect_register (int n, void *buf)
58caa3dc 239{
0d62e5e8
DJ
240 memcpy (buf, register_data (n, 1), register_size (n));
241}
242
243void
244collect_register_as_string (int n, char *buf)
245{
246 convert_int_to_ascii (register_data (n, 1), buf, register_size (n));
58caa3dc
DJ
247}
248
249void
0729219d 250collect_register_by_name (const char *name, void *buf)
58caa3dc
DJ
251{
252 collect_register (find_regno (name), buf);
253}
This page took 0.597042 seconds and 4 git commands to generate.