1 /* Linux-specific functions to retrieve OS data.
3 Copyright (C) 2009-2012 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"
48 /* Define PID_T to be a fixed size that is at least as large as pid_t,
49 so that reading pid values embedded in /proc works
52 typedef long long PID_T
;
54 /* Define TIME_T to be at least as large as time_t, so that reading
55 time values embedded in /proc works consistently. */
57 typedef long long TIME_T
;
59 #define MAX_PID_T_STRLEN (sizeof ("-9223372036854775808") - 1)
61 /* Returns the CPU core that thread PTID is currently running on. */
63 /* Compute and return the processor core of a given thread. */
66 linux_common_core_of_thread (ptid_t ptid
)
68 char filename
[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN
];
77 sprintf (filename
, "/proc/%lld/task/%lld/stat",
78 (PID_T
) ptid_get_pid (ptid
), (PID_T
) ptid_get_lwp (ptid
));
79 f
= fopen (filename
, "r");
86 content
= xrealloc (content
, content_read
+ 1024);
87 n
= fread (content
+ content_read
, 1, 1024, f
);
91 content
[content_read
] = '\0';
96 p
= strchr (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
= fopen (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 %32s", &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
= fopen (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 at least sysconf(_SC_NPROCESSOR_ONLN)
262 get_cores_used_by_process (PID_T pid
, int *cores
)
264 char taskdir
[sizeof ("/proc/") + MAX_PID_T_STRLEN
+ sizeof ("/task") - 1];
269 sprintf (taskdir
, "/proc/%lld/task", pid
);
270 dir
= opendir (taskdir
);
273 while ((dp
= readdir (dir
)) != NULL
)
278 if (!isdigit (dp
->d_name
[0])
279 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
282 sscanf (dp
->d_name
, "%lld", &tid
);
283 core
= linux_common_core_of_thread (ptid_build ((pid_t
) pid
,
300 linux_xfer_osdata_processes (gdb_byte
*readbuf
,
301 ULONGEST offset
, LONGEST len
)
303 /* We make the process list snapshot when the object starts to be read. */
304 static const char *buf
;
305 static LONGEST len_avail
= -1;
306 static struct buffer buffer
;
312 if (len_avail
!= -1 && len_avail
!= 0)
313 buffer_free (&buffer
);
316 buffer_init (&buffer
);
317 buffer_grow_str (&buffer
, "<osdata type=\"processes\">\n");
319 dirp
= opendir ("/proc");
322 const int num_cores
= sysconf (_SC_NPROCESSORS_ONLN
);
325 while ((dp
= readdir (dirp
)) != NULL
)
329 char user
[UT_NAMESIZE
];
336 if (!isdigit (dp
->d_name
[0])
337 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
340 sscanf (dp
->d_name
, "%lld", &pid
);
341 command_line
= commandline_from_pid (pid
);
343 if (get_process_owner (&owner
, pid
) == 0)
344 user_from_uid (user
, sizeof (user
), owner
);
348 /* Find CPU cores used by the process. */
349 cores
= (int *) xcalloc (num_cores
, sizeof (int));
350 task_count
= get_cores_used_by_process (pid
, cores
);
351 cores_str
= (char *) xcalloc (task_count
, sizeof ("4294967295") + 1);
353 for (i
= 0; i
< num_cores
&& task_count
> 0; ++i
)
356 char core_str
[sizeof ("4294967295")];
358 sprintf (core_str
, "%d", i
);
359 strcat (cores_str
, core_str
);
361 task_count
-= cores
[i
];
363 strcat (cores_str
, ",");
371 "<column name=\"pid\">%lld</column>"
372 "<column name=\"user\">%s</column>"
373 "<column name=\"command\">%s</column>"
374 "<column name=\"cores\">%s</column>"
378 command_line
? command_line
: "",
381 xfree (command_line
);
388 buffer_grow_str0 (&buffer
, "</osdata>\n");
389 buf
= buffer_finish (&buffer
);
390 len_avail
= strlen (buf
);
393 if (offset
>= len_avail
)
395 /* Done. Get rid of the buffer. */
396 buffer_free (&buffer
);
402 if (len
> len_avail
- offset
)
403 len
= len_avail
- offset
;
404 memcpy (readbuf
, buf
+ offset
, len
);
409 /* Auxiliary function used by qsort to sort processes by process
410 group. Compares two processes with ids PROCESS1 and PROCESS2.
411 PROCESS1 comes before PROCESS2 if it has a lower process group id.
412 If they belong to the same process group, PROCESS1 comes before
413 PROCESS2 if it has a lower process id or is the process group
417 compare_processes (const void *process1
, const void *process2
)
419 PID_T pid1
= *((PID_T
*) process1
);
420 PID_T pid2
= *((PID_T
*) process2
);
421 PID_T pgid1
= *((PID_T
*) process1
+ 1);
422 PID_T pgid2
= *((PID_T
*) process2
+ 1);
427 else if (pgid1
> pgid2
)
431 /* Process group leaders always come first, else sort by PID. */
434 else if (pid2
== pgid2
)
436 else if (pid1
< pid2
)
438 else if (pid1
> pid2
)
445 /* Collect all process groups from /proc. */
448 linux_xfer_osdata_processgroups (gdb_byte
*readbuf
,
449 ULONGEST offset
, LONGEST len
)
451 /* We make the process list snapshot when the object starts to be read. */
452 static const char *buf
;
453 static LONGEST len_avail
= -1;
454 static struct buffer buffer
;
460 if (len_avail
!= -1 && len_avail
!= 0)
461 buffer_free (&buffer
);
464 buffer_init (&buffer
);
465 buffer_grow_str (&buffer
, "<osdata type=\"process groups\">\n");
467 dirp
= opendir ("/proc");
471 const size_t list_block_size
= 512;
472 PID_T
*process_list
= (PID_T
*) xmalloc (list_block_size
* 2 * sizeof (PID_T
));
473 size_t process_count
= 0;
476 /* Build list consisting of PIDs followed by their
478 while ((dp
= readdir (dirp
)) != NULL
)
482 if (!isdigit (dp
->d_name
[0])
483 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
486 sscanf (dp
->d_name
, "%lld", &pid
);
487 pgid
= getpgid (pid
);
491 process_list
[2 * process_count
] = pid
;
492 process_list
[2 * process_count
+ 1] = pgid
;
495 /* Increase the size of the list if necessary. */
496 if (process_count
% list_block_size
== 0)
497 process_list
= (PID_T
*) xrealloc (
499 (process_count
+ list_block_size
)
500 * 2 * sizeof (PID_T
));
506 /* Sort the process list. */
507 qsort (process_list
, process_count
, 2 * sizeof (PID_T
),
510 for (i
= 0; i
< process_count
; ++i
)
512 PID_T pid
= process_list
[2 * i
];
513 PID_T pgid
= process_list
[2 * i
+ 1];
514 char leader_command
[32];
517 command_from_pid (leader_command
, sizeof (leader_command
), pgid
);
518 command_line
= commandline_from_pid (pid
);
523 "<column name=\"pgid\">%lld</column>"
524 "<column name=\"leader command\">%s</column>"
525 "<column name=\"pid\">%lld</column>"
526 "<column name=\"command line\">%s</column>"
531 command_line
? command_line
: "");
533 xfree (command_line
);
536 xfree (process_list
);
539 buffer_grow_str0 (&buffer
, "</osdata>\n");
540 buf
= buffer_finish (&buffer
);
541 len_avail
= strlen (buf
);
544 if (offset
>= len_avail
)
546 /* Done. Get rid of the buffer. */
547 buffer_free (&buffer
);
553 if (len
> len_avail
- offset
)
554 len
= len_avail
- offset
;
555 memcpy (readbuf
, buf
+ offset
, len
);
560 /* Collect all the threads in /proc by iterating through processes and
561 then tasks within each process. */
564 linux_xfer_osdata_threads (gdb_byte
*readbuf
,
565 ULONGEST offset
, LONGEST len
)
567 /* We make the process list snapshot when the object starts to be read. */
568 static const char *buf
;
569 static LONGEST len_avail
= -1;
570 static struct buffer buffer
;
576 if (len_avail
!= -1 && len_avail
!= 0)
577 buffer_free (&buffer
);
580 buffer_init (&buffer
);
581 buffer_grow_str (&buffer
, "<osdata type=\"threads\">\n");
583 dirp
= opendir ("/proc");
588 while ((dp
= readdir (dirp
)) != NULL
)
591 char procentry
[sizeof ("/proc/4294967295")];
593 if (!isdigit (dp
->d_name
[0])
594 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
597 sprintf (procentry
, "/proc/%s", dp
->d_name
);
598 if (stat (procentry
, &statbuf
) == 0
599 && S_ISDIR (statbuf
.st_mode
))
606 pathname
= xstrprintf ("/proc/%s/task", dp
->d_name
);
608 pid
= atoi (dp
->d_name
);
609 command_from_pid (command
, sizeof (command
), pid
);
611 dirp2
= opendir (pathname
);
617 while ((dp2
= readdir (dirp2
)) != NULL
)
622 if (!isdigit (dp2
->d_name
[0])
623 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
626 tid
= atoi (dp2
->d_name
);
627 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
632 "<column name=\"pid\">%lld</column>"
633 "<column name=\"command\">%s</column>"
634 "<column name=\"tid\">%lld</column>"
635 "<column name=\"core\">%d</column>"
653 buffer_grow_str0 (&buffer
, "</osdata>\n");
654 buf
= buffer_finish (&buffer
);
655 len_avail
= strlen (buf
);
658 if (offset
>= len_avail
)
660 /* Done. Get rid of the buffer. */
661 buffer_free (&buffer
);
667 if (len
> len_avail
- offset
)
668 len
= len_avail
- offset
;
669 memcpy (readbuf
, buf
+ offset
, len
);
674 /* Collect all the open file descriptors found in /proc and put the details
675 found about them into READBUF. */
678 linux_xfer_osdata_fds (gdb_byte
*readbuf
,
679 ULONGEST offset
, LONGEST len
)
681 /* We make the process list snapshot when the object starts to be read. */
682 static const char *buf
;
683 static LONGEST len_avail
= -1;
684 static struct buffer buffer
;
690 if (len_avail
!= -1 && len_avail
!= 0)
691 buffer_free (&buffer
);
694 buffer_init (&buffer
);
695 buffer_grow_str (&buffer
, "<osdata type=\"files\">\n");
697 dirp
= opendir ("/proc");
702 while ((dp
= readdir (dirp
)) != NULL
)
705 char procentry
[sizeof ("/proc/4294967295")];
707 if (!isdigit (dp
->d_name
[0])
708 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
711 sprintf (procentry
, "/proc/%s", dp
->d_name
);
712 if (stat (procentry
, &statbuf
) == 0
713 && S_ISDIR (statbuf
.st_mode
))
720 pid
= atoi (dp
->d_name
);
721 command_from_pid (command
, sizeof (command
), pid
);
723 pathname
= xstrprintf ("/proc/%s/fd", dp
->d_name
);
724 dirp2
= opendir (pathname
);
730 while ((dp2
= readdir (dirp2
)) != NULL
)
736 if (!isdigit (dp2
->d_name
[0]))
739 fdname
= xstrprintf ("%s/%s", pathname
, dp2
->d_name
);
740 rslt
= readlink (fdname
, buf
, sizeof (buf
) - 1);
747 "<column name=\"pid\">%s</column>"
748 "<column name=\"command\">%s</column>"
749 "<column name=\"file descriptor\">%s</column>"
750 "<column name=\"name\">%s</column>"
755 (rslt
>= 0 ? buf
: dp2
->d_name
));
768 buffer_grow_str0 (&buffer
, "</osdata>\n");
769 buf
= buffer_finish (&buffer
);
770 len_avail
= strlen (buf
);
773 if (offset
>= len_avail
)
775 /* Done. Get rid of the buffer. */
776 buffer_free (&buffer
);
782 if (len
> len_avail
- offset
)
783 len
= len_avail
- offset
;
784 memcpy (readbuf
, buf
+ offset
, len
);
789 /* Returns the socket state STATE in textual form. */
792 format_socket_state (unsigned char state
)
794 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
811 case TCP_ESTABLISHED
:
812 return "ESTABLISHED";
841 struct sockaddr_in sin
;
842 struct sockaddr_in6 sin6
;
845 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
846 information for all open internet sockets of type FAMILY on the
847 system into BUFFER. If TCP is set, only TCP sockets are processed,
848 otherwise only UDP sockets are processed. */
851 print_sockets (unsigned short family
, int tcp
, struct buffer
*buffer
)
853 const char *proc_file
;
856 if (family
== AF_INET
)
857 proc_file
= tcp
? "/proc/net/tcp" : "/proc/net/udp";
858 else if (family
== AF_INET6
)
859 proc_file
= tcp
? "/proc/net/tcp6" : "/proc/net/udp6";
863 fp
= fopen (proc_file
, "r");
870 if (fgets (buf
, sizeof (buf
), fp
))
873 unsigned long tlen
, inode
;
875 unsigned int local_port
, remote_port
, state
;
876 unsigned int txq
, rxq
, trun
, retn
;
877 char local_address
[NI_MAXHOST
], remote_address
[NI_MAXHOST
];
881 result
= sscanf (buf
,
882 "%d: %33[0-9A-F]:%X %33[0-9A-F]:%X %X %X:%X %X:%lX %X %d %d %lu %512s\n",
884 local_address
, &local_port
,
885 remote_address
, &remote_port
,
897 union socket_addr locaddr
, remaddr
;
899 char user
[UT_NAMESIZE
];
900 char local_service
[NI_MAXSERV
], remote_service
[NI_MAXSERV
];
902 if (family
== AF_INET
)
904 sscanf (local_address
, "%X",
905 &locaddr
.sin
.sin_addr
.s_addr
);
906 sscanf (remote_address
, "%X",
907 &remaddr
.sin
.sin_addr
.s_addr
);
909 locaddr
.sin
.sin_port
= htons (local_port
);
910 remaddr
.sin
.sin_port
= htons (remote_port
);
912 addr_size
= sizeof (struct sockaddr_in
);
916 sscanf (local_address
, "%8X%8X%8X%8X",
917 locaddr
.sin6
.sin6_addr
.s6_addr32
,
918 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
919 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
920 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
921 sscanf (remote_address
, "%8X%8X%8X%8X",
922 remaddr
.sin6
.sin6_addr
.s6_addr32
,
923 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
924 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
925 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
927 locaddr
.sin6
.sin6_port
= htons (local_port
);
928 remaddr
.sin6
.sin6_port
= htons (remote_port
);
930 locaddr
.sin6
.sin6_flowinfo
= 0;
931 remaddr
.sin6
.sin6_flowinfo
= 0;
932 locaddr
.sin6
.sin6_scope_id
= 0;
933 remaddr
.sin6
.sin6_scope_id
= 0;
935 addr_size
= sizeof (struct sockaddr_in6
);
938 locaddr
.sa
.sa_family
= remaddr
.sa
.sa_family
= family
;
940 result
= getnameinfo (&locaddr
.sa
, addr_size
,
941 local_address
, sizeof (local_address
),
942 local_service
, sizeof (local_service
),
943 NI_NUMERICHOST
| NI_NUMERICSERV
944 | (tcp
? 0 : NI_DGRAM
));
948 result
= getnameinfo (&remaddr
.sa
, addr_size
,
950 sizeof (remote_address
),
952 sizeof (remote_service
),
953 NI_NUMERICHOST
| NI_NUMERICSERV
954 | (tcp
? 0 : NI_DGRAM
));
958 user_from_uid (user
, sizeof (user
), uid
);
963 "<column name=\"local address\">%s</column>"
964 "<column name=\"local port\">%s</column>"
965 "<column name=\"remote address\">%s</column>"
966 "<column name=\"remote port\">%s</column>"
967 "<column name=\"state\">%s</column>"
968 "<column name=\"user\">%s</column>"
969 "<column name=\"family\">%s</column>"
970 "<column name=\"protocol\">%s</column>"
976 format_socket_state (state
),
978 (family
== AF_INET
) ? "INET" : "INET6",
979 tcp
? "STREAM" : "DGRAM");
989 /* Collect data about internet sockets and write it into READBUF. */
992 linux_xfer_osdata_isockets (gdb_byte
*readbuf
,
993 ULONGEST offset
, LONGEST len
)
995 static const char *buf
;
996 static LONGEST len_avail
= -1;
997 static struct buffer buffer
;
1001 if (len_avail
!= -1 && len_avail
!= 0)
1002 buffer_free (&buffer
);
1005 buffer_init (&buffer
);
1006 buffer_grow_str (&buffer
, "<osdata type=\"I sockets\">\n");
1008 print_sockets (AF_INET
, 1, &buffer
);
1009 print_sockets (AF_INET
, 0, &buffer
);
1010 print_sockets (AF_INET6
, 1, &buffer
);
1011 print_sockets (AF_INET6
, 0, &buffer
);
1013 buffer_grow_str0 (&buffer
, "</osdata>\n");
1014 buf
= buffer_finish (&buffer
);
1015 len_avail
= strlen (buf
);
1018 if (offset
>= len_avail
)
1020 /* Done. Get rid of the buffer. */
1021 buffer_free (&buffer
);
1027 if (len
> len_avail
- offset
)
1028 len
= len_avail
- offset
;
1029 memcpy (readbuf
, buf
+ offset
, len
);
1034 /* Converts the time SECONDS into textual form and copies it into a
1035 buffer TIME, with at most MAXLEN characters copied. */
1038 time_from_time_t (char *time
, int maxlen
, TIME_T seconds
)
1044 time_t t
= (time_t) seconds
;
1046 strncpy (time
, ctime (&t
), maxlen
);
1047 time
[maxlen
- 1] = '\0';
1051 /* Finds the group name for the group GID and copies it into GROUP.
1052 At most MAXLEN characters are copied. */
1055 group_from_gid (char *group
, int maxlen
, gid_t gid
)
1057 struct group
*grentry
= getgrgid (gid
);
1061 strncpy (group
, grentry
->gr_name
, maxlen
);
1062 /* Ensure that the group name is null-terminated. */
1063 group
[maxlen
- 1] = '\0';
1069 /* Collect data about shared memory recorded in /proc and write it
1073 linux_xfer_osdata_shm (gdb_byte
*readbuf
,
1074 ULONGEST offset
, LONGEST len
)
1076 static const char *buf
;
1077 static LONGEST len_avail
= -1;
1078 static struct buffer buffer
;
1084 if (len_avail
!= -1 && len_avail
!= 0)
1085 buffer_free (&buffer
);
1088 buffer_init (&buffer
);
1089 buffer_grow_str (&buffer
, "<osdata type=\"shared memory\">\n");
1091 fp
= fopen ("/proc/sysvipc/shm", "r");
1098 if (fgets (buf
, sizeof (buf
), fp
))
1104 int shmid
, size
, nattch
;
1105 TIME_T atime
, dtime
, ctime
;
1109 items_read
= sscanf (buf
,
1110 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1111 &key
, &shmid
, &perms
, &size
,
1114 &uid
, &gid
, &cuid
, &cgid
,
1115 &atime
, &dtime
, &ctime
);
1117 if (items_read
== 14)
1119 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1120 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1121 char ccmd
[32], lcmd
[32];
1122 char atime_str
[32], dtime_str
[32], ctime_str
[32];
1124 user_from_uid (user
, sizeof (user
), uid
);
1125 group_from_gid (group
, sizeof (group
), gid
);
1126 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1127 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1129 command_from_pid (ccmd
, sizeof (ccmd
), cpid
);
1130 command_from_pid (lcmd
, sizeof (lcmd
), lpid
);
1132 time_from_time_t (atime_str
, sizeof (atime_str
), atime
);
1133 time_from_time_t (dtime_str
, sizeof (dtime_str
), dtime
);
1134 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1139 "<column name=\"key\">%d</column>"
1140 "<column name=\"shmid\">%d</column>"
1141 "<column name=\"permissions\">%o</column>"
1142 "<column name=\"size\">%d</column>"
1143 "<column name=\"creator command\">%s</column>"
1144 "<column name=\"last op. command\">%s</column>"
1145 "<column name=\"num attached\">%d</column>"
1146 "<column name=\"user\">%s</column>"
1147 "<column name=\"group\">%s</column>"
1148 "<column name=\"creator user\">%s</column>"
1149 "<column name=\"creator group\">%s</column>"
1150 "<column name=\"last shmat() time\">%s</column>"
1151 "<column name=\"last shmdt() time\">%s</column>"
1152 "<column name=\"last shmctl() time\">%s</column>"
1176 buffer_grow_str0 (&buffer
, "</osdata>\n");
1177 buf
= buffer_finish (&buffer
);
1178 len_avail
= strlen (buf
);
1181 if (offset
>= len_avail
)
1183 /* Done. Get rid of the buffer. */
1184 buffer_free (&buffer
);
1190 if (len
> len_avail
- offset
)
1191 len
= len_avail
- offset
;
1192 memcpy (readbuf
, buf
+ offset
, len
);
1197 /* Collect data about semaphores recorded in /proc and write it
1201 linux_xfer_osdata_sem (gdb_byte
*readbuf
,
1202 ULONGEST offset
, LONGEST len
)
1204 static const char *buf
;
1205 static LONGEST len_avail
= -1;
1206 static struct buffer buffer
;
1212 if (len_avail
!= -1 && len_avail
!= 0)
1213 buffer_free (&buffer
);
1216 buffer_init (&buffer
);
1217 buffer_grow_str (&buffer
, "<osdata type=\"semaphores\">\n");
1219 fp
= fopen ("/proc/sysvipc/sem", "r");
1226 if (fgets (buf
, sizeof (buf
), fp
))
1231 unsigned int perms
, nsems
;
1233 TIME_T otime
, ctime
;
1236 items_read
= sscanf (buf
,
1237 "%d %d %o %u %d %d %d %d %lld %lld",
1238 &key
, &semid
, &perms
, &nsems
,
1239 &uid
, &gid
, &cuid
, &cgid
,
1242 if (items_read
== 10)
1244 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1245 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1246 char otime_str
[32], ctime_str
[32];
1248 user_from_uid (user
, sizeof (user
), uid
);
1249 group_from_gid (group
, sizeof (group
), gid
);
1250 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1251 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1253 time_from_time_t (otime_str
, sizeof (otime_str
), otime
);
1254 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1259 "<column name=\"key\">%d</column>"
1260 "<column name=\"semid\">%d</column>"
1261 "<column name=\"permissions\">%o</column>"
1262 "<column name=\"num semaphores\">%u</column>"
1263 "<column name=\"user\">%s</column>"
1264 "<column name=\"group\">%s</column>"
1265 "<column name=\"creator user\">%s</column>"
1266 "<column name=\"creator group\">%s</column>"
1267 "<column name=\"last semop() time\">%s</column>"
1268 "<column name=\"last semctl() time\">%s</column>"
1288 buffer_grow_str0 (&buffer
, "</osdata>\n");
1289 buf
= buffer_finish (&buffer
);
1290 len_avail
= strlen (buf
);
1293 if (offset
>= len_avail
)
1295 /* Done. Get rid of the buffer. */
1296 buffer_free (&buffer
);
1302 if (len
> len_avail
- offset
)
1303 len
= len_avail
- offset
;
1304 memcpy (readbuf
, buf
+ offset
, len
);
1309 /* Collect data about message queues recorded in /proc and write it
1313 linux_xfer_osdata_msg (gdb_byte
*readbuf
,
1314 ULONGEST offset
, LONGEST len
)
1316 static const char *buf
;
1317 static LONGEST len_avail
= -1;
1318 static struct buffer buffer
;
1324 if (len_avail
!= -1 && len_avail
!= 0)
1325 buffer_free (&buffer
);
1328 buffer_init (&buffer
);
1329 buffer_grow_str (&buffer
, "<osdata type=\"message queues\">\n");
1331 fp
= fopen ("/proc/sysvipc/msg", "r");
1338 if (fgets (buf
, sizeof (buf
), fp
))
1344 unsigned int perms
, cbytes
, qnum
;
1346 TIME_T stime
, rtime
, ctime
;
1349 items_read
= sscanf (buf
,
1350 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1351 &key
, &msqid
, &perms
, &cbytes
, &qnum
,
1352 &lspid
, &lrpid
, &uid
, &gid
, &cuid
, &cgid
,
1353 &stime
, &rtime
, &ctime
);
1355 if (items_read
== 14)
1357 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1358 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1359 char lscmd
[32], lrcmd
[32];
1360 char stime_str
[32], rtime_str
[32], ctime_str
[32];
1362 user_from_uid (user
, sizeof (user
), uid
);
1363 group_from_gid (group
, sizeof (group
), gid
);
1364 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1365 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1367 command_from_pid (lscmd
, sizeof (lscmd
), lspid
);
1368 command_from_pid (lrcmd
, sizeof (lrcmd
), lrpid
);
1370 time_from_time_t (stime_str
, sizeof (stime_str
), stime
);
1371 time_from_time_t (rtime_str
, sizeof (rtime_str
), rtime
);
1372 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1377 "<column name=\"key\">%d</column>"
1378 "<column name=\"msqid\">%d</column>"
1379 "<column name=\"permissions\">%o</column>"
1380 "<column name=\"num used bytes\">%u</column>"
1381 "<column name=\"num messages\">%u</column>"
1382 "<column name=\"last msgsnd() command\">%s</column>"
1383 "<column name=\"last msgrcv() command\">%s</column>"
1384 "<column name=\"user\">%s</column>"
1385 "<column name=\"group\">%s</column>"
1386 "<column name=\"creator user\">%s</column>"
1387 "<column name=\"creator group\">%s</column>"
1388 "<column name=\"last msgsnd() time\">%s</column>"
1389 "<column name=\"last msgrcv() time\">%s</column>"
1390 "<column name=\"last msgctl() time\">%s</column>"
1414 buffer_grow_str0 (&buffer
, "</osdata>\n");
1415 buf
= buffer_finish (&buffer
);
1416 len_avail
= strlen (buf
);
1419 if (offset
>= len_avail
)
1421 /* Done. Get rid of the buffer. */
1422 buffer_free (&buffer
);
1428 if (len
> len_avail
- offset
)
1429 len
= len_avail
- offset
;
1430 memcpy (readbuf
, buf
+ offset
, len
);
1435 /* Collect data about loaded kernel modules and write it into
1439 linux_xfer_osdata_modules (gdb_byte
*readbuf
,
1440 ULONGEST offset
, LONGEST len
)
1442 static const char *buf
;
1443 static LONGEST len_avail
= -1;
1444 static struct buffer buffer
;
1450 if (len_avail
!= -1 && len_avail
!= 0)
1451 buffer_free (&buffer
);
1454 buffer_init (&buffer
);
1455 buffer_grow_str (&buffer
, "<osdata type=\"modules\">\n");
1457 fp
= fopen ("/proc/modules", "r");
1464 if (fgets (buf
, sizeof (buf
), fp
))
1466 char name
[64], dependencies
[256], status
[16];
1468 unsigned long long address
;
1472 items_read
= sscanf (buf
,
1473 "%64s %d %d %256s %16s 0x%llx",
1475 dependencies
, status
, &address
);
1477 if (items_read
== 6)
1481 "<column name=\"name\">%s</column>"
1482 "<column name=\"size\">%u</column>"
1483 "<column name=\"num uses\">%d</column>"
1484 "<column name=\"dependencies\">%s</column>"
1485 "<column name=\"status\">%s</column>"
1486 "<column name=\"address\">%llx</column>"
1501 buffer_grow_str0 (&buffer
, "</osdata>\n");
1502 buf
= buffer_finish (&buffer
);
1503 len_avail
= strlen (buf
);
1506 if (offset
>= len_avail
)
1508 /* Done. Get rid of the buffer. */
1509 buffer_free (&buffer
);
1515 if (len
> len_avail
- offset
)
1516 len
= len_avail
- offset
;
1517 memcpy (readbuf
, buf
+ offset
, len
);
1522 struct osdata_type
{
1526 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, LONGEST len
);
1527 } osdata_table
[] = {
1528 { "processes", "Processes", "Listing of all processes",
1529 linux_xfer_osdata_processes
},
1530 { "procgroups", "Process groups", "Listing of all process groups",
1531 linux_xfer_osdata_processgroups
},
1532 { "threads", "Threads", "Listing of all threads",
1533 linux_xfer_osdata_threads
},
1534 { "files", "File descriptors", "Listing of all file descriptors",
1535 linux_xfer_osdata_fds
},
1536 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1537 linux_xfer_osdata_isockets
},
1538 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1539 linux_xfer_osdata_shm
},
1540 { "semaphores", "Semaphores", "Listing of all semaphores",
1541 linux_xfer_osdata_sem
},
1542 { "msg", "Message queues", "Listing of all message queues",
1543 linux_xfer_osdata_msg
},
1544 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1545 linux_xfer_osdata_modules
},
1546 { NULL
, NULL
, NULL
}
1550 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
1551 ULONGEST offset
, LONGEST len
)
1553 if (!annex
|| *annex
== '\0')
1555 static const char *buf
;
1556 static LONGEST len_avail
= -1;
1557 static struct buffer buffer
;
1563 if (len_avail
!= -1 && len_avail
!= 0)
1564 buffer_free (&buffer
);
1567 buffer_init (&buffer
);
1568 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
1570 for (i
= 0; osdata_table
[i
].type
; ++i
)
1574 "<column name=\"Type\">%s</column>"
1575 "<column name=\"Description\">%s</column>"
1576 "<column name=\"Title\">%s</column>"
1578 osdata_table
[i
].type
,
1579 osdata_table
[i
].description
,
1580 osdata_table
[i
].title
);
1582 buffer_grow_str0 (&buffer
, "</osdata>\n");
1583 buf
= buffer_finish (&buffer
);
1584 len_avail
= strlen (buf
);
1587 if (offset
>= len_avail
)
1589 /* Done. Get rid of the buffer. */
1590 buffer_free (&buffer
);
1596 if (len
> len_avail
- offset
)
1597 len
= len_avail
- offset
;
1598 memcpy (readbuf
, buf
+ offset
, len
);
1606 for (i
= 0; osdata_table
[i
].type
; ++i
)
1608 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
1610 gdb_assert (readbuf
);
1612 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);