summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Machado <luis.machado@linaro.org>2020-06-15 15:34:06 -0300
committerLuis Machado <luis.machado@linaro.org>2020-07-16 13:09:26 -0300
commit4dbf3463f822610b3fbe673ccc24955696789e1a (patch)
treed09759ee79f091c677c8526f68e124a8a98cb010
parent8bde5d89adb2fe092ceac4a577762de26938b2b5 (diff)
downloadbinutils-gdb-4dbf3463f822610b3fbe673ccc24955696789e1a.tar.gz
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.cc40
-rw-r--r--gdbserver/remote-utils.h2
-rw-r--r--gdbserver/server.cc126
-rw-r--r--gdbserver/server.h3
-rw-r--r--gdbserver/target.cc20
-rw-r--r--gdbserver/target.h17
6 files changed, 186 insertions, 22 deletions
diff --git a/gdbserver/remote-utils.cc b/gdbserver/remote-utils.cc
index c26668dc0f8..5cf98725103 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 1b31456798b..1c82f40ad6a 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 ab5363eb032..2fb2b399b24 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
@@ -2337,6 +2428,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. */
@@ -2454,6 +2551,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 ();
@@ -2646,6 +2746,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;
@@ -3852,6 +3977,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 22228050a80..3d4a086e180 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 87f62a0b555..8beeeaee9ef 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 13f069f7729..f85c876fa3c 100644
--- a/gdbserver/target.h
+++ b/gdbserver/target.h
@@ -30,6 +30,7 @@
#include "gdbsupport/array-view.h"
#include "gdbsupport/btrace-common.h"
#include <vector>
+#include "gdbsupport/byte-vector.h"
struct emit_ops;
struct buffer;
@@ -499,6 +500,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;
@@ -525,6 +539,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 ()