1 /* Linux-specific functions to retrieve OS data.
3 Copyright (C) 2009-2014 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/>. */
26 #include "linux-osdata.h"
28 #include <sys/types.h>
29 #include <sys/sysinfo.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
41 #include "xml-utils.h"
45 #include "filestuff.h"
47 #define NAMELEN(dirent) strlen ((dirent)->d_name)
49 /* Define PID_T to be a fixed size that is at least as large as pid_t,
50 so that reading pid values embedded in /proc works
53 typedef long long PID_T
;
55 /* Define TIME_T to be at least as large as time_t, so that reading
56 time values embedded in /proc works consistently. */
58 typedef long long TIME_T
;
60 #define MAX_PID_T_STRLEN (sizeof ("-9223372036854775808") - 1)
62 /* Returns the CPU core that thread PTID is currently running on. */
64 /* Compute and return the processor core of a given thread. */
67 linux_common_core_of_thread (ptid_t ptid
)
69 char filename
[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN
];
78 sprintf (filename
, "/proc/%lld/task/%lld/stat",
79 (PID_T
) ptid_get_pid (ptid
), (PID_T
) ptid_get_lwp (ptid
));
80 f
= gdb_fopen_cloexec (filename
, "r");
87 content
= xrealloc (content
, content_read
+ 1024);
88 n
= fread (content
+ content_read
, 1, 1024, f
);
92 content
[content_read
] = '\0';
97 /* ps command also relies on no trailing fields ever contain ')'. */
98 p
= strrchr (content
, ')');
102 /* If the first field after program name has index 0, then core number is
103 the field with index 36. There's no constant for that anywhere. */
105 p
= strtok_r (p
, " ", &ts
);
106 for (i
= 0; p
!= NULL
&& i
!= 36; ++i
)
107 p
= strtok_r (NULL
, " ", &ts
);
109 if (p
== NULL
|| sscanf (p
, "%d", &core
) == 0)
118 /* Finds the command-line of process PID and copies it into COMMAND.
119 At most MAXLEN characters are copied. If the command-line cannot
120 be found, PID is copied into command in text-form. */
123 command_from_pid (char *command
, int maxlen
, PID_T pid
)
125 char *stat_path
= xstrprintf ("/proc/%lld/stat", pid
);
126 FILE *fp
= gdb_fopen_cloexec (stat_path
, "r");
132 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
133 include/linux/sched.h in the Linux kernel sources) plus two
134 (for the brackets). */
137 int items_read
= fscanf (fp
, "%lld %17s", &stat_pid
, cmd
);
139 if (items_read
== 2 && pid
== stat_pid
)
141 cmd
[strlen (cmd
) - 1] = '\0'; /* Remove trailing parenthesis. */
142 strncpy (command
, cmd
+ 1, maxlen
); /* Ignore leading parenthesis. */
149 /* Return the PID if a /proc entry for the process cannot be found. */
150 snprintf (command
, maxlen
, "%lld", pid
);
153 command
[maxlen
- 1] = '\0'; /* Ensure string is null-terminated. */
158 /* Returns the command-line of the process with the given PID. The
159 returned string needs to be freed using xfree after use. */
162 commandline_from_pid (PID_T pid
)
164 char *pathname
= xstrprintf ("/proc/%lld/cmdline", pid
);
165 char *commandline
= NULL
;
166 FILE *f
= gdb_fopen_cloexec (pathname
, "r");
175 size_t read_bytes
= fread (buf
, 1, sizeof (buf
), f
);
179 commandline
= (char *) xrealloc (commandline
, len
+ read_bytes
+ 1);
180 memcpy (commandline
+ len
, buf
, read_bytes
);
191 /* Replace null characters with spaces. */
192 for (i
= 0; i
< len
; ++i
)
193 if (commandline
[i
] == '\0')
194 commandline
[i
] = ' ';
196 commandline
[len
] = '\0';
200 /* Return the command in square brackets if the command-line
202 commandline
= (char *) xmalloc (32);
203 commandline
[0] = '[';
204 command_from_pid (commandline
+ 1, 31, pid
);
206 len
= strlen (commandline
);
208 strcat (commandline
, "]");
217 /* Finds the user name for the user UID and copies it into USER. At
218 most MAXLEN characters are copied. */
221 user_from_uid (char *user
, int maxlen
, uid_t uid
)
223 struct passwd
*pwentry
= getpwuid (uid
);
227 strncpy (user
, pwentry
->pw_name
, maxlen
);
228 /* Ensure that the user name is null-terminated. */
229 user
[maxlen
- 1] = '\0';
235 /* Finds the owner of process PID and returns the user id in OWNER.
236 Returns 0 if the owner was found, -1 otherwise. */
239 get_process_owner (uid_t
*owner
, PID_T pid
)
242 char procentry
[sizeof ("/proc/") + MAX_PID_T_STRLEN
];
244 sprintf (procentry
, "/proc/%lld", pid
);
246 if (stat (procentry
, &statbuf
) == 0 && S_ISDIR (statbuf
.st_mode
))
248 *owner
= statbuf
.st_uid
;
255 /* Find the CPU cores used by process PID and return them in CORES.
256 CORES points to an array of NUM_CORES elements. */
259 get_cores_used_by_process (PID_T pid
, int *cores
, const int num_cores
)
261 char taskdir
[sizeof ("/proc/") + MAX_PID_T_STRLEN
+ sizeof ("/task") - 1];
266 sprintf (taskdir
, "/proc/%lld/task", pid
);
267 dir
= opendir (taskdir
);
270 while ((dp
= readdir (dir
)) != NULL
)
275 if (!isdigit (dp
->d_name
[0])
276 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
279 sscanf (dp
->d_name
, "%lld", &tid
);
280 core
= linux_common_core_of_thread (ptid_build ((pid_t
) pid
,
283 if (core
>= 0 && core
< num_cores
)
297 linux_xfer_osdata_processes (gdb_byte
*readbuf
,
298 ULONGEST offset
, ULONGEST len
)
300 /* We make the process list snapshot when the object starts to be read. */
301 static const char *buf
;
302 static LONGEST len_avail
= -1;
303 static struct buffer buffer
;
309 if (len_avail
!= -1 && len_avail
!= 0)
310 buffer_free (&buffer
);
313 buffer_init (&buffer
);
314 buffer_grow_str (&buffer
, "<osdata type=\"processes\">\n");
316 dirp
= opendir ("/proc");
319 const int num_cores
= sysconf (_SC_NPROCESSORS_ONLN
);
322 while ((dp
= readdir (dirp
)) != NULL
)
326 char user
[UT_NAMESIZE
];
333 if (!isdigit (dp
->d_name
[0])
334 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
337 sscanf (dp
->d_name
, "%lld", &pid
);
338 command_line
= commandline_from_pid (pid
);
340 if (get_process_owner (&owner
, pid
) == 0)
341 user_from_uid (user
, sizeof (user
), owner
);
345 /* Find CPU cores used by the process. */
346 cores
= (int *) xcalloc (num_cores
, sizeof (int));
347 task_count
= get_cores_used_by_process (pid
, cores
, num_cores
);
348 cores_str
= (char *) xcalloc (task_count
, sizeof ("4294967295") + 1);
350 for (i
= 0; i
< num_cores
&& task_count
> 0; ++i
)
353 char core_str
[sizeof ("4294967295")];
355 sprintf (core_str
, "%d", i
);
356 strcat (cores_str
, core_str
);
358 task_count
-= cores
[i
];
360 strcat (cores_str
, ",");
368 "<column name=\"pid\">%lld</column>"
369 "<column name=\"user\">%s</column>"
370 "<column name=\"command\">%s</column>"
371 "<column name=\"cores\">%s</column>"
375 command_line
? command_line
: "",
378 xfree (command_line
);
385 buffer_grow_str0 (&buffer
, "</osdata>\n");
386 buf
= buffer_finish (&buffer
);
387 len_avail
= strlen (buf
);
390 if (offset
>= len_avail
)
392 /* Done. Get rid of the buffer. */
393 buffer_free (&buffer
);
399 if (len
> len_avail
- offset
)
400 len
= len_avail
- offset
;
401 memcpy (readbuf
, buf
+ offset
, len
);
406 /* Auxiliary function used by qsort to sort processes by process
407 group. Compares two processes with ids PROCESS1 and PROCESS2.
408 PROCESS1 comes before PROCESS2 if it has a lower process group id.
409 If they belong to the same process group, PROCESS1 comes before
410 PROCESS2 if it has a lower process id or is the process group
414 compare_processes (const void *process1
, const void *process2
)
416 PID_T pid1
= *((PID_T
*) process1
);
417 PID_T pid2
= *((PID_T
*) process2
);
418 PID_T pgid1
= *((PID_T
*) process1
+ 1);
419 PID_T pgid2
= *((PID_T
*) process2
+ 1);
424 else if (pgid1
> pgid2
)
428 /* Process group leaders always come first, else sort by PID. */
431 else if (pid2
== pgid2
)
433 else if (pid1
< pid2
)
435 else if (pid1
> pid2
)
442 /* Collect all process groups from /proc. */
445 linux_xfer_osdata_processgroups (gdb_byte
*readbuf
,
446 ULONGEST offset
, ULONGEST len
)
448 /* We make the process list snapshot when the object starts to be read. */
449 static const char *buf
;
450 static LONGEST len_avail
= -1;
451 static struct buffer buffer
;
457 if (len_avail
!= -1 && len_avail
!= 0)
458 buffer_free (&buffer
);
461 buffer_init (&buffer
);
462 buffer_grow_str (&buffer
, "<osdata type=\"process groups\">\n");
464 dirp
= opendir ("/proc");
468 const size_t list_block_size
= 512;
469 PID_T
*process_list
= (PID_T
*) xmalloc (list_block_size
* 2 * sizeof (PID_T
));
470 size_t process_count
= 0;
473 /* Build list consisting of PIDs followed by their
475 while ((dp
= readdir (dirp
)) != NULL
)
479 if (!isdigit (dp
->d_name
[0])
480 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
483 sscanf (dp
->d_name
, "%lld", &pid
);
484 pgid
= getpgid (pid
);
488 process_list
[2 * process_count
] = pid
;
489 process_list
[2 * process_count
+ 1] = pgid
;
492 /* Increase the size of the list if necessary. */
493 if (process_count
% list_block_size
== 0)
494 process_list
= (PID_T
*) xrealloc (
496 (process_count
+ list_block_size
)
497 * 2 * sizeof (PID_T
));
503 /* Sort the process list. */
504 qsort (process_list
, process_count
, 2 * sizeof (PID_T
),
507 for (i
= 0; i
< process_count
; ++i
)
509 PID_T pid
= process_list
[2 * i
];
510 PID_T pgid
= process_list
[2 * i
+ 1];
511 char leader_command
[32];
514 command_from_pid (leader_command
, sizeof (leader_command
), pgid
);
515 command_line
= commandline_from_pid (pid
);
520 "<column name=\"pgid\">%lld</column>"
521 "<column name=\"leader command\">%s</column>"
522 "<column name=\"pid\">%lld</column>"
523 "<column name=\"command line\">%s</column>"
528 command_line
? command_line
: "");
530 xfree (command_line
);
533 xfree (process_list
);
536 buffer_grow_str0 (&buffer
, "</osdata>\n");
537 buf
= buffer_finish (&buffer
);
538 len_avail
= strlen (buf
);
541 if (offset
>= len_avail
)
543 /* Done. Get rid of the buffer. */
544 buffer_free (&buffer
);
550 if (len
> len_avail
- offset
)
551 len
= len_avail
- offset
;
552 memcpy (readbuf
, buf
+ offset
, len
);
557 /* Collect all the threads in /proc by iterating through processes and
558 then tasks within each process. */
561 linux_xfer_osdata_threads (gdb_byte
*readbuf
,
562 ULONGEST offset
, ULONGEST len
)
564 /* We make the process list snapshot when the object starts to be read. */
565 static const char *buf
;
566 static LONGEST len_avail
= -1;
567 static struct buffer buffer
;
573 if (len_avail
!= -1 && len_avail
!= 0)
574 buffer_free (&buffer
);
577 buffer_init (&buffer
);
578 buffer_grow_str (&buffer
, "<osdata type=\"threads\">\n");
580 dirp
= opendir ("/proc");
585 while ((dp
= readdir (dirp
)) != NULL
)
588 char procentry
[sizeof ("/proc/4294967295")];
590 if (!isdigit (dp
->d_name
[0])
591 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
594 sprintf (procentry
, "/proc/%s", dp
->d_name
);
595 if (stat (procentry
, &statbuf
) == 0
596 && S_ISDIR (statbuf
.st_mode
))
603 pathname
= xstrprintf ("/proc/%s/task", dp
->d_name
);
605 pid
= atoi (dp
->d_name
);
606 command_from_pid (command
, sizeof (command
), pid
);
608 dirp2
= opendir (pathname
);
614 while ((dp2
= readdir (dirp2
)) != NULL
)
619 if (!isdigit (dp2
->d_name
[0])
620 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
623 tid
= atoi (dp2
->d_name
);
624 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
629 "<column name=\"pid\">%lld</column>"
630 "<column name=\"command\">%s</column>"
631 "<column name=\"tid\">%lld</column>"
632 "<column name=\"core\">%d</column>"
650 buffer_grow_str0 (&buffer
, "</osdata>\n");
651 buf
= buffer_finish (&buffer
);
652 len_avail
= strlen (buf
);
655 if (offset
>= len_avail
)
657 /* Done. Get rid of the buffer. */
658 buffer_free (&buffer
);
664 if (len
> len_avail
- offset
)
665 len
= len_avail
- offset
;
666 memcpy (readbuf
, buf
+ offset
, len
);
671 /* Collect all the open file descriptors found in /proc and put the details
672 found about them into READBUF. */
675 linux_xfer_osdata_fds (gdb_byte
*readbuf
,
676 ULONGEST offset
, ULONGEST len
)
678 /* We make the process list snapshot when the object starts to be read. */
679 static const char *buf
;
680 static LONGEST len_avail
= -1;
681 static struct buffer buffer
;
687 if (len_avail
!= -1 && len_avail
!= 0)
688 buffer_free (&buffer
);
691 buffer_init (&buffer
);
692 buffer_grow_str (&buffer
, "<osdata type=\"files\">\n");
694 dirp
= opendir ("/proc");
699 while ((dp
= readdir (dirp
)) != NULL
)
702 char procentry
[sizeof ("/proc/4294967295")];
704 if (!isdigit (dp
->d_name
[0])
705 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
708 sprintf (procentry
, "/proc/%s", dp
->d_name
);
709 if (stat (procentry
, &statbuf
) == 0
710 && S_ISDIR (statbuf
.st_mode
))
717 pid
= atoi (dp
->d_name
);
718 command_from_pid (command
, sizeof (command
), pid
);
720 pathname
= xstrprintf ("/proc/%s/fd", dp
->d_name
);
721 dirp2
= opendir (pathname
);
727 while ((dp2
= readdir (dirp2
)) != NULL
)
733 if (!isdigit (dp2
->d_name
[0]))
736 fdname
= xstrprintf ("%s/%s", pathname
, dp2
->d_name
);
737 rslt
= readlink (fdname
, buf
, sizeof (buf
) - 1);
744 "<column name=\"pid\">%s</column>"
745 "<column name=\"command\">%s</column>"
746 "<column name=\"file descriptor\">%s</column>"
747 "<column name=\"name\">%s</column>"
752 (rslt
>= 0 ? buf
: dp2
->d_name
));
765 buffer_grow_str0 (&buffer
, "</osdata>\n");
766 buf
= buffer_finish (&buffer
);
767 len_avail
= strlen (buf
);
770 if (offset
>= len_avail
)
772 /* Done. Get rid of the buffer. */
773 buffer_free (&buffer
);
779 if (len
> len_avail
- offset
)
780 len
= len_avail
- offset
;
781 memcpy (readbuf
, buf
+ offset
, len
);
786 /* Returns the socket state STATE in textual form. */
789 format_socket_state (unsigned char state
)
791 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
808 case TCP_ESTABLISHED
:
809 return "ESTABLISHED";
838 struct sockaddr_in sin
;
839 struct sockaddr_in6 sin6
;
842 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
843 information for all open internet sockets of type FAMILY on the
844 system into BUFFER. If TCP is set, only TCP sockets are processed,
845 otherwise only UDP sockets are processed. */
848 print_sockets (unsigned short family
, int tcp
, struct buffer
*buffer
)
850 const char *proc_file
;
853 if (family
== AF_INET
)
854 proc_file
= tcp
? "/proc/net/tcp" : "/proc/net/udp";
855 else if (family
== AF_INET6
)
856 proc_file
= tcp
? "/proc/net/tcp6" : "/proc/net/udp6";
860 fp
= gdb_fopen_cloexec (proc_file
, "r");
867 if (fgets (buf
, sizeof (buf
), fp
))
870 unsigned int local_port
, remote_port
, state
;
871 char local_address
[NI_MAXHOST
], remote_address
[NI_MAXHOST
];
875 #error "local_address and remote_address buffers too small"
878 result
= sscanf (buf
,
879 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
880 local_address
, &local_port
,
881 remote_address
, &remote_port
,
887 union socket_addr locaddr
, remaddr
;
889 char user
[UT_NAMESIZE
];
890 char local_service
[NI_MAXSERV
], remote_service
[NI_MAXSERV
];
892 if (family
== AF_INET
)
894 sscanf (local_address
, "%X",
895 &locaddr
.sin
.sin_addr
.s_addr
);
896 sscanf (remote_address
, "%X",
897 &remaddr
.sin
.sin_addr
.s_addr
);
899 locaddr
.sin
.sin_port
= htons (local_port
);
900 remaddr
.sin
.sin_port
= htons (remote_port
);
902 addr_size
= sizeof (struct sockaddr_in
);
906 sscanf (local_address
, "%8X%8X%8X%8X",
907 locaddr
.sin6
.sin6_addr
.s6_addr32
,
908 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
909 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
910 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
911 sscanf (remote_address
, "%8X%8X%8X%8X",
912 remaddr
.sin6
.sin6_addr
.s6_addr32
,
913 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
914 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
915 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
917 locaddr
.sin6
.sin6_port
= htons (local_port
);
918 remaddr
.sin6
.sin6_port
= htons (remote_port
);
920 locaddr
.sin6
.sin6_flowinfo
= 0;
921 remaddr
.sin6
.sin6_flowinfo
= 0;
922 locaddr
.sin6
.sin6_scope_id
= 0;
923 remaddr
.sin6
.sin6_scope_id
= 0;
925 addr_size
= sizeof (struct sockaddr_in6
);
928 locaddr
.sa
.sa_family
= remaddr
.sa
.sa_family
= family
;
930 result
= getnameinfo (&locaddr
.sa
, addr_size
,
931 local_address
, sizeof (local_address
),
932 local_service
, sizeof (local_service
),
933 NI_NUMERICHOST
| NI_NUMERICSERV
934 | (tcp
? 0 : NI_DGRAM
));
938 result
= getnameinfo (&remaddr
.sa
, addr_size
,
940 sizeof (remote_address
),
942 sizeof (remote_service
),
943 NI_NUMERICHOST
| NI_NUMERICSERV
944 | (tcp
? 0 : NI_DGRAM
));
948 user_from_uid (user
, sizeof (user
), uid
);
953 "<column name=\"local address\">%s</column>"
954 "<column name=\"local port\">%s</column>"
955 "<column name=\"remote address\">%s</column>"
956 "<column name=\"remote port\">%s</column>"
957 "<column name=\"state\">%s</column>"
958 "<column name=\"user\">%s</column>"
959 "<column name=\"family\">%s</column>"
960 "<column name=\"protocol\">%s</column>"
966 format_socket_state (state
),
968 (family
== AF_INET
) ? "INET" : "INET6",
969 tcp
? "STREAM" : "DGRAM");
979 /* Collect data about internet sockets and write it into READBUF. */
982 linux_xfer_osdata_isockets (gdb_byte
*readbuf
,
983 ULONGEST offset
, ULONGEST len
)
985 static const char *buf
;
986 static LONGEST len_avail
= -1;
987 static struct buffer buffer
;
991 if (len_avail
!= -1 && len_avail
!= 0)
992 buffer_free (&buffer
);
995 buffer_init (&buffer
);
996 buffer_grow_str (&buffer
, "<osdata type=\"I sockets\">\n");
998 print_sockets (AF_INET
, 1, &buffer
);
999 print_sockets (AF_INET
, 0, &buffer
);
1000 print_sockets (AF_INET6
, 1, &buffer
);
1001 print_sockets (AF_INET6
, 0, &buffer
);
1003 buffer_grow_str0 (&buffer
, "</osdata>\n");
1004 buf
= buffer_finish (&buffer
);
1005 len_avail
= strlen (buf
);
1008 if (offset
>= len_avail
)
1010 /* Done. Get rid of the buffer. */
1011 buffer_free (&buffer
);
1017 if (len
> len_avail
- offset
)
1018 len
= len_avail
- offset
;
1019 memcpy (readbuf
, buf
+ offset
, len
);
1024 /* Converts the time SECONDS into textual form and copies it into a
1025 buffer TIME, with at most MAXLEN characters copied. */
1028 time_from_time_t (char *time
, int maxlen
, TIME_T seconds
)
1034 time_t t
= (time_t) seconds
;
1036 strncpy (time
, ctime (&t
), maxlen
);
1037 time
[maxlen
- 1] = '\0';
1041 /* Finds the group name for the group GID and copies it into GROUP.
1042 At most MAXLEN characters are copied. */
1045 group_from_gid (char *group
, int maxlen
, gid_t gid
)
1047 struct group
*grentry
= getgrgid (gid
);
1051 strncpy (group
, grentry
->gr_name
, maxlen
);
1052 /* Ensure that the group name is null-terminated. */
1053 group
[maxlen
- 1] = '\0';
1059 /* Collect data about shared memory recorded in /proc and write it
1063 linux_xfer_osdata_shm (gdb_byte
*readbuf
,
1064 ULONGEST offset
, ULONGEST len
)
1066 static const char *buf
;
1067 static LONGEST len_avail
= -1;
1068 static struct buffer buffer
;
1074 if (len_avail
!= -1 && len_avail
!= 0)
1075 buffer_free (&buffer
);
1078 buffer_init (&buffer
);
1079 buffer_grow_str (&buffer
, "<osdata type=\"shared memory\">\n");
1081 fp
= gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1088 if (fgets (buf
, sizeof (buf
), fp
))
1094 int shmid
, size
, nattch
;
1095 TIME_T atime
, dtime
, ctime
;
1099 items_read
= sscanf (buf
,
1100 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1101 &key
, &shmid
, &perms
, &size
,
1104 &uid
, &gid
, &cuid
, &cgid
,
1105 &atime
, &dtime
, &ctime
);
1107 if (items_read
== 14)
1109 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1110 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1111 char ccmd
[32], lcmd
[32];
1112 char atime_str
[32], dtime_str
[32], ctime_str
[32];
1114 user_from_uid (user
, sizeof (user
), uid
);
1115 group_from_gid (group
, sizeof (group
), gid
);
1116 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1117 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1119 command_from_pid (ccmd
, sizeof (ccmd
), cpid
);
1120 command_from_pid (lcmd
, sizeof (lcmd
), lpid
);
1122 time_from_time_t (atime_str
, sizeof (atime_str
), atime
);
1123 time_from_time_t (dtime_str
, sizeof (dtime_str
), dtime
);
1124 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1129 "<column name=\"key\">%d</column>"
1130 "<column name=\"shmid\">%d</column>"
1131 "<column name=\"permissions\">%o</column>"
1132 "<column name=\"size\">%d</column>"
1133 "<column name=\"creator command\">%s</column>"
1134 "<column name=\"last op. command\">%s</column>"
1135 "<column name=\"num attached\">%d</column>"
1136 "<column name=\"user\">%s</column>"
1137 "<column name=\"group\">%s</column>"
1138 "<column name=\"creator user\">%s</column>"
1139 "<column name=\"creator group\">%s</column>"
1140 "<column name=\"last shmat() time\">%s</column>"
1141 "<column name=\"last shmdt() time\">%s</column>"
1142 "<column name=\"last shmctl() time\">%s</column>"
1166 buffer_grow_str0 (&buffer
, "</osdata>\n");
1167 buf
= buffer_finish (&buffer
);
1168 len_avail
= strlen (buf
);
1171 if (offset
>= len_avail
)
1173 /* Done. Get rid of the buffer. */
1174 buffer_free (&buffer
);
1180 if (len
> len_avail
- offset
)
1181 len
= len_avail
- offset
;
1182 memcpy (readbuf
, buf
+ offset
, len
);
1187 /* Collect data about semaphores recorded in /proc and write it
1191 linux_xfer_osdata_sem (gdb_byte
*readbuf
,
1192 ULONGEST offset
, ULONGEST len
)
1194 static const char *buf
;
1195 static LONGEST len_avail
= -1;
1196 static struct buffer buffer
;
1202 if (len_avail
!= -1 && len_avail
!= 0)
1203 buffer_free (&buffer
);
1206 buffer_init (&buffer
);
1207 buffer_grow_str (&buffer
, "<osdata type=\"semaphores\">\n");
1209 fp
= gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1216 if (fgets (buf
, sizeof (buf
), fp
))
1221 unsigned int perms
, nsems
;
1223 TIME_T otime
, ctime
;
1226 items_read
= sscanf (buf
,
1227 "%d %d %o %u %d %d %d %d %lld %lld",
1228 &key
, &semid
, &perms
, &nsems
,
1229 &uid
, &gid
, &cuid
, &cgid
,
1232 if (items_read
== 10)
1234 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1235 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1236 char otime_str
[32], ctime_str
[32];
1238 user_from_uid (user
, sizeof (user
), uid
);
1239 group_from_gid (group
, sizeof (group
), gid
);
1240 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1241 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1243 time_from_time_t (otime_str
, sizeof (otime_str
), otime
);
1244 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1249 "<column name=\"key\">%d</column>"
1250 "<column name=\"semid\">%d</column>"
1251 "<column name=\"permissions\">%o</column>"
1252 "<column name=\"num semaphores\">%u</column>"
1253 "<column name=\"user\">%s</column>"
1254 "<column name=\"group\">%s</column>"
1255 "<column name=\"creator user\">%s</column>"
1256 "<column name=\"creator group\">%s</column>"
1257 "<column name=\"last semop() time\">%s</column>"
1258 "<column name=\"last semctl() time\">%s</column>"
1278 buffer_grow_str0 (&buffer
, "</osdata>\n");
1279 buf
= buffer_finish (&buffer
);
1280 len_avail
= strlen (buf
);
1283 if (offset
>= len_avail
)
1285 /* Done. Get rid of the buffer. */
1286 buffer_free (&buffer
);
1292 if (len
> len_avail
- offset
)
1293 len
= len_avail
- offset
;
1294 memcpy (readbuf
, buf
+ offset
, len
);
1299 /* Collect data about message queues recorded in /proc and write it
1303 linux_xfer_osdata_msg (gdb_byte
*readbuf
,
1304 ULONGEST offset
, ULONGEST len
)
1306 static const char *buf
;
1307 static LONGEST len_avail
= -1;
1308 static struct buffer buffer
;
1314 if (len_avail
!= -1 && len_avail
!= 0)
1315 buffer_free (&buffer
);
1318 buffer_init (&buffer
);
1319 buffer_grow_str (&buffer
, "<osdata type=\"message queues\">\n");
1321 fp
= gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1328 if (fgets (buf
, sizeof (buf
), fp
))
1334 unsigned int perms
, cbytes
, qnum
;
1336 TIME_T stime
, rtime
, ctime
;
1339 items_read
= sscanf (buf
,
1340 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1341 &key
, &msqid
, &perms
, &cbytes
, &qnum
,
1342 &lspid
, &lrpid
, &uid
, &gid
, &cuid
, &cgid
,
1343 &stime
, &rtime
, &ctime
);
1345 if (items_read
== 14)
1347 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1348 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1349 char lscmd
[32], lrcmd
[32];
1350 char stime_str
[32], rtime_str
[32], ctime_str
[32];
1352 user_from_uid (user
, sizeof (user
), uid
);
1353 group_from_gid (group
, sizeof (group
), gid
);
1354 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1355 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1357 command_from_pid (lscmd
, sizeof (lscmd
), lspid
);
1358 command_from_pid (lrcmd
, sizeof (lrcmd
), lrpid
);
1360 time_from_time_t (stime_str
, sizeof (stime_str
), stime
);
1361 time_from_time_t (rtime_str
, sizeof (rtime_str
), rtime
);
1362 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1367 "<column name=\"key\">%d</column>"
1368 "<column name=\"msqid\">%d</column>"
1369 "<column name=\"permissions\">%o</column>"
1370 "<column name=\"num used bytes\">%u</column>"
1371 "<column name=\"num messages\">%u</column>"
1372 "<column name=\"last msgsnd() command\">%s</column>"
1373 "<column name=\"last msgrcv() command\">%s</column>"
1374 "<column name=\"user\">%s</column>"
1375 "<column name=\"group\">%s</column>"
1376 "<column name=\"creator user\">%s</column>"
1377 "<column name=\"creator group\">%s</column>"
1378 "<column name=\"last msgsnd() time\">%s</column>"
1379 "<column name=\"last msgrcv() time\">%s</column>"
1380 "<column name=\"last msgctl() time\">%s</column>"
1404 buffer_grow_str0 (&buffer
, "</osdata>\n");
1405 buf
= buffer_finish (&buffer
);
1406 len_avail
= strlen (buf
);
1409 if (offset
>= len_avail
)
1411 /* Done. Get rid of the buffer. */
1412 buffer_free (&buffer
);
1418 if (len
> len_avail
- offset
)
1419 len
= len_avail
- offset
;
1420 memcpy (readbuf
, buf
+ offset
, len
);
1425 /* Collect data about loaded kernel modules and write it into
1429 linux_xfer_osdata_modules (gdb_byte
*readbuf
,
1430 ULONGEST offset
, ULONGEST len
)
1432 static const char *buf
;
1433 static LONGEST len_avail
= -1;
1434 static struct buffer buffer
;
1440 if (len_avail
!= -1 && len_avail
!= 0)
1441 buffer_free (&buffer
);
1444 buffer_init (&buffer
);
1445 buffer_grow_str (&buffer
, "<osdata type=\"modules\">\n");
1447 fp
= gdb_fopen_cloexec ("/proc/modules", "r");
1454 if (fgets (buf
, sizeof (buf
), fp
))
1456 char *name
, *dependencies
, *status
, *tmp
;
1458 unsigned long long address
;
1461 name
= strtok (buf
, " ");
1465 tmp
= strtok (NULL
, " ");
1468 if (sscanf (tmp
, "%u", &size
) != 1)
1471 tmp
= strtok (NULL
, " ");
1474 if (sscanf (tmp
, "%d", &uses
) != 1)
1477 dependencies
= strtok (NULL
, " ");
1478 if (dependencies
== NULL
)
1481 status
= strtok (NULL
, " ");
1485 tmp
= strtok (NULL
, "\n");
1488 if (sscanf (tmp
, "%llx", &address
) != 1)
1494 "<column name=\"name\">%s</column>"
1495 "<column name=\"size\">%u</column>"
1496 "<column name=\"num uses\">%d</column>"
1497 "<column name=\"dependencies\">%s</column>"
1498 "<column name=\"status\">%s</column>"
1499 "<column name=\"address\">%llx</column>"
1514 buffer_grow_str0 (&buffer
, "</osdata>\n");
1515 buf
= buffer_finish (&buffer
);
1516 len_avail
= strlen (buf
);
1519 if (offset
>= len_avail
)
1521 /* Done. Get rid of the buffer. */
1522 buffer_free (&buffer
);
1528 if (len
> len_avail
- offset
)
1529 len
= len_avail
- offset
;
1530 memcpy (readbuf
, buf
+ offset
, len
);
1535 struct osdata_type
{
1539 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, ULONGEST len
);
1540 } osdata_table
[] = {
1541 { "processes", "Processes", "Listing of all processes",
1542 linux_xfer_osdata_processes
},
1543 { "procgroups", "Process groups", "Listing of all process groups",
1544 linux_xfer_osdata_processgroups
},
1545 { "threads", "Threads", "Listing of all threads",
1546 linux_xfer_osdata_threads
},
1547 { "files", "File descriptors", "Listing of all file descriptors",
1548 linux_xfer_osdata_fds
},
1549 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1550 linux_xfer_osdata_isockets
},
1551 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1552 linux_xfer_osdata_shm
},
1553 { "semaphores", "Semaphores", "Listing of all semaphores",
1554 linux_xfer_osdata_sem
},
1555 { "msg", "Message queues", "Listing of all message queues",
1556 linux_xfer_osdata_msg
},
1557 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1558 linux_xfer_osdata_modules
},
1559 { NULL
, NULL
, NULL
}
1563 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
1564 ULONGEST offset
, ULONGEST len
)
1566 if (!annex
|| *annex
== '\0')
1568 static const char *buf
;
1569 static LONGEST len_avail
= -1;
1570 static struct buffer buffer
;
1576 if (len_avail
!= -1 && len_avail
!= 0)
1577 buffer_free (&buffer
);
1580 buffer_init (&buffer
);
1581 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
1583 for (i
= 0; osdata_table
[i
].type
; ++i
)
1587 "<column name=\"Type\">%s</column>"
1588 "<column name=\"Description\">%s</column>"
1589 "<column name=\"Title\">%s</column>"
1591 osdata_table
[i
].type
,
1592 osdata_table
[i
].description
,
1593 osdata_table
[i
].title
);
1595 buffer_grow_str0 (&buffer
, "</osdata>\n");
1596 buf
= buffer_finish (&buffer
);
1597 len_avail
= strlen (buf
);
1600 if (offset
>= len_avail
)
1602 /* Done. Get rid of the buffer. */
1603 buffer_free (&buffer
);
1609 if (len
> len_avail
- offset
)
1610 len
= len_avail
- offset
;
1611 memcpy (readbuf
, buf
+ offset
, len
);
1619 for (i
= 0; osdata_table
[i
].type
; ++i
)
1621 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
1623 gdb_assert (readbuf
);
1625 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);