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