[PATCH 7/57][Arm][GAS] Add support for MVE instructions: vstr/vldr
[binutils-gdb.git] / gdb / nat / linux-osdata.c
blob3599df7cbeb67908ab94067f4a9ee5ca4b738927
1 /* Linux-specific functions to retrieve OS data.
3 Copyright (C) 2009-2019 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 #include "common/common-defs.h"
21 #include "linux-osdata.h"
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>
35 #include "common/xml-utils.h"
36 #include "common/buffer.h"
37 #include <dirent.h>
38 #include <sys/stat.h>
39 #include "common/filestuff.h"
40 #include <algorithm>
42 #define NAMELEN(dirent) strlen ((dirent)->d_name)
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. */
48 typedef long long PID_T;
50 /* Define TIME_T to be at least as large as time_t, so that reading
51 time values embedded in /proc works consistently. */
53 typedef long long TIME_T;
55 #define MAX_PID_T_STRLEN (sizeof ("-9223372036854775808") - 1)
57 /* Returns the CPU core that thread PTID is currently running on. */
59 /* Compute and return the processor core of a given thread. */
61 int
62 linux_common_core_of_thread (ptid_t ptid)
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;
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;
78 for (;;)
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)
86 content[content_read] = '\0';
87 break;
91 /* ps command also relies on no trailing fields ever contain ')'. */
92 p = strrchr (content, ')');
93 if (p != NULL)
94 p++;
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);
103 if (p == NULL || sscanf (p, "%d", &core) == 0)
104 core = -1;
106 xfree (content);
108 return core;
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. */
115 static void
116 command_from_pid (char *command, int maxlen, PID_T pid)
118 std::string stat_path = string_printf ("/proc/%lld/stat", pid);
119 gdb_file_up fp = gdb_fopen_cloexec (stat_path, "r");
121 command[0] = '\0';
123 if (fp)
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);
132 if (items_read == 2 && pid == stat_pid)
134 cmd[strlen (cmd) - 1] = '\0'; /* Remove trailing parenthesis. */
135 strncpy (command, cmd + 1, maxlen); /* Ignore leading parenthesis. */
138 else
140 /* Return the PID if a /proc entry for the process cannot be found. */
141 snprintf (command, maxlen, "%lld", pid);
144 command[maxlen - 1] = '\0'; /* Ensure string is null-terminated. */
147 /* Returns the command-line of the process with the given PID. The
148 returned string needs to be freed using xfree after use. */
150 static char *
151 commandline_from_pid (PID_T pid)
153 std::string pathname = string_printf ("/proc/%lld/cmdline", pid);
154 char *commandline = NULL;
155 gdb_file_up f = gdb_fopen_cloexec (pathname, "r");
157 if (f)
159 size_t len = 0;
161 while (!feof (f.get ()))
163 char buf[1024];
164 size_t read_bytes = fread (buf, 1, sizeof (buf), f.get ());
166 if (read_bytes)
168 commandline = (char *) xrealloc (commandline, len + read_bytes + 1);
169 memcpy (commandline + len, buf, read_bytes);
170 len += read_bytes;
174 if (commandline)
176 size_t i;
178 /* Replace null characters with spaces. */
179 for (i = 0; i < len; ++i)
180 if (commandline[i] == '\0')
181 commandline[i] = ' ';
183 commandline[len] = '\0';
185 else
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);
193 len = strlen (commandline);
194 if (len < 31)
195 strcat (commandline, "]");
199 return commandline;
202 /* Finds the user name for the user UID and copies it into USER. At
203 most MAXLEN characters are copied. */
205 static void
206 user_from_uid (char *user, int maxlen, uid_t uid)
208 struct passwd *pwentry = getpwuid (uid);
210 if (pwentry)
212 strncpy (user, pwentry->pw_name, maxlen);
213 /* Ensure that the user name is null-terminated. */
214 user[maxlen - 1] = '\0';
216 else
217 user[0] = '\0';
220 /* Finds the owner of process PID and returns the user id in OWNER.
221 Returns 0 if the owner was found, -1 otherwise. */
223 static int
224 get_process_owner (uid_t *owner, PID_T pid)
226 struct stat statbuf;
227 char procentry[sizeof ("/proc/") + MAX_PID_T_STRLEN];
229 sprintf (procentry, "/proc/%lld", pid);
231 if (stat (procentry, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))
233 *owner = statbuf.st_uid;
234 return 0;
236 else
237 return -1;
240 /* Find the CPU cores used by process PID and return them in CORES.
241 CORES points to an array of NUM_CORES elements. */
243 static int
244 get_cores_used_by_process (PID_T pid, int *cores, const int num_cores)
246 char taskdir[sizeof ("/proc/") + MAX_PID_T_STRLEN + sizeof ("/task") - 1];
247 DIR *dir;
248 struct dirent *dp;
249 int task_count = 0;
251 sprintf (taskdir, "/proc/%lld/task", pid);
252 dir = opendir (taskdir);
253 if (dir)
255 while ((dp = readdir (dir)) != NULL)
257 PID_T tid;
258 int core;
260 if (!isdigit (dp->d_name[0])
261 || NAMELEN (dp) > MAX_PID_T_STRLEN)
262 continue;
264 sscanf (dp->d_name, "%lld", &tid);
265 core = linux_common_core_of_thread (ptid_t ((pid_t) pid,
266 (pid_t) tid, 0));
268 if (core >= 0 && core < num_cores)
270 ++cores[core];
271 ++task_count;
275 closedir (dir);
278 return task_count;
281 static void
282 linux_xfer_osdata_processes (struct buffer *buffer)
284 DIR *dirp;
286 buffer_grow_str (buffer, "<osdata type=\"processes\">\n");
288 dirp = opendir ("/proc");
289 if (dirp)
291 const int num_cores = sysconf (_SC_NPROCESSORS_ONLN);
292 struct dirent *dp;
294 while ((dp = readdir (dirp)) != NULL)
296 PID_T pid;
297 uid_t owner;
298 char user[UT_NAMESIZE];
299 char *command_line;
300 int *cores;
301 int task_count;
302 char *cores_str;
303 int i;
305 if (!isdigit (dp->d_name[0])
306 || NAMELEN (dp) > MAX_PID_T_STRLEN)
307 continue;
309 sscanf (dp->d_name, "%lld", &pid);
310 command_line = commandline_from_pid (pid);
312 if (get_process_owner (&owner, pid) == 0)
313 user_from_uid (user, sizeof (user), owner);
314 else
315 strcpy (user, "?");
317 /* Find CPU cores used by the process. */
318 cores = XCNEWVEC (int, num_cores);
319 task_count = get_cores_used_by_process (pid, cores, num_cores);
320 cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1);
322 for (i = 0; i < num_cores && task_count > 0; ++i)
323 if (cores[i])
325 char core_str[sizeof ("4294967295")];
327 sprintf (core_str, "%d", i);
328 strcat (cores_str, core_str);
330 task_count -= cores[i];
331 if (task_count > 0)
332 strcat (cores_str, ",");
335 xfree (cores);
337 buffer_xml_printf
338 (buffer,
339 "<item>"
340 "<column name=\"pid\">%lld</column>"
341 "<column name=\"user\">%s</column>"
342 "<column name=\"command\">%s</column>"
343 "<column name=\"cores\">%s</column>"
344 "</item>",
345 pid,
346 user,
347 command_line ? command_line : "",
348 cores_str);
350 xfree (command_line);
351 xfree (cores_str);
354 closedir (dirp);
357 buffer_grow_str0 (buffer, "</osdata>\n");
360 /* A simple PID/PGID pair. */
362 struct pid_pgid_entry
364 pid_pgid_entry (PID_T pid_, PID_T pgid_)
365 : pid (pid_), pgid (pgid_)
368 /* Return true if this pid is the leader of its process group. */
370 bool is_leader () const
372 return pid == pgid;
375 bool operator< (const pid_pgid_entry &other) const
377 /* Sort by PGID. */
378 if (this->pgid != other.pgid)
379 return this->pgid < other.pgid;
381 /* Process group leaders always come first... */
382 if (this->is_leader ())
384 if (!other.is_leader ())
385 return true;
387 else if (other.is_leader ())
388 return false;
390 /* ...else sort by PID. */
391 return this->pid < other.pid;
394 PID_T pid, pgid;
397 /* Collect all process groups from /proc in BUFFER. */
399 static void
400 linux_xfer_osdata_processgroups (struct buffer *buffer)
402 DIR *dirp;
404 buffer_grow_str (buffer, "<osdata type=\"process groups\">\n");
406 dirp = opendir ("/proc");
407 if (dirp)
409 std::vector<pid_pgid_entry> process_list;
410 struct dirent *dp;
412 process_list.reserve (512);
414 /* Build list consisting of PIDs followed by their
415 associated PGID. */
416 while ((dp = readdir (dirp)) != NULL)
418 PID_T pid, pgid;
420 if (!isdigit (dp->d_name[0])
421 || NAMELEN (dp) > MAX_PID_T_STRLEN)
422 continue;
424 sscanf (dp->d_name, "%lld", &pid);
425 pgid = getpgid (pid);
427 if (pgid > 0)
428 process_list.emplace_back (pid, pgid);
431 closedir (dirp);
433 /* Sort the process list. */
434 std::sort (process_list.begin (), process_list.end ());
436 for (const pid_pgid_entry &entry : process_list)
438 PID_T pid = entry.pid;
439 PID_T pgid = entry.pgid;
440 char leader_command[32];
441 char *command_line;
443 command_from_pid (leader_command, sizeof (leader_command), pgid);
444 command_line = commandline_from_pid (pid);
446 buffer_xml_printf
447 (buffer,
448 "<item>"
449 "<column name=\"pgid\">%lld</column>"
450 "<column name=\"leader command\">%s</column>"
451 "<column name=\"pid\">%lld</column>"
452 "<column name=\"command line\">%s</column>"
453 "</item>",
454 pgid,
455 leader_command,
456 pid,
457 command_line ? command_line : "");
459 xfree (command_line);
463 buffer_grow_str0 (buffer, "</osdata>\n");
466 /* Collect all the threads in /proc by iterating through processes and
467 then tasks within each process in BUFFER. */
469 static void
470 linux_xfer_osdata_threads (struct buffer *buffer)
472 DIR *dirp;
474 buffer_grow_str (buffer, "<osdata type=\"threads\">\n");
476 dirp = opendir ("/proc");
477 if (dirp)
479 struct dirent *dp;
481 while ((dp = readdir (dirp)) != NULL)
483 struct stat statbuf;
484 char procentry[sizeof ("/proc/4294967295")];
486 if (!isdigit (dp->d_name[0])
487 || NAMELEN (dp) > sizeof ("4294967295") - 1)
488 continue;
490 xsnprintf (procentry, sizeof (procentry), "/proc/%s",
491 dp->d_name);
492 if (stat (procentry, &statbuf) == 0
493 && S_ISDIR (statbuf.st_mode))
495 DIR *dirp2;
496 PID_T pid;
497 char command[32];
499 std::string pathname
500 = string_printf ("/proc/%s/task", dp->d_name);
502 pid = atoi (dp->d_name);
503 command_from_pid (command, sizeof (command), pid);
505 dirp2 = opendir (pathname.c_str ());
507 if (dirp2)
509 struct dirent *dp2;
511 while ((dp2 = readdir (dirp2)) != NULL)
513 PID_T tid;
514 int core;
516 if (!isdigit (dp2->d_name[0])
517 || NAMELEN (dp2) > sizeof ("4294967295") - 1)
518 continue;
520 tid = atoi (dp2->d_name);
521 core = linux_common_core_of_thread (ptid_t (pid, tid, 0));
523 buffer_xml_printf
524 (buffer,
525 "<item>"
526 "<column name=\"pid\">%lld</column>"
527 "<column name=\"command\">%s</column>"
528 "<column name=\"tid\">%lld</column>"
529 "<column name=\"core\">%d</column>"
530 "</item>",
531 pid,
532 command,
533 tid,
534 core);
537 closedir (dirp2);
542 closedir (dirp);
545 buffer_grow_str0 (buffer, "</osdata>\n");
548 /* Collect data about the cpus/cores on the system in BUFFER. */
550 static void
551 linux_xfer_osdata_cpus (struct buffer *buffer)
553 int first_item = 1;
555 buffer_grow_str (buffer, "<osdata type=\"cpus\">\n");
557 gdb_file_up fp = gdb_fopen_cloexec ("/proc/cpuinfo", "r");
558 if (fp != NULL)
560 char buf[8192];
564 if (fgets (buf, sizeof (buf), fp.get ()))
566 char *key, *value;
567 int i = 0;
569 key = strtok (buf, ":");
570 if (key == NULL)
571 continue;
573 value = strtok (NULL, ":");
574 if (value == NULL)
575 continue;
577 while (key[i] != '\t' && key[i] != '\0')
578 i++;
580 key[i] = '\0';
582 i = 0;
583 while (value[i] != '\t' && value[i] != '\0')
584 i++;
586 value[i] = '\0';
588 if (strcmp (key, "processor") == 0)
590 if (first_item)
591 buffer_grow_str (buffer, "<item>");
592 else
593 buffer_grow_str (buffer, "</item><item>");
595 first_item = 0;
598 buffer_xml_printf (buffer,
599 "<column name=\"%s\">%s</column>",
600 key,
601 value);
604 while (!feof (fp.get ()));
606 if (first_item == 0)
607 buffer_grow_str (buffer, "</item>");
610 buffer_grow_str0 (buffer, "</osdata>\n");
613 /* Collect all the open file descriptors found in /proc and put the details
614 found about them into BUFFER. */
616 static void
617 linux_xfer_osdata_fds (struct buffer *buffer)
619 DIR *dirp;
621 buffer_grow_str (buffer, "<osdata type=\"files\">\n");
623 dirp = opendir ("/proc");
624 if (dirp)
626 struct dirent *dp;
628 while ((dp = readdir (dirp)) != NULL)
630 struct stat statbuf;
631 char procentry[sizeof ("/proc/4294967295")];
633 if (!isdigit (dp->d_name[0])
634 || NAMELEN (dp) > sizeof ("4294967295") - 1)
635 continue;
637 xsnprintf (procentry, sizeof (procentry), "/proc/%s",
638 dp->d_name);
639 if (stat (procentry, &statbuf) == 0
640 && S_ISDIR (statbuf.st_mode))
642 DIR *dirp2;
643 PID_T pid;
644 char command[32];
646 pid = atoi (dp->d_name);
647 command_from_pid (command, sizeof (command), pid);
649 std::string pathname
650 = string_printf ("/proc/%s/fd", dp->d_name);
651 dirp2 = opendir (pathname.c_str ());
653 if (dirp2)
655 struct dirent *dp2;
657 while ((dp2 = readdir (dirp2)) != NULL)
659 char buf[1000];
660 ssize_t rslt;
662 if (!isdigit (dp2->d_name[0]))
663 continue;
665 std::string fdname
666 = string_printf ("%s/%s", pathname.c_str (),
667 dp2->d_name);
668 rslt = readlink (fdname.c_str (), buf,
669 sizeof (buf) - 1);
670 if (rslt >= 0)
671 buf[rslt] = '\0';
673 buffer_xml_printf
674 (buffer,
675 "<item>"
676 "<column name=\"pid\">%s</column>"
677 "<column name=\"command\">%s</column>"
678 "<column name=\"file descriptor\">%s</column>"
679 "<column name=\"name\">%s</column>"
680 "</item>",
681 dp->d_name,
682 command,
683 dp2->d_name,
684 (rslt >= 0 ? buf : dp2->d_name));
687 closedir (dirp2);
692 closedir (dirp);
695 buffer_grow_str0 (buffer, "</osdata>\n");
698 /* Returns the socket state STATE in textual form. */
700 static const char *
701 format_socket_state (unsigned char state)
703 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
704 enum {
705 TCP_ESTABLISHED = 1,
706 TCP_SYN_SENT,
707 TCP_SYN_RECV,
708 TCP_FIN_WAIT1,
709 TCP_FIN_WAIT2,
710 TCP_TIME_WAIT,
711 TCP_CLOSE,
712 TCP_CLOSE_WAIT,
713 TCP_LAST_ACK,
714 TCP_LISTEN,
715 TCP_CLOSING
718 switch (state)
720 case TCP_ESTABLISHED:
721 return "ESTABLISHED";
722 case TCP_SYN_SENT:
723 return "SYN_SENT";
724 case TCP_SYN_RECV:
725 return "SYN_RECV";
726 case TCP_FIN_WAIT1:
727 return "FIN_WAIT1";
728 case TCP_FIN_WAIT2:
729 return "FIN_WAIT2";
730 case TCP_TIME_WAIT:
731 return "TIME_WAIT";
732 case TCP_CLOSE:
733 return "CLOSE";
734 case TCP_CLOSE_WAIT:
735 return "CLOSE_WAIT";
736 case TCP_LAST_ACK:
737 return "LAST_ACK";
738 case TCP_LISTEN:
739 return "LISTEN";
740 case TCP_CLOSING:
741 return "CLOSING";
742 default:
743 return "(unknown)";
747 union socket_addr
749 struct sockaddr sa;
750 struct sockaddr_in sin;
751 struct sockaddr_in6 sin6;
754 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
755 information for all open internet sockets of type FAMILY on the
756 system into BUFFER. If TCP is set, only TCP sockets are processed,
757 otherwise only UDP sockets are processed. */
759 static void
760 print_sockets (unsigned short family, int tcp, struct buffer *buffer)
762 const char *proc_file;
764 if (family == AF_INET)
765 proc_file = tcp ? "/proc/net/tcp" : "/proc/net/udp";
766 else if (family == AF_INET6)
767 proc_file = tcp ? "/proc/net/tcp6" : "/proc/net/udp6";
768 else
769 return;
771 gdb_file_up fp = gdb_fopen_cloexec (proc_file, "r");
772 if (fp)
774 char buf[8192];
778 if (fgets (buf, sizeof (buf), fp.get ()))
780 uid_t uid;
781 unsigned int local_port, remote_port, state;
782 char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
783 int result;
785 #if NI_MAXHOST <= 32
786 #error "local_address and remote_address buffers too small"
787 #endif
789 result = sscanf (buf,
790 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
791 local_address, &local_port,
792 remote_address, &remote_port,
793 &state,
794 &uid);
796 if (result == 6)
798 union socket_addr locaddr, remaddr;
799 size_t addr_size;
800 char user[UT_NAMESIZE];
801 char local_service[NI_MAXSERV], remote_service[NI_MAXSERV];
803 if (family == AF_INET)
805 sscanf (local_address, "%X",
806 &locaddr.sin.sin_addr.s_addr);
807 sscanf (remote_address, "%X",
808 &remaddr.sin.sin_addr.s_addr);
810 locaddr.sin.sin_port = htons (local_port);
811 remaddr.sin.sin_port = htons (remote_port);
813 addr_size = sizeof (struct sockaddr_in);
815 else
817 sscanf (local_address, "%8X%8X%8X%8X",
818 locaddr.sin6.sin6_addr.s6_addr32,
819 locaddr.sin6.sin6_addr.s6_addr32 + 1,
820 locaddr.sin6.sin6_addr.s6_addr32 + 2,
821 locaddr.sin6.sin6_addr.s6_addr32 + 3);
822 sscanf (remote_address, "%8X%8X%8X%8X",
823 remaddr.sin6.sin6_addr.s6_addr32,
824 remaddr.sin6.sin6_addr.s6_addr32 + 1,
825 remaddr.sin6.sin6_addr.s6_addr32 + 2,
826 remaddr.sin6.sin6_addr.s6_addr32 + 3);
828 locaddr.sin6.sin6_port = htons (local_port);
829 remaddr.sin6.sin6_port = htons (remote_port);
831 locaddr.sin6.sin6_flowinfo = 0;
832 remaddr.sin6.sin6_flowinfo = 0;
833 locaddr.sin6.sin6_scope_id = 0;
834 remaddr.sin6.sin6_scope_id = 0;
836 addr_size = sizeof (struct sockaddr_in6);
839 locaddr.sa.sa_family = remaddr.sa.sa_family = family;
841 result = getnameinfo (&locaddr.sa, addr_size,
842 local_address, sizeof (local_address),
843 local_service, sizeof (local_service),
844 NI_NUMERICHOST | NI_NUMERICSERV
845 | (tcp ? 0 : NI_DGRAM));
846 if (result)
847 continue;
849 result = getnameinfo (&remaddr.sa, addr_size,
850 remote_address,
851 sizeof (remote_address),
852 remote_service,
853 sizeof (remote_service),
854 NI_NUMERICHOST | NI_NUMERICSERV
855 | (tcp ? 0 : NI_DGRAM));
856 if (result)
857 continue;
859 user_from_uid (user, sizeof (user), uid);
861 buffer_xml_printf (
862 buffer,
863 "<item>"
864 "<column name=\"local address\">%s</column>"
865 "<column name=\"local port\">%s</column>"
866 "<column name=\"remote address\">%s</column>"
867 "<column name=\"remote port\">%s</column>"
868 "<column name=\"state\">%s</column>"
869 "<column name=\"user\">%s</column>"
870 "<column name=\"family\">%s</column>"
871 "<column name=\"protocol\">%s</column>"
872 "</item>",
873 local_address,
874 local_service,
875 remote_address,
876 remote_service,
877 format_socket_state (state),
878 user,
879 (family == AF_INET) ? "INET" : "INET6",
880 tcp ? "STREAM" : "DGRAM");
884 while (!feof (fp.get ()));
888 /* Collect data about internet sockets and write it into BUFFER. */
890 static void
891 linux_xfer_osdata_isockets (struct buffer *buffer)
893 buffer_grow_str (buffer, "<osdata type=\"I sockets\">\n");
895 print_sockets (AF_INET, 1, buffer);
896 print_sockets (AF_INET, 0, buffer);
897 print_sockets (AF_INET6, 1, buffer);
898 print_sockets (AF_INET6, 0, buffer);
900 buffer_grow_str0 (buffer, "</osdata>\n");
903 /* Converts the time SECONDS into textual form and copies it into a
904 buffer TIME, with at most MAXLEN characters copied. */
906 static void
907 time_from_time_t (char *time, int maxlen, TIME_T seconds)
909 if (!seconds)
910 time[0] = '\0';
911 else
913 time_t t = (time_t) seconds;
915 strncpy (time, ctime (&t), maxlen);
916 time[maxlen - 1] = '\0';
920 /* Finds the group name for the group GID and copies it into GROUP.
921 At most MAXLEN characters are copied. */
923 static void
924 group_from_gid (char *group, int maxlen, gid_t gid)
926 struct group *grentry = getgrgid (gid);
928 if (grentry)
930 strncpy (group, grentry->gr_name, maxlen);
931 /* Ensure that the group name is null-terminated. */
932 group[maxlen - 1] = '\0';
934 else
935 group[0] = '\0';
938 /* Collect data about shared memory recorded in /proc and write it
939 into BUFFER. */
941 static void
942 linux_xfer_osdata_shm (struct buffer *buffer)
944 buffer_grow_str (buffer, "<osdata type=\"shared memory\">\n");
946 gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
947 if (fp)
949 char buf[8192];
953 if (fgets (buf, sizeof (buf), fp.get ()))
955 key_t key;
956 uid_t uid, cuid;
957 gid_t gid, cgid;
958 PID_T cpid, lpid;
959 int shmid, size, nattch;
960 TIME_T atime, dtime, ctime;
961 unsigned int perms;
962 int items_read;
964 items_read = sscanf (buf,
965 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
966 &key, &shmid, &perms, &size,
967 &cpid, &lpid,
968 &nattch,
969 &uid, &gid, &cuid, &cgid,
970 &atime, &dtime, &ctime);
972 if (items_read == 14)
974 char user[UT_NAMESIZE], group[UT_NAMESIZE];
975 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
976 char ccmd[32], lcmd[32];
977 char atime_str[32], dtime_str[32], ctime_str[32];
979 user_from_uid (user, sizeof (user), uid);
980 group_from_gid (group, sizeof (group), gid);
981 user_from_uid (cuser, sizeof (cuser), cuid);
982 group_from_gid (cgroup, sizeof (cgroup), cgid);
984 command_from_pid (ccmd, sizeof (ccmd), cpid);
985 command_from_pid (lcmd, sizeof (lcmd), lpid);
987 time_from_time_t (atime_str, sizeof (atime_str), atime);
988 time_from_time_t (dtime_str, sizeof (dtime_str), dtime);
989 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
991 buffer_xml_printf
992 (buffer,
993 "<item>"
994 "<column name=\"key\">%d</column>"
995 "<column name=\"shmid\">%d</column>"
996 "<column name=\"permissions\">%o</column>"
997 "<column name=\"size\">%d</column>"
998 "<column name=\"creator command\">%s</column>"
999 "<column name=\"last op. command\">%s</column>"
1000 "<column name=\"num attached\">%d</column>"
1001 "<column name=\"user\">%s</column>"
1002 "<column name=\"group\">%s</column>"
1003 "<column name=\"creator user\">%s</column>"
1004 "<column name=\"creator group\">%s</column>"
1005 "<column name=\"last shmat() time\">%s</column>"
1006 "<column name=\"last shmdt() time\">%s</column>"
1007 "<column name=\"last shmctl() time\">%s</column>"
1008 "</item>",
1009 key,
1010 shmid,
1011 perms,
1012 size,
1013 ccmd,
1014 lcmd,
1015 nattch,
1016 user,
1017 group,
1018 cuser,
1019 cgroup,
1020 atime_str,
1021 dtime_str,
1022 ctime_str);
1026 while (!feof (fp.get ()));
1029 buffer_grow_str0 (buffer, "</osdata>\n");
1032 /* Collect data about semaphores recorded in /proc and write it
1033 into BUFFER. */
1035 static void
1036 linux_xfer_osdata_sem (struct buffer *buffer)
1038 buffer_grow_str (buffer, "<osdata type=\"semaphores\">\n");
1040 gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1041 if (fp)
1043 char buf[8192];
1047 if (fgets (buf, sizeof (buf), fp.get ()))
1049 key_t key;
1050 uid_t uid, cuid;
1051 gid_t gid, cgid;
1052 unsigned int perms, nsems;
1053 int semid;
1054 TIME_T otime, ctime;
1055 int items_read;
1057 items_read = sscanf (buf,
1058 "%d %d %o %u %d %d %d %d %lld %lld",
1059 &key, &semid, &perms, &nsems,
1060 &uid, &gid, &cuid, &cgid,
1061 &otime, &ctime);
1063 if (items_read == 10)
1065 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1066 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1067 char otime_str[32], ctime_str[32];
1069 user_from_uid (user, sizeof (user), uid);
1070 group_from_gid (group, sizeof (group), gid);
1071 user_from_uid (cuser, sizeof (cuser), cuid);
1072 group_from_gid (cgroup, sizeof (cgroup), cgid);
1074 time_from_time_t (otime_str, sizeof (otime_str), otime);
1075 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1077 buffer_xml_printf
1078 (buffer,
1079 "<item>"
1080 "<column name=\"key\">%d</column>"
1081 "<column name=\"semid\">%d</column>"
1082 "<column name=\"permissions\">%o</column>"
1083 "<column name=\"num semaphores\">%u</column>"
1084 "<column name=\"user\">%s</column>"
1085 "<column name=\"group\">%s</column>"
1086 "<column name=\"creator user\">%s</column>"
1087 "<column name=\"creator group\">%s</column>"
1088 "<column name=\"last semop() time\">%s</column>"
1089 "<column name=\"last semctl() time\">%s</column>"
1090 "</item>",
1091 key,
1092 semid,
1093 perms,
1094 nsems,
1095 user,
1096 group,
1097 cuser,
1098 cgroup,
1099 otime_str,
1100 ctime_str);
1104 while (!feof (fp.get ()));
1107 buffer_grow_str0 (buffer, "</osdata>\n");
1110 /* Collect data about message queues recorded in /proc and write it
1111 into BUFFER. */
1113 static void
1114 linux_xfer_osdata_msg (struct buffer *buffer)
1116 buffer_grow_str (buffer, "<osdata type=\"message queues\">\n");
1118 gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1119 if (fp)
1121 char buf[8192];
1125 if (fgets (buf, sizeof (buf), fp.get ()))
1127 key_t key;
1128 PID_T lspid, lrpid;
1129 uid_t uid, cuid;
1130 gid_t gid, cgid;
1131 unsigned int perms, cbytes, qnum;
1132 int msqid;
1133 TIME_T stime, rtime, ctime;
1134 int items_read;
1136 items_read = sscanf (buf,
1137 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1138 &key, &msqid, &perms, &cbytes, &qnum,
1139 &lspid, &lrpid, &uid, &gid, &cuid, &cgid,
1140 &stime, &rtime, &ctime);
1142 if (items_read == 14)
1144 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1145 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1146 char lscmd[32], lrcmd[32];
1147 char stime_str[32], rtime_str[32], ctime_str[32];
1149 user_from_uid (user, sizeof (user), uid);
1150 group_from_gid (group, sizeof (group), gid);
1151 user_from_uid (cuser, sizeof (cuser), cuid);
1152 group_from_gid (cgroup, sizeof (cgroup), cgid);
1154 command_from_pid (lscmd, sizeof (lscmd), lspid);
1155 command_from_pid (lrcmd, sizeof (lrcmd), lrpid);
1157 time_from_time_t (stime_str, sizeof (stime_str), stime);
1158 time_from_time_t (rtime_str, sizeof (rtime_str), rtime);
1159 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1161 buffer_xml_printf
1162 (buffer,
1163 "<item>"
1164 "<column name=\"key\">%d</column>"
1165 "<column name=\"msqid\">%d</column>"
1166 "<column name=\"permissions\">%o</column>"
1167 "<column name=\"num used bytes\">%u</column>"
1168 "<column name=\"num messages\">%u</column>"
1169 "<column name=\"last msgsnd() command\">%s</column>"
1170 "<column name=\"last msgrcv() command\">%s</column>"
1171 "<column name=\"user\">%s</column>"
1172 "<column name=\"group\">%s</column>"
1173 "<column name=\"creator user\">%s</column>"
1174 "<column name=\"creator group\">%s</column>"
1175 "<column name=\"last msgsnd() time\">%s</column>"
1176 "<column name=\"last msgrcv() time\">%s</column>"
1177 "<column name=\"last msgctl() time\">%s</column>"
1178 "</item>",
1179 key,
1180 msqid,
1181 perms,
1182 cbytes,
1183 qnum,
1184 lscmd,
1185 lrcmd,
1186 user,
1187 group,
1188 cuser,
1189 cgroup,
1190 stime_str,
1191 rtime_str,
1192 ctime_str);
1196 while (!feof (fp.get ()));
1199 buffer_grow_str0 (buffer, "</osdata>\n");
1202 /* Collect data about loaded kernel modules and write it into
1203 BUFFER. */
1205 static void
1206 linux_xfer_osdata_modules (struct buffer *buffer)
1208 buffer_grow_str (buffer, "<osdata type=\"modules\">\n");
1210 gdb_file_up fp = gdb_fopen_cloexec ("/proc/modules", "r");
1211 if (fp)
1213 char buf[8192];
1217 if (fgets (buf, sizeof (buf), fp.get ()))
1219 char *name, *dependencies, *status, *tmp;
1220 unsigned int size;
1221 unsigned long long address;
1222 int uses;
1224 name = strtok (buf, " ");
1225 if (name == NULL)
1226 continue;
1228 tmp = strtok (NULL, " ");
1229 if (tmp == NULL)
1230 continue;
1231 if (sscanf (tmp, "%u", &size) != 1)
1232 continue;
1234 tmp = strtok (NULL, " ");
1235 if (tmp == NULL)
1236 continue;
1237 if (sscanf (tmp, "%d", &uses) != 1)
1238 continue;
1240 dependencies = strtok (NULL, " ");
1241 if (dependencies == NULL)
1242 continue;
1244 status = strtok (NULL, " ");
1245 if (status == NULL)
1246 continue;
1248 tmp = strtok (NULL, "\n");
1249 if (tmp == NULL)
1250 continue;
1251 if (sscanf (tmp, "%llx", &address) != 1)
1252 continue;
1254 buffer_xml_printf (buffer,
1255 "<item>"
1256 "<column name=\"name\">%s</column>"
1257 "<column name=\"size\">%u</column>"
1258 "<column name=\"num uses\">%d</column>"
1259 "<column name=\"dependencies\">%s</column>"
1260 "<column name=\"status\">%s</column>"
1261 "<column name=\"address\">%llx</column>"
1262 "</item>",
1263 name,
1264 size,
1265 uses,
1266 dependencies,
1267 status,
1268 address);
1271 while (!feof (fp.get ()));
1274 buffer_grow_str0 (buffer, "</osdata>\n");
1277 static void linux_xfer_osdata_info_os_types (struct buffer *buffer);
1279 struct osdata_type {
1280 const char *type;
1281 const char *title;
1282 const char *description;
1283 void (*take_snapshot) (struct buffer *buffer);
1284 LONGEST len_avail;
1285 struct buffer buffer;
1286 } osdata_table[] = {
1287 { "types", "Types", "Listing of info os types you can list",
1288 linux_xfer_osdata_info_os_types, -1 },
1289 { "cpus", "CPUs", "Listing of all cpus/cores on the system",
1290 linux_xfer_osdata_cpus, -1 },
1291 { "files", "File descriptors", "Listing of all file descriptors",
1292 linux_xfer_osdata_fds, -1 },
1293 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1294 linux_xfer_osdata_modules, -1 },
1295 { "msg", "Message queues", "Listing of all message queues",
1296 linux_xfer_osdata_msg, -1 },
1297 { "processes", "Processes", "Listing of all processes",
1298 linux_xfer_osdata_processes, -1 },
1299 { "procgroups", "Process groups", "Listing of all process groups",
1300 linux_xfer_osdata_processgroups, -1 },
1301 { "semaphores", "Semaphores", "Listing of all semaphores",
1302 linux_xfer_osdata_sem, -1 },
1303 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1304 linux_xfer_osdata_shm, -1 },
1305 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1306 linux_xfer_osdata_isockets, -1 },
1307 { "threads", "Threads", "Listing of all threads",
1308 linux_xfer_osdata_threads, -1 },
1309 { NULL, NULL, NULL }
1312 /* Collect data about all types info os can show in BUFFER. */
1314 static void
1315 linux_xfer_osdata_info_os_types (struct buffer *buffer)
1317 buffer_grow_str (buffer, "<osdata type=\"types\">\n");
1319 /* Start the below loop at 1, as we do not want to list ourselves. */
1320 for (int i = 1; osdata_table[i].type; ++i)
1321 buffer_xml_printf (buffer,
1322 "<item>"
1323 "<column name=\"Type\">%s</column>"
1324 "<column name=\"Description\">%s</column>"
1325 "<column name=\"Title\">%s</column>"
1326 "</item>",
1327 osdata_table[i].type,
1328 osdata_table[i].description,
1329 osdata_table[i].title);
1331 buffer_grow_str0 (buffer, "</osdata>\n");
1335 /* Copies up to LEN bytes in READBUF from offset OFFSET in OSD->BUFFER.
1336 If OFFSET is zero, first calls OSD->TAKE_SNAPSHOT. */
1338 static LONGEST
1339 common_getter (struct osdata_type *osd,
1340 gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
1342 gdb_assert (readbuf);
1344 if (offset == 0)
1346 if (osd->len_avail != -1 && osd->len_avail != 0)
1347 buffer_free (&osd->buffer);
1348 osd->len_avail = 0;
1349 buffer_init (&osd->buffer);
1350 (osd->take_snapshot) (&osd->buffer);
1351 osd->len_avail = strlen (osd->buffer.buffer);
1353 if (offset >= osd->len_avail)
1355 /* Done. Get rid of the buffer. */
1356 buffer_free (&osd->buffer);
1357 osd->len_avail = 0;
1358 return 0;
1360 if (len > osd->len_avail - offset)
1361 len = osd->len_avail - offset;
1362 memcpy (readbuf, osd->buffer.buffer + offset, len);
1364 return len;
1368 LONGEST
1369 linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
1370 ULONGEST offset, ULONGEST len)
1372 if (!annex || *annex == '\0')
1374 return common_getter (&osdata_table[0],
1375 readbuf, offset, len);
1377 else
1379 int i;
1381 for (i = 0; osdata_table[i].type; ++i)
1383 if (strcmp (annex, osdata_table[i].type) == 0)
1384 return common_getter (&osdata_table[i],
1385 readbuf, offset, len);
1388 return 0;