1 /* Linux-specific functions to retrieve OS data.
3 Copyright (C) 2009-2015 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"
41 #define NAMELEN(dirent) strlen ((dirent)->d_name)
43 /* Define PID_T to be a fixed size that is at least as large as pid_t,
44 so that reading pid values embedded in /proc works
47 typedef long long PID_T
;
49 /* Define TIME_T to be at least as large as time_t, so that reading
50 time values embedded in /proc works consistently. */
52 typedef long long TIME_T
;
54 #define MAX_PID_T_STRLEN (sizeof ("-9223372036854775808") - 1)
56 /* Returns the CPU core that thread PTID is currently running on. */
58 /* Compute and return the processor core of a given thread. */
61 linux_common_core_of_thread (ptid_t ptid
)
63 char filename
[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN
];
72 sprintf (filename
, "/proc/%lld/task/%lld/stat",
73 (PID_T
) ptid_get_pid (ptid
), (PID_T
) ptid_get_lwp (ptid
));
74 f
= gdb_fopen_cloexec (filename
, "r");
81 content
= xrealloc (content
, content_read
+ 1024);
82 n
= fread (content
+ content_read
, 1, 1024, f
);
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)
112 /* Finds the command-line of process PID and copies it into COMMAND.
113 At most MAXLEN characters are copied. If the command-line cannot
114 be found, PID is copied into command in text-form. */
117 command_from_pid (char *command
, int maxlen
, PID_T pid
)
119 char *stat_path
= xstrprintf ("/proc/%lld/stat", pid
);
120 FILE *fp
= gdb_fopen_cloexec (stat_path
, "r");
126 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
127 include/linux/sched.h in the Linux kernel sources) plus two
128 (for the brackets). */
131 int items_read
= fscanf (fp
, "%lld %17s", &stat_pid
, cmd
);
133 if (items_read
== 2 && pid
== stat_pid
)
135 cmd
[strlen (cmd
) - 1] = '\0'; /* Remove trailing parenthesis. */
136 strncpy (command
, cmd
+ 1, maxlen
); /* Ignore leading parenthesis. */
143 /* Return the PID if a /proc entry for the process cannot be found. */
144 snprintf (command
, maxlen
, "%lld", pid
);
147 command
[maxlen
- 1] = '\0'; /* Ensure string is null-terminated. */
152 /* Returns the command-line of the process with the given PID. The
153 returned string needs to be freed using xfree after use. */
156 commandline_from_pid (PID_T pid
)
158 char *pathname
= xstrprintf ("/proc/%lld/cmdline", pid
);
159 char *commandline
= NULL
;
160 FILE *f
= gdb_fopen_cloexec (pathname
, "r");
169 size_t read_bytes
= fread (buf
, 1, sizeof (buf
), f
);
173 commandline
= (char *) xrealloc (commandline
, len
+ read_bytes
+ 1);
174 memcpy (commandline
+ len
, buf
, read_bytes
);
185 /* Replace null characters with spaces. */
186 for (i
= 0; i
< len
; ++i
)
187 if (commandline
[i
] == '\0')
188 commandline
[i
] = ' ';
190 commandline
[len
] = '\0';
194 /* Return the command in square brackets if the command-line
196 commandline
= (char *) xmalloc (32);
197 commandline
[0] = '[';
198 command_from_pid (commandline
+ 1, 31, pid
);
200 len
= strlen (commandline
);
202 strcat (commandline
, "]");
211 /* Finds the user name for the user UID and copies it into USER. At
212 most MAXLEN characters are copied. */
215 user_from_uid (char *user
, int maxlen
, uid_t uid
)
217 struct passwd
*pwentry
= getpwuid (uid
);
221 strncpy (user
, pwentry
->pw_name
, maxlen
);
222 /* Ensure that the user name is null-terminated. */
223 user
[maxlen
- 1] = '\0';
229 /* Finds the owner of process PID and returns the user id in OWNER.
230 Returns 0 if the owner was found, -1 otherwise. */
233 get_process_owner (uid_t
*owner
, PID_T pid
)
236 char procentry
[sizeof ("/proc/") + MAX_PID_T_STRLEN
];
238 sprintf (procentry
, "/proc/%lld", pid
);
240 if (stat (procentry
, &statbuf
) == 0 && S_ISDIR (statbuf
.st_mode
))
242 *owner
= statbuf
.st_uid
;
249 /* Find the CPU cores used by process PID and return them in CORES.
250 CORES points to an array of NUM_CORES elements. */
253 get_cores_used_by_process (PID_T pid
, int *cores
, const int num_cores
)
255 char taskdir
[sizeof ("/proc/") + MAX_PID_T_STRLEN
+ sizeof ("/task") - 1];
260 sprintf (taskdir
, "/proc/%lld/task", pid
);
261 dir
= opendir (taskdir
);
264 while ((dp
= readdir (dir
)) != NULL
)
269 if (!isdigit (dp
->d_name
[0])
270 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
273 sscanf (dp
->d_name
, "%lld", &tid
);
274 core
= linux_common_core_of_thread (ptid_build ((pid_t
) pid
,
277 if (core
>= 0 && core
< num_cores
)
291 linux_xfer_osdata_processes (gdb_byte
*readbuf
,
292 ULONGEST offset
, ULONGEST len
)
294 /* We make the process list snapshot when the object starts to be read. */
295 static const char *buf
;
296 static LONGEST len_avail
= -1;
297 static struct buffer buffer
;
303 if (len_avail
!= -1 && len_avail
!= 0)
304 buffer_free (&buffer
);
307 buffer_init (&buffer
);
308 buffer_grow_str (&buffer
, "<osdata type=\"processes\">\n");
310 dirp
= opendir ("/proc");
313 const int num_cores
= sysconf (_SC_NPROCESSORS_ONLN
);
316 while ((dp
= readdir (dirp
)) != NULL
)
320 char user
[UT_NAMESIZE
];
327 if (!isdigit (dp
->d_name
[0])
328 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
331 sscanf (dp
->d_name
, "%lld", &pid
);
332 command_line
= commandline_from_pid (pid
);
334 if (get_process_owner (&owner
, pid
) == 0)
335 user_from_uid (user
, sizeof (user
), owner
);
339 /* Find CPU cores used by the process. */
340 cores
= XCNEWVEC (int, num_cores
);
341 task_count
= get_cores_used_by_process (pid
, cores
, num_cores
);
342 cores_str
= (char *) xcalloc (task_count
, sizeof ("4294967295") + 1);
344 for (i
= 0; i
< num_cores
&& task_count
> 0; ++i
)
347 char core_str
[sizeof ("4294967295")];
349 sprintf (core_str
, "%d", i
);
350 strcat (cores_str
, core_str
);
352 task_count
-= cores
[i
];
354 strcat (cores_str
, ",");
362 "<column name=\"pid\">%lld</column>"
363 "<column name=\"user\">%s</column>"
364 "<column name=\"command\">%s</column>"
365 "<column name=\"cores\">%s</column>"
369 command_line
? command_line
: "",
372 xfree (command_line
);
379 buffer_grow_str0 (&buffer
, "</osdata>\n");
380 buf
= buffer_finish (&buffer
);
381 len_avail
= strlen (buf
);
384 if (offset
>= len_avail
)
386 /* Done. Get rid of the buffer. */
387 buffer_free (&buffer
);
393 if (len
> len_avail
- offset
)
394 len
= len_avail
- offset
;
395 memcpy (readbuf
, buf
+ offset
, len
);
400 /* Auxiliary function used by qsort to sort processes by process
401 group. Compares two processes with ids PROCESS1 and PROCESS2.
402 PROCESS1 comes before PROCESS2 if it has a lower process group id.
403 If they belong to the same process group, PROCESS1 comes before
404 PROCESS2 if it has a lower process id or is the process group
408 compare_processes (const void *process1
, const void *process2
)
410 PID_T pid1
= *((PID_T
*) process1
);
411 PID_T pid2
= *((PID_T
*) process2
);
412 PID_T pgid1
= *((PID_T
*) process1
+ 1);
413 PID_T pgid2
= *((PID_T
*) process2
+ 1);
418 else if (pgid1
> pgid2
)
422 /* Process group leaders always come first, else sort by PID. */
425 else if (pid2
== pgid2
)
427 else if (pid1
< pid2
)
429 else if (pid1
> pid2
)
436 /* Collect all process groups from /proc. */
439 linux_xfer_osdata_processgroups (gdb_byte
*readbuf
,
440 ULONGEST offset
, ULONGEST len
)
442 /* We make the process list snapshot when the object starts to be read. */
443 static const char *buf
;
444 static LONGEST len_avail
= -1;
445 static struct buffer buffer
;
451 if (len_avail
!= -1 && len_avail
!= 0)
452 buffer_free (&buffer
);
455 buffer_init (&buffer
);
456 buffer_grow_str (&buffer
, "<osdata type=\"process groups\">\n");
458 dirp
= opendir ("/proc");
462 const size_t list_block_size
= 512;
463 PID_T
*process_list
= XNEWVEC (PID_T
, list_block_size
* 2);
464 size_t process_count
= 0;
467 /* Build list consisting of PIDs followed by their
469 while ((dp
= readdir (dirp
)) != NULL
)
473 if (!isdigit (dp
->d_name
[0])
474 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
477 sscanf (dp
->d_name
, "%lld", &pid
);
478 pgid
= getpgid (pid
);
482 process_list
[2 * process_count
] = pid
;
483 process_list
[2 * process_count
+ 1] = pgid
;
486 /* Increase the size of the list if necessary. */
487 if (process_count
% list_block_size
== 0)
488 process_list
= (PID_T
*) xrealloc (
490 (process_count
+ list_block_size
)
491 * 2 * sizeof (PID_T
));
497 /* Sort the process list. */
498 qsort (process_list
, process_count
, 2 * sizeof (PID_T
),
501 for (i
= 0; i
< process_count
; ++i
)
503 PID_T pid
= process_list
[2 * i
];
504 PID_T pgid
= process_list
[2 * i
+ 1];
505 char leader_command
[32];
508 command_from_pid (leader_command
, sizeof (leader_command
), pgid
);
509 command_line
= commandline_from_pid (pid
);
514 "<column name=\"pgid\">%lld</column>"
515 "<column name=\"leader command\">%s</column>"
516 "<column name=\"pid\">%lld</column>"
517 "<column name=\"command line\">%s</column>"
522 command_line
? command_line
: "");
524 xfree (command_line
);
527 xfree (process_list
);
530 buffer_grow_str0 (&buffer
, "</osdata>\n");
531 buf
= buffer_finish (&buffer
);
532 len_avail
= strlen (buf
);
535 if (offset
>= len_avail
)
537 /* Done. Get rid of the buffer. */
538 buffer_free (&buffer
);
544 if (len
> len_avail
- offset
)
545 len
= len_avail
- offset
;
546 memcpy (readbuf
, buf
+ offset
, len
);
551 /* Collect all the threads in /proc by iterating through processes and
552 then tasks within each process. */
555 linux_xfer_osdata_threads (gdb_byte
*readbuf
,
556 ULONGEST offset
, ULONGEST len
)
558 /* We make the process list snapshot when the object starts to be read. */
559 static const char *buf
;
560 static LONGEST len_avail
= -1;
561 static struct buffer buffer
;
567 if (len_avail
!= -1 && len_avail
!= 0)
568 buffer_free (&buffer
);
571 buffer_init (&buffer
);
572 buffer_grow_str (&buffer
, "<osdata type=\"threads\">\n");
574 dirp
= opendir ("/proc");
579 while ((dp
= readdir (dirp
)) != NULL
)
582 char procentry
[sizeof ("/proc/4294967295")];
584 if (!isdigit (dp
->d_name
[0])
585 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
588 sprintf (procentry
, "/proc/%s", dp
->d_name
);
589 if (stat (procentry
, &statbuf
) == 0
590 && S_ISDIR (statbuf
.st_mode
))
597 pathname
= xstrprintf ("/proc/%s/task", dp
->d_name
);
599 pid
= atoi (dp
->d_name
);
600 command_from_pid (command
, sizeof (command
), pid
);
602 dirp2
= opendir (pathname
);
608 while ((dp2
= readdir (dirp2
)) != NULL
)
613 if (!isdigit (dp2
->d_name
[0])
614 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
617 tid
= atoi (dp2
->d_name
);
618 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
623 "<column name=\"pid\">%lld</column>"
624 "<column name=\"command\">%s</column>"
625 "<column name=\"tid\">%lld</column>"
626 "<column name=\"core\">%d</column>"
644 buffer_grow_str0 (&buffer
, "</osdata>\n");
645 buf
= buffer_finish (&buffer
);
646 len_avail
= strlen (buf
);
649 if (offset
>= len_avail
)
651 /* Done. Get rid of the buffer. */
652 buffer_free (&buffer
);
658 if (len
> len_avail
- offset
)
659 len
= len_avail
- offset
;
660 memcpy (readbuf
, buf
+ offset
, len
);
665 /* Collect data about the cpus/cores on the system */
668 linux_xfer_osdata_cpus (gdb_byte
*readbuf
,
669 ULONGEST offset
, ULONGEST len
)
671 static const char *buf
;
672 static LONGEST len_avail
= -1;
673 static struct buffer buffer
;
680 if (len_avail
!= -1 && len_avail
!= 0)
681 buffer_free (&buffer
);
684 buffer_init (&buffer
);
685 buffer_grow_str (&buffer
, "<osdata type=\"cpus\">\n");
687 fp
= gdb_fopen_cloexec ("/proc/cpuinfo", "r");
694 if (fgets (buf
, sizeof (buf
), fp
))
699 key
= strtok (buf
, ":");
703 value
= strtok (NULL
, ":");
707 while (key
[i
] != '\t' && key
[i
] != '\0')
713 while (value
[i
] != '\t' && value
[i
] != '\0')
718 if (strcmp (key
, "processor") == 0)
721 buffer_grow_str (&buffer
, "<item>");
723 buffer_grow_str (&buffer
, "</item><item>");
728 buffer_xml_printf (&buffer
,
729 "<column name=\"%s\">%s</column>",
737 buffer_grow_str (&buffer
, "</item>");
742 buffer_grow_str0 (&buffer
, "</osdata>\n");
743 buf
= buffer_finish (&buffer
);
744 len_avail
= strlen (buf
);
747 if (offset
>= len_avail
)
749 /* Done. Get rid of the buffer. */
750 buffer_free (&buffer
);
756 if (len
> len_avail
- offset
)
757 len
= len_avail
- offset
;
758 memcpy (readbuf
, buf
+ offset
, len
);
763 /* Collect all the open file descriptors found in /proc and put the details
764 found about them into READBUF. */
767 linux_xfer_osdata_fds (gdb_byte
*readbuf
,
768 ULONGEST offset
, ULONGEST len
)
770 /* We make the process list snapshot when the object starts to be read. */
771 static const char *buf
;
772 static LONGEST len_avail
= -1;
773 static struct buffer buffer
;
779 if (len_avail
!= -1 && len_avail
!= 0)
780 buffer_free (&buffer
);
783 buffer_init (&buffer
);
784 buffer_grow_str (&buffer
, "<osdata type=\"files\">\n");
786 dirp
= opendir ("/proc");
791 while ((dp
= readdir (dirp
)) != NULL
)
794 char procentry
[sizeof ("/proc/4294967295")];
796 if (!isdigit (dp
->d_name
[0])
797 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
800 sprintf (procentry
, "/proc/%s", dp
->d_name
);
801 if (stat (procentry
, &statbuf
) == 0
802 && S_ISDIR (statbuf
.st_mode
))
809 pid
= atoi (dp
->d_name
);
810 command_from_pid (command
, sizeof (command
), pid
);
812 pathname
= xstrprintf ("/proc/%s/fd", dp
->d_name
);
813 dirp2
= opendir (pathname
);
819 while ((dp2
= readdir (dirp2
)) != NULL
)
825 if (!isdigit (dp2
->d_name
[0]))
828 fdname
= xstrprintf ("%s/%s", pathname
, dp2
->d_name
);
829 rslt
= readlink (fdname
, buf
, sizeof (buf
) - 1);
836 "<column name=\"pid\">%s</column>"
837 "<column name=\"command\">%s</column>"
838 "<column name=\"file descriptor\">%s</column>"
839 "<column name=\"name\">%s</column>"
844 (rslt
>= 0 ? buf
: dp2
->d_name
));
857 buffer_grow_str0 (&buffer
, "</osdata>\n");
858 buf
= buffer_finish (&buffer
);
859 len_avail
= strlen (buf
);
862 if (offset
>= len_avail
)
864 /* Done. Get rid of the buffer. */
865 buffer_free (&buffer
);
871 if (len
> len_avail
- offset
)
872 len
= len_avail
- offset
;
873 memcpy (readbuf
, buf
+ offset
, len
);
878 /* Returns the socket state STATE in textual form. */
881 format_socket_state (unsigned char state
)
883 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
900 case TCP_ESTABLISHED
:
901 return "ESTABLISHED";
930 struct sockaddr_in sin
;
931 struct sockaddr_in6 sin6
;
934 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
935 information for all open internet sockets of type FAMILY on the
936 system into BUFFER. If TCP is set, only TCP sockets are processed,
937 otherwise only UDP sockets are processed. */
940 print_sockets (unsigned short family
, int tcp
, struct buffer
*buffer
)
942 const char *proc_file
;
945 if (family
== AF_INET
)
946 proc_file
= tcp
? "/proc/net/tcp" : "/proc/net/udp";
947 else if (family
== AF_INET6
)
948 proc_file
= tcp
? "/proc/net/tcp6" : "/proc/net/udp6";
952 fp
= gdb_fopen_cloexec (proc_file
, "r");
959 if (fgets (buf
, sizeof (buf
), fp
))
962 unsigned int local_port
, remote_port
, state
;
963 char local_address
[NI_MAXHOST
], remote_address
[NI_MAXHOST
];
967 #error "local_address and remote_address buffers too small"
970 result
= sscanf (buf
,
971 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
972 local_address
, &local_port
,
973 remote_address
, &remote_port
,
979 union socket_addr locaddr
, remaddr
;
981 char user
[UT_NAMESIZE
];
982 char local_service
[NI_MAXSERV
], remote_service
[NI_MAXSERV
];
984 if (family
== AF_INET
)
986 sscanf (local_address
, "%X",
987 &locaddr
.sin
.sin_addr
.s_addr
);
988 sscanf (remote_address
, "%X",
989 &remaddr
.sin
.sin_addr
.s_addr
);
991 locaddr
.sin
.sin_port
= htons (local_port
);
992 remaddr
.sin
.sin_port
= htons (remote_port
);
994 addr_size
= sizeof (struct sockaddr_in
);
998 sscanf (local_address
, "%8X%8X%8X%8X",
999 locaddr
.sin6
.sin6_addr
.s6_addr32
,
1000 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
1001 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
1002 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
1003 sscanf (remote_address
, "%8X%8X%8X%8X",
1004 remaddr
.sin6
.sin6_addr
.s6_addr32
,
1005 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
1006 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
1007 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
1009 locaddr
.sin6
.sin6_port
= htons (local_port
);
1010 remaddr
.sin6
.sin6_port
= htons (remote_port
);
1012 locaddr
.sin6
.sin6_flowinfo
= 0;
1013 remaddr
.sin6
.sin6_flowinfo
= 0;
1014 locaddr
.sin6
.sin6_scope_id
= 0;
1015 remaddr
.sin6
.sin6_scope_id
= 0;
1017 addr_size
= sizeof (struct sockaddr_in6
);
1020 locaddr
.sa
.sa_family
= remaddr
.sa
.sa_family
= family
;
1022 result
= getnameinfo (&locaddr
.sa
, addr_size
,
1023 local_address
, sizeof (local_address
),
1024 local_service
, sizeof (local_service
),
1025 NI_NUMERICHOST
| NI_NUMERICSERV
1026 | (tcp
? 0 : NI_DGRAM
));
1030 result
= getnameinfo (&remaddr
.sa
, addr_size
,
1032 sizeof (remote_address
),
1034 sizeof (remote_service
),
1035 NI_NUMERICHOST
| NI_NUMERICSERV
1036 | (tcp
? 0 : NI_DGRAM
));
1040 user_from_uid (user
, sizeof (user
), uid
);
1045 "<column name=\"local address\">%s</column>"
1046 "<column name=\"local port\">%s</column>"
1047 "<column name=\"remote address\">%s</column>"
1048 "<column name=\"remote port\">%s</column>"
1049 "<column name=\"state\">%s</column>"
1050 "<column name=\"user\">%s</column>"
1051 "<column name=\"family\">%s</column>"
1052 "<column name=\"protocol\">%s</column>"
1058 format_socket_state (state
),
1060 (family
== AF_INET
) ? "INET" : "INET6",
1061 tcp
? "STREAM" : "DGRAM");
1071 /* Collect data about internet sockets and write it into READBUF. */
1074 linux_xfer_osdata_isockets (gdb_byte
*readbuf
,
1075 ULONGEST offset
, ULONGEST len
)
1077 static const char *buf
;
1078 static LONGEST len_avail
= -1;
1079 static struct buffer buffer
;
1083 if (len_avail
!= -1 && len_avail
!= 0)
1084 buffer_free (&buffer
);
1087 buffer_init (&buffer
);
1088 buffer_grow_str (&buffer
, "<osdata type=\"I sockets\">\n");
1090 print_sockets (AF_INET
, 1, &buffer
);
1091 print_sockets (AF_INET
, 0, &buffer
);
1092 print_sockets (AF_INET6
, 1, &buffer
);
1093 print_sockets (AF_INET6
, 0, &buffer
);
1095 buffer_grow_str0 (&buffer
, "</osdata>\n");
1096 buf
= buffer_finish (&buffer
);
1097 len_avail
= strlen (buf
);
1100 if (offset
>= len_avail
)
1102 /* Done. Get rid of the buffer. */
1103 buffer_free (&buffer
);
1109 if (len
> len_avail
- offset
)
1110 len
= len_avail
- offset
;
1111 memcpy (readbuf
, buf
+ offset
, len
);
1116 /* Converts the time SECONDS into textual form and copies it into a
1117 buffer TIME, with at most MAXLEN characters copied. */
1120 time_from_time_t (char *time
, int maxlen
, TIME_T seconds
)
1126 time_t t
= (time_t) seconds
;
1128 strncpy (time
, ctime (&t
), maxlen
);
1129 time
[maxlen
- 1] = '\0';
1133 /* Finds the group name for the group GID and copies it into GROUP.
1134 At most MAXLEN characters are copied. */
1137 group_from_gid (char *group
, int maxlen
, gid_t gid
)
1139 struct group
*grentry
= getgrgid (gid
);
1143 strncpy (group
, grentry
->gr_name
, maxlen
);
1144 /* Ensure that the group name is null-terminated. */
1145 group
[maxlen
- 1] = '\0';
1151 /* Collect data about shared memory recorded in /proc and write it
1155 linux_xfer_osdata_shm (gdb_byte
*readbuf
,
1156 ULONGEST offset
, ULONGEST len
)
1158 static const char *buf
;
1159 static LONGEST len_avail
= -1;
1160 static struct buffer buffer
;
1166 if (len_avail
!= -1 && len_avail
!= 0)
1167 buffer_free (&buffer
);
1170 buffer_init (&buffer
);
1171 buffer_grow_str (&buffer
, "<osdata type=\"shared memory\">\n");
1173 fp
= gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1180 if (fgets (buf
, sizeof (buf
), fp
))
1186 int shmid
, size
, nattch
;
1187 TIME_T atime
, dtime
, ctime
;
1191 items_read
= sscanf (buf
,
1192 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1193 &key
, &shmid
, &perms
, &size
,
1196 &uid
, &gid
, &cuid
, &cgid
,
1197 &atime
, &dtime
, &ctime
);
1199 if (items_read
== 14)
1201 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1202 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1203 char ccmd
[32], lcmd
[32];
1204 char atime_str
[32], dtime_str
[32], ctime_str
[32];
1206 user_from_uid (user
, sizeof (user
), uid
);
1207 group_from_gid (group
, sizeof (group
), gid
);
1208 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1209 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1211 command_from_pid (ccmd
, sizeof (ccmd
), cpid
);
1212 command_from_pid (lcmd
, sizeof (lcmd
), lpid
);
1214 time_from_time_t (atime_str
, sizeof (atime_str
), atime
);
1215 time_from_time_t (dtime_str
, sizeof (dtime_str
), dtime
);
1216 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1221 "<column name=\"key\">%d</column>"
1222 "<column name=\"shmid\">%d</column>"
1223 "<column name=\"permissions\">%o</column>"
1224 "<column name=\"size\">%d</column>"
1225 "<column name=\"creator command\">%s</column>"
1226 "<column name=\"last op. command\">%s</column>"
1227 "<column name=\"num attached\">%d</column>"
1228 "<column name=\"user\">%s</column>"
1229 "<column name=\"group\">%s</column>"
1230 "<column name=\"creator user\">%s</column>"
1231 "<column name=\"creator group\">%s</column>"
1232 "<column name=\"last shmat() time\">%s</column>"
1233 "<column name=\"last shmdt() time\">%s</column>"
1234 "<column name=\"last shmctl() time\">%s</column>"
1258 buffer_grow_str0 (&buffer
, "</osdata>\n");
1259 buf
= buffer_finish (&buffer
);
1260 len_avail
= strlen (buf
);
1263 if (offset
>= len_avail
)
1265 /* Done. Get rid of the buffer. */
1266 buffer_free (&buffer
);
1272 if (len
> len_avail
- offset
)
1273 len
= len_avail
- offset
;
1274 memcpy (readbuf
, buf
+ offset
, len
);
1279 /* Collect data about semaphores recorded in /proc and write it
1283 linux_xfer_osdata_sem (gdb_byte
*readbuf
,
1284 ULONGEST offset
, ULONGEST len
)
1286 static const char *buf
;
1287 static LONGEST len_avail
= -1;
1288 static struct buffer buffer
;
1294 if (len_avail
!= -1 && len_avail
!= 0)
1295 buffer_free (&buffer
);
1298 buffer_init (&buffer
);
1299 buffer_grow_str (&buffer
, "<osdata type=\"semaphores\">\n");
1301 fp
= gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1308 if (fgets (buf
, sizeof (buf
), fp
))
1313 unsigned int perms
, nsems
;
1315 TIME_T otime
, ctime
;
1318 items_read
= sscanf (buf
,
1319 "%d %d %o %u %d %d %d %d %lld %lld",
1320 &key
, &semid
, &perms
, &nsems
,
1321 &uid
, &gid
, &cuid
, &cgid
,
1324 if (items_read
== 10)
1326 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1327 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1328 char otime_str
[32], ctime_str
[32];
1330 user_from_uid (user
, sizeof (user
), uid
);
1331 group_from_gid (group
, sizeof (group
), gid
);
1332 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1333 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1335 time_from_time_t (otime_str
, sizeof (otime_str
), otime
);
1336 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1341 "<column name=\"key\">%d</column>"
1342 "<column name=\"semid\">%d</column>"
1343 "<column name=\"permissions\">%o</column>"
1344 "<column name=\"num semaphores\">%u</column>"
1345 "<column name=\"user\">%s</column>"
1346 "<column name=\"group\">%s</column>"
1347 "<column name=\"creator user\">%s</column>"
1348 "<column name=\"creator group\">%s</column>"
1349 "<column name=\"last semop() time\">%s</column>"
1350 "<column name=\"last semctl() time\">%s</column>"
1370 buffer_grow_str0 (&buffer
, "</osdata>\n");
1371 buf
= buffer_finish (&buffer
);
1372 len_avail
= strlen (buf
);
1375 if (offset
>= len_avail
)
1377 /* Done. Get rid of the buffer. */
1378 buffer_free (&buffer
);
1384 if (len
> len_avail
- offset
)
1385 len
= len_avail
- offset
;
1386 memcpy (readbuf
, buf
+ offset
, len
);
1391 /* Collect data about message queues recorded in /proc and write it
1395 linux_xfer_osdata_msg (gdb_byte
*readbuf
,
1396 ULONGEST offset
, ULONGEST len
)
1398 static const char *buf
;
1399 static LONGEST len_avail
= -1;
1400 static struct buffer buffer
;
1406 if (len_avail
!= -1 && len_avail
!= 0)
1407 buffer_free (&buffer
);
1410 buffer_init (&buffer
);
1411 buffer_grow_str (&buffer
, "<osdata type=\"message queues\">\n");
1413 fp
= gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1420 if (fgets (buf
, sizeof (buf
), fp
))
1426 unsigned int perms
, cbytes
, qnum
;
1428 TIME_T stime
, rtime
, ctime
;
1431 items_read
= sscanf (buf
,
1432 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1433 &key
, &msqid
, &perms
, &cbytes
, &qnum
,
1434 &lspid
, &lrpid
, &uid
, &gid
, &cuid
, &cgid
,
1435 &stime
, &rtime
, &ctime
);
1437 if (items_read
== 14)
1439 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1440 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1441 char lscmd
[32], lrcmd
[32];
1442 char stime_str
[32], rtime_str
[32], ctime_str
[32];
1444 user_from_uid (user
, sizeof (user
), uid
);
1445 group_from_gid (group
, sizeof (group
), gid
);
1446 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1447 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1449 command_from_pid (lscmd
, sizeof (lscmd
), lspid
);
1450 command_from_pid (lrcmd
, sizeof (lrcmd
), lrpid
);
1452 time_from_time_t (stime_str
, sizeof (stime_str
), stime
);
1453 time_from_time_t (rtime_str
, sizeof (rtime_str
), rtime
);
1454 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1459 "<column name=\"key\">%d</column>"
1460 "<column name=\"msqid\">%d</column>"
1461 "<column name=\"permissions\">%o</column>"
1462 "<column name=\"num used bytes\">%u</column>"
1463 "<column name=\"num messages\">%u</column>"
1464 "<column name=\"last msgsnd() command\">%s</column>"
1465 "<column name=\"last msgrcv() command\">%s</column>"
1466 "<column name=\"user\">%s</column>"
1467 "<column name=\"group\">%s</column>"
1468 "<column name=\"creator user\">%s</column>"
1469 "<column name=\"creator group\">%s</column>"
1470 "<column name=\"last msgsnd() time\">%s</column>"
1471 "<column name=\"last msgrcv() time\">%s</column>"
1472 "<column name=\"last msgctl() time\">%s</column>"
1496 buffer_grow_str0 (&buffer
, "</osdata>\n");
1497 buf
= buffer_finish (&buffer
);
1498 len_avail
= strlen (buf
);
1501 if (offset
>= len_avail
)
1503 /* Done. Get rid of the buffer. */
1504 buffer_free (&buffer
);
1510 if (len
> len_avail
- offset
)
1511 len
= len_avail
- offset
;
1512 memcpy (readbuf
, buf
+ offset
, len
);
1517 /* Collect data about loaded kernel modules and write it into
1521 linux_xfer_osdata_modules (gdb_byte
*readbuf
,
1522 ULONGEST offset
, ULONGEST len
)
1524 static const char *buf
;
1525 static LONGEST len_avail
= -1;
1526 static struct buffer buffer
;
1532 if (len_avail
!= -1 && len_avail
!= 0)
1533 buffer_free (&buffer
);
1536 buffer_init (&buffer
);
1537 buffer_grow_str (&buffer
, "<osdata type=\"modules\">\n");
1539 fp
= gdb_fopen_cloexec ("/proc/modules", "r");
1546 if (fgets (buf
, sizeof (buf
), fp
))
1548 char *name
, *dependencies
, *status
, *tmp
;
1550 unsigned long long address
;
1553 name
= strtok (buf
, " ");
1557 tmp
= strtok (NULL
, " ");
1560 if (sscanf (tmp
, "%u", &size
) != 1)
1563 tmp
= strtok (NULL
, " ");
1566 if (sscanf (tmp
, "%d", &uses
) != 1)
1569 dependencies
= strtok (NULL
, " ");
1570 if (dependencies
== NULL
)
1573 status
= strtok (NULL
, " ");
1577 tmp
= strtok (NULL
, "\n");
1580 if (sscanf (tmp
, "%llx", &address
) != 1)
1586 "<column name=\"name\">%s</column>"
1587 "<column name=\"size\">%u</column>"
1588 "<column name=\"num uses\">%d</column>"
1589 "<column name=\"dependencies\">%s</column>"
1590 "<column name=\"status\">%s</column>"
1591 "<column name=\"address\">%llx</column>"
1606 buffer_grow_str0 (&buffer
, "</osdata>\n");
1607 buf
= buffer_finish (&buffer
);
1608 len_avail
= strlen (buf
);
1611 if (offset
>= len_avail
)
1613 /* Done. Get rid of the buffer. */
1614 buffer_free (&buffer
);
1620 if (len
> len_avail
- offset
)
1621 len
= len_avail
- offset
;
1622 memcpy (readbuf
, buf
+ offset
, len
);
1627 struct osdata_type
{
1631 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, ULONGEST len
);
1632 } osdata_table
[] = {
1633 { "cpus", "CPUs", "Listing of all cpus/cores on the system",
1634 linux_xfer_osdata_cpus
},
1635 { "files", "File descriptors", "Listing of all file descriptors",
1636 linux_xfer_osdata_fds
},
1637 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1638 linux_xfer_osdata_modules
},
1639 { "msg", "Message queues", "Listing of all message queues",
1640 linux_xfer_osdata_msg
},
1641 { "processes", "Processes", "Listing of all processes",
1642 linux_xfer_osdata_processes
},
1643 { "procgroups", "Process groups", "Listing of all process groups",
1644 linux_xfer_osdata_processgroups
},
1645 { "semaphores", "Semaphores", "Listing of all semaphores",
1646 linux_xfer_osdata_sem
},
1647 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1648 linux_xfer_osdata_shm
},
1649 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1650 linux_xfer_osdata_isockets
},
1651 { "threads", "Threads", "Listing of all threads",
1652 linux_xfer_osdata_threads
},
1653 { NULL
, NULL
, NULL
}
1657 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
1658 ULONGEST offset
, ULONGEST len
)
1660 if (!annex
|| *annex
== '\0')
1662 static const char *buf
;
1663 static LONGEST len_avail
= -1;
1664 static struct buffer buffer
;
1670 if (len_avail
!= -1 && len_avail
!= 0)
1671 buffer_free (&buffer
);
1674 buffer_init (&buffer
);
1675 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
1677 for (i
= 0; osdata_table
[i
].type
; ++i
)
1681 "<column name=\"Type\">%s</column>"
1682 "<column name=\"Description\">%s</column>"
1683 "<column name=\"Title\">%s</column>"
1685 osdata_table
[i
].type
,
1686 osdata_table
[i
].description
,
1687 osdata_table
[i
].title
);
1689 buffer_grow_str0 (&buffer
, "</osdata>\n");
1690 buf
= buffer_finish (&buffer
);
1691 len_avail
= strlen (buf
);
1694 if (offset
>= len_avail
)
1696 /* Done. Get rid of the buffer. */
1697 buffer_free (&buffer
);
1703 if (len
> len_avail
- offset
)
1704 len
= len_avail
- offset
;
1705 memcpy (readbuf
, buf
+ offset
, len
);
1713 for (i
= 0; osdata_table
[i
].type
; ++i
)
1715 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
1717 gdb_assert (readbuf
);
1719 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);