mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-16 04:18:50 +00:00
Implement -list-thread-groups --available
* Makefile.in (XMLFILES): Add osdata.dtd.
(SFILES): Add osdata.c.
(COMMON_OBS): Add osdata.o.
* linux-nat.c: Include pwd.h, sys/types.h, gdb_dirent.h and xml-support.h.
(linux_nat_xfer_osdata): New function.
(linux_xfer_partial): Handle TARGET_OBJECT_OSDATA.
* osdata.c: New file.
* osdata.h: New file.
* remote.c (PACKET_qXfer_osdata): New packet enum.
(remote_protocol_features): Add "qXfer:osdata:read".
(remote_read_qxfer): Handle TARGET_OBJECT_OSDATA.
(extended_remote_can_run): New.
(init_extended_remote_ops): Set to_can_run to
extended_remote_can_run.
(_initialize_remote): Add packet config command for
"qXfer:osdata:read".
* xml-support.c (obstack_xml_printf): New function.
* xml-support.h (obstack_xml_printf): Declare.
* target.c (target_get_osdata): New function.
* target.h (enum target_object): Add TARGET_OBJECT_OSDATA.
(target_os_data): Declare.
* features/osdata.dtd: New file.
* mi/mi-main.c (mi_list_thread_groups): Handle the --available
option.
This commit is contained in:
115
gdb/linux-nat.c
115
gdb/linux-nat.c
@@ -49,6 +49,10 @@
|
||||
#include "inf-loop.h"
|
||||
#include "event-loop.h"
|
||||
#include "event-top.h"
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include "gdb_dirent.h"
|
||||
#include "xml-support.h"
|
||||
|
||||
#ifdef HAVE_PERSONALITY
|
||||
# include <sys/personality.h>
|
||||
@@ -3994,6 +3998,113 @@ linux_proc_pending_signals (int pid, sigset_t *pending, sigset_t *blocked, sigse
|
||||
do_cleanups (cleanup);
|
||||
}
|
||||
|
||||
static LONGEST
|
||||
linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
|
||||
const char *annex, gdb_byte *readbuf,
|
||||
const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
|
||||
{
|
||||
/* We make the process list snapshot when the object starts to be
|
||||
read. */
|
||||
static const char *buf;
|
||||
static LONGEST len_avail = -1;
|
||||
static struct obstack obstack;
|
||||
|
||||
DIR *dirp;
|
||||
|
||||
gdb_assert (object == TARGET_OBJECT_OSDATA);
|
||||
|
||||
if (strcmp (annex, "processes") != 0)
|
||||
return 0;
|
||||
|
||||
gdb_assert (readbuf && !writebuf);
|
||||
|
||||
if (offset == 0)
|
||||
{
|
||||
if (len_avail != -1 && len_avail != 0)
|
||||
obstack_free (&obstack, NULL);
|
||||
len_avail = 0;
|
||||
buf = NULL;
|
||||
obstack_init (&obstack);
|
||||
obstack_grow_str (&obstack, "<osdata type=\"processes\">\n");
|
||||
|
||||
dirp = opendir ("/proc");
|
||||
if (dirp)
|
||||
{
|
||||
struct dirent *dp;
|
||||
while ((dp = readdir (dirp)) != NULL)
|
||||
{
|
||||
struct stat statbuf;
|
||||
char procentry[sizeof ("/proc/4294967295")];
|
||||
|
||||
if (!isdigit (dp->d_name[0])
|
||||
|| strlen (dp->d_name) > sizeof ("4294967295") - 1)
|
||||
continue;
|
||||
|
||||
sprintf (procentry, "/proc/%s", dp->d_name);
|
||||
if (stat (procentry, &statbuf) == 0
|
||||
&& S_ISDIR (statbuf.st_mode))
|
||||
{
|
||||
char *pathname;
|
||||
FILE *f;
|
||||
char cmd[MAXPATHLEN + 1];
|
||||
struct passwd *entry;
|
||||
|
||||
pathname = xstrprintf ("/proc/%s/cmdline", dp->d_name);
|
||||
entry = getpwuid (statbuf.st_uid);
|
||||
|
||||
if ((f = fopen (pathname, "r")) != NULL)
|
||||
{
|
||||
size_t len = fread (cmd, 1, sizeof (cmd) - 1, f);
|
||||
if (len > 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++)
|
||||
if (cmd[i] == '\0')
|
||||
cmd[i] = ' ';
|
||||
cmd[len] = '\0';
|
||||
|
||||
obstack_xml_printf (
|
||||
&obstack,
|
||||
"<item>"
|
||||
"<column name=\"pid\">%s</column>"
|
||||
"<column name=\"user\">%s</column>"
|
||||
"<column name=\"command\">%s</column>"
|
||||
"</item>",
|
||||
dp->d_name,
|
||||
entry ? entry->pw_name : "?",
|
||||
cmd);
|
||||
}
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
xfree (pathname);
|
||||
}
|
||||
}
|
||||
|
||||
closedir (dirp);
|
||||
}
|
||||
|
||||
obstack_grow_str0 (&obstack, "</osdata>\n");
|
||||
buf = obstack_finish (&obstack);
|
||||
len_avail = strlen (buf);
|
||||
}
|
||||
|
||||
if (offset >= len_avail)
|
||||
{
|
||||
/* Done. Get rid of the obstack. */
|
||||
obstack_free (&obstack, NULL);
|
||||
buf = NULL;
|
||||
len_avail = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len > len_avail - offset)
|
||||
len = len_avail - offset;
|
||||
memcpy (readbuf, buf + offset, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static LONGEST
|
||||
linux_xfer_partial (struct target_ops *ops, enum target_object object,
|
||||
const char *annex, gdb_byte *readbuf,
|
||||
@@ -4005,6 +4116,10 @@ linux_xfer_partial (struct target_ops *ops, enum target_object object,
|
||||
return procfs_xfer_auxv (ops, object, annex, readbuf, writebuf,
|
||||
offset, len);
|
||||
|
||||
if (object == TARGET_OBJECT_OSDATA)
|
||||
return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf,
|
||||
offset, len);
|
||||
|
||||
xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf,
|
||||
offset, len);
|
||||
if (xfer != 0)
|
||||
|
||||
Reference in New Issue
Block a user