mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 15:15:42 +00:00
gdbserver, remote: introduce "id_str" in the "qXfer:threads:read" XML
GDB prints the target id of a thread in various places such as the output of the "info threads" command in the "Target Id" column or when switching to a thread. A target can define what to print for a given ptid by overriding the `pid_to_str` method. The remote target is a gateway behind which one of many various targets could be running. The remote target converts a given ptid to a string in a uniform way, without consulting the low target at the server-side. In this patch we introduce a new attribute in the XML that is sent in response to the "qXfer:threads:read" RSP packet, so that a low target at the server side, if it wishes, can specify what to print as the target id of a thread. Note that the existing "name" attribute or the "extra" text provided in the XML are not sufficient for the server-side low target to achieve the goal. Those attributes, when present, are simply appended to the target id by GDB. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Reviewed-By: Thiago Jung Bauermann <thiago.bauermann@linaro.org> Approved-By: Simon Marchi <simon.marchi@efficios.com>
This commit is contained in:
8
gdb/NEWS
8
gdb/NEWS
@@ -62,6 +62,14 @@ binary-upload in qSupported reply
|
|||||||
stub doesn't report this feature supported, then GDB will not use
|
stub doesn't report this feature supported, then GDB will not use
|
||||||
the 'x' packet.
|
the 'x' packet.
|
||||||
|
|
||||||
|
* Changed remote packets
|
||||||
|
|
||||||
|
qXfer:threads:read
|
||||||
|
The XML that is sent as a response can now include an "id_str"
|
||||||
|
attribute for a thread element. The attribute indicates what GDB
|
||||||
|
should print as the target ID of the thread, for example in the
|
||||||
|
"info threads" command or when switching to the thread.
|
||||||
|
|
||||||
* MI changes
|
* MI changes
|
||||||
|
|
||||||
** The =library-unloaded event now includes the 'ranges' field, which
|
** The =library-unloaded event now includes the 'ranges' field, which
|
||||||
|
|||||||
@@ -48444,7 +48444,7 @@ the following structure:
|
|||||||
@smallexample
|
@smallexample
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<threads>
|
<threads>
|
||||||
<thread id="id" core="0" name="name" handle="1a2b3c">
|
<thread id="id" core="0" name="name" id_str="Thread 12.34" handle="1a2b3c">
|
||||||
... description ...
|
... description ...
|
||||||
</thread>
|
</thread>
|
||||||
</threads>
|
</threads>
|
||||||
@@ -48456,7 +48456,10 @@ identifies the thread (@pxref{thread-id syntax}). The
|
|||||||
the thread was last executing on. The @samp{name} attribute, if
|
the thread was last executing on. The @samp{name} attribute, if
|
||||||
present, specifies the human-readable name of the thread. The content
|
present, specifies the human-readable name of the thread. The content
|
||||||
of the of @samp{thread} element is interpreted as human-readable
|
of the of @samp{thread} element is interpreted as human-readable
|
||||||
auxiliary information. The @samp{handle} attribute, if present,
|
auxiliary information. The @samp{id_str} attribute, if present,
|
||||||
|
specifies what @value{GDBN} should print as the target ID of the
|
||||||
|
thread (e.g.@: in the @samp{info threads} command or when switching
|
||||||
|
to the thread). The @samp{handle} attribute, if present,
|
||||||
is a hex encoded representation of the thread handle.
|
is a hex encoded representation of the thread handle.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
26
gdb/remote.c
26
gdb/remote.c
@@ -1623,6 +1623,12 @@ struct remote_thread_info : public private_thread_info
|
|||||||
std::string name;
|
std::string name;
|
||||||
int core = -1;
|
int core = -1;
|
||||||
|
|
||||||
|
/* The string representation for the thread's id.
|
||||||
|
|
||||||
|
The target specifies this if they want to display the thread id
|
||||||
|
in a specific way. If empty, the default approach is used. */
|
||||||
|
std::string id_str;
|
||||||
|
|
||||||
/* Thread handle, perhaps a pthread_t or thread_t value, stored as a
|
/* Thread handle, perhaps a pthread_t or thread_t value, stored as a
|
||||||
sequence of bytes. */
|
sequence of bytes. */
|
||||||
gdb::byte_vector thread_handle;
|
gdb::byte_vector thread_handle;
|
||||||
@@ -4030,6 +4036,9 @@ struct thread_item
|
|||||||
/* The thread's name. */
|
/* The thread's name. */
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
|
/* The thread's id, translated to a string for displaying. */
|
||||||
|
std::string id_str;
|
||||||
|
|
||||||
/* The core the thread was running on. -1 if not known. */
|
/* The core the thread was running on. -1 if not known. */
|
||||||
int core = -1;
|
int core = -1;
|
||||||
|
|
||||||
@@ -4156,6 +4165,10 @@ start_thread (struct gdb_xml_parser *parser,
|
|||||||
if (attr != NULL)
|
if (attr != NULL)
|
||||||
item.name = (const char *) attr->value.get ();
|
item.name = (const char *) attr->value.get ();
|
||||||
|
|
||||||
|
attr = xml_find_attribute (attributes, "id_str");
|
||||||
|
if (attr != nullptr)
|
||||||
|
item.id_str = (const char *) attr->value.get ();
|
||||||
|
|
||||||
attr = xml_find_attribute (attributes, "handle");
|
attr = xml_find_attribute (attributes, "handle");
|
||||||
if (attr != NULL)
|
if (attr != NULL)
|
||||||
item.thread_handle = hex2bin ((const char *) attr->value.get ());
|
item.thread_handle = hex2bin ((const char *) attr->value.get ());
|
||||||
@@ -4177,6 +4190,7 @@ const struct gdb_xml_attribute thread_attributes[] = {
|
|||||||
{ "id", GDB_XML_AF_NONE, NULL, NULL },
|
{ "id", GDB_XML_AF_NONE, NULL, NULL },
|
||||||
{ "core", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
|
{ "core", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
|
||||||
{ "name", GDB_XML_AF_OPTIONAL, NULL, NULL },
|
{ "name", GDB_XML_AF_OPTIONAL, NULL, NULL },
|
||||||
|
{ "id_str", GDB_XML_AF_OPTIONAL, NULL, NULL },
|
||||||
{ "handle", GDB_XML_AF_OPTIONAL, NULL, NULL },
|
{ "handle", GDB_XML_AF_OPTIONAL, NULL, NULL },
|
||||||
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
|
||||||
};
|
};
|
||||||
@@ -4361,6 +4375,7 @@ remote_target::update_thread_list ()
|
|||||||
info->core = item.core;
|
info->core = item.core;
|
||||||
info->extra = std::move (item.extra);
|
info->extra = std::move (item.extra);
|
||||||
info->name = std::move (item.name);
|
info->name = std::move (item.name);
|
||||||
|
info->id_str = std::move (item.id_str);
|
||||||
info->thread_handle = std::move (item.thread_handle);
|
info->thread_handle = std::move (item.thread_handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12392,7 +12407,16 @@ remote_target::pid_to_str (ptid_t ptid)
|
|||||||
{
|
{
|
||||||
if (magic_null_ptid == ptid)
|
if (magic_null_ptid == ptid)
|
||||||
return "Thread <main>";
|
return "Thread <main>";
|
||||||
else if (m_features.remote_multi_process_p ())
|
|
||||||
|
thread_info *thread = this->find_thread (ptid);
|
||||||
|
if ((thread != nullptr) && (thread->priv != nullptr))
|
||||||
|
{
|
||||||
|
remote_thread_info *priv = get_remote_thread_info (thread);
|
||||||
|
if (!priv->id_str.empty ())
|
||||||
|
return priv->id_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_features.remote_multi_process_p ())
|
||||||
if (ptid.lwp () == 0)
|
if (ptid.lwp () == 0)
|
||||||
return normal_pid_to_str (ptid);
|
return normal_pid_to_str (ptid);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1981,6 +1981,7 @@ handle_qxfer_threads_worker (thread_info *thread, std::string *buffer)
|
|||||||
int core = target_core_of_thread (ptid);
|
int core = target_core_of_thread (ptid);
|
||||||
char core_s[21];
|
char core_s[21];
|
||||||
const char *name = target_thread_name (ptid);
|
const char *name = target_thread_name (ptid);
|
||||||
|
std::string id_str = target_thread_id_str (thread);
|
||||||
int handle_len;
|
int handle_len;
|
||||||
gdb_byte *handle;
|
gdb_byte *handle;
|
||||||
bool handle_status = target_thread_handle (ptid, &handle, &handle_len);
|
bool handle_status = target_thread_handle (ptid, &handle, &handle_len);
|
||||||
@@ -2005,6 +2006,9 @@ handle_qxfer_threads_worker (thread_info *thread, std::string *buffer)
|
|||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
string_xml_appendf (*buffer, " name=\"%s\"", name);
|
string_xml_appendf (*buffer, " name=\"%s\"", name);
|
||||||
|
|
||||||
|
if (!id_str.empty ())
|
||||||
|
string_xml_appendf (*buffer, " id_str=\"%s\"", id_str.c_str ());
|
||||||
|
|
||||||
if (handle_status)
|
if (handle_status)
|
||||||
{
|
{
|
||||||
char *handle_s = (char *) alloca (handle_len * 2 + 1);
|
char *handle_s = (char *) alloca (handle_len * 2 + 1);
|
||||||
|
|||||||
@@ -807,6 +807,12 @@ process_stratum_target::thread_name (ptid_t thread)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
process_stratum_target::thread_id_str (thread_info *thread)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
process_stratum_target::thread_handle (ptid_t ptid, gdb_byte **handle,
|
process_stratum_target::thread_handle (ptid_t ptid, gdb_byte **handle,
|
||||||
int *handle_len)
|
int *handle_len)
|
||||||
|
|||||||
@@ -475,6 +475,13 @@ public:
|
|||||||
caller. */
|
caller. */
|
||||||
virtual const char *thread_name (ptid_t thread);
|
virtual const char *thread_name (ptid_t thread);
|
||||||
|
|
||||||
|
/* Return the string translation for THREAD's id. This gives the
|
||||||
|
target a chance to completely re-interpret the thread id and
|
||||||
|
present a target-specific description for displaying to the user.
|
||||||
|
Return empty if the target is fine with how an id is displayed
|
||||||
|
by default. */
|
||||||
|
virtual std::string thread_id_str (thread_info *thread);
|
||||||
|
|
||||||
/* Thread ID to (numeric) thread handle: Return true on success and
|
/* Thread ID to (numeric) thread handle: Return true on success and
|
||||||
false for failure. Return pointer to thread handle via HANDLE
|
false for failure. Return pointer to thread handle via HANDLE
|
||||||
and the handle's length via HANDLE_LEN. */
|
and the handle's length via HANDLE_LEN. */
|
||||||
@@ -735,4 +742,10 @@ bool set_desired_process ();
|
|||||||
|
|
||||||
std::string target_pid_to_str (ptid_t);
|
std::string target_pid_to_str (ptid_t);
|
||||||
|
|
||||||
|
static inline std::string
|
||||||
|
target_thread_id_str (thread_info *thread)
|
||||||
|
{
|
||||||
|
return the_target->thread_id_str (thread);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* GDBSERVER_TARGET_H */
|
#endif /* GDBSERVER_TARGET_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user