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