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