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