1 /* Linux-specific functions to retrieve OS data.
3 Copyright (C) 2009-2017 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
= (char *) 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 xsnprintf (procentry
, sizeof (procentry
), "/proc/%s",
590 if (stat (procentry
, &statbuf
) == 0
591 && S_ISDIR (statbuf
.st_mode
))
598 pathname
= xstrprintf ("/proc/%s/task", dp
->d_name
);
600 pid
= atoi (dp
->d_name
);
601 command_from_pid (command
, sizeof (command
), pid
);
603 dirp2
= opendir (pathname
);
609 while ((dp2
= readdir (dirp2
)) != NULL
)
614 if (!isdigit (dp2
->d_name
[0])
615 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
618 tid
= atoi (dp2
->d_name
);
619 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
624 "<column name=\"pid\">%lld</column>"
625 "<column name=\"command\">%s</column>"
626 "<column name=\"tid\">%lld</column>"
627 "<column name=\"core\">%d</column>"
645 buffer_grow_str0 (&buffer
, "</osdata>\n");
646 buf
= buffer_finish (&buffer
);
647 len_avail
= strlen (buf
);
650 if (offset
>= len_avail
)
652 /* Done. Get rid of the buffer. */
653 buffer_free (&buffer
);
659 if (len
> len_avail
- offset
)
660 len
= len_avail
- offset
;
661 memcpy (readbuf
, buf
+ offset
, len
);
666 /* Collect data about the cpus/cores on the system */
669 linux_xfer_osdata_cpus (gdb_byte
*readbuf
,
670 ULONGEST offset
, ULONGEST len
)
672 static const char *buf
;
673 static LONGEST len_avail
= -1;
674 static struct buffer buffer
;
681 if (len_avail
!= -1 && len_avail
!= 0)
682 buffer_free (&buffer
);
685 buffer_init (&buffer
);
686 buffer_grow_str (&buffer
, "<osdata type=\"cpus\">\n");
688 fp
= gdb_fopen_cloexec ("/proc/cpuinfo", "r");
695 if (fgets (buf
, sizeof (buf
), fp
))
700 key
= strtok (buf
, ":");
704 value
= strtok (NULL
, ":");
708 while (key
[i
] != '\t' && key
[i
] != '\0')
714 while (value
[i
] != '\t' && value
[i
] != '\0')
719 if (strcmp (key
, "processor") == 0)
722 buffer_grow_str (&buffer
, "<item>");
724 buffer_grow_str (&buffer
, "</item><item>");
729 buffer_xml_printf (&buffer
,
730 "<column name=\"%s\">%s</column>",
738 buffer_grow_str (&buffer
, "</item>");
743 buffer_grow_str0 (&buffer
, "</osdata>\n");
744 buf
= buffer_finish (&buffer
);
745 len_avail
= strlen (buf
);
748 if (offset
>= len_avail
)
750 /* Done. Get rid of the buffer. */
751 buffer_free (&buffer
);
757 if (len
> len_avail
- offset
)
758 len
= len_avail
- offset
;
759 memcpy (readbuf
, buf
+ offset
, len
);
764 /* Collect all the open file descriptors found in /proc and put the details
765 found about them into READBUF. */
768 linux_xfer_osdata_fds (gdb_byte
*readbuf
,
769 ULONGEST offset
, ULONGEST len
)
771 /* We make the process list snapshot when the object starts to be read. */
772 static const char *buf
;
773 static LONGEST len_avail
= -1;
774 static struct buffer buffer
;
780 if (len_avail
!= -1 && len_avail
!= 0)
781 buffer_free (&buffer
);
784 buffer_init (&buffer
);
785 buffer_grow_str (&buffer
, "<osdata type=\"files\">\n");
787 dirp
= opendir ("/proc");
792 while ((dp
= readdir (dirp
)) != NULL
)
795 char procentry
[sizeof ("/proc/4294967295")];
797 if (!isdigit (dp
->d_name
[0])
798 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
801 xsnprintf (procentry
, sizeof (procentry
), "/proc/%s",
803 if (stat (procentry
, &statbuf
) == 0
804 && S_ISDIR (statbuf
.st_mode
))
811 pid
= atoi (dp
->d_name
);
812 command_from_pid (command
, sizeof (command
), pid
);
814 pathname
= xstrprintf ("/proc/%s/fd", dp
->d_name
);
815 dirp2
= opendir (pathname
);
821 while ((dp2
= readdir (dirp2
)) != NULL
)
827 if (!isdigit (dp2
->d_name
[0]))
830 fdname
= xstrprintf ("%s/%s", pathname
, dp2
->d_name
);
831 rslt
= readlink (fdname
, buf
, sizeof (buf
) - 1);
838 "<column name=\"pid\">%s</column>"
839 "<column name=\"command\">%s</column>"
840 "<column name=\"file descriptor\">%s</column>"
841 "<column name=\"name\">%s</column>"
846 (rslt
>= 0 ? buf
: dp2
->d_name
));
859 buffer_grow_str0 (&buffer
, "</osdata>\n");
860 buf
= buffer_finish (&buffer
);
861 len_avail
= strlen (buf
);
864 if (offset
>= len_avail
)
866 /* Done. Get rid of the buffer. */
867 buffer_free (&buffer
);
873 if (len
> len_avail
- offset
)
874 len
= len_avail
- offset
;
875 memcpy (readbuf
, buf
+ offset
, len
);
880 /* Returns the socket state STATE in textual form. */
883 format_socket_state (unsigned char state
)
885 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
902 case TCP_ESTABLISHED
:
903 return "ESTABLISHED";
932 struct sockaddr_in sin
;
933 struct sockaddr_in6 sin6
;
936 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
937 information for all open internet sockets of type FAMILY on the
938 system into BUFFER. If TCP is set, only TCP sockets are processed,
939 otherwise only UDP sockets are processed. */
942 print_sockets (unsigned short family
, int tcp
, struct buffer
*buffer
)
944 const char *proc_file
;
947 if (family
== AF_INET
)
948 proc_file
= tcp
? "/proc/net/tcp" : "/proc/net/udp";
949 else if (family
== AF_INET6
)
950 proc_file
= tcp
? "/proc/net/tcp6" : "/proc/net/udp6";
954 fp
= gdb_fopen_cloexec (proc_file
, "r");
961 if (fgets (buf
, sizeof (buf
), fp
))
964 unsigned int local_port
, remote_port
, state
;
965 char local_address
[NI_MAXHOST
], remote_address
[NI_MAXHOST
];
969 #error "local_address and remote_address buffers too small"
972 result
= sscanf (buf
,
973 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
974 local_address
, &local_port
,
975 remote_address
, &remote_port
,
981 union socket_addr locaddr
, remaddr
;
983 char user
[UT_NAMESIZE
];
984 char local_service
[NI_MAXSERV
], remote_service
[NI_MAXSERV
];
986 if (family
== AF_INET
)
988 sscanf (local_address
, "%X",
989 &locaddr
.sin
.sin_addr
.s_addr
);
990 sscanf (remote_address
, "%X",
991 &remaddr
.sin
.sin_addr
.s_addr
);
993 locaddr
.sin
.sin_port
= htons (local_port
);
994 remaddr
.sin
.sin_port
= htons (remote_port
);
996 addr_size
= sizeof (struct sockaddr_in
);
1000 sscanf (local_address
, "%8X%8X%8X%8X",
1001 locaddr
.sin6
.sin6_addr
.s6_addr32
,
1002 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
1003 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
1004 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
1005 sscanf (remote_address
, "%8X%8X%8X%8X",
1006 remaddr
.sin6
.sin6_addr
.s6_addr32
,
1007 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
1008 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
1009 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
1011 locaddr
.sin6
.sin6_port
= htons (local_port
);
1012 remaddr
.sin6
.sin6_port
= htons (remote_port
);
1014 locaddr
.sin6
.sin6_flowinfo
= 0;
1015 remaddr
.sin6
.sin6_flowinfo
= 0;
1016 locaddr
.sin6
.sin6_scope_id
= 0;
1017 remaddr
.sin6
.sin6_scope_id
= 0;
1019 addr_size
= sizeof (struct sockaddr_in6
);
1022 locaddr
.sa
.sa_family
= remaddr
.sa
.sa_family
= family
;
1024 result
= getnameinfo (&locaddr
.sa
, addr_size
,
1025 local_address
, sizeof (local_address
),
1026 local_service
, sizeof (local_service
),
1027 NI_NUMERICHOST
| NI_NUMERICSERV
1028 | (tcp
? 0 : NI_DGRAM
));
1032 result
= getnameinfo (&remaddr
.sa
, addr_size
,
1034 sizeof (remote_address
),
1036 sizeof (remote_service
),
1037 NI_NUMERICHOST
| NI_NUMERICSERV
1038 | (tcp
? 0 : NI_DGRAM
));
1042 user_from_uid (user
, sizeof (user
), uid
);
1047 "<column name=\"local address\">%s</column>"
1048 "<column name=\"local port\">%s</column>"
1049 "<column name=\"remote address\">%s</column>"
1050 "<column name=\"remote port\">%s</column>"
1051 "<column name=\"state\">%s</column>"
1052 "<column name=\"user\">%s</column>"
1053 "<column name=\"family\">%s</column>"
1054 "<column name=\"protocol\">%s</column>"
1060 format_socket_state (state
),
1062 (family
== AF_INET
) ? "INET" : "INET6",
1063 tcp
? "STREAM" : "DGRAM");
1073 /* Collect data about internet sockets and write it into READBUF. */
1076 linux_xfer_osdata_isockets (gdb_byte
*readbuf
,
1077 ULONGEST offset
, ULONGEST len
)
1079 static const char *buf
;
1080 static LONGEST len_avail
= -1;
1081 static struct buffer buffer
;
1085 if (len_avail
!= -1 && len_avail
!= 0)
1086 buffer_free (&buffer
);
1089 buffer_init (&buffer
);
1090 buffer_grow_str (&buffer
, "<osdata type=\"I sockets\">\n");
1092 print_sockets (AF_INET
, 1, &buffer
);
1093 print_sockets (AF_INET
, 0, &buffer
);
1094 print_sockets (AF_INET6
, 1, &buffer
);
1095 print_sockets (AF_INET6
, 0, &buffer
);
1097 buffer_grow_str0 (&buffer
, "</osdata>\n");
1098 buf
= buffer_finish (&buffer
);
1099 len_avail
= strlen (buf
);
1102 if (offset
>= len_avail
)
1104 /* Done. Get rid of the buffer. */
1105 buffer_free (&buffer
);
1111 if (len
> len_avail
- offset
)
1112 len
= len_avail
- offset
;
1113 memcpy (readbuf
, buf
+ offset
, len
);
1118 /* Converts the time SECONDS into textual form and copies it into a
1119 buffer TIME, with at most MAXLEN characters copied. */
1122 time_from_time_t (char *time
, int maxlen
, TIME_T seconds
)
1128 time_t t
= (time_t) seconds
;
1130 strncpy (time
, ctime (&t
), maxlen
);
1131 time
[maxlen
- 1] = '\0';
1135 /* Finds the group name for the group GID and copies it into GROUP.
1136 At most MAXLEN characters are copied. */
1139 group_from_gid (char *group
, int maxlen
, gid_t gid
)
1141 struct group
*grentry
= getgrgid (gid
);
1145 strncpy (group
, grentry
->gr_name
, maxlen
);
1146 /* Ensure that the group name is null-terminated. */
1147 group
[maxlen
- 1] = '\0';
1153 /* Collect data about shared memory recorded in /proc and write it
1157 linux_xfer_osdata_shm (gdb_byte
*readbuf
,
1158 ULONGEST offset
, ULONGEST len
)
1160 static const char *buf
;
1161 static LONGEST len_avail
= -1;
1162 static struct buffer buffer
;
1168 if (len_avail
!= -1 && len_avail
!= 0)
1169 buffer_free (&buffer
);
1172 buffer_init (&buffer
);
1173 buffer_grow_str (&buffer
, "<osdata type=\"shared memory\">\n");
1175 fp
= gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1182 if (fgets (buf
, sizeof (buf
), fp
))
1188 int shmid
, size
, nattch
;
1189 TIME_T atime
, dtime
, ctime
;
1193 items_read
= sscanf (buf
,
1194 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1195 &key
, &shmid
, &perms
, &size
,
1198 &uid
, &gid
, &cuid
, &cgid
,
1199 &atime
, &dtime
, &ctime
);
1201 if (items_read
== 14)
1203 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1204 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1205 char ccmd
[32], lcmd
[32];
1206 char atime_str
[32], dtime_str
[32], ctime_str
[32];
1208 user_from_uid (user
, sizeof (user
), uid
);
1209 group_from_gid (group
, sizeof (group
), gid
);
1210 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1211 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1213 command_from_pid (ccmd
, sizeof (ccmd
), cpid
);
1214 command_from_pid (lcmd
, sizeof (lcmd
), lpid
);
1216 time_from_time_t (atime_str
, sizeof (atime_str
), atime
);
1217 time_from_time_t (dtime_str
, sizeof (dtime_str
), dtime
);
1218 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1223 "<column name=\"key\">%d</column>"
1224 "<column name=\"shmid\">%d</column>"
1225 "<column name=\"permissions\">%o</column>"
1226 "<column name=\"size\">%d</column>"
1227 "<column name=\"creator command\">%s</column>"
1228 "<column name=\"last op. command\">%s</column>"
1229 "<column name=\"num attached\">%d</column>"
1230 "<column name=\"user\">%s</column>"
1231 "<column name=\"group\">%s</column>"
1232 "<column name=\"creator user\">%s</column>"
1233 "<column name=\"creator group\">%s</column>"
1234 "<column name=\"last shmat() time\">%s</column>"
1235 "<column name=\"last shmdt() time\">%s</column>"
1236 "<column name=\"last shmctl() time\">%s</column>"
1260 buffer_grow_str0 (&buffer
, "</osdata>\n");
1261 buf
= buffer_finish (&buffer
);
1262 len_avail
= strlen (buf
);
1265 if (offset
>= len_avail
)
1267 /* Done. Get rid of the buffer. */
1268 buffer_free (&buffer
);
1274 if (len
> len_avail
- offset
)
1275 len
= len_avail
- offset
;
1276 memcpy (readbuf
, buf
+ offset
, len
);
1281 /* Collect data about semaphores recorded in /proc and write it
1285 linux_xfer_osdata_sem (gdb_byte
*readbuf
,
1286 ULONGEST offset
, ULONGEST len
)
1288 static const char *buf
;
1289 static LONGEST len_avail
= -1;
1290 static struct buffer buffer
;
1296 if (len_avail
!= -1 && len_avail
!= 0)
1297 buffer_free (&buffer
);
1300 buffer_init (&buffer
);
1301 buffer_grow_str (&buffer
, "<osdata type=\"semaphores\">\n");
1303 fp
= gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1310 if (fgets (buf
, sizeof (buf
), fp
))
1315 unsigned int perms
, nsems
;
1317 TIME_T otime
, ctime
;
1320 items_read
= sscanf (buf
,
1321 "%d %d %o %u %d %d %d %d %lld %lld",
1322 &key
, &semid
, &perms
, &nsems
,
1323 &uid
, &gid
, &cuid
, &cgid
,
1326 if (items_read
== 10)
1328 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1329 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1330 char otime_str
[32], ctime_str
[32];
1332 user_from_uid (user
, sizeof (user
), uid
);
1333 group_from_gid (group
, sizeof (group
), gid
);
1334 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1335 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1337 time_from_time_t (otime_str
, sizeof (otime_str
), otime
);
1338 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1343 "<column name=\"key\">%d</column>"
1344 "<column name=\"semid\">%d</column>"
1345 "<column name=\"permissions\">%o</column>"
1346 "<column name=\"num semaphores\">%u</column>"
1347 "<column name=\"user\">%s</column>"
1348 "<column name=\"group\">%s</column>"
1349 "<column name=\"creator user\">%s</column>"
1350 "<column name=\"creator group\">%s</column>"
1351 "<column name=\"last semop() time\">%s</column>"
1352 "<column name=\"last semctl() time\">%s</column>"
1372 buffer_grow_str0 (&buffer
, "</osdata>\n");
1373 buf
= buffer_finish (&buffer
);
1374 len_avail
= strlen (buf
);
1377 if (offset
>= len_avail
)
1379 /* Done. Get rid of the buffer. */
1380 buffer_free (&buffer
);
1386 if (len
> len_avail
- offset
)
1387 len
= len_avail
- offset
;
1388 memcpy (readbuf
, buf
+ offset
, len
);
1393 /* Collect data about message queues recorded in /proc and write it
1397 linux_xfer_osdata_msg (gdb_byte
*readbuf
,
1398 ULONGEST offset
, ULONGEST len
)
1400 static const char *buf
;
1401 static LONGEST len_avail
= -1;
1402 static struct buffer buffer
;
1408 if (len_avail
!= -1 && len_avail
!= 0)
1409 buffer_free (&buffer
);
1412 buffer_init (&buffer
);
1413 buffer_grow_str (&buffer
, "<osdata type=\"message queues\">\n");
1415 fp
= gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1422 if (fgets (buf
, sizeof (buf
), fp
))
1428 unsigned int perms
, cbytes
, qnum
;
1430 TIME_T stime
, rtime
, ctime
;
1433 items_read
= sscanf (buf
,
1434 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1435 &key
, &msqid
, &perms
, &cbytes
, &qnum
,
1436 &lspid
, &lrpid
, &uid
, &gid
, &cuid
, &cgid
,
1437 &stime
, &rtime
, &ctime
);
1439 if (items_read
== 14)
1441 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1442 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1443 char lscmd
[32], lrcmd
[32];
1444 char stime_str
[32], rtime_str
[32], ctime_str
[32];
1446 user_from_uid (user
, sizeof (user
), uid
);
1447 group_from_gid (group
, sizeof (group
), gid
);
1448 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1449 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1451 command_from_pid (lscmd
, sizeof (lscmd
), lspid
);
1452 command_from_pid (lrcmd
, sizeof (lrcmd
), lrpid
);
1454 time_from_time_t (stime_str
, sizeof (stime_str
), stime
);
1455 time_from_time_t (rtime_str
, sizeof (rtime_str
), rtime
);
1456 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1461 "<column name=\"key\">%d</column>"
1462 "<column name=\"msqid\">%d</column>"
1463 "<column name=\"permissions\">%o</column>"
1464 "<column name=\"num used bytes\">%u</column>"
1465 "<column name=\"num messages\">%u</column>"
1466 "<column name=\"last msgsnd() command\">%s</column>"
1467 "<column name=\"last msgrcv() command\">%s</column>"
1468 "<column name=\"user\">%s</column>"
1469 "<column name=\"group\">%s</column>"
1470 "<column name=\"creator user\">%s</column>"
1471 "<column name=\"creator group\">%s</column>"
1472 "<column name=\"last msgsnd() time\">%s</column>"
1473 "<column name=\"last msgrcv() time\">%s</column>"
1474 "<column name=\"last msgctl() time\">%s</column>"
1498 buffer_grow_str0 (&buffer
, "</osdata>\n");
1499 buf
= buffer_finish (&buffer
);
1500 len_avail
= strlen (buf
);
1503 if (offset
>= len_avail
)
1505 /* Done. Get rid of the buffer. */
1506 buffer_free (&buffer
);
1512 if (len
> len_avail
- offset
)
1513 len
= len_avail
- offset
;
1514 memcpy (readbuf
, buf
+ offset
, len
);
1519 /* Collect data about loaded kernel modules and write it into
1523 linux_xfer_osdata_modules (gdb_byte
*readbuf
,
1524 ULONGEST offset
, ULONGEST len
)
1526 static const char *buf
;
1527 static LONGEST len_avail
= -1;
1528 static struct buffer buffer
;
1534 if (len_avail
!= -1 && len_avail
!= 0)
1535 buffer_free (&buffer
);
1538 buffer_init (&buffer
);
1539 buffer_grow_str (&buffer
, "<osdata type=\"modules\">\n");
1541 fp
= gdb_fopen_cloexec ("/proc/modules", "r");
1548 if (fgets (buf
, sizeof (buf
), fp
))
1550 char *name
, *dependencies
, *status
, *tmp
;
1552 unsigned long long address
;
1555 name
= strtok (buf
, " ");
1559 tmp
= strtok (NULL
, " ");
1562 if (sscanf (tmp
, "%u", &size
) != 1)
1565 tmp
= strtok (NULL
, " ");
1568 if (sscanf (tmp
, "%d", &uses
) != 1)
1571 dependencies
= strtok (NULL
, " ");
1572 if (dependencies
== NULL
)
1575 status
= strtok (NULL
, " ");
1579 tmp
= strtok (NULL
, "\n");
1582 if (sscanf (tmp
, "%llx", &address
) != 1)
1588 "<column name=\"name\">%s</column>"
1589 "<column name=\"size\">%u</column>"
1590 "<column name=\"num uses\">%d</column>"
1591 "<column name=\"dependencies\">%s</column>"
1592 "<column name=\"status\">%s</column>"
1593 "<column name=\"address\">%llx</column>"
1608 buffer_grow_str0 (&buffer
, "</osdata>\n");
1609 buf
= buffer_finish (&buffer
);
1610 len_avail
= strlen (buf
);
1613 if (offset
>= len_avail
)
1615 /* Done. Get rid of the buffer. */
1616 buffer_free (&buffer
);
1622 if (len
> len_avail
- offset
)
1623 len
= len_avail
- offset
;
1624 memcpy (readbuf
, buf
+ offset
, len
);
1629 struct osdata_type
{
1633 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, ULONGEST len
);
1634 } osdata_table
[] = {
1635 { "cpus", "CPUs", "Listing of all cpus/cores on the system",
1636 linux_xfer_osdata_cpus
},
1637 { "files", "File descriptors", "Listing of all file descriptors",
1638 linux_xfer_osdata_fds
},
1639 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1640 linux_xfer_osdata_modules
},
1641 { "msg", "Message queues", "Listing of all message queues",
1642 linux_xfer_osdata_msg
},
1643 { "processes", "Processes", "Listing of all processes",
1644 linux_xfer_osdata_processes
},
1645 { "procgroups", "Process groups", "Listing of all process groups",
1646 linux_xfer_osdata_processgroups
},
1647 { "semaphores", "Semaphores", "Listing of all semaphores",
1648 linux_xfer_osdata_sem
},
1649 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1650 linux_xfer_osdata_shm
},
1651 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1652 linux_xfer_osdata_isockets
},
1653 { "threads", "Threads", "Listing of all threads",
1654 linux_xfer_osdata_threads
},
1655 { NULL
, NULL
, NULL
}
1659 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
1660 ULONGEST offset
, ULONGEST len
)
1662 if (!annex
|| *annex
== '\0')
1664 static const char *buf
;
1665 static LONGEST len_avail
= -1;
1666 static struct buffer buffer
;
1672 if (len_avail
!= -1 && len_avail
!= 0)
1673 buffer_free (&buffer
);
1676 buffer_init (&buffer
);
1677 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
1679 for (i
= 0; osdata_table
[i
].type
; ++i
)
1683 "<column name=\"Type\">%s</column>"
1684 "<column name=\"Description\">%s</column>"
1685 "<column name=\"Title\">%s</column>"
1687 osdata_table
[i
].type
,
1688 osdata_table
[i
].description
,
1689 osdata_table
[i
].title
);
1691 buffer_grow_str0 (&buffer
, "</osdata>\n");
1692 buf
= buffer_finish (&buffer
);
1693 len_avail
= strlen (buf
);
1696 if (offset
>= len_avail
)
1698 /* Done. Get rid of the buffer. */
1699 buffer_free (&buffer
);
1705 if (len
> len_avail
- offset
)
1706 len
= len_avail
- offset
;
1707 memcpy (readbuf
, buf
+ offset
, len
);
1715 for (i
= 0; osdata_table
[i
].type
; ++i
)
1717 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
1719 gdb_assert (readbuf
);
1721 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);