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