1 /* Low-level RSP routines for GDB, the GNU debugger. 2 3 Copyright (C) 1988-2020 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 3 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, see <http://www.gnu.org/licenses/>. */ 19 20 #include "common-defs.h" 21 #include "rsp-low.h" 22 23 /* See rsp-low.h. */ 24 25 int 26 fromhex (int a) 27 { 28 if (a >= '0' && a <= '9') 29 return a - '0'; 30 else if (a >= 'a' && a <= 'f') 31 return a - 'a' + 10; 32 else if (a >= 'A' && a <= 'F') 33 return a - 'A' + 10; 34 else 35 error (_("Reply contains invalid hex digit %d"), a); 36 } 37 38 /* See rsp-low.h. */ 39 40 int 41 tohex (int nib) 42 { 43 if (nib < 10) 44 return '0' + nib; 45 else 46 return 'a' + nib - 10; 47 } 48 49 /* Encode 64 bits in 16 chars of hex. */ 50 51 static const char hexchars[] = "0123456789abcdef"; 52 53 static int 54 ishex (int ch, int *val) 55 { 56 if ((ch >= 'a') && (ch <= 'f')) 57 { 58 *val = ch - 'a' + 10; 59 return 1; 60 } 61 if ((ch >= 'A') && (ch <= 'F')) 62 { 63 *val = ch - 'A' + 10; 64 return 1; 65 } 66 if ((ch >= '0') && (ch <= '9')) 67 { 68 *val = ch - '0'; 69 return 1; 70 } 71 return 0; 72 } 73 74 /* See rsp-low.h. */ 75 76 char * 77 pack_nibble (char *buf, int nibble) 78 { 79 *buf++ = hexchars[(nibble & 0x0f)]; 80 return buf; 81 } 82 83 /* See rsp-low.h. */ 84 85 char * 86 pack_hex_byte (char *pkt, int byte) 87 { 88 *pkt++ = hexchars[(byte >> 4) & 0xf]; 89 *pkt++ = hexchars[(byte & 0xf)]; 90 return pkt; 91 } 92 93 /* See rsp-low.h. */ 94 95 const char * 96 unpack_varlen_hex (const char *buff, /* packet to parse */ 97 ULONGEST *result) 98 { 99 int nibble; 100 ULONGEST retval = 0; 101 102 while (ishex (*buff, &nibble)) 103 { 104 buff++; 105 retval = retval << 4; 106 retval |= nibble & 0x0f; 107 } 108 *result = retval; 109 return buff; 110 } 111 112 /* See rsp-low.h. */ 113 114 int 115 hex2bin (const char *hex, gdb_byte *bin, int count) 116 { 117 int i; 118 119 for (i = 0; i < count; i++) 120 { 121 if (hex[0] == 0 || hex[1] == 0) 122 { 123 /* Hex string is short, or of uneven length. 124 Return the count that has been converted so far. */ 125 return i; 126 } 127 *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]); 128 hex += 2; 129 } 130 return i; 131 } 132 133 /* See rsp-low.h. */ 134 135 gdb::byte_vector 136 hex2bin (const char *hex) 137 { 138 size_t bin_len = strlen (hex) / 2; 139 gdb::byte_vector bin (bin_len); 140 141 hex2bin (hex, bin.data (), bin_len); 142 143 return bin; 144 } 145 146 /* See rsp-low.h. */ 147 148 std::string 149 hex2str (const char *hex) 150 { 151 return hex2str (hex, strlen (hex)); 152 } 153 154 /* See rsp-low.h. */ 155 156 std::string 157 hex2str (const char *hex, int count) 158 { 159 std::string ret; 160 161 ret.reserve (count); 162 for (size_t i = 0; i < count; ++i) 163 { 164 if (hex[0] == '\0' || hex[1] == '\0') 165 { 166 /* Hex string is short, or of uneven length. Return what we 167 have so far. */ 168 return ret; 169 } 170 ret += fromhex (hex[0]) * 16 + fromhex (hex[1]); 171 hex += 2; 172 } 173 174 return ret; 175 } 176 177 /* See rsp-low.h. */ 178 179 int 180 bin2hex (const gdb_byte *bin, char *hex, int count) 181 { 182 int i; 183 184 for (i = 0; i < count; i++) 185 { 186 *hex++ = tohex ((*bin >> 4) & 0xf); 187 *hex++ = tohex (*bin++ & 0xf); 188 } 189 *hex = 0; 190 return i; 191 } 192 193 /* See rsp-low.h. */ 194 195 std::string 196 bin2hex (const gdb_byte *bin, int count) 197 { 198 std::string ret; 199 200 ret.reserve (count * 2); 201 for (int i = 0; i < count; ++i) 202 { 203 ret += tohex ((*bin >> 4) & 0xf); 204 ret += tohex (*bin++ & 0xf); 205 } 206 207 return ret; 208 } 209 210 /* Return whether byte B needs escaping when sent as part of binary data. */ 211 212 static int 213 needs_escaping (gdb_byte b) 214 { 215 return b == '$' || b == '#' || b == '}' || b == '*'; 216 } 217 218 /* See rsp-low.h. */ 219 220 int 221 remote_escape_output (const gdb_byte *buffer, int len_units, int unit_size, 222 gdb_byte *out_buf, int *out_len_units, 223 int out_maxlen_bytes) 224 { 225 int input_unit_index, output_byte_index = 0, byte_index_in_unit; 226 int number_escape_bytes_needed; 227 228 /* Try to copy integral addressable memory units until 229 (1) we run out of space or 230 (2) we copied all of them. */ 231 for (input_unit_index = 0; 232 input_unit_index < len_units; 233 input_unit_index++) 234 { 235 /* Find out how many escape bytes we need for this unit. */ 236 number_escape_bytes_needed = 0; 237 for (byte_index_in_unit = 0; 238 byte_index_in_unit < unit_size; 239 byte_index_in_unit++) 240 { 241 int idx = input_unit_index * unit_size + byte_index_in_unit; 242 gdb_byte b = buffer[idx]; 243 if (needs_escaping (b)) 244 number_escape_bytes_needed++; 245 } 246 247 /* Check if we have room to fit this escaped unit. */ 248 if (output_byte_index + unit_size + number_escape_bytes_needed > 249 out_maxlen_bytes) 250 break; 251 252 /* Copy the unit byte per byte, adding escapes. */ 253 for (byte_index_in_unit = 0; 254 byte_index_in_unit < unit_size; 255 byte_index_in_unit++) 256 { 257 int idx = input_unit_index * unit_size + byte_index_in_unit; 258 gdb_byte b = buffer[idx]; 259 if (needs_escaping (b)) 260 { 261 out_buf[output_byte_index++] = '}'; 262 out_buf[output_byte_index++] = b ^ 0x20; 263 } 264 else 265 out_buf[output_byte_index++] = b; 266 } 267 } 268 269 *out_len_units = input_unit_index; 270 return output_byte_index; 271 } 272 273 /* See rsp-low.h. */ 274 275 int 276 remote_unescape_input (const gdb_byte *buffer, int len, 277 gdb_byte *out_buf, int out_maxlen) 278 { 279 int input_index, output_index; 280 int escaped; 281 282 output_index = 0; 283 escaped = 0; 284 for (input_index = 0; input_index < len; input_index++) 285 { 286 gdb_byte b = buffer[input_index]; 287 288 if (output_index + 1 > out_maxlen) 289 error (_("Received too much data from the target.")); 290 291 if (escaped) 292 { 293 out_buf[output_index++] = b ^ 0x20; 294 escaped = 0; 295 } 296 else if (b == '}') 297 escaped = 1; 298 else 299 out_buf[output_index++] = b; 300 } 301 302 if (escaped) 303 error (_("Unmatched escape character in target response.")); 304 305 return output_index; 306 } 307 308