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