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