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"
45 #include "gdb_dirent.h"
47 #include "filestuff.h"
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 p
= strchr (content
, '(');
105 /* If the first field after program name has index 0, then core number is
106 the field with index 36. There's no constant for that anywhere. */
108 p
= strtok_r (p
, " ", &ts
);
109 for (i
= 0; p
!= NULL
&& i
!= 36; ++i
)
110 p
= strtok_r (NULL
, " ", &ts
);
112 if (p
== NULL
|| sscanf (p
, "%d", &core
) == 0)
121 /* Finds the command-line of process PID and copies it into COMMAND.
122 At most MAXLEN characters are copied. If the command-line cannot
123 be found, PID is copied into command in text-form. */
126 command_from_pid (char *command
, int maxlen
, PID_T pid
)
128 char *stat_path
= xstrprintf ("/proc/%lld/stat", pid
);
129 FILE *fp
= gdb_fopen_cloexec (stat_path
, "r");
135 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
136 include/linux/sched.h in the Linux kernel sources) plus two
137 (for the brackets). */
140 int items_read
= fscanf (fp
, "%lld %32s", &stat_pid
, cmd
);
142 if (items_read
== 2 && pid
== stat_pid
)
144 cmd
[strlen (cmd
) - 1] = '\0'; /* Remove trailing parenthesis. */
145 strncpy (command
, cmd
+ 1, maxlen
); /* Ignore leading parenthesis. */
152 /* Return the PID if a /proc entry for the process cannot be found. */
153 snprintf (command
, maxlen
, "%lld", pid
);
156 command
[maxlen
- 1] = '\0'; /* Ensure string is null-terminated. */
161 /* Returns the command-line of the process with the given PID. The
162 returned string needs to be freed using xfree after use. */
165 commandline_from_pid (PID_T pid
)
167 char *pathname
= xstrprintf ("/proc/%lld/cmdline", pid
);
168 char *commandline
= NULL
;
169 FILE *f
= gdb_fopen_cloexec (pathname
, "r");
178 size_t read_bytes
= fread (buf
, 1, sizeof (buf
), f
);
182 commandline
= (char *) xrealloc (commandline
, len
+ read_bytes
+ 1);
183 memcpy (commandline
+ len
, buf
, read_bytes
);
194 /* Replace null characters with spaces. */
195 for (i
= 0; i
< len
; ++i
)
196 if (commandline
[i
] == '\0')
197 commandline
[i
] = ' ';
199 commandline
[len
] = '\0';
203 /* Return the command in square brackets if the command-line
205 commandline
= (char *) xmalloc (32);
206 commandline
[0] = '[';
207 command_from_pid (commandline
+ 1, 31, pid
);
209 len
= strlen (commandline
);
211 strcat (commandline
, "]");
220 /* Finds the user name for the user UID and copies it into USER. At
221 most MAXLEN characters are copied. */
224 user_from_uid (char *user
, int maxlen
, uid_t uid
)
226 struct passwd
*pwentry
= getpwuid (uid
);
230 strncpy (user
, pwentry
->pw_name
, maxlen
);
231 /* Ensure that the user name is null-terminated. */
232 user
[maxlen
- 1] = '\0';
238 /* Finds the owner of process PID and returns the user id in OWNER.
239 Returns 0 if the owner was found, -1 otherwise. */
242 get_process_owner (uid_t
*owner
, PID_T pid
)
245 char procentry
[sizeof ("/proc/") + MAX_PID_T_STRLEN
];
247 sprintf (procentry
, "/proc/%lld", pid
);
249 if (stat (procentry
, &statbuf
) == 0 && S_ISDIR (statbuf
.st_mode
))
251 *owner
= statbuf
.st_uid
;
258 /* Find the CPU cores used by process PID and return them in CORES.
259 CORES points to an array of at least sysconf(_SC_NPROCESSOR_ONLN)
263 get_cores_used_by_process (PID_T pid
, int *cores
)
265 char taskdir
[sizeof ("/proc/") + MAX_PID_T_STRLEN
+ sizeof ("/task") - 1];
270 sprintf (taskdir
, "/proc/%lld/task", pid
);
271 dir
= opendir (taskdir
);
274 while ((dp
= readdir (dir
)) != NULL
)
279 if (!isdigit (dp
->d_name
[0])
280 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
283 sscanf (dp
->d_name
, "%lld", &tid
);
284 core
= linux_common_core_of_thread (ptid_build ((pid_t
) pid
,
301 linux_xfer_osdata_processes (gdb_byte
*readbuf
,
302 ULONGEST offset
, LONGEST len
)
304 /* We make the process list snapshot when the object starts to be read. */
305 static const char *buf
;
306 static LONGEST len_avail
= -1;
307 static struct buffer buffer
;
313 if (len_avail
!= -1 && len_avail
!= 0)
314 buffer_free (&buffer
);
317 buffer_init (&buffer
);
318 buffer_grow_str (&buffer
, "<osdata type=\"processes\">\n");
320 dirp
= opendir ("/proc");
323 const int num_cores
= sysconf (_SC_NPROCESSORS_ONLN
);
326 while ((dp
= readdir (dirp
)) != NULL
)
330 char user
[UT_NAMESIZE
];
337 if (!isdigit (dp
->d_name
[0])
338 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
341 sscanf (dp
->d_name
, "%lld", &pid
);
342 command_line
= commandline_from_pid (pid
);
344 if (get_process_owner (&owner
, pid
) == 0)
345 user_from_uid (user
, sizeof (user
), owner
);
349 /* Find CPU cores used by the process. */
350 cores
= (int *) xcalloc (num_cores
, sizeof (int));
351 task_count
= get_cores_used_by_process (pid
, cores
);
352 cores_str
= (char *) xcalloc (task_count
, sizeof ("4294967295") + 1);
354 for (i
= 0; i
< num_cores
&& task_count
> 0; ++i
)
357 char core_str
[sizeof ("4294967295")];
359 sprintf (core_str
, "%d", i
);
360 strcat (cores_str
, core_str
);
362 task_count
-= cores
[i
];
364 strcat (cores_str
, ",");
372 "<column name=\"pid\">%lld</column>"
373 "<column name=\"user\">%s</column>"
374 "<column name=\"command\">%s</column>"
375 "<column name=\"cores\">%s</column>"
379 command_line
? command_line
: "",
382 xfree (command_line
);
389 buffer_grow_str0 (&buffer
, "</osdata>\n");
390 buf
= buffer_finish (&buffer
);
391 len_avail
= strlen (buf
);
394 if (offset
>= len_avail
)
396 /* Done. Get rid of the buffer. */
397 buffer_free (&buffer
);
403 if (len
> len_avail
- offset
)
404 len
= len_avail
- offset
;
405 memcpy (readbuf
, buf
+ offset
, len
);
410 /* Auxiliary function used by qsort to sort processes by process
411 group. Compares two processes with ids PROCESS1 and PROCESS2.
412 PROCESS1 comes before PROCESS2 if it has a lower process group id.
413 If they belong to the same process group, PROCESS1 comes before
414 PROCESS2 if it has a lower process id or is the process group
418 compare_processes (const void *process1
, const void *process2
)
420 PID_T pid1
= *((PID_T
*) process1
);
421 PID_T pid2
= *((PID_T
*) process2
);
422 PID_T pgid1
= *((PID_T
*) process1
+ 1);
423 PID_T pgid2
= *((PID_T
*) process2
+ 1);
428 else if (pgid1
> pgid2
)
432 /* Process group leaders always come first, else sort by PID. */
435 else if (pid2
== pgid2
)
437 else if (pid1
< pid2
)
439 else if (pid1
> pid2
)
446 /* Collect all process groups from /proc. */
449 linux_xfer_osdata_processgroups (gdb_byte
*readbuf
,
450 ULONGEST offset
, LONGEST len
)
452 /* We make the process list snapshot when the object starts to be read. */
453 static const char *buf
;
454 static LONGEST len_avail
= -1;
455 static struct buffer buffer
;
461 if (len_avail
!= -1 && len_avail
!= 0)
462 buffer_free (&buffer
);
465 buffer_init (&buffer
);
466 buffer_grow_str (&buffer
, "<osdata type=\"process groups\">\n");
468 dirp
= opendir ("/proc");
472 const size_t list_block_size
= 512;
473 PID_T
*process_list
= (PID_T
*) xmalloc (list_block_size
* 2 * sizeof (PID_T
));
474 size_t process_count
= 0;
477 /* Build list consisting of PIDs followed by their
479 while ((dp
= readdir (dirp
)) != NULL
)
483 if (!isdigit (dp
->d_name
[0])
484 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
487 sscanf (dp
->d_name
, "%lld", &pid
);
488 pgid
= getpgid (pid
);
492 process_list
[2 * process_count
] = pid
;
493 process_list
[2 * process_count
+ 1] = pgid
;
496 /* Increase the size of the list if necessary. */
497 if (process_count
% list_block_size
== 0)
498 process_list
= (PID_T
*) xrealloc (
500 (process_count
+ list_block_size
)
501 * 2 * sizeof (PID_T
));
507 /* Sort the process list. */
508 qsort (process_list
, process_count
, 2 * sizeof (PID_T
),
511 for (i
= 0; i
< process_count
; ++i
)
513 PID_T pid
= process_list
[2 * i
];
514 PID_T pgid
= process_list
[2 * i
+ 1];
515 char leader_command
[32];
518 command_from_pid (leader_command
, sizeof (leader_command
), pgid
);
519 command_line
= commandline_from_pid (pid
);
524 "<column name=\"pgid\">%lld</column>"
525 "<column name=\"leader command\">%s</column>"
526 "<column name=\"pid\">%lld</column>"
527 "<column name=\"command line\">%s</column>"
532 command_line
? command_line
: "");
534 xfree (command_line
);
537 xfree (process_list
);
540 buffer_grow_str0 (&buffer
, "</osdata>\n");
541 buf
= buffer_finish (&buffer
);
542 len_avail
= strlen (buf
);
545 if (offset
>= len_avail
)
547 /* Done. Get rid of the buffer. */
548 buffer_free (&buffer
);
554 if (len
> len_avail
- offset
)
555 len
= len_avail
- offset
;
556 memcpy (readbuf
, buf
+ offset
, len
);
561 /* Collect all the threads in /proc by iterating through processes and
562 then tasks within each process. */
565 linux_xfer_osdata_threads (gdb_byte
*readbuf
,
566 ULONGEST offset
, LONGEST len
)
568 /* We make the process list snapshot when the object starts to be read. */
569 static const char *buf
;
570 static LONGEST len_avail
= -1;
571 static struct buffer buffer
;
577 if (len_avail
!= -1 && len_avail
!= 0)
578 buffer_free (&buffer
);
581 buffer_init (&buffer
);
582 buffer_grow_str (&buffer
, "<osdata type=\"threads\">\n");
584 dirp
= opendir ("/proc");
589 while ((dp
= readdir (dirp
)) != NULL
)
592 char procentry
[sizeof ("/proc/4294967295")];
594 if (!isdigit (dp
->d_name
[0])
595 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
598 sprintf (procentry
, "/proc/%s", dp
->d_name
);
599 if (stat (procentry
, &statbuf
) == 0
600 && S_ISDIR (statbuf
.st_mode
))
607 pathname
= xstrprintf ("/proc/%s/task", dp
->d_name
);
609 pid
= atoi (dp
->d_name
);
610 command_from_pid (command
, sizeof (command
), pid
);
612 dirp2
= opendir (pathname
);
618 while ((dp2
= readdir (dirp2
)) != NULL
)
623 if (!isdigit (dp2
->d_name
[0])
624 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
627 tid
= atoi (dp2
->d_name
);
628 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
633 "<column name=\"pid\">%lld</column>"
634 "<column name=\"command\">%s</column>"
635 "<column name=\"tid\">%lld</column>"
636 "<column name=\"core\">%d</column>"
654 buffer_grow_str0 (&buffer
, "</osdata>\n");
655 buf
= buffer_finish (&buffer
);
656 len_avail
= strlen (buf
);
659 if (offset
>= len_avail
)
661 /* Done. Get rid of the buffer. */
662 buffer_free (&buffer
);
668 if (len
> len_avail
- offset
)
669 len
= len_avail
- offset
;
670 memcpy (readbuf
, buf
+ offset
, len
);
675 /* Collect all the open file descriptors found in /proc and put the details
676 found about them into READBUF. */
679 linux_xfer_osdata_fds (gdb_byte
*readbuf
,
680 ULONGEST offset
, LONGEST len
)
682 /* We make the process list snapshot when the object starts to be read. */
683 static const char *buf
;
684 static LONGEST len_avail
= -1;
685 static struct buffer buffer
;
691 if (len_avail
!= -1 && len_avail
!= 0)
692 buffer_free (&buffer
);
695 buffer_init (&buffer
);
696 buffer_grow_str (&buffer
, "<osdata type=\"files\">\n");
698 dirp
= opendir ("/proc");
703 while ((dp
= readdir (dirp
)) != NULL
)
706 char procentry
[sizeof ("/proc/4294967295")];
708 if (!isdigit (dp
->d_name
[0])
709 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
712 sprintf (procentry
, "/proc/%s", dp
->d_name
);
713 if (stat (procentry
, &statbuf
) == 0
714 && S_ISDIR (statbuf
.st_mode
))
721 pid
= atoi (dp
->d_name
);
722 command_from_pid (command
, sizeof (command
), pid
);
724 pathname
= xstrprintf ("/proc/%s/fd", dp
->d_name
);
725 dirp2
= opendir (pathname
);
731 while ((dp2
= readdir (dirp2
)) != NULL
)
737 if (!isdigit (dp2
->d_name
[0]))
740 fdname
= xstrprintf ("%s/%s", pathname
, dp2
->d_name
);
741 rslt
= readlink (fdname
, buf
, sizeof (buf
) - 1);
748 "<column name=\"pid\">%s</column>"
749 "<column name=\"command\">%s</column>"
750 "<column name=\"file descriptor\">%s</column>"
751 "<column name=\"name\">%s</column>"
756 (rslt
>= 0 ? buf
: dp2
->d_name
));
769 buffer_grow_str0 (&buffer
, "</osdata>\n");
770 buf
= buffer_finish (&buffer
);
771 len_avail
= strlen (buf
);
774 if (offset
>= len_avail
)
776 /* Done. Get rid of the buffer. */
777 buffer_free (&buffer
);
783 if (len
> len_avail
- offset
)
784 len
= len_avail
- offset
;
785 memcpy (readbuf
, buf
+ offset
, len
);
790 /* Returns the socket state STATE in textual form. */
793 format_socket_state (unsigned char state
)
795 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
812 case TCP_ESTABLISHED
:
813 return "ESTABLISHED";
842 struct sockaddr_in sin
;
843 struct sockaddr_in6 sin6
;
846 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
847 information for all open internet sockets of type FAMILY on the
848 system into BUFFER. If TCP is set, only TCP sockets are processed,
849 otherwise only UDP sockets are processed. */
852 print_sockets (unsigned short family
, int tcp
, struct buffer
*buffer
)
854 const char *proc_file
;
857 if (family
== AF_INET
)
858 proc_file
= tcp
? "/proc/net/tcp" : "/proc/net/udp";
859 else if (family
== AF_INET6
)
860 proc_file
= tcp
? "/proc/net/tcp6" : "/proc/net/udp6";
864 fp
= gdb_fopen_cloexec (proc_file
, "r");
871 if (fgets (buf
, sizeof (buf
), fp
))
874 unsigned long tlen
, inode
;
876 unsigned int local_port
, remote_port
, state
;
877 unsigned int txq
, rxq
, trun
, retn
;
878 char local_address
[NI_MAXHOST
], remote_address
[NI_MAXHOST
];
882 result
= sscanf (buf
,
883 "%d: %33[0-9A-F]:%X %33[0-9A-F]:%X %X %X:%X %X:%lX %X %d %d %lu %512s\n",
885 local_address
, &local_port
,
886 remote_address
, &remote_port
,
898 union socket_addr locaddr
, remaddr
;
900 char user
[UT_NAMESIZE
];
901 char local_service
[NI_MAXSERV
], remote_service
[NI_MAXSERV
];
903 if (family
== AF_INET
)
905 sscanf (local_address
, "%X",
906 &locaddr
.sin
.sin_addr
.s_addr
);
907 sscanf (remote_address
, "%X",
908 &remaddr
.sin
.sin_addr
.s_addr
);
910 locaddr
.sin
.sin_port
= htons (local_port
);
911 remaddr
.sin
.sin_port
= htons (remote_port
);
913 addr_size
= sizeof (struct sockaddr_in
);
917 sscanf (local_address
, "%8X%8X%8X%8X",
918 locaddr
.sin6
.sin6_addr
.s6_addr32
,
919 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
920 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
921 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
922 sscanf (remote_address
, "%8X%8X%8X%8X",
923 remaddr
.sin6
.sin6_addr
.s6_addr32
,
924 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
925 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
926 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
928 locaddr
.sin6
.sin6_port
= htons (local_port
);
929 remaddr
.sin6
.sin6_port
= htons (remote_port
);
931 locaddr
.sin6
.sin6_flowinfo
= 0;
932 remaddr
.sin6
.sin6_flowinfo
= 0;
933 locaddr
.sin6
.sin6_scope_id
= 0;
934 remaddr
.sin6
.sin6_scope_id
= 0;
936 addr_size
= sizeof (struct sockaddr_in6
);
939 locaddr
.sa
.sa_family
= remaddr
.sa
.sa_family
= family
;
941 result
= getnameinfo (&locaddr
.sa
, addr_size
,
942 local_address
, sizeof (local_address
),
943 local_service
, sizeof (local_service
),
944 NI_NUMERICHOST
| NI_NUMERICSERV
945 | (tcp
? 0 : NI_DGRAM
));
949 result
= getnameinfo (&remaddr
.sa
, addr_size
,
951 sizeof (remote_address
),
953 sizeof (remote_service
),
954 NI_NUMERICHOST
| NI_NUMERICSERV
955 | (tcp
? 0 : NI_DGRAM
));
959 user_from_uid (user
, sizeof (user
), uid
);
964 "<column name=\"local address\">%s</column>"
965 "<column name=\"local port\">%s</column>"
966 "<column name=\"remote address\">%s</column>"
967 "<column name=\"remote port\">%s</column>"
968 "<column name=\"state\">%s</column>"
969 "<column name=\"user\">%s</column>"
970 "<column name=\"family\">%s</column>"
971 "<column name=\"protocol\">%s</column>"
977 format_socket_state (state
),
979 (family
== AF_INET
) ? "INET" : "INET6",
980 tcp
? "STREAM" : "DGRAM");
990 /* Collect data about internet sockets and write it into READBUF. */
993 linux_xfer_osdata_isockets (gdb_byte
*readbuf
,
994 ULONGEST offset
, LONGEST len
)
996 static const char *buf
;
997 static LONGEST len_avail
= -1;
998 static struct buffer buffer
;
1002 if (len_avail
!= -1 && len_avail
!= 0)
1003 buffer_free (&buffer
);
1006 buffer_init (&buffer
);
1007 buffer_grow_str (&buffer
, "<osdata type=\"I sockets\">\n");
1009 print_sockets (AF_INET
, 1, &buffer
);
1010 print_sockets (AF_INET
, 0, &buffer
);
1011 print_sockets (AF_INET6
, 1, &buffer
);
1012 print_sockets (AF_INET6
, 0, &buffer
);
1014 buffer_grow_str0 (&buffer
, "</osdata>\n");
1015 buf
= buffer_finish (&buffer
);
1016 len_avail
= strlen (buf
);
1019 if (offset
>= len_avail
)
1021 /* Done. Get rid of the buffer. */
1022 buffer_free (&buffer
);
1028 if (len
> len_avail
- offset
)
1029 len
= len_avail
- offset
;
1030 memcpy (readbuf
, buf
+ offset
, len
);
1035 /* Converts the time SECONDS into textual form and copies it into a
1036 buffer TIME, with at most MAXLEN characters copied. */
1039 time_from_time_t (char *time
, int maxlen
, TIME_T seconds
)
1045 time_t t
= (time_t) seconds
;
1047 strncpy (time
, ctime (&t
), maxlen
);
1048 time
[maxlen
- 1] = '\0';
1052 /* Finds the group name for the group GID and copies it into GROUP.
1053 At most MAXLEN characters are copied. */
1056 group_from_gid (char *group
, int maxlen
, gid_t gid
)
1058 struct group
*grentry
= getgrgid (gid
);
1062 strncpy (group
, grentry
->gr_name
, maxlen
);
1063 /* Ensure that the group name is null-terminated. */
1064 group
[maxlen
- 1] = '\0';
1070 /* Collect data about shared memory recorded in /proc and write it
1074 linux_xfer_osdata_shm (gdb_byte
*readbuf
,
1075 ULONGEST offset
, LONGEST len
)
1077 static const char *buf
;
1078 static LONGEST len_avail
= -1;
1079 static struct buffer buffer
;
1085 if (len_avail
!= -1 && len_avail
!= 0)
1086 buffer_free (&buffer
);
1089 buffer_init (&buffer
);
1090 buffer_grow_str (&buffer
, "<osdata type=\"shared memory\">\n");
1092 fp
= gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1099 if (fgets (buf
, sizeof (buf
), fp
))
1105 int shmid
, size
, nattch
;
1106 TIME_T atime
, dtime
, ctime
;
1110 items_read
= sscanf (buf
,
1111 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1112 &key
, &shmid
, &perms
, &size
,
1115 &uid
, &gid
, &cuid
, &cgid
,
1116 &atime
, &dtime
, &ctime
);
1118 if (items_read
== 14)
1120 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1121 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1122 char ccmd
[32], lcmd
[32];
1123 char atime_str
[32], dtime_str
[32], ctime_str
[32];
1125 user_from_uid (user
, sizeof (user
), uid
);
1126 group_from_gid (group
, sizeof (group
), gid
);
1127 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1128 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1130 command_from_pid (ccmd
, sizeof (ccmd
), cpid
);
1131 command_from_pid (lcmd
, sizeof (lcmd
), lpid
);
1133 time_from_time_t (atime_str
, sizeof (atime_str
), atime
);
1134 time_from_time_t (dtime_str
, sizeof (dtime_str
), dtime
);
1135 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1140 "<column name=\"key\">%d</column>"
1141 "<column name=\"shmid\">%d</column>"
1142 "<column name=\"permissions\">%o</column>"
1143 "<column name=\"size\">%d</column>"
1144 "<column name=\"creator command\">%s</column>"
1145 "<column name=\"last op. command\">%s</column>"
1146 "<column name=\"num attached\">%d</column>"
1147 "<column name=\"user\">%s</column>"
1148 "<column name=\"group\">%s</column>"
1149 "<column name=\"creator user\">%s</column>"
1150 "<column name=\"creator group\">%s</column>"
1151 "<column name=\"last shmat() time\">%s</column>"
1152 "<column name=\"last shmdt() time\">%s</column>"
1153 "<column name=\"last shmctl() time\">%s</column>"
1177 buffer_grow_str0 (&buffer
, "</osdata>\n");
1178 buf
= buffer_finish (&buffer
);
1179 len_avail
= strlen (buf
);
1182 if (offset
>= len_avail
)
1184 /* Done. Get rid of the buffer. */
1185 buffer_free (&buffer
);
1191 if (len
> len_avail
- offset
)
1192 len
= len_avail
- offset
;
1193 memcpy (readbuf
, buf
+ offset
, len
);
1198 /* Collect data about semaphores recorded in /proc and write it
1202 linux_xfer_osdata_sem (gdb_byte
*readbuf
,
1203 ULONGEST offset
, LONGEST len
)
1205 static const char *buf
;
1206 static LONGEST len_avail
= -1;
1207 static struct buffer buffer
;
1213 if (len_avail
!= -1 && len_avail
!= 0)
1214 buffer_free (&buffer
);
1217 buffer_init (&buffer
);
1218 buffer_grow_str (&buffer
, "<osdata type=\"semaphores\">\n");
1220 fp
= gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1227 if (fgets (buf
, sizeof (buf
), fp
))
1232 unsigned int perms
, nsems
;
1234 TIME_T otime
, ctime
;
1237 items_read
= sscanf (buf
,
1238 "%d %d %o %u %d %d %d %d %lld %lld",
1239 &key
, &semid
, &perms
, &nsems
,
1240 &uid
, &gid
, &cuid
, &cgid
,
1243 if (items_read
== 10)
1245 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1246 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1247 char otime_str
[32], ctime_str
[32];
1249 user_from_uid (user
, sizeof (user
), uid
);
1250 group_from_gid (group
, sizeof (group
), gid
);
1251 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1252 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1254 time_from_time_t (otime_str
, sizeof (otime_str
), otime
);
1255 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1260 "<column name=\"key\">%d</column>"
1261 "<column name=\"semid\">%d</column>"
1262 "<column name=\"permissions\">%o</column>"
1263 "<column name=\"num semaphores\">%u</column>"
1264 "<column name=\"user\">%s</column>"
1265 "<column name=\"group\">%s</column>"
1266 "<column name=\"creator user\">%s</column>"
1267 "<column name=\"creator group\">%s</column>"
1268 "<column name=\"last semop() time\">%s</column>"
1269 "<column name=\"last semctl() time\">%s</column>"
1289 buffer_grow_str0 (&buffer
, "</osdata>\n");
1290 buf
= buffer_finish (&buffer
);
1291 len_avail
= strlen (buf
);
1294 if (offset
>= len_avail
)
1296 /* Done. Get rid of the buffer. */
1297 buffer_free (&buffer
);
1303 if (len
> len_avail
- offset
)
1304 len
= len_avail
- offset
;
1305 memcpy (readbuf
, buf
+ offset
, len
);
1310 /* Collect data about message queues recorded in /proc and write it
1314 linux_xfer_osdata_msg (gdb_byte
*readbuf
,
1315 ULONGEST offset
, LONGEST len
)
1317 static const char *buf
;
1318 static LONGEST len_avail
= -1;
1319 static struct buffer buffer
;
1325 if (len_avail
!= -1 && len_avail
!= 0)
1326 buffer_free (&buffer
);
1329 buffer_init (&buffer
);
1330 buffer_grow_str (&buffer
, "<osdata type=\"message queues\">\n");
1332 fp
= gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1339 if (fgets (buf
, sizeof (buf
), fp
))
1345 unsigned int perms
, cbytes
, qnum
;
1347 TIME_T stime
, rtime
, ctime
;
1350 items_read
= sscanf (buf
,
1351 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1352 &key
, &msqid
, &perms
, &cbytes
, &qnum
,
1353 &lspid
, &lrpid
, &uid
, &gid
, &cuid
, &cgid
,
1354 &stime
, &rtime
, &ctime
);
1356 if (items_read
== 14)
1358 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1359 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1360 char lscmd
[32], lrcmd
[32];
1361 char stime_str
[32], rtime_str
[32], ctime_str
[32];
1363 user_from_uid (user
, sizeof (user
), uid
);
1364 group_from_gid (group
, sizeof (group
), gid
);
1365 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1366 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1368 command_from_pid (lscmd
, sizeof (lscmd
), lspid
);
1369 command_from_pid (lrcmd
, sizeof (lrcmd
), lrpid
);
1371 time_from_time_t (stime_str
, sizeof (stime_str
), stime
);
1372 time_from_time_t (rtime_str
, sizeof (rtime_str
), rtime
);
1373 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1378 "<column name=\"key\">%d</column>"
1379 "<column name=\"msqid\">%d</column>"
1380 "<column name=\"permissions\">%o</column>"
1381 "<column name=\"num used bytes\">%u</column>"
1382 "<column name=\"num messages\">%u</column>"
1383 "<column name=\"last msgsnd() command\">%s</column>"
1384 "<column name=\"last msgrcv() command\">%s</column>"
1385 "<column name=\"user\">%s</column>"
1386 "<column name=\"group\">%s</column>"
1387 "<column name=\"creator user\">%s</column>"
1388 "<column name=\"creator group\">%s</column>"
1389 "<column name=\"last msgsnd() time\">%s</column>"
1390 "<column name=\"last msgrcv() time\">%s</column>"
1391 "<column name=\"last msgctl() time\">%s</column>"
1415 buffer_grow_str0 (&buffer
, "</osdata>\n");
1416 buf
= buffer_finish (&buffer
);
1417 len_avail
= strlen (buf
);
1420 if (offset
>= len_avail
)
1422 /* Done. Get rid of the buffer. */
1423 buffer_free (&buffer
);
1429 if (len
> len_avail
- offset
)
1430 len
= len_avail
- offset
;
1431 memcpy (readbuf
, buf
+ offset
, len
);
1436 /* Collect data about loaded kernel modules and write it into
1440 linux_xfer_osdata_modules (gdb_byte
*readbuf
,
1441 ULONGEST offset
, LONGEST len
)
1443 static const char *buf
;
1444 static LONGEST len_avail
= -1;
1445 static struct buffer buffer
;
1451 if (len_avail
!= -1 && len_avail
!= 0)
1452 buffer_free (&buffer
);
1455 buffer_init (&buffer
);
1456 buffer_grow_str (&buffer
, "<osdata type=\"modules\">\n");
1458 fp
= gdb_fopen_cloexec ("/proc/modules", "r");
1465 if (fgets (buf
, sizeof (buf
), fp
))
1467 char name
[64], dependencies
[256], status
[16];
1469 unsigned long long address
;
1473 items_read
= sscanf (buf
,
1474 "%64s %d %d %256s %16s 0x%llx",
1476 dependencies
, status
, &address
);
1478 if (items_read
== 6)
1482 "<column name=\"name\">%s</column>"
1483 "<column name=\"size\">%u</column>"
1484 "<column name=\"num uses\">%d</column>"
1485 "<column name=\"dependencies\">%s</column>"
1486 "<column name=\"status\">%s</column>"
1487 "<column name=\"address\">%llx</column>"
1502 buffer_grow_str0 (&buffer
, "</osdata>\n");
1503 buf
= buffer_finish (&buffer
);
1504 len_avail
= strlen (buf
);
1507 if (offset
>= len_avail
)
1509 /* Done. Get rid of the buffer. */
1510 buffer_free (&buffer
);
1516 if (len
> len_avail
- offset
)
1517 len
= len_avail
- offset
;
1518 memcpy (readbuf
, buf
+ offset
, len
);
1523 struct osdata_type
{
1527 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, LONGEST len
);
1528 } osdata_table
[] = {
1529 { "processes", "Processes", "Listing of all processes",
1530 linux_xfer_osdata_processes
},
1531 { "procgroups", "Process groups", "Listing of all process groups",
1532 linux_xfer_osdata_processgroups
},
1533 { "threads", "Threads", "Listing of all threads",
1534 linux_xfer_osdata_threads
},
1535 { "files", "File descriptors", "Listing of all file descriptors",
1536 linux_xfer_osdata_fds
},
1537 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1538 linux_xfer_osdata_isockets
},
1539 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1540 linux_xfer_osdata_shm
},
1541 { "semaphores", "Semaphores", "Listing of all semaphores",
1542 linux_xfer_osdata_sem
},
1543 { "msg", "Message queues", "Listing of all message queues",
1544 linux_xfer_osdata_msg
},
1545 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1546 linux_xfer_osdata_modules
},
1547 { NULL
, NULL
, NULL
}
1551 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
1552 ULONGEST offset
, LONGEST len
)
1554 if (!annex
|| *annex
== '\0')
1556 static const char *buf
;
1557 static LONGEST len_avail
= -1;
1558 static struct buffer buffer
;
1564 if (len_avail
!= -1 && len_avail
!= 0)
1565 buffer_free (&buffer
);
1568 buffer_init (&buffer
);
1569 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
1571 for (i
= 0; osdata_table
[i
].type
; ++i
)
1575 "<column name=\"Type\">%s</column>"
1576 "<column name=\"Description\">%s</column>"
1577 "<column name=\"Title\">%s</column>"
1579 osdata_table
[i
].type
,
1580 osdata_table
[i
].description
,
1581 osdata_table
[i
].title
);
1583 buffer_grow_str0 (&buffer
, "</osdata>\n");
1584 buf
= buffer_finish (&buffer
);
1585 len_avail
= strlen (buf
);
1588 if (offset
>= len_avail
)
1590 /* Done. Get rid of the buffer. */
1591 buffer_free (&buffer
);
1597 if (len
> len_avail
- offset
)
1598 len
= len_avail
- offset
;
1599 memcpy (readbuf
, buf
+ offset
, len
);
1607 for (i
= 0; osdata_table
[i
].type
; ++i
)
1609 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
1611 gdb_assert (readbuf
);
1613 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);