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 "common/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 "common/xml-utils.h" 36 #include "common/buffer.h" 37 #include <dirent.h> 38 #include <sys/stat.h> 39 #include "common/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 } 1391