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