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