1/* Register support routines for the remote server for GDB. 2 Copyright (C) 2001, 2002, 2004, 2005, 2011 3 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 It has been modified to integrate it in valgrind 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 Boston, MA 02110-1301, USA. */ 22 23#include "server.h" 24#include "regdef.h" 25 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 30struct inferior_regcache_data 31{ 32 int registers_valid; 33 unsigned char *registers; 34 Bool *register_supplied; /* set to True once it has been supplied */ 35}; 36 37static int register_bytes; 38 39static struct reg *reg_defs; 40static int num_registers; 41 42const char **gdbserver_expedite_regs; 43 44static 45struct inferior_regcache_data * get_regcache (struct thread_info *inf, 46 int fetch) 47{ 48 struct inferior_regcache_data *regcache; 49 50 regcache = (struct inferior_regcache_data *) inferior_regcache_data (inf); 51 52 if (regcache == NULL) 53 fatal ("no register cache\n"); 54 55 /* FIXME - fetch registers for INF */ 56 if (fetch && regcache->registers_valid == 0) { 57 valgrind_fetch_registers (0); 58 regcache->registers_valid = 1; 59 } 60 61 return regcache; 62} 63 64void regcache_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 struct thread_info *saved_inferior = current_inferior; 73 74 current_inferior = thread; 75 valgrind_store_registers (-1); 76 current_inferior = saved_inferior; 77 } 78 79 regcache->registers_valid = 0; 80} 81 82void regcache_invalidate () 83{ 84 for_each_inferior (&all_threads, regcache_invalidate_one); 85} 86 87int registers_length (void) 88{ 89 return 2 * register_bytes; 90} 91 92void *new_register_cache (void) 93{ 94 struct inferior_regcache_data *regcache; 95 96 regcache = malloc (sizeof (*regcache)); 97 98 /* Make sure to zero-initialize the register cache when it is created, 99 in case there are registers the target never fetches. This way they'll 100 read as zero instead of garbage. */ 101 regcache->registers = calloc (1, register_bytes); 102 if (regcache->registers == NULL) 103 fatal ("Could not allocate register cache.\n"); 104 105 regcache->register_supplied = calloc (1, num_registers); 106 if (regcache->register_supplied == NULL) 107 fatal ("Could not allocate register_supplied cache.\n"); 108 109 regcache->registers_valid = 0; 110 111 return regcache; 112} 113 114void free_register_cache (void *regcache_p) 115{ 116 struct inferior_regcache_data *regcache 117 = (struct inferior_regcache_data *) regcache_p; 118 119 free (regcache->registers); 120 free (regcache->register_supplied); 121 free (regcache); 122} 123 124/* if a regcache exists for entry, reallocate it. 125 This is needed if the shadow registers are added. 126 In such a case, a 2nd call to set_register_cache is done 127 which will cause the reallocation of already created caches. */ 128static 129void regcache_realloc_one (struct inferior_list_entry *entry) 130{ 131 struct thread_info *thread = (struct thread_info *) entry; 132 struct inferior_regcache_data *regcache; 133 134 regcache = (struct inferior_regcache_data *) inferior_regcache_data (thread); 135 136 if (regcache) { 137 free_register_cache (regcache); 138 set_inferior_regcache_data (thread, new_register_cache ()); 139 } 140} 141 142void set_register_cache (struct reg *regs, int n) 143{ 144 int offset, i; 145 146 reg_defs = regs; 147 num_registers = n; 148 149 offset = 0; 150 for (i = 0; i < n; i++) { 151 regs[i].offset = offset; 152 offset += regs[i].size; 153 } 154 155 register_bytes = offset / 8; 156 157 for_each_inferior (&all_threads, regcache_realloc_one); 158} 159 160void registers_to_string (char *buf) 161{ 162 unsigned char *registers = get_regcache (current_inferior, 1)->registers; 163 164 convert_int_to_ascii (registers, buf, register_bytes); 165} 166 167void registers_from_string (const char *buf) 168{ 169 int len = strlen (buf); 170 unsigned char *registers = get_regcache (current_inferior, 1)->registers; 171 172 if (len != register_bytes * 2) { 173 warning ("Wrong sized register packet (expected %d bytes, got %d)\n", 174 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 181int find_regno (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 i; 188 fatal ("Unknown register %s requested\n", name); 189 return -1; 190} 191 192struct reg *find_register_by_number (int n) 193{ 194 return ®_defs[n]; 195} 196 197int register_size (int n) 198{ 199 return reg_defs[n].size / 8; 200} 201 202static 203unsigned char *register_data (int n, int fetch) 204{ 205 unsigned char *registers 206 = get_regcache (current_inferior, fetch)->registers; 207 208 return registers + (reg_defs[n].offset / 8); 209} 210static 211unsigned char *register_data_for_supply (int n, int fetch, Bool *mod) 212{ 213 struct inferior_regcache_data * cache 214 = get_regcache (current_inferior, fetch); 215 unsigned char *registers = cache->registers; 216 217 if (cache->register_supplied[n]) 218 *mod = False; 219 else 220 *mod = True; 221 cache->register_supplied[n] = True; 222 return registers + (reg_defs[n].offset / 8); 223} 224 225void supply_register (int n, const void *buf, Bool *mod) 226{ 227 Bool new; 228 VG_(dmemcpy) (register_data_for_supply (n, 0, &new), 229 buf, register_size (n), mod); 230 if (new) 231 *mod = True; 232} 233 234void supply_register_from_string (int n, const char *buf, Bool *mod) 235{ 236 Bool new; 237 unsigned char bytes_register[register_size (n)]; 238 convert_ascii_to_int (buf, bytes_register, register_size (n)); 239 VG_(dmemcpy) (register_data_for_supply (n, 0, &new), 240 bytes_register, register_size (n), mod); 241 if (new) 242 *mod = True; 243} 244 245void supply_register_by_name (const char *name, const void *buf, Bool *mod) 246{ 247 supply_register (find_regno (name), buf, mod); 248} 249 250void collect_register (int n, void *buf) 251{ 252 VG_(memcpy) (buf, register_data (n, 1), register_size (n)); 253} 254 255void collect_register_as_string (int n, char *buf) 256{ 257 convert_int_to_ascii (register_data (n, 1), buf, register_size (n)); 258} 259 260void collect_register_by_name (const char *name, void *buf) 261{ 262 collect_register (find_regno (name), buf); 263} 264