packaging: Add python3-base dependency
[platform/upstream/gdb.git] / gdb / nat / linux-osdata.c
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
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   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
105 static void
106 command_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
140 static char *
141 commandline_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
195 static void
196 user_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
216 static int
217 get_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
236 static int
237 get_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
276 static gdb::optional<size_t>
277 get_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
322 static size_t
323 get_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
336 static std::string
337 linux_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
413 struct 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
450 static std::string
451 linux_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
521 static std::string
522 linux_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
603 static std::string
604 linux_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
671 static std::string
672 linux_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
756 static const char *
757 format_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
803 union 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
815 static void
816 print_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
946 static std::string
947 linux_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
964 static void
965 time_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
985 static void
986 group_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
1003 static std::string
1004 linux_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
1099 static std::string
1100 linux_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
1179 static std::string
1180 linux_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
1273 static std::string
1274 linux_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
1347 static std::string linux_xfer_osdata_info_os_types ();
1348
1349 static 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
1383 static std::string
1384 linux_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
1409 static LONGEST
1410 common_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
1432 LONGEST
1433 linux_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 }