* top.c (print_gdb_version): Update copyright year.
[deliverable/binutils-gdb.git] / gdb / gdbserver / regcache.c
CommitLineData
0a30fbc4 1/* Register support routines for the remote server for GDB.
9b254dd1
DJ
2 Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008
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 {
56 fetch_inferior_registers (0);
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
DJ
103 if (regcache->registers == NULL)
104 fatal ("Could not allocate register cache.");
105
0d62e5e8
DJ
106 regcache->registers_valid = 0;
107
108 return regcache;
c04a1aa8
DJ
109}
110
111void
0d62e5e8 112free_register_cache (void *regcache_p)
c04a1aa8 113{
0d62e5e8
DJ
114 struct inferior_regcache_data *regcache
115 = (struct inferior_regcache_data *) regcache_p;
116
5822d809
PA
117 if (regcache)
118 {
119 free (regcache->registers);
120 free (regcache);
121 }
c04a1aa8
DJ
122}
123
d61ddec4
UW
124static void
125realloc_register_cache (struct inferior_list_entry *thread_p)
126{
127 struct thread_info *thread = (struct thread_info *) thread_p;
128
129 free_register_cache (inferior_regcache_data (thread));
130 set_inferior_regcache_data (thread, new_register_cache ());
131}
132
0a30fbc4
DJ
133void
134set_register_cache (struct reg *regs, int n)
135{
136 int offset, i;
137
138 reg_defs = regs;
139 num_registers = n;
140
141 offset = 0;
142 for (i = 0; i < n; i++)
143 {
144 regs[i].offset = offset;
145 offset += regs[i].size;
146 }
147
148 register_bytes = offset / 8;
d61ddec4 149
bb9c3d36
UW
150 /* Make sure PBUFSIZ is large enough to hold a full register packet. */
151 if (2 * register_bytes + 32 > PBUFSIZ)
152 fatal ("Register packet size exceeds PBUFSIZ.");
153
d61ddec4
UW
154 /* Re-allocate all pre-existing register caches. */
155 for_each_inferior (&all_threads, realloc_register_cache);
0a30fbc4
DJ
156}
157
158void
159registers_to_string (char *buf)
160{
f450004a 161 unsigned char *registers = get_regcache (current_inferior, 1)->registers;
c04a1aa8 162
0a30fbc4
DJ
163 convert_int_to_ascii (registers, buf, register_bytes);
164}
165
166void
167registers_from_string (char *buf)
168{
169 int len = strlen (buf);
f450004a 170 unsigned char *registers = get_regcache (current_inferior, 1)->registers;
0a30fbc4
DJ
171
172 if (len != register_bytes * 2)
173 {
174 warning ("Wrong sized register packet (expected %d bytes, got %d)", 2*register_bytes, len);
175 if (len > register_bytes * 2)
176 len = register_bytes * 2;
177 }
178 convert_ascii_to_int (buf, registers, len / 2);
179}
180
181struct reg *
182find_register_by_name (const char *name)
183{
184 int i;
185
186 for (i = 0; i < num_registers; i++)
187 if (!strcmp (name, reg_defs[i].name))
188 return &reg_defs[i];
189 fatal ("Unknown register %s requested", name);
190 return 0;
191}
192
193int
194find_regno (const char *name)
195{
196 int i;
197
198 for (i = 0; i < num_registers; i++)
199 if (!strcmp (name, reg_defs[i].name))
200 return i;
201 fatal ("Unknown register %s requested", name);
202 return -1;
203}
204
205struct reg *
206find_register_by_number (int n)
207{
208 return &reg_defs[n];
209}
210
211int
212register_size (int n)
213{
214 return reg_defs[n].size / 8;
215}
216
f450004a 217static unsigned char *
0d62e5e8 218register_data (int n, int fetch)
0a30fbc4 219{
f450004a
DJ
220 unsigned char *registers
221 = get_regcache (current_inferior, fetch)->registers;
c04a1aa8 222
0a30fbc4
DJ
223 return registers + (reg_defs[n].offset / 8);
224}
225
58caa3dc 226void
0729219d 227supply_register (int n, const void *buf)
58caa3dc 228{
0d62e5e8 229 memcpy (register_data (n, 0), buf, register_size (n));
58caa3dc
DJ
230}
231
232void
0729219d 233supply_register_by_name (const char *name, const void *buf)
58caa3dc
DJ
234{
235 supply_register (find_regno (name), buf);
236}
237
238void
0729219d 239collect_register (int n, void *buf)
58caa3dc 240{
0d62e5e8
DJ
241 memcpy (buf, register_data (n, 1), register_size (n));
242}
243
244void
245collect_register_as_string (int n, char *buf)
246{
247 convert_int_to_ascii (register_data (n, 1), buf, register_size (n));
58caa3dc
DJ
248}
249
250void
0729219d 251collect_register_by_name (const char *name, void *buf)
58caa3dc
DJ
252{
253 collect_register (find_regno (name), buf);
254}
This page took 0.504292 seconds and 4 git commands to generate.