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:
parent
f3c85de60a
commit
07e059b5a9
22 changed files with 1093 additions and 7 deletions
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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue