diff options
author | Tom Tromey <tromey@redhat.com> | 2014-01-18 14:32:47 -0700 |
---|---|---|
committer | Tom Tromey <tromey@redhat.com> | 2014-02-12 09:59:14 -0700 |
commit | 9c3d65319a230a106392e4b67c8c89c8f5e2929f (patch) | |
tree | 857987f9c4847e816d518f3641ba091d07a768e4 /gdb/common/rsp-low.c | |
parent | 01fd3ea573324b8248efbb236d994420641e3d32 (diff) | |
download | gdb-9c3d65319a230a106392e4b67c8c89c8f5e2929f.zip gdb-9c3d65319a230a106392e4b67c8c89c8f5e2929f.tar.gz gdb-9c3d65319a230a106392e4b67c8c89c8f5e2929f.tar.bz2 |
move some rsp bits into rsp-low.h
This moves various low-level remote serial protocol bits into
common/rsp-low.[ch].
This is as close to a pure move as possible. There are some
redundancies remaining but those will be dealt with in a subsequent
patch.
Note that the two variants of remote_escape_output disagreed on the
treatment of "*". On the theory that quoting cannot hurt but the
absence possibly can, I chose the gdbserver variant to be the
canonical one.
2014-02-12 Tom Tromey <tromey@redhat.com>
* tracepoint.c: Include rsp-low.h.
* remote.h (hex2bin, bin2hex, unpack_varlen_hex): Don't declare.
* remote.c: Include rsp-low.h.
(hexchars, ishex, unpack_varlen_hex, pack_nibble, pack_hex_byte)
(fromhex, hex2bin, tohex, bin2hex, remote_escape_output)
(remote_unescape_input): Move to common/rsp-low.c.
* common/rsp-low.h: New file.
* common/rsp-low.c: New file.
* Makefile.in (SFILES): Add common/rsp-low.c.
(HFILES_NO_SRCDIR): Add common/rsp-low.h.
(COMMON_OBS): Add rsp-low.o.
(rsp-low.o): New target.
2014-02-12 Tom Tromey <tromey@redhat.com>
* tracepoint.c: Include rsp-low.h.
* server.c: Include rsp-low.h.
* remote-utils.h (convert_ascii_to_int, convert_int_to_ascii)
(unhexify, hexify, remote_escape_output, unpack_varlen_hex): Don't
declare.
* remote-utils.c: Include rsp-low.h.
(fromhex, hexchars, ishex, unhexify, tohex, hexify)
(remote_escape_output, remote_unescape_input, unpack_varlen_hex)
(convert_int_to_ascii, convert_ascii_to_int): Move to
common/rsp-low.c.
* regcache.c: Include rsp-low.h.
* ax.c: Include rsp-low.h.
* Makefile.in (SFILES): Add common/rsp-low.c.
(OBS): Add rsp-low.o.
(rsp-low.o): New target.
Diffstat (limited to 'gdb/common/rsp-low.c')
-rw-r--r-- | gdb/common/rsp-low.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/gdb/common/rsp-low.c b/gdb/common/rsp-low.c new file mode 100644 index 0000000..07e7ddb --- /dev/null +++ b/gdb/common/rsp-low.c @@ -0,0 +1,277 @@ +/* Low-level RSP routines for GDB, the GNU debugger. + + Copyright (C) 1988-2014 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef GDBSERVER +#include "server.h" +#else +#include "defs.h" +#endif + +#include <string.h> + +#include "rsp-low.h" + +/* Convert hex digit A to a number. */ + +int +fromhex (int a) +{ + if (a >= '0' && a <= '9') + return a - '0'; + else if (a >= 'a' && a <= 'f') + return a - 'a' + 10; + else if (a >= 'A' && a <= 'F') + return a - 'A' + 10; + else + error (_("Reply contains invalid hex digit %d"), a); +} + +int +tohex (int nib) +{ + if (nib < 10) + return '0' + nib; + else + return 'a' + nib - 10; +} + +/* Encode 64 bits in 16 chars of hex. */ + +static const char hexchars[] = "0123456789abcdef"; + +static int +ishex (int ch, int *val) +{ + if ((ch >= 'a') && (ch <= 'f')) + { + *val = ch - 'a' + 10; + return 1; + } + if ((ch >= 'A') && (ch <= 'F')) + { + *val = ch - 'A' + 10; + return 1; + } + if ((ch >= '0') && (ch <= '9')) + { + *val = ch - '0'; + return 1; + } + return 0; +} + +char * +pack_nibble (char *buf, int nibble) +{ + *buf++ = hexchars[(nibble & 0x0f)]; + return buf; +} + +char * +pack_hex_byte (char *pkt, int byte) +{ + *pkt++ = hexchars[(byte >> 4) & 0xf]; + *pkt++ = hexchars[(byte & 0xf)]; + return pkt; +} + +char * +unpack_varlen_hex (char *buff, /* packet to parse */ + ULONGEST *result) +{ + int nibble; + ULONGEST retval = 0; + + while (ishex (*buff, &nibble)) + { + buff++; + retval = retval << 4; + retval |= nibble & 0x0f; + } + *result = retval; + return buff; +} + +int +hex2bin (const char *hex, gdb_byte *bin, int count) +{ + int i; + + for (i = 0; i < count; i++) + { + if (hex[0] == 0 || hex[1] == 0) + { + /* Hex string is short, or of uneven length. + Return the count that has been converted so far. */ + return i; + } + *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]); + hex += 2; + } + return i; +} + +int +unhexify (char *bin, const char *hex, int count) +{ + int i; + + for (i = 0; i < count; i++) + { + if (hex[0] == 0 || hex[1] == 0) + { + /* Hex string is short, or of uneven length. + Return the count that has been converted so far. */ + return i; + } + *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]); + hex += 2; + } + return i; +} + +void +convert_ascii_to_int (const char *from, unsigned char *to, int n) +{ + int nib1, nib2; + while (n--) + { + nib1 = fromhex (*from++); + nib2 = fromhex (*from++); + *to++ = (((nib1 & 0x0f) << 4) & 0xf0) | (nib2 & 0x0f); + } +} + +int +bin2hex (const gdb_byte *bin, char *hex, int count) +{ + int i; + + /* May use a length, or a nul-terminated string as input. */ + if (count == 0) + count = strlen ((char *) bin); + + for (i = 0; i < count; i++) + { + *hex++ = tohex ((*bin >> 4) & 0xf); + *hex++ = tohex (*bin++ & 0xf); + } + *hex = 0; + return i; +} + +int +hexify (char *hex, const char *bin, int count) +{ + int i; + + /* May use a length, or a nul-terminated string as input. */ + if (count == 0) + count = strlen (bin); + + for (i = 0; i < count; i++) + { + *hex++ = tohex ((*bin >> 4) & 0xf); + *hex++ = tohex (*bin++ & 0xf); + } + *hex = 0; + return i; +} + +void +convert_int_to_ascii (const unsigned char *from, char *to, int n) +{ + int nib; + int ch; + while (n--) + { + ch = *from++; + nib = ((ch & 0xf0) >> 4) & 0x0f; + *to++ = tohex (nib); + nib = ch & 0x0f; + *to++ = tohex (nib); + } + *to++ = 0; +} + +int +remote_escape_output (const gdb_byte *buffer, int len, + gdb_byte *out_buf, int *out_len, + int out_maxlen) +{ + int input_index, output_index; + + output_index = 0; + for (input_index = 0; input_index < len; input_index++) + { + gdb_byte b = buffer[input_index]; + + if (b == '$' || b == '#' || b == '}' || b == '*') + { + /* These must be escaped. */ + if (output_index + 2 > out_maxlen) + break; + out_buf[output_index++] = '}'; + out_buf[output_index++] = b ^ 0x20; + } + else + { + if (output_index + 1 > out_maxlen) + break; + out_buf[output_index++] = b; + } + } + + *out_len = input_index; + return output_index; +} + +int +remote_unescape_input (const gdb_byte *buffer, int len, + gdb_byte *out_buf, int out_maxlen) +{ + int input_index, output_index; + int escaped; + + output_index = 0; + escaped = 0; + for (input_index = 0; input_index < len; input_index++) + { + gdb_byte b = buffer[input_index]; + + if (output_index + 1 > out_maxlen) + error (_("Received too much data from the target.")); + + if (escaped) + { + out_buf[output_index++] = b ^ 0x20; + escaped = 0; + } + else if (b == '}') + escaped = 1; + else + out_buf[output_index++] = b; + } + + if (escaped) + error (_("Unmatched escape character in target response.")); + + return output_index; +} + |