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 %17s", &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 int local_port, remote_port, state;
875 char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
879 #error "local_address and remote_address buffers too small"
882 result = sscanf (buf,
883 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
884 local_address, &local_port,
885 remote_address, &remote_port,
891 union socket_addr locaddr, remaddr;
893 char user[UT_NAMESIZE];
894 char local_service[NI_MAXSERV], remote_service[NI_MAXSERV];
896 if (family == AF_INET)
898 sscanf (local_address, "%X",
899 &locaddr.sin.sin_addr.s_addr);
900 sscanf (remote_address, "%X",
901 &remaddr.sin.sin_addr.s_addr);
903 locaddr.sin.sin_port = htons (local_port);
904 remaddr.sin.sin_port = htons (remote_port);
906 addr_size = sizeof (struct sockaddr_in);
910 sscanf (local_address, "%8X%8X%8X%8X",
911 locaddr.sin6.sin6_addr.s6_addr32,
912 locaddr.sin6.sin6_addr.s6_addr32 + 1,
913 locaddr.sin6.sin6_addr.s6_addr32 + 2,
914 locaddr.sin6.sin6_addr.s6_addr32 + 3);
915 sscanf (remote_address, "%8X%8X%8X%8X",
916 remaddr.sin6.sin6_addr.s6_addr32,
917 remaddr.sin6.sin6_addr.s6_addr32 + 1,
918 remaddr.sin6.sin6_addr.s6_addr32 + 2,
919 remaddr.sin6.sin6_addr.s6_addr32 + 3);
921 locaddr.sin6.sin6_port = htons (local_port);
922 remaddr.sin6.sin6_port = htons (remote_port);
924 locaddr.sin6.sin6_flowinfo = 0;
925 remaddr.sin6.sin6_flowinfo = 0;
926 locaddr.sin6.sin6_scope_id = 0;
927 remaddr.sin6.sin6_scope_id = 0;
929 addr_size = sizeof (struct sockaddr_in6);
932 locaddr.sa.sa_family = remaddr.sa.sa_family = family;
934 result = getnameinfo (&locaddr.sa, addr_size,
935 local_address, sizeof (local_address),
936 local_service, sizeof (local_service),
937 NI_NUMERICHOST | NI_NUMERICSERV
938 | (tcp ? 0 : NI_DGRAM));
942 result = getnameinfo (&remaddr.sa, addr_size,
944 sizeof (remote_address),
946 sizeof (remote_service),
947 NI_NUMERICHOST | NI_NUMERICSERV
948 | (tcp ? 0 : NI_DGRAM));
952 user_from_uid (user, sizeof (user), uid);
957 "<column name=\"local address\">%s</column>"
958 "<column name=\"local port\">%s</column>"
959 "<column name=\"remote address\">%s</column>"
960 "<column name=\"remote port\">%s</column>"
961 "<column name=\"state\">%s</column>"
962 "<column name=\"user\">%s</column>"
963 "<column name=\"family\">%s</column>"
964 "<column name=\"protocol\">%s</column>"
970 format_socket_state (state),
972 (family == AF_INET) ? "INET" : "INET6",
973 tcp ? "STREAM" : "DGRAM");
983 /* Collect data about internet sockets and write it into READBUF. */
986 linux_xfer_osdata_isockets (gdb_byte *readbuf,
987 ULONGEST offset, LONGEST len)
989 static const char *buf;
990 static LONGEST len_avail = -1;
991 static struct buffer buffer;
995 if (len_avail != -1 && len_avail != 0)
996 buffer_free (&buffer);
999 buffer_init (&buffer);
1000 buffer_grow_str (&buffer, "<osdata type=\"I sockets\">\n");
1002 print_sockets (AF_INET, 1, &buffer);
1003 print_sockets (AF_INET, 0, &buffer);
1004 print_sockets (AF_INET6, 1, &buffer);
1005 print_sockets (AF_INET6, 0, &buffer);
1007 buffer_grow_str0 (&buffer, "</osdata>\n");
1008 buf = buffer_finish (&buffer);
1009 len_avail = strlen (buf);
1012 if (offset >= len_avail)
1014 /* Done. Get rid of the buffer. */
1015 buffer_free (&buffer);
1021 if (len > len_avail - offset)
1022 len = len_avail - offset;
1023 memcpy (readbuf, buf + offset, len);
1028 /* Converts the time SECONDS into textual form and copies it into a
1029 buffer TIME, with at most MAXLEN characters copied. */
1032 time_from_time_t (char *time, int maxlen, TIME_T seconds)
1038 time_t t = (time_t) seconds;
1040 strncpy (time, ctime (&t), maxlen);
1041 time[maxlen - 1] = '\0';
1045 /* Finds the group name for the group GID and copies it into GROUP.
1046 At most MAXLEN characters are copied. */
1049 group_from_gid (char *group, int maxlen, gid_t gid)
1051 struct group *grentry = getgrgid (gid);
1055 strncpy (group, grentry->gr_name, maxlen);
1056 /* Ensure that the group name is null-terminated. */
1057 group[maxlen - 1] = '\0';
1063 /* Collect data about shared memory recorded in /proc and write it
1067 linux_xfer_osdata_shm (gdb_byte *readbuf,
1068 ULONGEST offset, LONGEST len)
1070 static const char *buf;
1071 static LONGEST len_avail = -1;
1072 static struct buffer buffer;
1078 if (len_avail != -1 && len_avail != 0)
1079 buffer_free (&buffer);
1082 buffer_init (&buffer);
1083 buffer_grow_str (&buffer, "<osdata type=\"shared memory\">\n");
1085 fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1092 if (fgets (buf, sizeof (buf), fp))
1098 int shmid, size, nattch;
1099 TIME_T atime, dtime, ctime;
1103 items_read = sscanf (buf,
1104 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1105 &key, &shmid, &perms, &size,
1108 &uid, &gid, &cuid, &cgid,
1109 &atime, &dtime, &ctime);
1111 if (items_read == 14)
1113 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1114 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1115 char ccmd[32], lcmd[32];
1116 char atime_str[32], dtime_str[32], ctime_str[32];
1118 user_from_uid (user, sizeof (user), uid);
1119 group_from_gid (group, sizeof (group), gid);
1120 user_from_uid (cuser, sizeof (cuser), cuid);
1121 group_from_gid (cgroup, sizeof (cgroup), cgid);
1123 command_from_pid (ccmd, sizeof (ccmd), cpid);
1124 command_from_pid (lcmd, sizeof (lcmd), lpid);
1126 time_from_time_t (atime_str, sizeof (atime_str), atime);
1127 time_from_time_t (dtime_str, sizeof (dtime_str), dtime);
1128 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1133 "<column name=\"key\">%d</column>"
1134 "<column name=\"shmid\">%d</column>"
1135 "<column name=\"permissions\">%o</column>"
1136 "<column name=\"size\">%d</column>"
1137 "<column name=\"creator command\">%s</column>"
1138 "<column name=\"last op. command\">%s</column>"
1139 "<column name=\"num attached\">%d</column>"
1140 "<column name=\"user\">%s</column>"
1141 "<column name=\"group\">%s</column>"
1142 "<column name=\"creator user\">%s</column>"
1143 "<column name=\"creator group\">%s</column>"
1144 "<column name=\"last shmat() time\">%s</column>"
1145 "<column name=\"last shmdt() time\">%s</column>"
1146 "<column name=\"last shmctl() time\">%s</column>"
1170 buffer_grow_str0 (&buffer, "</osdata>\n");
1171 buf = buffer_finish (&buffer);
1172 len_avail = strlen (buf);
1175 if (offset >= len_avail)
1177 /* Done. Get rid of the buffer. */
1178 buffer_free (&buffer);
1184 if (len > len_avail - offset)
1185 len = len_avail - offset;
1186 memcpy (readbuf, buf + offset, len);
1191 /* Collect data about semaphores recorded in /proc and write it
1195 linux_xfer_osdata_sem (gdb_byte *readbuf,
1196 ULONGEST offset, LONGEST len)
1198 static const char *buf;
1199 static LONGEST len_avail = -1;
1200 static struct buffer buffer;
1206 if (len_avail != -1 && len_avail != 0)
1207 buffer_free (&buffer);
1210 buffer_init (&buffer);
1211 buffer_grow_str (&buffer, "<osdata type=\"semaphores\">\n");
1213 fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1220 if (fgets (buf, sizeof (buf), fp))
1225 unsigned int perms, nsems;
1227 TIME_T otime, ctime;
1230 items_read = sscanf (buf,
1231 "%d %d %o %u %d %d %d %d %lld %lld",
1232 &key, &semid, &perms, &nsems,
1233 &uid, &gid, &cuid, &cgid,
1236 if (items_read == 10)
1238 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1239 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1240 char otime_str[32], ctime_str[32];
1242 user_from_uid (user, sizeof (user), uid);
1243 group_from_gid (group, sizeof (group), gid);
1244 user_from_uid (cuser, sizeof (cuser), cuid);
1245 group_from_gid (cgroup, sizeof (cgroup), cgid);
1247 time_from_time_t (otime_str, sizeof (otime_str), otime);
1248 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1253 "<column name=\"key\">%d</column>"
1254 "<column name=\"semid\">%d</column>"
1255 "<column name=\"permissions\">%o</column>"
1256 "<column name=\"num semaphores\">%u</column>"
1257 "<column name=\"user\">%s</column>"
1258 "<column name=\"group\">%s</column>"
1259 "<column name=\"creator user\">%s</column>"
1260 "<column name=\"creator group\">%s</column>"
1261 "<column name=\"last semop() time\">%s</column>"
1262 "<column name=\"last semctl() time\">%s</column>"
1282 buffer_grow_str0 (&buffer, "</osdata>\n");
1283 buf = buffer_finish (&buffer);
1284 len_avail = strlen (buf);
1287 if (offset >= len_avail)
1289 /* Done. Get rid of the buffer. */
1290 buffer_free (&buffer);
1296 if (len > len_avail - offset)
1297 len = len_avail - offset;
1298 memcpy (readbuf, buf + offset, len);
1303 /* Collect data about message queues recorded in /proc and write it
1307 linux_xfer_osdata_msg (gdb_byte *readbuf,
1308 ULONGEST offset, LONGEST len)
1310 static const char *buf;
1311 static LONGEST len_avail = -1;
1312 static struct buffer buffer;
1318 if (len_avail != -1 && len_avail != 0)
1319 buffer_free (&buffer);
1322 buffer_init (&buffer);
1323 buffer_grow_str (&buffer, "<osdata type=\"message queues\">\n");
1325 fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1332 if (fgets (buf, sizeof (buf), fp))
1338 unsigned int perms, cbytes, qnum;
1340 TIME_T stime, rtime, ctime;
1343 items_read = sscanf (buf,
1344 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1345 &key, &msqid, &perms, &cbytes, &qnum,
1346 &lspid, &lrpid, &uid, &gid, &cuid, &cgid,
1347 &stime, &rtime, &ctime);
1349 if (items_read == 14)
1351 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1352 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1353 char lscmd[32], lrcmd[32];
1354 char stime_str[32], rtime_str[32], ctime_str[32];
1356 user_from_uid (user, sizeof (user), uid);
1357 group_from_gid (group, sizeof (group), gid);
1358 user_from_uid (cuser, sizeof (cuser), cuid);
1359 group_from_gid (cgroup, sizeof (cgroup), cgid);
1361 command_from_pid (lscmd, sizeof (lscmd), lspid);
1362 command_from_pid (lrcmd, sizeof (lrcmd), lrpid);
1364 time_from_time_t (stime_str, sizeof (stime_str), stime);
1365 time_from_time_t (rtime_str, sizeof (rtime_str), rtime);
1366 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1371 "<column name=\"key\">%d</column>"
1372 "<column name=\"msqid\">%d</column>"
1373 "<column name=\"permissions\">%o</column>"
1374 "<column name=\"num used bytes\">%u</column>"
1375 "<column name=\"num messages\">%u</column>"
1376 "<column name=\"last msgsnd() command\">%s</column>"
1377 "<column name=\"last msgrcv() command\">%s</column>"
1378 "<column name=\"user\">%s</column>"
1379 "<column name=\"group\">%s</column>"
1380 "<column name=\"creator user\">%s</column>"
1381 "<column name=\"creator group\">%s</column>"
1382 "<column name=\"last msgsnd() time\">%s</column>"
1383 "<column name=\"last msgrcv() time\">%s</column>"
1384 "<column name=\"last msgctl() time\">%s</column>"
1408 buffer_grow_str0 (&buffer, "</osdata>\n");
1409 buf = buffer_finish (&buffer);
1410 len_avail = strlen (buf);
1413 if (offset >= len_avail)
1415 /* Done. Get rid of the buffer. */
1416 buffer_free (&buffer);
1422 if (len > len_avail - offset)
1423 len = len_avail - offset;
1424 memcpy (readbuf, buf + offset, len);
1429 /* Collect data about loaded kernel modules and write it into
1433 linux_xfer_osdata_modules (gdb_byte *readbuf,
1434 ULONGEST offset, LONGEST len)
1436 static const char *buf;
1437 static LONGEST len_avail = -1;
1438 static struct buffer buffer;
1444 if (len_avail != -1 && len_avail != 0)
1445 buffer_free (&buffer);
1448 buffer_init (&buffer);
1449 buffer_grow_str (&buffer, "<osdata type=\"modules\">\n");
1451 fp = gdb_fopen_cloexec ("/proc/modules", "r");
1458 if (fgets (buf, sizeof (buf), fp))
1460 char *name, *dependencies, *status, *tmp;
1462 unsigned long long address;
1465 name = strtok (buf, " ");
1469 tmp = strtok (NULL, " ");
1472 if (sscanf (tmp, "%u", &size) != 1)
1475 tmp = strtok (NULL, " ");
1478 if (sscanf (tmp, "%d", &uses) != 1)
1481 dependencies = strtok (NULL, " ");
1482 if (dependencies == NULL)
1485 status = strtok (NULL, " ");
1489 tmp = strtok (NULL, "\n");
1492 if (sscanf (tmp, "%llx", &address) != 1)
1498 "<column name=\"name\">%s</column>"
1499 "<column name=\"size\">%u</column>"
1500 "<column name=\"num uses\">%d</column>"
1501 "<column name=\"dependencies\">%s</column>"
1502 "<column name=\"status\">%s</column>"
1503 "<column name=\"address\">%llx</column>"
1518 buffer_grow_str0 (&buffer, "</osdata>\n");
1519 buf = buffer_finish (&buffer);
1520 len_avail = strlen (buf);
1523 if (offset >= len_avail)
1525 /* Done. Get rid of the buffer. */
1526 buffer_free (&buffer);
1532 if (len > len_avail - offset)
1533 len = len_avail - offset;
1534 memcpy (readbuf, buf + offset, len);
1539 struct osdata_type {
1543 LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, LONGEST len);
1544 } osdata_table[] = {
1545 { "processes", "Processes", "Listing of all processes",
1546 linux_xfer_osdata_processes },
1547 { "procgroups", "Process groups", "Listing of all process groups",
1548 linux_xfer_osdata_processgroups },
1549 { "threads", "Threads", "Listing of all threads",
1550 linux_xfer_osdata_threads },
1551 { "files", "File descriptors", "Listing of all file descriptors",
1552 linux_xfer_osdata_fds },
1553 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1554 linux_xfer_osdata_isockets },
1555 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1556 linux_xfer_osdata_shm },
1557 { "semaphores", "Semaphores", "Listing of all semaphores",
1558 linux_xfer_osdata_sem },
1559 { "msg", "Message queues", "Listing of all message queues",
1560 linux_xfer_osdata_msg },
1561 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1562 linux_xfer_osdata_modules },
1563 { NULL, NULL, NULL }
1567 linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
1568 ULONGEST offset, LONGEST len)
1570 if (!annex || *annex == '\0')
1572 static const char *buf;
1573 static LONGEST len_avail = -1;
1574 static struct buffer buffer;
1580 if (len_avail != -1 && len_avail != 0)
1581 buffer_free (&buffer);
1584 buffer_init (&buffer);
1585 buffer_grow_str (&buffer, "<osdata type=\"types\">\n");
1587 for (i = 0; osdata_table[i].type; ++i)
1591 "<column name=\"Type\">%s</column>"
1592 "<column name=\"Description\">%s</column>"
1593 "<column name=\"Title\">%s</column>"
1595 osdata_table[i].type,
1596 osdata_table[i].description,
1597 osdata_table[i].title);
1599 buffer_grow_str0 (&buffer, "</osdata>\n");
1600 buf = buffer_finish (&buffer);
1601 len_avail = strlen (buf);
1604 if (offset >= len_avail)
1606 /* Done. Get rid of the buffer. */
1607 buffer_free (&buffer);
1613 if (len > len_avail - offset)
1614 len = len_avail - offset;
1615 memcpy (readbuf, buf + offset, len);
1623 for (i = 0; osdata_table[i].type; ++i)
1625 if (strcmp (annex, osdata_table[i].type) == 0)
1627 gdb_assert (readbuf);
1629 return (osdata_table[i].getter) (readbuf, offset, len);