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