]> Git Repo - binutils.git/blob - gdb/nat/linux-osdata.c
Automatic date update in version.in
[binutils.git] / gdb / nat / linux-osdata.c
1 /* Linux-specific functions to retrieve OS data.
2
3    Copyright (C) 2009-2022 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 void
337 linux_xfer_osdata_processes (struct buffer *buffer)
338 {
339   DIR *dirp;
340
341   buffer_grow_str (buffer, "<osdata type=\"processes\">\n");
342
343   dirp = opendir ("/proc");
344   if (dirp)
345     {
346       const int core_array_size = get_core_array_size ();
347       struct dirent *dp;
348
349       while ((dp = readdir (dirp)) != NULL)
350         {
351           PID_T pid;
352           uid_t owner;
353           char user[UT_NAMESIZE];
354           char *command_line;
355           int *cores;
356           int task_count;
357           std::string cores_str;
358           int i;
359
360           if (!isdigit (dp->d_name[0])
361               || NAMELEN (dp) > MAX_PID_T_STRLEN)
362             continue;
363
364           sscanf (dp->d_name, "%lld", &pid);
365           command_line = commandline_from_pid (pid);
366
367           if (get_process_owner (&owner, pid) == 0)
368             user_from_uid (user, sizeof (user), owner);
369           else
370             strcpy (user, "?");
371
372           /* Find CPU cores used by the process.  */
373           cores = XCNEWVEC (int, core_array_size);
374           task_count = get_cores_used_by_process (pid, cores, core_array_size);
375
376           for (i = 0; i < core_array_size && task_count > 0; ++i)
377             if (cores[i])
378               {
379                 string_appendf (cores_str, "%d", i);
380
381                 task_count -= cores[i];
382                 if (task_count > 0)
383                   cores_str += ",";
384               }
385
386           xfree (cores);
387
388           buffer_xml_printf
389             (buffer,
390              "<item>"
391              "<column name=\"pid\">%lld</column>"
392              "<column name=\"user\">%s</column>"
393              "<column name=\"command\">%s</column>"
394              "<column name=\"cores\">%s</column>"
395              "</item>",
396              pid,
397              user,
398              command_line ? command_line : "",
399              cores_str.c_str());
400
401           xfree (command_line);
402         }
403
404       closedir (dirp);
405     }
406
407   buffer_grow_str0 (buffer, "</osdata>\n");
408 }
409
410 /* A simple PID/PGID pair.  */
411
412 struct pid_pgid_entry
413 {
414   pid_pgid_entry (PID_T pid_, PID_T pgid_)
415   : pid (pid_), pgid (pgid_)
416   {}
417
418   /* Return true if this pid is the leader of its process group.  */
419
420   bool is_leader () const
421   {
422     return pid == pgid;
423   }
424
425   bool operator< (const pid_pgid_entry &other) const
426   {
427     /* Sort by PGID.  */
428     if (this->pgid != other.pgid)
429       return this->pgid < other.pgid;
430
431     /* Process group leaders always come first...  */
432     if (this->is_leader ())
433       {
434         if (!other.is_leader ())
435           return true;
436       }
437     else if (other.is_leader ())
438       return false;
439
440     /* ...else sort by PID.  */
441     return this->pid < other.pid;
442   }
443
444   PID_T pid, pgid;
445 };
446
447 /* Collect all process groups from /proc in BUFFER.  */
448
449 static void
450 linux_xfer_osdata_processgroups (struct buffer *buffer)
451 {
452   DIR *dirp;
453
454   buffer_grow_str (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           buffer_xml_printf
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_grow_str0 (buffer, "</osdata>\n");
514 }
515
516 /* Collect all the threads in /proc by iterating through processes and
517    then tasks within each process in BUFFER.  */
518
519 static void
520 linux_xfer_osdata_threads (struct buffer *buffer)
521 {
522   DIR *dirp;
523
524   buffer_grow_str (buffer, "<osdata type=\"threads\">\n");
525
526   dirp = opendir ("/proc");
527   if (dirp)
528     {
529       struct dirent *dp;
530
531       while ((dp = readdir (dirp)) != NULL)
532         {
533           struct stat statbuf;
534           char procentry[sizeof ("/proc/4294967295")];
535
536           if (!isdigit (dp->d_name[0])
537               || NAMELEN (dp) > sizeof ("4294967295") - 1)
538             continue;
539
540           xsnprintf (procentry, sizeof (procentry), "/proc/%s",
541                      dp->d_name);
542           if (stat (procentry, &statbuf) == 0
543               && S_ISDIR (statbuf.st_mode))
544             {
545               DIR *dirp2;
546               PID_T pid;
547               char command[32];
548
549               std::string pathname
550                 = string_printf ("/proc/%s/task", dp->d_name);
551
552               pid = atoi (dp->d_name);
553               command_from_pid (command, sizeof (command), pid);
554
555               dirp2 = opendir (pathname.c_str ());
556
557               if (dirp2)
558                 {
559                   struct dirent *dp2;
560
561                   while ((dp2 = readdir (dirp2)) != NULL)
562                     {
563                       PID_T tid;
564                       int core;
565
566                       if (!isdigit (dp2->d_name[0])
567                           || NAMELEN (dp2) > sizeof ("4294967295") - 1)
568                         continue;
569
570                       tid = atoi (dp2->d_name);
571                       core = linux_common_core_of_thread (ptid_t (pid, tid));
572
573                       buffer_xml_printf
574                         (buffer,
575                          "<item>"
576                          "<column name=\"pid\">%lld</column>"
577                          "<column name=\"command\">%s</column>"
578                          "<column name=\"tid\">%lld</column>"
579                          "<column name=\"core\">%d</column>"
580                          "</item>",
581                          pid,
582                          command,
583                          tid,
584                          core);
585                     }
586
587                   closedir (dirp2);
588                 }
589             }
590         }
591
592       closedir (dirp);
593     }
594
595   buffer_grow_str0 (buffer, "</osdata>\n");
596 }
597
598 /* Collect data about the cpus/cores on the system in BUFFER.  */
599
600 static void
601 linux_xfer_osdata_cpus (struct buffer *buffer)
602 {
603   int first_item = 1;
604
605   buffer_grow_str (buffer, "<osdata type=\"cpus\">\n");
606
607   gdb_file_up fp = gdb_fopen_cloexec ("/proc/cpuinfo", "r");
608   if (fp != NULL)
609     {
610       char buf[8192];
611
612       do
613         {
614           if (fgets (buf, sizeof (buf), fp.get ()))
615             {
616               char *key, *value;
617               int i = 0;
618
619               char *saveptr;
620               key = strtok_r (buf, ":", &saveptr);
621               if (key == NULL)
622                 continue;
623
624               value = strtok_r (NULL, ":", &saveptr);
625               if (value == NULL)
626                 continue;
627
628               while (key[i] != '\t' && key[i] != '\0')
629                 i++;
630
631               key[i] = '\0';
632
633               i = 0;
634               while (value[i] != '\t' && value[i] != '\0')
635                 i++;
636
637               value[i] = '\0';
638
639               if (strcmp (key, "processor") == 0)
640                 {
641                   if (first_item)
642                     buffer_grow_str (buffer, "<item>");
643                   else
644                     buffer_grow_str (buffer, "</item><item>");
645
646                   first_item = 0;
647                 }
648
649               buffer_xml_printf (buffer,
650                                  "<column name=\"%s\">%s</column>",
651                                  key,
652                                  value);
653             }
654         }
655       while (!feof (fp.get ()));
656
657       if (first_item == 0)
658         buffer_grow_str (buffer, "</item>");
659     }
660
661   buffer_grow_str0 (buffer, "</osdata>\n");
662 }
663
664 /* Collect all the open file descriptors found in /proc and put the details
665    found about them into BUFFER.  */
666
667 static void
668 linux_xfer_osdata_fds (struct buffer *buffer)
669 {
670   DIR *dirp;
671
672   buffer_grow_str (buffer, "<osdata type=\"files\">\n");
673
674   dirp = opendir ("/proc");
675   if (dirp)
676     {
677       struct dirent *dp;
678
679       while ((dp = readdir (dirp)) != NULL)
680         {
681           struct stat statbuf;
682           char procentry[sizeof ("/proc/4294967295")];
683
684           if (!isdigit (dp->d_name[0])
685               || NAMELEN (dp) > sizeof ("4294967295") - 1)
686             continue;
687
688           xsnprintf (procentry, sizeof (procentry), "/proc/%s",
689                      dp->d_name);
690           if (stat (procentry, &statbuf) == 0
691               && S_ISDIR (statbuf.st_mode))
692             {
693               DIR *dirp2;
694               PID_T pid;
695               char command[32];
696
697               pid = atoi (dp->d_name);
698               command_from_pid (command, sizeof (command), pid);
699
700               std::string pathname
701                 = string_printf ("/proc/%s/fd", dp->d_name);
702               dirp2 = opendir (pathname.c_str ());
703
704               if (dirp2)
705                 {
706                   struct dirent *dp2;
707
708                   while ((dp2 = readdir (dirp2)) != NULL)
709                     {
710                       char buf[1000];
711                       ssize_t rslt;
712
713                       if (!isdigit (dp2->d_name[0]))
714                         continue;
715
716                       std::string fdname
717                         = string_printf ("%s/%s", pathname.c_str (),
718                                          dp2->d_name);
719                       rslt = readlink (fdname.c_str (), buf,
720                                        sizeof (buf) - 1);
721                       if (rslt >= 0)
722                         buf[rslt] = '\0';
723
724                       buffer_xml_printf
725                         (buffer,
726                          "<item>"
727                          "<column name=\"pid\">%s</column>"
728                          "<column name=\"command\">%s</column>"
729                          "<column name=\"file descriptor\">%s</column>"
730                          "<column name=\"name\">%s</column>"
731                          "</item>",
732                          dp->d_name,
733                          command,
734                          dp2->d_name,
735                          (rslt >= 0 ? buf : dp2->d_name));
736                     }
737
738                   closedir (dirp2);
739                 }
740             }
741         }
742
743       closedir (dirp);
744     }
745
746   buffer_grow_str0 (buffer, "</osdata>\n");
747 }
748
749 /* Returns the socket state STATE in textual form.  */
750
751 static const char *
752 format_socket_state (unsigned char state)
753 {
754   /* Copied from include/net/tcp_states.h in the Linux kernel sources.  */
755   enum {
756     TCP_ESTABLISHED = 1,
757     TCP_SYN_SENT,
758     TCP_SYN_RECV,
759     TCP_FIN_WAIT1,
760     TCP_FIN_WAIT2,
761     TCP_TIME_WAIT,
762     TCP_CLOSE,
763     TCP_CLOSE_WAIT,
764     TCP_LAST_ACK,
765     TCP_LISTEN,
766     TCP_CLOSING
767   };
768
769   switch (state)
770     {
771     case TCP_ESTABLISHED:
772       return "ESTABLISHED";
773     case TCP_SYN_SENT:
774       return "SYN_SENT";
775     case TCP_SYN_RECV:
776       return "SYN_RECV";
777     case TCP_FIN_WAIT1:
778       return "FIN_WAIT1";
779     case TCP_FIN_WAIT2:
780       return "FIN_WAIT2";
781     case TCP_TIME_WAIT:
782       return "TIME_WAIT";
783     case TCP_CLOSE:
784       return "CLOSE";
785     case TCP_CLOSE_WAIT:
786       return "CLOSE_WAIT";
787     case TCP_LAST_ACK:
788       return "LAST_ACK";
789     case TCP_LISTEN:
790       return "LISTEN";
791     case TCP_CLOSING:
792       return "CLOSING";
793     default:
794       return "(unknown)";
795     }
796 }
797
798 union socket_addr
799   {
800     struct sockaddr sa;
801     struct sockaddr_in sin;
802     struct sockaddr_in6 sin6;
803   };
804
805 /* Auxiliary function used by linux_xfer_osdata_isocket.  Formats
806    information for all open internet sockets of type FAMILY on the
807    system into BUFFER.  If TCP is set, only TCP sockets are processed,
808    otherwise only UDP sockets are processed.  */
809
810 static void
811 print_sockets (unsigned short family, int tcp, struct buffer *buffer)
812 {
813   const char *proc_file;
814
815   if (family == AF_INET)
816     proc_file = tcp ? "/proc/net/tcp" : "/proc/net/udp";
817   else if (family == AF_INET6)
818     proc_file = tcp ? "/proc/net/tcp6" : "/proc/net/udp6";
819   else
820     return;
821
822   gdb_file_up fp = gdb_fopen_cloexec (proc_file, "r");
823   if (fp)
824     {
825       char buf[8192];
826
827       do
828         {
829           if (fgets (buf, sizeof (buf), fp.get ()))
830             {
831               uid_t uid;
832               unsigned int local_port, remote_port, state;
833               char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
834               int result;
835
836 #if NI_MAXHOST <= 32
837 #error "local_address and remote_address buffers too small"
838 #endif
839
840               result = sscanf (buf,
841                                "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
842                                local_address, &local_port,
843                                remote_address, &remote_port,
844                                &state,
845                                &uid);
846
847               if (result == 6)
848                 {
849                   union socket_addr locaddr, remaddr;
850                   size_t addr_size;
851                   char user[UT_NAMESIZE];
852                   char local_service[NI_MAXSERV], remote_service[NI_MAXSERV];
853
854                   if (family == AF_INET)
855                     {
856                       sscanf (local_address, "%X",
857                               &locaddr.sin.sin_addr.s_addr);
858                       sscanf (remote_address, "%X",
859                               &remaddr.sin.sin_addr.s_addr);
860
861                       locaddr.sin.sin_port = htons (local_port);
862                       remaddr.sin.sin_port = htons (remote_port);
863
864                       addr_size = sizeof (struct sockaddr_in);
865                     }
866                   else
867                     {
868                       sscanf (local_address, "%8X%8X%8X%8X",
869                               locaddr.sin6.sin6_addr.s6_addr32,
870                               locaddr.sin6.sin6_addr.s6_addr32 + 1,
871                               locaddr.sin6.sin6_addr.s6_addr32 + 2,
872                               locaddr.sin6.sin6_addr.s6_addr32 + 3);
873                       sscanf (remote_address, "%8X%8X%8X%8X",
874                               remaddr.sin6.sin6_addr.s6_addr32,
875                               remaddr.sin6.sin6_addr.s6_addr32 + 1,
876                               remaddr.sin6.sin6_addr.s6_addr32 + 2,
877                               remaddr.sin6.sin6_addr.s6_addr32 + 3);
878
879                       locaddr.sin6.sin6_port = htons (local_port);
880                       remaddr.sin6.sin6_port = htons (remote_port);
881
882                       locaddr.sin6.sin6_flowinfo = 0;
883                       remaddr.sin6.sin6_flowinfo = 0;
884                       locaddr.sin6.sin6_scope_id = 0;
885                       remaddr.sin6.sin6_scope_id = 0;
886
887                       addr_size = sizeof (struct sockaddr_in6);
888                     }
889
890                   locaddr.sa.sa_family = remaddr.sa.sa_family = family;
891
892                   result = getnameinfo (&locaddr.sa, addr_size,
893                                         local_address, sizeof (local_address),
894                                         local_service, sizeof (local_service),
895                                         NI_NUMERICHOST | NI_NUMERICSERV
896                                         | (tcp ? 0 : NI_DGRAM));
897                   if (result)
898                     continue;
899
900                   result = getnameinfo (&remaddr.sa, addr_size,
901                                         remote_address,
902                                         sizeof (remote_address),
903                                         remote_service,
904                                         sizeof (remote_service),
905                                         NI_NUMERICHOST | NI_NUMERICSERV
906                                         | (tcp ? 0 : NI_DGRAM));
907                   if (result)
908                     continue;
909
910                   user_from_uid (user, sizeof (user), uid);
911
912                   buffer_xml_printf (
913                       buffer,
914                       "<item>"
915                       "<column name=\"local address\">%s</column>"
916                       "<column name=\"local port\">%s</column>"
917                       "<column name=\"remote address\">%s</column>"
918                       "<column name=\"remote port\">%s</column>"
919                       "<column name=\"state\">%s</column>"
920                       "<column name=\"user\">%s</column>"
921                       "<column name=\"family\">%s</column>"
922                       "<column name=\"protocol\">%s</column>"
923                       "</item>",
924                       local_address,
925                       local_service,
926                       remote_address,
927                       remote_service,
928                       format_socket_state (state),
929                       user,
930                       (family == AF_INET) ? "INET" : "INET6",
931                       tcp ? "STREAM" : "DGRAM");
932                 }
933             }
934         }
935       while (!feof (fp.get ()));
936     }
937 }
938
939 /* Collect data about internet sockets and write it into BUFFER.  */
940
941 static void
942 linux_xfer_osdata_isockets (struct buffer *buffer)
943 {
944   buffer_grow_str (buffer, "<osdata type=\"I sockets\">\n");
945
946   print_sockets (AF_INET, 1, buffer);
947   print_sockets (AF_INET, 0, buffer);
948   print_sockets (AF_INET6, 1, buffer);
949   print_sockets (AF_INET6, 0, buffer);
950
951   buffer_grow_str0 (buffer, "</osdata>\n");
952 }
953
954 /* Converts the time SECONDS into textual form and copies it into a
955    buffer TIME, with at most MAXLEN characters copied.  */
956
957 static void
958 time_from_time_t (char *time, int maxlen, TIME_T seconds)
959 {
960   if (!seconds)
961     time[0] = '\0';
962   else
963     {
964       time_t t = (time_t) seconds;
965
966       /* Per the ctime_r manpage, this buffer needs to be at least 26
967          characters long.  */
968       char buf[30];
969       const char *time_str = ctime_r (&t, buf);
970       strncpy (time, time_str, maxlen - 1);
971       time[maxlen - 1] = '\0';
972     }
973 }
974
975 /* Finds the group name for the group GID and copies it into GROUP.
976    At most MAXLEN characters are copied.  */
977
978 static void
979 group_from_gid (char *group, int maxlen, gid_t gid)
980 {
981   struct group *grentry = getgrgid (gid);
982
983   if (grentry)
984     {
985       strncpy (group, grentry->gr_name, maxlen - 1);
986       /* Ensure that the group name is null-terminated.  */
987       group[maxlen - 1] = '\0';
988     }
989   else
990     group[0] = '\0';
991 }
992
993 /* Collect data about shared memory recorded in /proc and write it
994    into BUFFER.  */
995
996 static void
997 linux_xfer_osdata_shm (struct buffer *buffer)
998 {
999   buffer_grow_str (buffer, "<osdata type=\"shared memory\">\n");
1000
1001   gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1002   if (fp)
1003     {
1004       char buf[8192];
1005
1006       do
1007         {
1008           if (fgets (buf, sizeof (buf), fp.get ()))
1009             {
1010               key_t key;
1011               uid_t uid, cuid;
1012               gid_t gid, cgid;
1013               PID_T cpid, lpid;
1014               int shmid, size, nattch;
1015               TIME_T atime, dtime, ctime;
1016               unsigned int perms;
1017               int items_read;
1018
1019               items_read = sscanf (buf,
1020                                    "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1021                                    &key, &shmid, &perms, &size,
1022                                    &cpid, &lpid,
1023                                    &nattch,
1024                                    &uid, &gid, &cuid, &cgid,
1025                                    &atime, &dtime, &ctime);
1026
1027               if (items_read == 14)
1028                 {
1029                   char user[UT_NAMESIZE], group[UT_NAMESIZE];
1030                   char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1031                   char ccmd[32], lcmd[32];
1032                   char atime_str[32], dtime_str[32], ctime_str[32];
1033
1034                   user_from_uid (user, sizeof (user), uid);
1035                   group_from_gid (group, sizeof (group), gid);
1036                   user_from_uid (cuser, sizeof (cuser), cuid);
1037                   group_from_gid (cgroup, sizeof (cgroup), cgid);
1038
1039                   command_from_pid (ccmd, sizeof (ccmd), cpid);
1040                   command_from_pid (lcmd, sizeof (lcmd), lpid);
1041
1042                   time_from_time_t (atime_str, sizeof (atime_str), atime);
1043                   time_from_time_t (dtime_str, sizeof (dtime_str), dtime);
1044                   time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1045
1046                   buffer_xml_printf
1047                     (buffer,
1048                      "<item>"
1049                      "<column name=\"key\">%d</column>"
1050                      "<column name=\"shmid\">%d</column>"
1051                      "<column name=\"permissions\">%o</column>"
1052                      "<column name=\"size\">%d</column>"
1053                      "<column name=\"creator command\">%s</column>"
1054                      "<column name=\"last op. command\">%s</column>"
1055                      "<column name=\"num attached\">%d</column>"
1056                      "<column name=\"user\">%s</column>"
1057                      "<column name=\"group\">%s</column>"
1058                      "<column name=\"creator user\">%s</column>"
1059                      "<column name=\"creator group\">%s</column>"
1060                      "<column name=\"last shmat() time\">%s</column>"
1061                      "<column name=\"last shmdt() time\">%s</column>"
1062                      "<column name=\"last shmctl() time\">%s</column>"
1063                      "</item>",
1064                      key,
1065                      shmid,
1066                      perms,
1067                      size,
1068                      ccmd,
1069                      lcmd,
1070                      nattch,
1071                      user,
1072                      group,
1073                      cuser,
1074                      cgroup,
1075                      atime_str,
1076                      dtime_str,
1077                      ctime_str);
1078                 }
1079             }
1080         }
1081       while (!feof (fp.get ()));
1082     }
1083
1084   buffer_grow_str0 (buffer, "</osdata>\n");
1085 }
1086
1087 /* Collect data about semaphores recorded in /proc and write it
1088    into BUFFER.  */
1089
1090 static void
1091 linux_xfer_osdata_sem (struct buffer *buffer)
1092 {
1093   buffer_grow_str (buffer, "<osdata type=\"semaphores\">\n");
1094
1095   gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1096   if (fp)
1097     {
1098       char buf[8192];
1099
1100       do
1101         {
1102           if (fgets (buf, sizeof (buf), fp.get ()))
1103             {
1104               key_t key;
1105               uid_t uid, cuid;
1106               gid_t gid, cgid;
1107               unsigned int perms, nsems;
1108               int semid;
1109               TIME_T otime, ctime;
1110               int items_read;
1111
1112               items_read = sscanf (buf,
1113                                    "%d %d %o %u %d %d %d %d %lld %lld",
1114                                    &key, &semid, &perms, &nsems,
1115                                    &uid, &gid, &cuid, &cgid,
1116                                    &otime, &ctime);
1117
1118               if (items_read == 10)
1119                 {
1120                   char user[UT_NAMESIZE], group[UT_NAMESIZE];
1121                   char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1122                   char otime_str[32], ctime_str[32];
1123
1124                   user_from_uid (user, sizeof (user), uid);
1125                   group_from_gid (group, sizeof (group), gid);
1126                   user_from_uid (cuser, sizeof (cuser), cuid);
1127                   group_from_gid (cgroup, sizeof (cgroup), cgid);
1128
1129                   time_from_time_t (otime_str, sizeof (otime_str), otime);
1130                   time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1131
1132                   buffer_xml_printf
1133                     (buffer,
1134                      "<item>"
1135                      "<column name=\"key\">%d</column>"
1136                      "<column name=\"semid\">%d</column>"
1137                      "<column name=\"permissions\">%o</column>"
1138                      "<column name=\"num semaphores\">%u</column>"
1139                      "<column name=\"user\">%s</column>"
1140                      "<column name=\"group\">%s</column>"
1141                      "<column name=\"creator user\">%s</column>"
1142                      "<column name=\"creator group\">%s</column>"
1143                      "<column name=\"last semop() time\">%s</column>"
1144                      "<column name=\"last semctl() time\">%s</column>"
1145                      "</item>",
1146                      key,
1147                      semid,
1148                      perms,
1149                      nsems,
1150                      user,
1151                      group,
1152                      cuser,
1153                      cgroup,
1154                      otime_str,
1155                      ctime_str);
1156                 }
1157             }
1158         }
1159       while (!feof (fp.get ()));
1160     }
1161
1162   buffer_grow_str0 (buffer, "</osdata>\n");
1163 }
1164
1165 /* Collect data about message queues recorded in /proc and write it
1166    into BUFFER.  */
1167
1168 static void
1169 linux_xfer_osdata_msg (struct buffer *buffer)
1170 {
1171   buffer_grow_str (buffer, "<osdata type=\"message queues\">\n");
1172
1173   gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1174   if (fp)
1175     {
1176       char buf[8192];
1177
1178       do
1179         {
1180           if (fgets (buf, sizeof (buf), fp.get ()))
1181             {
1182               key_t key;
1183               PID_T lspid, lrpid;
1184               uid_t uid, cuid;
1185               gid_t gid, cgid;
1186               unsigned int perms, cbytes, qnum;
1187               int msqid;
1188               TIME_T stime, rtime, ctime;
1189               int items_read;
1190
1191               items_read = sscanf (buf,
1192                                    "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1193                                    &key, &msqid, &perms, &cbytes, &qnum,
1194                                    &lspid, &lrpid, &uid, &gid, &cuid, &cgid,
1195                                    &stime, &rtime, &ctime);
1196
1197               if (items_read == 14)
1198                 {
1199                   char user[UT_NAMESIZE], group[UT_NAMESIZE];
1200                   char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1201                   char lscmd[32], lrcmd[32];
1202                   char stime_str[32], rtime_str[32], ctime_str[32];
1203
1204                   user_from_uid (user, sizeof (user), uid);
1205                   group_from_gid (group, sizeof (group), gid);
1206                   user_from_uid (cuser, sizeof (cuser), cuid);
1207                   group_from_gid (cgroup, sizeof (cgroup), cgid);
1208
1209                   command_from_pid (lscmd, sizeof (lscmd), lspid);
1210                   command_from_pid (lrcmd, sizeof (lrcmd), lrpid);
1211
1212                   time_from_time_t (stime_str, sizeof (stime_str), stime);
1213                   time_from_time_t (rtime_str, sizeof (rtime_str), rtime);
1214                   time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1215
1216                   buffer_xml_printf
1217                     (buffer,
1218                      "<item>"
1219                      "<column name=\"key\">%d</column>"
1220                      "<column name=\"msqid\">%d</column>"
1221                      "<column name=\"permissions\">%o</column>"
1222                      "<column name=\"num used bytes\">%u</column>"
1223                      "<column name=\"num messages\">%u</column>"
1224                      "<column name=\"last msgsnd() command\">%s</column>"
1225                      "<column name=\"last msgrcv() command\">%s</column>"
1226                      "<column name=\"user\">%s</column>"
1227                      "<column name=\"group\">%s</column>"
1228                      "<column name=\"creator user\">%s</column>"
1229                      "<column name=\"creator group\">%s</column>"
1230                      "<column name=\"last msgsnd() time\">%s</column>"
1231                      "<column name=\"last msgrcv() time\">%s</column>"
1232                      "<column name=\"last msgctl() time\">%s</column>"
1233                      "</item>",
1234                      key,
1235                      msqid,
1236                      perms,
1237                      cbytes,
1238                      qnum,
1239                      lscmd,
1240                      lrcmd,
1241                      user,
1242                      group,
1243                      cuser,
1244                      cgroup,
1245                      stime_str,
1246                      rtime_str,
1247                      ctime_str);
1248                 }
1249             }
1250         }
1251       while (!feof (fp.get ()));
1252     }
1253
1254   buffer_grow_str0 (buffer, "</osdata>\n");
1255 }
1256
1257 /* Collect data about loaded kernel modules and write it into
1258    BUFFER.  */
1259
1260 static void
1261 linux_xfer_osdata_modules (struct buffer *buffer)
1262 {
1263   buffer_grow_str (buffer, "<osdata type=\"modules\">\n");
1264
1265   gdb_file_up fp = gdb_fopen_cloexec ("/proc/modules", "r");
1266   if (fp)
1267     {
1268       char buf[8192];
1269
1270       do
1271         {
1272           if (fgets (buf, sizeof (buf), fp.get ()))
1273             {
1274               char *name, *dependencies, *status, *tmp, *saveptr;
1275               unsigned int size;
1276               unsigned long long address;
1277               int uses;
1278
1279               name = strtok_r (buf, " ", &saveptr);
1280               if (name == NULL)
1281                 continue;
1282
1283               tmp = strtok_r (NULL, " ", &saveptr);
1284               if (tmp == NULL)
1285                 continue;
1286               if (sscanf (tmp, "%u", &size) != 1)
1287                 continue;
1288
1289               tmp = strtok_r (NULL, " ", &saveptr);
1290               if (tmp == NULL)
1291                 continue;
1292               if (sscanf (tmp, "%d", &uses) != 1)
1293                 continue;
1294
1295               dependencies = strtok_r (NULL, " ", &saveptr);
1296               if (dependencies == NULL)
1297                 continue;
1298
1299               status = strtok_r (NULL, " ", &saveptr);
1300               if (status == NULL)
1301                 continue;
1302
1303               tmp = strtok_r (NULL, "\n", &saveptr);
1304               if (tmp == NULL)
1305                 continue;
1306               if (sscanf (tmp, "%llx", &address) != 1)
1307                 continue;
1308
1309               buffer_xml_printf (buffer,
1310                                  "<item>"
1311                                  "<column name=\"name\">%s</column>"
1312                                  "<column name=\"size\">%u</column>"
1313                                  "<column name=\"num uses\">%d</column>"
1314                                  "<column name=\"dependencies\">%s</column>"
1315                                  "<column name=\"status\">%s</column>"
1316                                  "<column name=\"address\">%llx</column>"
1317                                  "</item>",
1318                                  name,
1319                                  size,
1320                                  uses,
1321                                  dependencies,
1322                                  status,
1323                                  address);
1324             }
1325         }
1326       while (!feof (fp.get ()));
1327     }
1328
1329   buffer_grow_str0 (buffer, "</osdata>\n");
1330 }
1331
1332 static void linux_xfer_osdata_info_os_types (struct buffer *buffer);
1333
1334 static struct osdata_type {
1335   const char *type;
1336   const char *title;
1337   const char *description;
1338   void (*take_snapshot) (struct buffer *buffer);
1339   LONGEST len_avail;
1340   struct buffer buffer;
1341 } osdata_table[] = {
1342   { "types", "Types", "Listing of info os types you can list",
1343     linux_xfer_osdata_info_os_types, -1 },
1344   { "cpus", "CPUs", "Listing of all cpus/cores on the system",
1345     linux_xfer_osdata_cpus, -1 },
1346   { "files", "File descriptors", "Listing of all file descriptors",
1347     linux_xfer_osdata_fds, -1 },
1348   { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1349     linux_xfer_osdata_modules, -1 },
1350   { "msg", "Message queues", "Listing of all message queues",
1351     linux_xfer_osdata_msg, -1 },
1352   { "processes", "Processes", "Listing of all processes",
1353     linux_xfer_osdata_processes, -1 },
1354   { "procgroups", "Process groups", "Listing of all process groups",
1355     linux_xfer_osdata_processgroups, -1 },
1356   { "semaphores", "Semaphores", "Listing of all semaphores",
1357     linux_xfer_osdata_sem, -1 },
1358   { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1359     linux_xfer_osdata_shm, -1 },
1360   { "sockets", "Sockets", "Listing of all internet-domain sockets",
1361     linux_xfer_osdata_isockets, -1 },
1362   { "threads", "Threads", "Listing of all threads",
1363   linux_xfer_osdata_threads, -1 },
1364   { NULL, NULL, NULL }
1365 };
1366
1367 /* Collect data about all types info os can show in BUFFER.  */
1368
1369 static void
1370 linux_xfer_osdata_info_os_types (struct buffer *buffer)
1371 {
1372   buffer_grow_str (buffer, "<osdata type=\"types\">\n");
1373
1374   /* Start the below loop at 1, as we do not want to list ourselves.  */
1375   for (int i = 1; osdata_table[i].type; ++i)
1376     buffer_xml_printf (buffer,
1377                        "<item>"
1378                        "<column name=\"Type\">%s</column>"
1379                        "<column name=\"Description\">%s</column>"
1380                        "<column name=\"Title\">%s</column>"
1381                        "</item>",
1382                        osdata_table[i].type,
1383                        osdata_table[i].description,
1384                        osdata_table[i].title);
1385
1386   buffer_grow_str0 (buffer, "</osdata>\n");
1387 }
1388
1389
1390 /*  Copies up to LEN bytes in READBUF from offset OFFSET in OSD->BUFFER.
1391     If OFFSET is zero, first calls OSD->TAKE_SNAPSHOT.  */
1392
1393 static LONGEST
1394 common_getter (struct osdata_type *osd,
1395                gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
1396 {
1397   gdb_assert (readbuf);
1398
1399   if (offset == 0)
1400     {
1401       if (osd->len_avail != -1 && osd->len_avail != 0)
1402         buffer_free (&osd->buffer);
1403       osd->len_avail = 0;
1404       buffer_init (&osd->buffer);
1405       (osd->take_snapshot) (&osd->buffer);
1406       osd->len_avail = strlen (osd->buffer.buffer);
1407     }
1408   if (offset >= osd->len_avail)
1409     {
1410       /* Done.  Get rid of the buffer.  */
1411       buffer_free (&osd->buffer);
1412       osd->len_avail = 0;
1413       return 0;
1414     }
1415   if (len > osd->len_avail - offset)
1416     len = osd->len_avail - offset;
1417   memcpy (readbuf, osd->buffer.buffer + offset, len);
1418
1419   return len;
1420
1421 }
1422
1423 LONGEST
1424 linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
1425                           ULONGEST offset, ULONGEST len)
1426 {
1427   if (!annex || *annex == '\0')
1428     {
1429       return common_getter (&osdata_table[0],
1430                             readbuf, offset, len);
1431     }
1432   else
1433     {
1434       int i;
1435
1436       for (i = 0; osdata_table[i].type; ++i)
1437         {
1438           if (strcmp (annex, osdata_table[i].type) == 0)
1439             return common_getter (&osdata_table[i],
1440                                   readbuf, offset, len);
1441         }
1442
1443       return 0;
1444     }
1445 }
This page took 0.106581 seconds and 4 git commands to generate.