1 /* Linux-specific functions to retrieve OS data.
3 Copyright (C) 2009-2013 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>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
42 #include "xml-utils.h"
44 #include "gdb_assert.h"
47 #include "filestuff.h"
49 #define NAMELEN(dirent) strlen ((dirent)->d_name)
51 /* Define PID_T to be a fixed size that is at least as large as pid_t,
52 so that reading pid values embedded in /proc works
55 typedef long long PID_T
;
57 /* Define TIME_T to be at least as large as time_t, so that reading
58 time values embedded in /proc works consistently. */
60 typedef long long TIME_T
;
62 #define MAX_PID_T_STRLEN (sizeof ("-9223372036854775808") - 1)
64 /* Returns the CPU core that thread PTID is currently running on. */
66 /* Compute and return the processor core of a given thread. */
69 linux_common_core_of_thread (ptid_t ptid
)
71 char filename
[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN
];
80 sprintf (filename
, "/proc/%lld/task/%lld/stat",
81 (PID_T
) ptid_get_pid (ptid
), (PID_T
) ptid_get_lwp (ptid
));
82 f
= gdb_fopen_cloexec (filename
, "r");
89 content
= xrealloc (content
, content_read
+ 1024);
90 n
= fread (content
+ content_read
, 1, 1024, f
);
94 content
[content_read
] = '\0';
99 p
= strchr (content
, '(');
107 /* If the first field after program name has index 0, then core number is
108 the field with index 36. There's no constant for that anywhere. */
110 p
= strtok_r (p
, " ", &ts
);
111 for (i
= 0; p
!= NULL
&& i
!= 36; ++i
)
112 p
= strtok_r (NULL
, " ", &ts
);
114 if (p
== NULL
|| sscanf (p
, "%d", &core
) == 0)
123 /* Finds the command-line of process PID and copies it into COMMAND.
124 At most MAXLEN characters are copied. If the command-line cannot
125 be found, PID is copied into command in text-form. */
128 command_from_pid (char *command
, int maxlen
, PID_T pid
)
130 char *stat_path
= xstrprintf ("/proc/%lld/stat", pid
);
131 FILE *fp
= gdb_fopen_cloexec (stat_path
, "r");
137 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
138 include/linux/sched.h in the Linux kernel sources) plus two
139 (for the brackets). */
142 int items_read
= fscanf (fp
, "%lld %17s", &stat_pid
, cmd
);
144 if (items_read
== 2 && pid
== stat_pid
)
146 cmd
[strlen (cmd
) - 1] = '\0'; /* Remove trailing parenthesis. */
147 strncpy (command
, cmd
+ 1, maxlen
); /* Ignore leading parenthesis. */
154 /* Return the PID if a /proc entry for the process cannot be found. */
155 snprintf (command
, maxlen
, "%lld", pid
);
158 command
[maxlen
- 1] = '\0'; /* Ensure string is null-terminated. */
163 /* Returns the command-line of the process with the given PID. The
164 returned string needs to be freed using xfree after use. */
167 commandline_from_pid (PID_T pid
)
169 char *pathname
= xstrprintf ("/proc/%lld/cmdline", pid
);
170 char *commandline
= NULL
;
171 FILE *f
= gdb_fopen_cloexec (pathname
, "r");
180 size_t read_bytes
= fread (buf
, 1, sizeof (buf
), f
);
184 commandline
= (char *) xrealloc (commandline
, len
+ read_bytes
+ 1);
185 memcpy (commandline
+ len
, buf
, read_bytes
);
196 /* Replace null characters with spaces. */
197 for (i
= 0; i
< len
; ++i
)
198 if (commandline
[i
] == '\0')
199 commandline
[i
] = ' ';
201 commandline
[len
] = '\0';
205 /* Return the command in square brackets if the command-line
207 commandline
= (char *) xmalloc (32);
208 commandline
[0] = '[';
209 command_from_pid (commandline
+ 1, 31, pid
);
211 len
= strlen (commandline
);
213 strcat (commandline
, "]");
222 /* Finds the user name for the user UID and copies it into USER. At
223 most MAXLEN characters are copied. */
226 user_from_uid (char *user
, int maxlen
, uid_t uid
)
228 struct passwd
*pwentry
= getpwuid (uid
);
232 strncpy (user
, pwentry
->pw_name
, maxlen
);
233 /* Ensure that the user name is null-terminated. */
234 user
[maxlen
- 1] = '\0';
240 /* Finds the owner of process PID and returns the user id in OWNER.
241 Returns 0 if the owner was found, -1 otherwise. */
244 get_process_owner (uid_t
*owner
, PID_T pid
)
247 char procentry
[sizeof ("/proc/") + MAX_PID_T_STRLEN
];
249 sprintf (procentry
, "/proc/%lld", pid
);
251 if (stat (procentry
, &statbuf
) == 0 && S_ISDIR (statbuf
.st_mode
))
253 *owner
= statbuf
.st_uid
;
260 /* Find the CPU cores used by process PID and return them in CORES.
261 CORES points to an array of at least sysconf(_SC_NPROCESSOR_ONLN)
265 get_cores_used_by_process (PID_T pid
, int *cores
)
267 char taskdir
[sizeof ("/proc/") + MAX_PID_T_STRLEN
+ sizeof ("/task") - 1];
272 sprintf (taskdir
, "/proc/%lld/task", pid
);
273 dir
= opendir (taskdir
);
276 while ((dp
= readdir (dir
)) != NULL
)
281 if (!isdigit (dp
->d_name
[0])
282 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
285 sscanf (dp
->d_name
, "%lld", &tid
);
286 core
= linux_common_core_of_thread (ptid_build ((pid_t
) pid
,
303 linux_xfer_osdata_processes (gdb_byte
*readbuf
,
304 ULONGEST offset
, LONGEST len
)
306 /* We make the process list snapshot when the object starts to be read. */
307 static const char *buf
;
308 static LONGEST len_avail
= -1;
309 static struct buffer buffer
;
315 if (len_avail
!= -1 && len_avail
!= 0)
316 buffer_free (&buffer
);
319 buffer_init (&buffer
);
320 buffer_grow_str (&buffer
, "<osdata type=\"processes\">\n");
322 dirp
= opendir ("/proc");
325 const int num_cores
= sysconf (_SC_NPROCESSORS_ONLN
);
328 while ((dp
= readdir (dirp
)) != NULL
)
332 char user
[UT_NAMESIZE
];
339 if (!isdigit (dp
->d_name
[0])
340 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
343 sscanf (dp
->d_name
, "%lld", &pid
);
344 command_line
= commandline_from_pid (pid
);
346 if (get_process_owner (&owner
, pid
) == 0)
347 user_from_uid (user
, sizeof (user
), owner
);
351 /* Find CPU cores used by the process. */
352 cores
= (int *) xcalloc (num_cores
, sizeof (int));
353 task_count
= get_cores_used_by_process (pid
, cores
);
354 cores_str
= (char *) xcalloc (task_count
, sizeof ("4294967295") + 1);
356 for (i
= 0; i
< num_cores
&& task_count
> 0; ++i
)
359 char core_str
[sizeof ("4294967295")];
361 sprintf (core_str
, "%d", i
);
362 strcat (cores_str
, core_str
);
364 task_count
-= cores
[i
];
366 strcat (cores_str
, ",");
374 "<column name=\"pid\">%lld</column>"
375 "<column name=\"user\">%s</column>"
376 "<column name=\"command\">%s</column>"
377 "<column name=\"cores\">%s</column>"
381 command_line
? command_line
: "",
384 xfree (command_line
);
391 buffer_grow_str0 (&buffer
, "</osdata>\n");
392 buf
= buffer_finish (&buffer
);
393 len_avail
= strlen (buf
);
396 if (offset
>= len_avail
)
398 /* Done. Get rid of the buffer. */
399 buffer_free (&buffer
);
405 if (len
> len_avail
- offset
)
406 len
= len_avail
- offset
;
407 memcpy (readbuf
, buf
+ offset
, len
);
412 /* Auxiliary function used by qsort to sort processes by process
413 group. Compares two processes with ids PROCESS1 and PROCESS2.
414 PROCESS1 comes before PROCESS2 if it has a lower process group id.
415 If they belong to the same process group, PROCESS1 comes before
416 PROCESS2 if it has a lower process id or is the process group
420 compare_processes (const void *process1
, const void *process2
)
422 PID_T pid1
= *((PID_T
*) process1
);
423 PID_T pid2
= *((PID_T
*) process2
);
424 PID_T pgid1
= *((PID_T
*) process1
+ 1);
425 PID_T pgid2
= *((PID_T
*) process2
+ 1);
430 else if (pgid1
> pgid2
)
434 /* Process group leaders always come first, else sort by PID. */
437 else if (pid2
== pgid2
)
439 else if (pid1
< pid2
)
441 else if (pid1
> pid2
)
448 /* Collect all process groups from /proc. */
451 linux_xfer_osdata_processgroups (gdb_byte
*readbuf
,
452 ULONGEST offset
, LONGEST len
)
454 /* We make the process list snapshot when the object starts to be read. */
455 static const char *buf
;
456 static LONGEST len_avail
= -1;
457 static struct buffer buffer
;
463 if (len_avail
!= -1 && len_avail
!= 0)
464 buffer_free (&buffer
);
467 buffer_init (&buffer
);
468 buffer_grow_str (&buffer
, "<osdata type=\"process groups\">\n");
470 dirp
= opendir ("/proc");
474 const size_t list_block_size
= 512;
475 PID_T
*process_list
= (PID_T
*) xmalloc (list_block_size
* 2 * sizeof (PID_T
));
476 size_t process_count
= 0;
479 /* Build list consisting of PIDs followed by their
481 while ((dp
= readdir (dirp
)) != NULL
)
485 if (!isdigit (dp
->d_name
[0])
486 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
489 sscanf (dp
->d_name
, "%lld", &pid
);
490 pgid
= getpgid (pid
);
494 process_list
[2 * process_count
] = pid
;
495 process_list
[2 * process_count
+ 1] = pgid
;
498 /* Increase the size of the list if necessary. */
499 if (process_count
% list_block_size
== 0)
500 process_list
= (PID_T
*) xrealloc (
502 (process_count
+ list_block_size
)
503 * 2 * sizeof (PID_T
));
509 /* Sort the process list. */
510 qsort (process_list
, process_count
, 2 * sizeof (PID_T
),
513 for (i
= 0; i
< process_count
; ++i
)
515 PID_T pid
= process_list
[2 * i
];
516 PID_T pgid
= process_list
[2 * i
+ 1];
517 char leader_command
[32];
520 command_from_pid (leader_command
, sizeof (leader_command
), pgid
);
521 command_line
= commandline_from_pid (pid
);
526 "<column name=\"pgid\">%lld</column>"
527 "<column name=\"leader command\">%s</column>"
528 "<column name=\"pid\">%lld</column>"
529 "<column name=\"command line\">%s</column>"
534 command_line
? command_line
: "");
536 xfree (command_line
);
539 xfree (process_list
);
542 buffer_grow_str0 (&buffer
, "</osdata>\n");
543 buf
= buffer_finish (&buffer
);
544 len_avail
= strlen (buf
);
547 if (offset
>= len_avail
)
549 /* Done. Get rid of the buffer. */
550 buffer_free (&buffer
);
556 if (len
> len_avail
- offset
)
557 len
= len_avail
- offset
;
558 memcpy (readbuf
, buf
+ offset
, len
);
563 /* Collect all the threads in /proc by iterating through processes and
564 then tasks within each process. */
567 linux_xfer_osdata_threads (gdb_byte
*readbuf
,
568 ULONGEST offset
, LONGEST len
)
570 /* We make the process list snapshot when the object starts to be read. */
571 static const char *buf
;
572 static LONGEST len_avail
= -1;
573 static struct buffer buffer
;
579 if (len_avail
!= -1 && len_avail
!= 0)
580 buffer_free (&buffer
);
583 buffer_init (&buffer
);
584 buffer_grow_str (&buffer
, "<osdata type=\"threads\">\n");
586 dirp
= opendir ("/proc");
591 while ((dp
= readdir (dirp
)) != NULL
)
594 char procentry
[sizeof ("/proc/4294967295")];
596 if (!isdigit (dp
->d_name
[0])
597 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
600 sprintf (procentry
, "/proc/%s", dp
->d_name
);
601 if (stat (procentry
, &statbuf
) == 0
602 && S_ISDIR (statbuf
.st_mode
))
609 pathname
= xstrprintf ("/proc/%s/task", dp
->d_name
);
611 pid
= atoi (dp
->d_name
);
612 command_from_pid (command
, sizeof (command
), pid
);
614 dirp2
= opendir (pathname
);
620 while ((dp2
= readdir (dirp2
)) != NULL
)
625 if (!isdigit (dp2
->d_name
[0])
626 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
629 tid
= atoi (dp2
->d_name
);
630 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
635 "<column name=\"pid\">%lld</column>"
636 "<column name=\"command\">%s</column>"
637 "<column name=\"tid\">%lld</column>"
638 "<column name=\"core\">%d</column>"
656 buffer_grow_str0 (&buffer
, "</osdata>\n");
657 buf
= buffer_finish (&buffer
);
658 len_avail
= strlen (buf
);
661 if (offset
>= len_avail
)
663 /* Done. Get rid of the buffer. */
664 buffer_free (&buffer
);
670 if (len
> len_avail
- offset
)
671 len
= len_avail
- offset
;
672 memcpy (readbuf
, buf
+ offset
, len
);
677 /* Collect all the open file descriptors found in /proc and put the details
678 found about them into READBUF. */
681 linux_xfer_osdata_fds (gdb_byte
*readbuf
,
682 ULONGEST offset
, LONGEST len
)
684 /* We make the process list snapshot when the object starts to be read. */
685 static const char *buf
;
686 static LONGEST len_avail
= -1;
687 static struct buffer buffer
;
693 if (len_avail
!= -1 && len_avail
!= 0)
694 buffer_free (&buffer
);
697 buffer_init (&buffer
);
698 buffer_grow_str (&buffer
, "<osdata type=\"files\">\n");
700 dirp
= opendir ("/proc");
705 while ((dp
= readdir (dirp
)) != NULL
)
708 char procentry
[sizeof ("/proc/4294967295")];
710 if (!isdigit (dp
->d_name
[0])
711 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
714 sprintf (procentry
, "/proc/%s", dp
->d_name
);
715 if (stat (procentry
, &statbuf
) == 0
716 && S_ISDIR (statbuf
.st_mode
))
723 pid
= atoi (dp
->d_name
);
724 command_from_pid (command
, sizeof (command
), pid
);
726 pathname
= xstrprintf ("/proc/%s/fd", dp
->d_name
);
727 dirp2
= opendir (pathname
);
733 while ((dp2
= readdir (dirp2
)) != NULL
)
739 if (!isdigit (dp2
->d_name
[0]))
742 fdname
= xstrprintf ("%s/%s", pathname
, dp2
->d_name
);
743 rslt
= readlink (fdname
, buf
, sizeof (buf
) - 1);
750 "<column name=\"pid\">%s</column>"
751 "<column name=\"command\">%s</column>"
752 "<column name=\"file descriptor\">%s</column>"
753 "<column name=\"name\">%s</column>"
758 (rslt
>= 0 ? buf
: dp2
->d_name
));
771 buffer_grow_str0 (&buffer
, "</osdata>\n");
772 buf
= buffer_finish (&buffer
);
773 len_avail
= strlen (buf
);
776 if (offset
>= len_avail
)
778 /* Done. Get rid of the buffer. */
779 buffer_free (&buffer
);
785 if (len
> len_avail
- offset
)
786 len
= len_avail
- offset
;
787 memcpy (readbuf
, buf
+ offset
, len
);
792 /* Returns the socket state STATE in textual form. */
795 format_socket_state (unsigned char state
)
797 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
814 case TCP_ESTABLISHED
:
815 return "ESTABLISHED";
844 struct sockaddr_in sin
;
845 struct sockaddr_in6 sin6
;
848 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
849 information for all open internet sockets of type FAMILY on the
850 system into BUFFER. If TCP is set, only TCP sockets are processed,
851 otherwise only UDP sockets are processed. */
854 print_sockets (unsigned short family
, int tcp
, struct buffer
*buffer
)
856 const char *proc_file
;
859 if (family
== AF_INET
)
860 proc_file
= tcp
? "/proc/net/tcp" : "/proc/net/udp";
861 else if (family
== AF_INET6
)
862 proc_file
= tcp
? "/proc/net/tcp6" : "/proc/net/udp6";
866 fp
= gdb_fopen_cloexec (proc_file
, "r");
873 if (fgets (buf
, sizeof (buf
), fp
))
876 unsigned int local_port
, remote_port
, state
;
877 char local_address
[NI_MAXHOST
], remote_address
[NI_MAXHOST
];
881 #error "local_address and remote_address buffers too small"
884 result
= sscanf (buf
,
885 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
886 local_address
, &local_port
,
887 remote_address
, &remote_port
,
893 union socket_addr locaddr
, remaddr
;
895 char user
[UT_NAMESIZE
];
896 char local_service
[NI_MAXSERV
], remote_service
[NI_MAXSERV
];
898 if (family
== AF_INET
)
900 sscanf (local_address
, "%X",
901 &locaddr
.sin
.sin_addr
.s_addr
);
902 sscanf (remote_address
, "%X",
903 &remaddr
.sin
.sin_addr
.s_addr
);
905 locaddr
.sin
.sin_port
= htons (local_port
);
906 remaddr
.sin
.sin_port
= htons (remote_port
);
908 addr_size
= sizeof (struct sockaddr_in
);
912 sscanf (local_address
, "%8X%8X%8X%8X",
913 locaddr
.sin6
.sin6_addr
.s6_addr32
,
914 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
915 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
916 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
917 sscanf (remote_address
, "%8X%8X%8X%8X",
918 remaddr
.sin6
.sin6_addr
.s6_addr32
,
919 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
920 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
921 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
923 locaddr
.sin6
.sin6_port
= htons (local_port
);
924 remaddr
.sin6
.sin6_port
= htons (remote_port
);
926 locaddr
.sin6
.sin6_flowinfo
= 0;
927 remaddr
.sin6
.sin6_flowinfo
= 0;
928 locaddr
.sin6
.sin6_scope_id
= 0;
929 remaddr
.sin6
.sin6_scope_id
= 0;
931 addr_size
= sizeof (struct sockaddr_in6
);
934 locaddr
.sa
.sa_family
= remaddr
.sa
.sa_family
= family
;
936 result
= getnameinfo (&locaddr
.sa
, addr_size
,
937 local_address
, sizeof (local_address
),
938 local_service
, sizeof (local_service
),
939 NI_NUMERICHOST
| NI_NUMERICSERV
940 | (tcp
? 0 : NI_DGRAM
));
944 result
= getnameinfo (&remaddr
.sa
, addr_size
,
946 sizeof (remote_address
),
948 sizeof (remote_service
),
949 NI_NUMERICHOST
| NI_NUMERICSERV
950 | (tcp
? 0 : NI_DGRAM
));
954 user_from_uid (user
, sizeof (user
), uid
);
959 "<column name=\"local address\">%s</column>"
960 "<column name=\"local port\">%s</column>"
961 "<column name=\"remote address\">%s</column>"
962 "<column name=\"remote port\">%s</column>"
963 "<column name=\"state\">%s</column>"
964 "<column name=\"user\">%s</column>"
965 "<column name=\"family\">%s</column>"
966 "<column name=\"protocol\">%s</column>"
972 format_socket_state (state
),
974 (family
== AF_INET
) ? "INET" : "INET6",
975 tcp
? "STREAM" : "DGRAM");
985 /* Collect data about internet sockets and write it into READBUF. */
988 linux_xfer_osdata_isockets (gdb_byte
*readbuf
,
989 ULONGEST offset
, LONGEST len
)
991 static const char *buf
;
992 static LONGEST len_avail
= -1;
993 static struct buffer buffer
;
997 if (len_avail
!= -1 && len_avail
!= 0)
998 buffer_free (&buffer
);
1001 buffer_init (&buffer
);
1002 buffer_grow_str (&buffer
, "<osdata type=\"I sockets\">\n");
1004 print_sockets (AF_INET
, 1, &buffer
);
1005 print_sockets (AF_INET
, 0, &buffer
);
1006 print_sockets (AF_INET6
, 1, &buffer
);
1007 print_sockets (AF_INET6
, 0, &buffer
);
1009 buffer_grow_str0 (&buffer
, "</osdata>\n");
1010 buf
= buffer_finish (&buffer
);
1011 len_avail
= strlen (buf
);
1014 if (offset
>= len_avail
)
1016 /* Done. Get rid of the buffer. */
1017 buffer_free (&buffer
);
1023 if (len
> len_avail
- offset
)
1024 len
= len_avail
- offset
;
1025 memcpy (readbuf
, buf
+ offset
, len
);
1030 /* Converts the time SECONDS into textual form and copies it into a
1031 buffer TIME, with at most MAXLEN characters copied. */
1034 time_from_time_t (char *time
, int maxlen
, TIME_T seconds
)
1040 time_t t
= (time_t) seconds
;
1042 strncpy (time
, ctime (&t
), maxlen
);
1043 time
[maxlen
- 1] = '\0';
1047 /* Finds the group name for the group GID and copies it into GROUP.
1048 At most MAXLEN characters are copied. */
1051 group_from_gid (char *group
, int maxlen
, gid_t gid
)
1053 struct group
*grentry
= getgrgid (gid
);
1057 strncpy (group
, grentry
->gr_name
, maxlen
);
1058 /* Ensure that the group name is null-terminated. */
1059 group
[maxlen
- 1] = '\0';
1065 /* Collect data about shared memory recorded in /proc and write it
1069 linux_xfer_osdata_shm (gdb_byte
*readbuf
,
1070 ULONGEST offset
, LONGEST len
)
1072 static const char *buf
;
1073 static LONGEST len_avail
= -1;
1074 static struct buffer buffer
;
1080 if (len_avail
!= -1 && len_avail
!= 0)
1081 buffer_free (&buffer
);
1084 buffer_init (&buffer
);
1085 buffer_grow_str (&buffer
, "<osdata type=\"shared memory\">\n");
1087 fp
= gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1094 if (fgets (buf
, sizeof (buf
), fp
))
1100 int shmid
, size
, nattch
;
1101 TIME_T atime
, dtime
, ctime
;
1105 items_read
= sscanf (buf
,
1106 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1107 &key
, &shmid
, &perms
, &size
,
1110 &uid
, &gid
, &cuid
, &cgid
,
1111 &atime
, &dtime
, &ctime
);
1113 if (items_read
== 14)
1115 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1116 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1117 char ccmd
[32], lcmd
[32];
1118 char atime_str
[32], dtime_str
[32], ctime_str
[32];
1120 user_from_uid (user
, sizeof (user
), uid
);
1121 group_from_gid (group
, sizeof (group
), gid
);
1122 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1123 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1125 command_from_pid (ccmd
, sizeof (ccmd
), cpid
);
1126 command_from_pid (lcmd
, sizeof (lcmd
), lpid
);
1128 time_from_time_t (atime_str
, sizeof (atime_str
), atime
);
1129 time_from_time_t (dtime_str
, sizeof (dtime_str
), dtime
);
1130 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1135 "<column name=\"key\">%d</column>"
1136 "<column name=\"shmid\">%d</column>"
1137 "<column name=\"permissions\">%o</column>"
1138 "<column name=\"size\">%d</column>"
1139 "<column name=\"creator command\">%s</column>"
1140 "<column name=\"last op. command\">%s</column>"
1141 "<column name=\"num attached\">%d</column>"
1142 "<column name=\"user\">%s</column>"
1143 "<column name=\"group\">%s</column>"
1144 "<column name=\"creator user\">%s</column>"
1145 "<column name=\"creator group\">%s</column>"
1146 "<column name=\"last shmat() time\">%s</column>"
1147 "<column name=\"last shmdt() time\">%s</column>"
1148 "<column name=\"last shmctl() time\">%s</column>"
1172 buffer_grow_str0 (&buffer
, "</osdata>\n");
1173 buf
= buffer_finish (&buffer
);
1174 len_avail
= strlen (buf
);
1177 if (offset
>= len_avail
)
1179 /* Done. Get rid of the buffer. */
1180 buffer_free (&buffer
);
1186 if (len
> len_avail
- offset
)
1187 len
= len_avail
- offset
;
1188 memcpy (readbuf
, buf
+ offset
, len
);
1193 /* Collect data about semaphores recorded in /proc and write it
1197 linux_xfer_osdata_sem (gdb_byte
*readbuf
,
1198 ULONGEST offset
, LONGEST len
)
1200 static const char *buf
;
1201 static LONGEST len_avail
= -1;
1202 static struct buffer buffer
;
1208 if (len_avail
!= -1 && len_avail
!= 0)
1209 buffer_free (&buffer
);
1212 buffer_init (&buffer
);
1213 buffer_grow_str (&buffer
, "<osdata type=\"semaphores\">\n");
1215 fp
= gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1222 if (fgets (buf
, sizeof (buf
), fp
))
1227 unsigned int perms
, nsems
;
1229 TIME_T otime
, ctime
;
1232 items_read
= sscanf (buf
,
1233 "%d %d %o %u %d %d %d %d %lld %lld",
1234 &key
, &semid
, &perms
, &nsems
,
1235 &uid
, &gid
, &cuid
, &cgid
,
1238 if (items_read
== 10)
1240 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1241 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1242 char otime_str
[32], ctime_str
[32];
1244 user_from_uid (user
, sizeof (user
), uid
);
1245 group_from_gid (group
, sizeof (group
), gid
);
1246 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1247 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1249 time_from_time_t (otime_str
, sizeof (otime_str
), otime
);
1250 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1255 "<column name=\"key\">%d</column>"
1256 "<column name=\"semid\">%d</column>"
1257 "<column name=\"permissions\">%o</column>"
1258 "<column name=\"num semaphores\">%u</column>"
1259 "<column name=\"user\">%s</column>"
1260 "<column name=\"group\">%s</column>"
1261 "<column name=\"creator user\">%s</column>"
1262 "<column name=\"creator group\">%s</column>"
1263 "<column name=\"last semop() time\">%s</column>"
1264 "<column name=\"last semctl() time\">%s</column>"
1284 buffer_grow_str0 (&buffer
, "</osdata>\n");
1285 buf
= buffer_finish (&buffer
);
1286 len_avail
= strlen (buf
);
1289 if (offset
>= len_avail
)
1291 /* Done. Get rid of the buffer. */
1292 buffer_free (&buffer
);
1298 if (len
> len_avail
- offset
)
1299 len
= len_avail
- offset
;
1300 memcpy (readbuf
, buf
+ offset
, len
);
1305 /* Collect data about message queues recorded in /proc and write it
1309 linux_xfer_osdata_msg (gdb_byte
*readbuf
,
1310 ULONGEST offset
, LONGEST len
)
1312 static const char *buf
;
1313 static LONGEST len_avail
= -1;
1314 static struct buffer buffer
;
1320 if (len_avail
!= -1 && len_avail
!= 0)
1321 buffer_free (&buffer
);
1324 buffer_init (&buffer
);
1325 buffer_grow_str (&buffer
, "<osdata type=\"message queues\">\n");
1327 fp
= gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1334 if (fgets (buf
, sizeof (buf
), fp
))
1340 unsigned int perms
, cbytes
, qnum
;
1342 TIME_T stime
, rtime
, ctime
;
1345 items_read
= sscanf (buf
,
1346 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1347 &key
, &msqid
, &perms
, &cbytes
, &qnum
,
1348 &lspid
, &lrpid
, &uid
, &gid
, &cuid
, &cgid
,
1349 &stime
, &rtime
, &ctime
);
1351 if (items_read
== 14)
1353 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1354 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1355 char lscmd
[32], lrcmd
[32];
1356 char stime_str
[32], rtime_str
[32], ctime_str
[32];
1358 user_from_uid (user
, sizeof (user
), uid
);
1359 group_from_gid (group
, sizeof (group
), gid
);
1360 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1361 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1363 command_from_pid (lscmd
, sizeof (lscmd
), lspid
);
1364 command_from_pid (lrcmd
, sizeof (lrcmd
), lrpid
);
1366 time_from_time_t (stime_str
, sizeof (stime_str
), stime
);
1367 time_from_time_t (rtime_str
, sizeof (rtime_str
), rtime
);
1368 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1373 "<column name=\"key\">%d</column>"
1374 "<column name=\"msqid\">%d</column>"
1375 "<column name=\"permissions\">%o</column>"
1376 "<column name=\"num used bytes\">%u</column>"
1377 "<column name=\"num messages\">%u</column>"
1378 "<column name=\"last msgsnd() command\">%s</column>"
1379 "<column name=\"last msgrcv() command\">%s</column>"
1380 "<column name=\"user\">%s</column>"
1381 "<column name=\"group\">%s</column>"
1382 "<column name=\"creator user\">%s</column>"
1383 "<column name=\"creator group\">%s</column>"
1384 "<column name=\"last msgsnd() time\">%s</column>"
1385 "<column name=\"last msgrcv() time\">%s</column>"
1386 "<column name=\"last msgctl() time\">%s</column>"
1410 buffer_grow_str0 (&buffer
, "</osdata>\n");
1411 buf
= buffer_finish (&buffer
);
1412 len_avail
= strlen (buf
);
1415 if (offset
>= len_avail
)
1417 /* Done. Get rid of the buffer. */
1418 buffer_free (&buffer
);
1424 if (len
> len_avail
- offset
)
1425 len
= len_avail
- offset
;
1426 memcpy (readbuf
, buf
+ offset
, len
);
1431 /* Collect data about loaded kernel modules and write it into
1435 linux_xfer_osdata_modules (gdb_byte
*readbuf
,
1436 ULONGEST offset
, LONGEST len
)
1438 static const char *buf
;
1439 static LONGEST len_avail
= -1;
1440 static struct buffer buffer
;
1446 if (len_avail
!= -1 && len_avail
!= 0)
1447 buffer_free (&buffer
);
1450 buffer_init (&buffer
);
1451 buffer_grow_str (&buffer
, "<osdata type=\"modules\">\n");
1453 fp
= gdb_fopen_cloexec ("/proc/modules", "r");
1460 if (fgets (buf
, sizeof (buf
), fp
))
1462 char *name
, *dependencies
, *status
, *tmp
;
1464 unsigned long long address
;
1467 name
= strtok (buf
, " ");
1471 tmp
= strtok (NULL
, " ");
1474 if (sscanf (tmp
, "%u", &size
) != 1)
1477 tmp
= strtok (NULL
, " ");
1480 if (sscanf (tmp
, "%d", &uses
) != 1)
1483 dependencies
= strtok (NULL
, " ");
1484 if (dependencies
== NULL
)
1487 status
= strtok (NULL
, " ");
1491 tmp
= strtok (NULL
, "\n");
1494 if (sscanf (tmp
, "%llx", &address
) != 1)
1500 "<column name=\"name\">%s</column>"
1501 "<column name=\"size\">%u</column>"
1502 "<column name=\"num uses\">%d</column>"
1503 "<column name=\"dependencies\">%s</column>"
1504 "<column name=\"status\">%s</column>"
1505 "<column name=\"address\">%llx</column>"
1520 buffer_grow_str0 (&buffer
, "</osdata>\n");
1521 buf
= buffer_finish (&buffer
);
1522 len_avail
= strlen (buf
);
1525 if (offset
>= len_avail
)
1527 /* Done. Get rid of the buffer. */
1528 buffer_free (&buffer
);
1534 if (len
> len_avail
- offset
)
1535 len
= len_avail
- offset
;
1536 memcpy (readbuf
, buf
+ offset
, len
);
1541 struct osdata_type
{
1545 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, LONGEST len
);
1546 } osdata_table
[] = {
1547 { "processes", "Processes", "Listing of all processes",
1548 linux_xfer_osdata_processes
},
1549 { "procgroups", "Process groups", "Listing of all process groups",
1550 linux_xfer_osdata_processgroups
},
1551 { "threads", "Threads", "Listing of all threads",
1552 linux_xfer_osdata_threads
},
1553 { "files", "File descriptors", "Listing of all file descriptors",
1554 linux_xfer_osdata_fds
},
1555 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1556 linux_xfer_osdata_isockets
},
1557 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1558 linux_xfer_osdata_shm
},
1559 { "semaphores", "Semaphores", "Listing of all semaphores",
1560 linux_xfer_osdata_sem
},
1561 { "msg", "Message queues", "Listing of all message queues",
1562 linux_xfer_osdata_msg
},
1563 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1564 linux_xfer_osdata_modules
},
1565 { NULL
, NULL
, NULL
}
1569 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
1570 ULONGEST offset
, LONGEST len
)
1572 if (!annex
|| *annex
== '\0')
1574 static const char *buf
;
1575 static LONGEST len_avail
= -1;
1576 static struct buffer buffer
;
1582 if (len_avail
!= -1 && len_avail
!= 0)
1583 buffer_free (&buffer
);
1586 buffer_init (&buffer
);
1587 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
1589 for (i
= 0; osdata_table
[i
].type
; ++i
)
1593 "<column name=\"Type\">%s</column>"
1594 "<column name=\"Description\">%s</column>"
1595 "<column name=\"Title\">%s</column>"
1597 osdata_table
[i
].type
,
1598 osdata_table
[i
].description
,
1599 osdata_table
[i
].title
);
1601 buffer_grow_str0 (&buffer
, "</osdata>\n");
1602 buf
= buffer_finish (&buffer
);
1603 len_avail
= strlen (buf
);
1606 if (offset
>= len_avail
)
1608 /* Done. Get rid of the buffer. */
1609 buffer_free (&buffer
);
1615 if (len
> len_avail
- offset
)
1616 len
= len_avail
- offset
;
1617 memcpy (readbuf
, buf
+ offset
, len
);
1625 for (i
= 0; osdata_table
[i
].type
; ++i
)
1627 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
1629 gdb_assert (readbuf
);
1631 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);