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>
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 /* ps command also relies on no trailing fields ever contain ')'. */
100 p
= strrchr (content
, ')');
104 /* If the first field after program name has index 0, then core number is
105 the field with index 36. There's no constant for that anywhere. */
107 p
= strtok_r (p
, " ", &ts
);
108 for (i
= 0; p
!= NULL
&& i
!= 36; ++i
)
109 p
= strtok_r (NULL
, " ", &ts
);
111 if (p
== NULL
|| sscanf (p
, "%d", &core
) == 0)
120 /* Finds the command-line of process PID and copies it into COMMAND.
121 At most MAXLEN characters are copied. If the command-line cannot
122 be found, PID is copied into command in text-form. */
125 command_from_pid (char *command
, int maxlen
, PID_T pid
)
127 char *stat_path
= xstrprintf ("/proc/%lld/stat", pid
);
128 FILE *fp
= gdb_fopen_cloexec (stat_path
, "r");
134 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
135 include/linux/sched.h in the Linux kernel sources) plus two
136 (for the brackets). */
139 int items_read
= fscanf (fp
, "%lld %17s", &stat_pid
, cmd
);
141 if (items_read
== 2 && pid
== stat_pid
)
143 cmd
[strlen (cmd
) - 1] = '\0'; /* Remove trailing parenthesis. */
144 strncpy (command
, cmd
+ 1, maxlen
); /* Ignore leading parenthesis. */
151 /* Return the PID if a /proc entry for the process cannot be found. */
152 snprintf (command
, maxlen
, "%lld", pid
);
155 command
[maxlen
- 1] = '\0'; /* Ensure string is null-terminated. */
160 /* Returns the command-line of the process with the given PID. The
161 returned string needs to be freed using xfree after use. */
164 commandline_from_pid (PID_T pid
)
166 char *pathname
= xstrprintf ("/proc/%lld/cmdline", pid
);
167 char *commandline
= NULL
;
168 FILE *f
= gdb_fopen_cloexec (pathname
, "r");
177 size_t read_bytes
= fread (buf
, 1, sizeof (buf
), f
);
181 commandline
= (char *) xrealloc (commandline
, len
+ read_bytes
+ 1);
182 memcpy (commandline
+ len
, buf
, read_bytes
);
193 /* Replace null characters with spaces. */
194 for (i
= 0; i
< len
; ++i
)
195 if (commandline
[i
] == '\0')
196 commandline
[i
] = ' ';
198 commandline
[len
] = '\0';
202 /* Return the command in square brackets if the command-line
204 commandline
= (char *) xmalloc (32);
205 commandline
[0] = '[';
206 command_from_pid (commandline
+ 1, 31, pid
);
208 len
= strlen (commandline
);
210 strcat (commandline
, "]");
219 /* Finds the user name for the user UID and copies it into USER. At
220 most MAXLEN characters are copied. */
223 user_from_uid (char *user
, int maxlen
, uid_t uid
)
225 struct passwd
*pwentry
= getpwuid (uid
);
229 strncpy (user
, pwentry
->pw_name
, maxlen
);
230 /* Ensure that the user name is null-terminated. */
231 user
[maxlen
- 1] = '\0';
237 /* Finds the owner of process PID and returns the user id in OWNER.
238 Returns 0 if the owner was found, -1 otherwise. */
241 get_process_owner (uid_t
*owner
, PID_T pid
)
244 char procentry
[sizeof ("/proc/") + MAX_PID_T_STRLEN
];
246 sprintf (procentry
, "/proc/%lld", pid
);
248 if (stat (procentry
, &statbuf
) == 0 && S_ISDIR (statbuf
.st_mode
))
250 *owner
= statbuf
.st_uid
;
257 /* Find the CPU cores used by process PID and return them in CORES.
258 CORES points to an array of NUM_CORES elements. */
261 get_cores_used_by_process (PID_T pid
, int *cores
, const int num_cores
)
263 char taskdir
[sizeof ("/proc/") + MAX_PID_T_STRLEN
+ sizeof ("/task") - 1];
268 sprintf (taskdir
, "/proc/%lld/task", pid
);
269 dir
= opendir (taskdir
);
272 while ((dp
= readdir (dir
)) != NULL
)
277 if (!isdigit (dp
->d_name
[0])
278 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
281 sscanf (dp
->d_name
, "%lld", &tid
);
282 core
= linux_common_core_of_thread (ptid_build ((pid_t
) pid
,
285 if (core
>= 0 && core
< num_cores
)
299 linux_xfer_osdata_processes (gdb_byte
*readbuf
,
300 ULONGEST offset
, ULONGEST len
)
302 /* We make the process list snapshot when the object starts to be read. */
303 static const char *buf
;
304 static LONGEST len_avail
= -1;
305 static struct buffer buffer
;
311 if (len_avail
!= -1 && len_avail
!= 0)
312 buffer_free (&buffer
);
315 buffer_init (&buffer
);
316 buffer_grow_str (&buffer
, "<osdata type=\"processes\">\n");
318 dirp
= opendir ("/proc");
321 const int num_cores
= sysconf (_SC_NPROCESSORS_ONLN
);
324 while ((dp
= readdir (dirp
)) != NULL
)
328 char user
[UT_NAMESIZE
];
335 if (!isdigit (dp
->d_name
[0])
336 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
339 sscanf (dp
->d_name
, "%lld", &pid
);
340 command_line
= commandline_from_pid (pid
);
342 if (get_process_owner (&owner
, pid
) == 0)
343 user_from_uid (user
, sizeof (user
), owner
);
347 /* Find CPU cores used by the process. */
348 cores
= (int *) xcalloc (num_cores
, sizeof (int));
349 task_count
= get_cores_used_by_process (pid
, cores
, num_cores
);
350 cores_str
= (char *) xcalloc (task_count
, sizeof ("4294967295") + 1);
352 for (i
= 0; i
< num_cores
&& task_count
> 0; ++i
)
355 char core_str
[sizeof ("4294967295")];
357 sprintf (core_str
, "%d", i
);
358 strcat (cores_str
, core_str
);
360 task_count
-= cores
[i
];
362 strcat (cores_str
, ",");
370 "<column name=\"pid\">%lld</column>"
371 "<column name=\"user\">%s</column>"
372 "<column name=\"command\">%s</column>"
373 "<column name=\"cores\">%s</column>"
377 command_line
? command_line
: "",
380 xfree (command_line
);
387 buffer_grow_str0 (&buffer
, "</osdata>\n");
388 buf
= buffer_finish (&buffer
);
389 len_avail
= strlen (buf
);
392 if (offset
>= len_avail
)
394 /* Done. Get rid of the buffer. */
395 buffer_free (&buffer
);
401 if (len
> len_avail
- offset
)
402 len
= len_avail
- offset
;
403 memcpy (readbuf
, buf
+ offset
, len
);
408 /* Auxiliary function used by qsort to sort processes by process
409 group. Compares two processes with ids PROCESS1 and PROCESS2.
410 PROCESS1 comes before PROCESS2 if it has a lower process group id.
411 If they belong to the same process group, PROCESS1 comes before
412 PROCESS2 if it has a lower process id or is the process group
416 compare_processes (const void *process1
, const void *process2
)
418 PID_T pid1
= *((PID_T
*) process1
);
419 PID_T pid2
= *((PID_T
*) process2
);
420 PID_T pgid1
= *((PID_T
*) process1
+ 1);
421 PID_T pgid2
= *((PID_T
*) process2
+ 1);
426 else if (pgid1
> pgid2
)
430 /* Process group leaders always come first, else sort by PID. */
433 else if (pid2
== pgid2
)
435 else if (pid1
< pid2
)
437 else if (pid1
> pid2
)
444 /* Collect all process groups from /proc. */
447 linux_xfer_osdata_processgroups (gdb_byte
*readbuf
,
448 ULONGEST offset
, ULONGEST len
)
450 /* We make the process list snapshot when the object starts to be read. */
451 static const char *buf
;
452 static LONGEST len_avail
= -1;
453 static struct buffer buffer
;
459 if (len_avail
!= -1 && len_avail
!= 0)
460 buffer_free (&buffer
);
463 buffer_init (&buffer
);
464 buffer_grow_str (&buffer
, "<osdata type=\"process groups\">\n");
466 dirp
= opendir ("/proc");
470 const size_t list_block_size
= 512;
471 PID_T
*process_list
= (PID_T
*) xmalloc (list_block_size
* 2 * sizeof (PID_T
));
472 size_t process_count
= 0;
475 /* Build list consisting of PIDs followed by their
477 while ((dp
= readdir (dirp
)) != NULL
)
481 if (!isdigit (dp
->d_name
[0])
482 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
485 sscanf (dp
->d_name
, "%lld", &pid
);
486 pgid
= getpgid (pid
);
490 process_list
[2 * process_count
] = pid
;
491 process_list
[2 * process_count
+ 1] = pgid
;
494 /* Increase the size of the list if necessary. */
495 if (process_count
% list_block_size
== 0)
496 process_list
= (PID_T
*) xrealloc (
498 (process_count
+ list_block_size
)
499 * 2 * sizeof (PID_T
));
505 /* Sort the process list. */
506 qsort (process_list
, process_count
, 2 * sizeof (PID_T
),
509 for (i
= 0; i
< process_count
; ++i
)
511 PID_T pid
= process_list
[2 * i
];
512 PID_T pgid
= process_list
[2 * i
+ 1];
513 char leader_command
[32];
516 command_from_pid (leader_command
, sizeof (leader_command
), pgid
);
517 command_line
= commandline_from_pid (pid
);
522 "<column name=\"pgid\">%lld</column>"
523 "<column name=\"leader command\">%s</column>"
524 "<column name=\"pid\">%lld</column>"
525 "<column name=\"command line\">%s</column>"
530 command_line
? command_line
: "");
532 xfree (command_line
);
535 xfree (process_list
);
538 buffer_grow_str0 (&buffer
, "</osdata>\n");
539 buf
= buffer_finish (&buffer
);
540 len_avail
= strlen (buf
);
543 if (offset
>= len_avail
)
545 /* Done. Get rid of the buffer. */
546 buffer_free (&buffer
);
552 if (len
> len_avail
- offset
)
553 len
= len_avail
- offset
;
554 memcpy (readbuf
, buf
+ offset
, len
);
559 /* Collect all the threads in /proc by iterating through processes and
560 then tasks within each process. */
563 linux_xfer_osdata_threads (gdb_byte
*readbuf
,
564 ULONGEST offset
, ULONGEST len
)
566 /* We make the process list snapshot when the object starts to be read. */
567 static const char *buf
;
568 static LONGEST len_avail
= -1;
569 static struct buffer buffer
;
575 if (len_avail
!= -1 && len_avail
!= 0)
576 buffer_free (&buffer
);
579 buffer_init (&buffer
);
580 buffer_grow_str (&buffer
, "<osdata type=\"threads\">\n");
582 dirp
= opendir ("/proc");
587 while ((dp
= readdir (dirp
)) != NULL
)
590 char procentry
[sizeof ("/proc/4294967295")];
592 if (!isdigit (dp
->d_name
[0])
593 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
596 sprintf (procentry
, "/proc/%s", dp
->d_name
);
597 if (stat (procentry
, &statbuf
) == 0
598 && S_ISDIR (statbuf
.st_mode
))
605 pathname
= xstrprintf ("/proc/%s/task", dp
->d_name
);
607 pid
= atoi (dp
->d_name
);
608 command_from_pid (command
, sizeof (command
), pid
);
610 dirp2
= opendir (pathname
);
616 while ((dp2
= readdir (dirp2
)) != NULL
)
621 if (!isdigit (dp2
->d_name
[0])
622 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
625 tid
= atoi (dp2
->d_name
);
626 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
631 "<column name=\"pid\">%lld</column>"
632 "<column name=\"command\">%s</column>"
633 "<column name=\"tid\">%lld</column>"
634 "<column name=\"core\">%d</column>"
652 buffer_grow_str0 (&buffer
, "</osdata>\n");
653 buf
= buffer_finish (&buffer
);
654 len_avail
= strlen (buf
);
657 if (offset
>= len_avail
)
659 /* Done. Get rid of the buffer. */
660 buffer_free (&buffer
);
666 if (len
> len_avail
- offset
)
667 len
= len_avail
- offset
;
668 memcpy (readbuf
, buf
+ offset
, len
);
673 /* Collect all the open file descriptors found in /proc and put the details
674 found about them into READBUF. */
677 linux_xfer_osdata_fds (gdb_byte
*readbuf
,
678 ULONGEST offset
, ULONGEST len
)
680 /* We make the process list snapshot when the object starts to be read. */
681 static const char *buf
;
682 static LONGEST len_avail
= -1;
683 static struct buffer buffer
;
689 if (len_avail
!= -1 && len_avail
!= 0)
690 buffer_free (&buffer
);
693 buffer_init (&buffer
);
694 buffer_grow_str (&buffer
, "<osdata type=\"files\">\n");
696 dirp
= opendir ("/proc");
701 while ((dp
= readdir (dirp
)) != NULL
)
704 char procentry
[sizeof ("/proc/4294967295")];
706 if (!isdigit (dp
->d_name
[0])
707 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
710 sprintf (procentry
, "/proc/%s", dp
->d_name
);
711 if (stat (procentry
, &statbuf
) == 0
712 && S_ISDIR (statbuf
.st_mode
))
719 pid
= atoi (dp
->d_name
);
720 command_from_pid (command
, sizeof (command
), pid
);
722 pathname
= xstrprintf ("/proc/%s/fd", dp
->d_name
);
723 dirp2
= opendir (pathname
);
729 while ((dp2
= readdir (dirp2
)) != NULL
)
735 if (!isdigit (dp2
->d_name
[0]))
738 fdname
= xstrprintf ("%s/%s", pathname
, dp2
->d_name
);
739 rslt
= readlink (fdname
, buf
, sizeof (buf
) - 1);
746 "<column name=\"pid\">%s</column>"
747 "<column name=\"command\">%s</column>"
748 "<column name=\"file descriptor\">%s</column>"
749 "<column name=\"name\">%s</column>"
754 (rslt
>= 0 ? buf
: dp2
->d_name
));
767 buffer_grow_str0 (&buffer
, "</osdata>\n");
768 buf
= buffer_finish (&buffer
);
769 len_avail
= strlen (buf
);
772 if (offset
>= len_avail
)
774 /* Done. Get rid of the buffer. */
775 buffer_free (&buffer
);
781 if (len
> len_avail
- offset
)
782 len
= len_avail
- offset
;
783 memcpy (readbuf
, buf
+ offset
, len
);
788 /* Returns the socket state STATE in textual form. */
791 format_socket_state (unsigned char state
)
793 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
810 case TCP_ESTABLISHED
:
811 return "ESTABLISHED";
840 struct sockaddr_in sin
;
841 struct sockaddr_in6 sin6
;
844 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
845 information for all open internet sockets of type FAMILY on the
846 system into BUFFER. If TCP is set, only TCP sockets are processed,
847 otherwise only UDP sockets are processed. */
850 print_sockets (unsigned short family
, int tcp
, struct buffer
*buffer
)
852 const char *proc_file
;
855 if (family
== AF_INET
)
856 proc_file
= tcp
? "/proc/net/tcp" : "/proc/net/udp";
857 else if (family
== AF_INET6
)
858 proc_file
= tcp
? "/proc/net/tcp6" : "/proc/net/udp6";
862 fp
= gdb_fopen_cloexec (proc_file
, "r");
869 if (fgets (buf
, sizeof (buf
), fp
))
872 unsigned int local_port
, remote_port
, state
;
873 char local_address
[NI_MAXHOST
], remote_address
[NI_MAXHOST
];
877 #error "local_address and remote_address buffers too small"
880 result
= sscanf (buf
,
881 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
882 local_address
, &local_port
,
883 remote_address
, &remote_port
,
889 union socket_addr locaddr
, remaddr
;
891 char user
[UT_NAMESIZE
];
892 char local_service
[NI_MAXSERV
], remote_service
[NI_MAXSERV
];
894 if (family
== AF_INET
)
896 sscanf (local_address
, "%X",
897 &locaddr
.sin
.sin_addr
.s_addr
);
898 sscanf (remote_address
, "%X",
899 &remaddr
.sin
.sin_addr
.s_addr
);
901 locaddr
.sin
.sin_port
= htons (local_port
);
902 remaddr
.sin
.sin_port
= htons (remote_port
);
904 addr_size
= sizeof (struct sockaddr_in
);
908 sscanf (local_address
, "%8X%8X%8X%8X",
909 locaddr
.sin6
.sin6_addr
.s6_addr32
,
910 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
911 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
912 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
913 sscanf (remote_address
, "%8X%8X%8X%8X",
914 remaddr
.sin6
.sin6_addr
.s6_addr32
,
915 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
916 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
917 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
919 locaddr
.sin6
.sin6_port
= htons (local_port
);
920 remaddr
.sin6
.sin6_port
= htons (remote_port
);
922 locaddr
.sin6
.sin6_flowinfo
= 0;
923 remaddr
.sin6
.sin6_flowinfo
= 0;
924 locaddr
.sin6
.sin6_scope_id
= 0;
925 remaddr
.sin6
.sin6_scope_id
= 0;
927 addr_size
= sizeof (struct sockaddr_in6
);
930 locaddr
.sa
.sa_family
= remaddr
.sa
.sa_family
= family
;
932 result
= getnameinfo (&locaddr
.sa
, addr_size
,
933 local_address
, sizeof (local_address
),
934 local_service
, sizeof (local_service
),
935 NI_NUMERICHOST
| NI_NUMERICSERV
936 | (tcp
? 0 : NI_DGRAM
));
940 result
= getnameinfo (&remaddr
.sa
, addr_size
,
942 sizeof (remote_address
),
944 sizeof (remote_service
),
945 NI_NUMERICHOST
| NI_NUMERICSERV
946 | (tcp
? 0 : NI_DGRAM
));
950 user_from_uid (user
, sizeof (user
), uid
);
955 "<column name=\"local address\">%s</column>"
956 "<column name=\"local port\">%s</column>"
957 "<column name=\"remote address\">%s</column>"
958 "<column name=\"remote port\">%s</column>"
959 "<column name=\"state\">%s</column>"
960 "<column name=\"user\">%s</column>"
961 "<column name=\"family\">%s</column>"
962 "<column name=\"protocol\">%s</column>"
968 format_socket_state (state
),
970 (family
== AF_INET
) ? "INET" : "INET6",
971 tcp
? "STREAM" : "DGRAM");
981 /* Collect data about internet sockets and write it into READBUF. */
984 linux_xfer_osdata_isockets (gdb_byte
*readbuf
,
985 ULONGEST offset
, ULONGEST len
)
987 static const char *buf
;
988 static LONGEST len_avail
= -1;
989 static struct buffer buffer
;
993 if (len_avail
!= -1 && len_avail
!= 0)
994 buffer_free (&buffer
);
997 buffer_init (&buffer
);
998 buffer_grow_str (&buffer
, "<osdata type=\"I sockets\">\n");
1000 print_sockets (AF_INET
, 1, &buffer
);
1001 print_sockets (AF_INET
, 0, &buffer
);
1002 print_sockets (AF_INET6
, 1, &buffer
);
1003 print_sockets (AF_INET6
, 0, &buffer
);
1005 buffer_grow_str0 (&buffer
, "</osdata>\n");
1006 buf
= buffer_finish (&buffer
);
1007 len_avail
= strlen (buf
);
1010 if (offset
>= len_avail
)
1012 /* Done. Get rid of the buffer. */
1013 buffer_free (&buffer
);
1019 if (len
> len_avail
- offset
)
1020 len
= len_avail
- offset
;
1021 memcpy (readbuf
, buf
+ offset
, len
);
1026 /* Converts the time SECONDS into textual form and copies it into a
1027 buffer TIME, with at most MAXLEN characters copied. */
1030 time_from_time_t (char *time
, int maxlen
, TIME_T seconds
)
1036 time_t t
= (time_t) seconds
;
1038 strncpy (time
, ctime (&t
), maxlen
);
1039 time
[maxlen
- 1] = '\0';
1043 /* Finds the group name for the group GID and copies it into GROUP.
1044 At most MAXLEN characters are copied. */
1047 group_from_gid (char *group
, int maxlen
, gid_t gid
)
1049 struct group
*grentry
= getgrgid (gid
);
1053 strncpy (group
, grentry
->gr_name
, maxlen
);
1054 /* Ensure that the group name is null-terminated. */
1055 group
[maxlen
- 1] = '\0';
1061 /* Collect data about shared memory recorded in /proc and write it
1065 linux_xfer_osdata_shm (gdb_byte
*readbuf
,
1066 ULONGEST offset
, ULONGEST len
)
1068 static const char *buf
;
1069 static LONGEST len_avail
= -1;
1070 static struct buffer buffer
;
1076 if (len_avail
!= -1 && len_avail
!= 0)
1077 buffer_free (&buffer
);
1080 buffer_init (&buffer
);
1081 buffer_grow_str (&buffer
, "<osdata type=\"shared memory\">\n");
1083 fp
= gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1090 if (fgets (buf
, sizeof (buf
), fp
))
1096 int shmid
, size
, nattch
;
1097 TIME_T atime
, dtime
, ctime
;
1101 items_read
= sscanf (buf
,
1102 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1103 &key
, &shmid
, &perms
, &size
,
1106 &uid
, &gid
, &cuid
, &cgid
,
1107 &atime
, &dtime
, &ctime
);
1109 if (items_read
== 14)
1111 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1112 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1113 char ccmd
[32], lcmd
[32];
1114 char atime_str
[32], dtime_str
[32], ctime_str
[32];
1116 user_from_uid (user
, sizeof (user
), uid
);
1117 group_from_gid (group
, sizeof (group
), gid
);
1118 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1119 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1121 command_from_pid (ccmd
, sizeof (ccmd
), cpid
);
1122 command_from_pid (lcmd
, sizeof (lcmd
), lpid
);
1124 time_from_time_t (atime_str
, sizeof (atime_str
), atime
);
1125 time_from_time_t (dtime_str
, sizeof (dtime_str
), dtime
);
1126 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1131 "<column name=\"key\">%d</column>"
1132 "<column name=\"shmid\">%d</column>"
1133 "<column name=\"permissions\">%o</column>"
1134 "<column name=\"size\">%d</column>"
1135 "<column name=\"creator command\">%s</column>"
1136 "<column name=\"last op. command\">%s</column>"
1137 "<column name=\"num attached\">%d</column>"
1138 "<column name=\"user\">%s</column>"
1139 "<column name=\"group\">%s</column>"
1140 "<column name=\"creator user\">%s</column>"
1141 "<column name=\"creator group\">%s</column>"
1142 "<column name=\"last shmat() time\">%s</column>"
1143 "<column name=\"last shmdt() time\">%s</column>"
1144 "<column name=\"last shmctl() time\">%s</column>"
1168 buffer_grow_str0 (&buffer
, "</osdata>\n");
1169 buf
= buffer_finish (&buffer
);
1170 len_avail
= strlen (buf
);
1173 if (offset
>= len_avail
)
1175 /* Done. Get rid of the buffer. */
1176 buffer_free (&buffer
);
1182 if (len
> len_avail
- offset
)
1183 len
= len_avail
- offset
;
1184 memcpy (readbuf
, buf
+ offset
, len
);
1189 /* Collect data about semaphores recorded in /proc and write it
1193 linux_xfer_osdata_sem (gdb_byte
*readbuf
,
1194 ULONGEST offset
, ULONGEST len
)
1196 static const char *buf
;
1197 static LONGEST len_avail
= -1;
1198 static struct buffer buffer
;
1204 if (len_avail
!= -1 && len_avail
!= 0)
1205 buffer_free (&buffer
);
1208 buffer_init (&buffer
);
1209 buffer_grow_str (&buffer
, "<osdata type=\"semaphores\">\n");
1211 fp
= gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1218 if (fgets (buf
, sizeof (buf
), fp
))
1223 unsigned int perms
, nsems
;
1225 TIME_T otime
, ctime
;
1228 items_read
= sscanf (buf
,
1229 "%d %d %o %u %d %d %d %d %lld %lld",
1230 &key
, &semid
, &perms
, &nsems
,
1231 &uid
, &gid
, &cuid
, &cgid
,
1234 if (items_read
== 10)
1236 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1237 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1238 char otime_str
[32], ctime_str
[32];
1240 user_from_uid (user
, sizeof (user
), uid
);
1241 group_from_gid (group
, sizeof (group
), gid
);
1242 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1243 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1245 time_from_time_t (otime_str
, sizeof (otime_str
), otime
);
1246 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1251 "<column name=\"key\">%d</column>"
1252 "<column name=\"semid\">%d</column>"
1253 "<column name=\"permissions\">%o</column>"
1254 "<column name=\"num semaphores\">%u</column>"
1255 "<column name=\"user\">%s</column>"
1256 "<column name=\"group\">%s</column>"
1257 "<column name=\"creator user\">%s</column>"
1258 "<column name=\"creator group\">%s</column>"
1259 "<column name=\"last semop() time\">%s</column>"
1260 "<column name=\"last semctl() time\">%s</column>"
1280 buffer_grow_str0 (&buffer
, "</osdata>\n");
1281 buf
= buffer_finish (&buffer
);
1282 len_avail
= strlen (buf
);
1285 if (offset
>= len_avail
)
1287 /* Done. Get rid of the buffer. */
1288 buffer_free (&buffer
);
1294 if (len
> len_avail
- offset
)
1295 len
= len_avail
- offset
;
1296 memcpy (readbuf
, buf
+ offset
, len
);
1301 /* Collect data about message queues recorded in /proc and write it
1305 linux_xfer_osdata_msg (gdb_byte
*readbuf
,
1306 ULONGEST offset
, ULONGEST len
)
1308 static const char *buf
;
1309 static LONGEST len_avail
= -1;
1310 static struct buffer buffer
;
1316 if (len_avail
!= -1 && len_avail
!= 0)
1317 buffer_free (&buffer
);
1320 buffer_init (&buffer
);
1321 buffer_grow_str (&buffer
, "<osdata type=\"message queues\">\n");
1323 fp
= gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1330 if (fgets (buf
, sizeof (buf
), fp
))
1336 unsigned int perms
, cbytes
, qnum
;
1338 TIME_T stime
, rtime
, ctime
;
1341 items_read
= sscanf (buf
,
1342 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1343 &key
, &msqid
, &perms
, &cbytes
, &qnum
,
1344 &lspid
, &lrpid
, &uid
, &gid
, &cuid
, &cgid
,
1345 &stime
, &rtime
, &ctime
);
1347 if (items_read
== 14)
1349 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1350 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1351 char lscmd
[32], lrcmd
[32];
1352 char stime_str
[32], rtime_str
[32], ctime_str
[32];
1354 user_from_uid (user
, sizeof (user
), uid
);
1355 group_from_gid (group
, sizeof (group
), gid
);
1356 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1357 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1359 command_from_pid (lscmd
, sizeof (lscmd
), lspid
);
1360 command_from_pid (lrcmd
, sizeof (lrcmd
), lrpid
);
1362 time_from_time_t (stime_str
, sizeof (stime_str
), stime
);
1363 time_from_time_t (rtime_str
, sizeof (rtime_str
), rtime
);
1364 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1369 "<column name=\"key\">%d</column>"
1370 "<column name=\"msqid\">%d</column>"
1371 "<column name=\"permissions\">%o</column>"
1372 "<column name=\"num used bytes\">%u</column>"
1373 "<column name=\"num messages\">%u</column>"
1374 "<column name=\"last msgsnd() command\">%s</column>"
1375 "<column name=\"last msgrcv() command\">%s</column>"
1376 "<column name=\"user\">%s</column>"
1377 "<column name=\"group\">%s</column>"
1378 "<column name=\"creator user\">%s</column>"
1379 "<column name=\"creator group\">%s</column>"
1380 "<column name=\"last msgsnd() time\">%s</column>"
1381 "<column name=\"last msgrcv() time\">%s</column>"
1382 "<column name=\"last msgctl() time\">%s</column>"
1406 buffer_grow_str0 (&buffer
, "</osdata>\n");
1407 buf
= buffer_finish (&buffer
);
1408 len_avail
= strlen (buf
);
1411 if (offset
>= len_avail
)
1413 /* Done. Get rid of the buffer. */
1414 buffer_free (&buffer
);
1420 if (len
> len_avail
- offset
)
1421 len
= len_avail
- offset
;
1422 memcpy (readbuf
, buf
+ offset
, len
);
1427 /* Collect data about loaded kernel modules and write it into
1431 linux_xfer_osdata_modules (gdb_byte
*readbuf
,
1432 ULONGEST offset
, ULONGEST len
)
1434 static const char *buf
;
1435 static LONGEST len_avail
= -1;
1436 static struct buffer buffer
;
1442 if (len_avail
!= -1 && len_avail
!= 0)
1443 buffer_free (&buffer
);
1446 buffer_init (&buffer
);
1447 buffer_grow_str (&buffer
, "<osdata type=\"modules\">\n");
1449 fp
= gdb_fopen_cloexec ("/proc/modules", "r");
1456 if (fgets (buf
, sizeof (buf
), fp
))
1458 char *name
, *dependencies
, *status
, *tmp
;
1460 unsigned long long address
;
1463 name
= strtok (buf
, " ");
1467 tmp
= strtok (NULL
, " ");
1470 if (sscanf (tmp
, "%u", &size
) != 1)
1473 tmp
= strtok (NULL
, " ");
1476 if (sscanf (tmp
, "%d", &uses
) != 1)
1479 dependencies
= strtok (NULL
, " ");
1480 if (dependencies
== NULL
)
1483 status
= strtok (NULL
, " ");
1487 tmp
= strtok (NULL
, "\n");
1490 if (sscanf (tmp
, "%llx", &address
) != 1)
1496 "<column name=\"name\">%s</column>"
1497 "<column name=\"size\">%u</column>"
1498 "<column name=\"num uses\">%d</column>"
1499 "<column name=\"dependencies\">%s</column>"
1500 "<column name=\"status\">%s</column>"
1501 "<column name=\"address\">%llx</column>"
1516 buffer_grow_str0 (&buffer
, "</osdata>\n");
1517 buf
= buffer_finish (&buffer
);
1518 len_avail
= strlen (buf
);
1521 if (offset
>= len_avail
)
1523 /* Done. Get rid of the buffer. */
1524 buffer_free (&buffer
);
1530 if (len
> len_avail
- offset
)
1531 len
= len_avail
- offset
;
1532 memcpy (readbuf
, buf
+ offset
, len
);
1537 struct osdata_type
{
1541 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, ULONGEST len
);
1542 } osdata_table
[] = {
1543 { "processes", "Processes", "Listing of all processes",
1544 linux_xfer_osdata_processes
},
1545 { "procgroups", "Process groups", "Listing of all process groups",
1546 linux_xfer_osdata_processgroups
},
1547 { "threads", "Threads", "Listing of all threads",
1548 linux_xfer_osdata_threads
},
1549 { "files", "File descriptors", "Listing of all file descriptors",
1550 linux_xfer_osdata_fds
},
1551 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1552 linux_xfer_osdata_isockets
},
1553 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1554 linux_xfer_osdata_shm
},
1555 { "semaphores", "Semaphores", "Listing of all semaphores",
1556 linux_xfer_osdata_sem
},
1557 { "msg", "Message queues", "Listing of all message queues",
1558 linux_xfer_osdata_msg
},
1559 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1560 linux_xfer_osdata_modules
},
1561 { NULL
, NULL
, NULL
}
1565 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
1566 ULONGEST offset
, ULONGEST len
)
1568 if (!annex
|| *annex
== '\0')
1570 static const char *buf
;
1571 static LONGEST len_avail
= -1;
1572 static struct buffer buffer
;
1578 if (len_avail
!= -1 && len_avail
!= 0)
1579 buffer_free (&buffer
);
1582 buffer_init (&buffer
);
1583 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
1585 for (i
= 0; osdata_table
[i
].type
; ++i
)
1589 "<column name=\"Type\">%s</column>"
1590 "<column name=\"Description\">%s</column>"
1591 "<column name=\"Title\">%s</column>"
1593 osdata_table
[i
].type
,
1594 osdata_table
[i
].description
,
1595 osdata_table
[i
].title
);
1597 buffer_grow_str0 (&buffer
, "</osdata>\n");
1598 buf
= buffer_finish (&buffer
);
1599 len_avail
= strlen (buf
);
1602 if (offset
>= len_avail
)
1604 /* Done. Get rid of the buffer. */
1605 buffer_free (&buffer
);
1611 if (len
> len_avail
- offset
)
1612 len
= len_avail
- offset
;
1613 memcpy (readbuf
, buf
+ offset
, len
);
1621 for (i
= 0; osdata_table
[i
].type
; ++i
)
1623 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
1625 gdb_assert (readbuf
);
1627 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);