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