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