* inferiors.c (find_inferior): Make it safe for the callback
[deliverable/binutils-gdb.git] / gdb / gdbserver / regcache.c
CommitLineData
0a30fbc4 1/* Register support routines for the remote server for GDB.
0fb0cc75 2 Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008, 2009
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 {
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 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;
135
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 {
172 warning ("Wrong sized register packet (expected %d bytes, got %d)", 2*register_bytes, len);
173 if (len > register_bytes * 2)
174 len = register_bytes * 2;
175 }
176 convert_ascii_to_int (buf, registers, len / 2);
177}
178
179struct reg *
180find_register_by_name (const char *name)
181{
182 int i;
183
184 for (i = 0; i < num_registers; i++)
185 if (!strcmp (name, reg_defs[i].name))
186 return &reg_defs[i];
187 fatal ("Unknown register %s requested", name);
188 return 0;
189}
190
191int
192find_regno (const char *name)
193{
194 int i;
195
196 for (i = 0; i < num_registers; i++)
197 if (!strcmp (name, reg_defs[i].name))
198 return i;
199 fatal ("Unknown register %s requested", name);
200 return -1;
201}
202
203struct reg *
204find_register_by_number (int n)
205{
206 return &reg_defs[n];
207}
208
209int
210register_size (int n)
211{
212 return reg_defs[n].size / 8;
213}
214
f450004a 215static unsigned char *
0d62e5e8 216register_data (int n, int fetch)
0a30fbc4 217{
f450004a
DJ
218 unsigned char *registers
219 = get_regcache (current_inferior, fetch)->registers;
c04a1aa8 220
0a30fbc4
DJ
221 return registers + (reg_defs[n].offset / 8);
222}
223
58caa3dc 224void
0729219d 225supply_register (int n, const void *buf)
58caa3dc 226{
0d62e5e8 227 memcpy (register_data (n, 0), buf, register_size (n));
58caa3dc
DJ
228}
229
230void
0729219d 231supply_register_by_name (const char *name, const void *buf)
58caa3dc
DJ
232{
233 supply_register (find_regno (name), buf);
234}
235
236void
0729219d 237collect_register (int n, void *buf)
58caa3dc 238{
0d62e5e8
DJ
239 memcpy (buf, register_data (n, 1), register_size (n));
240}
241
242void
243collect_register_as_string (int n, char *buf)
244{
245 convert_int_to_ascii (register_data (n, 1), buf, register_size (n));
58caa3dc
DJ
246}
247
248void
0729219d 249collect_register_by_name (const char *name, void *buf)
58caa3dc
DJ
250{
251 collect_register (find_regno (name), buf);
252}
This page took 0.529792 seconds and 4 git commands to generate.