diff options
author | Luis Machado <luis.machado@linaro.org> | 2020-06-15 15:34:06 -0300 |
---|---|---|
committer | Luis Machado <luis.machado@linaro.org> | 2020-06-25 13:23:38 -0300 |
commit | 9ffb8389d39facef2ea2519e322a294b08bd8d16 (patch) | |
tree | 592439c419d76e1aa5e6ff386d81589c86355346 | |
parent | ebd61ee8b5161ded8653c32da0ec57927e1ba9c1 (diff) | |
download | gdb-9ffb8389d39facef2ea2519e322a294b08bd8d16.zip gdb-9ffb8389d39facef2ea2519e322a294b08bd8d16.tar.gz gdb-9ffb8389d39facef2ea2519e322a294b08bd8d16.tar.bz2 |
GDBserver remote packet support for memory tagging
This patch adds the generic remote bits to gdbserver so it can check for memory
tagging support and handle fetch tags and store tags requests.
gdbserver/ChangeLog:
YYYY-MM-DD Luis Machado <luis.machado@linaro.org>
* remote-utils.cc (decode_m_packet_params): Renamed from ...
(decode_m_packet): ... this, which now calls decode_m_packet_params.
(decode_M_packet): Use decode_m_packet_params.
* remote-utils.h (decode_m_packet_params): New prototype.
* server.cc (create_fmemtags_reply, parse_smemtags_request): New
functions.
(handle_general_set): Handle the QMemTags packet.
(parse_fmemtags_request): New function.
(handle_query): Handle the qMemTags packet and advertise memory
tagging support.
(captured_main): Initialize memory tagging flag.
* server.h (struct client_state): Initialize memory tagging flag.
* target.cc (process_stratum_target::supports_memory_tagging)
(process_stratum_target::fetch_memtags)
(process_stratum_target::store_memtags): New methods.
* target.h: Include gdbsupport/byte-vector.h.
(class process_stratum_target) <supports_memory_tagging>
<fetch_memtags, store_memtags>: New class virtual methods.
(target_supports_memory_tagging): Define.
-rw-r--r-- | gdbserver/remote-utils.cc | 40 | ||||
-rw-r--r-- | gdbserver/remote-utils.h | 2 | ||||
-rw-r--r-- | gdbserver/server.cc | 126 | ||||
-rw-r--r-- | gdbserver/server.h | 3 | ||||
-rw-r--r-- | gdbserver/target.cc | 20 | ||||
-rw-r--r-- | gdbserver/target.h | 17 |
6 files changed, 186 insertions, 22 deletions
diff --git a/gdbserver/remote-utils.cc b/gdbserver/remote-utils.cc index c26668d..5cf9872 100644 --- a/gdbserver/remote-utils.cc +++ b/gdbserver/remote-utils.cc @@ -1302,10 +1302,14 @@ prepare_resume_reply (char *buf, ptid_t ptid, } } -void -decode_m_packet (char *from, CORE_ADDR *mem_addr_ptr, unsigned int *len_ptr) +/* Decode ADDR and LEN from a parameter of the form "addr,len<x>", with <x> + being an end marker character. */ + +char * +decode_m_packet_params (char *from, CORE_ADDR *mem_addr_ptr, + unsigned int *len_ptr, const char end_marker) { - int i = 0, j = 0; + int i = 0; char ch; *mem_addr_ptr = *len_ptr = 0; @@ -1315,39 +1319,31 @@ decode_m_packet (char *from, CORE_ADDR *mem_addr_ptr, unsigned int *len_ptr) *mem_addr_ptr |= fromhex (ch) & 0x0f; } - for (j = 0; j < 4; j++) + while ((ch = from[i++]) != end_marker) { - if ((ch = from[i++]) == 0) - break; *len_ptr = *len_ptr << 4; *len_ptr |= fromhex (ch) & 0x0f; } + + return from + i; +} + +void +decode_m_packet (char *from, CORE_ADDR *mem_addr_ptr, unsigned int *len_ptr) +{ + decode_m_packet_params (from, mem_addr_ptr, len_ptr, '\0'); } void decode_M_packet (char *from, CORE_ADDR *mem_addr_ptr, unsigned int *len_ptr, unsigned char **to_p) { - int i = 0; - char ch; - *mem_addr_ptr = *len_ptr = 0; - - while ((ch = from[i++]) != ',') - { - *mem_addr_ptr = *mem_addr_ptr << 4; - *mem_addr_ptr |= fromhex (ch) & 0x0f; - } - - while ((ch = from[i++]) != ':') - { - *len_ptr = *len_ptr << 4; - *len_ptr |= fromhex (ch) & 0x0f; - } + from = decode_m_packet_params (from, mem_addr_ptr, len_ptr, ':'); if (*to_p == NULL) *to_p = (unsigned char *) xmalloc (*len_ptr); - hex2bin (&from[i++], *to_p, *len_ptr); + hex2bin (from, *to_p, *len_ptr); } int diff --git a/gdbserver/remote-utils.h b/gdbserver/remote-utils.h index 1b31456..1c82f40 100644 --- a/gdbserver/remote-utils.h +++ b/gdbserver/remote-utils.h @@ -45,6 +45,8 @@ void prepare_resume_reply (char *buf, ptid_t ptid, const char *decode_address_to_semicolon (CORE_ADDR *addrp, const char *start); void decode_address (CORE_ADDR *addrp, const char *start, int len); +char *decode_m_packet_params (char *from, CORE_ADDR *mem_addr_ptr, + unsigned int *len_ptr, const char end_marker); void decode_m_packet (char *from, CORE_ADDR * mem_addr_ptr, unsigned int *len_ptr); void decode_M_packet (char *from, CORE_ADDR * mem_addr_ptr, diff --git a/gdbserver/server.cc b/gdbserver/server.cc index 0313d18..bf5c557 100644 --- a/gdbserver/server.cc +++ b/gdbserver/server.cc @@ -545,12 +545,59 @@ handle_btrace_conf_general_set (char *own_buf) return 1; } +/* Create the qMemTags packet reply given TAGS. */ + +static int +create_fmemtags_reply (char *reply, const gdb::byte_vector &tags) +{ + /* It is an error to pass a zero-sized tag vector. */ + if (tags.size () == 0) + return 1; + + std::string packet ("m"); + + /* Write the tag data. */ + packet += bin2hex (tags.data (), tags.size ()); + + /* Check if the reply is too big for the packet to handle. */ + if (PBUFSIZ < packet.size ()) + return 1; + + strcpy (reply, packet.c_str ()); + return 0; +} + +/* Parse the QMemTags request into ADDR, LEN and TAGS. + + Return 0 if successful, non-zero otherwise. */ + +static int +parse_smemtags_request (char *request, CORE_ADDR *addr, size_t *len, + gdb::byte_vector &tags) +{ + if (!startswith (request, "QMemTags:")) + return 1; + + char *p = request + strlen ("QMemTags:"); + + /* Read address and length. */ + unsigned int length = 0; + p = decode_m_packet_params (p, addr, &length, ':'); + *len = length; + + /* Read the tag data. */ + tags = hex2bin (p); + + return 0; +} + /* Handle all of the extended 'Q' packets. */ static void handle_general_set (char *own_buf) { client_state &cs = get_client_state (); + if (startswith (own_buf, "QPassSignals:")) { int numsigs = (int) GDB_SIGNAL_LAST, i; @@ -899,6 +946,30 @@ handle_general_set (char *own_buf) return; } + + /* Handle store memory tags packets. */ + if (startswith (own_buf, "QMemTags:") + && target_supports_memory_tagging ()) + { + gdb::byte_vector tags; + CORE_ADDR addr = 0; + size_t len = 0; + + require_running_or_return (own_buf); + + int ret = parse_smemtags_request (own_buf, &addr, &len, tags); + + if (ret == 0) + ret = the_target->store_memtags (addr, len, tags); + + if (ret) + write_enn (own_buf); + else + write_ok (own_buf); + + return; + } + /* Otherwise we didn't know what packet it was. Say we didn't understand it. */ own_buf[0] = 0; @@ -2119,6 +2190,26 @@ crc32 (CORE_ADDR base, int len, unsigned int crc) return (unsigned long long) crc; } +/* Parse the qMemTags packet request into ADDR and LEN. + + Return 0 if successful, non-zero otherwise. */ + +static int +parse_fmemtags_request (char *request, CORE_ADDR *addr, size_t *len) +{ + if (!startswith (request, "qMemTags:")) + return 1; + + char *p = request + strlen ("qMemTags:"); + + /* Read address and length. */ + unsigned int length = 0; + decode_m_packet (p, addr, &length); + *len = length; + + return 0; +} + /* Add supported btrace packets to BUF. */ static void @@ -2344,6 +2435,12 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) events. */ report_no_resumed = true; } + else if (strcmp (p, "memory-tagging+") == 0) + { + /* GDB supports memory tagging features. */ + if (target_supports_memory_tagging ()) + cs.memory_tagging_feature = true; + } else { /* Move the unknown features all together. */ @@ -2467,6 +2564,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) strcat (own_buf, ";no-resumed+"); + if (target_supports_memory_tagging ()) + strcat (own_buf, ";memory-tagging+"); + /* Reinitialize components as needed for the new connection. */ hostio_handle_new_gdb_connection (); target_handle_new_gdb_connection (); @@ -2659,6 +2759,31 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) if (target_supports_tracepoints () && handle_tracepoint_query (own_buf)) return; + /* Handle fetch memory tags packets. */ + if (startswith (own_buf, "qMemTags:") + && target_supports_memory_tagging ()) + { + gdb::byte_vector tags; + CORE_ADDR addr = 0; + size_t len = 0; + + require_running_or_return (own_buf); + + int ret = parse_fmemtags_request (own_buf, &addr, &len); + + if (ret == 0) + ret = the_target->fetch_memtags (addr, len, tags); + + if (ret == 0) + ret = create_fmemtags_reply (own_buf, tags); + + if (ret) + write_enn (own_buf); + + *new_packet_len_p = strlen (own_buf); + return; + } + /* Otherwise we didn't know what packet it was. Say we didn't understand it. */ own_buf[0] = 0; @@ -3865,6 +3990,7 @@ captured_main (int argc, char *argv[]) cs.swbreak_feature = 0; cs.hwbreak_feature = 0; cs.vCont_supported = 0; + cs.memory_tagging_feature = false; remote_open (port); diff --git a/gdbserver/server.h b/gdbserver/server.h index 2222805..3d4a086 100644 --- a/gdbserver/server.h +++ b/gdbserver/server.h @@ -190,6 +190,9 @@ struct client_state int current_traceframe = -1; + /* If true, memory tagging features are supported. */ + bool memory_tagging_feature = false; + }; client_state &get_client_state (); diff --git a/gdbserver/target.cc b/gdbserver/target.cc index b5190e1..f20adcc 100644 --- a/gdbserver/target.cc +++ b/gdbserver/target.cc @@ -463,6 +463,26 @@ process_stratum_target::supports_read_offsets () return false; } +bool +process_stratum_target::supports_memory_tagging () +{ + return false; +} + +int +process_stratum_target::fetch_memtags (CORE_ADDR address, size_t len, + gdb::byte_vector &tags) +{ + return 0; +} + +int +process_stratum_target::store_memtags (CORE_ADDR address, size_t len, + const gdb::byte_vector &tags) +{ + return 0; +} + int process_stratum_target::read_offsets (CORE_ADDR *text, CORE_ADDR *data) { diff --git a/gdbserver/target.h b/gdbserver/target.h index 701c8ef..a28a3eb 100644 --- a/gdbserver/target.h +++ b/gdbserver/target.h @@ -29,6 +29,7 @@ #include "mem-break.h" #include "gdbsupport/btrace-common.h" #include <vector> +#include "gdbsupport/byte-vector.h" struct emit_ops; struct buffer; @@ -497,6 +498,19 @@ public: /* Return tdesc index for IPA. */ virtual int get_ipa_tdesc_idx (); + + /* Returns true if the target supports memory tagging facilities. */ + virtual bool supports_memory_tagging (); + + /* Return the allocated memory tags associated with + [ADDRESS, ADDRESS + LEN) in TAGS. */ + virtual int fetch_memtags (CORE_ADDR address, size_t len, + gdb::byte_vector &tags); + + /* Write the allocation tags contained in TAGS to the memory range + [ADDRESS, ADDRESS + LEN). */ + virtual int store_memtags (CORE_ADDR address, size_t len, + const gdb::byte_vector &tags); }; extern process_stratum_target *the_target; @@ -523,6 +537,9 @@ int kill_inferior (process_info *proc); #define target_supports_exec_events() \ the_target->supports_exec_events () +#define target_supports_memory_tagging() \ + the_target->supports_memory_tagging () + #define target_handle_new_gdb_connection() \ the_target->handle_new_gdb_connection () |