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