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>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
43 #include "xml-utils.h"
45 #include "gdb_assert.h"
46 #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 /* Returns the number of CPU cores found on the system. */
260 get_number_of_cpu_cores (void)
263 FILE *f
= fopen ("/proc/cpuinfo", "r");
268 char *p
= fgets (buf
, sizeof (buf
), f
);
270 if (p
&& strncmp (buf
, "processor", 9) == 0)
279 /* Find the CPU cores used by process PID and return them in CORES.
280 CORES points to an array of at least get_number_of_cpu_cores ()
284 get_cores_used_by_process (PID_T pid
, int *cores
)
286 char taskdir
[sizeof ("/proc/") + MAX_PID_T_STRLEN
+ sizeof ("/task") - 1];
291 sprintf (taskdir
, "/proc/%lld/task", pid
);
292 dir
= opendir (taskdir
);
295 while ((dp
= readdir (dir
)) != NULL
)
300 if (!isdigit (dp
->d_name
[0])
301 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
304 sscanf (dp
->d_name
, "%lld", &tid
);
305 core
= linux_common_core_of_thread (ptid_build ((pid_t
) pid
,
322 linux_xfer_osdata_processes (gdb_byte
*readbuf
,
323 ULONGEST offset
, LONGEST len
)
325 /* We make the process list snapshot when the object starts to be read. */
326 static const char *buf
;
327 static LONGEST len_avail
= -1;
328 static struct buffer buffer
;
334 if (len_avail
!= -1 && len_avail
!= 0)
335 buffer_free (&buffer
);
338 buffer_init (&buffer
);
339 buffer_grow_str (&buffer
, "<osdata type=\"processes\">\n");
341 dirp
= opendir ("/proc");
344 const int num_cores
= get_number_of_cpu_cores ();
347 while ((dp
= readdir (dirp
)) != NULL
)
351 char user
[UT_NAMESIZE
];
358 if (!isdigit (dp
->d_name
[0])
359 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
362 sscanf (dp
->d_name
, "%lld", &pid
);
363 command_line
= commandline_from_pid (pid
);
365 if (get_process_owner (&owner
, pid
) == 0)
366 user_from_uid (user
, sizeof (user
), owner
);
370 /* Find CPU cores used by the process. */
371 cores
= (int *) xcalloc (num_cores
, sizeof (int));
372 task_count
= get_cores_used_by_process (pid
, cores
);
373 cores_str
= (char *) xcalloc (task_count
, sizeof ("4294967295") + 1);
375 for (i
= 0; i
< num_cores
&& task_count
> 0; ++i
)
378 char core_str
[sizeof ("4294967295")];
380 sprintf (core_str
, "%d", i
);
381 strcat (cores_str
, core_str
);
383 task_count
-= cores
[i
];
385 strcat (cores_str
, ",");
393 "<column name=\"pid\">%lld</column>"
394 "<column name=\"user\">%s</column>"
395 "<column name=\"command\">%s</column>"
396 "<column name=\"cores\">%s</column>"
400 command_line
? command_line
: "",
403 xfree (command_line
);
410 buffer_grow_str0 (&buffer
, "</osdata>\n");
411 buf
= buffer_finish (&buffer
);
412 len_avail
= strlen (buf
);
415 if (offset
>= len_avail
)
417 /* Done. Get rid of the buffer. */
418 buffer_free (&buffer
);
424 if (len
> len_avail
- offset
)
425 len
= len_avail
- offset
;
426 memcpy (readbuf
, buf
+ offset
, len
);
431 /* Auxiliary function used by qsort to sort processes by process
432 group. Compares two processes with ids PROCESS1 and PROCESS2.
433 PROCESS1 comes before PROCESS2 if it has a lower process group id.
434 If they belong to the same process group, PROCESS1 comes before
435 PROCESS2 if it has a lower process id or is the process group
439 compare_processes (const void *process1
, const void *process2
)
441 PID_T pid1
= *((PID_T
*) process1
);
442 PID_T pid2
= *((PID_T
*) process2
);
443 PID_T pgid1
= *((PID_T
*) process1
+ 1);
444 PID_T pgid2
= *((PID_T
*) process2
+ 1);
449 else if (pgid1
> pgid2
)
453 /* Process group leaders always come first, else sort by PID. */
456 else if (pid2
== pgid2
)
458 else if (pid1
< pid2
)
460 else if (pid1
> pid2
)
467 /* Collect all process groups from /proc. */
470 linux_xfer_osdata_processgroups (gdb_byte
*readbuf
,
471 ULONGEST offset
, LONGEST len
)
473 /* We make the process list snapshot when the object starts to be read. */
474 static const char *buf
;
475 static LONGEST len_avail
= -1;
476 static struct buffer buffer
;
482 if (len_avail
!= -1 && len_avail
!= 0)
483 buffer_free (&buffer
);
486 buffer_init (&buffer
);
487 buffer_grow_str (&buffer
, "<osdata type=\"process groups\">\n");
489 dirp
= opendir ("/proc");
493 const size_t list_block_size
= 512;
494 PID_T
*process_list
= (PID_T
*) xmalloc (list_block_size
* 2 * sizeof (PID_T
));
495 size_t process_count
= 0;
498 /* Build list consisting of PIDs followed by their
500 while ((dp
= readdir (dirp
)) != NULL
)
504 if (!isdigit (dp
->d_name
[0])
505 || NAMELEN (dp
) > MAX_PID_T_STRLEN
)
508 sscanf (dp
->d_name
, "%lld", &pid
);
509 pgid
= getpgid (pid
);
513 process_list
[2 * process_count
] = pid
;
514 process_list
[2 * process_count
+ 1] = pgid
;
517 /* Increase the size of the list if necessary. */
518 if (process_count
% list_block_size
== 0)
519 process_list
= (PID_T
*) xrealloc (
521 (process_count
+ list_block_size
)
522 * 2 * sizeof (PID_T
));
528 /* Sort the process list. */
529 qsort (process_list
, process_count
, 2 * sizeof (PID_T
),
532 for (i
= 0; i
< process_count
; ++i
)
534 PID_T pid
= process_list
[2 * i
];
535 PID_T pgid
= process_list
[2 * i
+ 1];
536 char leader_command
[32];
539 command_from_pid (leader_command
, sizeof (leader_command
), pgid
);
540 command_line
= commandline_from_pid (pid
);
545 "<column name=\"pgid\">%lld</column>"
546 "<column name=\"leader command\">%s</column>"
547 "<column name=\"pid\">%lld</column>"
548 "<column name=\"command line\">%s</column>"
553 command_line
? command_line
: "");
555 xfree (command_line
);
558 xfree (process_list
);
561 buffer_grow_str0 (&buffer
, "</osdata>\n");
562 buf
= buffer_finish (&buffer
);
563 len_avail
= strlen (buf
);
566 if (offset
>= len_avail
)
568 /* Done. Get rid of the buffer. */
569 buffer_free (&buffer
);
575 if (len
> len_avail
- offset
)
576 len
= len_avail
- offset
;
577 memcpy (readbuf
, buf
+ offset
, len
);
582 /* Collect all the threads in /proc by iterating through processes and
583 then tasks within each process. */
586 linux_xfer_osdata_threads (gdb_byte
*readbuf
,
587 ULONGEST offset
, LONGEST len
)
589 /* We make the process list snapshot when the object starts to be read. */
590 static const char *buf
;
591 static LONGEST len_avail
= -1;
592 static struct buffer buffer
;
598 if (len_avail
!= -1 && len_avail
!= 0)
599 buffer_free (&buffer
);
602 buffer_init (&buffer
);
603 buffer_grow_str (&buffer
, "<osdata type=\"threads\">\n");
605 dirp
= opendir ("/proc");
610 while ((dp
= readdir (dirp
)) != NULL
)
613 char procentry
[sizeof ("/proc/4294967295")];
615 if (!isdigit (dp
->d_name
[0])
616 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
619 sprintf (procentry
, "/proc/%s", dp
->d_name
);
620 if (stat (procentry
, &statbuf
) == 0
621 && S_ISDIR (statbuf
.st_mode
))
628 pathname
= xstrprintf ("/proc/%s/task", dp
->d_name
);
630 pid
= atoi (dp
->d_name
);
631 command_from_pid (command
, sizeof (command
), pid
);
633 dirp2
= opendir (pathname
);
639 while ((dp2
= readdir (dirp2
)) != NULL
)
644 if (!isdigit (dp2
->d_name
[0])
645 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
648 tid
= atoi (dp2
->d_name
);
649 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
654 "<column name=\"pid\">%lld</column>"
655 "<column name=\"command\">%s</column>"
656 "<column name=\"tid\">%lld</column>"
657 "<column name=\"core\">%d</column>"
675 buffer_grow_str0 (&buffer
, "</osdata>\n");
676 buf
= buffer_finish (&buffer
);
677 len_avail
= strlen (buf
);
680 if (offset
>= len_avail
)
682 /* Done. Get rid of the buffer. */
683 buffer_free (&buffer
);
689 if (len
> len_avail
- offset
)
690 len
= len_avail
- offset
;
691 memcpy (readbuf
, buf
+ offset
, len
);
696 /* Collect all the open file descriptors found in /proc and put the details
697 found about them into READBUF. */
700 linux_xfer_osdata_fds (gdb_byte
*readbuf
,
701 ULONGEST offset
, LONGEST len
)
703 /* We make the process list snapshot when the object starts to be read. */
704 static const char *buf
;
705 static LONGEST len_avail
= -1;
706 static struct buffer buffer
;
712 if (len_avail
!= -1 && len_avail
!= 0)
713 buffer_free (&buffer
);
716 buffer_init (&buffer
);
717 buffer_grow_str (&buffer
, "<osdata type=\"files\">\n");
719 dirp
= opendir ("/proc");
724 while ((dp
= readdir (dirp
)) != NULL
)
727 char procentry
[sizeof ("/proc/4294967295")];
729 if (!isdigit (dp
->d_name
[0])
730 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
733 sprintf (procentry
, "/proc/%s", dp
->d_name
);
734 if (stat (procentry
, &statbuf
) == 0
735 && S_ISDIR (statbuf
.st_mode
))
742 pid
= atoi (dp
->d_name
);
743 command_from_pid (command
, sizeof (command
), pid
);
745 pathname
= xstrprintf ("/proc/%s/fd", dp
->d_name
);
746 dirp2
= opendir (pathname
);
752 while ((dp2
= readdir (dirp2
)) != NULL
)
758 if (!isdigit (dp2
->d_name
[0]))
761 fdname
= xstrprintf ("%s/%s", pathname
, dp2
->d_name
);
762 rslt
= readlink (fdname
, buf
, 1000);
769 "<column name=\"pid\">%s</column>"
770 "<column name=\"command\">%s</column>"
771 "<column name=\"file descriptor\">%s</column>"
772 "<column name=\"name\">%s</column>"
777 (rslt
>= 0 ? buf
: dp2
->d_name
));
790 buffer_grow_str0 (&buffer
, "</osdata>\n");
791 buf
= buffer_finish (&buffer
);
792 len_avail
= strlen (buf
);
795 if (offset
>= len_avail
)
797 /* Done. Get rid of the buffer. */
798 buffer_free (&buffer
);
804 if (len
> len_avail
- offset
)
805 len
= len_avail
- offset
;
806 memcpy (readbuf
, buf
+ offset
, len
);
811 /* Returns the socket state STATE in textual form. */
814 format_socket_state (unsigned char state
)
816 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
833 case TCP_ESTABLISHED
:
834 return "ESTABLISHED";
863 struct sockaddr_in sin
;
864 struct sockaddr_in6 sin6
;
867 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
868 information for all open internet sockets of type FAMILY on the
869 system into BUFFER. If TCP is set, only TCP sockets are processed,
870 otherwise only UDP sockets are processed. */
873 print_sockets (unsigned short family
, int tcp
, struct buffer
*buffer
)
875 const char *proc_file
;
878 if (family
== AF_INET
)
879 proc_file
= tcp
? "/proc/net/tcp" : "/proc/net/udp";
880 else if (family
== AF_INET6
)
881 proc_file
= tcp
? "/proc/net/tcp6" : "/proc/net/udp6";
885 fp
= fopen (proc_file
, "r");
892 if (fgets (buf
, sizeof (buf
), fp
))
895 unsigned long tlen
, inode
;
897 unsigned int local_port
, remote_port
, state
;
898 unsigned int txq
, rxq
, trun
, retn
;
899 char local_address
[NI_MAXHOST
], remote_address
[NI_MAXHOST
];
903 result
= sscanf (buf
,
904 "%d: %33[0-9A-F]:%X %33[0-9A-F]:%X %X %X:%X %X:%lX %X %d %d %lu %512s\n",
906 local_address
, &local_port
,
907 remote_address
, &remote_port
,
919 union socket_addr locaddr
, remaddr
;
921 char user
[UT_NAMESIZE
];
922 char local_service
[NI_MAXSERV
], remote_service
[NI_MAXSERV
];
924 if (family
== AF_INET
)
926 sscanf (local_address
, "%X",
927 &locaddr
.sin
.sin_addr
.s_addr
);
928 sscanf (remote_address
, "%X",
929 &remaddr
.sin
.sin_addr
.s_addr
);
931 locaddr
.sin
.sin_port
= htons (local_port
);
932 remaddr
.sin
.sin_port
= htons (remote_port
);
934 addr_size
= sizeof (struct sockaddr_in
);
938 sscanf (local_address
, "%8X%8X%8X%8X",
939 locaddr
.sin6
.sin6_addr
.s6_addr32
,
940 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
941 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
942 locaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
943 sscanf (remote_address
, "%8X%8X%8X%8X",
944 remaddr
.sin6
.sin6_addr
.s6_addr32
,
945 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 1,
946 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 2,
947 remaddr
.sin6
.sin6_addr
.s6_addr32
+ 3);
949 locaddr
.sin6
.sin6_port
= htons (local_port
);
950 remaddr
.sin6
.sin6_port
= htons (remote_port
);
952 locaddr
.sin6
.sin6_flowinfo
= 0;
953 remaddr
.sin6
.sin6_flowinfo
= 0;
954 locaddr
.sin6
.sin6_scope_id
= 0;
955 remaddr
.sin6
.sin6_scope_id
= 0;
957 addr_size
= sizeof (struct sockaddr_in6
);
960 locaddr
.sa
.sa_family
= remaddr
.sa
.sa_family
= family
;
962 result
= getnameinfo (&locaddr
.sa
, addr_size
,
963 local_address
, sizeof (local_address
),
964 local_service
, sizeof (local_service
),
965 NI_NUMERICHOST
| NI_NUMERICSERV
966 | (tcp
? 0 : NI_DGRAM
));
970 result
= getnameinfo (&remaddr
.sa
, addr_size
,
972 sizeof (remote_address
),
974 sizeof (remote_service
),
975 NI_NUMERICHOST
| NI_NUMERICSERV
976 | (tcp
? 0 : NI_DGRAM
));
980 user_from_uid (user
, sizeof (user
), uid
);
985 "<column name=\"local address\">%s</column>"
986 "<column name=\"local port\">%s</column>"
987 "<column name=\"remote address\">%s</column>"
988 "<column name=\"remote port\">%s</column>"
989 "<column name=\"state\">%s</column>"
990 "<column name=\"user\">%s</column>"
991 "<column name=\"family\">%s</column>"
992 "<column name=\"protocol\">%s</column>"
998 format_socket_state (state
),
1000 (family
== AF_INET
) ? "INET" : "INET6",
1001 tcp
? "STREAM" : "DGRAM");
1011 /* Collect data about internet sockets and write it into READBUF. */
1014 linux_xfer_osdata_isockets (gdb_byte
*readbuf
,
1015 ULONGEST offset
, LONGEST len
)
1017 static const char *buf
;
1018 static LONGEST len_avail
= -1;
1019 static struct buffer buffer
;
1023 if (len_avail
!= -1 && len_avail
!= 0)
1024 buffer_free (&buffer
);
1027 buffer_init (&buffer
);
1028 buffer_grow_str (&buffer
, "<osdata type=\"I sockets\">\n");
1030 print_sockets (AF_INET
, 1, &buffer
);
1031 print_sockets (AF_INET
, 0, &buffer
);
1032 print_sockets (AF_INET6
, 1, &buffer
);
1033 print_sockets (AF_INET6
, 0, &buffer
);
1035 buffer_grow_str0 (&buffer
, "</osdata>\n");
1036 buf
= buffer_finish (&buffer
);
1037 len_avail
= strlen (buf
);
1040 if (offset
>= len_avail
)
1042 /* Done. Get rid of the buffer. */
1043 buffer_free (&buffer
);
1049 if (len
> len_avail
- offset
)
1050 len
= len_avail
- offset
;
1051 memcpy (readbuf
, buf
+ offset
, len
);
1056 /* Converts the time SECONDS into textual form and copies it into a
1057 buffer TIME, with at most MAXLEN characters copied. */
1060 time_from_time_t (char *time
, int maxlen
, TIME_T seconds
)
1066 time_t t
= (time_t) seconds
;
1068 strncpy (time
, ctime (&t
), maxlen
);
1069 time
[maxlen
- 1] = '\0';
1073 /* Finds the group name for the group GID and copies it into GROUP.
1074 At most MAXLEN characters are copied. */
1077 group_from_gid (char *group
, int maxlen
, gid_t gid
)
1079 struct group
*grentry
= getgrgid (gid
);
1083 strncpy (group
, grentry
->gr_name
, maxlen
);
1084 /* Ensure that the group name is null-terminated. */
1085 group
[maxlen
- 1] = '\0';
1091 /* Collect data about shared memory recorded in /proc and write it
1095 linux_xfer_osdata_shm (gdb_byte
*readbuf
,
1096 ULONGEST offset
, LONGEST len
)
1098 static const char *buf
;
1099 static LONGEST len_avail
= -1;
1100 static struct buffer buffer
;
1106 if (len_avail
!= -1 && len_avail
!= 0)
1107 buffer_free (&buffer
);
1110 buffer_init (&buffer
);
1111 buffer_grow_str (&buffer
, "<osdata type=\"shared memory\">\n");
1113 fp
= fopen ("/proc/sysvipc/shm", "r");
1120 if (fgets (buf
, sizeof (buf
), fp
))
1126 int shmid
, size
, nattch
;
1127 TIME_T atime
, dtime
, ctime
;
1131 items_read
= sscanf (buf
,
1132 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1133 &key
, &shmid
, &perms
, &size
,
1136 &uid
, &gid
, &cuid
, &cgid
,
1137 &atime
, &dtime
, &ctime
);
1139 if (items_read
== 14)
1141 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1142 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1143 char ccmd
[32], lcmd
[32];
1144 char atime_str
[32], dtime_str
[32], ctime_str
[32];
1146 user_from_uid (user
, sizeof (user
), uid
);
1147 group_from_gid (group
, sizeof (group
), gid
);
1148 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1149 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1151 command_from_pid (ccmd
, sizeof (ccmd
), cpid
);
1152 command_from_pid (lcmd
, sizeof (lcmd
), lpid
);
1154 time_from_time_t (atime_str
, sizeof (atime_str
), atime
);
1155 time_from_time_t (dtime_str
, sizeof (dtime_str
), dtime
);
1156 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1161 "<column name=\"key\">%d</column>"
1162 "<column name=\"shmid\">%d</column>"
1163 "<column name=\"permissions\">%o</column>"
1164 "<column name=\"size\">%d</column>"
1165 "<column name=\"creator command\">%s</column>"
1166 "<column name=\"last op. command\">%s</column>"
1167 "<column name=\"num attached\">%d</column>"
1168 "<column name=\"user\">%s</column>"
1169 "<column name=\"group\">%s</column>"
1170 "<column name=\"creator user\">%s</column>"
1171 "<column name=\"creator group\">%s</column>"
1172 "<column name=\"last shmat() time\">%s</column>"
1173 "<column name=\"last shmdt() time\">%s</column>"
1174 "<column name=\"last shmctl() time\">%s</column>"
1198 buffer_grow_str0 (&buffer
, "</osdata>\n");
1199 buf
= buffer_finish (&buffer
);
1200 len_avail
= strlen (buf
);
1203 if (offset
>= len_avail
)
1205 /* Done. Get rid of the buffer. */
1206 buffer_free (&buffer
);
1212 if (len
> len_avail
- offset
)
1213 len
= len_avail
- offset
;
1214 memcpy (readbuf
, buf
+ offset
, len
);
1219 /* Collect data about semaphores recorded in /proc and write it
1223 linux_xfer_osdata_sem (gdb_byte
*readbuf
,
1224 ULONGEST offset
, LONGEST len
)
1226 static const char *buf
;
1227 static LONGEST len_avail
= -1;
1228 static struct buffer buffer
;
1234 if (len_avail
!= -1 && len_avail
!= 0)
1235 buffer_free (&buffer
);
1238 buffer_init (&buffer
);
1239 buffer_grow_str (&buffer
, "<osdata type=\"semaphores\">\n");
1241 fp
= fopen ("/proc/sysvipc/sem", "r");
1248 if (fgets (buf
, sizeof (buf
), fp
))
1253 unsigned int perms
, nsems
;
1255 TIME_T otime
, ctime
;
1258 items_read
= sscanf (buf
,
1259 "%d %d %o %u %d %d %d %d %lld %lld",
1260 &key
, &semid
, &perms
, &nsems
,
1261 &uid
, &gid
, &cuid
, &cgid
,
1264 if (items_read
== 10)
1266 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1267 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1268 char otime_str
[32], ctime_str
[32];
1270 user_from_uid (user
, sizeof (user
), uid
);
1271 group_from_gid (group
, sizeof (group
), gid
);
1272 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1273 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1275 time_from_time_t (otime_str
, sizeof (otime_str
), otime
);
1276 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1281 "<column name=\"key\">%d</column>"
1282 "<column name=\"semid\">%d</column>"
1283 "<column name=\"permissions\">%o</column>"
1284 "<column name=\"num semaphores\">%u</column>"
1285 "<column name=\"user\">%s</column>"
1286 "<column name=\"group\">%s</column>"
1287 "<column name=\"creator user\">%s</column>"
1288 "<column name=\"creator group\">%s</column>"
1289 "<column name=\"last semop() time\">%s</column>"
1290 "<column name=\"last semctl() time\">%s</column>"
1310 buffer_grow_str0 (&buffer
, "</osdata>\n");
1311 buf
= buffer_finish (&buffer
);
1312 len_avail
= strlen (buf
);
1315 if (offset
>= len_avail
)
1317 /* Done. Get rid of the buffer. */
1318 buffer_free (&buffer
);
1324 if (len
> len_avail
- offset
)
1325 len
= len_avail
- offset
;
1326 memcpy (readbuf
, buf
+ offset
, len
);
1331 /* Collect data about message queues recorded in /proc and write it
1335 linux_xfer_osdata_msg (gdb_byte
*readbuf
,
1336 ULONGEST offset
, LONGEST len
)
1338 static const char *buf
;
1339 static LONGEST len_avail
= -1;
1340 static struct buffer buffer
;
1346 if (len_avail
!= -1 && len_avail
!= 0)
1347 buffer_free (&buffer
);
1350 buffer_init (&buffer
);
1351 buffer_grow_str (&buffer
, "<osdata type=\"message queues\">\n");
1353 fp
= fopen ("/proc/sysvipc/msg", "r");
1360 if (fgets (buf
, sizeof (buf
), fp
))
1366 unsigned int perms
, cbytes
, qnum
;
1368 TIME_T stime
, rtime
, ctime
;
1371 items_read
= sscanf (buf
,
1372 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1373 &key
, &msqid
, &perms
, &cbytes
, &qnum
,
1374 &lspid
, &lrpid
, &uid
, &gid
, &cuid
, &cgid
,
1375 &stime
, &rtime
, &ctime
);
1377 if (items_read
== 14)
1379 char user
[UT_NAMESIZE
], group
[UT_NAMESIZE
];
1380 char cuser
[UT_NAMESIZE
], cgroup
[UT_NAMESIZE
];
1381 char lscmd
[32], lrcmd
[32];
1382 char stime_str
[32], rtime_str
[32], ctime_str
[32];
1384 user_from_uid (user
, sizeof (user
), uid
);
1385 group_from_gid (group
, sizeof (group
), gid
);
1386 user_from_uid (cuser
, sizeof (cuser
), cuid
);
1387 group_from_gid (cgroup
, sizeof (cgroup
), cgid
);
1389 command_from_pid (lscmd
, sizeof (lscmd
), lspid
);
1390 command_from_pid (lrcmd
, sizeof (lrcmd
), lrpid
);
1392 time_from_time_t (stime_str
, sizeof (stime_str
), stime
);
1393 time_from_time_t (rtime_str
, sizeof (rtime_str
), rtime
);
1394 time_from_time_t (ctime_str
, sizeof (ctime_str
), ctime
);
1399 "<column name=\"key\">%d</column>"
1400 "<column name=\"msqid\">%d</column>"
1401 "<column name=\"permissions\">%o</column>"
1402 "<column name=\"num used bytes\">%u</column>"
1403 "<column name=\"num messages\">%u</column>"
1404 "<column name=\"last msgsnd() command\">%s</column>"
1405 "<column name=\"last msgrcv() command\">%s</column>"
1406 "<column name=\"user\">%s</column>"
1407 "<column name=\"group\">%s</column>"
1408 "<column name=\"creator user\">%s</column>"
1409 "<column name=\"creator group\">%s</column>"
1410 "<column name=\"last msgsnd() time\">%s</column>"
1411 "<column name=\"last msgrcv() time\">%s</column>"
1412 "<column name=\"last msgctl() time\">%s</column>"
1436 buffer_grow_str0 (&buffer
, "</osdata>\n");
1437 buf
= buffer_finish (&buffer
);
1438 len_avail
= strlen (buf
);
1441 if (offset
>= len_avail
)
1443 /* Done. Get rid of the buffer. */
1444 buffer_free (&buffer
);
1450 if (len
> len_avail
- offset
)
1451 len
= len_avail
- offset
;
1452 memcpy (readbuf
, buf
+ offset
, len
);
1457 /* Collect data about loaded kernel modules and write it into
1461 linux_xfer_osdata_modules (gdb_byte
*readbuf
,
1462 ULONGEST offset
, LONGEST len
)
1464 static const char *buf
;
1465 static LONGEST len_avail
= -1;
1466 static struct buffer buffer
;
1472 if (len_avail
!= -1 && len_avail
!= 0)
1473 buffer_free (&buffer
);
1476 buffer_init (&buffer
);
1477 buffer_grow_str (&buffer
, "<osdata type=\"modules\">\n");
1479 fp
= fopen ("/proc/modules", "r");
1486 if (fgets (buf
, sizeof (buf
), fp
))
1488 char name
[64], dependencies
[256], status
[16];
1490 unsigned long long address
;
1494 items_read
= sscanf (buf
,
1495 "%64s %d %d %256s %16s 0x%llx",
1497 dependencies
, status
, &address
);
1499 if (items_read
== 6)
1503 "<column name=\"name\">%s</column>"
1504 "<column name=\"size\">%u</column>"
1505 "<column name=\"num uses\">%d</column>"
1506 "<column name=\"dependencies\">%s</column>"
1507 "<column name=\"status\">%s</column>"
1508 "<column name=\"address\">%llx</column>"
1523 buffer_grow_str0 (&buffer
, "</osdata>\n");
1524 buf
= buffer_finish (&buffer
);
1525 len_avail
= strlen (buf
);
1528 if (offset
>= len_avail
)
1530 /* Done. Get rid of the buffer. */
1531 buffer_free (&buffer
);
1537 if (len
> len_avail
- offset
)
1538 len
= len_avail
- offset
;
1539 memcpy (readbuf
, buf
+ offset
, len
);
1544 struct osdata_type
{
1548 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, LONGEST len
);
1549 } osdata_table
[] = {
1550 { "processes", "Processes", "Listing of all processes",
1551 linux_xfer_osdata_processes
},
1552 { "procgroups", "Process groups", "Listing of all process groups",
1553 linux_xfer_osdata_processgroups
},
1554 { "threads", "Threads", "Listing of all threads",
1555 linux_xfer_osdata_threads
},
1556 { "files", "File descriptors", "Listing of all file descriptors",
1557 linux_xfer_osdata_fds
},
1558 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1559 linux_xfer_osdata_isockets
},
1560 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1561 linux_xfer_osdata_shm
},
1562 { "semaphores", "Semaphores", "Listing of all semaphores",
1563 linux_xfer_osdata_sem
},
1564 { "msg", "Message queues", "Listing of all message queues",
1565 linux_xfer_osdata_msg
},
1566 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1567 linux_xfer_osdata_modules
},
1568 { NULL
, NULL
, NULL
}
1572 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
1573 ULONGEST offset
, LONGEST len
)
1575 if (!annex
|| *annex
== '\0')
1577 static const char *buf
;
1578 static LONGEST len_avail
= -1;
1579 static struct buffer buffer
;
1585 if (len_avail
!= -1 && len_avail
!= 0)
1586 buffer_free (&buffer
);
1589 buffer_init (&buffer
);
1590 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
1592 for (i
= 0; osdata_table
[i
].type
; ++i
)
1596 "<column name=\"Type\">%s</column>"
1597 "<column name=\"Description\">%s</column>"
1598 "<column name=\"Title\">%s</column>"
1600 osdata_table
[i
].type
,
1601 osdata_table
[i
].description
,
1602 osdata_table
[i
].title
);
1604 buffer_grow_str0 (&buffer
, "</osdata>\n");
1605 buf
= buffer_finish (&buffer
);
1606 len_avail
= strlen (buf
);
1609 if (offset
>= len_avail
)
1611 /* Done. Get rid of the buffer. */
1612 buffer_free (&buffer
);
1618 if (len
> len_avail
- offset
)
1619 len
= len_avail
- offset
;
1620 memcpy (readbuf
, buf
+ offset
, len
);
1628 for (i
= 0; osdata_table
[i
].type
; ++i
)
1630 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
1632 gdb_assert (readbuf
);
1634 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);