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>
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 /* Define PID_T to be a fixed size that is at least as large as pid_t,
48 so that reading pid values embedded in /proc works
51 typedef long long PID_T;
53 /* Define TIME_T to be at least as large as time_t, so that reading
54 time values embedded in /proc works consistently. */
56 typedef long long TIME_T;
58 #define MAX_PID_T_STRLEN (sizeof ("-9223372036854775808") - 1)
60 /* Returns the CPU core that thread PTID is currently running on. */
62 /* Compute and return the processor core of a given thread. */
65 linux_common_core_of_thread (ptid_t ptid)
67 char filename[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN];
76 sprintf (filename, "/proc/%lld/task/%lld/stat",
77 (PID_T) ptid_get_pid (ptid), (PID_T) ptid_get_lwp (ptid));
78 f = fopen (filename, "r");
85 content = xrealloc (content, content_read + 1024);
86 n = fread (content + content_read, 1, 1024, f);
90 content[content_read] = '\0';
95 p = strchr (content, '(');
103 /* If the first field after program name has index 0, then core number is
104 the field with index 36. There's no constant for that anywhere. */
106 p = strtok_r (p, " ", &ts);
107 for (i = 0; p != NULL && i != 36; ++i)
108 p = strtok_r (NULL, " ", &ts);
110 if (p == NULL || sscanf (p, "%d", &core) == 0)
119 /* Finds the command-line of process PID and copies it into COMMAND.
120 At most MAXLEN characters are copied. If the command-line cannot
121 be found, PID is copied into command in text-form. */
124 command_from_pid (char *command, int maxlen, PID_T pid)
126 char *stat_path = xstrprintf ("/proc/%lld/stat", pid);
127 FILE *fp = fopen (stat_path, "r");
133 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
134 include/linux/sched.h in the Linux kernel sources) plus two
135 (for the brackets). */
138 int items_read = fscanf (fp, "%lld %32s", &stat_pid, cmd);
140 if (items_read == 2 && pid == stat_pid)
142 cmd[strlen (cmd) - 1] = '\0'; /* Remove trailing parenthesis. */
143 strncpy (command, cmd + 1, maxlen); /* Ignore leading parenthesis. */
150 /* Return the PID if a /proc entry for the process cannot be found. */
151 snprintf (command, maxlen, "%lld", pid);
154 command[maxlen - 1] = '\0'; /* Ensure string is null-terminated. */
159 /* Returns the command-line of the process with the given PID. The
160 returned string needs to be freed using xfree after use. */
163 commandline_from_pid (PID_T pid)
165 char *pathname = xstrprintf ("/proc/%lld/cmdline", pid);
166 char *commandline = NULL;
167 FILE *f = fopen (pathname, "r");
176 size_t read_bytes = fread (buf, 1, sizeof (buf), f);
180 commandline = (char *) xrealloc (commandline, len + read_bytes + 1);
181 memcpy (commandline + len, buf, read_bytes);
192 /* Replace null characters with spaces. */
193 for (i = 0; i < len; ++i)
194 if (commandline[i] == '\0')
195 commandline[i] = ' ';
197 commandline[len] = '\0';
201 /* Return the command in square brackets if the command-line
203 commandline = (char *) xmalloc (32);
204 commandline[0] = '[';
205 command_from_pid (commandline + 1, 31, pid);
207 len = strlen (commandline);
209 strcat (commandline, "]");
218 /* Finds the user name for the user UID and copies it into USER. At
219 most MAXLEN characters are copied. */
222 user_from_uid (char *user, int maxlen, uid_t uid)
224 struct passwd *pwentry = getpwuid (uid);
228 strncpy (user, pwentry->pw_name, maxlen);
229 /* Ensure that the user name is null-terminated. */
230 user[maxlen - 1] = '\0';
236 /* Finds the owner of process PID and returns the user id in OWNER.
237 Returns 0 if the owner was found, -1 otherwise. */
240 get_process_owner (uid_t *owner, PID_T pid)
243 char procentry[sizeof ("/proc/") + MAX_PID_T_STRLEN];
245 sprintf (procentry, "/proc/%lld", pid);
247 if (stat (procentry, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))
249 *owner = statbuf.st_uid;
256 /* Returns the number of CPU cores found on the system. */
259 get_number_of_cpu_cores (void)
262 FILE *f = fopen ("/proc/cpuinfo", "r");
267 char *p = fgets (buf, sizeof (buf), f);
269 if (p && strncmp (buf, "processor", 9) == 0)
278 /* Find the CPU cores used by process PID and return them in CORES.
279 CORES points to an array of at least get_number_of_cpu_cores ()
283 get_cores_used_by_process (PID_T pid, int *cores)
285 char taskdir[sizeof ("/proc/") + MAX_PID_T_STRLEN + sizeof ("/task") - 1];
290 sprintf (taskdir, "/proc/%lld/task", pid);
291 dir = opendir (taskdir);
294 while ((dp = readdir (dir)) != NULL)
299 if (!isdigit (dp->d_name[0])
300 || NAMELEN (dp) > MAX_PID_T_STRLEN)
303 sscanf (dp->d_name, "%lld", &tid);
304 core = linux_common_core_of_thread (ptid_build ((pid_t) pid,
321 linux_xfer_osdata_processes (gdb_byte *readbuf,
322 ULONGEST offset, LONGEST len)
324 /* We make the process list snapshot when the object starts to be read. */
325 static const char *buf;
326 static LONGEST len_avail = -1;
327 static struct buffer buffer;
333 if (len_avail != -1 && len_avail != 0)
334 buffer_free (&buffer);
337 buffer_init (&buffer);
338 buffer_grow_str (&buffer, "<osdata type=\"processes\">\n");
340 dirp = opendir ("/proc");
343 const int num_cores = get_number_of_cpu_cores ();
346 while ((dp = readdir (dirp)) != NULL)
350 char user[UT_NAMESIZE];
357 if (!isdigit (dp->d_name[0])
358 || NAMELEN (dp) > MAX_PID_T_STRLEN)
361 sscanf (dp->d_name, "%lld", &pid);
362 command_line = commandline_from_pid (pid);
364 if (get_process_owner (&owner, pid) == 0)
365 user_from_uid (user, sizeof (user), owner);
369 /* Find CPU cores used by the process. */
370 cores = (int *) xcalloc (num_cores, sizeof (int));
371 task_count = get_cores_used_by_process (pid, cores);
372 cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1);
374 for (i = 0; i < num_cores && task_count > 0; ++i)
377 char core_str[sizeof ("4294967295")];
379 sprintf (core_str, "%d", i);
380 strcat (cores_str, core_str);
382 task_count -= cores[i];
384 strcat (cores_str, ",");
392 "<column name=\"pid\">%lld</column>"
393 "<column name=\"user\">%s</column>"
394 "<column name=\"command\">%s</column>"
395 "<column name=\"cores\">%s</column>"
399 command_line ? command_line : "",
402 xfree (command_line);
409 buffer_grow_str0 (&buffer, "</osdata>\n");
410 buf = buffer_finish (&buffer);
411 len_avail = strlen (buf);
414 if (offset >= len_avail)
416 /* Done. Get rid of the buffer. */
417 buffer_free (&buffer);
423 if (len > len_avail - offset)
424 len = len_avail - offset;
425 memcpy (readbuf, buf + offset, len);
430 /* Auxiliary function used by qsort to sort processes by process
431 group. Compares two processes with ids PROCESS1 and PROCESS2.
432 PROCESS1 comes before PROCESS2 if it has a lower process group id.
433 If they belong to the same process group, PROCESS1 comes before
434 PROCESS2 if it has a lower process id or is the process group
438 compare_processes (const void *process1, const void *process2)
440 PID_T pid1 = *((PID_T *) process1);
441 PID_T pid2 = *((PID_T *) process2);
442 PID_T pgid1 = *((PID_T *) process1 + 1);
443 PID_T pgid2 = *((PID_T *) process2 + 1);
448 else if (pgid1 > pgid2)
452 /* Process group leaders always come first, else sort by PID. */
455 else if (pid2 == pgid2)
457 else if (pid1 < pid2)
459 else if (pid1 > pid2)
466 /* Collect all process groups from /proc. */
469 linux_xfer_osdata_processgroups (gdb_byte *readbuf,
470 ULONGEST offset, LONGEST len)
472 /* We make the process list snapshot when the object starts to be read. */
473 static const char *buf;
474 static LONGEST len_avail = -1;
475 static struct buffer buffer;
481 if (len_avail != -1 && len_avail != 0)
482 buffer_free (&buffer);
485 buffer_init (&buffer);
486 buffer_grow_str (&buffer, "<osdata type=\"process groups\">\n");
488 dirp = opendir ("/proc");
492 const size_t list_block_size = 512;
493 PID_T *process_list = (PID_T *) xmalloc (list_block_size * 2 * sizeof (PID_T));
494 size_t process_count = 0;
497 /* Build list consisting of PIDs followed by their
499 while ((dp = readdir (dirp)) != NULL)
503 if (!isdigit (dp->d_name[0])
504 || NAMELEN (dp) > MAX_PID_T_STRLEN)
507 sscanf (dp->d_name, "%lld", &pid);
508 pgid = getpgid (pid);
512 process_list[2 * process_count] = pid;
513 process_list[2 * process_count + 1] = pgid;
516 /* Increase the size of the list if necessary. */
517 if (process_count % list_block_size == 0)
518 process_list = (PID_T *) xrealloc (
520 (process_count + list_block_size)
521 * 2 * sizeof (PID_T));
527 /* Sort the process list. */
528 qsort (process_list, process_count, 2 * sizeof (PID_T),
531 for (i = 0; i < process_count; ++i)
533 PID_T pid = process_list[2 * i];
534 PID_T pgid = process_list[2 * i + 1];
535 char leader_command[32];
538 command_from_pid (leader_command, sizeof (leader_command), pgid);
539 command_line = commandline_from_pid (pid);
544 "<column name=\"pgid\">%lld</column>"
545 "<column name=\"leader command\">%s</column>"
546 "<column name=\"pid\">%lld</column>"
547 "<column name=\"command line\">%s</column>"
552 command_line ? command_line : "");
554 xfree (command_line);
557 xfree (process_list);
560 buffer_grow_str0 (&buffer, "</osdata>\n");
561 buf = buffer_finish (&buffer);
562 len_avail = strlen (buf);
565 if (offset >= len_avail)
567 /* Done. Get rid of the buffer. */
568 buffer_free (&buffer);
574 if (len > len_avail - offset)
575 len = len_avail - offset;
576 memcpy (readbuf, buf + offset, len);
581 /* Collect all the threads in /proc by iterating through processes and
582 then tasks within each process. */
585 linux_xfer_osdata_threads (gdb_byte *readbuf,
586 ULONGEST offset, LONGEST len)
588 /* We make the process list snapshot when the object starts to be read. */
589 static const char *buf;
590 static LONGEST len_avail = -1;
591 static struct buffer buffer;
597 if (len_avail != -1 && len_avail != 0)
598 buffer_free (&buffer);
601 buffer_init (&buffer);
602 buffer_grow_str (&buffer, "<osdata type=\"threads\">\n");
604 dirp = opendir ("/proc");
609 while ((dp = readdir (dirp)) != NULL)
612 char procentry[sizeof ("/proc/4294967295")];
614 if (!isdigit (dp->d_name[0])
615 || NAMELEN (dp) > sizeof ("4294967295") - 1)
618 sprintf (procentry, "/proc/%s", dp->d_name);
619 if (stat (procentry, &statbuf) == 0
620 && S_ISDIR (statbuf.st_mode))
627 pathname = xstrprintf ("/proc/%s/task", dp->d_name);
629 pid = atoi (dp->d_name);
630 command_from_pid (command, sizeof (command), pid);
632 dirp2 = opendir (pathname);
638 while ((dp2 = readdir (dirp2)) != NULL)
643 if (!isdigit (dp2->d_name[0])
644 || NAMELEN (dp2) > sizeof ("4294967295") - 1)
647 tid = atoi (dp2->d_name);
648 core = linux_common_core_of_thread (ptid_build (pid, tid, 0));
653 "<column name=\"pid\">%lld</column>"
654 "<column name=\"command\">%s</column>"
655 "<column name=\"tid\">%lld</column>"
656 "<column name=\"core\">%d</column>"
674 buffer_grow_str0 (&buffer, "</osdata>\n");
675 buf = buffer_finish (&buffer);
676 len_avail = strlen (buf);
679 if (offset >= len_avail)
681 /* Done. Get rid of the buffer. */
682 buffer_free (&buffer);
688 if (len > len_avail - offset)
689 len = len_avail - offset;
690 memcpy (readbuf, buf + offset, len);
695 /* Collect all the open file descriptors found in /proc and put the details
696 found about them into READBUF. */
699 linux_xfer_osdata_fds (gdb_byte *readbuf,
700 ULONGEST offset, LONGEST len)
702 /* We make the process list snapshot when the object starts to be read. */
703 static const char *buf;
704 static LONGEST len_avail = -1;
705 static struct buffer buffer;
711 if (len_avail != -1 && len_avail != 0)
712 buffer_free (&buffer);
715 buffer_init (&buffer);
716 buffer_grow_str (&buffer, "<osdata type=\"files\">\n");
718 dirp = opendir ("/proc");
723 while ((dp = readdir (dirp)) != NULL)
726 char procentry[sizeof ("/proc/4294967295")];
728 if (!isdigit (dp->d_name[0])
729 || NAMELEN (dp) > sizeof ("4294967295") - 1)
732 sprintf (procentry, "/proc/%s", dp->d_name);
733 if (stat (procentry, &statbuf) == 0
734 && S_ISDIR (statbuf.st_mode))
741 pid = atoi (dp->d_name);
742 command_from_pid (command, sizeof (command), pid);
744 pathname = xstrprintf ("/proc/%s/fd", dp->d_name);
745 dirp2 = opendir (pathname);
751 while ((dp2 = readdir (dirp2)) != NULL)
757 if (!isdigit (dp2->d_name[0]))
760 fdname = xstrprintf ("%s/%s", pathname, dp2->d_name);
761 rslt = readlink (fdname, buf, 1000);
768 "<column name=\"pid\">%s</column>"
769 "<column name=\"command\">%s</column>"
770 "<column name=\"file descriptor\">%s</column>"
771 "<column name=\"name\">%s</column>"
776 (rslt >= 0 ? buf : dp2->d_name));
789 buffer_grow_str0 (&buffer, "</osdata>\n");
790 buf = buffer_finish (&buffer);
791 len_avail = strlen (buf);
794 if (offset >= len_avail)
796 /* Done. Get rid of the buffer. */
797 buffer_free (&buffer);
803 if (len > len_avail - offset)
804 len = len_avail - offset;
805 memcpy (readbuf, buf + offset, len);
810 /* Returns the socket state STATE in textual form. */
813 format_socket_state (unsigned char state)
815 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
832 case TCP_ESTABLISHED:
833 return "ESTABLISHED";
862 struct sockaddr_in sin;
863 struct sockaddr_in6 sin6;
866 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
867 information for all open internet sockets of type FAMILY on the
868 system into BUFFER. If TCP is set, only TCP sockets are processed,
869 otherwise only UDP sockets are processed. */
872 print_sockets (unsigned short family, int tcp, struct buffer *buffer)
874 const char *proc_file;
877 if (family == AF_INET)
878 proc_file = tcp ? "/proc/net/tcp" : "/proc/net/udp";
879 else if (family == AF_INET6)
880 proc_file = tcp ? "/proc/net/tcp6" : "/proc/net/udp6";
884 fp = fopen (proc_file, "r");
891 if (fgets (buf, sizeof (buf), fp))
894 unsigned long tlen, inode;
896 unsigned int local_port, remote_port, state;
897 unsigned int txq, rxq, trun, retn;
898 char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
902 result = sscanf (buf,
903 "%d: %33[0-9A-F]:%X %33[0-9A-F]:%X %X %X:%X %X:%lX %X %d %d %lu %512s\n",
905 local_address, &local_port,
906 remote_address, &remote_port,
918 union socket_addr locaddr, remaddr;
920 char user[UT_NAMESIZE];
921 char local_service[NI_MAXSERV], remote_service[NI_MAXSERV];
923 if (family == AF_INET)
925 sscanf (local_address, "%X",
926 &locaddr.sin.sin_addr.s_addr);
927 sscanf (remote_address, "%X",
928 &remaddr.sin.sin_addr.s_addr);
930 locaddr.sin.sin_port = htons (local_port);
931 remaddr.sin.sin_port = htons (remote_port);
933 addr_size = sizeof (struct sockaddr_in);
937 sscanf (local_address, "%8X%8X%8X%8X",
938 locaddr.sin6.sin6_addr.s6_addr32,
939 locaddr.sin6.sin6_addr.s6_addr32 + 1,
940 locaddr.sin6.sin6_addr.s6_addr32 + 2,
941 locaddr.sin6.sin6_addr.s6_addr32 + 3);
942 sscanf (remote_address, "%8X%8X%8X%8X",
943 remaddr.sin6.sin6_addr.s6_addr32,
944 remaddr.sin6.sin6_addr.s6_addr32 + 1,
945 remaddr.sin6.sin6_addr.s6_addr32 + 2,
946 remaddr.sin6.sin6_addr.s6_addr32 + 3);
948 locaddr.sin6.sin6_port = htons (local_port);
949 remaddr.sin6.sin6_port = htons (remote_port);
951 locaddr.sin6.sin6_flowinfo = 0;
952 remaddr.sin6.sin6_flowinfo = 0;
953 locaddr.sin6.sin6_scope_id = 0;
954 remaddr.sin6.sin6_scope_id = 0;
956 addr_size = sizeof (struct sockaddr_in6);
959 locaddr.sa.sa_family = remaddr.sa.sa_family = family;
961 result = getnameinfo (&locaddr.sa, addr_size,
962 local_address, sizeof (local_address),
963 local_service, sizeof (local_service),
964 NI_NUMERICHOST | NI_NUMERICSERV
965 | (tcp ? 0 : NI_DGRAM));
969 result = getnameinfo (&remaddr.sa, addr_size,
971 sizeof (remote_address),
973 sizeof (remote_service),
974 NI_NUMERICHOST | NI_NUMERICSERV
975 | (tcp ? 0 : NI_DGRAM));
979 user_from_uid (user, sizeof (user), uid);
984 "<column name=\"local address\">%s</column>"
985 "<column name=\"local port\">%s</column>"
986 "<column name=\"remote address\">%s</column>"
987 "<column name=\"remote port\">%s</column>"
988 "<column name=\"state\">%s</column>"
989 "<column name=\"user\">%s</column>"
990 "<column name=\"family\">%s</column>"
991 "<column name=\"protocol\">%s</column>"
997 format_socket_state (state),
999 (family == AF_INET) ? "INET" : "INET6",
1000 tcp ? "STREAM" : "DGRAM");
1010 /* Collect data about internet sockets and write it into READBUF. */
1013 linux_xfer_osdata_isockets (gdb_byte *readbuf,
1014 ULONGEST offset, LONGEST len)
1016 static const char *buf;
1017 static LONGEST len_avail = -1;
1018 static struct buffer buffer;
1022 if (len_avail != -1 && len_avail != 0)
1023 buffer_free (&buffer);
1026 buffer_init (&buffer);
1027 buffer_grow_str (&buffer, "<osdata type=\"I sockets\">\n");
1029 print_sockets (AF_INET, 1, &buffer);
1030 print_sockets (AF_INET, 0, &buffer);
1031 print_sockets (AF_INET6, 1, &buffer);
1032 print_sockets (AF_INET6, 0, &buffer);
1034 buffer_grow_str0 (&buffer, "</osdata>\n");
1035 buf = buffer_finish (&buffer);
1036 len_avail = strlen (buf);
1039 if (offset >= len_avail)
1041 /* Done. Get rid of the buffer. */
1042 buffer_free (&buffer);
1048 if (len > len_avail - offset)
1049 len = len_avail - offset;
1050 memcpy (readbuf, buf + offset, len);
1055 /* Converts the time SECONDS into textual form and copies it into a
1056 buffer TIME, with at most MAXLEN characters copied. */
1059 time_from_time_t (char *time, int maxlen, TIME_T seconds)
1065 time_t t = (time_t) seconds;
1067 strncpy (time, ctime (&t), maxlen);
1068 time[maxlen - 1] = '\0';
1072 /* Finds the group name for the group GID and copies it into GROUP.
1073 At most MAXLEN characters are copied. */
1076 group_from_gid (char *group, int maxlen, gid_t gid)
1078 struct group *grentry = getgrgid (gid);
1082 strncpy (group, grentry->gr_name, maxlen);
1083 /* Ensure that the group name is null-terminated. */
1084 group[maxlen - 1] = '\0';
1090 /* Collect data about shared memory recorded in /proc and write it
1094 linux_xfer_osdata_shm (gdb_byte *readbuf,
1095 ULONGEST offset, LONGEST len)
1097 static const char *buf;
1098 static LONGEST len_avail = -1;
1099 static struct buffer buffer;
1105 if (len_avail != -1 && len_avail != 0)
1106 buffer_free (&buffer);
1109 buffer_init (&buffer);
1110 buffer_grow_str (&buffer, "<osdata type=\"shared memory\">\n");
1112 fp = fopen ("/proc/sysvipc/shm", "r");
1119 if (fgets (buf, sizeof (buf), fp))
1125 int shmid, size, nattch;
1126 TIME_T atime, dtime, ctime;
1130 items_read = sscanf (buf,
1131 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1132 &key, &shmid, &perms, &size,
1135 &uid, &gid, &cuid, &cgid,
1136 &atime, &dtime, &ctime);
1138 if (items_read == 14)
1140 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1141 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1142 char ccmd[32], lcmd[32];
1143 char atime_str[32], dtime_str[32], ctime_str[32];
1145 user_from_uid (user, sizeof (user), uid);
1146 group_from_gid (group, sizeof (group), gid);
1147 user_from_uid (cuser, sizeof (cuser), cuid);
1148 group_from_gid (cgroup, sizeof (cgroup), cgid);
1150 command_from_pid (ccmd, sizeof (ccmd), cpid);
1151 command_from_pid (lcmd, sizeof (lcmd), lpid);
1153 time_from_time_t (atime_str, sizeof (atime_str), atime);
1154 time_from_time_t (dtime_str, sizeof (dtime_str), dtime);
1155 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1160 "<column name=\"key\">%d</column>"
1161 "<column name=\"shmid\">%d</column>"
1162 "<column name=\"permissions\">%o</column>"
1163 "<column name=\"size\">%d</column>"
1164 "<column name=\"creator command\">%s</column>"
1165 "<column name=\"last op. command\">%s</column>"
1166 "<column name=\"num attached\">%d</column>"
1167 "<column name=\"user\">%s</column>"
1168 "<column name=\"group\">%s</column>"
1169 "<column name=\"creator user\">%s</column>"
1170 "<column name=\"creator group\">%s</column>"
1171 "<column name=\"last shmat() time\">%s</column>"
1172 "<column name=\"last shmdt() time\">%s</column>"
1173 "<column name=\"last shmctl() time\">%s</column>"
1197 buffer_grow_str0 (&buffer, "</osdata>\n");
1198 buf = buffer_finish (&buffer);
1199 len_avail = strlen (buf);
1202 if (offset >= len_avail)
1204 /* Done. Get rid of the buffer. */
1205 buffer_free (&buffer);
1211 if (len > len_avail - offset)
1212 len = len_avail - offset;
1213 memcpy (readbuf, buf + offset, len);
1218 /* Collect data about semaphores recorded in /proc and write it
1222 linux_xfer_osdata_sem (gdb_byte *readbuf,
1223 ULONGEST offset, LONGEST len)
1225 static const char *buf;
1226 static LONGEST len_avail = -1;
1227 static struct buffer buffer;
1233 if (len_avail != -1 && len_avail != 0)
1234 buffer_free (&buffer);
1237 buffer_init (&buffer);
1238 buffer_grow_str (&buffer, "<osdata type=\"semaphores\">\n");
1240 fp = fopen ("/proc/sysvipc/sem", "r");
1247 if (fgets (buf, sizeof (buf), fp))
1252 unsigned int perms, nsems;
1254 TIME_T otime, ctime;
1257 items_read = sscanf (buf,
1258 "%d %d %o %u %d %d %d %d %lld %lld",
1259 &key, &semid, &perms, &nsems,
1260 &uid, &gid, &cuid, &cgid,
1263 if (items_read == 10)
1265 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1266 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1267 char otime_str[32], ctime_str[32];
1269 user_from_uid (user, sizeof (user), uid);
1270 group_from_gid (group, sizeof (group), gid);
1271 user_from_uid (cuser, sizeof (cuser), cuid);
1272 group_from_gid (cgroup, sizeof (cgroup), cgid);
1274 time_from_time_t (otime_str, sizeof (otime_str), otime);
1275 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1280 "<column name=\"key\">%d</column>"
1281 "<column name=\"semid\">%d</column>"
1282 "<column name=\"permissions\">%o</column>"
1283 "<column name=\"num semaphores\">%u</column>"
1284 "<column name=\"user\">%s</column>"
1285 "<column name=\"group\">%s</column>"
1286 "<column name=\"creator user\">%s</column>"
1287 "<column name=\"creator group\">%s</column>"
1288 "<column name=\"last semop() time\">%s</column>"
1289 "<column name=\"last semctl() time\">%s</column>"
1309 buffer_grow_str0 (&buffer, "</osdata>\n");
1310 buf = buffer_finish (&buffer);
1311 len_avail = strlen (buf);
1314 if (offset >= len_avail)
1316 /* Done. Get rid of the buffer. */
1317 buffer_free (&buffer);
1323 if (len > len_avail - offset)
1324 len = len_avail - offset;
1325 memcpy (readbuf, buf + offset, len);
1330 /* Collect data about message queues recorded in /proc and write it
1334 linux_xfer_osdata_msg (gdb_byte *readbuf,
1335 ULONGEST offset, LONGEST len)
1337 static const char *buf;
1338 static LONGEST len_avail = -1;
1339 static struct buffer buffer;
1345 if (len_avail != -1 && len_avail != 0)
1346 buffer_free (&buffer);
1349 buffer_init (&buffer);
1350 buffer_grow_str (&buffer, "<osdata type=\"message queues\">\n");
1352 fp = fopen ("/proc/sysvipc/msg", "r");
1359 if (fgets (buf, sizeof (buf), fp))
1365 unsigned int perms, cbytes, qnum;
1367 TIME_T stime, rtime, ctime;
1370 items_read = sscanf (buf,
1371 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1372 &key, &msqid, &perms, &cbytes, &qnum,
1373 &lspid, &lrpid, &uid, &gid, &cuid, &cgid,
1374 &stime, &rtime, &ctime);
1376 if (items_read == 14)
1378 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1379 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1380 char lscmd[32], lrcmd[32];
1381 char stime_str[32], rtime_str[32], ctime_str[32];
1383 user_from_uid (user, sizeof (user), uid);
1384 group_from_gid (group, sizeof (group), gid);
1385 user_from_uid (cuser, sizeof (cuser), cuid);
1386 group_from_gid (cgroup, sizeof (cgroup), cgid);
1388 command_from_pid (lscmd, sizeof (lscmd), lspid);
1389 command_from_pid (lrcmd, sizeof (lrcmd), lrpid);
1391 time_from_time_t (stime_str, sizeof (stime_str), stime);
1392 time_from_time_t (rtime_str, sizeof (rtime_str), rtime);
1393 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1398 "<column name=\"key\">%d</column>"
1399 "<column name=\"msqid\">%d</column>"
1400 "<column name=\"permissions\">%o</column>"
1401 "<column name=\"num used bytes\">%u</column>"
1402 "<column name=\"num messages\">%u</column>"
1403 "<column name=\"last msgsnd() command\">%s</column>"
1404 "<column name=\"last msgrcv() command\">%s</column>"
1405 "<column name=\"user\">%s</column>"
1406 "<column name=\"group\">%s</column>"
1407 "<column name=\"creator user\">%s</column>"
1408 "<column name=\"creator group\">%s</column>"
1409 "<column name=\"last msgsnd() time\">%s</column>"
1410 "<column name=\"last msgrcv() time\">%s</column>"
1411 "<column name=\"last msgctl() time\">%s</column>"
1435 buffer_grow_str0 (&buffer, "</osdata>\n");
1436 buf = buffer_finish (&buffer);
1437 len_avail = strlen (buf);
1440 if (offset >= len_avail)
1442 /* Done. Get rid of the buffer. */
1443 buffer_free (&buffer);
1449 if (len > len_avail - offset)
1450 len = len_avail - offset;
1451 memcpy (readbuf, buf + offset, len);
1456 /* Collect data about loaded kernel modules and write it into
1460 linux_xfer_osdata_modules (gdb_byte *readbuf,
1461 ULONGEST offset, LONGEST len)
1463 static const char *buf;
1464 static LONGEST len_avail = -1;
1465 static struct buffer buffer;
1471 if (len_avail != -1 && len_avail != 0)
1472 buffer_free (&buffer);
1475 buffer_init (&buffer);
1476 buffer_grow_str (&buffer, "<osdata type=\"modules\">\n");
1478 fp = fopen ("/proc/modules", "r");
1485 if (fgets (buf, sizeof (buf), fp))
1487 char name[64], dependencies[256], status[16];
1489 unsigned long long address;
1493 items_read = sscanf (buf,
1494 "%64s %d %d %256s %16s 0x%llx",
1496 dependencies, status, &address);
1498 if (items_read == 6)
1502 "<column name=\"name\">%s</column>"
1503 "<column name=\"size\">%u</column>"
1504 "<column name=\"num uses\">%d</column>"
1505 "<column name=\"dependencies\">%s</column>"
1506 "<column name=\"status\">%s</column>"
1507 "<column name=\"address\">%llx</column>"
1522 buffer_grow_str0 (&buffer, "</osdata>\n");
1523 buf = buffer_finish (&buffer);
1524 len_avail = strlen (buf);
1527 if (offset >= len_avail)
1529 /* Done. Get rid of the buffer. */
1530 buffer_free (&buffer);
1536 if (len > len_avail - offset)
1537 len = len_avail - offset;
1538 memcpy (readbuf, buf + offset, len);
1543 struct osdata_type {
1547 LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, LONGEST len);
1548 } osdata_table[] = {
1549 { "processes", "Processes", "Listing of all processes",
1550 linux_xfer_osdata_processes },
1551 { "procgroups", "Process groups", "Listing of all process groups",
1552 linux_xfer_osdata_processgroups },
1553 { "threads", "Threads", "Listing of all threads",
1554 linux_xfer_osdata_threads },
1555 { "files", "File descriptors", "Listing of all file descriptors",
1556 linux_xfer_osdata_fds },
1557 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1558 linux_xfer_osdata_isockets },
1559 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1560 linux_xfer_osdata_shm },
1561 { "semaphores", "Semaphores", "Listing of all semaphores",
1562 linux_xfer_osdata_sem },
1563 { "msg", "Message queues", "Listing of all message queues",
1564 linux_xfer_osdata_msg },
1565 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1566 linux_xfer_osdata_modules },
1567 { NULL, NULL, NULL }
1571 linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
1572 ULONGEST offset, LONGEST len)
1574 if (!annex || *annex == '\0')
1576 static const char *buf;
1577 static LONGEST len_avail = -1;
1578 static struct buffer buffer;
1584 if (len_avail != -1 && len_avail != 0)
1585 buffer_free (&buffer);
1588 buffer_init (&buffer);
1589 buffer_grow_str (&buffer, "<osdata type=\"types\">\n");
1591 for (i = 0; osdata_table[i].type; ++i)
1595 "<column name=\"Type\">%s</column>"
1596 "<column name=\"Description\">%s</column>"
1597 "<column name=\"Title\">%s</column>"
1599 osdata_table[i].type,
1600 osdata_table[i].description,
1601 osdata_table[i].title);
1603 buffer_grow_str0 (&buffer, "</osdata>\n");
1604 buf = buffer_finish (&buffer);
1605 len_avail = strlen (buf);
1608 if (offset >= len_avail)
1610 /* Done. Get rid of the buffer. */
1611 buffer_free (&buffer);
1617 if (len > len_avail - offset)
1618 len = len_avail - offset;
1619 memcpy (readbuf, buf + offset, len);
1627 for (i = 0; osdata_table[i].type; ++i)
1629 if (strcmp (annex, osdata_table[i].type) == 0)
1631 gdb_assert (readbuf);
1633 return (osdata_table[i].getter) (readbuf, offset, len);