From: Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
To: gdb-patches@sourceware.org, Markus Metzger <markus.t.metzger@intel.com>
Subject: [PATCH v3 09/44] gdb, gdbserver, ze: in-memory libraries
Date: Fri, 1 Aug 2025 11:37:11 +0200 [thread overview]
Message-ID: <20250801-upstream-intelgt-mvp-v3-9-59ce0f87075b@intel.com> (raw)
In-Reply-To: <20250801-upstream-intelgt-mvp-v3-0-59ce0f87075b@intel.com>
From: Markus Metzger <markus.t.metzger@intel.com>
For Intel GPU devices, device libraries live in the host memory and are
loaded onto the device from there.
Add support for reporting such in-memory shared libraries via
qXfer:libraries:read
and have GDB read them from target memory.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
---
gdb/NEWS | 6 ++
gdb/doc/gdb.texinfo | 43 +++++++++----
gdb/features/library-list.dtd | 8 ++-
gdb/remote.c | 3 +
gdb/solib-target.c | 88 +++++++++++++++++++++++++--
gdb/solib-target.h | 2 +
gdb/solib.c | 31 +++++++++-
gdb/solib.h | 12 +++-
gdbserver/dll.cc | 95 +++++++++++++++++++++++------
gdbserver/dll.h | 34 ++++++++++-
gdbserver/server.cc | 137 ++++++++++++++++++++++++++++++++++++++++--
gdbserver/server.h | 3 +
12 files changed, 415 insertions(+), 47 deletions(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index 5736565d4758a31ad7902905d280c2f68f7a8b08..36944e1a0a408aab3200bcd32c8ee462bb06428e 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -196,6 +196,12 @@ vFile:lstat
vFile:stat but if the filename is a symbolic link, return
information about the link itself, the file the link refers to.
+qXfer:libraries:read's response
+
+ The qXfer:libraries:read query supports reporting in-memory libraries. GDB
+ indicates support by supplying qXfer:libraries:read:in-memory-library+ in the
+ qSupported packet.
+
* Changed remote packets
qXfer:threads:read
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index a4c98d18e20182765f8cf0546447c6777cdd5e2d..628ee49b703c23888f518af584128111c9473ef9 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -24882,6 +24882,9 @@ future connections is shown. The available settings are:
@tab @code{no resumed thread left stop reply}
@tab Tracking thread lifetime.
+@item @code{qXfer:libraries:read:in-memory-library}
+@tab @code{in-memory-library library elements}
+@tab Support for in-memory libraries.
@end multitable
@cindex packet size, remote, configuring
@@ -48295,9 +48298,10 @@ queries the target's operating system and reports which libraries
are loaded.
The @samp{qXfer:libraries:read} packet returns an XML document which
-lists loaded libraries and their offsets. Each library has an
-associated name and one or more segment or section base addresses,
-which report where the library was loaded in memory.
+lists loaded libraries and their offsets. Each library has either an
+associated name or begin and end addresses and one or more segment or
+section base addresses, which report where the library was loaded in
+memory.
For the common case of libraries that are fully linked binaries, the
library should have a list of segments. If the target supports
@@ -48309,6 +48313,10 @@ depend on the library's link-time base addresses.
@value{GDBN} must be linked with the Expat library to support XML
library lists. @xref{Expat}.
+@value{GDBN} indicates support for in-memory library elements by
+supplying the @code{qXfer:libraries:read:in-memory-library+}
+@samp{qSupported} feature (@pxref{qSupported}).
+
A simple memory map, with one loaded library relocated by a single
offset, looks like this:
@@ -48320,6 +48328,16 @@ offset, looks like this:
</library-list>
@end smallexample
+A corresponding memory map for an in-memory library looks like this:
+
+@smallexample
+<library-list>
+ <in-memory-library begin="0xa000000" end="0xa001000">
+ <segment address="0x10000000"/>
+ </in-memory-library>
+</library-list>
+@end smallexample
+
Another simple memory map, with one loaded library with three
allocated sections (.text, .data, .bss), looks like this:
@@ -48337,14 +48355,17 @@ The format of a library list is described by this DTD:
@smallexample
<!-- library-list: Root element with versioning -->
-<!ELEMENT library-list (library)*>
-<!ATTLIST library-list version CDATA #FIXED "1.0">
-<!ELEMENT library (segment*, section*)>
-<!ATTLIST library name CDATA #REQUIRED>
-<!ELEMENT segment EMPTY>
-<!ATTLIST segment address CDATA #REQUIRED>
-<!ELEMENT section EMPTY>
-<!ATTLIST section address CDATA #REQUIRED>
+<!ELEMENT library-list (library | in-memory-library)*>
+<!ATTLIST library-list version CDATA #FIXED "1.1">
+<!ELEMENT library (segment*, section*)>
+<!ATTLIST library name CDATA #REQUIRED>
+<!ELEMENT in-memory-library (segment*, section*)>
+<!ATTLIST in-memory-library begin CDATA #REQUIRED
+ end CDATA #REQUIRED>
+<!ELEMENT segment EMPTY>
+<!ATTLIST segment address CDATA #REQUIRED>
+<!ELEMENT section EMPTY>
+<!ATTLIST section address CDATA #REQUIRED>
@end smallexample
In addition, segments and section descriptors cannot be mixed within a
diff --git a/gdb/features/library-list.dtd b/gdb/features/library-list.dtd
index 66945cbe97c13cfac5a4d00e9a752ccd8419252f..baa01485af950c58e9e242229365501c043e2fe1 100644
--- a/gdb/features/library-list.dtd
+++ b/gdb/features/library-list.dtd
@@ -5,12 +5,16 @@
notice and this notice are preserved. -->
<!-- library-list: Root element with versioning -->
-<!ELEMENT library-list (library)*>
-<!ATTLIST library-list version CDATA #FIXED "1.0">
+<!ELEMENT library-list (library | in-memory-library)*>
+<!ATTLIST library-list version CDATA #FIXED "1.1">
<!ELEMENT library (segment*, section*)>
<!ATTLIST library name CDATA #REQUIRED>
+<!ELEMENT in-memory-library (segment*, section*)>
+<!ATTLIST in-memory-library begin CDATA #REQUIRED
+ end CDATA #REQUIRED>
+
<!ELEMENT segment EMPTY>
<!ATTLIST segment address CDATA #REQUIRED>
diff --git a/gdb/remote.c b/gdb/remote.c
index 6208a90f94a70bf25b0e16cfc4dcce1e01f28828..3d3acd19a53c3665055f8e27cc8669916083f562 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -5975,6 +5975,9 @@ remote_target::remote_query_supported ()
!= AUTO_BOOLEAN_FALSE)
remote_query_supported_append (&q, "memory-tagging+");
+ remote_query_supported_append
+ (&q, "qXfer:libraries:read:in-memory-library+");
+
/* Keep this one last to work around a gdbserver <= 7.10 bug in
the qSupported:xmlRegisters=i386 handling. */
if (remote_support_xml != NULL
diff --git a/gdb/solib-target.c b/gdb/solib-target.c
index 770028d9903953cb761c2901aae5a1f247aaa34b..5d9bc8f53204eb7e629f3807bcb170c6ace357aa 100644
--- a/gdb/solib-target.c
+++ b/gdb/solib-target.c
@@ -23,16 +23,36 @@
#include "symfile.h"
#include "target.h"
#include "solib-target.h"
+#include "gdbsupport/filestuff.h"
+#include "gdb_bfd.h"
#include <vector>
#include "inferior.h"
+/* The location of a loaded library. */
+
+enum lm_location_t
+{
+ lm_on_disk,
+ lm_in_memory
+};
+
/* Private data for each loaded library. */
struct lm_info_target final : public lm_info
{
+ /* The library's location. */
+ lm_location_t location;
+
/* The library's name. The name is normally kept in the struct
- solib; it is only here during XML parsing. */
+ solib; it is only here during XML parsing.
+
+ This is only valid if location == lm_on_disk. */
std::string name;
+ /* The library's begin and end memory addresses.
+
+ This is only valid if location == lm_in_memory. */
+ CORE_ADDR begin = 0ull, end = 0ull;
+
/* The target can either specify segment bases or section bases, not
both. */
@@ -122,12 +142,32 @@ library_list_start_library (struct gdb_xml_parser *parser,
{
auto *list = (std::vector<lm_info_target_up> *) user_data;
lm_info_target *item = new lm_info_target;
+ item->location = lm_on_disk;
item->name
= (const char *) xml_find_attribute (attributes, "name")->value.get ();
list->emplace_back (item);
}
+/* Handle the start of a <in-memory-library> element. */
+
+static void
+in_memory_library_list_start_library (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data,
+ std::vector<gdb_xml_value> &attributes)
+{
+ auto *list = (std::vector<lm_info_target_up> *) user_data;
+ lm_info_target *item = new lm_info_target;
+ item->location = lm_in_memory;
+ item->begin = (CORE_ADDR) *(ULONGEST *)
+ xml_find_attribute (attributes, "begin")->value.get ();
+ item->end = (CORE_ADDR) *(ULONGEST *)
+ xml_find_attribute (attributes, "end")->value.get ();
+
+ list->emplace_back (item);
+}
+
static void
library_list_end_library (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
@@ -156,7 +196,7 @@ library_list_start_list (struct gdb_xml_parser *parser,
{
const char *string = (const char *) version->value.get ();
- if (strcmp (string, "1.0") != 0)
+ if ((strcmp (string, "1.0") != 0) && (strcmp (string, "1.1") != 0))
gdb_xml_error (parser,
_("Library list has unsupported version \"%s\""),
string);
@@ -191,10 +231,19 @@ static const struct gdb_xml_attribute library_attributes[] = {
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
+static const struct gdb_xml_attribute in_memory_library_attributes[] = {
+ { "begin", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { "end", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
static const struct gdb_xml_element library_list_children[] = {
{ "library", library_attributes, library_children,
GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
library_list_start_library, library_list_end_library },
+ { "in-memory-library", in_memory_library_attributes, library_children,
+ GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
+ in_memory_library_list_start_library, library_list_end_library },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
@@ -246,10 +295,31 @@ target_solib_ops::current_sos () const
for (lm_info_target_up &info : library_list)
{
auto &new_solib = sos.emplace_back (*this);
+ switch (info->location)
+ {
+ case lm_on_disk:
+ /* We don't need a copy of the name in INFO anymore. */
+ new_solib.name = std::move (info->name);
+ new_solib.original_name = new_solib.name;
+ break;
+
+ case lm_in_memory:
+ if (info->end <= info->begin)
+ warning (_("bad in-memory-library location: begin=%s, end=%s"),
+ core_addr_to_string_nz (info->begin),
+ core_addr_to_string_nz (info->end));
+ else
+ {
+ new_solib.original_name = std::string ("in-memory-")
+ + core_addr_to_string_nz (info->begin)
+ + "-"
+ + core_addr_to_string_nz (info->end);
- /* We don't need a copy of the name in INFO anymore. */
- new_solib.name = std::move (info->name);
- new_solib.original_name = new_solib.name;
+ new_solib.begin = info->begin;
+ new_solib.end = info->end;
+ }
+ break;
+ }
new_solib.lm_info = std::move (info);
}
@@ -386,6 +456,14 @@ target_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const
return in_plt_section (pc);
}
+gdb_bfd_ref_ptr
+target_solib_ops::bfd_open_from_target_memory (CORE_ADDR addr,
+ CORE_ADDR size,
+ const char *target) const
+{
+ return gdb_bfd_open_from_target_memory (addr, size, target);
+}
+
/* See solib-target.h. */
solib_ops_up
diff --git a/gdb/solib-target.h b/gdb/solib-target.h
index 89ae2bc9b9e155b9cc31b7410a814e2340ab867a..ecd67658c71cb854f012c4311ba79bb40a2ca1b1 100644
--- a/gdb/solib-target.h
+++ b/gdb/solib-target.h
@@ -29,6 +29,8 @@ struct target_solib_ops : solib_ops
void relocate_section_addresses (solib &so, target_section *) const override;
owning_intrusive_list<solib> current_sos () const override;
bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
+ gdb_bfd_ref_ptr bfd_open_from_target_memory
+ (CORE_ADDR addr, CORE_ADDR size, const char *target) const override;
};
/* Return a new solib_ops for systems fetching solibs from the target. */
diff --git a/gdb/solib.c b/gdb/solib.c
index 3ec2032f01289011ba1bc3a651b076364f9438f1..f2b26d4e9f9b56b0d174e5223669bd392c3114de 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -473,6 +473,14 @@ solib_ops::bfd_open (const char *pathname) const
return solib_bfd_open (pathname);
}
+gdb_bfd_ref_ptr
+solib_ops::bfd_open_from_target_memory (CORE_ADDR addr,
+ CORE_ADDR size,
+ const char *target) const
+{
+ error (_("Target does not support in-memory shared libraries."));
+}
+
/* Given a pointer to one of the shared objects in our list of mapped
objects, use the recorded name to open a bfd descriptor for the
object, build a section table, relocate all the section addresses
@@ -488,8 +496,25 @@ solib_ops::bfd_open (const char *pathname) const
static int
solib_map_sections (solib &so)
{
- gdb::unique_xmalloc_ptr<char> filename (tilde_expand (so.name.c_str ()));
- gdb_bfd_ref_ptr abfd (so.ops ().bfd_open (filename.get ()));
+ gdb_bfd_ref_ptr abfd;
+ if (!so.name.empty ())
+ {
+ gdb::unique_xmalloc_ptr<char> filename (tilde_expand (so.name.c_str ()));
+ abfd = so.ops ().bfd_open (filename.get ());
+ }
+ else if (so.begin != 0 && so.end != 0)
+ {
+ if (so.end <= so.begin)
+ error (_("Bad address range [%s; %s) for in-memory shared library."),
+ core_addr_to_string_nz (so.begin),
+ core_addr_to_string_nz (so.end));
+
+ abfd = so.ops ().bfd_open_from_target_memory (so.begin,
+ so.end - so.begin,
+ gnutarget);
+ }
+ else
+ internal_error (_("bad so_list"));
/* If we have a core target then the core target might have some helpful
information (i.e. build-ids) about the shared libraries we are trying
@@ -536,7 +561,7 @@ solib_map_sections (solib &so)
{
warning (_("Build-id of %ps does not match core file."),
styled_string (file_name_style.style (),
- filename.get ()));
+ so.name.c_str ()));
abfd = nullptr;
}
}
diff --git a/gdb/solib.h b/gdb/solib.h
index b9465e103bdd89c83ba575d7551ce84e5e1c7a36..32101d27cc5acae22939eb6a9f72239aaf4812a4 100644
--- a/gdb/solib.h
+++ b/gdb/solib.h
@@ -94,9 +94,14 @@ struct solib : intrusive_list_node<solib>
map we've already loaded. */
std::string original_name;
- /* Shared object file name, expanded to something GDB can open. */
+ /* Shared object file name, expanded to something GDB can open.
+ This is an empty string for in-memory shared objects. */
std::string name;
+ /* The address range of an in-memory shared object. Both BEGIN and END
+ are zero for on-disk shared objects. */
+ CORE_ADDR begin = 0, end = 0;
+
/* The following fields of the structure are built from
information gathered from the shared object file itself, and
are set when we actually add it to our symbol tables.
@@ -259,6 +264,11 @@ struct solib_ops
The supports_namespaces method must return true for this to be called. */
virtual std::vector<const solib *> get_solibs_in_ns (int ns) const
{ gdb_assert_not_reached ("namespaces not supported"); }
+
+ /* Open an in-memory shared library at ADDR of at most SIZE bytes.
+ The TARGET string is used to identify the target. */
+ virtual gdb_bfd_ref_ptr bfd_open_from_target_memory
+ (CORE_ADDR addr, CORE_ADDR size, const char *target) const;
};
/* A unique pointer to an solib_ops. */
diff --git a/gdbserver/dll.cc b/gdbserver/dll.cc
index 5ce8b2b45d508bab69dd6c57cce6d4f60911d065..c8e7c03012a6fd1650a7f7a4827f79b3735d624b 100644
--- a/gdbserver/dll.cc
+++ b/gdbserver/dll.cc
@@ -40,34 +40,44 @@ loaded_dll (process_info *proc, const char *name, CORE_ADDR base_addr)
proc->dlls_changed = true;
}
-/* Record that the DLL with NAME and BASE_ADDR has been unloaded
- from the current process. */
+/* Record a newly loaded in-memory DLL at BASE_ADDR for PROC. */
void
-unloaded_dll (const char *name, CORE_ADDR base_addr)
+loaded_dll (process_info *proc, CORE_ADDR begin, CORE_ADDR end,
+ CORE_ADDR base_addr)
{
- unloaded_dll (current_process (), name, base_addr);
+ gdb_assert (proc != nullptr);
+
+ /* We do not support duplicate in-memory libraries. */
+ std::list<dll_info> &dlls = proc->all_dlls;
+ std::list<dll_info>::iterator it
+ = std::find_if (dlls.begin (), dlls.end (),
+ [begin, end] (const dll_info &dll)
+ {
+ return ((dll.begin == begin) && (dll.end == end));
+ });
+
+ if (it != dlls.end ())
+ error (_("Duplicate in-memory library; begin: %s, end: %s, base: %s."),
+ paddress (begin), paddress (end), paddress (base_addr));
+
+ proc->all_dlls.emplace_back (begin, end, base_addr);
+ proc->dlls_changed = true;
}
/* Record that the DLL with NAME and BASE_ADDR has been unloaded
- from PROC. */
+ from the current process. */
void
-unloaded_dll (process_info *proc, const char *name, CORE_ADDR base_addr)
+unloaded_dll (const char *name, CORE_ADDR base_addr)
{
- gdb_assert (proc != nullptr);
- auto pred = [&] (const dll_info &dll)
- {
- if (base_addr != UNSPECIFIED_CORE_ADDR
- && base_addr == dll.base_addr)
- return true;
-
- if (name != NULL && dll.name == name)
- return true;
-
- return false;
- };
+ unloaded_dll (current_process (), name, base_addr);
+}
+static void
+unload_dll_if (process_info *proc,
+ std::function<bool (const dll_info &)> pred)
+{
auto iter = std::find_if (proc->all_dlls.begin (), proc->all_dlls.end (),
pred);
@@ -89,3 +99,52 @@ unloaded_dll (process_info *proc, const char *name, CORE_ADDR base_addr)
proc->dlls_changed = true;
}
}
+
+/* Record that the DLL with NAME and BASE_ADDR has been unloaded
+ from PROC. */
+
+void
+unloaded_dll (process_info *proc, const char *name, CORE_ADDR base_addr)
+{
+ unload_dll_if (proc, [&] (const dll_info &dll)
+ {
+ if (dll.location != dll_info::on_disk)
+ return false;
+
+ if (base_addr != UNSPECIFIED_CORE_ADDR
+ && base_addr == dll.base_addr)
+ return true;
+
+ if (name != NULL && dll.name == name)
+ return true;
+
+ return false;
+ });
+}
+
+/* Record that the in-memory DLL from BEGIN to END loaded at BASE_ADDR has been
+ unloaded. */
+
+void
+unloaded_dll (process_info *proc, CORE_ADDR begin, CORE_ADDR end,
+ CORE_ADDR base_addr)
+{
+ unload_dll_if (proc, [&] (const dll_info &dll)
+ {
+ if (dll.location != dll_info::in_memory)
+ return false;
+
+ if (base_addr != UNSPECIFIED_CORE_ADDR
+ && base_addr == dll.base_addr)
+ return true;
+
+ /* We do not require the end address to be specified - we don't
+ support partially unloaded libraries, anyway. */
+ if ((begin == dll.begin)
+ && (end == UNSPECIFIED_CORE_ADDR
+ || end == dll.end))
+ return true;
+
+ return false;
+ });
+}
diff --git a/gdbserver/dll.h b/gdbserver/dll.h
index b5d9c3957f0ab6851083aee342f90b74b4dd10d9..a3af86dd6122ff8b8c47a335890f54a906f6d5be 100644
--- a/gdbserver/dll.h
+++ b/gdbserver/dll.h
@@ -18,25 +18,57 @@
#ifndef GDBSERVER_DLL_H
#define GDBSERVER_DLL_H
+#include "gdbsupport/gdb_unlinker.h"
#include <list>
struct process_info;
struct dll_info
{
+ enum location_t
+ {
+ on_disk,
+ in_memory
+ };
+
dll_info (const std::string &name_, CORE_ADDR base_addr_)
- : name (name_), base_addr (base_addr_)
+ : location (on_disk), name (name_), base_addr (base_addr_)
+ {}
+
+ dll_info (CORE_ADDR begin_, CORE_ADDR end_, CORE_ADDR base_addr_)
+ : location (in_memory), begin (begin_), end (end_), base_addr (base_addr_)
{}
+ /* Where the library bits are stored. */
+ location_t location;
+
+ /* The name of a file on disk containing the library.
+
+ This is only valid if LOCATION == ON_DISK. */
std::string name;
+
+ /* An optional unlinker in case this is a temporary file. */
+ std::optional<gdb::unlinker> unlinker;
+
+ /* The address range in memory containing the library.
+
+ This is only valid if LOCATION == IN_MEMORY. */
+ CORE_ADDR begin;
+ CORE_ADDR end;
+
+ /* The base address at which the library is loaded. */
CORE_ADDR base_addr;
};
extern void loaded_dll (const char *name, CORE_ADDR base_addr);
extern void loaded_dll (process_info *proc, const char *name,
CORE_ADDR base_addr);
+extern void loaded_dll (process_info *proc, CORE_ADDR begin, CORE_ADDR end,
+ CORE_ADDR base_addr);
extern void unloaded_dll (const char *name, CORE_ADDR base_addr);
extern void unloaded_dll (process_info *proc, const char *name,
CORE_ADDR base_addr);
+extern void unloaded_dll (process_info *proc, CORE_ADDR begin, CORE_ADDR end,
+ CORE_ADDR base_addr);
#endif /* GDBSERVER_DLL_H */
diff --git a/gdbserver/server.cc b/gdbserver/server.cc
index ce84c7f75d98999117752465fd129226b0f443e9..aa695f2f2f80686ea6dc2ae3ae1bfd7c081067bf 100644
--- a/gdbserver/server.cc
+++ b/gdbserver/server.cc
@@ -1885,6 +1885,128 @@ handle_qxfer_features (const char *annex,
return len;
}
+/* Turn an in-memory library DLL into an on-disk library using a temporary
+ file. */
+
+static void
+dll_to_tmpfile (dll_info &dll)
+{
+ gdb_assert (dll.location == dll_info::in_memory);
+
+ if (dll.end <= dll.begin)
+ error (_("bad in-memory-library location: begin=%s, end=%s"),
+ core_addr_to_string_nz (dll.begin),
+ core_addr_to_string_nz (dll.end));
+
+ std::vector<unsigned char> buffer (dll.end - dll.begin);
+ int errcode = gdb_read_memory (dll.begin, buffer.data (), buffer.size ());
+ if (errcode != buffer.size ())
+ error (_("failed to read in-memory library at %s..%s"),
+ core_addr_to_string_nz (dll.begin),
+ core_addr_to_string_nz (dll.end));
+
+ std::string name = get_standard_temp_dir ()
+ + "/gdb-in-memory-"
+ + core_addr_to_string_nz (dll.begin)
+ + "-"
+ + core_addr_to_string_nz (dll.end);
+
+ gdb::char_vector tmpname = make_temp_filename (name);
+
+ scoped_fd fd { gdb_mkostemp_cloexec (tmpname.data (), O_BINARY) };
+ if (fd.get () == -1)
+ error (_("failed to create temporary file %s: %s"), tmpname.data (),
+ safe_strerror (errno));
+
+ gdb::unlinker unlinker (tmpname.data ());
+ size_t size = buffer.size ();
+ unsigned char *head = buffer.data ();
+ do
+ {
+ ssize_t written = write (fd.get (), head, size);
+ if (written <= 0)
+ error (_("failed to write into %s"), name.c_str ());
+
+ head += written;
+ size -= written;
+ }
+ while (size > 0);
+
+ dll.location = dll_info::on_disk;
+ dll.name = tmpname.data ();
+ dll.unlinker.emplace (dll.name.c_str ());
+
+ unlinker.keep ();
+}
+
+/* Print a qXfer:libraries:read entry for DLL. */
+
+static std::string
+print_qxfer_libraries_entry (dll_info &dll)
+{
+ switch (dll.location)
+ {
+ case dll_info::in_memory:
+ if (get_client_state ().in_memory_library_supported)
+ return string_printf
+ (" <in-memory-library begin=\"0x%s\" end=\"0x%s\">"
+ "<segment address=\"0x%s\"/></in-memory-library>\n",
+ paddress (dll.begin), paddress (dll.end),
+ paddress (dll.base_addr));
+
+ /* GDB does not support in-memory-library. Fall back to storing it in a
+ temporary file and report that file to GDB. */
+ try
+ {
+ dll_to_tmpfile (dll);
+ }
+ catch (const gdb_exception &ex)
+ {
+ warning ("%s", ex.what ());
+ return std::string ();
+ }
+
+ [[fallthrough]];
+ case dll_info::on_disk:
+ return string_printf
+ (" <library name=\"%s\"><segment address=\"0x%s\"/></library>\n",
+ dll.name.c_str (), paddress (dll.base_addr));
+ }
+
+ gdb_assert_not_reached ("unknown dll location: %x", dll.location);
+}
+
+/* Determine the library-list version required for communicating the shared
+ libraries. */
+
+static std::string
+library_list_version_needed (const std::list<dll_info> &dlls)
+{
+ const client_state &cs = get_client_state ();
+ int major = 1, minor = 0;
+
+ for (const dll_info &dll : dlls)
+ {
+ switch (dll.location)
+ {
+ case dll_info::on_disk:
+ major = std::max (major, 1);
+ minor = std::max (minor, 0);
+ break;
+
+ case dll_info::in_memory:
+ if (cs.in_memory_library_supported)
+ {
+ major = std::max (major, 1);
+ minor = std::max (minor, 1);
+ }
+ break;
+ }
+ }
+
+ return std::to_string (major) + std::string (".") + std::to_string (minor);
+}
+
/* Handle qXfer:libraries:read. */
static int
@@ -1898,13 +2020,13 @@ handle_qxfer_libraries (const char *annex,
if (annex[0] != '\0' || current_thread == NULL)
return -1;
- std::string document = "<library-list version=\"1.0\">\n";
-
process_info *proc = current_process ();
- for (const dll_info &dll : proc->all_dlls)
- document += string_printf
- (" <library name=\"%s\"><segment address=\"0x%s\"/></library>\n",
- dll.name.c_str (), paddress (dll.base_addr));
+ std::string document = "<library-list version=\""
+ + library_list_version_needed (proc->all_dlls)
+ + "\">\n";
+
+ for (dll_info &dll : proc->all_dlls)
+ document += print_qxfer_libraries_entry (dll);
document += "</library-list>\n";
@@ -2742,6 +2864,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
}
else if (feature == "error-message+")
cs.error_message_supported = true;
+ else if (feature == "qXfer:libraries:read:in-memory-library+")
+ cs.in_memory_library_supported = true;
else
{
/* Move the unknown features all together. */
@@ -2772,6 +2896,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
/* We do not have any hook to indicate whether the non-SVR4 target
backend supports qXfer:libraries:read, so always report it. */
strcat (own_buf, ";qXfer:libraries:read+");
+ strcat (own_buf, ";qXfer:libraries:read:in-memory-library+");
}
if (the_target->supports_read_auxv ())
diff --git a/gdbserver/server.h b/gdbserver/server.h
index 5609584f716488fca599a8d30dfa0f11b50042c8..ebb5980f70dd778abfaade1086b4b89a529b4298 100644
--- a/gdbserver/server.h
+++ b/gdbserver/server.h
@@ -196,6 +196,9 @@ struct client_state
are not supported with qRcmd and m packets, but are still supported
everywhere else. This is for backward compatibility reasons. */
bool error_message_supported = false;
+
+ /* True if qXfer:libraries:read supports in-memory-library. */
+ bool in_memory_library_supported = false;
};
client_state &get_client_state ();
--
2.34.1
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
next prev parent reply other threads:[~2025-08-01 9:48 UTC|newest]
Thread overview: 92+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-01 9:37 [PATCH v3 00/44] A new target to debug Intel GPUs Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 01/44] gdb, intelgt: add intelgt as a basic machine Tankut Baris Aktemur
2025-12-09 20:44 ` Simon Marchi
2025-12-19 11:13 ` Aktemur, Tankut Baris
2025-08-01 9:37 ` [PATCH v3 02/44] bfd: add intelgt target to BFD Tankut Baris Aktemur
2025-08-01 12:20 ` Jan Beulich
2025-08-08 5:03 ` Metzger, Markus T
2025-12-09 21:05 ` Simon Marchi
2025-12-19 12:46 ` Aktemur, Tankut Baris
2025-08-01 9:37 ` [PATCH v3 03/44] ld: add intelgt as a target configuration Tankut Baris Aktemur
2025-08-01 12:06 ` Jan Beulich
2025-08-08 5:03 ` Metzger, Markus T
2025-08-01 9:37 ` [PATCH v3 04/44] opcodes: add intelgt as a configuration Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 05/44] gdb, gdbserver, gdbsupport: add 'device' tag to XML target description Tankut Baris Aktemur
2025-12-09 21:27 ` Simon Marchi
2025-12-15 21:03 ` Simon Marchi
2025-12-18 15:04 ` Aktemur, Tankut Baris
2026-01-09 19:12 ` Aktemur, Tankut Baris
2026-01-09 19:34 ` Simon Marchi
2025-08-01 9:37 ` [PATCH v3 06/44] gdb, arch, intelgt: add intelgt arch definitions Tankut Baris Aktemur
2025-12-09 21:48 ` Simon Marchi
2025-12-16 15:47 ` Metzger, Markus T
2025-08-01 9:37 ` [PATCH v3 07/44] gdb, intelgt: add the target-dependent definitions for the Intel GT architecture Tankut Baris Aktemur
2025-12-11 18:53 ` Simon Marchi
2025-12-19 16:01 ` Aktemur, Tankut Baris
2025-08-01 9:37 ` [PATCH v3 08/44] gdb, intelgt: add disassemble feature " Tankut Baris Aktemur
2025-12-11 19:37 ` Simon Marchi
2025-12-23 11:03 ` Aktemur, Tankut Baris
2025-08-01 9:37 ` Tankut Baris Aktemur [this message]
2025-12-12 4:13 ` [PATCH v3 09/44] gdb, gdbserver, ze: in-memory libraries Simon Marchi
2025-12-12 11:20 ` Metzger, Markus T
2025-12-12 19:34 ` Simon Marchi
2025-12-15 13:07 ` Metzger, Markus T
2025-12-15 21:25 ` Simon Marchi
2025-08-01 9:37 ` [PATCH v3 10/44] gdb, gdbserver, rsp, ze: acknowledge libraries Tankut Baris Aktemur
2025-12-12 4:41 ` Simon Marchi
2025-12-12 14:28 ` Metzger, Markus T
2025-08-01 9:37 ` [PATCH v3 11/44] gdb, solib, ze: update target_solib_ops::bfd_open_from_target_memory Tankut Baris Aktemur
2025-12-12 4:43 ` Simon Marchi
2025-12-12 14:33 ` Metzger, Markus T
2025-08-01 9:37 ` [PATCH v3 12/44] gdb, infrun, ze: allow saving process events Tankut Baris Aktemur
2025-12-12 4:57 ` Simon Marchi
2025-12-15 13:13 ` Metzger, Markus T
2025-12-16 21:10 ` Simon Marchi
2025-12-17 9:30 ` Metzger, Markus T
2025-12-17 20:44 ` Simon Marchi
2025-12-18 7:20 ` Metzger, Markus T
2025-08-01 9:37 ` [PATCH v3 13/44] gdb, ze: add TARGET_WAITKIND_UNAVAILABLE Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 14/44] gdb, infrun, ze: handle stopping unavailable threads Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 15/44] gdb, infrun, ze: allow resuming " Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 16/44] gdb, gdbserver, ze: add U stop reply Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 17/44] gdb, gdbserver, ze: add library notification to " Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 18/44] gdbserver, ze: report TARGET_WAITKIND_UNAVAILABLE events Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 19/44] gdb, ze: handle TARGET_WAITKIND_UNAVAILABLE in stop_all_threads Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 20/44] gdb, remote: handle thread unavailability in print_one_stopped_thread Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 21/44] gdb, remote: do 'remote_add_inferior' in 'remote_notice_new_inferior' earlier Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 22/44] gdb, remote: handle a generic process PID in remote_notice_new_inferior Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 23/44] gdb, remote: handle a generic process PID in process_stop_reply Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 24/44] gdb: use the pid from inferior in setup_inferior Tankut Baris Aktemur
2025-12-12 19:51 ` Simon Marchi
2025-12-13 12:40 ` Aktemur, Tankut Baris
2025-08-01 9:37 ` [PATCH v3 25/44] gdb: revise the pid_to_exec_file target op Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 26/44] gdb: load solibs if the target does not have the notion of an exec file Tankut Baris Aktemur
2025-12-12 20:30 ` Simon Marchi
2026-01-09 19:10 ` Aktemur, Tankut Baris
2025-08-01 9:37 ` [PATCH v3 27/44] gdbserver: import AC_LIB_HAVE_LINKFLAGS macro into the autoconf script Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 28/44] gdbserver: add a pointer to the owner thread in regcache Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 29/44] gdbserver: wait for stopped threads in queue_stop_reply_callback Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 30/44] gdbserver: adjust pid after the target attaches Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 31/44] gdb: do not create a thread after a process event Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 32/44] gdb, ze: on a whole process stop, mark all threads as not_resumed Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 33/44] gdb, dwarf, ze: add DW_OP_INTEL_regval_bits Tankut Baris Aktemur
2025-08-01 12:02 ` Jan Beulich
2025-08-01 12:31 ` Metzger, Markus T
2025-08-01 12:50 ` Jan Beulich
2025-08-08 5:25 ` Metzger, Markus T
2025-08-01 9:37 ` [PATCH v3 34/44] gdbserver: allow configuring for a heterogeneous target Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 35/44] gdbserver, ze, intelgt: introduce ze-low and intel-ze-low targets Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 36/44] testsuite, sycl: add SYCL support Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 37/44] testsuite, sycl: add test for backtracing inside a kernel Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 38/44] testsuite, sycl: add test for 'info locals' and 'info args' Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 39/44] testsuite, sycl: add tests for stepping and accessing data elements Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 40/44] testsuite, sycl: add test for 1-D and 2-D parallel_for kernels Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 41/44] testsuite, sycl: add test for scheduler-locking Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 42/44] testsuite, arch, intelgt: add a disassembly test Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 43/44] testsuite, arch, intelgt: add intelgt-program-bp.exp Tankut Baris Aktemur
2025-08-01 9:37 ` [PATCH v3 44/44] testsuite, sycl: test canceling a stepping flow Tankut Baris Aktemur
2025-09-17 12:43 ` [PATCH v3 00/44] A new target to debug Intel GPUs Aktemur, Tankut Baris
2025-10-14 6:34 ` Aktemur, Tankut Baris
2025-12-08 11:32 ` Aktemur, Tankut Baris
2025-12-09 21:30 ` Simon Marchi
2025-12-19 12:52 ` Aktemur, Tankut Baris
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250801-upstream-intelgt-mvp-v3-9-59ce0f87075b@intel.com \
--to=tankut.baris.aktemur@intel.com \
--cc=gdb-patches@sourceware.org \
--cc=markus.t.metzger@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox