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
];
71 sprintf (filename
, "/proc/%lld/task/%lld/stat",
72 (PID_T
) ptid_get_pid (ptid
), (PID_T
) ptid_get_lwp (ptid
));
73 gdb_file_up f
= gdb_fopen_cloexec (filename
, "r");
80 content
= (char *) xrealloc (content
, content_read
+ 1024);
81 n
= fread (content
+ content_read
, 1, 1024, f
.get ());
85 content
[content_read
] = '\0';
90 /* ps command also relies on no trailing fields ever contain ')'. */
91 p
= strrchr (content
, ')');
95 /* If the first field after program name has index 0, then core number is
96 the field with index 36. There's no constant for that anywhere. */
98 p
= strtok_r (p
, " ", &ts
);
99 for (i
= 0; p
!= NULL
&& i
!= 36; ++i
)
100 p
= strtok_r (NULL
, " ", &ts
);
102 if (p
== NULL
|| sscanf (p
, "%d", &core
) == 0)
110 /* Finds the command-line of process PID and copies it into COMMAND.
111 At most MAXLEN characters are copied. If the command-line cannot
112 be found, PID is copied into command in text-form. */
115 command_from_pid (char *command
, int maxlen
, PID_T pid
)
117 char *stat_path
= xstrprintf ("/proc/%lld/stat", pid
);
118 gdb_file_up fp
= gdb_fopen_cloexec (stat_path
, "r");
124 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
125 include/linux/sched.h in the Linux kernel sources) plus two
126 (for the brackets). */
129 int items_read
= fscanf (fp
.get (), "%lld %17s", &stat_pid
, cmd
);
131 if (items_read
== 2 && pid
== stat_pid
)
133 cmd
[strlen (cmd
) - 1] = '\0'; /* Remove trailing parenthesis. */
134 strncpy (command
, cmd
+ 1, maxlen
); /* Ignore leading parenthesis. */
139 /* Return the PID if a /proc entry for the process cannot be found. */
140 snprintf (command
, maxlen
, "%lld", pid
);
143 command
[maxlen
- 1] = '\0'; /* Ensure string is null-terminated. */
148 /* Returns the command-line of the process with the given PID. The
149 returned string needs to be freed using xfree after use. */
152 commandline_from_pid (PID_T pid
)
154 char *pathname
= xstrprintf ("/proc/%lld/cmdline", pid
);
155 char *commandline
= NULL
;
156 gdb_file_up f
= gdb_fopen_cloexec (pathname
, "r");
162 while (!feof (f
.get ()))
165 size_t read_bytes
= fread (buf
, 1, sizeof (buf
), f
.get ());
169 commandline
= (char *) xrealloc (commandline
, len
+ read_bytes
+ 1);
170 memcpy (commandline
+ len
, buf
, read_bytes
);
179 /* Replace null characters with spaces. */
180 for (i
= 0; i
< len
; ++i
)
181 if (commandline
[i
] == '\0')
182 commandline
[i
] = ' ';
184 commandline
[len
] = '\0';
188 /* Return the command in square brackets if the command-line
190 commandline
= (char *) xmalloc (32);
191 commandline
[0] = '[';
192 command_from_pid (commandline
+ 1, 31, pid
);
194 len
= strlen (commandline
);
196 strcat (commandline
, "]");
205 /* Finds the user name for the user UID and copies it into USER. At
206 most MAXLEN characters are copied. */
209 user_from_uid (char *user
, int maxlen
, uid_t uid
)
211 struct passwd
*pwentry
= getpwuid (uid
);
215 strncpy (user
, pwentry
->pw_name
, maxlen
);
216 /* Ensure that the user name is null-terminated. */
217 user
[maxlen
- 1] = '\0';
223 /* Finds the owner of process PID and returns the user id in OWNER.
224 Returns 0 if the owner was found, -1 otherwise. */
227 get_process_owner (uid_t
*owner
, PID_T pid
)
230 char procentry
[sizeof ("/proc/") + MAX_PID_T_STRLEN
];
232 sprintf (procentry
, "/proc/%lld", pid
);
234 if (stat (procentry
, &statbuf
) == 0 && S_ISDIR (statbuf
.st_mode
))
236 *owner
= statbuf
.st_uid
;
243 /* Find the CPU cores used by process PID and return them in CORES.
244 CORES points to an array of NUM_CORES elements. */
247 get_cores_used_by_process (PID_T pid
, int *cores
, const int num_cores
)
249 char taskdir
[sizeof ("/proc/") + MAX_PID_T_STRLEN
+ sizeof ("/task") - 1];
254 sprintf (taskdir
, "/proc/%lld/task", pid
);
255 dir
= opendir (taskdir
);
258 while ((dp
= readdir (dir
)) != NULL
)
263 if (!isdigit (dp
->d_name
[0])
264 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
267 sscanf (dp
->d_name
, "%lld", &tid
);
268 core
= linux_common_core_of_thread (ptid_build ((pid_t
) pid
,
271 if (core
>= 0 && core
< num_cores
)
285 linux_xfer_osdata_processes (gdb_byte
*readbuf
,
286 ULONGEST offset
, ULONGEST len
)
288 /* We make the process list snapshot when the object starts to be read. */
289 static const char *buf
;
290 static LONGEST len_avail
= -1;
291 static struct buffer buffer
;
297 if (len_avail
!= -1 && len_avail
!= 0)
298 buffer_free (&buffer
);
301 buffer_init (&buffer
);
302 buffer_grow_str (&buffer
, "<osdata type=\"processes\">\n");
304 dirp
= opendir ("/proc");
307 const int num_cores
= sysconf (_SC_NPROCESSORS_ONLN
);
310 while ((dp
= readdir (dirp
)) != NULL
)
314 char user
[UT_NAMESIZE
];
321 if (!isdigit (dp
->d_name
[0])
322 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
325 sscanf (dp
->d_name
, "%lld", &pid
);
326 command_line
= commandline_from_pid (pid
);
328 if (get_process_owner (&owner
, pid
) == 0)
329 user_from_uid (user
, sizeof (user
), owner
);
333 /* Find CPU cores used by the process. */
334 cores
= XCNEWVEC (int, num_cores
);
335 task_count
= get_cores_used_by_process (pid
, cores
, num_cores
);
336 cores_str
= (char *) xcalloc (task_count
, sizeof ("4294967295") + 1);
338 for (i
= 0; i
< num_cores
&& task_count
> 0; ++i
)
341 char core_str
[sizeof ("4294967295")];
343 sprintf (core_str
, "%d", i
);
344 strcat (cores_str
, core_str
);
346 task_count
-= cores
[i
];
348 strcat (cores_str
, ",");
356 "<column name=\"pid\">%lld</column>"
357 "<column name=\"user\">%s</column>"
358 "<column name=\"command\">%s</column>"
359 "<column name=\"cores\">%s</column>"
363 command_line
? command_line
: "",
366 xfree (command_line
);
373 buffer_grow_str0 (&buffer
, "</osdata>\n");
374 buf
= buffer_finish (&buffer
);
375 len_avail
= strlen (buf
);
378 if (offset
>= len_avail
)
380 /* Done. Get rid of the buffer. */
381 buffer_free (&buffer
);
387 if (len
> len_avail
- offset
)
388 len
= len_avail
- offset
;
389 memcpy (readbuf
, buf
+ offset
, len
);
394 /* Auxiliary function used by qsort to sort processes by process
395 group. Compares two processes with ids PROCESS1 and PROCESS2.
396 PROCESS1 comes before PROCESS2 if it has a lower process group id.
397 If they belong to the same process group, PROCESS1 comes before
398 PROCESS2 if it has a lower process id or is the process group
402 compare_processes (const void *process1
, const void *process2
)
404 PID_T pid1
= *((PID_T
*) process1
);
405 PID_T pid2
= *((PID_T
*) process2
);
406 PID_T pgid1
= *((PID_T
*) process1
+ 1);
407 PID_T pgid2
= *((PID_T
*) process2
+ 1);
412 else if (pgid1
> pgid2
)
416 /* Process group leaders always come first, else sort by PID. */
419 else if (pid2
== pgid2
)
421 else if (pid1
< pid2
)
423 else if (pid1
> pid2
)
430 /* Collect all process groups from /proc. */
433 linux_xfer_osdata_processgroups (gdb_byte
*readbuf
,
434 ULONGEST offset
, ULONGEST len
)
436 /* We make the process list snapshot when the object starts to be read. */
437 static const char *buf
;
438 static LONGEST len_avail
= -1;
439 static struct buffer buffer
;
445 if (len_avail
!= -1 && len_avail
!= 0)
446 buffer_free (&buffer
);
449 buffer_init (&buffer
);
450 buffer_grow_str (&buffer
, "<osdata type=\"process groups\">\n");
452 dirp
= opendir ("/proc");
456 const size_t list_block_size
= 512;
457 PID_T
*process_list
= XNEWVEC (PID_T
, list_block_size
* 2);
458 size_t process_count
= 0;
461 /* Build list consisting of PIDs followed by their
463 while ((dp
= readdir (dirp
)) != NULL
)
467 if (!isdigit (dp
->d_name
[0])
468 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
471 sscanf (dp
->d_name
, "%lld", &pid
);
472 pgid
= getpgid (pid
);
476 process_list
[2 * process_count
] = pid
;
477 process_list
[2 * process_count
+ 1] = pgid
;
480 /* Increase the size of the list if necessary. */
481 if (process_count
% list_block_size
== 0)
482 process_list
= (PID_T
*) xrealloc (
484 (process_count
+ list_block_size
)
485 * 2 * sizeof (PID_T
));
491 /* Sort the process list. */
492 qsort (process_list
, process_count
, 2 * sizeof (PID_T
),
495 for (i
= 0; i
< process_count
; ++i
)
497 PID_T pid
= process_list
[2 * i
];
498 PID_T pgid
= process_list
[2 * i
+ 1];
499 char leader_command
[32];
502 command_from_pid (leader_command
, sizeof (leader_command
), pgid
);
503 command_line
= commandline_from_pid (pid
);
508 "<column name=\"pgid\">%lld</column>"
509 "<column name=\"leader command\">%s</column>"
510 "<column name=\"pid\">%lld</column>"
511 "<column name=\"command line\">%s</column>"
516 command_line
? command_line
: "");
518 xfree (command_line
);
521 xfree (process_list
);
524 buffer_grow_str0 (&buffer
, "</osdata>\n");
525 buf
= buffer_finish (&buffer
);
526 len_avail
= strlen (buf
);
529 if (offset
>= len_avail
)
531 /* Done. Get rid of the buffer. */
532 buffer_free (&buffer
);
538 if (len
> len_avail
- offset
)
539 len
= len_avail
- offset
;
540 memcpy (readbuf
, buf
+ offset
, len
);
545 /* Collect all the threads in /proc by iterating through processes and
546 then tasks within each process. */
549 linux_xfer_osdata_threads (gdb_byte
*readbuf
,
550 ULONGEST offset
, ULONGEST len
)
552 /* We make the process list snapshot when the object starts to be read. */
553 static const char *buf
;
554 static LONGEST len_avail
= -1;
555 static struct buffer buffer
;
561 if (len_avail
!= -1 && len_avail
!= 0)
562 buffer_free (&buffer
);
565 buffer_init (&buffer
);
566 buffer_grow_str (&buffer
, "<osdata type=\"threads\">\n");
568 dirp
= opendir ("/proc");
573 while ((dp
= readdir (dirp
)) != NULL
)
576 char procentry
[sizeof ("/proc/4294967295")];
578 if (!isdigit (dp
->d_name
[0])
579 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
582 xsnprintf (procentry
, sizeof (procentry
), "/proc/%s",
584 if (stat (procentry
, &statbuf
) == 0
585 && S_ISDIR (statbuf
.st_mode
))
592 pathname
= xstrprintf ("/proc/%s/task", dp
->d_name
);
594 pid
= atoi (dp
->d_name
);
595 command_from_pid (command
, sizeof (command
), pid
);
597 dirp2
= opendir (pathname
);
603 while ((dp2
= readdir (dirp2
)) != NULL
)
608 if (!isdigit (dp2
->d_name
[0])
609 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
612 tid
= atoi (dp2
->d_name
);
613 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
618 "<column name=\"pid\">%lld</column>"
619 "<column name=\"command\">%s</column>"
620 "<column name=\"tid\">%lld</column>"
621 "<column name=\"core\">%d</column>"
639 buffer_grow_str0 (&buffer
, "</osdata>\n");
640 buf
= buffer_finish (&buffer
);
641 len_avail
= strlen (buf
);
644 if (offset
>= len_avail
)
646 /* Done. Get rid of the buffer. */
647 buffer_free (&buffer
);
653 if (len
> len_avail
- offset
)
654 len
= len_avail
- offset
;
655 memcpy (readbuf
, buf
+ offset
, len
);
660 /* Collect data about the cpus/cores on the system */
663 linux_xfer_osdata_cpus (gdb_byte
*readbuf
,
664 ULONGEST offset
, ULONGEST len
)
666 static const char *buf
;
667 static LONGEST len_avail
= -1;
668 static struct buffer buffer
;
674 if (len_avail
!= -1 && len_avail
!= 0)
675 buffer_free (&buffer
);
678 buffer_init (&buffer
);
679 buffer_grow_str (&buffer
, "<osdata type=\"cpus\">\n");
681 gdb_file_up fp
= gdb_fopen_cloexec ("/proc/cpuinfo", "r");
688 if (fgets (buf
, sizeof (buf
), fp
.get ()))
693 key
= strtok (buf
, ":");
697 value
= strtok (NULL
, ":");
701 while (key
[i
] != '\t' && key
[i
] != '\0')
707 while (value
[i
] != '\t' && value
[i
] != '\0')
712 if (strcmp (key
, "processor") == 0)
715 buffer_grow_str (&buffer
, "<item>");
717 buffer_grow_str (&buffer
, "</item><item>");
722 buffer_xml_printf (&buffer
,
723 "<column name=\"%s\">%s</column>",
728 while (!feof (fp
.get ()));
731 buffer_grow_str (&buffer
, "</item>");
734 buffer_grow_str0 (&buffer
, "</osdata>\n");
735 buf
= buffer_finish (&buffer
);
736 len_avail
= strlen (buf
);
739 if (offset
>= len_avail
)
741 /* Done. Get rid of the buffer. */
742 buffer_free (&buffer
);
748 if (len
> len_avail
- offset
)
749 len
= len_avail
- offset
;
750 memcpy (readbuf
, buf
+ offset
, len
);
755 /* Collect all the open file descriptors found in /proc and put the details
756 found about them into READBUF. */
759 linux_xfer_osdata_fds (gdb_byte
*readbuf
,
760 ULONGEST offset
, ULONGEST len
)
762 /* We make the process list snapshot when the object starts to be read. */
763 static const char *buf
;
764 static LONGEST len_avail
= -1;
765 static struct buffer buffer
;
771 if (len_avail
!= -1 && len_avail
!= 0)
772 buffer_free (&buffer
);
775 buffer_init (&buffer
);
776 buffer_grow_str (&buffer
, "<osdata type=\"files\">\n");
778 dirp
= opendir ("/proc");
783 while ((dp
= readdir (dirp
)) != NULL
)
786 char procentry
[sizeof ("/proc/4294967295")];
788 if (!isdigit (dp
->d_name
[0])
789 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
792 xsnprintf (procentry
, sizeof (procentry
), "/proc/%s",
794 if (stat (procentry
, &statbuf
) == 0
795 && S_ISDIR (statbuf
.st_mode
))
802 pid
= atoi (dp
->d_name
);
803 command_from_pid (command
, sizeof (command
), pid
);
805 pathname
= xstrprintf ("/proc/%s/fd", dp
->d_name
);
806 dirp2
= opendir (pathname
);
812 while ((dp2
= readdir (dirp2
)) != NULL
)
818 if (!isdigit (dp2
->d_name
[0]))
821 fdname
= xstrprintf ("%s/%s", pathname
, dp2
->d_name
);
822 rslt
= readlink (fdname
, buf
, sizeof (buf
) - 1);
829 "<column name=\"pid\">%s</column>"
830 "<column name=\"command\">%s</column>"
831 "<column name=\"file descriptor\">%s</column>"
832 "<column name=\"name\">%s</column>"
837 (rslt
>= 0 ? buf
: dp2
->d_name
));
850 buffer_grow_str0 (&buffer
, "</osdata>\n");
851 buf
= buffer_finish (&buffer
);
852 len_avail
= strlen (buf
);
855 if (offset
>= len_avail
)
857 /* Done. Get rid of the buffer. */
858 buffer_free (&buffer
);
864 if (len
> len_avail
- offset
)
865 len
= len_avail
- offset
;
866 memcpy (readbuf
, buf
+ offset
, len
);
871 /* Returns the socket state STATE in textual form. */
874 format_socket_state (unsigned char state
)
876 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
893 case TCP_ESTABLISHED
:
894 return "ESTABLISHED";
923 struct sockaddr_in sin
;
924 struct sockaddr_in6 sin6
;
927 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
928 information for all open internet sockets of type FAMILY on the
929 system into BUFFER. If TCP is set, only TCP sockets are processed,
930 otherwise only UDP sockets are processed. */
933 print_sockets (unsigned short family
, int tcp
, struct buffer
*buffer
)
935 const char *proc_file
;
937 if (family
== AF_INET
)
938 proc_file
= tcp
? "/proc/net/tcp" : "/proc/net/udp";
939 else if (family
== AF_INET6
)
940 proc_file
= tcp
? "/proc/net/tcp6" : "/proc/net/udp6";
944 gdb_file_up fp
= gdb_fopen_cloexec (proc_file
, "r");
951 if (fgets (buf
, sizeof (buf
), fp
.get ()))
954 unsigned int local_port
, remote_port
, state
;
955 char local_address
[NI_MAXHOST
], remote_address
[NI_MAXHOST
];
959 #error "local_address and remote_address buffers too small"
962 result
= sscanf (buf
,
963 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
964 local_address
, &local_port
,
965 remote_address
, &remote_port
,
971 union socket_addr locaddr
, remaddr
;
973 char user
[UT_NAMESIZE
];
974 char local_service
[NI_MAXSERV
], remote_service
[NI_MAXSERV
];
976 if (family
== AF_INET
)
978 sscanf (local_address
, "%X",
979 &locaddr
.sin
.sin_addr
.s_addr
);
980 sscanf (remote_address
, "%X",
981 &remaddr
.sin
.sin_addr
.s_addr
);
983 locaddr
.sin
.sin_port
= htons (local_port
);
984 remaddr
.sin
.sin_port
= htons (remote_port
);
986 addr_size
= sizeof (struct sockaddr_in
);
990 sscanf (local_address
, "%8X%8X%8X%8X",
991 locaddr
.sin6
.sin6_addr
.s6_addr32
,
992 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
993 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
994 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
995 sscanf (remote_address
, "%8X%8X%8X%8X",
996 remaddr
.sin6
.sin6_addr
.s6_addr32
,
997 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
998 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
999 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
1001 locaddr
.sin6
.sin6_port
= htons (local_port
);
1002 remaddr
.sin6
.sin6_port
= htons (remote_port
);
1004 locaddr
.sin6
.sin6_flowinfo
= 0;
1005 remaddr
.sin6
.sin6_flowinfo
= 0;
1006 locaddr
.sin6
.sin6_scope_id
= 0;
1007 remaddr
.sin6
.sin6_scope_id
= 0;
1009 addr_size
= sizeof (struct sockaddr_in6
);
1012 locaddr
.sa
.sa_family
= remaddr
.sa
.sa_family
= family
;
1014 result
= getnameinfo (&locaddr
.sa
, addr_size
,
1015 local_address
, sizeof (local_address
),
1016 local_service
, sizeof (local_service
),
1017 NI_NUMERICHOST
| NI_NUMERICSERV
1018 | (tcp
? 0 : NI_DGRAM
));
1022 result
= getnameinfo (&remaddr
.sa
, addr_size
,
1024 sizeof (remote_address
),
1026 sizeof (remote_service
),
1027 NI_NUMERICHOST
| NI_NUMERICSERV
1028 | (tcp
? 0 : NI_DGRAM
));
1032 user_from_uid (user
, sizeof (user
), uid
);
1037 "<column name=\"local address\">%s</column>"
1038 "<column name=\"local port\">%s</column>"
1039 "<column name=\"remote address\">%s</column>"
1040 "<column name=\"remote port\">%s</column>"
1041 "<column name=\"state\">%s</column>"
1042 "<column name=\"user\">%s</column>"
1043 "<column name=\"family\">%s</column>"
1044 "<column name=\"protocol\">%s</column>"
1050 format_socket_state (state
),
1052 (family
== AF_INET
) ? "INET" : "INET6",
1053 tcp
? "STREAM" : "DGRAM");
1057 while (!feof (fp
.get ()));
1061 /* Collect data about internet sockets and write it into READBUF. */
1064 linux_xfer_osdata_isockets (gdb_byte
*readbuf
,
1065 ULONGEST offset
, ULONGEST len
)
1067 static const char *buf
;
1068 static LONGEST len_avail
= -1;
1069 static struct buffer buffer
;
1073 if (len_avail
!= -1 && len_avail
!= 0)
1074 buffer_free (&buffer
);
1077 buffer_init (&buffer
);
1078 buffer_grow_str (&buffer
, "<osdata type=\"I sockets\">\n");
1080 print_sockets (AF_INET
, 1, &buffer
);
1081 print_sockets (AF_INET
, 0, &buffer
);
1082 print_sockets (AF_INET6
, 1, &buffer
);
1083 print_sockets (AF_INET6
, 0, &buffer
);
1085 buffer_grow_str0 (&buffer
, "</osdata>\n");
1086 buf
= buffer_finish (&buffer
);
1087 len_avail
= strlen (buf
);
1090 if (offset
>= len_avail
)
1092 /* Done. Get rid of the buffer. */
1093 buffer_free (&buffer
);
1099 if (len
> len_avail
- offset
)
1100 len
= len_avail
- offset
;
1101 memcpy (readbuf
, buf
+ offset
, len
);
1106 /* Converts the time SECONDS into textual form and copies it into a
1107 buffer TIME, with at most MAXLEN characters copied. */
1110 time_from_time_t (char *time
, int maxlen
, TIME_T seconds
)
1116 time_t t
= (time_t) seconds
;
1118 strncpy (time
, ctime (&t
), maxlen
);
1119 time
[maxlen
- 1] = '\0';
1123 /* Finds the group name for the group GID and copies it into GROUP.
1124 At most MAXLEN characters are copied. */
1127 group_from_gid (char *group
, int maxlen
, gid_t gid
)
1129 struct group
*grentry
= getgrgid (gid
);
1133 strncpy (group
, grentry
->gr_name
, maxlen
);
1134 /* Ensure that the group name is null-terminated. */
1135 group
[maxlen
- 1] = '\0';
1141 /* Collect data about shared memory recorded in /proc and write it
1145 linux_xfer_osdata_shm (gdb_byte
*readbuf
,
1146 ULONGEST offset
, ULONGEST len
)
1148 static const char *buf
;
1149 static LONGEST len_avail
= -1;
1150 static struct buffer buffer
;
1154 if (len_avail
!= -1 && len_avail
!= 0)
1155 buffer_free (&buffer
);
1158 buffer_init (&buffer
);
1159 buffer_grow_str (&buffer
, "<osdata type=\"shared memory\">\n");
1161 gdb_file_up fp
= gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1168 if (fgets (buf
, sizeof (buf
), fp
.get ()))
1174 int shmid
, size
, nattch
;
1175 TIME_T atime
, dtime
, ctime
;
1179 items_read
= sscanf (buf
,
1180 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1181 &key
, &shmid
, &perms
, &size
,
1184 &uid
, &gid
, &cuid
, &cgid
,
1185 &atime
, &dtime
, &ctime
);
1187 if (items_read
== 14)
1189 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1190 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1191 char ccmd
[32], lcmd
[32];
1192 char atime_str
[32], dtime_str
[32], ctime_str
[32];
1194 user_from_uid (user
, sizeof (user
), uid
);
1195 group_from_gid (group
, sizeof (group
), gid
);
1196 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1197 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1199 command_from_pid (ccmd
, sizeof (ccmd
), cpid
);
1200 command_from_pid (lcmd
, sizeof (lcmd
), lpid
);
1202 time_from_time_t (atime_str
, sizeof (atime_str
), atime
);
1203 time_from_time_t (dtime_str
, sizeof (dtime_str
), dtime
);
1204 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1209 "<column name=\"key\">%d</column>"
1210 "<column name=\"shmid\">%d</column>"
1211 "<column name=\"permissions\">%o</column>"
1212 "<column name=\"size\">%d</column>"
1213 "<column name=\"creator command\">%s</column>"
1214 "<column name=\"last op. command\">%s</column>"
1215 "<column name=\"num attached\">%d</column>"
1216 "<column name=\"user\">%s</column>"
1217 "<column name=\"group\">%s</column>"
1218 "<column name=\"creator user\">%s</column>"
1219 "<column name=\"creator group\">%s</column>"
1220 "<column name=\"last shmat() time\">%s</column>"
1221 "<column name=\"last shmdt() time\">%s</column>"
1222 "<column name=\"last shmctl() time\">%s</column>"
1241 while (!feof (fp
.get ()));
1244 buffer_grow_str0 (&buffer
, "</osdata>\n");
1245 buf
= buffer_finish (&buffer
);
1246 len_avail
= strlen (buf
);
1249 if (offset
>= len_avail
)
1251 /* Done. Get rid of the buffer. */
1252 buffer_free (&buffer
);
1258 if (len
> len_avail
- offset
)
1259 len
= len_avail
- offset
;
1260 memcpy (readbuf
, buf
+ offset
, len
);
1265 /* Collect data about semaphores recorded in /proc and write it
1269 linux_xfer_osdata_sem (gdb_byte
*readbuf
,
1270 ULONGEST offset
, ULONGEST len
)
1272 static const char *buf
;
1273 static LONGEST len_avail
= -1;
1274 static struct buffer buffer
;
1278 if (len_avail
!= -1 && len_avail
!= 0)
1279 buffer_free (&buffer
);
1282 buffer_init (&buffer
);
1283 buffer_grow_str (&buffer
, "<osdata type=\"semaphores\">\n");
1285 gdb_file_up fp
= gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1292 if (fgets (buf
, sizeof (buf
), fp
.get ()))
1297 unsigned int perms
, nsems
;
1299 TIME_T otime
, ctime
;
1302 items_read
= sscanf (buf
,
1303 "%d %d %o %u %d %d %d %d %lld %lld",
1304 &key
, &semid
, &perms
, &nsems
,
1305 &uid
, &gid
, &cuid
, &cgid
,
1308 if (items_read
== 10)
1310 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1311 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1312 char otime_str
[32], ctime_str
[32];
1314 user_from_uid (user
, sizeof (user
), uid
);
1315 group_from_gid (group
, sizeof (group
), gid
);
1316 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1317 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1319 time_from_time_t (otime_str
, sizeof (otime_str
), otime
);
1320 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1325 "<column name=\"key\">%d</column>"
1326 "<column name=\"semid\">%d</column>"
1327 "<column name=\"permissions\">%o</column>"
1328 "<column name=\"num semaphores\">%u</column>"
1329 "<column name=\"user\">%s</column>"
1330 "<column name=\"group\">%s</column>"
1331 "<column name=\"creator user\">%s</column>"
1332 "<column name=\"creator group\">%s</column>"
1333 "<column name=\"last semop() time\">%s</column>"
1334 "<column name=\"last semctl() time\">%s</column>"
1349 while (!feof (fp
.get ()));
1352 buffer_grow_str0 (&buffer
, "</osdata>\n");
1353 buf
= buffer_finish (&buffer
);
1354 len_avail
= strlen (buf
);
1357 if (offset
>= len_avail
)
1359 /* Done. Get rid of the buffer. */
1360 buffer_free (&buffer
);
1366 if (len
> len_avail
- offset
)
1367 len
= len_avail
- offset
;
1368 memcpy (readbuf
, buf
+ offset
, len
);
1373 /* Collect data about message queues recorded in /proc and write it
1377 linux_xfer_osdata_msg (gdb_byte
*readbuf
,
1378 ULONGEST offset
, ULONGEST len
)
1380 static const char *buf
;
1381 static LONGEST len_avail
= -1;
1382 static struct buffer buffer
;
1386 if (len_avail
!= -1 && len_avail
!= 0)
1387 buffer_free (&buffer
);
1390 buffer_init (&buffer
);
1391 buffer_grow_str (&buffer
, "<osdata type=\"message queues\">\n");
1393 gdb_file_up fp
= gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1400 if (fgets (buf
, sizeof (buf
), fp
.get ()))
1406 unsigned int perms
, cbytes
, qnum
;
1408 TIME_T stime
, rtime
, ctime
;
1411 items_read
= sscanf (buf
,
1412 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1413 &key
, &msqid
, &perms
, &cbytes
, &qnum
,
1414 &lspid
, &lrpid
, &uid
, &gid
, &cuid
, &cgid
,
1415 &stime
, &rtime
, &ctime
);
1417 if (items_read
== 14)
1419 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1420 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1421 char lscmd
[32], lrcmd
[32];
1422 char stime_str
[32], rtime_str
[32], ctime_str
[32];
1424 user_from_uid (user
, sizeof (user
), uid
);
1425 group_from_gid (group
, sizeof (group
), gid
);
1426 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1427 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1429 command_from_pid (lscmd
, sizeof (lscmd
), lspid
);
1430 command_from_pid (lrcmd
, sizeof (lrcmd
), lrpid
);
1432 time_from_time_t (stime_str
, sizeof (stime_str
), stime
);
1433 time_from_time_t (rtime_str
, sizeof (rtime_str
), rtime
);
1434 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1439 "<column name=\"key\">%d</column>"
1440 "<column name=\"msqid\">%d</column>"
1441 "<column name=\"permissions\">%o</column>"
1442 "<column name=\"num used bytes\">%u</column>"
1443 "<column name=\"num messages\">%u</column>"
1444 "<column name=\"last msgsnd() command\">%s</column>"
1445 "<column name=\"last msgrcv() command\">%s</column>"
1446 "<column name=\"user\">%s</column>"
1447 "<column name=\"group\">%s</column>"
1448 "<column name=\"creator user\">%s</column>"
1449 "<column name=\"creator group\">%s</column>"
1450 "<column name=\"last msgsnd() time\">%s</column>"
1451 "<column name=\"last msgrcv() time\">%s</column>"
1452 "<column name=\"last msgctl() time\">%s</column>"
1471 while (!feof (fp
.get ()));
1474 buffer_grow_str0 (&buffer
, "</osdata>\n");
1475 buf
= buffer_finish (&buffer
);
1476 len_avail
= strlen (buf
);
1479 if (offset
>= len_avail
)
1481 /* Done. Get rid of the buffer. */
1482 buffer_free (&buffer
);
1488 if (len
> len_avail
- offset
)
1489 len
= len_avail
- offset
;
1490 memcpy (readbuf
, buf
+ offset
, len
);
1495 /* Collect data about loaded kernel modules and write it into
1499 linux_xfer_osdata_modules (gdb_byte
*readbuf
,
1500 ULONGEST offset
, ULONGEST len
)
1502 static const char *buf
;
1503 static LONGEST len_avail
= -1;
1504 static struct buffer buffer
;
1508 if (len_avail
!= -1 && len_avail
!= 0)
1509 buffer_free (&buffer
);
1512 buffer_init (&buffer
);
1513 buffer_grow_str (&buffer
, "<osdata type=\"modules\">\n");
1515 gdb_file_up fp
= gdb_fopen_cloexec ("/proc/modules", "r");
1522 if (fgets (buf
, sizeof (buf
), fp
.get ()))
1524 char *name
, *dependencies
, *status
, *tmp
;
1526 unsigned long long address
;
1529 name
= strtok (buf
, " ");
1533 tmp
= strtok (NULL
, " ");
1536 if (sscanf (tmp
, "%u", &size
) != 1)
1539 tmp
= strtok (NULL
, " ");
1542 if (sscanf (tmp
, "%d", &uses
) != 1)
1545 dependencies
= strtok (NULL
, " ");
1546 if (dependencies
== NULL
)
1549 status
= strtok (NULL
, " ");
1553 tmp
= strtok (NULL
, "\n");
1556 if (sscanf (tmp
, "%llx", &address
) != 1)
1562 "<column name=\"name\">%s</column>"
1563 "<column name=\"size\">%u</column>"
1564 "<column name=\"num uses\">%d</column>"
1565 "<column name=\"dependencies\">%s</column>"
1566 "<column name=\"status\">%s</column>"
1567 "<column name=\"address\">%llx</column>"
1577 while (!feof (fp
.get ()));
1580 buffer_grow_str0 (&buffer
, "</osdata>\n");
1581 buf
= buffer_finish (&buffer
);
1582 len_avail
= strlen (buf
);
1585 if (offset
>= len_avail
)
1587 /* Done. Get rid of the buffer. */
1588 buffer_free (&buffer
);
1594 if (len
> len_avail
- offset
)
1595 len
= len_avail
- offset
;
1596 memcpy (readbuf
, buf
+ offset
, len
);
1601 struct osdata_type
{
1604 const char *description
;
1605 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, ULONGEST len
);
1606 } osdata_table
[] = {
1607 { "cpus", "CPUs", "Listing of all cpus/cores on the system",
1608 linux_xfer_osdata_cpus
},
1609 { "files", "File descriptors", "Listing of all file descriptors",
1610 linux_xfer_osdata_fds
},
1611 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1612 linux_xfer_osdata_modules
},
1613 { "msg", "Message queues", "Listing of all message queues",
1614 linux_xfer_osdata_msg
},
1615 { "processes", "Processes", "Listing of all processes",
1616 linux_xfer_osdata_processes
},
1617 { "procgroups", "Process groups", "Listing of all process groups",
1618 linux_xfer_osdata_processgroups
},
1619 { "semaphores", "Semaphores", "Listing of all semaphores",
1620 linux_xfer_osdata_sem
},
1621 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1622 linux_xfer_osdata_shm
},
1623 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1624 linux_xfer_osdata_isockets
},
1625 { "threads", "Threads", "Listing of all threads",
1626 linux_xfer_osdata_threads
},
1627 { NULL
, NULL
, NULL
}
1631 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
1632 ULONGEST offset
, ULONGEST len
)
1634 if (!annex
|| *annex
== '\0')
1636 static const char *buf
;
1637 static LONGEST len_avail
= -1;
1638 static struct buffer buffer
;
1644 if (len_avail
!= -1 && len_avail
!= 0)
1645 buffer_free (&buffer
);
1648 buffer_init (&buffer
);
1649 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
1651 for (i
= 0; osdata_table
[i
].type
; ++i
)
1655 "<column name=\"Type\">%s</column>"
1656 "<column name=\"Description\">%s</column>"
1657 "<column name=\"Title\">%s</column>"
1659 osdata_table
[i
].type
,
1660 osdata_table
[i
].description
,
1661 osdata_table
[i
].title
);
1663 buffer_grow_str0 (&buffer
, "</osdata>\n");
1664 buf
= buffer_finish (&buffer
);
1665 len_avail
= strlen (buf
);
1668 if (offset
>= len_avail
)
1670 /* Done. Get rid of the buffer. */
1671 buffer_free (&buffer
);
1677 if (len
> len_avail
- offset
)
1678 len
= len_avail
- offset
;
1679 memcpy (readbuf
, buf
+ offset
, len
);
1687 for (i
= 0; osdata_table
[i
].type
; ++i
)
1689 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
1691 gdb_assert (readbuf
);
1693 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);