1/* Register support routines for the remote server for GDB. 2 Copyright 2001, 2002, 2004 3 Free Software Foundation, Inc. 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 9 the Free Software Foundation; either version 2 of the License, or 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 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22#include "server.h" 23#include "regdef.h" 24 25#include <stdlib.h> 26#include <string.h> 27 28/* The private data for the register cache. Note that we have one 29 per inferior; this is primarily for simplicity, as the performance 30 benefit is minimal. */ 31 32struct inferior_regcache_data 33{ 34 int registers_valid; 35 char *registers; 36}; 37 38static int register_bytes; 39 40static struct reg *reg_defs; 41static int num_registers; 42 43const char **gdbserver_expedite_regs; 44 45static struct inferior_regcache_data * 46get_regcache (struct thread_info *inf, 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"); 54 55 /* FIXME - fetch registers for INF */ 56 if (fetch && regcache->registers_valid == 0) 57 { 58 fetch_inferior_registers (0); 59 regcache->registers_valid = 1; 60 } 61 62 return regcache; 63} 64 65void 66regcache_invalidate_one (struct inferior_list_entry *entry) 67{ 68 struct thread_info *thread = (struct thread_info *) entry; 69 struct inferior_regcache_data *regcache; 70 71 regcache = (struct inferior_regcache_data *) inferior_regcache_data (thread); 72 73 if (regcache->registers_valid) 74 { 75 struct thread_info *saved_inferior = current_inferior; 76 77 current_inferior = thread; 78 store_inferior_registers (-1); 79 current_inferior = saved_inferior; 80 } 81 82 regcache->registers_valid = 0; 83} 84 85void 86regcache_invalidate () 87{ 88 for_each_inferior (&all_threads, regcache_invalidate_one); 89} 90 91int 92registers_length (void) 93{ 94 return 2 * register_bytes; 95} 96 97void * 98new_register_cache (void) 99{ 100 struct inferior_regcache_data *regcache; 101 102 regcache = malloc (sizeof (*regcache)); 103 104 /* Make sure to zero-initialize the register cache when it is created, 105 in case there are registers the target never fetches. This way they'll 106 read as zero instead of garbage. */ 107 regcache->registers = calloc (1, register_bytes); 108 if (regcache->registers == NULL) 109 fatal ("Could not allocate register cache."); 110 111 regcache->registers_valid = 0; 112 113 return regcache; 114} 115 116void 117free_register_cache (void *regcache_p) 118{ 119 struct inferior_regcache_data *regcache 120 = (struct inferior_regcache_data *) regcache_p; 121 122 free (regcache->registers); 123 free (regcache); 124} 125 126void 127set_register_cache (struct reg *regs, int n) 128{ 129 int offset, i; 130 131 reg_defs = regs; 132 num_registers = n; 133 134 offset = 0; 135 for (i = 0; i < n; i++) 136 { 137 regs[i].offset = offset; 138 offset += regs[i].size; 139 } 140 141 register_bytes = offset / 8; 142} 143 144void 145registers_to_string (char *buf) 146{ 147 char *registers = get_regcache (current_inferior, 1)->registers; 148 149 convert_int_to_ascii (registers, buf, register_bytes); 150} 151 152void 153registers_from_string (char *buf) 154{ 155 int len = strlen (buf); 156 char *registers = get_regcache (current_inferior, 1)->registers; 157 158 if (len != register_bytes * 2) 159 { 160 warning ("Wrong sized register packet (expected %d bytes, got %d)", 2*register_bytes, len); 161 if (len > register_bytes * 2) 162 len = register_bytes * 2; 163 } 164 convert_ascii_to_int (buf, registers, len / 2); 165} 166 167struct reg * 168find_register_by_name (const char *name) 169{ 170 int i; 171 172 for (i = 0; i < num_registers; i++) 173 if (!strcmp (name, reg_defs[i].name)) 174 return ®_defs[i]; 175 fatal ("Unknown register %s requested", name); 176 return 0; 177} 178 179int 180find_regno (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 i; 187 fatal ("Unknown register %s requested", name); 188 return -1; 189} 190 191struct reg * 192find_register_by_number (int n) 193{ 194 return ®_defs[n]; 195} 196 197int 198register_size (int n) 199{ 200 return reg_defs[n].size / 8; 201} 202 203static char * 204register_data (int n, int fetch) 205{ 206 char *registers = get_regcache (current_inferior, fetch)->registers; 207 208 return registers + (reg_defs[n].offset / 8); 209} 210 211void 212supply_register (int n, const void *buf) 213{ 214 memcpy (register_data (n, 0), buf, register_size (n)); 215} 216 217void 218supply_register_by_name (const char *name, const void *buf) 219{ 220 supply_register (find_regno (name), buf); 221} 222 223void 224collect_register (int n, void *buf) 225{ 226 memcpy (buf, register_data (n, 1), register_size (n)); 227} 228 229void 230collect_register_as_string (int n, char *buf) 231{ 232 convert_int_to_ascii (register_data (n, 1), buf, register_size (n)); 233} 234 235void 236collect_register_by_name (const char *name, void *buf) 237{ 238 collect_register (find_regno (name), buf); 239} 240