diff options
-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 () |