xref: /dflybsd-src/contrib/gdb-7/gdb/common/linux-osdata.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
1a45ae5f8SJohn Marino /* Linux-specific functions to retrieve OS data.
2a45ae5f8SJohn Marino 
3*ef5ccd6cSJohn Marino    Copyright (C) 2009-2013 Free Software Foundation, Inc.
4a45ae5f8SJohn Marino 
5a45ae5f8SJohn Marino    This file is part of GDB.
6a45ae5f8SJohn Marino 
7a45ae5f8SJohn Marino    This program is free software; you can redistribute it and/or modify
8a45ae5f8SJohn Marino    it under the terms of the GNU General Public License as published by
9a45ae5f8SJohn Marino    the Free Software Foundation; either version 3 of the License, or
10a45ae5f8SJohn Marino    (at your option) any later version.
11a45ae5f8SJohn Marino 
12a45ae5f8SJohn Marino    This program is distributed in the hope that it will be useful,
13a45ae5f8SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
14a45ae5f8SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15a45ae5f8SJohn Marino    GNU General Public License for more details.
16a45ae5f8SJohn Marino 
17a45ae5f8SJohn Marino    You should have received a copy of the GNU General Public License
18a45ae5f8SJohn Marino    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19a45ae5f8SJohn Marino 
20a45ae5f8SJohn Marino #ifdef GDBSERVER
21a45ae5f8SJohn Marino #include "server.h"
22a45ae5f8SJohn Marino #else
23a45ae5f8SJohn Marino #include "defs.h"
24a45ae5f8SJohn Marino #endif
25a45ae5f8SJohn Marino 
26a45ae5f8SJohn Marino #include "linux-osdata.h"
27a45ae5f8SJohn Marino 
28a45ae5f8SJohn Marino #include <sys/types.h>
29*ef5ccd6cSJohn Marino #include <sys/sysinfo.h>
30a45ae5f8SJohn Marino #include <ctype.h>
31a45ae5f8SJohn Marino #include <stdlib.h>
32a45ae5f8SJohn Marino #include <string.h>
33a45ae5f8SJohn Marino #include <utmp.h>
34a45ae5f8SJohn Marino #include <time.h>
35a45ae5f8SJohn Marino #include <unistd.h>
36a45ae5f8SJohn Marino #include <pwd.h>
37a45ae5f8SJohn Marino #include <grp.h>
38a45ae5f8SJohn Marino #include <netdb.h>
39a45ae5f8SJohn Marino #include <netinet/in.h>
40a45ae5f8SJohn Marino #include <arpa/inet.h>
41a45ae5f8SJohn Marino 
42a45ae5f8SJohn Marino #include "xml-utils.h"
43a45ae5f8SJohn Marino #include "buffer.h"
44a45ae5f8SJohn Marino #include "gdb_assert.h"
45a45ae5f8SJohn Marino #include "gdb_dirent.h"
46*ef5ccd6cSJohn Marino #include "gdb_stat.h"
47*ef5ccd6cSJohn Marino 
48*ef5ccd6cSJohn Marino /* Define PID_T to be a fixed size that is at least as large as pid_t,
49*ef5ccd6cSJohn Marino    so that reading pid values embedded in /proc works
50*ef5ccd6cSJohn Marino    consistently.  */
51*ef5ccd6cSJohn Marino 
52*ef5ccd6cSJohn Marino typedef long long  PID_T;
53*ef5ccd6cSJohn Marino 
54*ef5ccd6cSJohn Marino /* Define TIME_T to be at least as large as time_t, so that reading
55*ef5ccd6cSJohn Marino    time values embedded in /proc works consistently.  */
56*ef5ccd6cSJohn Marino 
57*ef5ccd6cSJohn Marino typedef long long TIME_T;
58*ef5ccd6cSJohn Marino 
59*ef5ccd6cSJohn Marino #define MAX_PID_T_STRLEN  (sizeof ("-9223372036854775808") - 1)
60*ef5ccd6cSJohn Marino 
61*ef5ccd6cSJohn Marino /* Returns the CPU core that thread PTID is currently running on.  */
62*ef5ccd6cSJohn Marino 
63*ef5ccd6cSJohn Marino /* Compute and return the processor core of a given thread.  */
64a45ae5f8SJohn Marino 
65a45ae5f8SJohn Marino int
linux_common_core_of_thread(ptid_t ptid)66a45ae5f8SJohn Marino linux_common_core_of_thread (ptid_t ptid)
67a45ae5f8SJohn Marino {
68*ef5ccd6cSJohn Marino   char filename[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN];
69a45ae5f8SJohn Marino   FILE *f;
70a45ae5f8SJohn Marino   char *content = NULL;
71a45ae5f8SJohn Marino   char *p;
72a45ae5f8SJohn Marino   char *ts = 0;
73a45ae5f8SJohn Marino   int content_read = 0;
74a45ae5f8SJohn Marino   int i;
75a45ae5f8SJohn Marino   int core;
76a45ae5f8SJohn Marino 
77*ef5ccd6cSJohn Marino   sprintf (filename, "/proc/%lld/task/%lld/stat",
78*ef5ccd6cSJohn Marino 	   (PID_T) ptid_get_pid (ptid), (PID_T) ptid_get_lwp (ptid));
79a45ae5f8SJohn Marino   f = fopen (filename, "r");
80a45ae5f8SJohn Marino   if (!f)
81a45ae5f8SJohn Marino     return -1;
82a45ae5f8SJohn Marino 
83a45ae5f8SJohn Marino   for (;;)
84a45ae5f8SJohn Marino     {
85a45ae5f8SJohn Marino       int n;
86a45ae5f8SJohn Marino       content = xrealloc (content, content_read + 1024);
87a45ae5f8SJohn Marino       n = fread (content + content_read, 1, 1024, f);
88a45ae5f8SJohn Marino       content_read += n;
89a45ae5f8SJohn Marino       if (n < 1024)
90a45ae5f8SJohn Marino 	{
91a45ae5f8SJohn Marino 	  content[content_read] = '\0';
92a45ae5f8SJohn Marino 	  break;
93a45ae5f8SJohn Marino 	}
94a45ae5f8SJohn Marino     }
95a45ae5f8SJohn Marino 
96a45ae5f8SJohn Marino   p = strchr (content, '(');
97a45ae5f8SJohn Marino 
98a45ae5f8SJohn Marino   /* Skip ")".  */
99a45ae5f8SJohn Marino   if (p != NULL)
100a45ae5f8SJohn Marino     p = strchr (p, ')');
101a45ae5f8SJohn Marino   if (p != NULL)
102a45ae5f8SJohn Marino     p++;
103a45ae5f8SJohn Marino 
104a45ae5f8SJohn Marino   /* If the first field after program name has index 0, then core number is
105a45ae5f8SJohn Marino      the field with index 36.  There's no constant for that anywhere.  */
106a45ae5f8SJohn Marino   if (p != NULL)
107a45ae5f8SJohn Marino     p = strtok_r (p, " ", &ts);
108a45ae5f8SJohn Marino   for (i = 0; p != NULL && i != 36; ++i)
109a45ae5f8SJohn Marino     p = strtok_r (NULL, " ", &ts);
110a45ae5f8SJohn Marino 
111a45ae5f8SJohn Marino   if (p == NULL || sscanf (p, "%d", &core) == 0)
112a45ae5f8SJohn Marino     core = -1;
113a45ae5f8SJohn Marino 
114a45ae5f8SJohn Marino   xfree (content);
115a45ae5f8SJohn Marino   fclose (f);
116a45ae5f8SJohn Marino 
117a45ae5f8SJohn Marino   return core;
118a45ae5f8SJohn Marino }
119a45ae5f8SJohn Marino 
120*ef5ccd6cSJohn Marino /* Finds the command-line of process PID and copies it into COMMAND.
121*ef5ccd6cSJohn Marino    At most MAXLEN characters are copied.  If the command-line cannot
122*ef5ccd6cSJohn Marino    be found, PID is copied into command in text-form.  */
123*ef5ccd6cSJohn Marino 
124a45ae5f8SJohn Marino static void
command_from_pid(char * command,int maxlen,PID_T pid)125*ef5ccd6cSJohn Marino command_from_pid (char *command, int maxlen, PID_T pid)
126a45ae5f8SJohn Marino {
127*ef5ccd6cSJohn Marino   char *stat_path = xstrprintf ("/proc/%lld/stat", pid);
128a45ae5f8SJohn Marino   FILE *fp = fopen (stat_path, "r");
129a45ae5f8SJohn Marino 
130a45ae5f8SJohn Marino   command[0] = '\0';
131a45ae5f8SJohn Marino 
132a45ae5f8SJohn Marino   if (fp)
133a45ae5f8SJohn Marino     {
134a45ae5f8SJohn Marino       /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
135a45ae5f8SJohn Marino 	 include/linux/sched.h in the Linux kernel sources) plus two
136a45ae5f8SJohn Marino 	 (for the brackets).  */
137a45ae5f8SJohn Marino       char cmd[32];
138*ef5ccd6cSJohn Marino       PID_T stat_pid;
139*ef5ccd6cSJohn Marino       int items_read = fscanf (fp, "%lld %32s", &stat_pid, cmd);
140a45ae5f8SJohn Marino 
141a45ae5f8SJohn Marino       if (items_read == 2 && pid == stat_pid)
142a45ae5f8SJohn Marino 	{
143a45ae5f8SJohn Marino 	  cmd[strlen (cmd) - 1] = '\0'; /* Remove trailing parenthesis.  */
144a45ae5f8SJohn Marino 	  strncpy (command, cmd + 1, maxlen); /* Ignore leading parenthesis.  */
145a45ae5f8SJohn Marino 	}
146a45ae5f8SJohn Marino 
147a45ae5f8SJohn Marino       fclose (fp);
148a45ae5f8SJohn Marino     }
149a45ae5f8SJohn Marino   else
150a45ae5f8SJohn Marino     {
151a45ae5f8SJohn Marino       /* Return the PID if a /proc entry for the process cannot be found.  */
152*ef5ccd6cSJohn Marino       snprintf (command, maxlen, "%lld", pid);
153a45ae5f8SJohn Marino     }
154a45ae5f8SJohn Marino 
155a45ae5f8SJohn Marino   command[maxlen - 1] = '\0'; /* Ensure string is null-terminated.  */
156a45ae5f8SJohn Marino 
157a45ae5f8SJohn Marino   xfree (stat_path);
158a45ae5f8SJohn Marino }
159a45ae5f8SJohn Marino 
160*ef5ccd6cSJohn Marino /* Returns the command-line of the process with the given PID. The
161*ef5ccd6cSJohn Marino    returned string needs to be freed using xfree after use.  */
162a45ae5f8SJohn Marino 
163a45ae5f8SJohn Marino static char *
commandline_from_pid(PID_T pid)164*ef5ccd6cSJohn Marino commandline_from_pid (PID_T pid)
165a45ae5f8SJohn Marino {
166*ef5ccd6cSJohn Marino   char *pathname = xstrprintf ("/proc/%lld/cmdline", pid);
167a45ae5f8SJohn Marino   char *commandline = NULL;
168a45ae5f8SJohn Marino   FILE *f = fopen (pathname, "r");
169a45ae5f8SJohn Marino 
170a45ae5f8SJohn Marino   if (f)
171a45ae5f8SJohn Marino     {
172a45ae5f8SJohn Marino       size_t len = 0;
173a45ae5f8SJohn Marino 
174a45ae5f8SJohn Marino       while (!feof (f))
175a45ae5f8SJohn Marino 	{
176a45ae5f8SJohn Marino 	  char buf[1024];
177a45ae5f8SJohn Marino 	  size_t read_bytes = fread (buf, 1, sizeof (buf), f);
178a45ae5f8SJohn Marino 
179a45ae5f8SJohn Marino 	  if (read_bytes)
180a45ae5f8SJohn Marino 	    {
181a45ae5f8SJohn Marino 	      commandline = (char *) xrealloc (commandline, len + read_bytes + 1);
182a45ae5f8SJohn Marino 	      memcpy (commandline + len, buf, read_bytes);
183a45ae5f8SJohn Marino 	      len += read_bytes;
184a45ae5f8SJohn Marino 	    }
185a45ae5f8SJohn Marino 	}
186a45ae5f8SJohn Marino 
187a45ae5f8SJohn Marino       fclose (f);
188a45ae5f8SJohn Marino 
189a45ae5f8SJohn Marino       if (commandline)
190a45ae5f8SJohn Marino 	{
191a45ae5f8SJohn Marino 	  size_t i;
192a45ae5f8SJohn Marino 
193a45ae5f8SJohn Marino 	  /* Replace null characters with spaces.  */
194a45ae5f8SJohn Marino 	  for (i = 0; i < len; ++i)
195a45ae5f8SJohn Marino 	    if (commandline[i] == '\0')
196a45ae5f8SJohn Marino 	      commandline[i] = ' ';
197a45ae5f8SJohn Marino 
198a45ae5f8SJohn Marino 	  commandline[len] = '\0';
199a45ae5f8SJohn Marino 	}
200a45ae5f8SJohn Marino       else
201a45ae5f8SJohn Marino 	{
202*ef5ccd6cSJohn Marino 	  /* Return the command in square brackets if the command-line
203*ef5ccd6cSJohn Marino 	     is empty.  */
204a45ae5f8SJohn Marino 	  commandline = (char *) xmalloc (32);
205a45ae5f8SJohn Marino 	  commandline[0] = '[';
206a45ae5f8SJohn Marino 	  command_from_pid (commandline + 1, 31, pid);
207a45ae5f8SJohn Marino 
208a45ae5f8SJohn Marino 	  len = strlen (commandline);
209a45ae5f8SJohn Marino 	  if (len < 31)
210a45ae5f8SJohn Marino 	    strcat (commandline, "]");
211a45ae5f8SJohn Marino 	}
212a45ae5f8SJohn Marino     }
213a45ae5f8SJohn Marino 
214a45ae5f8SJohn Marino   xfree (pathname);
215a45ae5f8SJohn Marino 
216a45ae5f8SJohn Marino   return commandline;
217a45ae5f8SJohn Marino }
218a45ae5f8SJohn Marino 
219*ef5ccd6cSJohn Marino /* Finds the user name for the user UID and copies it into USER.  At
220*ef5ccd6cSJohn Marino    most MAXLEN characters are copied.  */
221*ef5ccd6cSJohn Marino 
222a45ae5f8SJohn Marino static void
user_from_uid(char * user,int maxlen,uid_t uid)223a45ae5f8SJohn Marino user_from_uid (char *user, int maxlen, uid_t uid)
224a45ae5f8SJohn Marino {
225a45ae5f8SJohn Marino   struct passwd *pwentry = getpwuid (uid);
226a45ae5f8SJohn Marino 
227a45ae5f8SJohn Marino   if (pwentry)
228a45ae5f8SJohn Marino     {
229a45ae5f8SJohn Marino       strncpy (user, pwentry->pw_name, maxlen);
230*ef5ccd6cSJohn Marino       /* Ensure that the user name is null-terminated.  */
231*ef5ccd6cSJohn Marino       user[maxlen - 1] = '\0';
232a45ae5f8SJohn Marino     }
233a45ae5f8SJohn Marino   else
234a45ae5f8SJohn Marino     user[0] = '\0';
235a45ae5f8SJohn Marino }
236a45ae5f8SJohn Marino 
237*ef5ccd6cSJohn Marino /* Finds the owner of process PID and returns the user id in OWNER.
238*ef5ccd6cSJohn Marino    Returns 0 if the owner was found, -1 otherwise.  */
239*ef5ccd6cSJohn Marino 
240a45ae5f8SJohn Marino static int
get_process_owner(uid_t * owner,PID_T pid)241*ef5ccd6cSJohn Marino get_process_owner (uid_t *owner, PID_T pid)
242a45ae5f8SJohn Marino {
243a45ae5f8SJohn Marino   struct stat statbuf;
244*ef5ccd6cSJohn Marino   char procentry[sizeof ("/proc/") + MAX_PID_T_STRLEN];
245a45ae5f8SJohn Marino 
246*ef5ccd6cSJohn Marino   sprintf (procentry, "/proc/%lld", pid);
247a45ae5f8SJohn Marino 
248a45ae5f8SJohn Marino   if (stat (procentry, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))
249a45ae5f8SJohn Marino     {
250a45ae5f8SJohn Marino       *owner = statbuf.st_uid;
251a45ae5f8SJohn Marino       return 0;
252a45ae5f8SJohn Marino     }
253a45ae5f8SJohn Marino   else
254a45ae5f8SJohn Marino     return -1;
255a45ae5f8SJohn Marino }
256a45ae5f8SJohn Marino 
257*ef5ccd6cSJohn Marino /* Find the CPU cores used by process PID and return them in CORES.
258*ef5ccd6cSJohn Marino    CORES points to an array of at least sysconf(_SC_NPROCESSOR_ONLN)
259*ef5ccd6cSJohn Marino    elements.  */
260a45ae5f8SJohn Marino 
261a45ae5f8SJohn Marino static int
get_cores_used_by_process(PID_T pid,int * cores)262*ef5ccd6cSJohn Marino get_cores_used_by_process (PID_T pid, int *cores)
263a45ae5f8SJohn Marino {
264*ef5ccd6cSJohn Marino   char taskdir[sizeof ("/proc/") + MAX_PID_T_STRLEN + sizeof ("/task") - 1];
265a45ae5f8SJohn Marino   DIR *dir;
266a45ae5f8SJohn Marino   struct dirent *dp;
267a45ae5f8SJohn Marino   int task_count = 0;
268a45ae5f8SJohn Marino 
269*ef5ccd6cSJohn Marino   sprintf (taskdir, "/proc/%lld/task", pid);
270a45ae5f8SJohn Marino   dir = opendir (taskdir);
271a45ae5f8SJohn Marino   if (dir)
272a45ae5f8SJohn Marino     {
273a45ae5f8SJohn Marino       while ((dp = readdir (dir)) != NULL)
274a45ae5f8SJohn Marino 	{
275*ef5ccd6cSJohn Marino 	  PID_T tid;
276a45ae5f8SJohn Marino 	  int core;
277a45ae5f8SJohn Marino 
278a45ae5f8SJohn Marino 	  if (!isdigit (dp->d_name[0])
279*ef5ccd6cSJohn Marino 	      || NAMELEN (dp) > MAX_PID_T_STRLEN)
280a45ae5f8SJohn Marino 	    continue;
281a45ae5f8SJohn Marino 
282*ef5ccd6cSJohn Marino 	  sscanf (dp->d_name, "%lld", &tid);
283*ef5ccd6cSJohn Marino 	  core = linux_common_core_of_thread (ptid_build ((pid_t) pid,
284*ef5ccd6cSJohn Marino 							  (pid_t) tid, 0));
285a45ae5f8SJohn Marino 
286a45ae5f8SJohn Marino 	  if (core >= 0)
287a45ae5f8SJohn Marino 	    {
288a45ae5f8SJohn Marino 	      ++cores[core];
289a45ae5f8SJohn Marino 	      ++task_count;
290a45ae5f8SJohn Marino 	    }
291a45ae5f8SJohn Marino 	}
292a45ae5f8SJohn Marino 
293a45ae5f8SJohn Marino       closedir (dir);
294a45ae5f8SJohn Marino     }
295a45ae5f8SJohn Marino 
296a45ae5f8SJohn Marino   return task_count;
297a45ae5f8SJohn Marino }
298a45ae5f8SJohn Marino 
299a45ae5f8SJohn Marino static LONGEST
linux_xfer_osdata_processes(gdb_byte * readbuf,ULONGEST offset,LONGEST len)300a45ae5f8SJohn Marino linux_xfer_osdata_processes (gdb_byte *readbuf,
301a45ae5f8SJohn Marino 			     ULONGEST offset, LONGEST len)
302a45ae5f8SJohn Marino {
303a45ae5f8SJohn Marino   /* We make the process list snapshot when the object starts to be read.  */
304a45ae5f8SJohn Marino   static const char *buf;
305a45ae5f8SJohn Marino   static LONGEST len_avail = -1;
306a45ae5f8SJohn Marino   static struct buffer buffer;
307a45ae5f8SJohn Marino 
308a45ae5f8SJohn Marino   if (offset == 0)
309a45ae5f8SJohn Marino     {
310a45ae5f8SJohn Marino       DIR *dirp;
311a45ae5f8SJohn Marino 
312a45ae5f8SJohn Marino       if (len_avail != -1 && len_avail != 0)
313a45ae5f8SJohn Marino 	buffer_free (&buffer);
314a45ae5f8SJohn Marino       len_avail = 0;
315a45ae5f8SJohn Marino       buf = NULL;
316a45ae5f8SJohn Marino       buffer_init (&buffer);
317a45ae5f8SJohn Marino       buffer_grow_str (&buffer, "<osdata type=\"processes\">\n");
318a45ae5f8SJohn Marino 
319a45ae5f8SJohn Marino       dirp = opendir ("/proc");
320a45ae5f8SJohn Marino       if (dirp)
321a45ae5f8SJohn Marino 	{
322*ef5ccd6cSJohn Marino 	  const int num_cores = sysconf (_SC_NPROCESSORS_ONLN);
323a45ae5f8SJohn Marino 	  struct dirent *dp;
324a45ae5f8SJohn Marino 
325a45ae5f8SJohn Marino 	  while ((dp = readdir (dirp)) != NULL)
326a45ae5f8SJohn Marino 	    {
327*ef5ccd6cSJohn Marino 	      PID_T pid;
328a45ae5f8SJohn Marino 	      uid_t owner;
329a45ae5f8SJohn Marino 	      char user[UT_NAMESIZE];
330a45ae5f8SJohn Marino 	      char *command_line;
331a45ae5f8SJohn Marino 	      int *cores;
332a45ae5f8SJohn Marino 	      int task_count;
333a45ae5f8SJohn Marino 	      char *cores_str;
334a45ae5f8SJohn Marino 	      int i;
335a45ae5f8SJohn Marino 
336a45ae5f8SJohn Marino 	      if (!isdigit (dp->d_name[0])
337*ef5ccd6cSJohn Marino 		  || NAMELEN (dp) > MAX_PID_T_STRLEN)
338a45ae5f8SJohn Marino 		continue;
339a45ae5f8SJohn Marino 
340*ef5ccd6cSJohn Marino 	      sscanf (dp->d_name, "%lld", &pid);
341a45ae5f8SJohn Marino 	      command_line = commandline_from_pid (pid);
342a45ae5f8SJohn Marino 
343a45ae5f8SJohn Marino 	      if (get_process_owner (&owner, pid) == 0)
344a45ae5f8SJohn Marino 		user_from_uid (user, sizeof (user), owner);
345a45ae5f8SJohn Marino 	      else
346a45ae5f8SJohn Marino 		strcpy (user, "?");
347a45ae5f8SJohn Marino 
348a45ae5f8SJohn Marino 	      /* Find CPU cores used by the process.  */
349a45ae5f8SJohn Marino 	      cores = (int *) xcalloc (num_cores, sizeof (int));
350a45ae5f8SJohn Marino 	      task_count = get_cores_used_by_process (pid, cores);
351a45ae5f8SJohn Marino 	      cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1);
352a45ae5f8SJohn Marino 
353a45ae5f8SJohn Marino 	      for (i = 0; i < num_cores && task_count > 0; ++i)
354a45ae5f8SJohn Marino 		if (cores[i])
355a45ae5f8SJohn Marino 		  {
356*ef5ccd6cSJohn Marino 		    char core_str[sizeof ("4294967295")];
357a45ae5f8SJohn Marino 
358a45ae5f8SJohn Marino 		    sprintf (core_str, "%d", i);
359a45ae5f8SJohn Marino 		    strcat (cores_str, core_str);
360a45ae5f8SJohn Marino 
361a45ae5f8SJohn Marino 		    task_count -= cores[i];
362a45ae5f8SJohn Marino 		    if (task_count > 0)
363a45ae5f8SJohn Marino 		      strcat (cores_str, ",");
364a45ae5f8SJohn Marino 		  }
365a45ae5f8SJohn Marino 
366a45ae5f8SJohn Marino 	      xfree (cores);
367a45ae5f8SJohn Marino 
368a45ae5f8SJohn Marino 	      buffer_xml_printf (
369a45ae5f8SJohn Marino 		  &buffer,
370a45ae5f8SJohn Marino 		  "<item>"
371*ef5ccd6cSJohn Marino 		  "<column name=\"pid\">%lld</column>"
372a45ae5f8SJohn Marino 		  "<column name=\"user\">%s</column>"
373a45ae5f8SJohn Marino 		  "<column name=\"command\">%s</column>"
374a45ae5f8SJohn Marino 		  "<column name=\"cores\">%s</column>"
375a45ae5f8SJohn Marino 		  "</item>",
376a45ae5f8SJohn Marino 		  pid,
377a45ae5f8SJohn Marino 		  user,
378a45ae5f8SJohn Marino 		  command_line ? command_line : "",
379a45ae5f8SJohn Marino 		  cores_str);
380a45ae5f8SJohn Marino 
381a45ae5f8SJohn Marino 	      xfree (command_line);
382a45ae5f8SJohn Marino 	      xfree (cores_str);
383a45ae5f8SJohn Marino 	    }
384a45ae5f8SJohn Marino 
385a45ae5f8SJohn Marino 	  closedir (dirp);
386a45ae5f8SJohn Marino 	}
387a45ae5f8SJohn Marino 
388a45ae5f8SJohn Marino       buffer_grow_str0 (&buffer, "</osdata>\n");
389a45ae5f8SJohn Marino       buf = buffer_finish (&buffer);
390a45ae5f8SJohn Marino       len_avail = strlen (buf);
391a45ae5f8SJohn Marino     }
392a45ae5f8SJohn Marino 
393a45ae5f8SJohn Marino   if (offset >= len_avail)
394a45ae5f8SJohn Marino     {
395a45ae5f8SJohn Marino       /* Done.  Get rid of the buffer.  */
396a45ae5f8SJohn Marino       buffer_free (&buffer);
397a45ae5f8SJohn Marino       buf = NULL;
398a45ae5f8SJohn Marino       len_avail = 0;
399a45ae5f8SJohn Marino       return 0;
400a45ae5f8SJohn Marino     }
401a45ae5f8SJohn Marino 
402a45ae5f8SJohn Marino   if (len > len_avail - offset)
403a45ae5f8SJohn Marino     len = len_avail - offset;
404a45ae5f8SJohn Marino   memcpy (readbuf, buf + offset, len);
405a45ae5f8SJohn Marino 
406a45ae5f8SJohn Marino   return len;
407a45ae5f8SJohn Marino }
408a45ae5f8SJohn Marino 
409*ef5ccd6cSJohn Marino /* Auxiliary function used by qsort to sort processes by process
410*ef5ccd6cSJohn Marino    group.  Compares two processes with ids PROCESS1 and PROCESS2.
411*ef5ccd6cSJohn Marino    PROCESS1 comes before PROCESS2 if it has a lower process group id.
412*ef5ccd6cSJohn Marino    If they belong to the same process group, PROCESS1 comes before
413*ef5ccd6cSJohn Marino    PROCESS2 if it has a lower process id or is the process group
414*ef5ccd6cSJohn Marino    leader.  */
415*ef5ccd6cSJohn Marino 
416*ef5ccd6cSJohn Marino static int
compare_processes(const void * process1,const void * process2)417*ef5ccd6cSJohn Marino compare_processes (const void *process1, const void *process2)
418*ef5ccd6cSJohn Marino {
419*ef5ccd6cSJohn Marino   PID_T pid1 = *((PID_T *) process1);
420*ef5ccd6cSJohn Marino   PID_T pid2 = *((PID_T *) process2);
421*ef5ccd6cSJohn Marino   PID_T pgid1 = *((PID_T *) process1 + 1);
422*ef5ccd6cSJohn Marino   PID_T pgid2 = *((PID_T *) process2 + 1);
423*ef5ccd6cSJohn Marino 
424*ef5ccd6cSJohn Marino   /* Sort by PGID.  */
425*ef5ccd6cSJohn Marino   if (pgid1 < pgid2)
426*ef5ccd6cSJohn Marino     return -1;
427*ef5ccd6cSJohn Marino   else if (pgid1 > pgid2)
428*ef5ccd6cSJohn Marino     return 1;
429*ef5ccd6cSJohn Marino   else
430*ef5ccd6cSJohn Marino     {
431*ef5ccd6cSJohn Marino       /* Process group leaders always come first, else sort by PID.  */
432*ef5ccd6cSJohn Marino       if (pid1 == pgid1)
433*ef5ccd6cSJohn Marino 	return -1;
434*ef5ccd6cSJohn Marino       else if (pid2 == pgid2)
435*ef5ccd6cSJohn Marino 	return 1;
436*ef5ccd6cSJohn Marino       else if (pid1 < pid2)
437*ef5ccd6cSJohn Marino 	return -1;
438*ef5ccd6cSJohn Marino       else if (pid1 > pid2)
439*ef5ccd6cSJohn Marino 	return 1;
440*ef5ccd6cSJohn Marino       else
441*ef5ccd6cSJohn Marino 	return 0;
442*ef5ccd6cSJohn Marino     }
443*ef5ccd6cSJohn Marino }
444*ef5ccd6cSJohn Marino 
445*ef5ccd6cSJohn Marino /* Collect all process groups from /proc.  */
446*ef5ccd6cSJohn Marino 
447*ef5ccd6cSJohn Marino static LONGEST
linux_xfer_osdata_processgroups(gdb_byte * readbuf,ULONGEST offset,LONGEST len)448*ef5ccd6cSJohn Marino linux_xfer_osdata_processgroups (gdb_byte *readbuf,
449*ef5ccd6cSJohn Marino 				 ULONGEST offset, LONGEST len)
450*ef5ccd6cSJohn Marino {
451*ef5ccd6cSJohn Marino   /* We make the process list snapshot when the object starts to be read.  */
452*ef5ccd6cSJohn Marino   static const char *buf;
453*ef5ccd6cSJohn Marino   static LONGEST len_avail = -1;
454*ef5ccd6cSJohn Marino   static struct buffer buffer;
455*ef5ccd6cSJohn Marino 
456*ef5ccd6cSJohn Marino   if (offset == 0)
457*ef5ccd6cSJohn Marino     {
458*ef5ccd6cSJohn Marino       DIR *dirp;
459*ef5ccd6cSJohn Marino 
460*ef5ccd6cSJohn Marino       if (len_avail != -1 && len_avail != 0)
461*ef5ccd6cSJohn Marino 	buffer_free (&buffer);
462*ef5ccd6cSJohn Marino       len_avail = 0;
463*ef5ccd6cSJohn Marino       buf = NULL;
464*ef5ccd6cSJohn Marino       buffer_init (&buffer);
465*ef5ccd6cSJohn Marino       buffer_grow_str (&buffer, "<osdata type=\"process groups\">\n");
466*ef5ccd6cSJohn Marino 
467*ef5ccd6cSJohn Marino       dirp = opendir ("/proc");
468*ef5ccd6cSJohn Marino       if (dirp)
469*ef5ccd6cSJohn Marino 	{
470*ef5ccd6cSJohn Marino 	  struct dirent *dp;
471*ef5ccd6cSJohn Marino 	  const size_t list_block_size = 512;
472*ef5ccd6cSJohn Marino 	  PID_T *process_list = (PID_T *) xmalloc (list_block_size * 2 * sizeof (PID_T));
473*ef5ccd6cSJohn Marino 	  size_t process_count = 0;
474*ef5ccd6cSJohn Marino 	  size_t i;
475*ef5ccd6cSJohn Marino 
476*ef5ccd6cSJohn Marino 	  /* Build list consisting of PIDs followed by their
477*ef5ccd6cSJohn Marino 	     associated PGID.  */
478*ef5ccd6cSJohn Marino 	  while ((dp = readdir (dirp)) != NULL)
479*ef5ccd6cSJohn Marino 	    {
480*ef5ccd6cSJohn Marino 	      PID_T pid, pgid;
481*ef5ccd6cSJohn Marino 
482*ef5ccd6cSJohn Marino 	      if (!isdigit (dp->d_name[0])
483*ef5ccd6cSJohn Marino 		  || NAMELEN (dp) > MAX_PID_T_STRLEN)
484*ef5ccd6cSJohn Marino 		continue;
485*ef5ccd6cSJohn Marino 
486*ef5ccd6cSJohn Marino 	      sscanf (dp->d_name, "%lld", &pid);
487*ef5ccd6cSJohn Marino 	      pgid = getpgid (pid);
488*ef5ccd6cSJohn Marino 
489*ef5ccd6cSJohn Marino 	      if (pgid > 0)
490*ef5ccd6cSJohn Marino 		{
491*ef5ccd6cSJohn Marino 		  process_list[2 * process_count] = pid;
492*ef5ccd6cSJohn Marino 		  process_list[2 * process_count + 1] = pgid;
493*ef5ccd6cSJohn Marino 		  ++process_count;
494*ef5ccd6cSJohn Marino 
495*ef5ccd6cSJohn Marino 		  /* Increase the size of the list if necessary.  */
496*ef5ccd6cSJohn Marino 		  if (process_count % list_block_size == 0)
497*ef5ccd6cSJohn Marino 		    process_list = (PID_T *) xrealloc (
498*ef5ccd6cSJohn Marino 			process_list,
499*ef5ccd6cSJohn Marino 			(process_count + list_block_size)
500*ef5ccd6cSJohn Marino 			* 2 * sizeof (PID_T));
501*ef5ccd6cSJohn Marino 		}
502*ef5ccd6cSJohn Marino 	    }
503*ef5ccd6cSJohn Marino 
504*ef5ccd6cSJohn Marino 	  closedir (dirp);
505*ef5ccd6cSJohn Marino 
506*ef5ccd6cSJohn Marino 	  /* Sort the process list.  */
507*ef5ccd6cSJohn Marino 	  qsort (process_list, process_count, 2 * sizeof (PID_T),
508*ef5ccd6cSJohn Marino 		 compare_processes);
509*ef5ccd6cSJohn Marino 
510*ef5ccd6cSJohn Marino 	  for (i = 0; i < process_count; ++i)
511*ef5ccd6cSJohn Marino 	    {
512*ef5ccd6cSJohn Marino 	      PID_T pid = process_list[2 * i];
513*ef5ccd6cSJohn Marino 	      PID_T pgid = process_list[2 * i + 1];
514*ef5ccd6cSJohn Marino 	      char leader_command[32];
515*ef5ccd6cSJohn Marino 	      char *command_line;
516*ef5ccd6cSJohn Marino 
517*ef5ccd6cSJohn Marino 	      command_from_pid (leader_command, sizeof (leader_command), pgid);
518*ef5ccd6cSJohn Marino 	      command_line = commandline_from_pid (pid);
519*ef5ccd6cSJohn Marino 
520*ef5ccd6cSJohn Marino 	      buffer_xml_printf (
521*ef5ccd6cSJohn Marino 		  &buffer,
522*ef5ccd6cSJohn Marino 		  "<item>"
523*ef5ccd6cSJohn Marino 		  "<column name=\"pgid\">%lld</column>"
524*ef5ccd6cSJohn Marino 		  "<column name=\"leader command\">%s</column>"
525*ef5ccd6cSJohn Marino 		  "<column name=\"pid\">%lld</column>"
526*ef5ccd6cSJohn Marino 		  "<column name=\"command line\">%s</column>"
527*ef5ccd6cSJohn Marino 		  "</item>",
528*ef5ccd6cSJohn Marino 		  pgid,
529*ef5ccd6cSJohn Marino 		  leader_command,
530*ef5ccd6cSJohn Marino 		  pid,
531*ef5ccd6cSJohn Marino 		  command_line ? command_line : "");
532*ef5ccd6cSJohn Marino 
533*ef5ccd6cSJohn Marino 	      xfree (command_line);
534*ef5ccd6cSJohn Marino 	    }
535*ef5ccd6cSJohn Marino 
536*ef5ccd6cSJohn Marino 	  xfree (process_list);
537*ef5ccd6cSJohn Marino 	}
538*ef5ccd6cSJohn Marino 
539*ef5ccd6cSJohn Marino       buffer_grow_str0 (&buffer, "</osdata>\n");
540*ef5ccd6cSJohn Marino       buf = buffer_finish (&buffer);
541*ef5ccd6cSJohn Marino       len_avail = strlen (buf);
542*ef5ccd6cSJohn Marino     }
543*ef5ccd6cSJohn Marino 
544*ef5ccd6cSJohn Marino   if (offset >= len_avail)
545*ef5ccd6cSJohn Marino     {
546*ef5ccd6cSJohn Marino       /* Done.  Get rid of the buffer.  */
547*ef5ccd6cSJohn Marino       buffer_free (&buffer);
548*ef5ccd6cSJohn Marino       buf = NULL;
549*ef5ccd6cSJohn Marino       len_avail = 0;
550*ef5ccd6cSJohn Marino       return 0;
551*ef5ccd6cSJohn Marino     }
552*ef5ccd6cSJohn Marino 
553*ef5ccd6cSJohn Marino   if (len > len_avail - offset)
554*ef5ccd6cSJohn Marino     len = len_avail - offset;
555*ef5ccd6cSJohn Marino   memcpy (readbuf, buf + offset, len);
556*ef5ccd6cSJohn Marino 
557*ef5ccd6cSJohn Marino   return len;
558*ef5ccd6cSJohn Marino }
559*ef5ccd6cSJohn Marino 
560*ef5ccd6cSJohn Marino /* Collect all the threads in /proc by iterating through processes and
561*ef5ccd6cSJohn Marino    then tasks within each process.  */
562*ef5ccd6cSJohn Marino 
563a45ae5f8SJohn Marino static LONGEST
linux_xfer_osdata_threads(gdb_byte * readbuf,ULONGEST offset,LONGEST len)564a45ae5f8SJohn Marino linux_xfer_osdata_threads (gdb_byte *readbuf,
565a45ae5f8SJohn Marino 			   ULONGEST offset, LONGEST len)
566a45ae5f8SJohn Marino {
567a45ae5f8SJohn Marino   /* We make the process list snapshot when the object starts to be read.  */
568a45ae5f8SJohn Marino   static const char *buf;
569a45ae5f8SJohn Marino   static LONGEST len_avail = -1;
570a45ae5f8SJohn Marino   static struct buffer buffer;
571a45ae5f8SJohn Marino 
572a45ae5f8SJohn Marino   if (offset == 0)
573a45ae5f8SJohn Marino     {
574a45ae5f8SJohn Marino       DIR *dirp;
575a45ae5f8SJohn Marino 
576a45ae5f8SJohn Marino       if (len_avail != -1 && len_avail != 0)
577a45ae5f8SJohn Marino 	buffer_free (&buffer);
578a45ae5f8SJohn Marino       len_avail = 0;
579a45ae5f8SJohn Marino       buf = NULL;
580a45ae5f8SJohn Marino       buffer_init (&buffer);
581a45ae5f8SJohn Marino       buffer_grow_str (&buffer, "<osdata type=\"threads\">\n");
582a45ae5f8SJohn Marino 
583a45ae5f8SJohn Marino       dirp = opendir ("/proc");
584a45ae5f8SJohn Marino       if (dirp)
585a45ae5f8SJohn Marino 	{
586a45ae5f8SJohn Marino 	  struct dirent *dp;
587a45ae5f8SJohn Marino 
588a45ae5f8SJohn Marino 	  while ((dp = readdir (dirp)) != NULL)
589a45ae5f8SJohn Marino 	    {
590a45ae5f8SJohn Marino 	      struct stat statbuf;
591a45ae5f8SJohn Marino 	      char procentry[sizeof ("/proc/4294967295")];
592a45ae5f8SJohn Marino 
593a45ae5f8SJohn Marino 	      if (!isdigit (dp->d_name[0])
594a45ae5f8SJohn Marino 		  || NAMELEN (dp) > sizeof ("4294967295") - 1)
595a45ae5f8SJohn Marino 		continue;
596a45ae5f8SJohn Marino 
597a45ae5f8SJohn Marino 	      sprintf (procentry, "/proc/%s", dp->d_name);
598a45ae5f8SJohn Marino 	      if (stat (procentry, &statbuf) == 0
599a45ae5f8SJohn Marino 		  && S_ISDIR (statbuf.st_mode))
600a45ae5f8SJohn Marino 		{
601a45ae5f8SJohn Marino 		  DIR *dirp2;
602a45ae5f8SJohn Marino 		  char *pathname;
603*ef5ccd6cSJohn Marino 		  PID_T pid;
604a45ae5f8SJohn Marino 		  char command[32];
605a45ae5f8SJohn Marino 
606a45ae5f8SJohn Marino 		  pathname = xstrprintf ("/proc/%s/task", dp->d_name);
607a45ae5f8SJohn Marino 
608a45ae5f8SJohn Marino 		  pid = atoi (dp->d_name);
609a45ae5f8SJohn Marino 		  command_from_pid (command, sizeof (command), pid);
610a45ae5f8SJohn Marino 
611a45ae5f8SJohn Marino 		  dirp2 = opendir (pathname);
612a45ae5f8SJohn Marino 
613a45ae5f8SJohn Marino 		  if (dirp2)
614a45ae5f8SJohn Marino 		    {
615a45ae5f8SJohn Marino 		      struct dirent *dp2;
616a45ae5f8SJohn Marino 
617a45ae5f8SJohn Marino 		      while ((dp2 = readdir (dirp2)) != NULL)
618a45ae5f8SJohn Marino 			{
619*ef5ccd6cSJohn Marino 			  PID_T tid;
620a45ae5f8SJohn Marino 			  int core;
621a45ae5f8SJohn Marino 
622a45ae5f8SJohn Marino 			  if (!isdigit (dp2->d_name[0])
623a45ae5f8SJohn Marino 			      || NAMELEN (dp2) > sizeof ("4294967295") - 1)
624a45ae5f8SJohn Marino 			    continue;
625a45ae5f8SJohn Marino 
626a45ae5f8SJohn Marino 			  tid = atoi (dp2->d_name);
627a45ae5f8SJohn Marino 			  core = linux_common_core_of_thread (ptid_build (pid, tid, 0));
628a45ae5f8SJohn Marino 
629a45ae5f8SJohn Marino 			  buffer_xml_printf (
630a45ae5f8SJohn Marino 			    &buffer,
631a45ae5f8SJohn Marino 			    "<item>"
632*ef5ccd6cSJohn Marino 			    "<column name=\"pid\">%lld</column>"
633a45ae5f8SJohn Marino 			    "<column name=\"command\">%s</column>"
634*ef5ccd6cSJohn Marino 			    "<column name=\"tid\">%lld</column>"
635a45ae5f8SJohn Marino 			    "<column name=\"core\">%d</column>"
636a45ae5f8SJohn Marino 			    "</item>",
637a45ae5f8SJohn Marino 			    pid,
638a45ae5f8SJohn Marino 			    command,
639a45ae5f8SJohn Marino 			    tid,
640a45ae5f8SJohn Marino 			    core);
641a45ae5f8SJohn Marino 			}
642a45ae5f8SJohn Marino 
643a45ae5f8SJohn Marino 		      closedir (dirp2);
644a45ae5f8SJohn Marino 		    }
645a45ae5f8SJohn Marino 
646a45ae5f8SJohn Marino 		  xfree (pathname);
647a45ae5f8SJohn Marino 		}
648a45ae5f8SJohn Marino 	    }
649a45ae5f8SJohn Marino 
650a45ae5f8SJohn Marino 	  closedir (dirp);
651a45ae5f8SJohn Marino 	}
652a45ae5f8SJohn Marino 
653a45ae5f8SJohn Marino       buffer_grow_str0 (&buffer, "</osdata>\n");
654a45ae5f8SJohn Marino       buf = buffer_finish (&buffer);
655a45ae5f8SJohn Marino       len_avail = strlen (buf);
656a45ae5f8SJohn Marino     }
657a45ae5f8SJohn Marino 
658a45ae5f8SJohn Marino   if (offset >= len_avail)
659a45ae5f8SJohn Marino     {
660a45ae5f8SJohn Marino       /* Done.  Get rid of the buffer.  */
661a45ae5f8SJohn Marino       buffer_free (&buffer);
662a45ae5f8SJohn Marino       buf = NULL;
663a45ae5f8SJohn Marino       len_avail = 0;
664a45ae5f8SJohn Marino       return 0;
665a45ae5f8SJohn Marino     }
666a45ae5f8SJohn Marino 
667a45ae5f8SJohn Marino   if (len > len_avail - offset)
668a45ae5f8SJohn Marino     len = len_avail - offset;
669a45ae5f8SJohn Marino   memcpy (readbuf, buf + offset, len);
670a45ae5f8SJohn Marino 
671a45ae5f8SJohn Marino   return len;
672a45ae5f8SJohn Marino }
673a45ae5f8SJohn Marino 
674*ef5ccd6cSJohn Marino /* Collect all the open file descriptors found in /proc and put the details
675*ef5ccd6cSJohn Marino    found about them into READBUF.  */
676*ef5ccd6cSJohn Marino 
677*ef5ccd6cSJohn Marino static LONGEST
linux_xfer_osdata_fds(gdb_byte * readbuf,ULONGEST offset,LONGEST len)678*ef5ccd6cSJohn Marino linux_xfer_osdata_fds (gdb_byte *readbuf,
679*ef5ccd6cSJohn Marino 		       ULONGEST offset, LONGEST len)
680*ef5ccd6cSJohn Marino {
681*ef5ccd6cSJohn Marino   /* We make the process list snapshot when the object starts to be read.  */
682*ef5ccd6cSJohn Marino   static const char *buf;
683*ef5ccd6cSJohn Marino   static LONGEST len_avail = -1;
684*ef5ccd6cSJohn Marino   static struct buffer buffer;
685*ef5ccd6cSJohn Marino 
686*ef5ccd6cSJohn Marino   if (offset == 0)
687*ef5ccd6cSJohn Marino     {
688*ef5ccd6cSJohn Marino       DIR *dirp;
689*ef5ccd6cSJohn Marino 
690*ef5ccd6cSJohn Marino       if (len_avail != -1 && len_avail != 0)
691*ef5ccd6cSJohn Marino 	buffer_free (&buffer);
692*ef5ccd6cSJohn Marino       len_avail = 0;
693*ef5ccd6cSJohn Marino       buf = NULL;
694*ef5ccd6cSJohn Marino       buffer_init (&buffer);
695*ef5ccd6cSJohn Marino       buffer_grow_str (&buffer, "<osdata type=\"files\">\n");
696*ef5ccd6cSJohn Marino 
697*ef5ccd6cSJohn Marino       dirp = opendir ("/proc");
698*ef5ccd6cSJohn Marino       if (dirp)
699*ef5ccd6cSJohn Marino 	{
700*ef5ccd6cSJohn Marino 	  struct dirent *dp;
701*ef5ccd6cSJohn Marino 
702*ef5ccd6cSJohn Marino 	  while ((dp = readdir (dirp)) != NULL)
703*ef5ccd6cSJohn Marino 	    {
704*ef5ccd6cSJohn Marino 	      struct stat statbuf;
705*ef5ccd6cSJohn Marino 	      char procentry[sizeof ("/proc/4294967295")];
706*ef5ccd6cSJohn Marino 
707*ef5ccd6cSJohn Marino 	      if (!isdigit (dp->d_name[0])
708*ef5ccd6cSJohn Marino 		  || NAMELEN (dp) > sizeof ("4294967295") - 1)
709*ef5ccd6cSJohn Marino 		continue;
710*ef5ccd6cSJohn Marino 
711*ef5ccd6cSJohn Marino 	      sprintf (procentry, "/proc/%s", dp->d_name);
712*ef5ccd6cSJohn Marino 	      if (stat (procentry, &statbuf) == 0
713*ef5ccd6cSJohn Marino 		  && S_ISDIR (statbuf.st_mode))
714*ef5ccd6cSJohn Marino 		{
715*ef5ccd6cSJohn Marino 		  char *pathname;
716*ef5ccd6cSJohn Marino 		  DIR *dirp2;
717*ef5ccd6cSJohn Marino 		  PID_T pid;
718*ef5ccd6cSJohn Marino 		  char command[32];
719*ef5ccd6cSJohn Marino 
720*ef5ccd6cSJohn Marino 		  pid = atoi (dp->d_name);
721*ef5ccd6cSJohn Marino 		  command_from_pid (command, sizeof (command), pid);
722*ef5ccd6cSJohn Marino 
723*ef5ccd6cSJohn Marino 		  pathname = xstrprintf ("/proc/%s/fd", dp->d_name);
724*ef5ccd6cSJohn Marino 		  dirp2 = opendir (pathname);
725*ef5ccd6cSJohn Marino 
726*ef5ccd6cSJohn Marino 		  if (dirp2)
727*ef5ccd6cSJohn Marino 		    {
728*ef5ccd6cSJohn Marino 		      struct dirent *dp2;
729*ef5ccd6cSJohn Marino 
730*ef5ccd6cSJohn Marino 		      while ((dp2 = readdir (dirp2)) != NULL)
731*ef5ccd6cSJohn Marino 			{
732*ef5ccd6cSJohn Marino 			  char *fdname;
733*ef5ccd6cSJohn Marino 			  char buf[1000];
734*ef5ccd6cSJohn Marino 			  ssize_t rslt;
735*ef5ccd6cSJohn Marino 
736*ef5ccd6cSJohn Marino 			  if (!isdigit (dp2->d_name[0]))
737*ef5ccd6cSJohn Marino 			    continue;
738*ef5ccd6cSJohn Marino 
739*ef5ccd6cSJohn Marino 			  fdname = xstrprintf ("%s/%s", pathname, dp2->d_name);
740*ef5ccd6cSJohn Marino 			  rslt = readlink (fdname, buf, sizeof (buf) - 1);
741*ef5ccd6cSJohn Marino 			  if (rslt >= 0)
742*ef5ccd6cSJohn Marino 			    buf[rslt] = '\0';
743*ef5ccd6cSJohn Marino 
744*ef5ccd6cSJohn Marino 			  buffer_xml_printf (
745*ef5ccd6cSJohn Marino 			    &buffer,
746*ef5ccd6cSJohn Marino 			    "<item>"
747*ef5ccd6cSJohn Marino 			    "<column name=\"pid\">%s</column>"
748*ef5ccd6cSJohn Marino 			    "<column name=\"command\">%s</column>"
749*ef5ccd6cSJohn Marino 			    "<column name=\"file descriptor\">%s</column>"
750*ef5ccd6cSJohn Marino 			    "<column name=\"name\">%s</column>"
751*ef5ccd6cSJohn Marino 			    "</item>",
752*ef5ccd6cSJohn Marino 			    dp->d_name,
753*ef5ccd6cSJohn Marino 			    command,
754*ef5ccd6cSJohn Marino 			    dp2->d_name,
755*ef5ccd6cSJohn Marino 			    (rslt >= 0 ? buf : dp2->d_name));
756*ef5ccd6cSJohn Marino 			}
757*ef5ccd6cSJohn Marino 
758*ef5ccd6cSJohn Marino 		      closedir (dirp2);
759*ef5ccd6cSJohn Marino 		    }
760*ef5ccd6cSJohn Marino 
761*ef5ccd6cSJohn Marino 		  xfree (pathname);
762*ef5ccd6cSJohn Marino 		}
763*ef5ccd6cSJohn Marino 	    }
764*ef5ccd6cSJohn Marino 
765*ef5ccd6cSJohn Marino 	  closedir (dirp);
766*ef5ccd6cSJohn Marino 	}
767*ef5ccd6cSJohn Marino 
768*ef5ccd6cSJohn Marino       buffer_grow_str0 (&buffer, "</osdata>\n");
769*ef5ccd6cSJohn Marino       buf = buffer_finish (&buffer);
770*ef5ccd6cSJohn Marino       len_avail = strlen (buf);
771*ef5ccd6cSJohn Marino     }
772*ef5ccd6cSJohn Marino 
773*ef5ccd6cSJohn Marino   if (offset >= len_avail)
774*ef5ccd6cSJohn Marino     {
775*ef5ccd6cSJohn Marino       /* Done.  Get rid of the buffer.  */
776*ef5ccd6cSJohn Marino       buffer_free (&buffer);
777*ef5ccd6cSJohn Marino       buf = NULL;
778*ef5ccd6cSJohn Marino       len_avail = 0;
779*ef5ccd6cSJohn Marino       return 0;
780*ef5ccd6cSJohn Marino     }
781*ef5ccd6cSJohn Marino 
782*ef5ccd6cSJohn Marino   if (len > len_avail - offset)
783*ef5ccd6cSJohn Marino     len = len_avail - offset;
784*ef5ccd6cSJohn Marino   memcpy (readbuf, buf + offset, len);
785*ef5ccd6cSJohn Marino 
786*ef5ccd6cSJohn Marino   return len;
787*ef5ccd6cSJohn Marino }
788*ef5ccd6cSJohn Marino 
789*ef5ccd6cSJohn Marino /* Returns the socket state STATE in textual form.  */
790*ef5ccd6cSJohn Marino 
791*ef5ccd6cSJohn Marino static const char *
format_socket_state(unsigned char state)792*ef5ccd6cSJohn Marino format_socket_state (unsigned char state)
793*ef5ccd6cSJohn Marino {
794*ef5ccd6cSJohn Marino   /* Copied from include/net/tcp_states.h in the Linux kernel sources.  */
795*ef5ccd6cSJohn Marino   enum {
796*ef5ccd6cSJohn Marino     TCP_ESTABLISHED = 1,
797*ef5ccd6cSJohn Marino     TCP_SYN_SENT,
798*ef5ccd6cSJohn Marino     TCP_SYN_RECV,
799*ef5ccd6cSJohn Marino     TCP_FIN_WAIT1,
800*ef5ccd6cSJohn Marino     TCP_FIN_WAIT2,
801*ef5ccd6cSJohn Marino     TCP_TIME_WAIT,
802*ef5ccd6cSJohn Marino     TCP_CLOSE,
803*ef5ccd6cSJohn Marino     TCP_CLOSE_WAIT,
804*ef5ccd6cSJohn Marino     TCP_LAST_ACK,
805*ef5ccd6cSJohn Marino     TCP_LISTEN,
806*ef5ccd6cSJohn Marino     TCP_CLOSING
807*ef5ccd6cSJohn Marino   };
808*ef5ccd6cSJohn Marino 
809*ef5ccd6cSJohn Marino   switch (state)
810*ef5ccd6cSJohn Marino     {
811*ef5ccd6cSJohn Marino     case TCP_ESTABLISHED:
812*ef5ccd6cSJohn Marino       return "ESTABLISHED";
813*ef5ccd6cSJohn Marino     case TCP_SYN_SENT:
814*ef5ccd6cSJohn Marino       return "SYN_SENT";
815*ef5ccd6cSJohn Marino     case TCP_SYN_RECV:
816*ef5ccd6cSJohn Marino       return "SYN_RECV";
817*ef5ccd6cSJohn Marino     case TCP_FIN_WAIT1:
818*ef5ccd6cSJohn Marino       return "FIN_WAIT1";
819*ef5ccd6cSJohn Marino     case TCP_FIN_WAIT2:
820*ef5ccd6cSJohn Marino       return "FIN_WAIT2";
821*ef5ccd6cSJohn Marino     case TCP_TIME_WAIT:
822*ef5ccd6cSJohn Marino       return "TIME_WAIT";
823*ef5ccd6cSJohn Marino     case TCP_CLOSE:
824*ef5ccd6cSJohn Marino       return "CLOSE";
825*ef5ccd6cSJohn Marino     case TCP_CLOSE_WAIT:
826*ef5ccd6cSJohn Marino       return "CLOSE_WAIT";
827*ef5ccd6cSJohn Marino     case TCP_LAST_ACK:
828*ef5ccd6cSJohn Marino       return "LAST_ACK";
829*ef5ccd6cSJohn Marino     case TCP_LISTEN:
830*ef5ccd6cSJohn Marino       return "LISTEN";
831*ef5ccd6cSJohn Marino     case TCP_CLOSING:
832*ef5ccd6cSJohn Marino       return "CLOSING";
833*ef5ccd6cSJohn Marino     default:
834*ef5ccd6cSJohn Marino       return "(unknown)";
835*ef5ccd6cSJohn Marino     }
836*ef5ccd6cSJohn Marino }
837*ef5ccd6cSJohn Marino 
838*ef5ccd6cSJohn Marino union socket_addr
839*ef5ccd6cSJohn Marino   {
840*ef5ccd6cSJohn Marino     struct sockaddr sa;
841*ef5ccd6cSJohn Marino     struct sockaddr_in sin;
842*ef5ccd6cSJohn Marino     struct sockaddr_in6 sin6;
843*ef5ccd6cSJohn Marino   };
844*ef5ccd6cSJohn Marino 
845*ef5ccd6cSJohn Marino /* Auxiliary function used by linux_xfer_osdata_isocket.  Formats
846*ef5ccd6cSJohn Marino    information for all open internet sockets of type FAMILY on the
847*ef5ccd6cSJohn Marino    system into BUFFER.  If TCP is set, only TCP sockets are processed,
848*ef5ccd6cSJohn Marino    otherwise only UDP sockets are processed.  */
849*ef5ccd6cSJohn Marino 
850*ef5ccd6cSJohn Marino static void
print_sockets(unsigned short family,int tcp,struct buffer * buffer)851*ef5ccd6cSJohn Marino print_sockets (unsigned short family, int tcp, struct buffer *buffer)
852*ef5ccd6cSJohn Marino {
853*ef5ccd6cSJohn Marino   const char *proc_file;
854*ef5ccd6cSJohn Marino   FILE *fp;
855*ef5ccd6cSJohn Marino 
856*ef5ccd6cSJohn Marino   if (family == AF_INET)
857*ef5ccd6cSJohn Marino     proc_file = tcp ? "/proc/net/tcp" : "/proc/net/udp";
858*ef5ccd6cSJohn Marino   else if (family == AF_INET6)
859*ef5ccd6cSJohn Marino     proc_file = tcp ? "/proc/net/tcp6" : "/proc/net/udp6";
860*ef5ccd6cSJohn Marino   else
861*ef5ccd6cSJohn Marino     return;
862*ef5ccd6cSJohn Marino 
863*ef5ccd6cSJohn Marino   fp = fopen (proc_file, "r");
864*ef5ccd6cSJohn Marino   if (fp)
865*ef5ccd6cSJohn Marino     {
866*ef5ccd6cSJohn Marino       char buf[8192];
867*ef5ccd6cSJohn Marino 
868*ef5ccd6cSJohn Marino       do
869*ef5ccd6cSJohn Marino 	{
870*ef5ccd6cSJohn Marino 	  if (fgets (buf, sizeof (buf), fp))
871*ef5ccd6cSJohn Marino 	    {
872*ef5ccd6cSJohn Marino 	      uid_t uid;
873*ef5ccd6cSJohn Marino 	      unsigned long tlen, inode;
874*ef5ccd6cSJohn Marino 	      int sl, timeout;
875*ef5ccd6cSJohn Marino 	      unsigned int local_port, remote_port, state;
876*ef5ccd6cSJohn Marino 	      unsigned int txq, rxq, trun, retn;
877*ef5ccd6cSJohn Marino 	      char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
878*ef5ccd6cSJohn Marino 	      char extra[512];
879*ef5ccd6cSJohn Marino 	      int result;
880*ef5ccd6cSJohn Marino 
881*ef5ccd6cSJohn Marino 	      result = sscanf (buf,
882*ef5ccd6cSJohn Marino 			       "%d: %33[0-9A-F]:%X %33[0-9A-F]:%X %X %X:%X %X:%lX %X %d %d %lu %512s\n",
883*ef5ccd6cSJohn Marino 			       &sl,
884*ef5ccd6cSJohn Marino 			       local_address, &local_port,
885*ef5ccd6cSJohn Marino 			       remote_address, &remote_port,
886*ef5ccd6cSJohn Marino 			       &state,
887*ef5ccd6cSJohn Marino 			       &txq, &rxq,
888*ef5ccd6cSJohn Marino 			       &trun, &tlen,
889*ef5ccd6cSJohn Marino 			       &retn,
890*ef5ccd6cSJohn Marino 			       &uid,
891*ef5ccd6cSJohn Marino 			       &timeout,
892*ef5ccd6cSJohn Marino 			       &inode,
893*ef5ccd6cSJohn Marino 			       extra);
894*ef5ccd6cSJohn Marino 
895*ef5ccd6cSJohn Marino 	      if (result == 15)
896*ef5ccd6cSJohn Marino 		{
897*ef5ccd6cSJohn Marino 		  union socket_addr locaddr, remaddr;
898*ef5ccd6cSJohn Marino 		  size_t addr_size;
899*ef5ccd6cSJohn Marino 		  char user[UT_NAMESIZE];
900*ef5ccd6cSJohn Marino 		  char local_service[NI_MAXSERV], remote_service[NI_MAXSERV];
901*ef5ccd6cSJohn Marino 
902*ef5ccd6cSJohn Marino 		  if (family == AF_INET)
903*ef5ccd6cSJohn Marino 		    {
904*ef5ccd6cSJohn Marino 		      sscanf (local_address, "%X",
905*ef5ccd6cSJohn Marino 			      &locaddr.sin.sin_addr.s_addr);
906*ef5ccd6cSJohn Marino 		      sscanf (remote_address, "%X",
907*ef5ccd6cSJohn Marino 			      &remaddr.sin.sin_addr.s_addr);
908*ef5ccd6cSJohn Marino 
909*ef5ccd6cSJohn Marino 		      locaddr.sin.sin_port = htons (local_port);
910*ef5ccd6cSJohn Marino 		      remaddr.sin.sin_port = htons (remote_port);
911*ef5ccd6cSJohn Marino 
912*ef5ccd6cSJohn Marino 		      addr_size = sizeof (struct sockaddr_in);
913*ef5ccd6cSJohn Marino 		    }
914*ef5ccd6cSJohn Marino 		  else
915*ef5ccd6cSJohn Marino 		    {
916*ef5ccd6cSJohn Marino 		      sscanf (local_address, "%8X%8X%8X%8X",
917*ef5ccd6cSJohn Marino 			      locaddr.sin6.sin6_addr.s6_addr32,
918*ef5ccd6cSJohn Marino 			      locaddr.sin6.sin6_addr.s6_addr32 + 1,
919*ef5ccd6cSJohn Marino 			      locaddr.sin6.sin6_addr.s6_addr32 + 2,
920*ef5ccd6cSJohn Marino 			      locaddr.sin6.sin6_addr.s6_addr32 + 3);
921*ef5ccd6cSJohn Marino 		      sscanf (remote_address, "%8X%8X%8X%8X",
922*ef5ccd6cSJohn Marino 			      remaddr.sin6.sin6_addr.s6_addr32,
923*ef5ccd6cSJohn Marino 			      remaddr.sin6.sin6_addr.s6_addr32 + 1,
924*ef5ccd6cSJohn Marino 			      remaddr.sin6.sin6_addr.s6_addr32 + 2,
925*ef5ccd6cSJohn Marino 			      remaddr.sin6.sin6_addr.s6_addr32 + 3);
926*ef5ccd6cSJohn Marino 
927*ef5ccd6cSJohn Marino 		      locaddr.sin6.sin6_port = htons (local_port);
928*ef5ccd6cSJohn Marino 		      remaddr.sin6.sin6_port = htons (remote_port);
929*ef5ccd6cSJohn Marino 
930*ef5ccd6cSJohn Marino 		      locaddr.sin6.sin6_flowinfo = 0;
931*ef5ccd6cSJohn Marino 		      remaddr.sin6.sin6_flowinfo = 0;
932*ef5ccd6cSJohn Marino 		      locaddr.sin6.sin6_scope_id = 0;
933*ef5ccd6cSJohn Marino 		      remaddr.sin6.sin6_scope_id = 0;
934*ef5ccd6cSJohn Marino 
935*ef5ccd6cSJohn Marino 		      addr_size = sizeof (struct sockaddr_in6);
936*ef5ccd6cSJohn Marino 		    }
937*ef5ccd6cSJohn Marino 
938*ef5ccd6cSJohn Marino 		  locaddr.sa.sa_family = remaddr.sa.sa_family = family;
939*ef5ccd6cSJohn Marino 
940*ef5ccd6cSJohn Marino 		  result = getnameinfo (&locaddr.sa, addr_size,
941*ef5ccd6cSJohn Marino 					local_address, sizeof (local_address),
942*ef5ccd6cSJohn Marino 					local_service, sizeof (local_service),
943*ef5ccd6cSJohn Marino 					NI_NUMERICHOST | NI_NUMERICSERV
944*ef5ccd6cSJohn Marino 					| (tcp ? 0 : NI_DGRAM));
945*ef5ccd6cSJohn Marino 		  if (result)
946*ef5ccd6cSJohn Marino 		    continue;
947*ef5ccd6cSJohn Marino 
948*ef5ccd6cSJohn Marino 		  result = getnameinfo (&remaddr.sa, addr_size,
949*ef5ccd6cSJohn Marino 					remote_address,
950*ef5ccd6cSJohn Marino 					sizeof (remote_address),
951*ef5ccd6cSJohn Marino 					remote_service,
952*ef5ccd6cSJohn Marino 					sizeof (remote_service),
953*ef5ccd6cSJohn Marino 					NI_NUMERICHOST | NI_NUMERICSERV
954*ef5ccd6cSJohn Marino 					| (tcp ? 0 : NI_DGRAM));
955*ef5ccd6cSJohn Marino 		  if (result)
956*ef5ccd6cSJohn Marino 		    continue;
957*ef5ccd6cSJohn Marino 
958*ef5ccd6cSJohn Marino 		  user_from_uid (user, sizeof (user), uid);
959*ef5ccd6cSJohn Marino 
960*ef5ccd6cSJohn Marino 		  buffer_xml_printf (
961*ef5ccd6cSJohn Marino 		      buffer,
962*ef5ccd6cSJohn Marino 		      "<item>"
963*ef5ccd6cSJohn Marino 		      "<column name=\"local address\">%s</column>"
964*ef5ccd6cSJohn Marino 		      "<column name=\"local port\">%s</column>"
965*ef5ccd6cSJohn Marino 		      "<column name=\"remote address\">%s</column>"
966*ef5ccd6cSJohn Marino 		      "<column name=\"remote port\">%s</column>"
967*ef5ccd6cSJohn Marino 		      "<column name=\"state\">%s</column>"
968*ef5ccd6cSJohn Marino 		      "<column name=\"user\">%s</column>"
969*ef5ccd6cSJohn Marino 		      "<column name=\"family\">%s</column>"
970*ef5ccd6cSJohn Marino 		      "<column name=\"protocol\">%s</column>"
971*ef5ccd6cSJohn Marino 		      "</item>",
972*ef5ccd6cSJohn Marino 		      local_address,
973*ef5ccd6cSJohn Marino 		      local_service,
974*ef5ccd6cSJohn Marino 		      remote_address,
975*ef5ccd6cSJohn Marino 		      remote_service,
976*ef5ccd6cSJohn Marino 		      format_socket_state (state),
977*ef5ccd6cSJohn Marino 		      user,
978*ef5ccd6cSJohn Marino 		      (family == AF_INET) ? "INET" : "INET6",
979*ef5ccd6cSJohn Marino 		      tcp ? "STREAM" : "DGRAM");
980*ef5ccd6cSJohn Marino 		}
981*ef5ccd6cSJohn Marino 	    }
982*ef5ccd6cSJohn Marino 	}
983*ef5ccd6cSJohn Marino       while (!feof (fp));
984*ef5ccd6cSJohn Marino 
985*ef5ccd6cSJohn Marino       fclose (fp);
986*ef5ccd6cSJohn Marino     }
987*ef5ccd6cSJohn Marino }
988*ef5ccd6cSJohn Marino 
989*ef5ccd6cSJohn Marino /* Collect data about internet sockets and write it into READBUF.  */
990*ef5ccd6cSJohn Marino 
991*ef5ccd6cSJohn Marino static LONGEST
linux_xfer_osdata_isockets(gdb_byte * readbuf,ULONGEST offset,LONGEST len)992*ef5ccd6cSJohn Marino linux_xfer_osdata_isockets (gdb_byte *readbuf,
993*ef5ccd6cSJohn Marino 			    ULONGEST offset, LONGEST len)
994*ef5ccd6cSJohn Marino {
995*ef5ccd6cSJohn Marino   static const char *buf;
996*ef5ccd6cSJohn Marino   static LONGEST len_avail = -1;
997*ef5ccd6cSJohn Marino   static struct buffer buffer;
998*ef5ccd6cSJohn Marino 
999*ef5ccd6cSJohn Marino   if (offset == 0)
1000*ef5ccd6cSJohn Marino     {
1001*ef5ccd6cSJohn Marino       if (len_avail != -1 && len_avail != 0)
1002*ef5ccd6cSJohn Marino 	buffer_free (&buffer);
1003*ef5ccd6cSJohn Marino       len_avail = 0;
1004*ef5ccd6cSJohn Marino       buf = NULL;
1005*ef5ccd6cSJohn Marino       buffer_init (&buffer);
1006*ef5ccd6cSJohn Marino       buffer_grow_str (&buffer, "<osdata type=\"I sockets\">\n");
1007*ef5ccd6cSJohn Marino 
1008*ef5ccd6cSJohn Marino       print_sockets (AF_INET, 1, &buffer);
1009*ef5ccd6cSJohn Marino       print_sockets (AF_INET, 0, &buffer);
1010*ef5ccd6cSJohn Marino       print_sockets (AF_INET6, 1, &buffer);
1011*ef5ccd6cSJohn Marino       print_sockets (AF_INET6, 0, &buffer);
1012*ef5ccd6cSJohn Marino 
1013*ef5ccd6cSJohn Marino       buffer_grow_str0 (&buffer, "</osdata>\n");
1014*ef5ccd6cSJohn Marino       buf = buffer_finish (&buffer);
1015*ef5ccd6cSJohn Marino       len_avail = strlen (buf);
1016*ef5ccd6cSJohn Marino     }
1017*ef5ccd6cSJohn Marino 
1018*ef5ccd6cSJohn Marino   if (offset >= len_avail)
1019*ef5ccd6cSJohn Marino     {
1020*ef5ccd6cSJohn Marino       /* Done.  Get rid of the buffer.  */
1021*ef5ccd6cSJohn Marino       buffer_free (&buffer);
1022*ef5ccd6cSJohn Marino       buf = NULL;
1023*ef5ccd6cSJohn Marino       len_avail = 0;
1024*ef5ccd6cSJohn Marino       return 0;
1025*ef5ccd6cSJohn Marino     }
1026*ef5ccd6cSJohn Marino 
1027*ef5ccd6cSJohn Marino   if (len > len_avail - offset)
1028*ef5ccd6cSJohn Marino     len = len_avail - offset;
1029*ef5ccd6cSJohn Marino   memcpy (readbuf, buf + offset, len);
1030*ef5ccd6cSJohn Marino 
1031*ef5ccd6cSJohn Marino   return len;
1032*ef5ccd6cSJohn Marino }
1033*ef5ccd6cSJohn Marino 
1034*ef5ccd6cSJohn Marino /* Converts the time SECONDS into textual form and copies it into a
1035*ef5ccd6cSJohn Marino    buffer TIME, with at most MAXLEN characters copied.  */
1036*ef5ccd6cSJohn Marino 
1037*ef5ccd6cSJohn Marino static void
time_from_time_t(char * time,int maxlen,TIME_T seconds)1038*ef5ccd6cSJohn Marino time_from_time_t (char *time, int maxlen, TIME_T seconds)
1039*ef5ccd6cSJohn Marino {
1040*ef5ccd6cSJohn Marino   if (!seconds)
1041*ef5ccd6cSJohn Marino     time[0] = '\0';
1042*ef5ccd6cSJohn Marino   else
1043*ef5ccd6cSJohn Marino     {
1044*ef5ccd6cSJohn Marino       time_t t = (time_t) seconds;
1045*ef5ccd6cSJohn Marino 
1046*ef5ccd6cSJohn Marino       strncpy (time, ctime (&t), maxlen);
1047*ef5ccd6cSJohn Marino       time[maxlen - 1] = '\0';
1048*ef5ccd6cSJohn Marino     }
1049*ef5ccd6cSJohn Marino }
1050*ef5ccd6cSJohn Marino 
1051*ef5ccd6cSJohn Marino /* Finds the group name for the group GID and copies it into GROUP.
1052*ef5ccd6cSJohn Marino    At most MAXLEN characters are copied.  */
1053*ef5ccd6cSJohn Marino 
1054*ef5ccd6cSJohn Marino static void
group_from_gid(char * group,int maxlen,gid_t gid)1055*ef5ccd6cSJohn Marino group_from_gid (char *group, int maxlen, gid_t gid)
1056*ef5ccd6cSJohn Marino {
1057*ef5ccd6cSJohn Marino   struct group *grentry = getgrgid (gid);
1058*ef5ccd6cSJohn Marino 
1059*ef5ccd6cSJohn Marino   if (grentry)
1060*ef5ccd6cSJohn Marino     {
1061*ef5ccd6cSJohn Marino       strncpy (group, grentry->gr_name, maxlen);
1062*ef5ccd6cSJohn Marino       /* Ensure that the group name is null-terminated.  */
1063*ef5ccd6cSJohn Marino       group[maxlen - 1] = '\0';
1064*ef5ccd6cSJohn Marino     }
1065*ef5ccd6cSJohn Marino   else
1066*ef5ccd6cSJohn Marino     group[0] = '\0';
1067*ef5ccd6cSJohn Marino }
1068*ef5ccd6cSJohn Marino 
1069*ef5ccd6cSJohn Marino /* Collect data about shared memory recorded in /proc and write it
1070*ef5ccd6cSJohn Marino    into READBUF.  */
1071*ef5ccd6cSJohn Marino 
1072*ef5ccd6cSJohn Marino static LONGEST
linux_xfer_osdata_shm(gdb_byte * readbuf,ULONGEST offset,LONGEST len)1073*ef5ccd6cSJohn Marino linux_xfer_osdata_shm (gdb_byte *readbuf,
1074*ef5ccd6cSJohn Marino 		       ULONGEST offset, LONGEST len)
1075*ef5ccd6cSJohn Marino {
1076*ef5ccd6cSJohn Marino   static const char *buf;
1077*ef5ccd6cSJohn Marino   static LONGEST len_avail = -1;
1078*ef5ccd6cSJohn Marino   static struct buffer buffer;
1079*ef5ccd6cSJohn Marino 
1080*ef5ccd6cSJohn Marino   if (offset == 0)
1081*ef5ccd6cSJohn Marino     {
1082*ef5ccd6cSJohn Marino       FILE *fp;
1083*ef5ccd6cSJohn Marino 
1084*ef5ccd6cSJohn Marino       if (len_avail != -1 && len_avail != 0)
1085*ef5ccd6cSJohn Marino 	buffer_free (&buffer);
1086*ef5ccd6cSJohn Marino       len_avail = 0;
1087*ef5ccd6cSJohn Marino       buf = NULL;
1088*ef5ccd6cSJohn Marino       buffer_init (&buffer);
1089*ef5ccd6cSJohn Marino       buffer_grow_str (&buffer, "<osdata type=\"shared memory\">\n");
1090*ef5ccd6cSJohn Marino 
1091*ef5ccd6cSJohn Marino       fp = fopen ("/proc/sysvipc/shm", "r");
1092*ef5ccd6cSJohn Marino       if (fp)
1093*ef5ccd6cSJohn Marino 	{
1094*ef5ccd6cSJohn Marino 	  char buf[8192];
1095*ef5ccd6cSJohn Marino 
1096*ef5ccd6cSJohn Marino 	  do
1097*ef5ccd6cSJohn Marino 	    {
1098*ef5ccd6cSJohn Marino 	      if (fgets (buf, sizeof (buf), fp))
1099*ef5ccd6cSJohn Marino 		{
1100*ef5ccd6cSJohn Marino 		  key_t key;
1101*ef5ccd6cSJohn Marino 		  uid_t uid, cuid;
1102*ef5ccd6cSJohn Marino 		  gid_t gid, cgid;
1103*ef5ccd6cSJohn Marino 		  PID_T cpid, lpid;
1104*ef5ccd6cSJohn Marino 		  int shmid, size, nattch;
1105*ef5ccd6cSJohn Marino 		  TIME_T atime, dtime, ctime;
1106*ef5ccd6cSJohn Marino 		  unsigned int perms;
1107*ef5ccd6cSJohn Marino 		  int items_read;
1108*ef5ccd6cSJohn Marino 
1109*ef5ccd6cSJohn Marino 		  items_read = sscanf (buf,
1110*ef5ccd6cSJohn Marino 				       "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1111*ef5ccd6cSJohn Marino 				       &key, &shmid, &perms, &size,
1112*ef5ccd6cSJohn Marino 				       &cpid, &lpid,
1113*ef5ccd6cSJohn Marino 				       &nattch,
1114*ef5ccd6cSJohn Marino 				       &uid, &gid, &cuid, &cgid,
1115*ef5ccd6cSJohn Marino 				       &atime, &dtime, &ctime);
1116*ef5ccd6cSJohn Marino 
1117*ef5ccd6cSJohn Marino 		  if (items_read == 14)
1118*ef5ccd6cSJohn Marino 		    {
1119*ef5ccd6cSJohn Marino 		      char user[UT_NAMESIZE], group[UT_NAMESIZE];
1120*ef5ccd6cSJohn Marino 		      char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1121*ef5ccd6cSJohn Marino 		      char ccmd[32], lcmd[32];
1122*ef5ccd6cSJohn Marino 		      char atime_str[32], dtime_str[32], ctime_str[32];
1123*ef5ccd6cSJohn Marino 
1124*ef5ccd6cSJohn Marino 		      user_from_uid (user, sizeof (user), uid);
1125*ef5ccd6cSJohn Marino 		      group_from_gid (group, sizeof (group), gid);
1126*ef5ccd6cSJohn Marino 		      user_from_uid (cuser, sizeof (cuser), cuid);
1127*ef5ccd6cSJohn Marino 		      group_from_gid (cgroup, sizeof (cgroup), cgid);
1128*ef5ccd6cSJohn Marino 
1129*ef5ccd6cSJohn Marino 		      command_from_pid (ccmd, sizeof (ccmd), cpid);
1130*ef5ccd6cSJohn Marino 		      command_from_pid (lcmd, sizeof (lcmd), lpid);
1131*ef5ccd6cSJohn Marino 
1132*ef5ccd6cSJohn Marino 		      time_from_time_t (atime_str, sizeof (atime_str), atime);
1133*ef5ccd6cSJohn Marino 		      time_from_time_t (dtime_str, sizeof (dtime_str), dtime);
1134*ef5ccd6cSJohn Marino 		      time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1135*ef5ccd6cSJohn Marino 
1136*ef5ccd6cSJohn Marino 		      buffer_xml_printf (
1137*ef5ccd6cSJohn Marino 		          &buffer,
1138*ef5ccd6cSJohn Marino 			  "<item>"
1139*ef5ccd6cSJohn Marino 			  "<column name=\"key\">%d</column>"
1140*ef5ccd6cSJohn Marino 			  "<column name=\"shmid\">%d</column>"
1141*ef5ccd6cSJohn Marino 			  "<column name=\"permissions\">%o</column>"
1142*ef5ccd6cSJohn Marino 			  "<column name=\"size\">%d</column>"
1143*ef5ccd6cSJohn Marino 			  "<column name=\"creator command\">%s</column>"
1144*ef5ccd6cSJohn Marino 			  "<column name=\"last op. command\">%s</column>"
1145*ef5ccd6cSJohn Marino 			  "<column name=\"num attached\">%d</column>"
1146*ef5ccd6cSJohn Marino 			  "<column name=\"user\">%s</column>"
1147*ef5ccd6cSJohn Marino 			  "<column name=\"group\">%s</column>"
1148*ef5ccd6cSJohn Marino 			  "<column name=\"creator user\">%s</column>"
1149*ef5ccd6cSJohn Marino 			  "<column name=\"creator group\">%s</column>"
1150*ef5ccd6cSJohn Marino 			  "<column name=\"last shmat() time\">%s</column>"
1151*ef5ccd6cSJohn Marino 			  "<column name=\"last shmdt() time\">%s</column>"
1152*ef5ccd6cSJohn Marino 			  "<column name=\"last shmctl() time\">%s</column>"
1153*ef5ccd6cSJohn Marino 			  "</item>",
1154*ef5ccd6cSJohn Marino 			  key,
1155*ef5ccd6cSJohn Marino 			  shmid,
1156*ef5ccd6cSJohn Marino 			  perms,
1157*ef5ccd6cSJohn Marino 			  size,
1158*ef5ccd6cSJohn Marino 			  ccmd,
1159*ef5ccd6cSJohn Marino 			  lcmd,
1160*ef5ccd6cSJohn Marino 			  nattch,
1161*ef5ccd6cSJohn Marino 			  user,
1162*ef5ccd6cSJohn Marino 			  group,
1163*ef5ccd6cSJohn Marino 			  cuser,
1164*ef5ccd6cSJohn Marino 			  cgroup,
1165*ef5ccd6cSJohn Marino 			  atime_str,
1166*ef5ccd6cSJohn Marino 			  dtime_str,
1167*ef5ccd6cSJohn Marino 			  ctime_str);
1168*ef5ccd6cSJohn Marino 		    }
1169*ef5ccd6cSJohn Marino 		}
1170*ef5ccd6cSJohn Marino 	    }
1171*ef5ccd6cSJohn Marino 	  while (!feof (fp));
1172*ef5ccd6cSJohn Marino 
1173*ef5ccd6cSJohn Marino 	  fclose (fp);
1174*ef5ccd6cSJohn Marino 	}
1175*ef5ccd6cSJohn Marino 
1176*ef5ccd6cSJohn Marino       buffer_grow_str0 (&buffer, "</osdata>\n");
1177*ef5ccd6cSJohn Marino       buf = buffer_finish (&buffer);
1178*ef5ccd6cSJohn Marino       len_avail = strlen (buf);
1179*ef5ccd6cSJohn Marino     }
1180*ef5ccd6cSJohn Marino 
1181*ef5ccd6cSJohn Marino   if (offset >= len_avail)
1182*ef5ccd6cSJohn Marino     {
1183*ef5ccd6cSJohn Marino       /* Done.  Get rid of the buffer.  */
1184*ef5ccd6cSJohn Marino       buffer_free (&buffer);
1185*ef5ccd6cSJohn Marino       buf = NULL;
1186*ef5ccd6cSJohn Marino       len_avail = 0;
1187*ef5ccd6cSJohn Marino       return 0;
1188*ef5ccd6cSJohn Marino     }
1189*ef5ccd6cSJohn Marino 
1190*ef5ccd6cSJohn Marino   if (len > len_avail - offset)
1191*ef5ccd6cSJohn Marino     len = len_avail - offset;
1192*ef5ccd6cSJohn Marino   memcpy (readbuf, buf + offset, len);
1193*ef5ccd6cSJohn Marino 
1194*ef5ccd6cSJohn Marino   return len;
1195*ef5ccd6cSJohn Marino }
1196*ef5ccd6cSJohn Marino 
1197*ef5ccd6cSJohn Marino /* Collect data about semaphores recorded in /proc and write it
1198*ef5ccd6cSJohn Marino    into READBUF.  */
1199*ef5ccd6cSJohn Marino 
1200*ef5ccd6cSJohn Marino static LONGEST
linux_xfer_osdata_sem(gdb_byte * readbuf,ULONGEST offset,LONGEST len)1201*ef5ccd6cSJohn Marino linux_xfer_osdata_sem (gdb_byte *readbuf,
1202*ef5ccd6cSJohn Marino 		       ULONGEST offset, LONGEST len)
1203*ef5ccd6cSJohn Marino {
1204*ef5ccd6cSJohn Marino   static const char *buf;
1205*ef5ccd6cSJohn Marino   static LONGEST len_avail = -1;
1206*ef5ccd6cSJohn Marino   static struct buffer buffer;
1207*ef5ccd6cSJohn Marino 
1208*ef5ccd6cSJohn Marino   if (offset == 0)
1209*ef5ccd6cSJohn Marino     {
1210*ef5ccd6cSJohn Marino       FILE *fp;
1211*ef5ccd6cSJohn Marino 
1212*ef5ccd6cSJohn Marino       if (len_avail != -1 && len_avail != 0)
1213*ef5ccd6cSJohn Marino 	buffer_free (&buffer);
1214*ef5ccd6cSJohn Marino       len_avail = 0;
1215*ef5ccd6cSJohn Marino       buf = NULL;
1216*ef5ccd6cSJohn Marino       buffer_init (&buffer);
1217*ef5ccd6cSJohn Marino       buffer_grow_str (&buffer, "<osdata type=\"semaphores\">\n");
1218*ef5ccd6cSJohn Marino 
1219*ef5ccd6cSJohn Marino       fp = fopen ("/proc/sysvipc/sem", "r");
1220*ef5ccd6cSJohn Marino       if (fp)
1221*ef5ccd6cSJohn Marino 	{
1222*ef5ccd6cSJohn Marino 	  char buf[8192];
1223*ef5ccd6cSJohn Marino 
1224*ef5ccd6cSJohn Marino 	  do
1225*ef5ccd6cSJohn Marino 	    {
1226*ef5ccd6cSJohn Marino 	      if (fgets (buf, sizeof (buf), fp))
1227*ef5ccd6cSJohn Marino 		{
1228*ef5ccd6cSJohn Marino 		  key_t key;
1229*ef5ccd6cSJohn Marino 		  uid_t uid, cuid;
1230*ef5ccd6cSJohn Marino 		  gid_t gid, cgid;
1231*ef5ccd6cSJohn Marino 		  unsigned int perms, nsems;
1232*ef5ccd6cSJohn Marino 		  int semid;
1233*ef5ccd6cSJohn Marino 		  TIME_T otime, ctime;
1234*ef5ccd6cSJohn Marino 		  int items_read;
1235*ef5ccd6cSJohn Marino 
1236*ef5ccd6cSJohn Marino 		  items_read = sscanf (buf,
1237*ef5ccd6cSJohn Marino 				       "%d %d %o %u %d %d %d %d %lld %lld",
1238*ef5ccd6cSJohn Marino 				       &key, &semid, &perms, &nsems,
1239*ef5ccd6cSJohn Marino 				       &uid, &gid, &cuid, &cgid,
1240*ef5ccd6cSJohn Marino 				       &otime, &ctime);
1241*ef5ccd6cSJohn Marino 
1242*ef5ccd6cSJohn Marino 		  if (items_read == 10)
1243*ef5ccd6cSJohn Marino 		    {
1244*ef5ccd6cSJohn Marino 		      char user[UT_NAMESIZE], group[UT_NAMESIZE];
1245*ef5ccd6cSJohn Marino 		      char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1246*ef5ccd6cSJohn Marino 		      char otime_str[32], ctime_str[32];
1247*ef5ccd6cSJohn Marino 
1248*ef5ccd6cSJohn Marino 		      user_from_uid (user, sizeof (user), uid);
1249*ef5ccd6cSJohn Marino 		      group_from_gid (group, sizeof (group), gid);
1250*ef5ccd6cSJohn Marino 		      user_from_uid (cuser, sizeof (cuser), cuid);
1251*ef5ccd6cSJohn Marino 		      group_from_gid (cgroup, sizeof (cgroup), cgid);
1252*ef5ccd6cSJohn Marino 
1253*ef5ccd6cSJohn Marino 		      time_from_time_t (otime_str, sizeof (otime_str), otime);
1254*ef5ccd6cSJohn Marino 		      time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1255*ef5ccd6cSJohn Marino 
1256*ef5ccd6cSJohn Marino 		      buffer_xml_printf (
1257*ef5ccd6cSJohn Marino 			  &buffer,
1258*ef5ccd6cSJohn Marino 			  "<item>"
1259*ef5ccd6cSJohn Marino 			  "<column name=\"key\">%d</column>"
1260*ef5ccd6cSJohn Marino 			  "<column name=\"semid\">%d</column>"
1261*ef5ccd6cSJohn Marino 			  "<column name=\"permissions\">%o</column>"
1262*ef5ccd6cSJohn Marino 			  "<column name=\"num semaphores\">%u</column>"
1263*ef5ccd6cSJohn Marino 			  "<column name=\"user\">%s</column>"
1264*ef5ccd6cSJohn Marino 			  "<column name=\"group\">%s</column>"
1265*ef5ccd6cSJohn Marino 			  "<column name=\"creator user\">%s</column>"
1266*ef5ccd6cSJohn Marino 			  "<column name=\"creator group\">%s</column>"
1267*ef5ccd6cSJohn Marino 			  "<column name=\"last semop() time\">%s</column>"
1268*ef5ccd6cSJohn Marino 			  "<column name=\"last semctl() time\">%s</column>"
1269*ef5ccd6cSJohn Marino 			  "</item>",
1270*ef5ccd6cSJohn Marino 			  key,
1271*ef5ccd6cSJohn Marino 			  semid,
1272*ef5ccd6cSJohn Marino 			  perms,
1273*ef5ccd6cSJohn Marino 			  nsems,
1274*ef5ccd6cSJohn Marino 			  user,
1275*ef5ccd6cSJohn Marino 			  group,
1276*ef5ccd6cSJohn Marino 			  cuser,
1277*ef5ccd6cSJohn Marino 			  cgroup,
1278*ef5ccd6cSJohn Marino 			  otime_str,
1279*ef5ccd6cSJohn Marino 			  ctime_str);
1280*ef5ccd6cSJohn Marino 		    }
1281*ef5ccd6cSJohn Marino 		}
1282*ef5ccd6cSJohn Marino 	    }
1283*ef5ccd6cSJohn Marino 	  while (!feof (fp));
1284*ef5ccd6cSJohn Marino 
1285*ef5ccd6cSJohn Marino 	  fclose (fp);
1286*ef5ccd6cSJohn Marino 	}
1287*ef5ccd6cSJohn Marino 
1288*ef5ccd6cSJohn Marino       buffer_grow_str0 (&buffer, "</osdata>\n");
1289*ef5ccd6cSJohn Marino       buf = buffer_finish (&buffer);
1290*ef5ccd6cSJohn Marino       len_avail = strlen (buf);
1291*ef5ccd6cSJohn Marino     }
1292*ef5ccd6cSJohn Marino 
1293*ef5ccd6cSJohn Marino   if (offset >= len_avail)
1294*ef5ccd6cSJohn Marino     {
1295*ef5ccd6cSJohn Marino       /* Done.  Get rid of the buffer.  */
1296*ef5ccd6cSJohn Marino       buffer_free (&buffer);
1297*ef5ccd6cSJohn Marino       buf = NULL;
1298*ef5ccd6cSJohn Marino       len_avail = 0;
1299*ef5ccd6cSJohn Marino       return 0;
1300*ef5ccd6cSJohn Marino     }
1301*ef5ccd6cSJohn Marino 
1302*ef5ccd6cSJohn Marino   if (len > len_avail - offset)
1303*ef5ccd6cSJohn Marino     len = len_avail - offset;
1304*ef5ccd6cSJohn Marino   memcpy (readbuf, buf + offset, len);
1305*ef5ccd6cSJohn Marino 
1306*ef5ccd6cSJohn Marino   return len;
1307*ef5ccd6cSJohn Marino }
1308*ef5ccd6cSJohn Marino 
1309*ef5ccd6cSJohn Marino /* Collect data about message queues recorded in /proc and write it
1310*ef5ccd6cSJohn Marino    into READBUF.  */
1311*ef5ccd6cSJohn Marino 
1312*ef5ccd6cSJohn Marino static LONGEST
linux_xfer_osdata_msg(gdb_byte * readbuf,ULONGEST offset,LONGEST len)1313*ef5ccd6cSJohn Marino linux_xfer_osdata_msg (gdb_byte *readbuf,
1314*ef5ccd6cSJohn Marino 		       ULONGEST offset, LONGEST len)
1315*ef5ccd6cSJohn Marino {
1316*ef5ccd6cSJohn Marino   static const char *buf;
1317*ef5ccd6cSJohn Marino   static LONGEST len_avail = -1;
1318*ef5ccd6cSJohn Marino   static struct buffer buffer;
1319*ef5ccd6cSJohn Marino 
1320*ef5ccd6cSJohn Marino   if (offset == 0)
1321*ef5ccd6cSJohn Marino     {
1322*ef5ccd6cSJohn Marino       FILE *fp;
1323*ef5ccd6cSJohn Marino 
1324*ef5ccd6cSJohn Marino       if (len_avail != -1 && len_avail != 0)
1325*ef5ccd6cSJohn Marino 	buffer_free (&buffer);
1326*ef5ccd6cSJohn Marino       len_avail = 0;
1327*ef5ccd6cSJohn Marino       buf = NULL;
1328*ef5ccd6cSJohn Marino       buffer_init (&buffer);
1329*ef5ccd6cSJohn Marino       buffer_grow_str (&buffer, "<osdata type=\"message queues\">\n");
1330*ef5ccd6cSJohn Marino 
1331*ef5ccd6cSJohn Marino       fp = fopen ("/proc/sysvipc/msg", "r");
1332*ef5ccd6cSJohn Marino       if (fp)
1333*ef5ccd6cSJohn Marino 	{
1334*ef5ccd6cSJohn Marino 	  char buf[8192];
1335*ef5ccd6cSJohn Marino 
1336*ef5ccd6cSJohn Marino 	  do
1337*ef5ccd6cSJohn Marino 	    {
1338*ef5ccd6cSJohn Marino 	      if (fgets (buf, sizeof (buf), fp))
1339*ef5ccd6cSJohn Marino 		{
1340*ef5ccd6cSJohn Marino 		  key_t key;
1341*ef5ccd6cSJohn Marino 		  PID_T lspid, lrpid;
1342*ef5ccd6cSJohn Marino 		  uid_t uid, cuid;
1343*ef5ccd6cSJohn Marino 		  gid_t gid, cgid;
1344*ef5ccd6cSJohn Marino 		  unsigned int perms, cbytes, qnum;
1345*ef5ccd6cSJohn Marino 		  int msqid;
1346*ef5ccd6cSJohn Marino 		  TIME_T stime, rtime, ctime;
1347*ef5ccd6cSJohn Marino 		  int items_read;
1348*ef5ccd6cSJohn Marino 
1349*ef5ccd6cSJohn Marino 		  items_read = sscanf (buf,
1350*ef5ccd6cSJohn Marino 				       "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1351*ef5ccd6cSJohn Marino 				       &key, &msqid, &perms, &cbytes, &qnum,
1352*ef5ccd6cSJohn Marino 				       &lspid, &lrpid, &uid, &gid, &cuid, &cgid,
1353*ef5ccd6cSJohn Marino 				       &stime, &rtime, &ctime);
1354*ef5ccd6cSJohn Marino 
1355*ef5ccd6cSJohn Marino 		  if (items_read == 14)
1356*ef5ccd6cSJohn Marino 		    {
1357*ef5ccd6cSJohn Marino 		      char user[UT_NAMESIZE], group[UT_NAMESIZE];
1358*ef5ccd6cSJohn Marino 		      char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1359*ef5ccd6cSJohn Marino 		      char lscmd[32], lrcmd[32];
1360*ef5ccd6cSJohn Marino 		      char stime_str[32], rtime_str[32], ctime_str[32];
1361*ef5ccd6cSJohn Marino 
1362*ef5ccd6cSJohn Marino 		      user_from_uid (user, sizeof (user), uid);
1363*ef5ccd6cSJohn Marino 		      group_from_gid (group, sizeof (group), gid);
1364*ef5ccd6cSJohn Marino 		      user_from_uid (cuser, sizeof (cuser), cuid);
1365*ef5ccd6cSJohn Marino 		      group_from_gid (cgroup, sizeof (cgroup), cgid);
1366*ef5ccd6cSJohn Marino 
1367*ef5ccd6cSJohn Marino 		      command_from_pid (lscmd, sizeof (lscmd), lspid);
1368*ef5ccd6cSJohn Marino 		      command_from_pid (lrcmd, sizeof (lrcmd), lrpid);
1369*ef5ccd6cSJohn Marino 
1370*ef5ccd6cSJohn Marino 		      time_from_time_t (stime_str, sizeof (stime_str), stime);
1371*ef5ccd6cSJohn Marino 		      time_from_time_t (rtime_str, sizeof (rtime_str), rtime);
1372*ef5ccd6cSJohn Marino 		      time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1373*ef5ccd6cSJohn Marino 
1374*ef5ccd6cSJohn Marino 		      buffer_xml_printf (
1375*ef5ccd6cSJohn Marino 			  &buffer,
1376*ef5ccd6cSJohn Marino 			  "<item>"
1377*ef5ccd6cSJohn Marino 			  "<column name=\"key\">%d</column>"
1378*ef5ccd6cSJohn Marino 			  "<column name=\"msqid\">%d</column>"
1379*ef5ccd6cSJohn Marino 			  "<column name=\"permissions\">%o</column>"
1380*ef5ccd6cSJohn Marino 			  "<column name=\"num used bytes\">%u</column>"
1381*ef5ccd6cSJohn Marino 			  "<column name=\"num messages\">%u</column>"
1382*ef5ccd6cSJohn Marino 			  "<column name=\"last msgsnd() command\">%s</column>"
1383*ef5ccd6cSJohn Marino 			  "<column name=\"last msgrcv() command\">%s</column>"
1384*ef5ccd6cSJohn Marino 			  "<column name=\"user\">%s</column>"
1385*ef5ccd6cSJohn Marino 			  "<column name=\"group\">%s</column>"
1386*ef5ccd6cSJohn Marino 			  "<column name=\"creator user\">%s</column>"
1387*ef5ccd6cSJohn Marino 			  "<column name=\"creator group\">%s</column>"
1388*ef5ccd6cSJohn Marino 			  "<column name=\"last msgsnd() time\">%s</column>"
1389*ef5ccd6cSJohn Marino 			  "<column name=\"last msgrcv() time\">%s</column>"
1390*ef5ccd6cSJohn Marino 			  "<column name=\"last msgctl() time\">%s</column>"
1391*ef5ccd6cSJohn Marino 			  "</item>",
1392*ef5ccd6cSJohn Marino 			  key,
1393*ef5ccd6cSJohn Marino 			  msqid,
1394*ef5ccd6cSJohn Marino 			  perms,
1395*ef5ccd6cSJohn Marino 			  cbytes,
1396*ef5ccd6cSJohn Marino 			  qnum,
1397*ef5ccd6cSJohn Marino 			  lscmd,
1398*ef5ccd6cSJohn Marino 			  lrcmd,
1399*ef5ccd6cSJohn Marino 			  user,
1400*ef5ccd6cSJohn Marino 			  group,
1401*ef5ccd6cSJohn Marino 			  cuser,
1402*ef5ccd6cSJohn Marino 			  cgroup,
1403*ef5ccd6cSJohn Marino 			  stime_str,
1404*ef5ccd6cSJohn Marino 			  rtime_str,
1405*ef5ccd6cSJohn Marino 			  ctime_str);
1406*ef5ccd6cSJohn Marino 		    }
1407*ef5ccd6cSJohn Marino 		}
1408*ef5ccd6cSJohn Marino 	    }
1409*ef5ccd6cSJohn Marino 	  while (!feof (fp));
1410*ef5ccd6cSJohn Marino 
1411*ef5ccd6cSJohn Marino 	  fclose (fp);
1412*ef5ccd6cSJohn Marino 	}
1413*ef5ccd6cSJohn Marino 
1414*ef5ccd6cSJohn Marino       buffer_grow_str0 (&buffer, "</osdata>\n");
1415*ef5ccd6cSJohn Marino       buf = buffer_finish (&buffer);
1416*ef5ccd6cSJohn Marino       len_avail = strlen (buf);
1417*ef5ccd6cSJohn Marino     }
1418*ef5ccd6cSJohn Marino 
1419*ef5ccd6cSJohn Marino   if (offset >= len_avail)
1420*ef5ccd6cSJohn Marino     {
1421*ef5ccd6cSJohn Marino       /* Done.  Get rid of the buffer.  */
1422*ef5ccd6cSJohn Marino       buffer_free (&buffer);
1423*ef5ccd6cSJohn Marino       buf = NULL;
1424*ef5ccd6cSJohn Marino       len_avail = 0;
1425*ef5ccd6cSJohn Marino       return 0;
1426*ef5ccd6cSJohn Marino     }
1427*ef5ccd6cSJohn Marino 
1428*ef5ccd6cSJohn Marino   if (len > len_avail - offset)
1429*ef5ccd6cSJohn Marino     len = len_avail - offset;
1430*ef5ccd6cSJohn Marino   memcpy (readbuf, buf + offset, len);
1431*ef5ccd6cSJohn Marino 
1432*ef5ccd6cSJohn Marino   return len;
1433*ef5ccd6cSJohn Marino }
1434*ef5ccd6cSJohn Marino 
1435*ef5ccd6cSJohn Marino /* Collect data about loaded kernel modules and write it into
1436*ef5ccd6cSJohn Marino    READBUF.  */
1437*ef5ccd6cSJohn Marino 
1438*ef5ccd6cSJohn Marino static LONGEST
linux_xfer_osdata_modules(gdb_byte * readbuf,ULONGEST offset,LONGEST len)1439*ef5ccd6cSJohn Marino linux_xfer_osdata_modules (gdb_byte *readbuf,
1440*ef5ccd6cSJohn Marino 			   ULONGEST offset, LONGEST len)
1441*ef5ccd6cSJohn Marino {
1442*ef5ccd6cSJohn Marino   static const char *buf;
1443*ef5ccd6cSJohn Marino   static LONGEST len_avail = -1;
1444*ef5ccd6cSJohn Marino   static struct buffer buffer;
1445*ef5ccd6cSJohn Marino 
1446*ef5ccd6cSJohn Marino   if (offset == 0)
1447*ef5ccd6cSJohn Marino     {
1448*ef5ccd6cSJohn Marino       FILE *fp;
1449*ef5ccd6cSJohn Marino 
1450*ef5ccd6cSJohn Marino       if (len_avail != -1 && len_avail != 0)
1451*ef5ccd6cSJohn Marino 	buffer_free (&buffer);
1452*ef5ccd6cSJohn Marino       len_avail = 0;
1453*ef5ccd6cSJohn Marino       buf = NULL;
1454*ef5ccd6cSJohn Marino       buffer_init (&buffer);
1455*ef5ccd6cSJohn Marino       buffer_grow_str (&buffer, "<osdata type=\"modules\">\n");
1456*ef5ccd6cSJohn Marino 
1457*ef5ccd6cSJohn Marino       fp = fopen ("/proc/modules", "r");
1458*ef5ccd6cSJohn Marino       if (fp)
1459*ef5ccd6cSJohn Marino 	{
1460*ef5ccd6cSJohn Marino 	  char buf[8192];
1461*ef5ccd6cSJohn Marino 
1462*ef5ccd6cSJohn Marino 	  do
1463*ef5ccd6cSJohn Marino 	    {
1464*ef5ccd6cSJohn Marino 	      if (fgets (buf, sizeof (buf), fp))
1465*ef5ccd6cSJohn Marino 		{
1466*ef5ccd6cSJohn Marino 		  char name[64], dependencies[256], status[16];
1467*ef5ccd6cSJohn Marino 		  unsigned int size;
1468*ef5ccd6cSJohn Marino 		  unsigned long long address;
1469*ef5ccd6cSJohn Marino 		  int uses;
1470*ef5ccd6cSJohn Marino 		  int items_read;
1471*ef5ccd6cSJohn Marino 
1472*ef5ccd6cSJohn Marino 		  items_read = sscanf (buf,
1473*ef5ccd6cSJohn Marino 				       "%64s %d %d %256s %16s 0x%llx",
1474*ef5ccd6cSJohn Marino 				       name, &size, &uses,
1475*ef5ccd6cSJohn Marino 				       dependencies, status, &address);
1476*ef5ccd6cSJohn Marino 
1477*ef5ccd6cSJohn Marino 		  if (items_read == 6)
1478*ef5ccd6cSJohn Marino 		    buffer_xml_printf (
1479*ef5ccd6cSJohn Marino 			&buffer,
1480*ef5ccd6cSJohn Marino 			"<item>"
1481*ef5ccd6cSJohn Marino 			"<column name=\"name\">%s</column>"
1482*ef5ccd6cSJohn Marino 			"<column name=\"size\">%u</column>"
1483*ef5ccd6cSJohn Marino 			"<column name=\"num uses\">%d</column>"
1484*ef5ccd6cSJohn Marino 			"<column name=\"dependencies\">%s</column>"
1485*ef5ccd6cSJohn Marino 			"<column name=\"status\">%s</column>"
1486*ef5ccd6cSJohn Marino 			"<column name=\"address\">%llx</column>"
1487*ef5ccd6cSJohn Marino 			"</item>",
1488*ef5ccd6cSJohn Marino 			name,
1489*ef5ccd6cSJohn Marino 			size,
1490*ef5ccd6cSJohn Marino 			uses,
1491*ef5ccd6cSJohn Marino 			dependencies,
1492*ef5ccd6cSJohn Marino 			status,
1493*ef5ccd6cSJohn Marino 			address);
1494*ef5ccd6cSJohn Marino 		}
1495*ef5ccd6cSJohn Marino 	    }
1496*ef5ccd6cSJohn Marino 	  while (!feof (fp));
1497*ef5ccd6cSJohn Marino 
1498*ef5ccd6cSJohn Marino 	  fclose (fp);
1499*ef5ccd6cSJohn Marino 	}
1500*ef5ccd6cSJohn Marino 
1501*ef5ccd6cSJohn Marino       buffer_grow_str0 (&buffer, "</osdata>\n");
1502*ef5ccd6cSJohn Marino       buf = buffer_finish (&buffer);
1503*ef5ccd6cSJohn Marino       len_avail = strlen (buf);
1504*ef5ccd6cSJohn Marino     }
1505*ef5ccd6cSJohn Marino 
1506*ef5ccd6cSJohn Marino   if (offset >= len_avail)
1507*ef5ccd6cSJohn Marino     {
1508*ef5ccd6cSJohn Marino       /* Done.  Get rid of the buffer.  */
1509*ef5ccd6cSJohn Marino       buffer_free (&buffer);
1510*ef5ccd6cSJohn Marino       buf = NULL;
1511*ef5ccd6cSJohn Marino       len_avail = 0;
1512*ef5ccd6cSJohn Marino       return 0;
1513*ef5ccd6cSJohn Marino     }
1514*ef5ccd6cSJohn Marino 
1515*ef5ccd6cSJohn Marino   if (len > len_avail - offset)
1516*ef5ccd6cSJohn Marino     len = len_avail - offset;
1517*ef5ccd6cSJohn Marino   memcpy (readbuf, buf + offset, len);
1518*ef5ccd6cSJohn Marino 
1519*ef5ccd6cSJohn Marino   return len;
1520*ef5ccd6cSJohn Marino }
1521*ef5ccd6cSJohn Marino 
1522a45ae5f8SJohn Marino struct osdata_type {
1523a45ae5f8SJohn Marino   char *type;
1524*ef5ccd6cSJohn Marino   char *title;
1525a45ae5f8SJohn Marino   char *description;
1526a45ae5f8SJohn Marino   LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, LONGEST len);
1527a45ae5f8SJohn Marino } osdata_table[] = {
1528*ef5ccd6cSJohn Marino   { "processes", "Processes", "Listing of all processes",
1529*ef5ccd6cSJohn Marino     linux_xfer_osdata_processes },
1530*ef5ccd6cSJohn Marino   { "procgroups", "Process groups", "Listing of all process groups",
1531*ef5ccd6cSJohn Marino     linux_xfer_osdata_processgroups },
1532*ef5ccd6cSJohn Marino   { "threads", "Threads", "Listing of all threads",
1533*ef5ccd6cSJohn Marino     linux_xfer_osdata_threads },
1534*ef5ccd6cSJohn Marino   { "files", "File descriptors", "Listing of all file descriptors",
1535*ef5ccd6cSJohn Marino     linux_xfer_osdata_fds },
1536*ef5ccd6cSJohn Marino   { "sockets", "Sockets", "Listing of all internet-domain sockets",
1537*ef5ccd6cSJohn Marino     linux_xfer_osdata_isockets },
1538*ef5ccd6cSJohn Marino   { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1539*ef5ccd6cSJohn Marino     linux_xfer_osdata_shm },
1540*ef5ccd6cSJohn Marino   { "semaphores", "Semaphores", "Listing of all semaphores",
1541*ef5ccd6cSJohn Marino     linux_xfer_osdata_sem },
1542*ef5ccd6cSJohn Marino   { "msg", "Message queues", "Listing of all message queues",
1543*ef5ccd6cSJohn Marino     linux_xfer_osdata_msg },
1544*ef5ccd6cSJohn Marino   { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1545*ef5ccd6cSJohn Marino     linux_xfer_osdata_modules },
1546a45ae5f8SJohn Marino   { NULL, NULL, NULL }
1547a45ae5f8SJohn Marino };
1548a45ae5f8SJohn Marino 
1549a45ae5f8SJohn Marino LONGEST
linux_common_xfer_osdata(const char * annex,gdb_byte * readbuf,ULONGEST offset,LONGEST len)1550a45ae5f8SJohn Marino linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
1551a45ae5f8SJohn Marino 			  ULONGEST offset, LONGEST len)
1552a45ae5f8SJohn Marino {
1553a45ae5f8SJohn Marino   if (!annex || *annex == '\0')
1554a45ae5f8SJohn Marino     {
1555a45ae5f8SJohn Marino       static const char *buf;
1556a45ae5f8SJohn Marino       static LONGEST len_avail = -1;
1557a45ae5f8SJohn Marino       static struct buffer buffer;
1558a45ae5f8SJohn Marino 
1559a45ae5f8SJohn Marino       if (offset == 0)
1560a45ae5f8SJohn Marino 	{
1561a45ae5f8SJohn Marino 	  int i;
1562a45ae5f8SJohn Marino 
1563a45ae5f8SJohn Marino 	  if (len_avail != -1 && len_avail != 0)
1564a45ae5f8SJohn Marino 	    buffer_free (&buffer);
1565a45ae5f8SJohn Marino 	  len_avail = 0;
1566a45ae5f8SJohn Marino 	  buf = NULL;
1567a45ae5f8SJohn Marino 	  buffer_init (&buffer);
1568a45ae5f8SJohn Marino 	  buffer_grow_str (&buffer, "<osdata type=\"types\">\n");
1569a45ae5f8SJohn Marino 
1570a45ae5f8SJohn Marino 	  for (i = 0; osdata_table[i].type; ++i)
1571a45ae5f8SJohn Marino 	    buffer_xml_printf (
1572a45ae5f8SJohn Marino 			       &buffer,
1573a45ae5f8SJohn Marino 			       "<item>"
1574a45ae5f8SJohn Marino 			       "<column name=\"Type\">%s</column>"
1575a45ae5f8SJohn Marino 			       "<column name=\"Description\">%s</column>"
1576*ef5ccd6cSJohn Marino 			       "<column name=\"Title\">%s</column>"
1577a45ae5f8SJohn Marino 			       "</item>",
1578a45ae5f8SJohn Marino 			       osdata_table[i].type,
1579*ef5ccd6cSJohn Marino 			       osdata_table[i].description,
1580*ef5ccd6cSJohn Marino 			       osdata_table[i].title);
1581a45ae5f8SJohn Marino 
1582a45ae5f8SJohn Marino 	  buffer_grow_str0 (&buffer, "</osdata>\n");
1583a45ae5f8SJohn Marino 	  buf = buffer_finish (&buffer);
1584a45ae5f8SJohn Marino 	  len_avail = strlen (buf);
1585a45ae5f8SJohn Marino 	}
1586a45ae5f8SJohn Marino 
1587a45ae5f8SJohn Marino       if (offset >= len_avail)
1588a45ae5f8SJohn Marino 	{
1589a45ae5f8SJohn Marino 	  /* Done.  Get rid of the buffer.  */
1590a45ae5f8SJohn Marino 	  buffer_free (&buffer);
1591a45ae5f8SJohn Marino 	  buf = NULL;
1592a45ae5f8SJohn Marino 	  len_avail = 0;
1593a45ae5f8SJohn Marino 	  return 0;
1594a45ae5f8SJohn Marino 	}
1595a45ae5f8SJohn Marino 
1596a45ae5f8SJohn Marino       if (len > len_avail - offset)
1597a45ae5f8SJohn Marino 	len = len_avail - offset;
1598a45ae5f8SJohn Marino       memcpy (readbuf, buf + offset, len);
1599a45ae5f8SJohn Marino 
1600a45ae5f8SJohn Marino       return len;
1601a45ae5f8SJohn Marino     }
1602a45ae5f8SJohn Marino   else
1603a45ae5f8SJohn Marino     {
1604a45ae5f8SJohn Marino       int i;
1605a45ae5f8SJohn Marino 
1606a45ae5f8SJohn Marino       for (i = 0; osdata_table[i].type; ++i)
1607a45ae5f8SJohn Marino 	{
1608a45ae5f8SJohn Marino 	  if (strcmp (annex, osdata_table[i].type) == 0)
1609a45ae5f8SJohn Marino 	    {
1610a45ae5f8SJohn Marino 	      gdb_assert (readbuf);
1611a45ae5f8SJohn Marino 
1612a45ae5f8SJohn Marino 	      return (osdata_table[i].getter) (readbuf, offset, len);
1613a45ae5f8SJohn Marino 	    }
1614a45ae5f8SJohn Marino 	}
1615a45ae5f8SJohn Marino 
1616a45ae5f8SJohn Marino       return 0;
1617a45ae5f8SJohn Marino     }
1618a45ae5f8SJohn Marino }
1619a45ae5f8SJohn Marino 
1620