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/>. */
20 #include "common-defs.h"
21 #include "linux-osdata.h"
23 #include <sys/types.h>
24 #include <sys/sysinfo.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
35 #include "xml-utils.h"
39 #include "filestuff.h"
41 #define NAMELEN(dirent) strlen ((dirent)->d_name)
43 /* Define PID_T to be a fixed size that is at least as large as pid_t,
44 so that reading pid values embedded in /proc works
47 typedef long long PID_T;
49 /* Define TIME_T to be at least as large as time_t, so that reading
50 time values embedded in /proc works consistently. */
52 typedef long long TIME_T;
54 #define MAX_PID_T_STRLEN (sizeof ("-9223372036854775808") - 1)
56 /* Returns the CPU core that thread PTID is currently running on. */
58 /* Compute and return the processor core of a given thread. */
61 linux_common_core_of_thread (ptid_t ptid)
63 char filename[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN];
72 sprintf (filename, "/proc/%lld/task/%lld/stat",
73 (PID_T) ptid_get_pid (ptid), (PID_T) ptid_get_lwp (ptid));
74 f = gdb_fopen_cloexec (filename, "r");
81 content = xrealloc (content, content_read + 1024);
82 n = fread (content + content_read, 1, 1024, f);
86 content[content_read] = '\0';
91 /* ps command also relies on no trailing fields ever contain ')'. */
92 p = strrchr (content, ')');
96 /* If the first field after program name has index 0, then core number is
97 the field with index 36. There's no constant for that anywhere. */
99 p = strtok_r (p, " ", &ts);
100 for (i = 0; p != NULL && i != 36; ++i)
101 p = strtok_r (NULL, " ", &ts);
103 if (p == NULL || sscanf (p, "%d", &core) == 0)
112 /* Finds the command-line of process PID and copies it into COMMAND.
113 At most MAXLEN characters are copied. If the command-line cannot
114 be found, PID is copied into command in text-form. */
117 command_from_pid (char *command, int maxlen, PID_T pid)
119 char *stat_path = xstrprintf ("/proc/%lld/stat", pid);
120 FILE *fp = gdb_fopen_cloexec (stat_path, "r");
126 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
127 include/linux/sched.h in the Linux kernel sources) plus two
128 (for the brackets). */
131 int items_read = fscanf (fp, "%lld %17s", &stat_pid, cmd);
133 if (items_read == 2 && pid == stat_pid)
135 cmd[strlen (cmd) - 1] = '\0'; /* Remove trailing parenthesis. */
136 strncpy (command, cmd + 1, maxlen); /* Ignore leading parenthesis. */
143 /* Return the PID if a /proc entry for the process cannot be found. */
144 snprintf (command, maxlen, "%lld", pid);
147 command[maxlen - 1] = '\0'; /* Ensure string is null-terminated. */
152 /* Returns the command-line of the process with the given PID. The
153 returned string needs to be freed using xfree after use. */
156 commandline_from_pid (PID_T pid)
158 char *pathname = xstrprintf ("/proc/%lld/cmdline", pid);
159 char *commandline = NULL;
160 FILE *f = gdb_fopen_cloexec (pathname, "r");
169 size_t read_bytes = fread (buf, 1, sizeof (buf), f);
173 commandline = (char *) xrealloc (commandline, len + read_bytes + 1);
174 memcpy (commandline + len, buf, read_bytes);
185 /* Replace null characters with spaces. */
186 for (i = 0; i < len; ++i)
187 if (commandline[i] == '\0')
188 commandline[i] = ' ';
190 commandline[len] = '\0';
194 /* Return the command in square brackets if the command-line
196 commandline = (char *) xmalloc (32);
197 commandline[0] = '[';
198 command_from_pid (commandline + 1, 31, pid);
200 len = strlen (commandline);
202 strcat (commandline, "]");
211 /* Finds the user name for the user UID and copies it into USER. At
212 most MAXLEN characters are copied. */
215 user_from_uid (char *user, int maxlen, uid_t uid)
217 struct passwd *pwentry = getpwuid (uid);
221 strncpy (user, pwentry->pw_name, maxlen);
222 /* Ensure that the user name is null-terminated. */
223 user[maxlen - 1] = '\0';
229 /* Finds the owner of process PID and returns the user id in OWNER.
230 Returns 0 if the owner was found, -1 otherwise. */
233 get_process_owner (uid_t *owner, PID_T pid)
236 char procentry[sizeof ("/proc/") + MAX_PID_T_STRLEN];
238 sprintf (procentry, "/proc/%lld", pid);
240 if (stat (procentry, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))
242 *owner = statbuf.st_uid;
249 /* Find the CPU cores used by process PID and return them in CORES.
250 CORES points to an array of NUM_CORES elements. */
253 get_cores_used_by_process (PID_T pid, int *cores, const int num_cores)
255 char taskdir[sizeof ("/proc/") + MAX_PID_T_STRLEN + sizeof ("/task") - 1];
260 sprintf (taskdir, "/proc/%lld/task", pid);
261 dir = opendir (taskdir);
264 while ((dp = readdir (dir)) != NULL)
269 if (!isdigit (dp->d_name[0])
270 || NAMELEN (dp) > MAX_PID_T_STRLEN)
273 sscanf (dp->d_name, "%lld", &tid);
274 core = linux_common_core_of_thread (ptid_build ((pid_t) pid,
277 if (core >= 0 && core < num_cores)
291 linux_xfer_osdata_processes (gdb_byte *readbuf,
292 ULONGEST offset, ULONGEST len)
294 /* We make the process list snapshot when the object starts to be read. */
295 static const char *buf;
296 static LONGEST len_avail = -1;
297 static struct buffer buffer;
303 if (len_avail != -1 && len_avail != 0)
304 buffer_free (&buffer);
307 buffer_init (&buffer);
308 buffer_grow_str (&buffer, "<osdata type=\"processes\">\n");
310 dirp = opendir ("/proc");
313 const int num_cores = sysconf (_SC_NPROCESSORS_ONLN);
316 while ((dp = readdir (dirp)) != NULL)
320 char user[UT_NAMESIZE];
327 if (!isdigit (dp->d_name[0])
328 || NAMELEN (dp) > MAX_PID_T_STRLEN)
331 sscanf (dp->d_name, "%lld", &pid);
332 command_line = commandline_from_pid (pid);
334 if (get_process_owner (&owner, pid) == 0)
335 user_from_uid (user, sizeof (user), owner);
339 /* Find CPU cores used by the process. */
340 cores = (int *) xcalloc (num_cores, sizeof (int));
341 task_count = get_cores_used_by_process (pid, cores, num_cores);
342 cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1);
344 for (i = 0; i < num_cores && task_count > 0; ++i)
347 char core_str[sizeof ("4294967295")];
349 sprintf (core_str, "%d", i);
350 strcat (cores_str, core_str);
352 task_count -= cores[i];
354 strcat (cores_str, ",");
362 "<column name=\"pid\">%lld</column>"
363 "<column name=\"user\">%s</column>"
364 "<column name=\"command\">%s</column>"
365 "<column name=\"cores\">%s</column>"
369 command_line ? command_line : "",
372 xfree (command_line);
379 buffer_grow_str0 (&buffer, "</osdata>\n");
380 buf = buffer_finish (&buffer);
381 len_avail = strlen (buf);
384 if (offset >= len_avail)
386 /* Done. Get rid of the buffer. */
387 buffer_free (&buffer);
393 if (len > len_avail - offset)
394 len = len_avail - offset;
395 memcpy (readbuf, buf + offset, len);
400 /* Auxiliary function used by qsort to sort processes by process
401 group. Compares two processes with ids PROCESS1 and PROCESS2.
402 PROCESS1 comes before PROCESS2 if it has a lower process group id.
403 If they belong to the same process group, PROCESS1 comes before
404 PROCESS2 if it has a lower process id or is the process group
408 compare_processes (const void *process1, const void *process2)
410 PID_T pid1 = *((PID_T *) process1);
411 PID_T pid2 = *((PID_T *) process2);
412 PID_T pgid1 = *((PID_T *) process1 + 1);
413 PID_T pgid2 = *((PID_T *) process2 + 1);
418 else if (pgid1 > pgid2)
422 /* Process group leaders always come first, else sort by PID. */
425 else if (pid2 == pgid2)
427 else if (pid1 < pid2)
429 else if (pid1 > pid2)
436 /* Collect all process groups from /proc. */
439 linux_xfer_osdata_processgroups (gdb_byte *readbuf,
440 ULONGEST offset, ULONGEST len)
442 /* We make the process list snapshot when the object starts to be read. */
443 static const char *buf;
444 static LONGEST len_avail = -1;
445 static struct buffer buffer;
451 if (len_avail != -1 && len_avail != 0)
452 buffer_free (&buffer);
455 buffer_init (&buffer);
456 buffer_grow_str (&buffer, "<osdata type=\"process groups\">\n");
458 dirp = opendir ("/proc");
462 const size_t list_block_size = 512;
463 PID_T *process_list = (PID_T *) xmalloc (list_block_size * 2 * sizeof (PID_T));
464 size_t process_count = 0;
467 /* Build list consisting of PIDs followed by their
469 while ((dp = readdir (dirp)) != NULL)
473 if (!isdigit (dp->d_name[0])
474 || NAMELEN (dp) > MAX_PID_T_STRLEN)
477 sscanf (dp->d_name, "%lld", &pid);
478 pgid = getpgid (pid);
482 process_list[2 * process_count] = pid;
483 process_list[2 * process_count + 1] = pgid;
486 /* Increase the size of the list if necessary. */
487 if (process_count % list_block_size == 0)
488 process_list = (PID_T *) xrealloc (
490 (process_count + list_block_size)
491 * 2 * sizeof (PID_T));
497 /* Sort the process list. */
498 qsort (process_list, process_count, 2 * sizeof (PID_T),
501 for (i = 0; i < process_count; ++i)
503 PID_T pid = process_list[2 * i];
504 PID_T pgid = process_list[2 * i + 1];
505 char leader_command[32];
508 command_from_pid (leader_command, sizeof (leader_command), pgid);
509 command_line = commandline_from_pid (pid);
514 "<column name=\"pgid\">%lld</column>"
515 "<column name=\"leader command\">%s</column>"
516 "<column name=\"pid\">%lld</column>"
517 "<column name=\"command line\">%s</column>"
522 command_line ? command_line : "");
524 xfree (command_line);
527 xfree (process_list);
530 buffer_grow_str0 (&buffer, "</osdata>\n");
531 buf = buffer_finish (&buffer);
532 len_avail = strlen (buf);
535 if (offset >= len_avail)
537 /* Done. Get rid of the buffer. */
538 buffer_free (&buffer);
544 if (len > len_avail - offset)
545 len = len_avail - offset;
546 memcpy (readbuf, buf + offset, len);
551 /* Collect all the threads in /proc by iterating through processes and
552 then tasks within each process. */
555 linux_xfer_osdata_threads (gdb_byte *readbuf,
556 ULONGEST offset, ULONGEST len)
558 /* We make the process list snapshot when the object starts to be read. */
559 static const char *buf;
560 static LONGEST len_avail = -1;
561 static struct buffer buffer;
567 if (len_avail != -1 && len_avail != 0)
568 buffer_free (&buffer);
571 buffer_init (&buffer);
572 buffer_grow_str (&buffer, "<osdata type=\"threads\">\n");
574 dirp = opendir ("/proc");
579 while ((dp = readdir (dirp)) != NULL)
582 char procentry[sizeof ("/proc/4294967295")];
584 if (!isdigit (dp->d_name[0])
585 || NAMELEN (dp) > sizeof ("4294967295") - 1)
588 sprintf (procentry, "/proc/%s", dp->d_name);
589 if (stat (procentry, &statbuf) == 0
590 && S_ISDIR (statbuf.st_mode))
597 pathname = xstrprintf ("/proc/%s/task", dp->d_name);
599 pid = atoi (dp->d_name);
600 command_from_pid (command, sizeof (command), pid);
602 dirp2 = opendir (pathname);
608 while ((dp2 = readdir (dirp2)) != NULL)
613 if (!isdigit (dp2->d_name[0])
614 || NAMELEN (dp2) > sizeof ("4294967295") - 1)
617 tid = atoi (dp2->d_name);
618 core = linux_common_core_of_thread (ptid_build (pid, tid, 0));
623 "<column name=\"pid\">%lld</column>"
624 "<column name=\"command\">%s</column>"
625 "<column name=\"tid\">%lld</column>"
626 "<column name=\"core\">%d</column>"
644 buffer_grow_str0 (&buffer, "</osdata>\n");
645 buf = buffer_finish (&buffer);
646 len_avail = strlen (buf);
649 if (offset >= len_avail)
651 /* Done. Get rid of the buffer. */
652 buffer_free (&buffer);
658 if (len > len_avail - offset)
659 len = len_avail - offset;
660 memcpy (readbuf, buf + offset, len);
665 /* Collect all the open file descriptors found in /proc and put the details
666 found about them into READBUF. */
669 linux_xfer_osdata_fds (gdb_byte *readbuf,
670 ULONGEST offset, ULONGEST len)
672 /* We make the process list snapshot when the object starts to be read. */
673 static const char *buf;
674 static LONGEST len_avail = -1;
675 static struct buffer buffer;
681 if (len_avail != -1 && len_avail != 0)
682 buffer_free (&buffer);
685 buffer_init (&buffer);
686 buffer_grow_str (&buffer, "<osdata type=\"files\">\n");
688 dirp = opendir ("/proc");
693 while ((dp = readdir (dirp)) != NULL)
696 char procentry[sizeof ("/proc/4294967295")];
698 if (!isdigit (dp->d_name[0])
699 || NAMELEN (dp) > sizeof ("4294967295") - 1)
702 sprintf (procentry, "/proc/%s", dp->d_name);
703 if (stat (procentry, &statbuf) == 0
704 && S_ISDIR (statbuf.st_mode))
711 pid = atoi (dp->d_name);
712 command_from_pid (command, sizeof (command), pid);
714 pathname = xstrprintf ("/proc/%s/fd", dp->d_name);
715 dirp2 = opendir (pathname);
721 while ((dp2 = readdir (dirp2)) != NULL)
727 if (!isdigit (dp2->d_name[0]))
730 fdname = xstrprintf ("%s/%s", pathname, dp2->d_name);
731 rslt = readlink (fdname, buf, sizeof (buf) - 1);
738 "<column name=\"pid\">%s</column>"
739 "<column name=\"command\">%s</column>"
740 "<column name=\"file descriptor\">%s</column>"
741 "<column name=\"name\">%s</column>"
746 (rslt >= 0 ? buf : dp2->d_name));
759 buffer_grow_str0 (&buffer, "</osdata>\n");
760 buf = buffer_finish (&buffer);
761 len_avail = strlen (buf);
764 if (offset >= len_avail)
766 /* Done. Get rid of the buffer. */
767 buffer_free (&buffer);
773 if (len > len_avail - offset)
774 len = len_avail - offset;
775 memcpy (readbuf, buf + offset, len);
780 /* Returns the socket state STATE in textual form. */
783 format_socket_state (unsigned char state)
785 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
802 case TCP_ESTABLISHED:
803 return "ESTABLISHED";
832 struct sockaddr_in sin;
833 struct sockaddr_in6 sin6;
836 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
837 information for all open internet sockets of type FAMILY on the
838 system into BUFFER. If TCP is set, only TCP sockets are processed,
839 otherwise only UDP sockets are processed. */
842 print_sockets (unsigned short family, int tcp, struct buffer *buffer)
844 const char *proc_file;
847 if (family == AF_INET)
848 proc_file = tcp ? "/proc/net/tcp" : "/proc/net/udp";
849 else if (family == AF_INET6)
850 proc_file = tcp ? "/proc/net/tcp6" : "/proc/net/udp6";
854 fp = gdb_fopen_cloexec (proc_file, "r");
861 if (fgets (buf, sizeof (buf), fp))
864 unsigned int local_port, remote_port, state;
865 char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
869 #error "local_address and remote_address buffers too small"
872 result = sscanf (buf,
873 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
874 local_address, &local_port,
875 remote_address, &remote_port,
881 union socket_addr locaddr, remaddr;
883 char user[UT_NAMESIZE];
884 char local_service[NI_MAXSERV], remote_service[NI_MAXSERV];
886 if (family == AF_INET)
888 sscanf (local_address, "%X",
889 &locaddr.sin.sin_addr.s_addr);
890 sscanf (remote_address, "%X",
891 &remaddr.sin.sin_addr.s_addr);
893 locaddr.sin.sin_port = htons (local_port);
894 remaddr.sin.sin_port = htons (remote_port);
896 addr_size = sizeof (struct sockaddr_in);
900 sscanf (local_address, "%8X%8X%8X%8X",
901 locaddr.sin6.sin6_addr.s6_addr32,
902 locaddr.sin6.sin6_addr.s6_addr32 + 1,
903 locaddr.sin6.sin6_addr.s6_addr32 + 2,
904 locaddr.sin6.sin6_addr.s6_addr32 + 3);
905 sscanf (remote_address, "%8X%8X%8X%8X",
906 remaddr.sin6.sin6_addr.s6_addr32,
907 remaddr.sin6.sin6_addr.s6_addr32 + 1,
908 remaddr.sin6.sin6_addr.s6_addr32 + 2,
909 remaddr.sin6.sin6_addr.s6_addr32 + 3);
911 locaddr.sin6.sin6_port = htons (local_port);
912 remaddr.sin6.sin6_port = htons (remote_port);
914 locaddr.sin6.sin6_flowinfo = 0;
915 remaddr.sin6.sin6_flowinfo = 0;
916 locaddr.sin6.sin6_scope_id = 0;
917 remaddr.sin6.sin6_scope_id = 0;
919 addr_size = sizeof (struct sockaddr_in6);
922 locaddr.sa.sa_family = remaddr.sa.sa_family = family;
924 result = getnameinfo (&locaddr.sa, addr_size,
925 local_address, sizeof (local_address),
926 local_service, sizeof (local_service),
927 NI_NUMERICHOST | NI_NUMERICSERV
928 | (tcp ? 0 : NI_DGRAM));
932 result = getnameinfo (&remaddr.sa, addr_size,
934 sizeof (remote_address),
936 sizeof (remote_service),
937 NI_NUMERICHOST | NI_NUMERICSERV
938 | (tcp ? 0 : NI_DGRAM));
942 user_from_uid (user, sizeof (user), uid);
947 "<column name=\"local address\">%s</column>"
948 "<column name=\"local port\">%s</column>"
949 "<column name=\"remote address\">%s</column>"
950 "<column name=\"remote port\">%s</column>"
951 "<column name=\"state\">%s</column>"
952 "<column name=\"user\">%s</column>"
953 "<column name=\"family\">%s</column>"
954 "<column name=\"protocol\">%s</column>"
960 format_socket_state (state),
962 (family == AF_INET) ? "INET" : "INET6",
963 tcp ? "STREAM" : "DGRAM");
973 /* Collect data about internet sockets and write it into READBUF. */
976 linux_xfer_osdata_isockets (gdb_byte *readbuf,
977 ULONGEST offset, ULONGEST len)
979 static const char *buf;
980 static LONGEST len_avail = -1;
981 static struct buffer buffer;
985 if (len_avail != -1 && len_avail != 0)
986 buffer_free (&buffer);
989 buffer_init (&buffer);
990 buffer_grow_str (&buffer, "<osdata type=\"I sockets\">\n");
992 print_sockets (AF_INET, 1, &buffer);
993 print_sockets (AF_INET, 0, &buffer);
994 print_sockets (AF_INET6, 1, &buffer);
995 print_sockets (AF_INET6, 0, &buffer);
997 buffer_grow_str0 (&buffer, "</osdata>\n");
998 buf = buffer_finish (&buffer);
999 len_avail = strlen (buf);
1002 if (offset >= len_avail)
1004 /* Done. Get rid of the buffer. */
1005 buffer_free (&buffer);
1011 if (len > len_avail - offset)
1012 len = len_avail - offset;
1013 memcpy (readbuf, buf + offset, len);
1018 /* Converts the time SECONDS into textual form and copies it into a
1019 buffer TIME, with at most MAXLEN characters copied. */
1022 time_from_time_t (char *time, int maxlen, TIME_T seconds)
1028 time_t t = (time_t) seconds;
1030 strncpy (time, ctime (&t), maxlen);
1031 time[maxlen - 1] = '\0';
1035 /* Finds the group name for the group GID and copies it into GROUP.
1036 At most MAXLEN characters are copied. */
1039 group_from_gid (char *group, int maxlen, gid_t gid)
1041 struct group *grentry = getgrgid (gid);
1045 strncpy (group, grentry->gr_name, maxlen);
1046 /* Ensure that the group name is null-terminated. */
1047 group[maxlen - 1] = '\0';
1053 /* Collect data about shared memory recorded in /proc and write it
1057 linux_xfer_osdata_shm (gdb_byte *readbuf,
1058 ULONGEST offset, ULONGEST len)
1060 static const char *buf;
1061 static LONGEST len_avail = -1;
1062 static struct buffer buffer;
1068 if (len_avail != -1 && len_avail != 0)
1069 buffer_free (&buffer);
1072 buffer_init (&buffer);
1073 buffer_grow_str (&buffer, "<osdata type=\"shared memory\">\n");
1075 fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1082 if (fgets (buf, sizeof (buf), fp))
1088 int shmid, size, nattch;
1089 TIME_T atime, dtime, ctime;
1093 items_read = sscanf (buf,
1094 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1095 &key, &shmid, &perms, &size,
1098 &uid, &gid, &cuid, &cgid,
1099 &atime, &dtime, &ctime);
1101 if (items_read == 14)
1103 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1104 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1105 char ccmd[32], lcmd[32];
1106 char atime_str[32], dtime_str[32], ctime_str[32];
1108 user_from_uid (user, sizeof (user), uid);
1109 group_from_gid (group, sizeof (group), gid);
1110 user_from_uid (cuser, sizeof (cuser), cuid);
1111 group_from_gid (cgroup, sizeof (cgroup), cgid);
1113 command_from_pid (ccmd, sizeof (ccmd), cpid);
1114 command_from_pid (lcmd, sizeof (lcmd), lpid);
1116 time_from_time_t (atime_str, sizeof (atime_str), atime);
1117 time_from_time_t (dtime_str, sizeof (dtime_str), dtime);
1118 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1123 "<column name=\"key\">%d</column>"
1124 "<column name=\"shmid\">%d</column>"
1125 "<column name=\"permissions\">%o</column>"
1126 "<column name=\"size\">%d</column>"
1127 "<column name=\"creator command\">%s</column>"
1128 "<column name=\"last op. command\">%s</column>"
1129 "<column name=\"num attached\">%d</column>"
1130 "<column name=\"user\">%s</column>"
1131 "<column name=\"group\">%s</column>"
1132 "<column name=\"creator user\">%s</column>"
1133 "<column name=\"creator group\">%s</column>"
1134 "<column name=\"last shmat() time\">%s</column>"
1135 "<column name=\"last shmdt() time\">%s</column>"
1136 "<column name=\"last shmctl() time\">%s</column>"
1160 buffer_grow_str0 (&buffer, "</osdata>\n");
1161 buf = buffer_finish (&buffer);
1162 len_avail = strlen (buf);
1165 if (offset >= len_avail)
1167 /* Done. Get rid of the buffer. */
1168 buffer_free (&buffer);
1174 if (len > len_avail - offset)
1175 len = len_avail - offset;
1176 memcpy (readbuf, buf + offset, len);
1181 /* Collect data about semaphores recorded in /proc and write it
1185 linux_xfer_osdata_sem (gdb_byte *readbuf,
1186 ULONGEST offset, ULONGEST len)
1188 static const char *buf;
1189 static LONGEST len_avail = -1;
1190 static struct buffer buffer;
1196 if (len_avail != -1 && len_avail != 0)
1197 buffer_free (&buffer);
1200 buffer_init (&buffer);
1201 buffer_grow_str (&buffer, "<osdata type=\"semaphores\">\n");
1203 fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1210 if (fgets (buf, sizeof (buf), fp))
1215 unsigned int perms, nsems;
1217 TIME_T otime, ctime;
1220 items_read = sscanf (buf,
1221 "%d %d %o %u %d %d %d %d %lld %lld",
1222 &key, &semid, &perms, &nsems,
1223 &uid, &gid, &cuid, &cgid,
1226 if (items_read == 10)
1228 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1229 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1230 char otime_str[32], ctime_str[32];
1232 user_from_uid (user, sizeof (user), uid);
1233 group_from_gid (group, sizeof (group), gid);
1234 user_from_uid (cuser, sizeof (cuser), cuid);
1235 group_from_gid (cgroup, sizeof (cgroup), cgid);
1237 time_from_time_t (otime_str, sizeof (otime_str), otime);
1238 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1243 "<column name=\"key\">%d</column>"
1244 "<column name=\"semid\">%d</column>"
1245 "<column name=\"permissions\">%o</column>"
1246 "<column name=\"num semaphores\">%u</column>"
1247 "<column name=\"user\">%s</column>"
1248 "<column name=\"group\">%s</column>"
1249 "<column name=\"creator user\">%s</column>"
1250 "<column name=\"creator group\">%s</column>"
1251 "<column name=\"last semop() time\">%s</column>"
1252 "<column name=\"last semctl() time\">%s</column>"
1272 buffer_grow_str0 (&buffer, "</osdata>\n");
1273 buf = buffer_finish (&buffer);
1274 len_avail = strlen (buf);
1277 if (offset >= len_avail)
1279 /* Done. Get rid of the buffer. */
1280 buffer_free (&buffer);
1286 if (len > len_avail - offset)
1287 len = len_avail - offset;
1288 memcpy (readbuf, buf + offset, len);
1293 /* Collect data about message queues recorded in /proc and write it
1297 linux_xfer_osdata_msg (gdb_byte *readbuf,
1298 ULONGEST offset, ULONGEST len)
1300 static const char *buf;
1301 static LONGEST len_avail = -1;
1302 static struct buffer buffer;
1308 if (len_avail != -1 && len_avail != 0)
1309 buffer_free (&buffer);
1312 buffer_init (&buffer);
1313 buffer_grow_str (&buffer, "<osdata type=\"message queues\">\n");
1315 fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1322 if (fgets (buf, sizeof (buf), fp))
1328 unsigned int perms, cbytes, qnum;
1330 TIME_T stime, rtime, ctime;
1333 items_read = sscanf (buf,
1334 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1335 &key, &msqid, &perms, &cbytes, &qnum,
1336 &lspid, &lrpid, &uid, &gid, &cuid, &cgid,
1337 &stime, &rtime, &ctime);
1339 if (items_read == 14)
1341 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1342 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1343 char lscmd[32], lrcmd[32];
1344 char stime_str[32], rtime_str[32], ctime_str[32];
1346 user_from_uid (user, sizeof (user), uid);
1347 group_from_gid (group, sizeof (group), gid);
1348 user_from_uid (cuser, sizeof (cuser), cuid);
1349 group_from_gid (cgroup, sizeof (cgroup), cgid);
1351 command_from_pid (lscmd, sizeof (lscmd), lspid);
1352 command_from_pid (lrcmd, sizeof (lrcmd), lrpid);
1354 time_from_time_t (stime_str, sizeof (stime_str), stime);
1355 time_from_time_t (rtime_str, sizeof (rtime_str), rtime);
1356 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1361 "<column name=\"key\">%d</column>"
1362 "<column name=\"msqid\">%d</column>"
1363 "<column name=\"permissions\">%o</column>"
1364 "<column name=\"num used bytes\">%u</column>"
1365 "<column name=\"num messages\">%u</column>"
1366 "<column name=\"last msgsnd() command\">%s</column>"
1367 "<column name=\"last msgrcv() command\">%s</column>"
1368 "<column name=\"user\">%s</column>"
1369 "<column name=\"group\">%s</column>"
1370 "<column name=\"creator user\">%s</column>"
1371 "<column name=\"creator group\">%s</column>"
1372 "<column name=\"last msgsnd() time\">%s</column>"
1373 "<column name=\"last msgrcv() time\">%s</column>"
1374 "<column name=\"last msgctl() time\">%s</column>"
1398 buffer_grow_str0 (&buffer, "</osdata>\n");
1399 buf = buffer_finish (&buffer);
1400 len_avail = strlen (buf);
1403 if (offset >= len_avail)
1405 /* Done. Get rid of the buffer. */
1406 buffer_free (&buffer);
1412 if (len > len_avail - offset)
1413 len = len_avail - offset;
1414 memcpy (readbuf, buf + offset, len);
1419 /* Collect data about loaded kernel modules and write it into
1423 linux_xfer_osdata_modules (gdb_byte *readbuf,
1424 ULONGEST offset, ULONGEST len)
1426 static const char *buf;
1427 static LONGEST len_avail = -1;
1428 static struct buffer buffer;
1434 if (len_avail != -1 && len_avail != 0)
1435 buffer_free (&buffer);
1438 buffer_init (&buffer);
1439 buffer_grow_str (&buffer, "<osdata type=\"modules\">\n");
1441 fp = gdb_fopen_cloexec ("/proc/modules", "r");
1448 if (fgets (buf, sizeof (buf), fp))
1450 char *name, *dependencies, *status, *tmp;
1452 unsigned long long address;
1455 name = strtok (buf, " ");
1459 tmp = strtok (NULL, " ");
1462 if (sscanf (tmp, "%u", &size) != 1)
1465 tmp = strtok (NULL, " ");
1468 if (sscanf (tmp, "%d", &uses) != 1)
1471 dependencies = strtok (NULL, " ");
1472 if (dependencies == NULL)
1475 status = strtok (NULL, " ");
1479 tmp = strtok (NULL, "\n");
1482 if (sscanf (tmp, "%llx", &address) != 1)
1488 "<column name=\"name\">%s</column>"
1489 "<column name=\"size\">%u</column>"
1490 "<column name=\"num uses\">%d</column>"
1491 "<column name=\"dependencies\">%s</column>"
1492 "<column name=\"status\">%s</column>"
1493 "<column name=\"address\">%llx</column>"
1508 buffer_grow_str0 (&buffer, "</osdata>\n");
1509 buf = buffer_finish (&buffer);
1510 len_avail = strlen (buf);
1513 if (offset >= len_avail)
1515 /* Done. Get rid of the buffer. */
1516 buffer_free (&buffer);
1522 if (len > len_avail - offset)
1523 len = len_avail - offset;
1524 memcpy (readbuf, buf + offset, len);
1529 struct osdata_type {
1533 LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
1534 } osdata_table[] = {
1535 { "processes", "Processes", "Listing of all processes",
1536 linux_xfer_osdata_processes },
1537 { "procgroups", "Process groups", "Listing of all process groups",
1538 linux_xfer_osdata_processgroups },
1539 { "threads", "Threads", "Listing of all threads",
1540 linux_xfer_osdata_threads },
1541 { "files", "File descriptors", "Listing of all file descriptors",
1542 linux_xfer_osdata_fds },
1543 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1544 linux_xfer_osdata_isockets },
1545 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1546 linux_xfer_osdata_shm },
1547 { "semaphores", "Semaphores", "Listing of all semaphores",
1548 linux_xfer_osdata_sem },
1549 { "msg", "Message queues", "Listing of all message queues",
1550 linux_xfer_osdata_msg },
1551 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1552 linux_xfer_osdata_modules },
1553 { NULL, NULL, NULL }
1557 linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
1558 ULONGEST offset, ULONGEST len)
1560 if (!annex || *annex == '\0')
1562 static const char *buf;
1563 static LONGEST len_avail = -1;
1564 static struct buffer buffer;
1570 if (len_avail != -1 && len_avail != 0)
1571 buffer_free (&buffer);
1574 buffer_init (&buffer);
1575 buffer_grow_str (&buffer, "<osdata type=\"types\">\n");
1577 for (i = 0; osdata_table[i].type; ++i)
1581 "<column name=\"Type\">%s</column>"
1582 "<column name=\"Description\">%s</column>"
1583 "<column name=\"Title\">%s</column>"
1585 osdata_table[i].type,
1586 osdata_table[i].description,
1587 osdata_table[i].title);
1589 buffer_grow_str0 (&buffer, "</osdata>\n");
1590 buf = buffer_finish (&buffer);
1591 len_avail = strlen (buf);
1594 if (offset >= len_avail)
1596 /* Done. Get rid of the buffer. */
1597 buffer_free (&buffer);
1603 if (len > len_avail - offset)
1604 len = len_avail - offset;
1605 memcpy (readbuf, buf + offset, len);
1613 for (i = 0; osdata_table[i].type; ++i)
1615 if (strcmp (annex, osdata_table[i].type) == 0)
1617 gdb_assert (readbuf);
1619 return (osdata_table[i].getter) (readbuf, offset, len);