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