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