diff options
author | Vladimir Prus <vladimir@codesourcery.com> | 2008-12-02 07:57:38 +0000 |
---|---|---|
committer | Vladimir Prus <vladimir@codesourcery.com> | 2008-12-02 07:57:38 +0000 |
commit | 07e059b5a9cbdeab8bf2980e07e79f892a2da854 (patch) | |
tree | 065ba2dfb548976f2d0691a8753a54d03148c1d5 /gdb/linux-nat.c | |
parent | f3c85de60aa06c1f075332c95fb2c32de79d50d3 (diff) | |
download | gdb-07e059b5a9cbdeab8bf2980e07e79f892a2da854.zip gdb-07e059b5a9cbdeab8bf2980e07e79f892a2da854.tar.gz gdb-07e059b5a9cbdeab8bf2980e07e79f892a2da854.tar.bz2 |
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.
Diffstat (limited to 'gdb/linux-nat.c')
-rw-r--r-- | gdb/linux-nat.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 913bfec..e537c6f 100644 --- a/gdb/linux-nat.c +++ b/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> @@ -3995,6 +3999,113 @@ linux_proc_pending_signals (int pid, sigset_t *pending, sigset_t *blocked, sigse } 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, const gdb_byte *writebuf, ULONGEST offset, LONGEST len) @@ -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) |