1 /* Linux-specific functions to retrieve OS data. 2 3 Copyright (C) 2009-2015 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-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 "xml-utils.h" 36 #include "buffer.h" 37 #include <dirent.h> 38 #include <sys/stat.h> 39 #include "filestuff.h" 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 FILE *f; 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_get_pid (ptid), (PID_T) ptid_get_lwp (ptid)); 74 f = gdb_fopen_cloexec (filename, "r"); 75 if (!f) 76 return -1; 77 78 for (;;) 79 { 80 int n; 81 content = xrealloc (content, content_read + 1024); 82 n = fread (content + content_read, 1, 1024, f); 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 fclose (f); 108 109 return core; 110 } 111 112 /* Finds the command-line of process PID and copies it into COMMAND. 113 At most MAXLEN characters are copied. If the command-line cannot 114 be found, PID is copied into command in text-form. */ 115 116 static void 117 command_from_pid (char *command, int maxlen, PID_T pid) 118 { 119 char *stat_path = xstrprintf ("/proc/%lld/stat", pid); 120 FILE *fp = gdb_fopen_cloexec (stat_path, "r"); 121 122 command[0] = '\0'; 123 124 if (fp) 125 { 126 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in 127 include/linux/sched.h in the Linux kernel sources) plus two 128 (for the brackets). */ 129 char cmd[18]; 130 PID_T stat_pid; 131 int items_read = fscanf (fp, "%lld %17s", &stat_pid, cmd); 132 133 if (items_read == 2 && pid == stat_pid) 134 { 135 cmd[strlen (cmd) - 1] = '\0'; /* Remove trailing parenthesis. */ 136 strncpy (command, cmd + 1, maxlen); /* Ignore leading parenthesis. */ 137 } 138 139 fclose (fp); 140 } 141 else 142 { 143 /* Return the PID if a /proc entry for the process cannot be found. */ 144 snprintf (command, maxlen, "%lld", pid); 145 } 146 147 command[maxlen - 1] = '\0'; /* Ensure string is null-terminated. */ 148 149 xfree (stat_path); 150 } 151 152 /* Returns the command-line of the process with the given PID. The 153 returned string needs to be freed using xfree after use. */ 154 155 static char * 156 commandline_from_pid (PID_T pid) 157 { 158 char *pathname = xstrprintf ("/proc/%lld/cmdline", pid); 159 char *commandline = NULL; 160 FILE *f = gdb_fopen_cloexec (pathname, "r"); 161 162 if (f) 163 { 164 size_t len = 0; 165 166 while (!feof (f)) 167 { 168 char buf[1024]; 169 size_t read_bytes = fread (buf, 1, sizeof (buf), f); 170 171 if (read_bytes) 172 { 173 commandline = (char *) xrealloc (commandline, len + read_bytes + 1); 174 memcpy (commandline + len, buf, read_bytes); 175 len += read_bytes; 176 } 177 } 178 179 fclose (f); 180 181 if (commandline) 182 { 183 size_t i; 184 185 /* Replace null characters with spaces. */ 186 for (i = 0; i < len; ++i) 187 if (commandline[i] == '\0') 188 commandline[i] = ' '; 189 190 commandline[len] = '\0'; 191 } 192 else 193 { 194 /* Return the command in square brackets if the command-line 195 is empty. */ 196 commandline = (char *) xmalloc (32); 197 commandline[0] = '['; 198 command_from_pid (commandline + 1, 31, pid); 199 200 len = strlen (commandline); 201 if (len < 31) 202 strcat (commandline, "]"); 203 } 204 } 205 206 xfree (pathname); 207 208 return commandline; 209 } 210 211 /* Finds the user name for the user UID and copies it into USER. At 212 most MAXLEN characters are copied. */ 213 214 static void 215 user_from_uid (char *user, int maxlen, uid_t uid) 216 { 217 struct passwd *pwentry = getpwuid (uid); 218 219 if (pwentry) 220 { 221 strncpy (user, pwentry->pw_name, maxlen); 222 /* Ensure that the user name is null-terminated. */ 223 user[maxlen - 1] = '\0'; 224 } 225 else 226 user[0] = '\0'; 227 } 228 229 /* Finds the owner of process PID and returns the user id in OWNER. 230 Returns 0 if the owner was found, -1 otherwise. */ 231 232 static int 233 get_process_owner (uid_t *owner, PID_T pid) 234 { 235 struct stat statbuf; 236 char procentry[sizeof ("/proc/") + MAX_PID_T_STRLEN]; 237 238 sprintf (procentry, "/proc/%lld", pid); 239 240 if (stat (procentry, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) 241 { 242 *owner = statbuf.st_uid; 243 return 0; 244 } 245 else 246 return -1; 247 } 248 249 /* Find the CPU cores used by process PID and return them in CORES. 250 CORES points to an array of NUM_CORES elements. */ 251 252 static int 253 get_cores_used_by_process (PID_T pid, int *cores, const int num_cores) 254 { 255 char taskdir[sizeof ("/proc/") + MAX_PID_T_STRLEN + sizeof ("/task") - 1]; 256 DIR *dir; 257 struct dirent *dp; 258 int task_count = 0; 259 260 sprintf (taskdir, "/proc/%lld/task", pid); 261 dir = opendir (taskdir); 262 if (dir) 263 { 264 while ((dp = readdir (dir)) != NULL) 265 { 266 PID_T tid; 267 int core; 268 269 if (!isdigit (dp->d_name[0]) 270 || NAMELEN (dp) > MAX_PID_T_STRLEN) 271 continue; 272 273 sscanf (dp->d_name, "%lld", &tid); 274 core = linux_common_core_of_thread (ptid_build ((pid_t) pid, 275 (pid_t) tid, 0)); 276 277 if (core >= 0 && core < num_cores) 278 { 279 ++cores[core]; 280 ++task_count; 281 } 282 } 283 284 closedir (dir); 285 } 286 287 return task_count; 288 } 289 290 static LONGEST 291 linux_xfer_osdata_processes (gdb_byte *readbuf, 292 ULONGEST offset, ULONGEST len) 293 { 294 /* We make the process list snapshot when the object starts to be read. */ 295 static const char *buf; 296 static LONGEST len_avail = -1; 297 static struct buffer buffer; 298 299 if (offset == 0) 300 { 301 DIR *dirp; 302 303 if (len_avail != -1 && len_avail != 0) 304 buffer_free (&buffer); 305 len_avail = 0; 306 buf = NULL; 307 buffer_init (&buffer); 308 buffer_grow_str (&buffer, "<osdata type=\"processes\">\n"); 309 310 dirp = opendir ("/proc"); 311 if (dirp) 312 { 313 const int num_cores = sysconf (_SC_NPROCESSORS_ONLN); 314 struct dirent *dp; 315 316 while ((dp = readdir (dirp)) != NULL) 317 { 318 PID_T pid; 319 uid_t owner; 320 char user[UT_NAMESIZE]; 321 char *command_line; 322 int *cores; 323 int task_count; 324 char *cores_str; 325 int i; 326 327 if (!isdigit (dp->d_name[0]) 328 || NAMELEN (dp) > MAX_PID_T_STRLEN) 329 continue; 330 331 sscanf (dp->d_name, "%lld", &pid); 332 command_line = commandline_from_pid (pid); 333 334 if (get_process_owner (&owner, pid) == 0) 335 user_from_uid (user, sizeof (user), owner); 336 else 337 strcpy (user, "?"); 338 339 /* Find CPU cores used by the process. */ 340 cores = (int *) xcalloc (num_cores, sizeof (int)); 341 task_count = get_cores_used_by_process (pid, cores, num_cores); 342 cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1); 343 344 for (i = 0; i < num_cores && task_count > 0; ++i) 345 if (cores[i]) 346 { 347 char core_str[sizeof ("4294967295")]; 348 349 sprintf (core_str, "%d", i); 350 strcat (cores_str, core_str); 351 352 task_count -= cores[i]; 353 if (task_count > 0) 354 strcat (cores_str, ","); 355 } 356 357 xfree (cores); 358 359 buffer_xml_printf ( 360 &buffer, 361 "<item>" 362 "<column name=\"pid\">%lld</column>" 363 "<column name=\"user\">%s</column>" 364 "<column name=\"command\">%s</column>" 365 "<column name=\"cores\">%s</column>" 366 "</item>", 367 pid, 368 user, 369 command_line ? command_line : "", 370 cores_str); 371 372 xfree (command_line); 373 xfree (cores_str); 374 } 375 376 closedir (dirp); 377 } 378 379 buffer_grow_str0 (&buffer, "</osdata>\n"); 380 buf = buffer_finish (&buffer); 381 len_avail = strlen (buf); 382 } 383 384 if (offset >= len_avail) 385 { 386 /* Done. Get rid of the buffer. */ 387 buffer_free (&buffer); 388 buf = NULL; 389 len_avail = 0; 390 return 0; 391 } 392 393 if (len > len_avail - offset) 394 len = len_avail - offset; 395 memcpy (readbuf, buf + offset, len); 396 397 return len; 398 } 399 400 /* Auxiliary function used by qsort to sort processes by process 401 group. Compares two processes with ids PROCESS1 and PROCESS2. 402 PROCESS1 comes before PROCESS2 if it has a lower process group id. 403 If they belong to the same process group, PROCESS1 comes before 404 PROCESS2 if it has a lower process id or is the process group 405 leader. */ 406 407 static int 408 compare_processes (const void *process1, const void *process2) 409 { 410 PID_T pid1 = *((PID_T *) process1); 411 PID_T pid2 = *((PID_T *) process2); 412 PID_T pgid1 = *((PID_T *) process1 + 1); 413 PID_T pgid2 = *((PID_T *) process2 + 1); 414 415 /* Sort by PGID. */ 416 if (pgid1 < pgid2) 417 return -1; 418 else if (pgid1 > pgid2) 419 return 1; 420 else 421 { 422 /* Process group leaders always come first, else sort by PID. */ 423 if (pid1 == pgid1) 424 return -1; 425 else if (pid2 == pgid2) 426 return 1; 427 else if (pid1 < pid2) 428 return -1; 429 else if (pid1 > pid2) 430 return 1; 431 else 432 return 0; 433 } 434 } 435 436 /* Collect all process groups from /proc. */ 437 438 static LONGEST 439 linux_xfer_osdata_processgroups (gdb_byte *readbuf, 440 ULONGEST offset, ULONGEST len) 441 { 442 /* We make the process list snapshot when the object starts to be read. */ 443 static const char *buf; 444 static LONGEST len_avail = -1; 445 static struct buffer buffer; 446 447 if (offset == 0) 448 { 449 DIR *dirp; 450 451 if (len_avail != -1 && len_avail != 0) 452 buffer_free (&buffer); 453 len_avail = 0; 454 buf = NULL; 455 buffer_init (&buffer); 456 buffer_grow_str (&buffer, "<osdata type=\"process groups\">\n"); 457 458 dirp = opendir ("/proc"); 459 if (dirp) 460 { 461 struct dirent *dp; 462 const size_t list_block_size = 512; 463 PID_T *process_list = (PID_T *) xmalloc (list_block_size * 2 * sizeof (PID_T)); 464 size_t process_count = 0; 465 size_t i; 466 467 /* Build list consisting of PIDs followed by their 468 associated PGID. */ 469 while ((dp = readdir (dirp)) != NULL) 470 { 471 PID_T pid, pgid; 472 473 if (!isdigit (dp->d_name[0]) 474 || NAMELEN (dp) > MAX_PID_T_STRLEN) 475 continue; 476 477 sscanf (dp->d_name, "%lld", &pid); 478 pgid = getpgid (pid); 479 480 if (pgid > 0) 481 { 482 process_list[2 * process_count] = pid; 483 process_list[2 * process_count + 1] = pgid; 484 ++process_count; 485 486 /* Increase the size of the list if necessary. */ 487 if (process_count % list_block_size == 0) 488 process_list = (PID_T *) xrealloc ( 489 process_list, 490 (process_count + list_block_size) 491 * 2 * sizeof (PID_T)); 492 } 493 } 494 495 closedir (dirp); 496 497 /* Sort the process list. */ 498 qsort (process_list, process_count, 2 * sizeof (PID_T), 499 compare_processes); 500 501 for (i = 0; i < process_count; ++i) 502 { 503 PID_T pid = process_list[2 * i]; 504 PID_T pgid = process_list[2 * i + 1]; 505 char leader_command[32]; 506 char *command_line; 507 508 command_from_pid (leader_command, sizeof (leader_command), pgid); 509 command_line = commandline_from_pid (pid); 510 511 buffer_xml_printf ( 512 &buffer, 513 "<item>" 514 "<column name=\"pgid\">%lld</column>" 515 "<column name=\"leader command\">%s</column>" 516 "<column name=\"pid\">%lld</column>" 517 "<column name=\"command line\">%s</column>" 518 "</item>", 519 pgid, 520 leader_command, 521 pid, 522 command_line ? command_line : ""); 523 524 xfree (command_line); 525 } 526 527 xfree (process_list); 528 } 529 530 buffer_grow_str0 (&buffer, "</osdata>\n"); 531 buf = buffer_finish (&buffer); 532 len_avail = strlen (buf); 533 } 534 535 if (offset >= len_avail) 536 { 537 /* Done. Get rid of the buffer. */ 538 buffer_free (&buffer); 539 buf = NULL; 540 len_avail = 0; 541 return 0; 542 } 543 544 if (len > len_avail - offset) 545 len = len_avail - offset; 546 memcpy (readbuf, buf + offset, len); 547 548 return len; 549 } 550 551 /* Collect all the threads in /proc by iterating through processes and 552 then tasks within each process. */ 553 554 static LONGEST 555 linux_xfer_osdata_threads (gdb_byte *readbuf, 556 ULONGEST offset, ULONGEST len) 557 { 558 /* We make the process list snapshot when the object starts to be read. */ 559 static const char *buf; 560 static LONGEST len_avail = -1; 561 static struct buffer buffer; 562 563 if (offset == 0) 564 { 565 DIR *dirp; 566 567 if (len_avail != -1 && len_avail != 0) 568 buffer_free (&buffer); 569 len_avail = 0; 570 buf = NULL; 571 buffer_init (&buffer); 572 buffer_grow_str (&buffer, "<osdata type=\"threads\">\n"); 573 574 dirp = opendir ("/proc"); 575 if (dirp) 576 { 577 struct dirent *dp; 578 579 while ((dp = readdir (dirp)) != NULL) 580 { 581 struct stat statbuf; 582 char procentry[sizeof ("/proc/4294967295")]; 583 584 if (!isdigit (dp->d_name[0]) 585 || NAMELEN (dp) > sizeof ("4294967295") - 1) 586 continue; 587 588 sprintf (procentry, "/proc/%s", dp->d_name); 589 if (stat (procentry, &statbuf) == 0 590 && S_ISDIR (statbuf.st_mode)) 591 { 592 DIR *dirp2; 593 char *pathname; 594 PID_T pid; 595 char command[32]; 596 597 pathname = xstrprintf ("/proc/%s/task", dp->d_name); 598 599 pid = atoi (dp->d_name); 600 command_from_pid (command, sizeof (command), pid); 601 602 dirp2 = opendir (pathname); 603 604 if (dirp2) 605 { 606 struct dirent *dp2; 607 608 while ((dp2 = readdir (dirp2)) != NULL) 609 { 610 PID_T tid; 611 int core; 612 613 if (!isdigit (dp2->d_name[0]) 614 || NAMELEN (dp2) > sizeof ("4294967295") - 1) 615 continue; 616 617 tid = atoi (dp2->d_name); 618 core = linux_common_core_of_thread (ptid_build (pid, tid, 0)); 619 620 buffer_xml_printf ( 621 &buffer, 622 "<item>" 623 "<column name=\"pid\">%lld</column>" 624 "<column name=\"command\">%s</column>" 625 "<column name=\"tid\">%lld</column>" 626 "<column name=\"core\">%d</column>" 627 "</item>", 628 pid, 629 command, 630 tid, 631 core); 632 } 633 634 closedir (dirp2); 635 } 636 637 xfree (pathname); 638 } 639 } 640 641 closedir (dirp); 642 } 643 644 buffer_grow_str0 (&buffer, "</osdata>\n"); 645 buf = buffer_finish (&buffer); 646 len_avail = strlen (buf); 647 } 648 649 if (offset >= len_avail) 650 { 651 /* Done. Get rid of the buffer. */ 652 buffer_free (&buffer); 653 buf = NULL; 654 len_avail = 0; 655 return 0; 656 } 657 658 if (len > len_avail - offset) 659 len = len_avail - offset; 660 memcpy (readbuf, buf + offset, len); 661 662 return len; 663 } 664 665 /* Collect all the open file descriptors found in /proc and put the details 666 found about them into READBUF. */ 667 668 static LONGEST 669 linux_xfer_osdata_fds (gdb_byte *readbuf, 670 ULONGEST offset, ULONGEST len) 671 { 672 /* We make the process list snapshot when the object starts to be read. */ 673 static const char *buf; 674 static LONGEST len_avail = -1; 675 static struct buffer buffer; 676 677 if (offset == 0) 678 { 679 DIR *dirp; 680 681 if (len_avail != -1 && len_avail != 0) 682 buffer_free (&buffer); 683 len_avail = 0; 684 buf = NULL; 685 buffer_init (&buffer); 686 buffer_grow_str (&buffer, "<osdata type=\"files\">\n"); 687 688 dirp = opendir ("/proc"); 689 if (dirp) 690 { 691 struct dirent *dp; 692 693 while ((dp = readdir (dirp)) != NULL) 694 { 695 struct stat statbuf; 696 char procentry[sizeof ("/proc/4294967295")]; 697 698 if (!isdigit (dp->d_name[0]) 699 || NAMELEN (dp) > sizeof ("4294967295") - 1) 700 continue; 701 702 sprintf (procentry, "/proc/%s", dp->d_name); 703 if (stat (procentry, &statbuf) == 0 704 && S_ISDIR (statbuf.st_mode)) 705 { 706 char *pathname; 707 DIR *dirp2; 708 PID_T pid; 709 char command[32]; 710 711 pid = atoi (dp->d_name); 712 command_from_pid (command, sizeof (command), pid); 713 714 pathname = xstrprintf ("/proc/%s/fd", dp->d_name); 715 dirp2 = opendir (pathname); 716 717 if (dirp2) 718 { 719 struct dirent *dp2; 720 721 while ((dp2 = readdir (dirp2)) != NULL) 722 { 723 char *fdname; 724 char buf[1000]; 725 ssize_t rslt; 726 727 if (!isdigit (dp2->d_name[0])) 728 continue; 729 730 fdname = xstrprintf ("%s/%s", pathname, dp2->d_name); 731 rslt = readlink (fdname, buf, sizeof (buf) - 1); 732 if (rslt >= 0) 733 buf[rslt] = '\0'; 734 735 buffer_xml_printf ( 736 &buffer, 737 "<item>" 738 "<column name=\"pid\">%s</column>" 739 "<column name=\"command\">%s</column>" 740 "<column name=\"file descriptor\">%s</column>" 741 "<column name=\"name\">%s</column>" 742 "</item>", 743 dp->d_name, 744 command, 745 dp2->d_name, 746 (rslt >= 0 ? buf : dp2->d_name)); 747 } 748 749 closedir (dirp2); 750 } 751 752 xfree (pathname); 753 } 754 } 755 756 closedir (dirp); 757 } 758 759 buffer_grow_str0 (&buffer, "</osdata>\n"); 760 buf = buffer_finish (&buffer); 761 len_avail = strlen (buf); 762 } 763 764 if (offset >= len_avail) 765 { 766 /* Done. Get rid of the buffer. */ 767 buffer_free (&buffer); 768 buf = NULL; 769 len_avail = 0; 770 return 0; 771 } 772 773 if (len > len_avail - offset) 774 len = len_avail - offset; 775 memcpy (readbuf, buf + offset, len); 776 777 return len; 778 } 779 780 /* Returns the socket state STATE in textual form. */ 781 782 static const char * 783 format_socket_state (unsigned char state) 784 { 785 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */ 786 enum { 787 TCP_ESTABLISHED = 1, 788 TCP_SYN_SENT, 789 TCP_SYN_RECV, 790 TCP_FIN_WAIT1, 791 TCP_FIN_WAIT2, 792 TCP_TIME_WAIT, 793 TCP_CLOSE, 794 TCP_CLOSE_WAIT, 795 TCP_LAST_ACK, 796 TCP_LISTEN, 797 TCP_CLOSING 798 }; 799 800 switch (state) 801 { 802 case TCP_ESTABLISHED: 803 return "ESTABLISHED"; 804 case TCP_SYN_SENT: 805 return "SYN_SENT"; 806 case TCP_SYN_RECV: 807 return "SYN_RECV"; 808 case TCP_FIN_WAIT1: 809 return "FIN_WAIT1"; 810 case TCP_FIN_WAIT2: 811 return "FIN_WAIT2"; 812 case TCP_TIME_WAIT: 813 return "TIME_WAIT"; 814 case TCP_CLOSE: 815 return "CLOSE"; 816 case TCP_CLOSE_WAIT: 817 return "CLOSE_WAIT"; 818 case TCP_LAST_ACK: 819 return "LAST_ACK"; 820 case TCP_LISTEN: 821 return "LISTEN"; 822 case TCP_CLOSING: 823 return "CLOSING"; 824 default: 825 return "(unknown)"; 826 } 827 } 828 829 union socket_addr 830 { 831 struct sockaddr sa; 832 struct sockaddr_in sin; 833 struct sockaddr_in6 sin6; 834 }; 835 836 /* Auxiliary function used by linux_xfer_osdata_isocket. Formats 837 information for all open internet sockets of type FAMILY on the 838 system into BUFFER. If TCP is set, only TCP sockets are processed, 839 otherwise only UDP sockets are processed. */ 840 841 static void 842 print_sockets (unsigned short family, int tcp, struct buffer *buffer) 843 { 844 const char *proc_file; 845 FILE *fp; 846 847 if (family == AF_INET) 848 proc_file = tcp ? "/proc/net/tcp" : "/proc/net/udp"; 849 else if (family == AF_INET6) 850 proc_file = tcp ? "/proc/net/tcp6" : "/proc/net/udp6"; 851 else 852 return; 853 854 fp = gdb_fopen_cloexec (proc_file, "r"); 855 if (fp) 856 { 857 char buf[8192]; 858 859 do 860 { 861 if (fgets (buf, sizeof (buf), fp)) 862 { 863 uid_t uid; 864 unsigned int local_port, remote_port, state; 865 char local_address[NI_MAXHOST], remote_address[NI_MAXHOST]; 866 int result; 867 868 #if NI_MAXHOST <= 32 869 #error "local_address and remote_address buffers too small" 870 #endif 871 872 result = sscanf (buf, 873 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n", 874 local_address, &local_port, 875 remote_address, &remote_port, 876 &state, 877 &uid); 878 879 if (result == 6) 880 { 881 union socket_addr locaddr, remaddr; 882 size_t addr_size; 883 char user[UT_NAMESIZE]; 884 char local_service[NI_MAXSERV], remote_service[NI_MAXSERV]; 885 886 if (family == AF_INET) 887 { 888 sscanf (local_address, "%X", 889 &locaddr.sin.sin_addr.s_addr); 890 sscanf (remote_address, "%X", 891 &remaddr.sin.sin_addr.s_addr); 892 893 locaddr.sin.sin_port = htons (local_port); 894 remaddr.sin.sin_port = htons (remote_port); 895 896 addr_size = sizeof (struct sockaddr_in); 897 } 898 else 899 { 900 sscanf (local_address, "%8X%8X%8X%8X", 901 locaddr.sin6.sin6_addr.s6_addr32, 902 locaddr.sin6.sin6_addr.s6_addr32 + 1, 903 locaddr.sin6.sin6_addr.s6_addr32 + 2, 904 locaddr.sin6.sin6_addr.s6_addr32 + 3); 905 sscanf (remote_address, "%8X%8X%8X%8X", 906 remaddr.sin6.sin6_addr.s6_addr32, 907 remaddr.sin6.sin6_addr.s6_addr32 + 1, 908 remaddr.sin6.sin6_addr.s6_addr32 + 2, 909 remaddr.sin6.sin6_addr.s6_addr32 + 3); 910 911 locaddr.sin6.sin6_port = htons (local_port); 912 remaddr.sin6.sin6_port = htons (remote_port); 913 914 locaddr.sin6.sin6_flowinfo = 0; 915 remaddr.sin6.sin6_flowinfo = 0; 916 locaddr.sin6.sin6_scope_id = 0; 917 remaddr.sin6.sin6_scope_id = 0; 918 919 addr_size = sizeof (struct sockaddr_in6); 920 } 921 922 locaddr.sa.sa_family = remaddr.sa.sa_family = family; 923 924 result = getnameinfo (&locaddr.sa, addr_size, 925 local_address, sizeof (local_address), 926 local_service, sizeof (local_service), 927 NI_NUMERICHOST | NI_NUMERICSERV 928 | (tcp ? 0 : NI_DGRAM)); 929 if (result) 930 continue; 931 932 result = getnameinfo (&remaddr.sa, addr_size, 933 remote_address, 934 sizeof (remote_address), 935 remote_service, 936 sizeof (remote_service), 937 NI_NUMERICHOST | NI_NUMERICSERV 938 | (tcp ? 0 : NI_DGRAM)); 939 if (result) 940 continue; 941 942 user_from_uid (user, sizeof (user), uid); 943 944 buffer_xml_printf ( 945 buffer, 946 "<item>" 947 "<column name=\"local address\">%s</column>" 948 "<column name=\"local port\">%s</column>" 949 "<column name=\"remote address\">%s</column>" 950 "<column name=\"remote port\">%s</column>" 951 "<column name=\"state\">%s</column>" 952 "<column name=\"user\">%s</column>" 953 "<column name=\"family\">%s</column>" 954 "<column name=\"protocol\">%s</column>" 955 "</item>", 956 local_address, 957 local_service, 958 remote_address, 959 remote_service, 960 format_socket_state (state), 961 user, 962 (family == AF_INET) ? "INET" : "INET6", 963 tcp ? "STREAM" : "DGRAM"); 964 } 965 } 966 } 967 while (!feof (fp)); 968 969 fclose (fp); 970 } 971 } 972 973 /* Collect data about internet sockets and write it into READBUF. */ 974 975 static LONGEST 976 linux_xfer_osdata_isockets (gdb_byte *readbuf, 977 ULONGEST offset, ULONGEST len) 978 { 979 static const char *buf; 980 static LONGEST len_avail = -1; 981 static struct buffer buffer; 982 983 if (offset == 0) 984 { 985 if (len_avail != -1 && len_avail != 0) 986 buffer_free (&buffer); 987 len_avail = 0; 988 buf = NULL; 989 buffer_init (&buffer); 990 buffer_grow_str (&buffer, "<osdata type=\"I sockets\">\n"); 991 992 print_sockets (AF_INET, 1, &buffer); 993 print_sockets (AF_INET, 0, &buffer); 994 print_sockets (AF_INET6, 1, &buffer); 995 print_sockets (AF_INET6, 0, &buffer); 996 997 buffer_grow_str0 (&buffer, "</osdata>\n"); 998 buf = buffer_finish (&buffer); 999 len_avail = strlen (buf); 1000 } 1001 1002 if (offset >= len_avail) 1003 { 1004 /* Done. Get rid of the buffer. */ 1005 buffer_free (&buffer); 1006 buf = NULL; 1007 len_avail = 0; 1008 return 0; 1009 } 1010 1011 if (len > len_avail - offset) 1012 len = len_avail - offset; 1013 memcpy (readbuf, buf + offset, len); 1014 1015 return len; 1016 } 1017 1018 /* Converts the time SECONDS into textual form and copies it into a 1019 buffer TIME, with at most MAXLEN characters copied. */ 1020 1021 static void 1022 time_from_time_t (char *time, int maxlen, TIME_T seconds) 1023 { 1024 if (!seconds) 1025 time[0] = '\0'; 1026 else 1027 { 1028 time_t t = (time_t) seconds; 1029 1030 strncpy (time, ctime (&t), maxlen); 1031 time[maxlen - 1] = '\0'; 1032 } 1033 } 1034 1035 /* Finds the group name for the group GID and copies it into GROUP. 1036 At most MAXLEN characters are copied. */ 1037 1038 static void 1039 group_from_gid (char *group, int maxlen, gid_t gid) 1040 { 1041 struct group *grentry = getgrgid (gid); 1042 1043 if (grentry) 1044 { 1045 strncpy (group, grentry->gr_name, maxlen); 1046 /* Ensure that the group name is null-terminated. */ 1047 group[maxlen - 1] = '\0'; 1048 } 1049 else 1050 group[0] = '\0'; 1051 } 1052 1053 /* Collect data about shared memory recorded in /proc and write it 1054 into READBUF. */ 1055 1056 static LONGEST 1057 linux_xfer_osdata_shm (gdb_byte *readbuf, 1058 ULONGEST offset, ULONGEST len) 1059 { 1060 static const char *buf; 1061 static LONGEST len_avail = -1; 1062 static struct buffer buffer; 1063 1064 if (offset == 0) 1065 { 1066 FILE *fp; 1067 1068 if (len_avail != -1 && len_avail != 0) 1069 buffer_free (&buffer); 1070 len_avail = 0; 1071 buf = NULL; 1072 buffer_init (&buffer); 1073 buffer_grow_str (&buffer, "<osdata type=\"shared memory\">\n"); 1074 1075 fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r"); 1076 if (fp) 1077 { 1078 char buf[8192]; 1079 1080 do 1081 { 1082 if (fgets (buf, sizeof (buf), fp)) 1083 { 1084 key_t key; 1085 uid_t uid, cuid; 1086 gid_t gid, cgid; 1087 PID_T cpid, lpid; 1088 int shmid, size, nattch; 1089 TIME_T atime, dtime, ctime; 1090 unsigned int perms; 1091 int items_read; 1092 1093 items_read = sscanf (buf, 1094 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld", 1095 &key, &shmid, &perms, &size, 1096 &cpid, &lpid, 1097 &nattch, 1098 &uid, &gid, &cuid, &cgid, 1099 &atime, &dtime, &ctime); 1100 1101 if (items_read == 14) 1102 { 1103 char user[UT_NAMESIZE], group[UT_NAMESIZE]; 1104 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE]; 1105 char ccmd[32], lcmd[32]; 1106 char atime_str[32], dtime_str[32], ctime_str[32]; 1107 1108 user_from_uid (user, sizeof (user), uid); 1109 group_from_gid (group, sizeof (group), gid); 1110 user_from_uid (cuser, sizeof (cuser), cuid); 1111 group_from_gid (cgroup, sizeof (cgroup), cgid); 1112 1113 command_from_pid (ccmd, sizeof (ccmd), cpid); 1114 command_from_pid (lcmd, sizeof (lcmd), lpid); 1115 1116 time_from_time_t (atime_str, sizeof (atime_str), atime); 1117 time_from_time_t (dtime_str, sizeof (dtime_str), dtime); 1118 time_from_time_t (ctime_str, sizeof (ctime_str), ctime); 1119 1120 buffer_xml_printf ( 1121 &buffer, 1122 "<item>" 1123 "<column name=\"key\">%d</column>" 1124 "<column name=\"shmid\">%d</column>" 1125 "<column name=\"permissions\">%o</column>" 1126 "<column name=\"size\">%d</column>" 1127 "<column name=\"creator command\">%s</column>" 1128 "<column name=\"last op. command\">%s</column>" 1129 "<column name=\"num attached\">%d</column>" 1130 "<column name=\"user\">%s</column>" 1131 "<column name=\"group\">%s</column>" 1132 "<column name=\"creator user\">%s</column>" 1133 "<column name=\"creator group\">%s</column>" 1134 "<column name=\"last shmat() time\">%s</column>" 1135 "<column name=\"last shmdt() time\">%s</column>" 1136 "<column name=\"last shmctl() time\">%s</column>" 1137 "</item>", 1138 key, 1139 shmid, 1140 perms, 1141 size, 1142 ccmd, 1143 lcmd, 1144 nattch, 1145 user, 1146 group, 1147 cuser, 1148 cgroup, 1149 atime_str, 1150 dtime_str, 1151 ctime_str); 1152 } 1153 } 1154 } 1155 while (!feof (fp)); 1156 1157 fclose (fp); 1158 } 1159 1160 buffer_grow_str0 (&buffer, "</osdata>\n"); 1161 buf = buffer_finish (&buffer); 1162 len_avail = strlen (buf); 1163 } 1164 1165 if (offset >= len_avail) 1166 { 1167 /* Done. Get rid of the buffer. */ 1168 buffer_free (&buffer); 1169 buf = NULL; 1170 len_avail = 0; 1171 return 0; 1172 } 1173 1174 if (len > len_avail - offset) 1175 len = len_avail - offset; 1176 memcpy (readbuf, buf + offset, len); 1177 1178 return len; 1179 } 1180 1181 /* Collect data about semaphores recorded in /proc and write it 1182 into READBUF. */ 1183 1184 static LONGEST 1185 linux_xfer_osdata_sem (gdb_byte *readbuf, 1186 ULONGEST offset, ULONGEST len) 1187 { 1188 static const char *buf; 1189 static LONGEST len_avail = -1; 1190 static struct buffer buffer; 1191 1192 if (offset == 0) 1193 { 1194 FILE *fp; 1195 1196 if (len_avail != -1 && len_avail != 0) 1197 buffer_free (&buffer); 1198 len_avail = 0; 1199 buf = NULL; 1200 buffer_init (&buffer); 1201 buffer_grow_str (&buffer, "<osdata type=\"semaphores\">\n"); 1202 1203 fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r"); 1204 if (fp) 1205 { 1206 char buf[8192]; 1207 1208 do 1209 { 1210 if (fgets (buf, sizeof (buf), fp)) 1211 { 1212 key_t key; 1213 uid_t uid, cuid; 1214 gid_t gid, cgid; 1215 unsigned int perms, nsems; 1216 int semid; 1217 TIME_T otime, ctime; 1218 int items_read; 1219 1220 items_read = sscanf (buf, 1221 "%d %d %o %u %d %d %d %d %lld %lld", 1222 &key, &semid, &perms, &nsems, 1223 &uid, &gid, &cuid, &cgid, 1224 &otime, &ctime); 1225 1226 if (items_read == 10) 1227 { 1228 char user[UT_NAMESIZE], group[UT_NAMESIZE]; 1229 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE]; 1230 char otime_str[32], ctime_str[32]; 1231 1232 user_from_uid (user, sizeof (user), uid); 1233 group_from_gid (group, sizeof (group), gid); 1234 user_from_uid (cuser, sizeof (cuser), cuid); 1235 group_from_gid (cgroup, sizeof (cgroup), cgid); 1236 1237 time_from_time_t (otime_str, sizeof (otime_str), otime); 1238 time_from_time_t (ctime_str, sizeof (ctime_str), ctime); 1239 1240 buffer_xml_printf ( 1241 &buffer, 1242 "<item>" 1243 "<column name=\"key\">%d</column>" 1244 "<column name=\"semid\">%d</column>" 1245 "<column name=\"permissions\">%o</column>" 1246 "<column name=\"num semaphores\">%u</column>" 1247 "<column name=\"user\">%s</column>" 1248 "<column name=\"group\">%s</column>" 1249 "<column name=\"creator user\">%s</column>" 1250 "<column name=\"creator group\">%s</column>" 1251 "<column name=\"last semop() time\">%s</column>" 1252 "<column name=\"last semctl() time\">%s</column>" 1253 "</item>", 1254 key, 1255 semid, 1256 perms, 1257 nsems, 1258 user, 1259 group, 1260 cuser, 1261 cgroup, 1262 otime_str, 1263 ctime_str); 1264 } 1265 } 1266 } 1267 while (!feof (fp)); 1268 1269 fclose (fp); 1270 } 1271 1272 buffer_grow_str0 (&buffer, "</osdata>\n"); 1273 buf = buffer_finish (&buffer); 1274 len_avail = strlen (buf); 1275 } 1276 1277 if (offset >= len_avail) 1278 { 1279 /* Done. Get rid of the buffer. */ 1280 buffer_free (&buffer); 1281 buf = NULL; 1282 len_avail = 0; 1283 return 0; 1284 } 1285 1286 if (len > len_avail - offset) 1287 len = len_avail - offset; 1288 memcpy (readbuf, buf + offset, len); 1289 1290 return len; 1291 } 1292 1293 /* Collect data about message queues recorded in /proc and write it 1294 into READBUF. */ 1295 1296 static LONGEST 1297 linux_xfer_osdata_msg (gdb_byte *readbuf, 1298 ULONGEST offset, ULONGEST len) 1299 { 1300 static const char *buf; 1301 static LONGEST len_avail = -1; 1302 static struct buffer buffer; 1303 1304 if (offset == 0) 1305 { 1306 FILE *fp; 1307 1308 if (len_avail != -1 && len_avail != 0) 1309 buffer_free (&buffer); 1310 len_avail = 0; 1311 buf = NULL; 1312 buffer_init (&buffer); 1313 buffer_grow_str (&buffer, "<osdata type=\"message queues\">\n"); 1314 1315 fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r"); 1316 if (fp) 1317 { 1318 char buf[8192]; 1319 1320 do 1321 { 1322 if (fgets (buf, sizeof (buf), fp)) 1323 { 1324 key_t key; 1325 PID_T lspid, lrpid; 1326 uid_t uid, cuid; 1327 gid_t gid, cgid; 1328 unsigned int perms, cbytes, qnum; 1329 int msqid; 1330 TIME_T stime, rtime, ctime; 1331 int items_read; 1332 1333 items_read = sscanf (buf, 1334 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld", 1335 &key, &msqid, &perms, &cbytes, &qnum, 1336 &lspid, &lrpid, &uid, &gid, &cuid, &cgid, 1337 &stime, &rtime, &ctime); 1338 1339 if (items_read == 14) 1340 { 1341 char user[UT_NAMESIZE], group[UT_NAMESIZE]; 1342 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE]; 1343 char lscmd[32], lrcmd[32]; 1344 char stime_str[32], rtime_str[32], ctime_str[32]; 1345 1346 user_from_uid (user, sizeof (user), uid); 1347 group_from_gid (group, sizeof (group), gid); 1348 user_from_uid (cuser, sizeof (cuser), cuid); 1349 group_from_gid (cgroup, sizeof (cgroup), cgid); 1350 1351 command_from_pid (lscmd, sizeof (lscmd), lspid); 1352 command_from_pid (lrcmd, sizeof (lrcmd), lrpid); 1353 1354 time_from_time_t (stime_str, sizeof (stime_str), stime); 1355 time_from_time_t (rtime_str, sizeof (rtime_str), rtime); 1356 time_from_time_t (ctime_str, sizeof (ctime_str), ctime); 1357 1358 buffer_xml_printf ( 1359 &buffer, 1360 "<item>" 1361 "<column name=\"key\">%d</column>" 1362 "<column name=\"msqid\">%d</column>" 1363 "<column name=\"permissions\">%o</column>" 1364 "<column name=\"num used bytes\">%u</column>" 1365 "<column name=\"num messages\">%u</column>" 1366 "<column name=\"last msgsnd() command\">%s</column>" 1367 "<column name=\"last msgrcv() command\">%s</column>" 1368 "<column name=\"user\">%s</column>" 1369 "<column name=\"group\">%s</column>" 1370 "<column name=\"creator user\">%s</column>" 1371 "<column name=\"creator group\">%s</column>" 1372 "<column name=\"last msgsnd() time\">%s</column>" 1373 "<column name=\"last msgrcv() time\">%s</column>" 1374 "<column name=\"last msgctl() time\">%s</column>" 1375 "</item>", 1376 key, 1377 msqid, 1378 perms, 1379 cbytes, 1380 qnum, 1381 lscmd, 1382 lrcmd, 1383 user, 1384 group, 1385 cuser, 1386 cgroup, 1387 stime_str, 1388 rtime_str, 1389 ctime_str); 1390 } 1391 } 1392 } 1393 while (!feof (fp)); 1394 1395 fclose (fp); 1396 } 1397 1398 buffer_grow_str0 (&buffer, "</osdata>\n"); 1399 buf = buffer_finish (&buffer); 1400 len_avail = strlen (buf); 1401 } 1402 1403 if (offset >= len_avail) 1404 { 1405 /* Done. Get rid of the buffer. */ 1406 buffer_free (&buffer); 1407 buf = NULL; 1408 len_avail = 0; 1409 return 0; 1410 } 1411 1412 if (len > len_avail - offset) 1413 len = len_avail - offset; 1414 memcpy (readbuf, buf + offset, len); 1415 1416 return len; 1417 } 1418 1419 /* Collect data about loaded kernel modules and write it into 1420 READBUF. */ 1421 1422 static LONGEST 1423 linux_xfer_osdata_modules (gdb_byte *readbuf, 1424 ULONGEST offset, ULONGEST len) 1425 { 1426 static const char *buf; 1427 static LONGEST len_avail = -1; 1428 static struct buffer buffer; 1429 1430 if (offset == 0) 1431 { 1432 FILE *fp; 1433 1434 if (len_avail != -1 && len_avail != 0) 1435 buffer_free (&buffer); 1436 len_avail = 0; 1437 buf = NULL; 1438 buffer_init (&buffer); 1439 buffer_grow_str (&buffer, "<osdata type=\"modules\">\n"); 1440 1441 fp = gdb_fopen_cloexec ("/proc/modules", "r"); 1442 if (fp) 1443 { 1444 char buf[8192]; 1445 1446 do 1447 { 1448 if (fgets (buf, sizeof (buf), fp)) 1449 { 1450 char *name, *dependencies, *status, *tmp; 1451 unsigned int size; 1452 unsigned long long address; 1453 int uses; 1454 1455 name = strtok (buf, " "); 1456 if (name == NULL) 1457 continue; 1458 1459 tmp = strtok (NULL, " "); 1460 if (tmp == NULL) 1461 continue; 1462 if (sscanf (tmp, "%u", &size) != 1) 1463 continue; 1464 1465 tmp = strtok (NULL, " "); 1466 if (tmp == NULL) 1467 continue; 1468 if (sscanf (tmp, "%d", &uses) != 1) 1469 continue; 1470 1471 dependencies = strtok (NULL, " "); 1472 if (dependencies == NULL) 1473 continue; 1474 1475 status = strtok (NULL, " "); 1476 if (status == NULL) 1477 continue; 1478 1479 tmp = strtok (NULL, "\n"); 1480 if (tmp == NULL) 1481 continue; 1482 if (sscanf (tmp, "%llx", &address) != 1) 1483 continue; 1484 1485 buffer_xml_printf ( 1486 &buffer, 1487 "<item>" 1488 "<column name=\"name\">%s</column>" 1489 "<column name=\"size\">%u</column>" 1490 "<column name=\"num uses\">%d</column>" 1491 "<column name=\"dependencies\">%s</column>" 1492 "<column name=\"status\">%s</column>" 1493 "<column name=\"address\">%llx</column>" 1494 "</item>", 1495 name, 1496 size, 1497 uses, 1498 dependencies, 1499 status, 1500 address); 1501 } 1502 } 1503 while (!feof (fp)); 1504 1505 fclose (fp); 1506 } 1507 1508 buffer_grow_str0 (&buffer, "</osdata>\n"); 1509 buf = buffer_finish (&buffer); 1510 len_avail = strlen (buf); 1511 } 1512 1513 if (offset >= len_avail) 1514 { 1515 /* Done. Get rid of the buffer. */ 1516 buffer_free (&buffer); 1517 buf = NULL; 1518 len_avail = 0; 1519 return 0; 1520 } 1521 1522 if (len > len_avail - offset) 1523 len = len_avail - offset; 1524 memcpy (readbuf, buf + offset, len); 1525 1526 return len; 1527 } 1528 1529 struct osdata_type { 1530 char *type; 1531 char *title; 1532 char *description; 1533 LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, ULONGEST len); 1534 } osdata_table[] = { 1535 { "processes", "Processes", "Listing of all processes", 1536 linux_xfer_osdata_processes }, 1537 { "procgroups", "Process groups", "Listing of all process groups", 1538 linux_xfer_osdata_processgroups }, 1539 { "threads", "Threads", "Listing of all threads", 1540 linux_xfer_osdata_threads }, 1541 { "files", "File descriptors", "Listing of all file descriptors", 1542 linux_xfer_osdata_fds }, 1543 { "sockets", "Sockets", "Listing of all internet-domain sockets", 1544 linux_xfer_osdata_isockets }, 1545 { "shm", "Shared-memory regions", "Listing of all shared-memory regions", 1546 linux_xfer_osdata_shm }, 1547 { "semaphores", "Semaphores", "Listing of all semaphores", 1548 linux_xfer_osdata_sem }, 1549 { "msg", "Message queues", "Listing of all message queues", 1550 linux_xfer_osdata_msg }, 1551 { "modules", "Kernel modules", "Listing of all loaded kernel modules", 1552 linux_xfer_osdata_modules }, 1553 { NULL, NULL, NULL } 1554 }; 1555 1556 LONGEST 1557 linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf, 1558 ULONGEST offset, ULONGEST len) 1559 { 1560 if (!annex || *annex == '\0') 1561 { 1562 static const char *buf; 1563 static LONGEST len_avail = -1; 1564 static struct buffer buffer; 1565 1566 if (offset == 0) 1567 { 1568 int i; 1569 1570 if (len_avail != -1 && len_avail != 0) 1571 buffer_free (&buffer); 1572 len_avail = 0; 1573 buf = NULL; 1574 buffer_init (&buffer); 1575 buffer_grow_str (&buffer, "<osdata type=\"types\">\n"); 1576 1577 for (i = 0; osdata_table[i].type; ++i) 1578 buffer_xml_printf ( 1579 &buffer, 1580 "<item>" 1581 "<column name=\"Type\">%s</column>" 1582 "<column name=\"Description\">%s</column>" 1583 "<column name=\"Title\">%s</column>" 1584 "</item>", 1585 osdata_table[i].type, 1586 osdata_table[i].description, 1587 osdata_table[i].title); 1588 1589 buffer_grow_str0 (&buffer, "</osdata>\n"); 1590 buf = buffer_finish (&buffer); 1591 len_avail = strlen (buf); 1592 } 1593 1594 if (offset >= len_avail) 1595 { 1596 /* Done. Get rid of the buffer. */ 1597 buffer_free (&buffer); 1598 buf = NULL; 1599 len_avail = 0; 1600 return 0; 1601 } 1602 1603 if (len > len_avail - offset) 1604 len = len_avail - offset; 1605 memcpy (readbuf, buf + offset, len); 1606 1607 return len; 1608 } 1609 else 1610 { 1611 int i; 1612 1613 for (i = 0; osdata_table[i].type; ++i) 1614 { 1615 if (strcmp (annex, osdata_table[i].type) == 0) 1616 { 1617 gdb_assert (readbuf); 1618 1619 return (osdata_table[i].getter) (readbuf, offset, len); 1620 } 1621 } 1622 1623 return 0; 1624 } 1625 } 1626 1627