Remove "\nError: " suffix from nat/fork-inferior.c:trace_start_error warning message
[deliverable/binutils-gdb.git] / gdb / nat / linux-osdata.c
1 /* Linux-specific functions to retrieve OS data.
2
3 Copyright (C) 2009-2019 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
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.
11
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.
16
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/>. */
19
20 #include "gdbsupport/common-defs.h"
21 #include "linux-osdata.h"
22
23 #include <sys/types.h>
24 #include <sys/sysinfo.h>
25 #include <ctype.h>
26 #include <utmp.h>
27 #include <time.h>
28 #include <unistd.h>
29 #include <pwd.h>
30 #include <grp.h>
31 #include <netdb.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34
35 #include "gdbsupport/xml-utils.h"
36 #include "gdbsupport/buffer.h"
37 #include <dirent.h>
38 #include <sys/stat.h>
39 #include "gdbsupport/filestuff.h"
40 #include <algorithm>
41
42 #define NAMELEN(dirent) strlen ((dirent)->d_name)
43
44 /* Define PID_T to be a fixed size that is at least as large as pid_t,
45 so that reading pid values embedded in /proc works
46 consistently. */
47
48 typedef long long PID_T;
49
50 /* Define TIME_T to be at least as large as time_t, so that reading
51 time values embedded in /proc works consistently. */
52
53 typedef long long TIME_T;
54
55 #define MAX_PID_T_STRLEN (sizeof ("-9223372036854775808") - 1)
56
57 /* Returns the CPU core that thread PTID is currently running on. */
58
59 /* Compute and return the processor core of a given thread. */
60
61 int
62 linux_common_core_of_thread (ptid_t ptid)
63 {
64 char filename[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN];
65 char *content = NULL;
66 char *p;
67 char *ts = 0;
68 int content_read = 0;
69 int i;
70 int core;
71
72 sprintf (filename, "/proc/%lld/task/%lld/stat",
73 (PID_T) ptid.pid (), (PID_T) ptid.lwp ());
74 gdb_file_up f = gdb_fopen_cloexec (filename, "r");
75 if (!f)
76 return -1;
77
78 for (;;)
79 {
80 int n;
81 content = (char *) xrealloc (content, content_read + 1024);
82 n = fread (content + content_read, 1, 1024, f.get ());
83 content_read += n;
84 if (n < 1024)
85 {
86 content[content_read] = '\0';
87 break;
88 }
89 }
90
91 /* ps command also relies on no trailing fields ever contain ')'. */
92 p = strrchr (content, ')');
93 if (p != NULL)
94 p++;
95
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. */
98 if (p != NULL)
99 p = strtok_r (p, " ", &ts);
100 for (i = 0; p != NULL && i != 36; ++i)
101 p = strtok_r (NULL, " ", &ts);
102
103 if (p == NULL || sscanf (p, "%d", &core) == 0)
104 core = -1;
105
106 xfree (content);
107
108 return core;
109 }
110
111 /* Finds the command-line of process PID and copies it into COMMAND.
112 At most MAXLEN characters are copied. If the command-line cannot
113 be found, PID is copied into command in text-form. */
114
115 static void
116 command_from_pid (char *command, int maxlen, PID_T pid)
117 {
118 std::string stat_path = string_printf ("/proc/%lld/stat", pid);
119 gdb_file_up fp = gdb_fopen_cloexec (stat_path, "r");
120
121 command[0] = '\0';
122
123 if (fp)
124 {
125 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
126 include/linux/sched.h in the Linux kernel sources) plus two
127 (for the brackets). */
128 char cmd[18];
129 PID_T stat_pid;
130 int items_read = fscanf (fp.get (), "%lld %17s", &stat_pid, cmd);
131
132 if (items_read == 2 && pid == stat_pid)
133 {
134 cmd[strlen (cmd) - 1] = '\0'; /* Remove trailing parenthesis. */
135 strncpy (command, cmd + 1, maxlen); /* Ignore leading parenthesis. */
136 }
137 }
138 else
139 {
140 /* Return the PID if a /proc entry for the process cannot be found. */
141 snprintf (command, maxlen, "%lld", pid);
142 }
143
144 command[maxlen - 1] = '\0'; /* Ensure string is null-terminated. */
145 }
146
147 /* Returns the command-line of the process with the given PID. The
148 returned string needs to be freed using xfree after use. */
149
150 static char *
151 commandline_from_pid (PID_T pid)
152 {
153 std::string pathname = string_printf ("/proc/%lld/cmdline", pid);
154 char *commandline = NULL;
155 gdb_file_up f = gdb_fopen_cloexec (pathname, "r");
156
157 if (f)
158 {
159 size_t len = 0;
160
161 while (!feof (f.get ()))
162 {
163 char buf[1024];
164 size_t read_bytes = fread (buf, 1, sizeof (buf), f.get ());
165
166 if (read_bytes)
167 {
168 commandline = (char *) xrealloc (commandline, len + read_bytes + 1);
169 memcpy (commandline + len, buf, read_bytes);
170 len += read_bytes;
171 }
172 }
173
174 if (commandline)
175 {
176 size_t i;
177
178 /* Replace null characters with spaces. */
179 for (i = 0; i < len; ++i)
180 if (commandline[i] == '\0')
181 commandline[i] = ' ';
182
183 commandline[len] = '\0';
184 }
185 else
186 {
187 /* Return the command in square brackets if the command-line
188 is empty. */
189 commandline = (char *) xmalloc (32);
190 commandline[0] = '[';
191 command_from_pid (commandline + 1, 31, pid);
192
193 len = strlen (commandline);
194 if (len < 31)
195 strcat (commandline, "]");
196 }
197 }
198
199 return commandline;
200 }
201
202 /* Finds the user name for the user UID and copies it into USER. At
203 most MAXLEN characters are copied. */
204
205 static void
206 user_from_uid (char *user, int maxlen, uid_t uid)
207 {
208 struct passwd *pwentry = getpwuid (uid);
209
210 if (pwentry)
211 {
212 strncpy (user, pwentry->pw_name, maxlen);
213 /* Ensure that the user name is null-terminated. */
214 user[maxlen - 1] = '\0';
215 }
216 else
217 user[0] = '\0';
218 }
219
220 /* Finds the owner of process PID and returns the user id in OWNER.
221 Returns 0 if the owner was found, -1 otherwise. */
222
223 static int
224 get_process_owner (uid_t *owner, PID_T pid)
225 {
226 struct stat statbuf;
227 char procentry[sizeof ("/proc/") + MAX_PID_T_STRLEN];
228
229 sprintf (procentry, "/proc/%lld", pid);
230
231 if (stat (procentry, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))
232 {
233 *owner = statbuf.st_uid;
234 return 0;
235 }
236 else
237 return -1;
238 }
239
240 /* Find the CPU cores used by process PID and return them in CORES.
241 CORES points to an array of NUM_CORES elements. */
242
243 static int
244 get_cores_used_by_process (PID_T pid, int *cores, const int num_cores)
245 {
246 char taskdir[sizeof ("/proc/") + MAX_PID_T_STRLEN + sizeof ("/task") - 1];
247 DIR *dir;
248 struct dirent *dp;
249 int task_count = 0;
250
251 sprintf (taskdir, "/proc/%lld/task", pid);
252 dir = opendir (taskdir);
253 if (dir)
254 {
255 while ((dp = readdir (dir)) != NULL)
256 {
257 PID_T tid;
258 int core;
259
260 if (!isdigit (dp->d_name[0])
261 || NAMELEN (dp) > MAX_PID_T_STRLEN)
262 continue;
263
264 sscanf (dp->d_name, "%lld", &tid);
265 core = linux_common_core_of_thread (ptid_t ((pid_t) pid,
266 (pid_t) tid, 0));
267
268 if (core >= 0 && core < num_cores)
269 {
270 ++cores[core];
271 ++task_count;
272 }
273 }
274
275 closedir (dir);
276 }
277
278 return task_count;
279 }
280
281 static void
282 linux_xfer_osdata_processes (struct buffer *buffer)
283 {
284 DIR *dirp;
285
286 buffer_grow_str (buffer, "<osdata type=\"processes\">\n");
287
288 dirp = opendir ("/proc");
289 if (dirp)
290 {
291 const int num_cores = sysconf (_SC_NPROCESSORS_ONLN);
292 struct dirent *dp;
293
294 while ((dp = readdir (dirp)) != NULL)
295 {
296 PID_T pid;
297 uid_t owner;
298 char user[UT_NAMESIZE];
299 char *command_line;
300 int *cores;
301 int task_count;
302 char *cores_str;
303 int i;
304
305 if (!isdigit (dp->d_name[0])
306 || NAMELEN (dp) > MAX_PID_T_STRLEN)
307 continue;
308
309 sscanf (dp->d_name, "%lld", &pid);
310 command_line = commandline_from_pid (pid);
311
312 if (get_process_owner (&owner, pid) == 0)
313 user_from_uid (user, sizeof (user), owner);
314 else
315 strcpy (user, "?");
316
317 /* Find CPU cores used by the process. */
318 cores = XCNEWVEC (int, num_cores);
319 task_count = get_cores_used_by_process (pid, cores, num_cores);
320 cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1);
321
322 for (i = 0; i < num_cores && task_count > 0; ++i)
323 if (cores[i])
324 {
325 char core_str[sizeof ("4294967295")];
326
327 sprintf (core_str, "%d", i);
328 strcat (cores_str, core_str);
329
330 task_count -= cores[i];
331 if (task_count > 0)
332 strcat (cores_str, ",");
333 }
334
335 xfree (cores);
336
337 buffer_xml_printf
338 (buffer,
339 "<item>"
340 "<column name=\"pid\">%lld</column>"
341 "<column name=\"user\">%s</column>"
342 "<column name=\"command\">%s</column>"
343 "<column name=\"cores\">%s</column>"
344 "</item>",
345 pid,
346 user,
347 command_line ? command_line : "",
348 cores_str);
349
350 xfree (command_line);
351 xfree (cores_str);
352 }
353
354 closedir (dirp);
355 }
356
357 buffer_grow_str0 (buffer, "</osdata>\n");
358 }
359
360 /* A simple PID/PGID pair. */
361
362 struct pid_pgid_entry
363 {
364 pid_pgid_entry (PID_T pid_, PID_T pgid_)
365 : pid (pid_), pgid (pgid_)
366 {}
367
368 /* Return true if this pid is the leader of its process group. */
369
370 bool is_leader () const
371 {
372 return pid == pgid;
373 }
374
375 bool operator< (const pid_pgid_entry &other) const
376 {
377 /* Sort by PGID. */
378 if (this->pgid != other.pgid)
379 return this->pgid < other.pgid;
380
381 /* Process group leaders always come first... */
382 if (this->is_leader ())
383 {
384 if (!other.is_leader ())
385 return true;
386 }
387 else if (other.is_leader ())
388 return false;
389
390 /* ...else sort by PID. */
391 return this->pid < other.pid;
392 }
393
394 PID_T pid, pgid;
395 };
396
397 /* Collect all process groups from /proc in BUFFER. */
398
399 static void
400 linux_xfer_osdata_processgroups (struct buffer *buffer)
401 {
402 DIR *dirp;
403
404 buffer_grow_str (buffer, "<osdata type=\"process groups\">\n");
405
406 dirp = opendir ("/proc");
407 if (dirp)
408 {
409 std::vector<pid_pgid_entry> process_list;
410 struct dirent *dp;
411
412 process_list.reserve (512);
413
414 /* Build list consisting of PIDs followed by their
415 associated PGID. */
416 while ((dp = readdir (dirp)) != NULL)
417 {
418 PID_T pid, pgid;
419
420 if (!isdigit (dp->d_name[0])
421 || NAMELEN (dp) > MAX_PID_T_STRLEN)
422 continue;
423
424 sscanf (dp->d_name, "%lld", &pid);
425 pgid = getpgid (pid);
426
427 if (pgid > 0)
428 process_list.emplace_back (pid, pgid);
429 }
430
431 closedir (dirp);
432
433 /* Sort the process list. */
434 std::sort (process_list.begin (), process_list.end ());
435
436 for (const pid_pgid_entry &entry : process_list)
437 {
438 PID_T pid = entry.pid;
439 PID_T pgid = entry.pgid;
440 char leader_command[32];
441 char *command_line;
442
443 command_from_pid (leader_command, sizeof (leader_command), pgid);
444 command_line = commandline_from_pid (pid);
445
446 buffer_xml_printf
447 (buffer,
448 "<item>"
449 "<column name=\"pgid\">%lld</column>"
450 "<column name=\"leader command\">%s</column>"
451 "<column name=\"pid\">%lld</column>"
452 "<column name=\"command line\">%s</column>"
453 "</item>",
454 pgid,
455 leader_command,
456 pid,
457 command_line ? command_line : "");
458
459 xfree (command_line);
460 }
461 }
462
463 buffer_grow_str0 (buffer, "</osdata>\n");
464 }
465
466 /* Collect all the threads in /proc by iterating through processes and
467 then tasks within each process in BUFFER. */
468
469 static void
470 linux_xfer_osdata_threads (struct buffer *buffer)
471 {
472 DIR *dirp;
473
474 buffer_grow_str (buffer, "<osdata type=\"threads\">\n");
475
476 dirp = opendir ("/proc");
477 if (dirp)
478 {
479 struct dirent *dp;
480
481 while ((dp = readdir (dirp)) != NULL)
482 {
483 struct stat statbuf;
484 char procentry[sizeof ("/proc/4294967295")];
485
486 if (!isdigit (dp->d_name[0])
487 || NAMELEN (dp) > sizeof ("4294967295") - 1)
488 continue;
489
490 xsnprintf (procentry, sizeof (procentry), "/proc/%s",
491 dp->d_name);
492 if (stat (procentry, &statbuf) == 0
493 && S_ISDIR (statbuf.st_mode))
494 {
495 DIR *dirp2;
496 PID_T pid;
497 char command[32];
498
499 std::string pathname
500 = string_printf ("/proc/%s/task", dp->d_name);
501
502 pid = atoi (dp->d_name);
503 command_from_pid (command, sizeof (command), pid);
504
505 dirp2 = opendir (pathname.c_str ());
506
507 if (dirp2)
508 {
509 struct dirent *dp2;
510
511 while ((dp2 = readdir (dirp2)) != NULL)
512 {
513 PID_T tid;
514 int core;
515
516 if (!isdigit (dp2->d_name[0])
517 || NAMELEN (dp2) > sizeof ("4294967295") - 1)
518 continue;
519
520 tid = atoi (dp2->d_name);
521 core = linux_common_core_of_thread (ptid_t (pid, tid, 0));
522
523 buffer_xml_printf
524 (buffer,
525 "<item>"
526 "<column name=\"pid\">%lld</column>"
527 "<column name=\"command\">%s</column>"
528 "<column name=\"tid\">%lld</column>"
529 "<column name=\"core\">%d</column>"
530 "</item>",
531 pid,
532 command,
533 tid,
534 core);
535 }
536
537 closedir (dirp2);
538 }
539 }
540 }
541
542 closedir (dirp);
543 }
544
545 buffer_grow_str0 (buffer, "</osdata>\n");
546 }
547
548 /* Collect data about the cpus/cores on the system in BUFFER. */
549
550 static void
551 linux_xfer_osdata_cpus (struct buffer *buffer)
552 {
553 int first_item = 1;
554
555 buffer_grow_str (buffer, "<osdata type=\"cpus\">\n");
556
557 gdb_file_up fp = gdb_fopen_cloexec ("/proc/cpuinfo", "r");
558 if (fp != NULL)
559 {
560 char buf[8192];
561
562 do
563 {
564 if (fgets (buf, sizeof (buf), fp.get ()))
565 {
566 char *key, *value;
567 int i = 0;
568
569 key = strtok (buf, ":");
570 if (key == NULL)
571 continue;
572
573 value = strtok (NULL, ":");
574 if (value == NULL)
575 continue;
576
577 while (key[i] != '\t' && key[i] != '\0')
578 i++;
579
580 key[i] = '\0';
581
582 i = 0;
583 while (value[i] != '\t' && value[i] != '\0')
584 i++;
585
586 value[i] = '\0';
587
588 if (strcmp (key, "processor") == 0)
589 {
590 if (first_item)
591 buffer_grow_str (buffer, "<item>");
592 else
593 buffer_grow_str (buffer, "</item><item>");
594
595 first_item = 0;
596 }
597
598 buffer_xml_printf (buffer,
599 "<column name=\"%s\">%s</column>",
600 key,
601 value);
602 }
603 }
604 while (!feof (fp.get ()));
605
606 if (first_item == 0)
607 buffer_grow_str (buffer, "</item>");
608 }
609
610 buffer_grow_str0 (buffer, "</osdata>\n");
611 }
612
613 /* Collect all the open file descriptors found in /proc and put the details
614 found about them into BUFFER. */
615
616 static void
617 linux_xfer_osdata_fds (struct buffer *buffer)
618 {
619 DIR *dirp;
620
621 buffer_grow_str (buffer, "<osdata type=\"files\">\n");
622
623 dirp = opendir ("/proc");
624 if (dirp)
625 {
626 struct dirent *dp;
627
628 while ((dp = readdir (dirp)) != NULL)
629 {
630 struct stat statbuf;
631 char procentry[sizeof ("/proc/4294967295")];
632
633 if (!isdigit (dp->d_name[0])
634 || NAMELEN (dp) > sizeof ("4294967295") - 1)
635 continue;
636
637 xsnprintf (procentry, sizeof (procentry), "/proc/%s",
638 dp->d_name);
639 if (stat (procentry, &statbuf) == 0
640 && S_ISDIR (statbuf.st_mode))
641 {
642 DIR *dirp2;
643 PID_T pid;
644 char command[32];
645
646 pid = atoi (dp->d_name);
647 command_from_pid (command, sizeof (command), pid);
648
649 std::string pathname
650 = string_printf ("/proc/%s/fd", dp->d_name);
651 dirp2 = opendir (pathname.c_str ());
652
653 if (dirp2)
654 {
655 struct dirent *dp2;
656
657 while ((dp2 = readdir (dirp2)) != NULL)
658 {
659 char buf[1000];
660 ssize_t rslt;
661
662 if (!isdigit (dp2->d_name[0]))
663 continue;
664
665 std::string fdname
666 = string_printf ("%s/%s", pathname.c_str (),
667 dp2->d_name);
668 rslt = readlink (fdname.c_str (), buf,
669 sizeof (buf) - 1);
670 if (rslt >= 0)
671 buf[rslt] = '\0';
672
673 buffer_xml_printf
674 (buffer,
675 "<item>"
676 "<column name=\"pid\">%s</column>"
677 "<column name=\"command\">%s</column>"
678 "<column name=\"file descriptor\">%s</column>"
679 "<column name=\"name\">%s</column>"
680 "</item>",
681 dp->d_name,
682 command,
683 dp2->d_name,
684 (rslt >= 0 ? buf : dp2->d_name));
685 }
686
687 closedir (dirp2);
688 }
689 }
690 }
691
692 closedir (dirp);
693 }
694
695 buffer_grow_str0 (buffer, "</osdata>\n");
696 }
697
698 /* Returns the socket state STATE in textual form. */
699
700 static const char *
701 format_socket_state (unsigned char state)
702 {
703 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
704 enum {
705 TCP_ESTABLISHED = 1,
706 TCP_SYN_SENT,
707 TCP_SYN_RECV,
708 TCP_FIN_WAIT1,
709 TCP_FIN_WAIT2,
710 TCP_TIME_WAIT,
711 TCP_CLOSE,
712 TCP_CLOSE_WAIT,
713 TCP_LAST_ACK,
714 TCP_LISTEN,
715 TCP_CLOSING
716 };
717
718 switch (state)
719 {
720 case TCP_ESTABLISHED:
721 return "ESTABLISHED";
722 case TCP_SYN_SENT:
723 return "SYN_SENT";
724 case TCP_SYN_RECV:
725 return "SYN_RECV";
726 case TCP_FIN_WAIT1:
727 return "FIN_WAIT1";
728 case TCP_FIN_WAIT2:
729 return "FIN_WAIT2";
730 case TCP_TIME_WAIT:
731 return "TIME_WAIT";
732 case TCP_CLOSE:
733 return "CLOSE";
734 case TCP_CLOSE_WAIT:
735 return "CLOSE_WAIT";
736 case TCP_LAST_ACK:
737 return "LAST_ACK";
738 case TCP_LISTEN:
739 return "LISTEN";
740 case TCP_CLOSING:
741 return "CLOSING";
742 default:
743 return "(unknown)";
744 }
745 }
746
747 union socket_addr
748 {
749 struct sockaddr sa;
750 struct sockaddr_in sin;
751 struct sockaddr_in6 sin6;
752 };
753
754 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats
755 information for all open internet sockets of type FAMILY on the
756 system into BUFFER. If TCP is set, only TCP sockets are processed,
757 otherwise only UDP sockets are processed. */
758
759 static void
760 print_sockets (unsigned short family, int tcp, struct buffer *buffer)
761 {
762 const char *proc_file;
763
764 if (family == AF_INET)
765 proc_file = tcp ? "/proc/net/tcp" : "/proc/net/udp";
766 else if (family == AF_INET6)
767 proc_file = tcp ? "/proc/net/tcp6" : "/proc/net/udp6";
768 else
769 return;
770
771 gdb_file_up fp = gdb_fopen_cloexec (proc_file, "r");
772 if (fp)
773 {
774 char buf[8192];
775
776 do
777 {
778 if (fgets (buf, sizeof (buf), fp.get ()))
779 {
780 uid_t uid;
781 unsigned int local_port, remote_port, state;
782 char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
783 int result;
784
785 #if NI_MAXHOST <= 32
786 #error "local_address and remote_address buffers too small"
787 #endif
788
789 result = sscanf (buf,
790 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
791 local_address, &local_port,
792 remote_address, &remote_port,
793 &state,
794 &uid);
795
796 if (result == 6)
797 {
798 union socket_addr locaddr, remaddr;
799 size_t addr_size;
800 char user[UT_NAMESIZE];
801 char local_service[NI_MAXSERV], remote_service[NI_MAXSERV];
802
803 if (family == AF_INET)
804 {
805 sscanf (local_address, "%X",
806 &locaddr.sin.sin_addr.s_addr);
807 sscanf (remote_address, "%X",
808 &remaddr.sin.sin_addr.s_addr);
809
810 locaddr.sin.sin_port = htons (local_port);
811 remaddr.sin.sin_port = htons (remote_port);
812
813 addr_size = sizeof (struct sockaddr_in);
814 }
815 else
816 {
817 sscanf (local_address, "%8X%8X%8X%8X",
818 locaddr.sin6.sin6_addr.s6_addr32,
819 locaddr.sin6.sin6_addr.s6_addr32 + 1,
820 locaddr.sin6.sin6_addr.s6_addr32 + 2,
821 locaddr.sin6.sin6_addr.s6_addr32 + 3);
822 sscanf (remote_address, "%8X%8X%8X%8X",
823 remaddr.sin6.sin6_addr.s6_addr32,
824 remaddr.sin6.sin6_addr.s6_addr32 + 1,
825 remaddr.sin6.sin6_addr.s6_addr32 + 2,
826 remaddr.sin6.sin6_addr.s6_addr32 + 3);
827
828 locaddr.sin6.sin6_port = htons (local_port);
829 remaddr.sin6.sin6_port = htons (remote_port);
830
831 locaddr.sin6.sin6_flowinfo = 0;
832 remaddr.sin6.sin6_flowinfo = 0;
833 locaddr.sin6.sin6_scope_id = 0;
834 remaddr.sin6.sin6_scope_id = 0;
835
836 addr_size = sizeof (struct sockaddr_in6);
837 }
838
839 locaddr.sa.sa_family = remaddr.sa.sa_family = family;
840
841 result = getnameinfo (&locaddr.sa, addr_size,
842 local_address, sizeof (local_address),
843 local_service, sizeof (local_service),
844 NI_NUMERICHOST | NI_NUMERICSERV
845 | (tcp ? 0 : NI_DGRAM));
846 if (result)
847 continue;
848
849 result = getnameinfo (&remaddr.sa, addr_size,
850 remote_address,
851 sizeof (remote_address),
852 remote_service,
853 sizeof (remote_service),
854 NI_NUMERICHOST | NI_NUMERICSERV
855 | (tcp ? 0 : NI_DGRAM));
856 if (result)
857 continue;
858
859 user_from_uid (user, sizeof (user), uid);
860
861 buffer_xml_printf (
862 buffer,
863 "<item>"
864 "<column name=\"local address\">%s</column>"
865 "<column name=\"local port\">%s</column>"
866 "<column name=\"remote address\">%s</column>"
867 "<column name=\"remote port\">%s</column>"
868 "<column name=\"state\">%s</column>"
869 "<column name=\"user\">%s</column>"
870 "<column name=\"family\">%s</column>"
871 "<column name=\"protocol\">%s</column>"
872 "</item>",
873 local_address,
874 local_service,
875 remote_address,
876 remote_service,
877 format_socket_state (state),
878 user,
879 (family == AF_INET) ? "INET" : "INET6",
880 tcp ? "STREAM" : "DGRAM");
881 }
882 }
883 }
884 while (!feof (fp.get ()));
885 }
886 }
887
888 /* Collect data about internet sockets and write it into BUFFER. */
889
890 static void
891 linux_xfer_osdata_isockets (struct buffer *buffer)
892 {
893 buffer_grow_str (buffer, "<osdata type=\"I sockets\">\n");
894
895 print_sockets (AF_INET, 1, buffer);
896 print_sockets (AF_INET, 0, buffer);
897 print_sockets (AF_INET6, 1, buffer);
898 print_sockets (AF_INET6, 0, buffer);
899
900 buffer_grow_str0 (buffer, "</osdata>\n");
901 }
902
903 /* Converts the time SECONDS into textual form and copies it into a
904 buffer TIME, with at most MAXLEN characters copied. */
905
906 static void
907 time_from_time_t (char *time, int maxlen, TIME_T seconds)
908 {
909 if (!seconds)
910 time[0] = '\0';
911 else
912 {
913 time_t t = (time_t) seconds;
914
915 strncpy (time, ctime (&t), maxlen);
916 time[maxlen - 1] = '\0';
917 }
918 }
919
920 /* Finds the group name for the group GID and copies it into GROUP.
921 At most MAXLEN characters are copied. */
922
923 static void
924 group_from_gid (char *group, int maxlen, gid_t gid)
925 {
926 struct group *grentry = getgrgid (gid);
927
928 if (grentry)
929 {
930 strncpy (group, grentry->gr_name, maxlen);
931 /* Ensure that the group name is null-terminated. */
932 group[maxlen - 1] = '\0';
933 }
934 else
935 group[0] = '\0';
936 }
937
938 /* Collect data about shared memory recorded in /proc and write it
939 into BUFFER. */
940
941 static void
942 linux_xfer_osdata_shm (struct buffer *buffer)
943 {
944 buffer_grow_str (buffer, "<osdata type=\"shared memory\">\n");
945
946 gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
947 if (fp)
948 {
949 char buf[8192];
950
951 do
952 {
953 if (fgets (buf, sizeof (buf), fp.get ()))
954 {
955 key_t key;
956 uid_t uid, cuid;
957 gid_t gid, cgid;
958 PID_T cpid, lpid;
959 int shmid, size, nattch;
960 TIME_T atime, dtime, ctime;
961 unsigned int perms;
962 int items_read;
963
964 items_read = sscanf (buf,
965 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
966 &key, &shmid, &perms, &size,
967 &cpid, &lpid,
968 &nattch,
969 &uid, &gid, &cuid, &cgid,
970 &atime, &dtime, &ctime);
971
972 if (items_read == 14)
973 {
974 char user[UT_NAMESIZE], group[UT_NAMESIZE];
975 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
976 char ccmd[32], lcmd[32];
977 char atime_str[32], dtime_str[32], ctime_str[32];
978
979 user_from_uid (user, sizeof (user), uid);
980 group_from_gid (group, sizeof (group), gid);
981 user_from_uid (cuser, sizeof (cuser), cuid);
982 group_from_gid (cgroup, sizeof (cgroup), cgid);
983
984 command_from_pid (ccmd, sizeof (ccmd), cpid);
985 command_from_pid (lcmd, sizeof (lcmd), lpid);
986
987 time_from_time_t (atime_str, sizeof (atime_str), atime);
988 time_from_time_t (dtime_str, sizeof (dtime_str), dtime);
989 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
990
991 buffer_xml_printf
992 (buffer,
993 "<item>"
994 "<column name=\"key\">%d</column>"
995 "<column name=\"shmid\">%d</column>"
996 "<column name=\"permissions\">%o</column>"
997 "<column name=\"size\">%d</column>"
998 "<column name=\"creator command\">%s</column>"
999 "<column name=\"last op. command\">%s</column>"
1000 "<column name=\"num attached\">%d</column>"
1001 "<column name=\"user\">%s</column>"
1002 "<column name=\"group\">%s</column>"
1003 "<column name=\"creator user\">%s</column>"
1004 "<column name=\"creator group\">%s</column>"
1005 "<column name=\"last shmat() time\">%s</column>"
1006 "<column name=\"last shmdt() time\">%s</column>"
1007 "<column name=\"last shmctl() time\">%s</column>"
1008 "</item>",
1009 key,
1010 shmid,
1011 perms,
1012 size,
1013 ccmd,
1014 lcmd,
1015 nattch,
1016 user,
1017 group,
1018 cuser,
1019 cgroup,
1020 atime_str,
1021 dtime_str,
1022 ctime_str);
1023 }
1024 }
1025 }
1026 while (!feof (fp.get ()));
1027 }
1028
1029 buffer_grow_str0 (buffer, "</osdata>\n");
1030 }
1031
1032 /* Collect data about semaphores recorded in /proc and write it
1033 into BUFFER. */
1034
1035 static void
1036 linux_xfer_osdata_sem (struct buffer *buffer)
1037 {
1038 buffer_grow_str (buffer, "<osdata type=\"semaphores\">\n");
1039
1040 gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1041 if (fp)
1042 {
1043 char buf[8192];
1044
1045 do
1046 {
1047 if (fgets (buf, sizeof (buf), fp.get ()))
1048 {
1049 key_t key;
1050 uid_t uid, cuid;
1051 gid_t gid, cgid;
1052 unsigned int perms, nsems;
1053 int semid;
1054 TIME_T otime, ctime;
1055 int items_read;
1056
1057 items_read = sscanf (buf,
1058 "%d %d %o %u %d %d %d %d %lld %lld",
1059 &key, &semid, &perms, &nsems,
1060 &uid, &gid, &cuid, &cgid,
1061 &otime, &ctime);
1062
1063 if (items_read == 10)
1064 {
1065 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1066 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1067 char otime_str[32], ctime_str[32];
1068
1069 user_from_uid (user, sizeof (user), uid);
1070 group_from_gid (group, sizeof (group), gid);
1071 user_from_uid (cuser, sizeof (cuser), cuid);
1072 group_from_gid (cgroup, sizeof (cgroup), cgid);
1073
1074 time_from_time_t (otime_str, sizeof (otime_str), otime);
1075 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1076
1077 buffer_xml_printf
1078 (buffer,
1079 "<item>"
1080 "<column name=\"key\">%d</column>"
1081 "<column name=\"semid\">%d</column>"
1082 "<column name=\"permissions\">%o</column>"
1083 "<column name=\"num semaphores\">%u</column>"
1084 "<column name=\"user\">%s</column>"
1085 "<column name=\"group\">%s</column>"
1086 "<column name=\"creator user\">%s</column>"
1087 "<column name=\"creator group\">%s</column>"
1088 "<column name=\"last semop() time\">%s</column>"
1089 "<column name=\"last semctl() time\">%s</column>"
1090 "</item>",
1091 key,
1092 semid,
1093 perms,
1094 nsems,
1095 user,
1096 group,
1097 cuser,
1098 cgroup,
1099 otime_str,
1100 ctime_str);
1101 }
1102 }
1103 }
1104 while (!feof (fp.get ()));
1105 }
1106
1107 buffer_grow_str0 (buffer, "</osdata>\n");
1108 }
1109
1110 /* Collect data about message queues recorded in /proc and write it
1111 into BUFFER. */
1112
1113 static void
1114 linux_xfer_osdata_msg (struct buffer *buffer)
1115 {
1116 buffer_grow_str (buffer, "<osdata type=\"message queues\">\n");
1117
1118 gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1119 if (fp)
1120 {
1121 char buf[8192];
1122
1123 do
1124 {
1125 if (fgets (buf, sizeof (buf), fp.get ()))
1126 {
1127 key_t key;
1128 PID_T lspid, lrpid;
1129 uid_t uid, cuid;
1130 gid_t gid, cgid;
1131 unsigned int perms, cbytes, qnum;
1132 int msqid;
1133 TIME_T stime, rtime, ctime;
1134 int items_read;
1135
1136 items_read = sscanf (buf,
1137 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1138 &key, &msqid, &perms, &cbytes, &qnum,
1139 &lspid, &lrpid, &uid, &gid, &cuid, &cgid,
1140 &stime, &rtime, &ctime);
1141
1142 if (items_read == 14)
1143 {
1144 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1145 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1146 char lscmd[32], lrcmd[32];
1147 char stime_str[32], rtime_str[32], ctime_str[32];
1148
1149 user_from_uid (user, sizeof (user), uid);
1150 group_from_gid (group, sizeof (group), gid);
1151 user_from_uid (cuser, sizeof (cuser), cuid);
1152 group_from_gid (cgroup, sizeof (cgroup), cgid);
1153
1154 command_from_pid (lscmd, sizeof (lscmd), lspid);
1155 command_from_pid (lrcmd, sizeof (lrcmd), lrpid);
1156
1157 time_from_time_t (stime_str, sizeof (stime_str), stime);
1158 time_from_time_t (rtime_str, sizeof (rtime_str), rtime);
1159 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1160
1161 buffer_xml_printf
1162 (buffer,
1163 "<item>"
1164 "<column name=\"key\">%d</column>"
1165 "<column name=\"msqid\">%d</column>"
1166 "<column name=\"permissions\">%o</column>"
1167 "<column name=\"num used bytes\">%u</column>"
1168 "<column name=\"num messages\">%u</column>"
1169 "<column name=\"last msgsnd() command\">%s</column>"
1170 "<column name=\"last msgrcv() command\">%s</column>"
1171 "<column name=\"user\">%s</column>"
1172 "<column name=\"group\">%s</column>"
1173 "<column name=\"creator user\">%s</column>"
1174 "<column name=\"creator group\">%s</column>"
1175 "<column name=\"last msgsnd() time\">%s</column>"
1176 "<column name=\"last msgrcv() time\">%s</column>"
1177 "<column name=\"last msgctl() time\">%s</column>"
1178 "</item>",
1179 key,
1180 msqid,
1181 perms,
1182 cbytes,
1183 qnum,
1184 lscmd,
1185 lrcmd,
1186 user,
1187 group,
1188 cuser,
1189 cgroup,
1190 stime_str,
1191 rtime_str,
1192 ctime_str);
1193 }
1194 }
1195 }
1196 while (!feof (fp.get ()));
1197 }
1198
1199 buffer_grow_str0 (buffer, "</osdata>\n");
1200 }
1201
1202 /* Collect data about loaded kernel modules and write it into
1203 BUFFER. */
1204
1205 static void
1206 linux_xfer_osdata_modules (struct buffer *buffer)
1207 {
1208 buffer_grow_str (buffer, "<osdata type=\"modules\">\n");
1209
1210 gdb_file_up fp = gdb_fopen_cloexec ("/proc/modules", "r");
1211 if (fp)
1212 {
1213 char buf[8192];
1214
1215 do
1216 {
1217 if (fgets (buf, sizeof (buf), fp.get ()))
1218 {
1219 char *name, *dependencies, *status, *tmp;
1220 unsigned int size;
1221 unsigned long long address;
1222 int uses;
1223
1224 name = strtok (buf, " ");
1225 if (name == NULL)
1226 continue;
1227
1228 tmp = strtok (NULL, " ");
1229 if (tmp == NULL)
1230 continue;
1231 if (sscanf (tmp, "%u", &size) != 1)
1232 continue;
1233
1234 tmp = strtok (NULL, " ");
1235 if (tmp == NULL)
1236 continue;
1237 if (sscanf (tmp, "%d", &uses) != 1)
1238 continue;
1239
1240 dependencies = strtok (NULL, " ");
1241 if (dependencies == NULL)
1242 continue;
1243
1244 status = strtok (NULL, " ");
1245 if (status == NULL)
1246 continue;
1247
1248 tmp = strtok (NULL, "\n");
1249 if (tmp == NULL)
1250 continue;
1251 if (sscanf (tmp, "%llx", &address) != 1)
1252 continue;
1253
1254 buffer_xml_printf (buffer,
1255 "<item>"
1256 "<column name=\"name\">%s</column>"
1257 "<column name=\"size\">%u</column>"
1258 "<column name=\"num uses\">%d</column>"
1259 "<column name=\"dependencies\">%s</column>"
1260 "<column name=\"status\">%s</column>"
1261 "<column name=\"address\">%llx</column>"
1262 "</item>",
1263 name,
1264 size,
1265 uses,
1266 dependencies,
1267 status,
1268 address);
1269 }
1270 }
1271 while (!feof (fp.get ()));
1272 }
1273
1274 buffer_grow_str0 (buffer, "</osdata>\n");
1275 }
1276
1277 static void linux_xfer_osdata_info_os_types (struct buffer *buffer);
1278
1279 struct osdata_type {
1280 const char *type;
1281 const char *title;
1282 const char *description;
1283 void (*take_snapshot) (struct buffer *buffer);
1284 LONGEST len_avail;
1285 struct buffer buffer;
1286 } osdata_table[] = {
1287 { "types", "Types", "Listing of info os types you can list",
1288 linux_xfer_osdata_info_os_types, -1 },
1289 { "cpus", "CPUs", "Listing of all cpus/cores on the system",
1290 linux_xfer_osdata_cpus, -1 },
1291 { "files", "File descriptors", "Listing of all file descriptors",
1292 linux_xfer_osdata_fds, -1 },
1293 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1294 linux_xfer_osdata_modules, -1 },
1295 { "msg", "Message queues", "Listing of all message queues",
1296 linux_xfer_osdata_msg, -1 },
1297 { "processes", "Processes", "Listing of all processes",
1298 linux_xfer_osdata_processes, -1 },
1299 { "procgroups", "Process groups", "Listing of all process groups",
1300 linux_xfer_osdata_processgroups, -1 },
1301 { "semaphores", "Semaphores", "Listing of all semaphores",
1302 linux_xfer_osdata_sem, -1 },
1303 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1304 linux_xfer_osdata_shm, -1 },
1305 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1306 linux_xfer_osdata_isockets, -1 },
1307 { "threads", "Threads", "Listing of all threads",
1308 linux_xfer_osdata_threads, -1 },
1309 { NULL, NULL, NULL }
1310 };
1311
1312 /* Collect data about all types info os can show in BUFFER. */
1313
1314 static void
1315 linux_xfer_osdata_info_os_types (struct buffer *buffer)
1316 {
1317 buffer_grow_str (buffer, "<osdata type=\"types\">\n");
1318
1319 /* Start the below loop at 1, as we do not want to list ourselves. */
1320 for (int i = 1; osdata_table[i].type; ++i)
1321 buffer_xml_printf (buffer,
1322 "<item>"
1323 "<column name=\"Type\">%s</column>"
1324 "<column name=\"Description\">%s</column>"
1325 "<column name=\"Title\">%s</column>"
1326 "</item>",
1327 osdata_table[i].type,
1328 osdata_table[i].description,
1329 osdata_table[i].title);
1330
1331 buffer_grow_str0 (buffer, "</osdata>\n");
1332 }
1333
1334
1335 /* Copies up to LEN bytes in READBUF from offset OFFSET in OSD->BUFFER.
1336 If OFFSET is zero, first calls OSD->TAKE_SNAPSHOT. */
1337
1338 static LONGEST
1339 common_getter (struct osdata_type *osd,
1340 gdb_byte *readbuf, ULONGEST offset, ULONGEST len)
1341 {
1342 gdb_assert (readbuf);
1343
1344 if (offset == 0)
1345 {
1346 if (osd->len_avail != -1 && osd->len_avail != 0)
1347 buffer_free (&osd->buffer);
1348 osd->len_avail = 0;
1349 buffer_init (&osd->buffer);
1350 (osd->take_snapshot) (&osd->buffer);
1351 osd->len_avail = strlen (osd->buffer.buffer);
1352 }
1353 if (offset >= osd->len_avail)
1354 {
1355 /* Done. Get rid of the buffer. */
1356 buffer_free (&osd->buffer);
1357 osd->len_avail = 0;
1358 return 0;
1359 }
1360 if (len > osd->len_avail - offset)
1361 len = osd->len_avail - offset;
1362 memcpy (readbuf, osd->buffer.buffer + offset, len);
1363
1364 return len;
1365
1366 }
1367
1368 LONGEST
1369 linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
1370 ULONGEST offset, ULONGEST len)
1371 {
1372 if (!annex || *annex == '\0')
1373 {
1374 return common_getter (&osdata_table[0],
1375 readbuf, offset, len);
1376 }
1377 else
1378 {
1379 int i;
1380
1381 for (i = 0; osdata_table[i].type; ++i)
1382 {
1383 if (strcmp (annex, osdata_table[i].type) == 0)
1384 return common_getter (&osdata_table[i],
1385 readbuf, offset, len);
1386 }
1387
1388 return 0;
1389 }
1390 }
This page took 0.088166 seconds and 4 git commands to generate.