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