Introduce and use ui_out_emit_table
[deliverable/binutils-gdb.git] / gdb / nat / linux-osdata.c
CommitLineData
d26e3629
KY
1/* Linux-specific functions to retrieve OS data.
2
61baf725 3 Copyright (C) 2009-2017 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;
224c3ddb 81 content = (char *) xrealloc (content, content_read + 1024);
d26e3629
KY
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. */
8d749320 340 cores = XCNEWVEC (int, num_cores);
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;
8d749320 463 PID_T *process_list = XNEWVEC (PID_T, list_block_size * 2);
85d4a676
SS
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
97e64e5a
YQ
588 xsnprintf (procentry, sizeof (procentry), "/proc/%s",
589 dp->d_name);
d26e3629
KY
590 if (stat (procentry, &statbuf) == 0
591 && S_ISDIR (statbuf.st_mode))
592 {
593 DIR *dirp2;
594 char *pathname;
85d4a676 595 PID_T pid;
d26e3629
KY
596 char command[32];
597
598 pathname = xstrprintf ("/proc/%s/task", dp->d_name);
599
600 pid = atoi (dp->d_name);
601 command_from_pid (command, sizeof (command), pid);
602
603 dirp2 = opendir (pathname);
604
605 if (dirp2)
606 {
607 struct dirent *dp2;
608
609 while ((dp2 = readdir (dirp2)) != NULL)
610 {
85d4a676 611 PID_T tid;
d26e3629
KY
612 int core;
613
614 if (!isdigit (dp2->d_name[0])
615 || NAMELEN (dp2) > sizeof ("4294967295") - 1)
616 continue;
617
618 tid = atoi (dp2->d_name);
619 core = linux_common_core_of_thread (ptid_build (pid, tid, 0));
620
621 buffer_xml_printf (
622 &buffer,
623 "<item>"
85d4a676 624 "<column name=\"pid\">%lld</column>"
d26e3629 625 "<column name=\"command\">%s</column>"
85d4a676 626 "<column name=\"tid\">%lld</column>"
d26e3629
KY
627 "<column name=\"core\">%d</column>"
628 "</item>",
629 pid,
630 command,
631 tid,
632 core);
633 }
634
635 closedir (dirp2);
636 }
637
638 xfree (pathname);
639 }
640 }
641
642 closedir (dirp);
643 }
644
645 buffer_grow_str0 (&buffer, "</osdata>\n");
646 buf = buffer_finish (&buffer);
647 len_avail = strlen (buf);
648 }
649
650 if (offset >= len_avail)
651 {
652 /* Done. Get rid of the buffer. */
653 buffer_free (&buffer);
654 buf = NULL;
655 len_avail = 0;
656 return 0;
657 }
658
659 if (len > len_avail - offset)
660 len = len_avail - offset;
661 memcpy (readbuf, buf + offset, len);
662
663 return len;
664}
665
d33279b3
AT
666/* Collect data about the cpus/cores on the system */
667
668static LONGEST
669linux_xfer_osdata_cpus (gdb_byte *readbuf,
670 ULONGEST offset, ULONGEST len)
671{
672 static const char *buf;
673 static LONGEST len_avail = -1;
674 static struct buffer buffer;
675
676 if (offset == 0)
677 {
678 FILE *fp;
679 int first_item = 1;
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=\"cpus\">\n");
687
688 fp = gdb_fopen_cloexec ("/proc/cpuinfo", "r");
689 if (fp != NULL)
690 {
691 char buf[8192];
692
693 do
694 {
695 if (fgets (buf, sizeof (buf), fp))
696 {
697 char *key, *value;
698 int i = 0;
699
700 key = strtok (buf, ":");
701 if (key == NULL)
702 continue;
703
704 value = strtok (NULL, ":");
705 if (value == NULL)
706 continue;
707
708 while (key[i] != '\t' && key[i] != '\0')
709 i++;
710
711 key[i] = '\0';
712
713 i = 0;
714 while (value[i] != '\t' && value[i] != '\0')
715 i++;
716
717 value[i] = '\0';
718
719 if (strcmp (key, "processor") == 0)
720 {
721 if (first_item)
722 buffer_grow_str (&buffer, "<item>");
723 else
724 buffer_grow_str (&buffer, "</item><item>");
725
726 first_item = 0;
727 }
728
729 buffer_xml_printf (&buffer,
730 "<column name=\"%s\">%s</column>",
731 key,
732 value);
733 }
734 }
735 while (!feof (fp));
736
737 if (first_item == 0)
738 buffer_grow_str (&buffer, "</item>");
739
740 fclose (fp);
741 }
742
743 buffer_grow_str0 (&buffer, "</osdata>\n");
744 buf = buffer_finish (&buffer);
745 len_avail = strlen (buf);
746 }
747
748 if (offset >= len_avail)
749 {
750 /* Done. Get rid of the buffer. */
751 buffer_free (&buffer);
752 buf = NULL;
753 len_avail = 0;
754 return 0;
755 }
756
757 if (len > len_avail - offset)
758 len = len_avail - offset;
759 memcpy (readbuf, buf + offset, len);
760
761 return len;
762}
763
85d4a676
SS
764/* Collect all the open file descriptors found in /proc and put the details
765 found about them into READBUF. */
766
767static LONGEST
768linux_xfer_osdata_fds (gdb_byte *readbuf,
dea80a27 769 ULONGEST offset, ULONGEST len)
85d4a676
SS
770{
771 /* We make the process list snapshot when the object starts to be read. */
772 static const char *buf;
773 static LONGEST len_avail = -1;
774 static struct buffer buffer;
775
776 if (offset == 0)
777 {
778 DIR *dirp;
779
780 if (len_avail != -1 && len_avail != 0)
781 buffer_free (&buffer);
782 len_avail = 0;
783 buf = NULL;
784 buffer_init (&buffer);
785 buffer_grow_str (&buffer, "<osdata type=\"files\">\n");
786
787 dirp = opendir ("/proc");
788 if (dirp)
789 {
790 struct dirent *dp;
791
792 while ((dp = readdir (dirp)) != NULL)
793 {
794 struct stat statbuf;
795 char procentry[sizeof ("/proc/4294967295")];
796
797 if (!isdigit (dp->d_name[0])
798 || NAMELEN (dp) > sizeof ("4294967295") - 1)
799 continue;
800
97e64e5a
YQ
801 xsnprintf (procentry, sizeof (procentry), "/proc/%s",
802 dp->d_name);
85d4a676
SS
803 if (stat (procentry, &statbuf) == 0
804 && S_ISDIR (statbuf.st_mode))
805 {
806 char *pathname;
807 DIR *dirp2;
808 PID_T pid;
809 char command[32];
810
811 pid = atoi (dp->d_name);
812 command_from_pid (command, sizeof (command), pid);
813
814 pathname = xstrprintf ("/proc/%s/fd", dp->d_name);
815 dirp2 = opendir (pathname);
816
817 if (dirp2)
818 {
819 struct dirent *dp2;
820
821 while ((dp2 = readdir (dirp2)) != NULL)
822 {
823 char *fdname;
824 char buf[1000];
825 ssize_t rslt;
826
827 if (!isdigit (dp2->d_name[0]))
828 continue;
829
830 fdname = xstrprintf ("%s/%s", pathname, dp2->d_name);
0270a750 831 rslt = readlink (fdname, buf, sizeof (buf) - 1);
85d4a676
SS
832 if (rslt >= 0)
833 buf[rslt] = '\0';
834
835 buffer_xml_printf (
836 &buffer,
837 "<item>"
838 "<column name=\"pid\">%s</column>"
839 "<column name=\"command\">%s</column>"
840 "<column name=\"file descriptor\">%s</column>"
841 "<column name=\"name\">%s</column>"
842 "</item>",
843 dp->d_name,
844 command,
845 dp2->d_name,
846 (rslt >= 0 ? buf : dp2->d_name));
847 }
848
849 closedir (dirp2);
850 }
851
852 xfree (pathname);
853 }
854 }
855
856 closedir (dirp);
857 }
858
859 buffer_grow_str0 (&buffer, "</osdata>\n");
860 buf = buffer_finish (&buffer);
861 len_avail = strlen (buf);
862 }
863
864 if (offset >= len_avail)
865 {
866 /* Done. Get rid of the buffer. */
867 buffer_free (&buffer);
868 buf = NULL;
869 len_avail = 0;
870 return 0;
871 }
872
873 if (len > len_avail - offset)
874 len = len_avail - offset;
875 memcpy (readbuf, buf + offset, len);
876
877 return len;
878}
879
880/* Returns the socket state STATE in textual form. */
881
882static const char *
883format_socket_state (unsigned char state)
884{
885 /* Copied from include/net/tcp_states.h in the Linux kernel sources. */
886 enum {
887 TCP_ESTABLISHED = 1,
888 TCP_SYN_SENT,
889 TCP_SYN_RECV,
890 TCP_FIN_WAIT1,
891 TCP_FIN_WAIT2,
892 TCP_TIME_WAIT,
893 TCP_CLOSE,
894 TCP_CLOSE_WAIT,
895 TCP_LAST_ACK,
896 TCP_LISTEN,
897 TCP_CLOSING
898 };
899
900 switch (state)
901 {
902 case TCP_ESTABLISHED:
903 return "ESTABLISHED";
904 case TCP_SYN_SENT:
905 return "SYN_SENT";
906 case TCP_SYN_RECV:
907 return "SYN_RECV";
908 case TCP_FIN_WAIT1:
909 return "FIN_WAIT1";
910 case TCP_FIN_WAIT2:
911 return "FIN_WAIT2";
912 case TCP_TIME_WAIT:
913 return "TIME_WAIT";
914 case TCP_CLOSE:
915 return "CLOSE";
916 case TCP_CLOSE_WAIT:
917 return "CLOSE_WAIT";
918 case TCP_LAST_ACK:
919 return "LAST_ACK";
920 case TCP_LISTEN:
921 return "LISTEN";
922 case TCP_CLOSING:
923 return "CLOSING";
924 default:
925 return "(unknown)";
926 }
927}
928
929union socket_addr
930 {
931 struct sockaddr sa;
932 struct sockaddr_in sin;
933 struct sockaddr_in6 sin6;
934 };
935
936/* Auxiliary function used by linux_xfer_osdata_isocket. Formats
937 information for all open internet sockets of type FAMILY on the
938 system into BUFFER. If TCP is set, only TCP sockets are processed,
939 otherwise only UDP sockets are processed. */
940
941static void
942print_sockets (unsigned short family, int tcp, struct buffer *buffer)
943{
944 const char *proc_file;
945 FILE *fp;
946
947 if (family == AF_INET)
948 proc_file = tcp ? "/proc/net/tcp" : "/proc/net/udp";
949 else if (family == AF_INET6)
950 proc_file = tcp ? "/proc/net/tcp6" : "/proc/net/udp6";
951 else
952 return;
953
614c279d 954 fp = gdb_fopen_cloexec (proc_file, "r");
85d4a676
SS
955 if (fp)
956 {
957 char buf[8192];
958
959 do
960 {
961 if (fgets (buf, sizeof (buf), fp))
962 {
963 uid_t uid;
85d4a676 964 unsigned int local_port, remote_port, state;
85d4a676 965 char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
85d4a676
SS
966 int result;
967
f60db4f0
GB
968#if NI_MAXHOST <= 32
969#error "local_address and remote_address buffers too small"
970#endif
971
85d4a676 972 result = sscanf (buf,
f60db4f0 973 "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
85d4a676
SS
974 local_address, &local_port,
975 remote_address, &remote_port,
976 &state,
f60db4f0 977 &uid);
85d4a676 978
f60db4f0 979 if (result == 6)
85d4a676
SS
980 {
981 union socket_addr locaddr, remaddr;
982 size_t addr_size;
983 char user[UT_NAMESIZE];
984 char local_service[NI_MAXSERV], remote_service[NI_MAXSERV];
985
986 if (family == AF_INET)
987 {
988 sscanf (local_address, "%X",
989 &locaddr.sin.sin_addr.s_addr);
990 sscanf (remote_address, "%X",
991 &remaddr.sin.sin_addr.s_addr);
992
993 locaddr.sin.sin_port = htons (local_port);
994 remaddr.sin.sin_port = htons (remote_port);
995
996 addr_size = sizeof (struct sockaddr_in);
997 }
998 else
999 {
1000 sscanf (local_address, "%8X%8X%8X%8X",
1001 locaddr.sin6.sin6_addr.s6_addr32,
1002 locaddr.sin6.sin6_addr.s6_addr32 + 1,
1003 locaddr.sin6.sin6_addr.s6_addr32 + 2,
1004 locaddr.sin6.sin6_addr.s6_addr32 + 3);
1005 sscanf (remote_address, "%8X%8X%8X%8X",
1006 remaddr.sin6.sin6_addr.s6_addr32,
1007 remaddr.sin6.sin6_addr.s6_addr32 + 1,
1008 remaddr.sin6.sin6_addr.s6_addr32 + 2,
1009 remaddr.sin6.sin6_addr.s6_addr32 + 3);
1010
1011 locaddr.sin6.sin6_port = htons (local_port);
1012 remaddr.sin6.sin6_port = htons (remote_port);
1013
1014 locaddr.sin6.sin6_flowinfo = 0;
1015 remaddr.sin6.sin6_flowinfo = 0;
1016 locaddr.sin6.sin6_scope_id = 0;
1017 remaddr.sin6.sin6_scope_id = 0;
1018
1019 addr_size = sizeof (struct sockaddr_in6);
1020 }
1021
1022 locaddr.sa.sa_family = remaddr.sa.sa_family = family;
1023
1024 result = getnameinfo (&locaddr.sa, addr_size,
1025 local_address, sizeof (local_address),
1026 local_service, sizeof (local_service),
1027 NI_NUMERICHOST | NI_NUMERICSERV
1028 | (tcp ? 0 : NI_DGRAM));
1029 if (result)
1030 continue;
1031
1032 result = getnameinfo (&remaddr.sa, addr_size,
1033 remote_address,
1034 sizeof (remote_address),
1035 remote_service,
1036 sizeof (remote_service),
1037 NI_NUMERICHOST | NI_NUMERICSERV
1038 | (tcp ? 0 : NI_DGRAM));
1039 if (result)
1040 continue;
1041
1042 user_from_uid (user, sizeof (user), uid);
1043
1044 buffer_xml_printf (
1045 buffer,
1046 "<item>"
1047 "<column name=\"local address\">%s</column>"
1048 "<column name=\"local port\">%s</column>"
1049 "<column name=\"remote address\">%s</column>"
1050 "<column name=\"remote port\">%s</column>"
1051 "<column name=\"state\">%s</column>"
1052 "<column name=\"user\">%s</column>"
1053 "<column name=\"family\">%s</column>"
1054 "<column name=\"protocol\">%s</column>"
1055 "</item>",
1056 local_address,
1057 local_service,
1058 remote_address,
1059 remote_service,
1060 format_socket_state (state),
1061 user,
1062 (family == AF_INET) ? "INET" : "INET6",
1063 tcp ? "STREAM" : "DGRAM");
1064 }
1065 }
1066 }
1067 while (!feof (fp));
1068
1069 fclose (fp);
1070 }
1071}
1072
1073/* Collect data about internet sockets and write it into READBUF. */
1074
1075static LONGEST
1076linux_xfer_osdata_isockets (gdb_byte *readbuf,
dea80a27 1077 ULONGEST offset, ULONGEST len)
85d4a676
SS
1078{
1079 static const char *buf;
1080 static LONGEST len_avail = -1;
1081 static struct buffer buffer;
1082
1083 if (offset == 0)
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=\"I sockets\">\n");
1091
1092 print_sockets (AF_INET, 1, &buffer);
1093 print_sockets (AF_INET, 0, &buffer);
1094 print_sockets (AF_INET6, 1, &buffer);
1095 print_sockets (AF_INET6, 0, &buffer);
1096
1097 buffer_grow_str0 (&buffer, "</osdata>\n");
1098 buf = buffer_finish (&buffer);
1099 len_avail = strlen (buf);
1100 }
1101
1102 if (offset >= len_avail)
1103 {
1104 /* Done. Get rid of the buffer. */
1105 buffer_free (&buffer);
1106 buf = NULL;
1107 len_avail = 0;
1108 return 0;
1109 }
1110
1111 if (len > len_avail - offset)
1112 len = len_avail - offset;
1113 memcpy (readbuf, buf + offset, len);
1114
1115 return len;
1116}
1117
1118/* Converts the time SECONDS into textual form and copies it into a
1119 buffer TIME, with at most MAXLEN characters copied. */
1120
1121static void
1122time_from_time_t (char *time, int maxlen, TIME_T seconds)
1123{
1124 if (!seconds)
1125 time[0] = '\0';
1126 else
1127 {
1128 time_t t = (time_t) seconds;
1129
1130 strncpy (time, ctime (&t), maxlen);
1131 time[maxlen - 1] = '\0';
1132 }
1133}
1134
1135/* Finds the group name for the group GID and copies it into GROUP.
1136 At most MAXLEN characters are copied. */
1137
1138static void
1139group_from_gid (char *group, int maxlen, gid_t gid)
1140{
1141 struct group *grentry = getgrgid (gid);
1142
1143 if (grentry)
1144 {
1145 strncpy (group, grentry->gr_name, maxlen);
1146 /* Ensure that the group name is null-terminated. */
1147 group[maxlen - 1] = '\0';
1148 }
1149 else
1150 group[0] = '\0';
1151}
1152
1153/* Collect data about shared memory recorded in /proc and write it
1154 into READBUF. */
1155
1156static LONGEST
1157linux_xfer_osdata_shm (gdb_byte *readbuf,
dea80a27 1158 ULONGEST offset, ULONGEST len)
85d4a676
SS
1159{
1160 static const char *buf;
1161 static LONGEST len_avail = -1;
1162 static struct buffer buffer;
1163
1164 if (offset == 0)
1165 {
1166 FILE *fp;
1167
1168 if (len_avail != -1 && len_avail != 0)
1169 buffer_free (&buffer);
1170 len_avail = 0;
1171 buf = NULL;
1172 buffer_init (&buffer);
1173 buffer_grow_str (&buffer, "<osdata type=\"shared memory\">\n");
1174
614c279d 1175 fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
85d4a676
SS
1176 if (fp)
1177 {
1178 char buf[8192];
1179
1180 do
1181 {
1182 if (fgets (buf, sizeof (buf), fp))
1183 {
1184 key_t key;
1185 uid_t uid, cuid;
1186 gid_t gid, cgid;
1187 PID_T cpid, lpid;
1188 int shmid, size, nattch;
1189 TIME_T atime, dtime, ctime;
1190 unsigned int perms;
1191 int items_read;
1192
1193 items_read = sscanf (buf,
1194 "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1195 &key, &shmid, &perms, &size,
1196 &cpid, &lpid,
1197 &nattch,
1198 &uid, &gid, &cuid, &cgid,
1199 &atime, &dtime, &ctime);
1200
1201 if (items_read == 14)
1202 {
1203 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1204 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1205 char ccmd[32], lcmd[32];
1206 char atime_str[32], dtime_str[32], ctime_str[32];
1207
1208 user_from_uid (user, sizeof (user), uid);
1209 group_from_gid (group, sizeof (group), gid);
1210 user_from_uid (cuser, sizeof (cuser), cuid);
1211 group_from_gid (cgroup, sizeof (cgroup), cgid);
1212
1213 command_from_pid (ccmd, sizeof (ccmd), cpid);
1214 command_from_pid (lcmd, sizeof (lcmd), lpid);
1215
1216 time_from_time_t (atime_str, sizeof (atime_str), atime);
1217 time_from_time_t (dtime_str, sizeof (dtime_str), dtime);
1218 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1219
1220 buffer_xml_printf (
1221 &buffer,
1222 "<item>"
1223 "<column name=\"key\">%d</column>"
1224 "<column name=\"shmid\">%d</column>"
1225 "<column name=\"permissions\">%o</column>"
1226 "<column name=\"size\">%d</column>"
1227 "<column name=\"creator command\">%s</column>"
1228 "<column name=\"last op. command\">%s</column>"
1229 "<column name=\"num attached\">%d</column>"
1230 "<column name=\"user\">%s</column>"
1231 "<column name=\"group\">%s</column>"
1232 "<column name=\"creator user\">%s</column>"
1233 "<column name=\"creator group\">%s</column>"
1234 "<column name=\"last shmat() time\">%s</column>"
1235 "<column name=\"last shmdt() time\">%s</column>"
1236 "<column name=\"last shmctl() time\">%s</column>"
1237 "</item>",
1238 key,
1239 shmid,
1240 perms,
1241 size,
1242 ccmd,
1243 lcmd,
1244 nattch,
1245 user,
1246 group,
1247 cuser,
1248 cgroup,
1249 atime_str,
1250 dtime_str,
1251 ctime_str);
1252 }
1253 }
1254 }
1255 while (!feof (fp));
1256
1257 fclose (fp);
1258 }
1259
1260 buffer_grow_str0 (&buffer, "</osdata>\n");
1261 buf = buffer_finish (&buffer);
1262 len_avail = strlen (buf);
1263 }
1264
1265 if (offset >= len_avail)
1266 {
1267 /* Done. Get rid of the buffer. */
1268 buffer_free (&buffer);
1269 buf = NULL;
1270 len_avail = 0;
1271 return 0;
1272 }
1273
1274 if (len > len_avail - offset)
1275 len = len_avail - offset;
1276 memcpy (readbuf, buf + offset, len);
1277
1278 return len;
1279}
1280
1281/* Collect data about semaphores recorded in /proc and write it
1282 into READBUF. */
1283
1284static LONGEST
1285linux_xfer_osdata_sem (gdb_byte *readbuf,
dea80a27 1286 ULONGEST offset, ULONGEST len)
85d4a676
SS
1287{
1288 static const char *buf;
1289 static LONGEST len_avail = -1;
1290 static struct buffer buffer;
1291
1292 if (offset == 0)
1293 {
1294 FILE *fp;
1295
1296 if (len_avail != -1 && len_avail != 0)
1297 buffer_free (&buffer);
1298 len_avail = 0;
1299 buf = NULL;
1300 buffer_init (&buffer);
1301 buffer_grow_str (&buffer, "<osdata type=\"semaphores\">\n");
1302
614c279d 1303 fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
85d4a676
SS
1304 if (fp)
1305 {
1306 char buf[8192];
1307
1308 do
1309 {
1310 if (fgets (buf, sizeof (buf), fp))
1311 {
1312 key_t key;
1313 uid_t uid, cuid;
1314 gid_t gid, cgid;
1315 unsigned int perms, nsems;
1316 int semid;
1317 TIME_T otime, ctime;
1318 int items_read;
1319
1320 items_read = sscanf (buf,
1321 "%d %d %o %u %d %d %d %d %lld %lld",
1322 &key, &semid, &perms, &nsems,
1323 &uid, &gid, &cuid, &cgid,
1324 &otime, &ctime);
1325
1326 if (items_read == 10)
1327 {
1328 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1329 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1330 char otime_str[32], ctime_str[32];
1331
1332 user_from_uid (user, sizeof (user), uid);
1333 group_from_gid (group, sizeof (group), gid);
1334 user_from_uid (cuser, sizeof (cuser), cuid);
1335 group_from_gid (cgroup, sizeof (cgroup), cgid);
1336
1337 time_from_time_t (otime_str, sizeof (otime_str), otime);
1338 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1339
1340 buffer_xml_printf (
1341 &buffer,
1342 "<item>"
1343 "<column name=\"key\">%d</column>"
1344 "<column name=\"semid\">%d</column>"
1345 "<column name=\"permissions\">%o</column>"
1346 "<column name=\"num semaphores\">%u</column>"
1347 "<column name=\"user\">%s</column>"
1348 "<column name=\"group\">%s</column>"
1349 "<column name=\"creator user\">%s</column>"
1350 "<column name=\"creator group\">%s</column>"
1351 "<column name=\"last semop() time\">%s</column>"
1352 "<column name=\"last semctl() time\">%s</column>"
1353 "</item>",
1354 key,
1355 semid,
1356 perms,
1357 nsems,
1358 user,
1359 group,
1360 cuser,
1361 cgroup,
1362 otime_str,
1363 ctime_str);
1364 }
1365 }
1366 }
1367 while (!feof (fp));
1368
1369 fclose (fp);
1370 }
1371
1372 buffer_grow_str0 (&buffer, "</osdata>\n");
1373 buf = buffer_finish (&buffer);
1374 len_avail = strlen (buf);
1375 }
1376
1377 if (offset >= len_avail)
1378 {
1379 /* Done. Get rid of the buffer. */
1380 buffer_free (&buffer);
1381 buf = NULL;
1382 len_avail = 0;
1383 return 0;
1384 }
1385
1386 if (len > len_avail - offset)
1387 len = len_avail - offset;
1388 memcpy (readbuf, buf + offset, len);
1389
1390 return len;
1391}
1392
1393/* Collect data about message queues recorded in /proc and write it
1394 into READBUF. */
1395
1396static LONGEST
1397linux_xfer_osdata_msg (gdb_byte *readbuf,
dea80a27 1398 ULONGEST offset, ULONGEST len)
85d4a676
SS
1399{
1400 static const char *buf;
1401 static LONGEST len_avail = -1;
1402 static struct buffer buffer;
1403
1404 if (offset == 0)
1405 {
1406 FILE *fp;
1407
1408 if (len_avail != -1 && len_avail != 0)
1409 buffer_free (&buffer);
1410 len_avail = 0;
1411 buf = NULL;
1412 buffer_init (&buffer);
1413 buffer_grow_str (&buffer, "<osdata type=\"message queues\">\n");
1414
614c279d 1415 fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
85d4a676
SS
1416 if (fp)
1417 {
1418 char buf[8192];
1419
1420 do
1421 {
1422 if (fgets (buf, sizeof (buf), fp))
1423 {
1424 key_t key;
1425 PID_T lspid, lrpid;
1426 uid_t uid, cuid;
1427 gid_t gid, cgid;
1428 unsigned int perms, cbytes, qnum;
1429 int msqid;
1430 TIME_T stime, rtime, ctime;
1431 int items_read;
1432
1433 items_read = sscanf (buf,
1434 "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1435 &key, &msqid, &perms, &cbytes, &qnum,
1436 &lspid, &lrpid, &uid, &gid, &cuid, &cgid,
1437 &stime, &rtime, &ctime);
1438
1439 if (items_read == 14)
1440 {
1441 char user[UT_NAMESIZE], group[UT_NAMESIZE];
1442 char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1443 char lscmd[32], lrcmd[32];
1444 char stime_str[32], rtime_str[32], ctime_str[32];
1445
1446 user_from_uid (user, sizeof (user), uid);
1447 group_from_gid (group, sizeof (group), gid);
1448 user_from_uid (cuser, sizeof (cuser), cuid);
1449 group_from_gid (cgroup, sizeof (cgroup), cgid);
1450
1451 command_from_pid (lscmd, sizeof (lscmd), lspid);
1452 command_from_pid (lrcmd, sizeof (lrcmd), lrpid);
1453
1454 time_from_time_t (stime_str, sizeof (stime_str), stime);
1455 time_from_time_t (rtime_str, sizeof (rtime_str), rtime);
1456 time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1457
1458 buffer_xml_printf (
1459 &buffer,
1460 "<item>"
1461 "<column name=\"key\">%d</column>"
1462 "<column name=\"msqid\">%d</column>"
1463 "<column name=\"permissions\">%o</column>"
1464 "<column name=\"num used bytes\">%u</column>"
1465 "<column name=\"num messages\">%u</column>"
1466 "<column name=\"last msgsnd() command\">%s</column>"
1467 "<column name=\"last msgrcv() command\">%s</column>"
1468 "<column name=\"user\">%s</column>"
1469 "<column name=\"group\">%s</column>"
1470 "<column name=\"creator user\">%s</column>"
1471 "<column name=\"creator group\">%s</column>"
1472 "<column name=\"last msgsnd() time\">%s</column>"
1473 "<column name=\"last msgrcv() time\">%s</column>"
1474 "<column name=\"last msgctl() time\">%s</column>"
1475 "</item>",
1476 key,
1477 msqid,
1478 perms,
1479 cbytes,
1480 qnum,
1481 lscmd,
1482 lrcmd,
1483 user,
1484 group,
1485 cuser,
1486 cgroup,
1487 stime_str,
1488 rtime_str,
1489 ctime_str);
1490 }
1491 }
1492 }
1493 while (!feof (fp));
1494
1495 fclose (fp);
1496 }
1497
1498 buffer_grow_str0 (&buffer, "</osdata>\n");
1499 buf = buffer_finish (&buffer);
1500 len_avail = strlen (buf);
1501 }
1502
1503 if (offset >= len_avail)
1504 {
1505 /* Done. Get rid of the buffer. */
1506 buffer_free (&buffer);
1507 buf = NULL;
1508 len_avail = 0;
1509 return 0;
1510 }
1511
1512 if (len > len_avail - offset)
1513 len = len_avail - offset;
1514 memcpy (readbuf, buf + offset, len);
1515
1516 return len;
1517}
1518
1519/* Collect data about loaded kernel modules and write it into
1520 READBUF. */
1521
1522static LONGEST
1523linux_xfer_osdata_modules (gdb_byte *readbuf,
dea80a27 1524 ULONGEST offset, ULONGEST len)
85d4a676
SS
1525{
1526 static const char *buf;
1527 static LONGEST len_avail = -1;
1528 static struct buffer buffer;
1529
1530 if (offset == 0)
1531 {
1532 FILE *fp;
1533
1534 if (len_avail != -1 && len_avail != 0)
1535 buffer_free (&buffer);
1536 len_avail = 0;
1537 buf = NULL;
1538 buffer_init (&buffer);
1539 buffer_grow_str (&buffer, "<osdata type=\"modules\">\n");
1540
614c279d 1541 fp = gdb_fopen_cloexec ("/proc/modules", "r");
85d4a676
SS
1542 if (fp)
1543 {
1544 char buf[8192];
1545
1546 do
1547 {
1548 if (fgets (buf, sizeof (buf), fp))
1549 {
f60db4f0 1550 char *name, *dependencies, *status, *tmp;
85d4a676
SS
1551 unsigned int size;
1552 unsigned long long address;
1553 int uses;
85d4a676 1554
f60db4f0
GB
1555 name = strtok (buf, " ");
1556 if (name == NULL)
1557 continue;
1558
1559 tmp = strtok (NULL, " ");
1560 if (tmp == NULL)
1561 continue;
1562 if (sscanf (tmp, "%u", &size) != 1)
1563 continue;
1564
1565 tmp = strtok (NULL, " ");
1566 if (tmp == NULL)
1567 continue;
1568 if (sscanf (tmp, "%d", &uses) != 1)
1569 continue;
1570
1571 dependencies = strtok (NULL, " ");
1572 if (dependencies == NULL)
1573 continue;
1574
1575 status = strtok (NULL, " ");
1576 if (status == NULL)
1577 continue;
1578
1579 tmp = strtok (NULL, "\n");
1580 if (tmp == NULL)
1581 continue;
1582 if (sscanf (tmp, "%llx", &address) != 1)
1583 continue;
1584
1585 buffer_xml_printf (
85d4a676
SS
1586 &buffer,
1587 "<item>"
1588 "<column name=\"name\">%s</column>"
1589 "<column name=\"size\">%u</column>"
1590 "<column name=\"num uses\">%d</column>"
1591 "<column name=\"dependencies\">%s</column>"
1592 "<column name=\"status\">%s</column>"
1593 "<column name=\"address\">%llx</column>"
1594 "</item>",
1595 name,
1596 size,
1597 uses,
1598 dependencies,
1599 status,
1600 address);
1601 }
1602 }
1603 while (!feof (fp));
1604
1605 fclose (fp);
1606 }
1607
1608 buffer_grow_str0 (&buffer, "</osdata>\n");
1609 buf = buffer_finish (&buffer);
1610 len_avail = strlen (buf);
1611 }
1612
1613 if (offset >= len_avail)
1614 {
1615 /* Done. Get rid of the buffer. */
1616 buffer_free (&buffer);
1617 buf = NULL;
1618 len_avail = 0;
1619 return 0;
1620 }
1621
1622 if (len > len_avail - offset)
1623 len = len_avail - offset;
1624 memcpy (readbuf, buf + offset, len);
1625
1626 return len;
1627}
1628
d26e3629 1629struct osdata_type {
a121b7c1
PA
1630 const char *type;
1631 const char *title;
1632 const char *description;
dea80a27 1633 LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
d26e3629 1634} osdata_table[] = {
d33279b3
AT
1635 { "cpus", "CPUs", "Listing of all cpus/cores on the system",
1636 linux_xfer_osdata_cpus },
1637 { "files", "File descriptors", "Listing of all file descriptors",
1638 linux_xfer_osdata_fds },
1639 { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1640 linux_xfer_osdata_modules },
1641 { "msg", "Message queues", "Listing of all message queues",
1642 linux_xfer_osdata_msg },
71caed83 1643 { "processes", "Processes", "Listing of all processes",
85d4a676 1644 linux_xfer_osdata_processes },
71caed83 1645 { "procgroups", "Process groups", "Listing of all process groups",
85d4a676 1646 linux_xfer_osdata_processgroups },
71caed83 1647 { "semaphores", "Semaphores", "Listing of all semaphores",
85d4a676 1648 linux_xfer_osdata_sem },
d33279b3
AT
1649 { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1650 linux_xfer_osdata_shm },
1651 { "sockets", "Sockets", "Listing of all internet-domain sockets",
1652 linux_xfer_osdata_isockets },
1653 { "threads", "Threads", "Listing of all threads",
1654 linux_xfer_osdata_threads },
d26e3629
KY
1655 { NULL, NULL, NULL }
1656};
1657
1658LONGEST
1659linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
dea80a27 1660 ULONGEST offset, ULONGEST len)
d26e3629
KY
1661{
1662 if (!annex || *annex == '\0')
1663 {
1664 static const char *buf;
1665 static LONGEST len_avail = -1;
1666 static struct buffer buffer;
1667
1668 if (offset == 0)
1669 {
1670 int i;
1671
1672 if (len_avail != -1 && len_avail != 0)
1673 buffer_free (&buffer);
1674 len_avail = 0;
1675 buf = NULL;
1676 buffer_init (&buffer);
1677 buffer_grow_str (&buffer, "<osdata type=\"types\">\n");
1678
1679 for (i = 0; osdata_table[i].type; ++i)
1680 buffer_xml_printf (
1681 &buffer,
1682 "<item>"
1683 "<column name=\"Type\">%s</column>"
1684 "<column name=\"Description\">%s</column>"
71caed83 1685 "<column name=\"Title\">%s</column>"
d26e3629
KY
1686 "</item>",
1687 osdata_table[i].type,
71caed83
SS
1688 osdata_table[i].description,
1689 osdata_table[i].title);
d26e3629
KY
1690
1691 buffer_grow_str0 (&buffer, "</osdata>\n");
1692 buf = buffer_finish (&buffer);
1693 len_avail = strlen (buf);
1694 }
1695
1696 if (offset >= len_avail)
1697 {
1698 /* Done. Get rid of the buffer. */
1699 buffer_free (&buffer);
1700 buf = NULL;
1701 len_avail = 0;
1702 return 0;
1703 }
1704
1705 if (len > len_avail - offset)
1706 len = len_avail - offset;
1707 memcpy (readbuf, buf + offset, len);
1708
1709 return len;
1710 }
1711 else
1712 {
1713 int i;
1714
1715 for (i = 0; osdata_table[i].type; ++i)
1716 {
1717 if (strcmp (annex, osdata_table[i].type) == 0)
1718 {
1719 gdb_assert (readbuf);
1720
1721 return (osdata_table[i].getter) (readbuf, offset, len);
1722 }
1723 }
1724
1725 return 0;
1726 }
1727}
1728
This page took 0.613739 seconds and 4 git commands to generate.