1 /* Linux-specific functions to retrieve OS data.
3 Copyright (C) 2009-2018 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-defs.h"
21 #include "linux-osdata.h"
23 #include <sys/types.h>
24 #include <sys/sysinfo.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
35 #include "xml-utils.h"
39 #include "filestuff.h"
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
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. */
62 linux_common_core_of_thread (ptid_t ptid
)
64 char filename
[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN
];
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");
81 content
= (char *) xrealloc (content
, content_read
+ 1024);
82 n
= fread (content
+ content_read
, 1, 1024, f
.get ());
86 content
[content_read
] = '\0';
91 /* ps command also relies on no trailing fields ever contain ')'. */
92 p
= strrchr (content
, ')');
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. */
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)
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. */
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");
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). */
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. */
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. */
151 commandline_from_pid (PID_T pid
)
153 std::string pathname
= xstrprintf ("/proc/%lld/cmdline", pid
);
154 char *commandline
= NULL
;
155 gdb_file_up f
= gdb_fopen_cloexec (pathname
, "r");
161 while (!feof (f
.get ()))
164 size_t read_bytes
= fread (buf
, 1, sizeof (buf
), f
.get ());
168 commandline
= (char *) xrealloc (commandline
, len
+ read_bytes
+ 1);
169 memcpy (commandline
+ len
, buf
, read_bytes
);
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';
187 /* Return the command in square brackets if the command-line
189 commandline
= (char *) xmalloc (32);
190 commandline
[0] = '[';
191 command_from_pid (commandline
+ 1, 31, pid
);
193 len
= strlen (commandline
);
195 strcat (commandline
, "]");
202 /* Finds the user name for the user UID and copies it into USER. At
203 most MAXLEN characters are copied. */
206 user_from_uid (char *user
, int maxlen
, uid_t uid
)
208 struct passwd
*pwentry
= getpwuid (uid
);
212 strncpy (user
, pwentry
->pw_name
, maxlen
);
213 /* Ensure that the user name is null-terminated. */
214 user
[maxlen
- 1] = '\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. */
224 get_process_owner (uid_t
*owner
, PID_T pid
)
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
;
240 /* Find the CPU cores used by process PID and return them in CORES.
241 CORES points to an array of NUM_CORES elements. */
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];
251 sprintf (taskdir
, "/proc/%lld/task", pid
);
252 dir
= opendir (taskdir
);
255 while ((dp
= readdir (dir
)) != NULL
)
260 if (!isdigit (dp
->d_name
[0])
261 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
264 sscanf (dp
->d_name
, "%lld", &tid
);
265 core
= linux_common_core_of_thread (ptid_t ((pid_t
) pid
,
268 if (core
>= 0 && core
< num_cores
)
282 linux_xfer_osdata_processes (gdb_byte
*readbuf
,
283 ULONGEST offset
, ULONGEST len
)
285 /* We make the process list snapshot when the object starts to be read. */
286 static const char *buf
;
287 static LONGEST len_avail
= -1;
288 static struct buffer buffer
;
294 if (len_avail
!= -1 && len_avail
!= 0)
295 buffer_free (&buffer
);
298 buffer_init (&buffer
);
299 buffer_grow_str (&buffer
, "<osdata type=\"processes\">\n");
301 dirp
= opendir ("/proc");
304 const int num_cores
= sysconf (_SC_NPROCESSORS_ONLN
);
307 while ((dp
= readdir (dirp
)) != NULL
)
311 char user
[UT_NAMESIZE
];
318 if (!isdigit (dp
->d_name
[0])
319 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
322 sscanf (dp
->d_name
, "%lld", &pid
);
323 command_line
= commandline_from_pid (pid
);
325 if (get_process_owner (&owner
, pid
) == 0)
326 user_from_uid (user
, sizeof (user
), owner
);
330 /* Find CPU cores used by the process. */
331 cores
= XCNEWVEC (int, num_cores
);
332 task_count
= get_cores_used_by_process (pid
, cores
, num_cores
);
333 cores_str
= (char *) xcalloc (task_count
, sizeof ("4294967295") + 1);
335 for (i
= 0; i
< num_cores
&& task_count
> 0; ++i
)
338 char core_str
[sizeof ("4294967295")];
340 sprintf (core_str
, "%d", i
);
341 strcat (cores_str
, core_str
);
343 task_count
-= cores
[i
];
345 strcat (cores_str
, ",");
353 "<column name=\"pid\">%lld</column>"
354 "<column name=\"user\">%s</column>"
355 "<column name=\"command\">%s</column>"
356 "<column name=\"cores\">%s</column>"
360 command_line
? command_line
: "",
363 xfree (command_line
);
370 buffer_grow_str0 (&buffer
, "</osdata>\n");
371 buf
= buffer_finish (&buffer
);
372 len_avail
= strlen (buf
);
375 if (offset
>= len_avail
)
377 /* Done. Get rid of the buffer. */
378 buffer_free (&buffer
);
384 if (len
> len_avail
- offset
)
385 len
= len_avail
- offset
;
386 memcpy (readbuf
, buf
+ offset
, len
);
391 /* A simple PID/PGID pair. */
393 struct pid_pgid_entry
395 pid_pgid_entry (PID_T pid_
, PID_T pgid_
)
396 : pid (pid_
), pgid (pgid_
)
399 /* Return true if this pid is the leader of its process group. */
401 bool is_leader () const
406 bool operator< (const pid_pgid_entry
&other
) const
409 if (this->pgid
!= other
.pgid
)
410 return this->pgid
< other
.pgid
;
412 /* Process group leaders always come first... */
413 if (this->is_leader ())
415 if (!other
.is_leader ())
418 else if (other
.is_leader ())
421 /* ...else sort by PID. */
422 return this->pid
< other
.pid
;
428 /* Collect all process groups from /proc. */
431 linux_xfer_osdata_processgroups (gdb_byte
*readbuf
,
432 ULONGEST offset
, ULONGEST len
)
434 /* We make the process list snapshot when the object starts to be read. */
435 static const char *buf
;
436 static LONGEST len_avail
= -1;
437 static struct buffer buffer
;
443 if (len_avail
!= -1 && len_avail
!= 0)
444 buffer_free (&buffer
);
447 buffer_init (&buffer
);
448 buffer_grow_str (&buffer
, "<osdata type=\"process groups\">\n");
450 dirp
= opendir ("/proc");
453 std::vector
<pid_pgid_entry
> process_list
;
456 process_list
.reserve (512);
458 /* Build list consisting of PIDs followed by their
460 while ((dp
= readdir (dirp
)) != NULL
)
464 if (!isdigit (dp
->d_name
[0])
465 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
468 sscanf (dp
->d_name
, "%lld", &pid
);
469 pgid
= getpgid (pid
);
472 process_list
.emplace_back (pid
, pgid
);
477 /* Sort the process list. */
478 std::sort (process_list
.begin (), process_list
.end ());
480 for (const pid_pgid_entry
&entry
: process_list
)
482 PID_T pid
= entry
.pid
;
483 PID_T pgid
= entry
.pgid
;
484 char leader_command
[32];
487 command_from_pid (leader_command
, sizeof (leader_command
), pgid
);
488 command_line
= commandline_from_pid (pid
);
493 "<column name=\"pgid\">%lld</column>"
494 "<column name=\"leader command\">%s</column>"
495 "<column name=\"pid\">%lld</column>"
496 "<column name=\"command line\">%s</column>"
501 command_line
? command_line
: "");
503 xfree (command_line
);
507 buffer_grow_str0 (&buffer
, "</osdata>\n");
508 buf
= buffer_finish (&buffer
);
509 len_avail
= strlen (buf
);
512 if (offset
>= len_avail
)
514 /* Done. Get rid of the buffer. */
515 buffer_free (&buffer
);
521 if (len
> len_avail
- offset
)
522 len
= len_avail
- offset
;
523 memcpy (readbuf
, buf
+ offset
, len
);
528 /* Collect all the threads in /proc by iterating through processes and
529 then tasks within each process. */
532 linux_xfer_osdata_threads (gdb_byte
*readbuf
,
533 ULONGEST offset
, ULONGEST len
)
535 /* We make the process list snapshot when the object starts to be read. */
536 static const char *buf
;
537 static LONGEST len_avail
= -1;
538 static struct buffer buffer
;
544 if (len_avail
!= -1 && len_avail
!= 0)
545 buffer_free (&buffer
);
548 buffer_init (&buffer
);
549 buffer_grow_str (&buffer
, "<osdata type=\"threads\">\n");
551 dirp
= opendir ("/proc");
556 while ((dp
= readdir (dirp
)) != NULL
)
559 char procentry
[sizeof ("/proc/4294967295")];
561 if (!isdigit (dp
->d_name
[0])
562 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
565 xsnprintf (procentry
, sizeof (procentry
), "/proc/%s",
567 if (stat (procentry
, &statbuf
) == 0
568 && S_ISDIR (statbuf
.st_mode
))
575 = string_printf ("/proc/%s/task", dp
->d_name
);
577 pid
= atoi (dp
->d_name
);
578 command_from_pid (command
, sizeof (command
), pid
);
580 dirp2
= opendir (pathname
.c_str ());
586 while ((dp2
= readdir (dirp2
)) != NULL
)
591 if (!isdigit (dp2
->d_name
[0])
592 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
595 tid
= atoi (dp2
->d_name
);
596 core
= linux_common_core_of_thread (ptid_t (pid
, tid
, 0));
601 "<column name=\"pid\">%lld</column>"
602 "<column name=\"command\">%s</column>"
603 "<column name=\"tid\">%lld</column>"
604 "<column name=\"core\">%d</column>"
620 buffer_grow_str0 (&buffer
, "</osdata>\n");
621 buf
= buffer_finish (&buffer
);
622 len_avail
= strlen (buf
);
625 if (offset
>= len_avail
)
627 /* Done. Get rid of the buffer. */
628 buffer_free (&buffer
);
634 if (len
> len_avail
- offset
)
635 len
= len_avail
- offset
;
636 memcpy (readbuf
, buf
+ offset
, len
);
641 /* Collect data about the cpus/cores on the system */
644 linux_xfer_osdata_cpus (gdb_byte
*readbuf
,
645 ULONGEST offset
, ULONGEST len
)
647 static const char *buf
;
648 static LONGEST len_avail
= -1;
649 static struct buffer buffer
;
655 if (len_avail
!= -1 && len_avail
!= 0)
656 buffer_free (&buffer
);
659 buffer_init (&buffer
);
660 buffer_grow_str (&buffer
, "<osdata type=\"cpus\">\n");
662 gdb_file_up fp
= gdb_fopen_cloexec ("/proc/cpuinfo", "r");
669 if (fgets (buf
, sizeof (buf
), fp
.get ()))
674 key
= strtok (buf
, ":");
678 value
= strtok (NULL
, ":");
682 while (key
[i
] != '\t' && key
[i
] != '\0')
688 while (value
[i
] != '\t' && value
[i
] != '\0')
693 if (strcmp (key
, "processor") == 0)
696 buffer_grow_str (&buffer
, "<item>");
698 buffer_grow_str (&buffer
, "</item><item>");
703 buffer_xml_printf (&buffer
,
704 "<column name=\"%s\">%s</column>",
709 while (!feof (fp
.get ()));
712 buffer_grow_str (&buffer
, "</item>");
715 buffer_grow_str0 (&buffer
, "</osdata>\n");
716 buf
= buffer_finish (&buffer
);
717 len_avail
= strlen (buf
);
720 if (offset
>= len_avail
)
722 /* Done. Get rid of the buffer. */
723 buffer_free (&buffer
);
729 if (len
> len_avail
- offset
)
730 len
= len_avail
- offset
;
731 memcpy (readbuf
, buf
+ offset
, len
);
736 /* Collect all the open file descriptors found in /proc and put the details
737 found about them into READBUF. */
740 linux_xfer_osdata_fds (gdb_byte
*readbuf
,
741 ULONGEST offset
, ULONGEST len
)
743 /* We make the process list snapshot when the object starts to be read. */
744 static const char *buf
;
745 static LONGEST len_avail
= -1;
746 static struct buffer buffer
;
752 if (len_avail
!= -1 && len_avail
!= 0)
753 buffer_free (&buffer
);
756 buffer_init (&buffer
);
757 buffer_grow_str (&buffer
, "<osdata type=\"files\">\n");
759 dirp
= opendir ("/proc");
764 while ((dp
= readdir (dirp
)) != NULL
)
767 char procentry
[sizeof ("/proc/4294967295")];
769 if (!isdigit (dp
->d_name
[0])
770 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
773 xsnprintf (procentry
, sizeof (procentry
), "/proc/%s",
775 if (stat (procentry
, &statbuf
) == 0
776 && S_ISDIR (statbuf
.st_mode
))
782 pid
= atoi (dp
->d_name
);
783 command_from_pid (command
, sizeof (command
), pid
);
786 = string_printf ("/proc/%s/fd", dp
->d_name
);
787 dirp2
= opendir (pathname
.c_str ());
793 while ((dp2
= readdir (dirp2
)) != NULL
)
798 if (!isdigit (dp2
->d_name
[0]))
802 = string_printf ("%s/%s", pathname
.c_str (),
804 rslt
= readlink (fdname
.c_str (), buf
,
812 "<column name=\"pid\">%s</column>"
813 "<column name=\"command\">%s</column>"
814 "<column name=\"file descriptor\">%s</column>"
815 "<column name=\"name\">%s</column>"
820 (rslt
>= 0 ? buf
: dp2
->d_name
));
831 buffer_grow_str0 (&buffer
, "</osdata>\n");
832 buf
= buffer_finish (&buffer
);
833 len_avail
= strlen (buf
);
836 if (offset
>= len_avail
)
838 /* Done. Get rid of the buffer. */
839 buffer_free (&buffer
);
845 if (len
> len_avail
- offset
)
846 len
= len_avail
- offset
;
847 memcpy (readbuf
, buf
+ offset
, len
);
852 /* Returns the socket state STATE in textual form. */
855 format_socket_state (unsigned char state
)
857 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
874 case TCP_ESTABLISHED
:
875 return "ESTABLISHED";
904 struct sockaddr_in sin
;
905 struct sockaddr_in6 sin6
;
908 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
909 information for all open internet sockets of type FAMILY on the
910 system into BUFFER. If TCP is set, only TCP sockets are processed,
911 otherwise only UDP sockets are processed. */
914 print_sockets (unsigned short family
, int tcp
, struct buffer
*buffer
)
916 const char *proc_file
;
918 if (family
== AF_INET
)
919 proc_file
= tcp
? "/proc/net/tcp" : "/proc/net/udp";
920 else if (family
== AF_INET6
)
921 proc_file
= tcp
? "/proc/net/tcp6" : "/proc/net/udp6";
925 gdb_file_up fp
= gdb_fopen_cloexec (proc_file
, "r");
932 if (fgets (buf
, sizeof (buf
), fp
.get ()))
935 unsigned int local_port
, remote_port
, state
;
936 char local_address
[NI_MAXHOST
], remote_address
[NI_MAXHOST
];
940 #error "local_address and remote_address buffers too small"
943 result
= sscanf (buf
,
944 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
945 local_address
, &local_port
,
946 remote_address
, &remote_port
,
952 union socket_addr locaddr
, remaddr
;
954 char user
[UT_NAMESIZE
];
955 char local_service
[NI_MAXSERV
], remote_service
[NI_MAXSERV
];
957 if (family
== AF_INET
)
959 sscanf (local_address
, "%X",
960 &locaddr
.sin
.sin_addr
.s_addr
);
961 sscanf (remote_address
, "%X",
962 &remaddr
.sin
.sin_addr
.s_addr
);
964 locaddr
.sin
.sin_port
= htons (local_port
);
965 remaddr
.sin
.sin_port
= htons (remote_port
);
967 addr_size
= sizeof (struct sockaddr_in
);
971 sscanf (local_address
, "%8X%8X%8X%8X",
972 locaddr
.sin6
.sin6_addr
.s6_addr32
,
973 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
974 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
975 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
976 sscanf (remote_address
, "%8X%8X%8X%8X",
977 remaddr
.sin6
.sin6_addr
.s6_addr32
,
978 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
979 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
980 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
982 locaddr
.sin6
.sin6_port
= htons (local_port
);
983 remaddr
.sin6
.sin6_port
= htons (remote_port
);
985 locaddr
.sin6
.sin6_flowinfo
= 0;
986 remaddr
.sin6
.sin6_flowinfo
= 0;
987 locaddr
.sin6
.sin6_scope_id
= 0;
988 remaddr
.sin6
.sin6_scope_id
= 0;
990 addr_size
= sizeof (struct sockaddr_in6
);
993 locaddr
.sa
.sa_family
= remaddr
.sa
.sa_family
= family
;
995 result
= getnameinfo (&locaddr
.sa
, addr_size
,
996 local_address
, sizeof (local_address
),
997 local_service
, sizeof (local_service
),
998 NI_NUMERICHOST
| NI_NUMERICSERV
999 | (tcp
? 0 : NI_DGRAM
));
1003 result
= getnameinfo (&remaddr
.sa
, addr_size
,
1005 sizeof (remote_address
),
1007 sizeof (remote_service
),
1008 NI_NUMERICHOST
| NI_NUMERICSERV
1009 | (tcp
? 0 : NI_DGRAM
));
1013 user_from_uid (user
, sizeof (user
), uid
);
1018 "<column name=\"local address\">%s</column>"
1019 "<column name=\"local port\">%s</column>"
1020 "<column name=\"remote address\">%s</column>"
1021 "<column name=\"remote port\">%s</column>"
1022 "<column name=\"state\">%s</column>"
1023 "<column name=\"user\">%s</column>"
1024 "<column name=\"family\">%s</column>"
1025 "<column name=\"protocol\">%s</column>"
1031 format_socket_state (state
),
1033 (family
== AF_INET
) ? "INET" : "INET6",
1034 tcp
? "STREAM" : "DGRAM");
1038 while (!feof (fp
.get ()));
1042 /* Collect data about internet sockets and write it into READBUF. */
1045 linux_xfer_osdata_isockets (gdb_byte
*readbuf
,
1046 ULONGEST offset
, ULONGEST len
)
1048 static const char *buf
;
1049 static LONGEST len_avail
= -1;
1050 static struct buffer buffer
;
1054 if (len_avail
!= -1 && len_avail
!= 0)
1055 buffer_free (&buffer
);
1058 buffer_init (&buffer
);
1059 buffer_grow_str (&buffer
, "<osdata type=\"I sockets\">\n");
1061 print_sockets (AF_INET
, 1, &buffer
);
1062 print_sockets (AF_INET
, 0, &buffer
);
1063 print_sockets (AF_INET6
, 1, &buffer
);
1064 print_sockets (AF_INET6
, 0, &buffer
);
1066 buffer_grow_str0 (&buffer
, "</osdata>\n");
1067 buf
= buffer_finish (&buffer
);
1068 len_avail
= strlen (buf
);
1071 if (offset
>= len_avail
)
1073 /* Done. Get rid of the buffer. */
1074 buffer_free (&buffer
);
1080 if (len
> len_avail
- offset
)
1081 len
= len_avail
- offset
;
1082 memcpy (readbuf
, buf
+ offset
, len
);
1087 /* Converts the time SECONDS into textual form and copies it into a
1088 buffer TIME, with at most MAXLEN characters copied. */
1091 time_from_time_t (char *time
, int maxlen
, TIME_T seconds
)
1097 time_t t
= (time_t) seconds
;
1099 strncpy (time
, ctime (&t
), maxlen
);
1100 time
[maxlen
- 1] = '\0';
1104 /* Finds the group name for the group GID and copies it into GROUP.
1105 At most MAXLEN characters are copied. */
1108 group_from_gid (char *group
, int maxlen
, gid_t gid
)
1110 struct group
*grentry
= getgrgid (gid
);
1114 strncpy (group
, grentry
->gr_name
, maxlen
);
1115 /* Ensure that the group name is null-terminated. */
1116 group
[maxlen
- 1] = '\0';
1122 /* Collect data about shared memory recorded in /proc and write it
1126 linux_xfer_osdata_shm (gdb_byte
*readbuf
,
1127 ULONGEST offset
, ULONGEST len
)
1129 static const char *buf
;
1130 static LONGEST len_avail
= -1;
1131 static struct buffer buffer
;
1135 if (len_avail
!= -1 && len_avail
!= 0)
1136 buffer_free (&buffer
);
1139 buffer_init (&buffer
);
1140 buffer_grow_str (&buffer
, "<osdata type=\"shared memory\">\n");
1142 gdb_file_up fp
= gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1149 if (fgets (buf
, sizeof (buf
), fp
.get ()))
1155 int shmid
, size
, nattch
;
1156 TIME_T atime
, dtime
, ctime
;
1160 items_read
= sscanf (buf
,
1161 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1162 &key
, &shmid
, &perms
, &size
,
1165 &uid
, &gid
, &cuid
, &cgid
,
1166 &atime
, &dtime
, &ctime
);
1168 if (items_read
== 14)
1170 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1171 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1172 char ccmd
[32], lcmd
[32];
1173 char atime_str
[32], dtime_str
[32], ctime_str
[32];
1175 user_from_uid (user
, sizeof (user
), uid
);
1176 group_from_gid (group
, sizeof (group
), gid
);
1177 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1178 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1180 command_from_pid (ccmd
, sizeof (ccmd
), cpid
);
1181 command_from_pid (lcmd
, sizeof (lcmd
), lpid
);
1183 time_from_time_t (atime_str
, sizeof (atime_str
), atime
);
1184 time_from_time_t (dtime_str
, sizeof (dtime_str
), dtime
);
1185 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1190 "<column name=\"key\">%d</column>"
1191 "<column name=\"shmid\">%d</column>"
1192 "<column name=\"permissions\">%o</column>"
1193 "<column name=\"size\">%d</column>"
1194 "<column name=\"creator command\">%s</column>"
1195 "<column name=\"last op. command\">%s</column>"
1196 "<column name=\"num attached\">%d</column>"
1197 "<column name=\"user\">%s</column>"
1198 "<column name=\"group\">%s</column>"
1199 "<column name=\"creator user\">%s</column>"
1200 "<column name=\"creator group\">%s</column>"
1201 "<column name=\"last shmat() time\">%s</column>"
1202 "<column name=\"last shmdt() time\">%s</column>"
1203 "<column name=\"last shmctl() time\">%s</column>"
1222 while (!feof (fp
.get ()));
1225 buffer_grow_str0 (&buffer
, "</osdata>\n");
1226 buf
= buffer_finish (&buffer
);
1227 len_avail
= strlen (buf
);
1230 if (offset
>= len_avail
)
1232 /* Done. Get rid of the buffer. */
1233 buffer_free (&buffer
);
1239 if (len
> len_avail
- offset
)
1240 len
= len_avail
- offset
;
1241 memcpy (readbuf
, buf
+ offset
, len
);
1246 /* Collect data about semaphores recorded in /proc and write it
1250 linux_xfer_osdata_sem (gdb_byte
*readbuf
,
1251 ULONGEST offset
, ULONGEST len
)
1253 static const char *buf
;
1254 static LONGEST len_avail
= -1;
1255 static struct buffer buffer
;
1259 if (len_avail
!= -1 && len_avail
!= 0)
1260 buffer_free (&buffer
);
1263 buffer_init (&buffer
);
1264 buffer_grow_str (&buffer
, "<osdata type=\"semaphores\">\n");
1266 gdb_file_up fp
= gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1273 if (fgets (buf
, sizeof (buf
), fp
.get ()))
1278 unsigned int perms
, nsems
;
1280 TIME_T otime
, ctime
;
1283 items_read
= sscanf (buf
,
1284 "%d %d %o %u %d %d %d %d %lld %lld",
1285 &key
, &semid
, &perms
, &nsems
,
1286 &uid
, &gid
, &cuid
, &cgid
,
1289 if (items_read
== 10)
1291 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1292 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1293 char otime_str
[32], ctime_str
[32];
1295 user_from_uid (user
, sizeof (user
), uid
);
1296 group_from_gid (group
, sizeof (group
), gid
);
1297 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1298 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1300 time_from_time_t (otime_str
, sizeof (otime_str
), otime
);
1301 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1306 "<column name=\"key\">%d</column>"
1307 "<column name=\"semid\">%d</column>"
1308 "<column name=\"permissions\">%o</column>"
1309 "<column name=\"num semaphores\">%u</column>"
1310 "<column name=\"user\">%s</column>"
1311 "<column name=\"group\">%s</column>"
1312 "<column name=\"creator user\">%s</column>"
1313 "<column name=\"creator group\">%s</column>"
1314 "<column name=\"last semop() time\">%s</column>"
1315 "<column name=\"last semctl() time\">%s</column>"
1330 while (!feof (fp
.get ()));
1333 buffer_grow_str0 (&buffer
, "</osdata>\n");
1334 buf
= buffer_finish (&buffer
);
1335 len_avail
= strlen (buf
);
1338 if (offset
>= len_avail
)
1340 /* Done. Get rid of the buffer. */
1341 buffer_free (&buffer
);
1347 if (len
> len_avail
- offset
)
1348 len
= len_avail
- offset
;
1349 memcpy (readbuf
, buf
+ offset
, len
);
1354 /* Collect data about message queues recorded in /proc and write it
1358 linux_xfer_osdata_msg (gdb_byte
*readbuf
,
1359 ULONGEST offset
, ULONGEST len
)
1361 static const char *buf
;
1362 static LONGEST len_avail
= -1;
1363 static struct buffer buffer
;
1367 if (len_avail
!= -1 && len_avail
!= 0)
1368 buffer_free (&buffer
);
1371 buffer_init (&buffer
);
1372 buffer_grow_str (&buffer
, "<osdata type=\"message queues\">\n");
1374 gdb_file_up fp
= gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1381 if (fgets (buf
, sizeof (buf
), fp
.get ()))
1387 unsigned int perms
, cbytes
, qnum
;
1389 TIME_T stime
, rtime
, ctime
;
1392 items_read
= sscanf (buf
,
1393 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1394 &key
, &msqid
, &perms
, &cbytes
, &qnum
,
1395 &lspid
, &lrpid
, &uid
, &gid
, &cuid
, &cgid
,
1396 &stime
, &rtime
, &ctime
);
1398 if (items_read
== 14)
1400 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1401 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1402 char lscmd
[32], lrcmd
[32];
1403 char stime_str
[32], rtime_str
[32], ctime_str
[32];
1405 user_from_uid (user
, sizeof (user
), uid
);
1406 group_from_gid (group
, sizeof (group
), gid
);
1407 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1408 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1410 command_from_pid (lscmd
, sizeof (lscmd
), lspid
);
1411 command_from_pid (lrcmd
, sizeof (lrcmd
), lrpid
);
1413 time_from_time_t (stime_str
, sizeof (stime_str
), stime
);
1414 time_from_time_t (rtime_str
, sizeof (rtime_str
), rtime
);
1415 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1420 "<column name=\"key\">%d</column>"
1421 "<column name=\"msqid\">%d</column>"
1422 "<column name=\"permissions\">%o</column>"
1423 "<column name=\"num used bytes\">%u</column>"
1424 "<column name=\"num messages\">%u</column>"
1425 "<column name=\"last msgsnd() command\">%s</column>"
1426 "<column name=\"last msgrcv() command\">%s</column>"
1427 "<column name=\"user\">%s</column>"
1428 "<column name=\"group\">%s</column>"
1429 "<column name=\"creator user\">%s</column>"
1430 "<column name=\"creator group\">%s</column>"
1431 "<column name=\"last msgsnd() time\">%s</column>"
1432 "<column name=\"last msgrcv() time\">%s</column>"
1433 "<column name=\"last msgctl() time\">%s</column>"
1452 while (!feof (fp
.get ()));
1455 buffer_grow_str0 (&buffer
, "</osdata>\n");
1456 buf
= buffer_finish (&buffer
);
1457 len_avail
= strlen (buf
);
1460 if (offset
>= len_avail
)
1462 /* Done. Get rid of the buffer. */
1463 buffer_free (&buffer
);
1469 if (len
> len_avail
- offset
)
1470 len
= len_avail
- offset
;
1471 memcpy (readbuf
, buf
+ offset
, len
);
1476 /* Collect data about loaded kernel modules and write it into
1480 linux_xfer_osdata_modules (gdb_byte
*readbuf
,
1481 ULONGEST offset
, ULONGEST len
)
1483 static const char *buf
;
1484 static LONGEST len_avail
= -1;
1485 static struct buffer buffer
;
1489 if (len_avail
!= -1 && len_avail
!= 0)
1490 buffer_free (&buffer
);
1493 buffer_init (&buffer
);
1494 buffer_grow_str (&buffer
, "<osdata type=\"modules\">\n");
1496 gdb_file_up fp
= gdb_fopen_cloexec ("/proc/modules", "r");
1503 if (fgets (buf
, sizeof (buf
), fp
.get ()))
1505 char *name
, *dependencies
, *status
, *tmp
;
1507 unsigned long long address
;
1510 name
= strtok (buf
, " ");
1514 tmp
= strtok (NULL
, " ");
1517 if (sscanf (tmp
, "%u", &size
) != 1)
1520 tmp
= strtok (NULL
, " ");
1523 if (sscanf (tmp
, "%d", &uses
) != 1)
1526 dependencies
= strtok (NULL
, " ");
1527 if (dependencies
== NULL
)
1530 status
= strtok (NULL
, " ");
1534 tmp
= strtok (NULL
, "\n");
1537 if (sscanf (tmp
, "%llx", &address
) != 1)
1543 "<column name=\"name\">%s</column>"
1544 "<column name=\"size\">%u</column>"
1545 "<column name=\"num uses\">%d</column>"
1546 "<column name=\"dependencies\">%s</column>"
1547 "<column name=\"status\">%s</column>"
1548 "<column name=\"address\">%llx</column>"
1558 while (!feof (fp
.get ()));
1561 buffer_grow_str0 (&buffer
, "</osdata>\n");
1562 buf
= buffer_finish (&buffer
);
1563 len_avail
= strlen (buf
);
1566 if (offset
>= len_avail
)
1568 /* Done. Get rid of the buffer. */
1569 buffer_free (&buffer
);
1575 if (len
> len_avail
- offset
)
1576 len
= len_avail
- offset
;
1577 memcpy (readbuf
, buf
+ offset
, len
);
1582 struct osdata_type
{
1585 const char *description
;
1586 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, ULONGEST len
);
1587 } osdata_table
[] = {
1588 { "cpus", "CPUs", "Listing of all cpus/cores on the system",
1589 linux_xfer_osdata_cpus
},
1590 { "files", "File descriptors", "Listing of all file descriptors",
1591 linux_xfer_osdata_fds
},
1592 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1593 linux_xfer_osdata_modules
},
1594 { "msg", "Message queues", "Listing of all message queues",
1595 linux_xfer_osdata_msg
},
1596 { "processes", "Processes", "Listing of all processes",
1597 linux_xfer_osdata_processes
},
1598 { "procgroups", "Process groups", "Listing of all process groups",
1599 linux_xfer_osdata_processgroups
},
1600 { "semaphores", "Semaphores", "Listing of all semaphores",
1601 linux_xfer_osdata_sem
},
1602 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1603 linux_xfer_osdata_shm
},
1604 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1605 linux_xfer_osdata_isockets
},
1606 { "threads", "Threads", "Listing of all threads",
1607 linux_xfer_osdata_threads
},
1608 { NULL
, NULL
, NULL
}
1612 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
1613 ULONGEST offset
, ULONGEST len
)
1615 if (!annex
|| *annex
== '\0')
1617 static const char *buf
;
1618 static LONGEST len_avail
= -1;
1619 static struct buffer buffer
;
1625 if (len_avail
!= -1 && len_avail
!= 0)
1626 buffer_free (&buffer
);
1629 buffer_init (&buffer
);
1630 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
1632 for (i
= 0; osdata_table
[i
].type
; ++i
)
1636 "<column name=\"Type\">%s</column>"
1637 "<column name=\"Description\">%s</column>"
1638 "<column name=\"Title\">%s</column>"
1640 osdata_table
[i
].type
,
1641 osdata_table
[i
].description
,
1642 osdata_table
[i
].title
);
1644 buffer_grow_str0 (&buffer
, "</osdata>\n");
1645 buf
= buffer_finish (&buffer
);
1646 len_avail
= strlen (buf
);
1649 if (offset
>= len_avail
)
1651 /* Done. Get rid of the buffer. */
1652 buffer_free (&buffer
);
1658 if (len
> len_avail
- offset
)
1659 len
= len_avail
- offset
;
1660 memcpy (readbuf
, buf
+ offset
, len
);
1668 for (i
= 0; osdata_table
[i
].type
; ++i
)
1670 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
1672 gdb_assert (readbuf
);
1674 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);