aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 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 ()