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