Imported Upstream version 7.8.1
[platform/upstream/gdb.git] / gdb / nat / linux-osdata.c
1 /* Linux-specific functions to retrieve OS data.
2    
3    Copyright (C) 2009-2015 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 #include "common-defs.h"
21 #include "linux-osdata.h"
22
23 #include <sys/types.h>
24 #include <sys/sysinfo.h>
25 #include <ctype.h>
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"
37 #include <dirent.h>
38 #include <sys/stat.h>
39 #include "filestuff.h"
40
41 #define NAMELEN(dirent) strlen ((dirent)->d_name)
42
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
47 typedef 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
52 typedef 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                                           
58 /* Compute and return the processor core of a given thread.  */
59
60 int
61 linux_common_core_of_thread (ptid_t ptid)
62 {
63   char filename[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN];
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
72   sprintf (filename, "/proc/%lld/task/%lld/stat",
73            (PID_T) ptid_get_pid (ptid), (PID_T) ptid_get_lwp (ptid));
74   f = gdb_fopen_cloexec (filename, "r");
75   if (!f)
76     return -1;
77
78   for (;;)
79     {
80       int n;
81       content = xrealloc (content, content_read + 1024);
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
91   /* ps command also relies on no trailing fields ever contain ')'.  */
92   p = strrchr (content, ')');
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
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
116 static void
117 command_from_pid (char *command, int maxlen, PID_T pid)
118 {
119   char *stat_path = xstrprintf ("/proc/%lld/stat", pid); 
120   FILE *fp = gdb_fopen_cloexec (stat_path, "r");
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).  */
129       char cmd[18];
130       PID_T stat_pid;
131       int items_read = fscanf (fp, "%lld %17s", &stat_pid, cmd);
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.  */
144       snprintf (command, maxlen, "%lld", pid);
145     }
146
147   command[maxlen - 1] = '\0'; /* Ensure string is null-terminated.  */
148         
149   xfree (stat_path);
150 }
151
152 /* Returns the command-line of the process with the given PID. The
153    returned string needs to be freed using xfree after use.  */
154
155 static char *
156 commandline_from_pid (PID_T pid)
157 {
158   char *pathname = xstrprintf ("/proc/%lld/cmdline", pid);
159   char *commandline = NULL;
160   FILE *f = gdb_fopen_cloexec (pathname, "r");
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         {
194           /* Return the command in square brackets if the command-line
195              is empty.  */
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
211 /* Finds the user name for the user UID and copies it into USER.  At
212    most MAXLEN characters are copied.  */
213
214 static void
215 user_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);
222       /* Ensure that the user name is null-terminated.  */
223       user[maxlen - 1] = '\0';
224     }
225   else
226     user[0] = '\0';
227 }
228
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
232 static int
233 get_process_owner (uid_t *owner, PID_T pid)
234 {
235   struct stat statbuf;
236   char procentry[sizeof ("/proc/") + MAX_PID_T_STRLEN];
237
238   sprintf (procentry, "/proc/%lld", pid);
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
249 /* Find the CPU cores used by process PID and return them in CORES.
250    CORES points to an array of NUM_CORES elements.  */
251
252 static int
253 get_cores_used_by_process (PID_T pid, int *cores, const int num_cores)
254 {
255   char taskdir[sizeof ("/proc/") + MAX_PID_T_STRLEN + sizeof ("/task") - 1];
256   DIR *dir;
257   struct dirent *dp;
258   int task_count = 0;
259
260   sprintf (taskdir, "/proc/%lld/task", pid);
261   dir = opendir (taskdir);
262   if (dir)
263     {
264       while ((dp = readdir (dir)) != NULL)
265         {
266           PID_T tid;
267           int core;
268
269           if (!isdigit (dp->d_name[0])
270               || NAMELEN (dp) > MAX_PID_T_STRLEN)
271             continue;
272
273           sscanf (dp->d_name, "%lld", &tid);
274           core = linux_common_core_of_thread (ptid_build ((pid_t) pid,
275                                                           (pid_t) tid, 0));
276
277           if (core >= 0 && core < num_cores)
278             {
279               ++cores[core];
280               ++task_count;
281             }
282         }
283
284       closedir (dir);
285     }
286
287   return task_count;
288 }
289
290 static LONGEST
291 linux_xfer_osdata_processes (gdb_byte *readbuf,
292                              ULONGEST offset, ULONGEST len)
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         {
313           const int num_cores = sysconf (_SC_NPROCESSORS_ONLN);
314           struct dirent *dp;
315
316           while ((dp = readdir (dirp)) != NULL)
317             {
318               PID_T pid;
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])
328                   || NAMELEN (dp) > MAX_PID_T_STRLEN)
329                 continue;
330
331               sscanf (dp->d_name, "%lld", &pid);
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.  */
340               cores = (int *) xcalloc (num_cores, sizeof (int));
341               task_count = get_cores_used_by_process (pid, cores, num_cores);
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                   {
347                     char core_str[sizeof ("4294967295")];
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>"
362                   "<column name=\"pid\">%lld</column>"
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
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
407 static int
408 compare_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
438 static LONGEST
439 linux_xfer_osdata_processgroups (gdb_byte *readbuf,
440                                  ULONGEST offset, ULONGEST len)
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;
463           PID_T *process_list = (PID_T *) xmalloc (list_block_size * 2 * sizeof (PID_T));
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
554 static LONGEST
555 linux_xfer_osdata_threads (gdb_byte *readbuf,
556                            ULONGEST offset, ULONGEST len)
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;
594                   PID_T pid;
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                         {
610                           PID_T tid;
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>"
623                             "<column name=\"pid\">%lld</column>"
624                             "<column name=\"command\">%s</column>"
625                             "<column name=\"tid\">%lld</column>"
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
665 /* Collect all the open file descriptors found in /proc and put the details
666    found about them into READBUF.  */
667
668 static LONGEST
669 linux_xfer_osdata_fds (gdb_byte *readbuf,
670                        ULONGEST offset, ULONGEST len)
671 {
672   /* We make the process list snapshot when the object starts to be read.  */
673   static const char *buf;
674   static LONGEST len_avail = -1;
675   static struct buffer buffer;
676
677   if (offset == 0)
678     {
679       DIR *dirp;
680
681       if (len_avail != -1 && len_avail != 0)
682         buffer_free (&buffer);
683       len_avail = 0;
684       buf = NULL;
685       buffer_init (&buffer);
686       buffer_grow_str (&buffer, "<osdata type=\"files\">\n");
687
688       dirp = opendir ("/proc");
689       if (dirp)
690         {
691           struct dirent *dp;
692
693           while ((dp = readdir (dirp)) != NULL)
694             {
695               struct stat statbuf;
696               char procentry[sizeof ("/proc/4294967295")];
697
698               if (!isdigit (dp->d_name[0])
699                   || NAMELEN (dp) > sizeof ("4294967295") - 1)
700                 continue;
701
702               sprintf (procentry, "/proc/%s", dp->d_name);
703               if (stat (procentry, &statbuf) == 0
704                   && S_ISDIR (statbuf.st_mode))
705                 {
706                   char *pathname;
707                   DIR *dirp2;
708                   PID_T pid;
709                   char command[32];
710
711                   pid = atoi (dp->d_name);
712                   command_from_pid (command, sizeof (command), pid);
713
714                   pathname = xstrprintf ("/proc/%s/fd", dp->d_name);
715                   dirp2 = opendir (pathname);
716
717                   if (dirp2)
718                     {
719                       struct dirent *dp2;
720
721                       while ((dp2 = readdir (dirp2)) != NULL)
722                         {
723                           char *fdname;
724                           char buf[1000];
725                           ssize_t rslt;
726
727                           if (!isdigit (dp2->d_name[0]))
728                             continue;
729
730                           fdname = xstrprintf ("%s/%s", pathname, dp2->d_name);
731                           rslt = readlink (fdname, buf, sizeof (buf) - 1);
732                           if (rslt >= 0)
733                             buf[rslt] = '\0';
734
735                           buffer_xml_printf (
736                             &buffer,
737                             "<item>"
738                             "<column name=\"pid\">%s</column>"
739                             "<column name=\"command\">%s</column>"
740                             "<column name=\"file descriptor\">%s</column>"
741                             "<column name=\"name\">%s</column>"
742                             "</item>",
743                             dp->d_name,
744                             command,
745                             dp2->d_name,
746                             (rslt >= 0 ? buf : dp2->d_name));
747                         }
748
749                       closedir (dirp2);
750                     }
751
752                   xfree (pathname);
753                 }
754             }
755
756           closedir (dirp);
757         }
758
759       buffer_grow_str0 (&buffer, "</osdata>\n");
760       buf = buffer_finish (&buffer);
761       len_avail = strlen (buf);
762     }
763
764   if (offset >= len_avail)
765     {
766       /* Done.  Get rid of the buffer.  */
767       buffer_free (&buffer);
768       buf = NULL;
769       len_avail = 0;
770       return 0;
771     }
772
773   if (len > len_avail - offset)
774     len = len_avail - offset;
775   memcpy (readbuf, buf + offset, len);
776
777   return len;
778 }
779
780 /* Returns the socket state STATE in textual form.  */
781
782 static const char *
783 format_socket_state (unsigned char state)
784 {
785   /* Copied from include/net/tcp_states.h in the Linux kernel sources.  */
786   enum {
787     TCP_ESTABLISHED = 1,
788     TCP_SYN_SENT,
789     TCP_SYN_RECV,
790     TCP_FIN_WAIT1,
791     TCP_FIN_WAIT2,
792     TCP_TIME_WAIT,
793     TCP_CLOSE,
794     TCP_CLOSE_WAIT,
795     TCP_LAST_ACK,
796     TCP_LISTEN,
797     TCP_CLOSING
798   };
799
800   switch (state)
801     {
802     case TCP_ESTABLISHED:
803       return "ESTABLISHED";
804     case TCP_SYN_SENT:
805       return "SYN_SENT";
806     case TCP_SYN_RECV:
807       return "SYN_RECV";
808     case TCP_FIN_WAIT1:
809       return "FIN_WAIT1";
810     case TCP_FIN_WAIT2:
811       return "FIN_WAIT2";
812     case TCP_TIME_WAIT:
813       return "TIME_WAIT";
814     case TCP_CLOSE:
815       return "CLOSE";
816     case TCP_CLOSE_WAIT:
817       return "CLOSE_WAIT";
818     case TCP_LAST_ACK:
819       return "LAST_ACK";
820     case TCP_LISTEN:
821       return "LISTEN";
822     case TCP_CLOSING:
823       return "CLOSING";
824     default:
825       return "(unknown)";
826     }
827 }
828
829 union socket_addr
830   {
831     struct sockaddr sa;
832     struct sockaddr_in sin;
833     struct sockaddr_in6 sin6;
834   };
835
836 /* Auxiliary function used by linux_xfer_osdata_isocket.  Formats
837    information for all open internet sockets of type FAMILY on the
838    system into BUFFER.  If TCP is set, only TCP sockets are processed,
839    otherwise only UDP sockets are processed.  */
840
841 static void
842 print_sockets (unsigned short family, int tcp, struct buffer *buffer)
843 {
844   const char *proc_file;
845   FILE *fp;
846
847   if (family == AF_INET)
848     proc_file = tcp ? "/proc/net/tcp" : "/proc/net/udp";
849   else if (family == AF_INET6)
850     proc_file = tcp ? "/proc/net/tcp6" : "/proc/net/udp6";
851   else
852     return;
853
854   fp = gdb_fopen_cloexec (proc_file, "r");
855   if (fp)
856     {
857       char buf[8192];
858
859       do
860         {
861           if (fgets (buf, sizeof (buf), fp))
862             {
863               uid_t uid;
864               unsigned int local_port, remote_port, state;
865               char local_address[NI_MAXHOST], remote_address[NI_MAXHOST];
866               int result;
867
868 #if NI_MAXHOST <= 32
869 #error "local_address and remote_address buffers too small"
870 #endif
871
872               result = sscanf (buf,
873                                "%*d: %32[0-9A-F]:%X %32[0-9A-F]:%X %X %*X:%*X %*X:%*X %*X %d %*d %*u %*s\n",
874                                local_address, &local_port,
875                                remote_address, &remote_port,
876                                &state,
877                                &uid);
878               
879               if (result == 6)
880                 {
881                   union socket_addr locaddr, remaddr;
882                   size_t addr_size;
883                   char user[UT_NAMESIZE];
884                   char local_service[NI_MAXSERV], remote_service[NI_MAXSERV];
885
886                   if (family == AF_INET)
887                     {
888                       sscanf (local_address, "%X",
889                               &locaddr.sin.sin_addr.s_addr);
890                       sscanf (remote_address, "%X",
891                               &remaddr.sin.sin_addr.s_addr);
892                       
893                       locaddr.sin.sin_port = htons (local_port);
894                       remaddr.sin.sin_port = htons (remote_port);
895
896                       addr_size = sizeof (struct sockaddr_in);
897                     }
898                   else
899                     {
900                       sscanf (local_address, "%8X%8X%8X%8X",
901                               locaddr.sin6.sin6_addr.s6_addr32,
902                               locaddr.sin6.sin6_addr.s6_addr32 + 1,
903                               locaddr.sin6.sin6_addr.s6_addr32 + 2,
904                               locaddr.sin6.sin6_addr.s6_addr32 + 3);
905                       sscanf (remote_address, "%8X%8X%8X%8X",
906                               remaddr.sin6.sin6_addr.s6_addr32,
907                               remaddr.sin6.sin6_addr.s6_addr32 + 1,
908                               remaddr.sin6.sin6_addr.s6_addr32 + 2,
909                               remaddr.sin6.sin6_addr.s6_addr32 + 3);
910
911                       locaddr.sin6.sin6_port = htons (local_port);
912                       remaddr.sin6.sin6_port = htons (remote_port);
913                       
914                       locaddr.sin6.sin6_flowinfo = 0;
915                       remaddr.sin6.sin6_flowinfo = 0;
916                       locaddr.sin6.sin6_scope_id = 0;
917                       remaddr.sin6.sin6_scope_id = 0;
918
919                       addr_size = sizeof (struct sockaddr_in6);
920                     }
921               
922                   locaddr.sa.sa_family = remaddr.sa.sa_family = family;
923                       
924                   result = getnameinfo (&locaddr.sa, addr_size,
925                                         local_address, sizeof (local_address),
926                                         local_service, sizeof (local_service),
927                                         NI_NUMERICHOST | NI_NUMERICSERV
928                                         | (tcp ? 0 : NI_DGRAM));
929                   if (result)
930                     continue;
931                   
932                   result = getnameinfo (&remaddr.sa, addr_size,
933                                         remote_address,
934                                         sizeof (remote_address),
935                                         remote_service,
936                                         sizeof (remote_service),
937                                         NI_NUMERICHOST | NI_NUMERICSERV
938                                         | (tcp ? 0 : NI_DGRAM));
939                   if (result)
940                     continue;
941                   
942                   user_from_uid (user, sizeof (user), uid);
943                   
944                   buffer_xml_printf (
945                       buffer,
946                       "<item>"
947                       "<column name=\"local address\">%s</column>"
948                       "<column name=\"local port\">%s</column>"
949                       "<column name=\"remote address\">%s</column>"
950                       "<column name=\"remote port\">%s</column>"
951                       "<column name=\"state\">%s</column>"
952                       "<column name=\"user\">%s</column>"
953                       "<column name=\"family\">%s</column>" 
954                       "<column name=\"protocol\">%s</column>"
955                       "</item>",
956                       local_address,
957                       local_service,
958                       remote_address,
959                       remote_service,
960                       format_socket_state (state),
961                       user,
962                       (family == AF_INET) ? "INET" : "INET6",
963                       tcp ? "STREAM" : "DGRAM");
964                 }
965             }
966         }
967       while (!feof (fp));
968
969       fclose (fp);
970     }
971 }
972
973 /* Collect data about internet sockets and write it into READBUF.  */
974
975 static LONGEST
976 linux_xfer_osdata_isockets (gdb_byte *readbuf,
977                             ULONGEST offset, ULONGEST len)
978 {
979   static const char *buf;
980   static LONGEST len_avail = -1;
981   static struct buffer buffer;
982
983   if (offset == 0)
984     {
985       if (len_avail != -1 && len_avail != 0)
986         buffer_free (&buffer);
987       len_avail = 0;
988       buf = NULL;
989       buffer_init (&buffer);
990       buffer_grow_str (&buffer, "<osdata type=\"I sockets\">\n");
991
992       print_sockets (AF_INET, 1, &buffer);
993       print_sockets (AF_INET, 0, &buffer);
994       print_sockets (AF_INET6, 1, &buffer);
995       print_sockets (AF_INET6, 0, &buffer);
996
997       buffer_grow_str0 (&buffer, "</osdata>\n");
998       buf = buffer_finish (&buffer);
999       len_avail = strlen (buf);
1000     }
1001
1002   if (offset >= len_avail)
1003     {
1004       /* Done.  Get rid of the buffer.  */
1005       buffer_free (&buffer);
1006       buf = NULL;
1007       len_avail = 0;
1008       return 0;
1009     }
1010
1011   if (len > len_avail - offset)
1012     len = len_avail - offset;
1013   memcpy (readbuf, buf + offset, len);
1014
1015   return len;
1016 }
1017
1018 /* Converts the time SECONDS into textual form and copies it into a
1019    buffer TIME, with at most MAXLEN characters copied.  */
1020
1021 static void
1022 time_from_time_t (char *time, int maxlen, TIME_T seconds)
1023 {
1024   if (!seconds)
1025     time[0] = '\0';
1026   else
1027     {
1028       time_t t = (time_t) seconds;
1029       
1030       strncpy (time, ctime (&t), maxlen);
1031       time[maxlen - 1] = '\0';
1032     }
1033 }
1034
1035 /* Finds the group name for the group GID and copies it into GROUP.
1036    At most MAXLEN characters are copied.  */
1037
1038 static void
1039 group_from_gid (char *group, int maxlen, gid_t gid)
1040 {
1041   struct group *grentry = getgrgid (gid);
1042   
1043   if (grentry)
1044     {
1045       strncpy (group, grentry->gr_name, maxlen);
1046       /* Ensure that the group name is null-terminated.  */
1047       group[maxlen - 1] = '\0';
1048     }
1049   else
1050     group[0] = '\0';
1051 }
1052
1053 /* Collect data about shared memory recorded in /proc and write it
1054    into READBUF.  */
1055
1056 static LONGEST
1057 linux_xfer_osdata_shm (gdb_byte *readbuf,
1058                        ULONGEST offset, ULONGEST len)
1059 {
1060   static const char *buf;
1061   static LONGEST len_avail = -1;
1062   static struct buffer buffer;
1063
1064   if (offset == 0)
1065     {
1066       FILE *fp;
1067
1068       if (len_avail != -1 && len_avail != 0)
1069         buffer_free (&buffer);
1070       len_avail = 0;
1071       buf = NULL;
1072       buffer_init (&buffer);
1073       buffer_grow_str (&buffer, "<osdata type=\"shared memory\">\n");
1074
1075       fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
1076       if (fp)
1077         {
1078           char buf[8192];
1079
1080           do
1081             {
1082               if (fgets (buf, sizeof (buf), fp))
1083                 {
1084                   key_t key;
1085                   uid_t uid, cuid;
1086                   gid_t gid, cgid;
1087                   PID_T cpid, lpid;
1088                   int shmid, size, nattch;
1089                   TIME_T atime, dtime, ctime;
1090                   unsigned int perms;
1091                   int items_read;
1092                                   
1093                   items_read = sscanf (buf,
1094                                        "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld",
1095                                        &key, &shmid, &perms, &size,
1096                                        &cpid, &lpid,
1097                                        &nattch,
1098                                        &uid, &gid, &cuid, &cgid,
1099                                        &atime, &dtime, &ctime);
1100
1101                   if (items_read == 14)
1102                     {
1103                       char user[UT_NAMESIZE], group[UT_NAMESIZE];
1104                       char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1105                       char ccmd[32], lcmd[32];
1106                       char atime_str[32], dtime_str[32], ctime_str[32];
1107                       
1108                       user_from_uid (user, sizeof (user), uid);
1109                       group_from_gid (group, sizeof (group), gid);
1110                       user_from_uid (cuser, sizeof (cuser), cuid);
1111                       group_from_gid (cgroup, sizeof (cgroup), cgid);
1112                       
1113                       command_from_pid (ccmd, sizeof (ccmd), cpid);
1114                       command_from_pid (lcmd, sizeof (lcmd), lpid);
1115                       
1116                       time_from_time_t (atime_str, sizeof (atime_str), atime);
1117                       time_from_time_t (dtime_str, sizeof (dtime_str), dtime);
1118                       time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1119                       
1120                       buffer_xml_printf (
1121                           &buffer,
1122                           "<item>"
1123                           "<column name=\"key\">%d</column>"
1124                           "<column name=\"shmid\">%d</column>"
1125                           "<column name=\"permissions\">%o</column>"
1126                           "<column name=\"size\">%d</column>"
1127                           "<column name=\"creator command\">%s</column>"
1128                           "<column name=\"last op. command\">%s</column>"
1129                           "<column name=\"num attached\">%d</column>"
1130                           "<column name=\"user\">%s</column>"
1131                           "<column name=\"group\">%s</column>"
1132                           "<column name=\"creator user\">%s</column>"
1133                           "<column name=\"creator group\">%s</column>"
1134                           "<column name=\"last shmat() time\">%s</column>"
1135                           "<column name=\"last shmdt() time\">%s</column>"
1136                           "<column name=\"last shmctl() time\">%s</column>"
1137                           "</item>",
1138                           key,
1139                           shmid,
1140                           perms,
1141                           size,
1142                           ccmd,
1143                           lcmd,
1144                           nattch,
1145                           user,
1146                           group,
1147                           cuser,
1148                           cgroup,
1149                           atime_str,
1150                           dtime_str,
1151                           ctime_str);
1152                     }
1153                 }
1154             }
1155           while (!feof (fp));
1156
1157           fclose (fp);
1158         }
1159       
1160       buffer_grow_str0 (&buffer, "</osdata>\n");
1161       buf = buffer_finish (&buffer);
1162       len_avail = strlen (buf);
1163     }
1164
1165   if (offset >= len_avail)
1166     {
1167       /* Done.  Get rid of the buffer.  */
1168       buffer_free (&buffer);
1169       buf = NULL;
1170       len_avail = 0;
1171       return 0;
1172     }
1173
1174   if (len > len_avail - offset)
1175     len = len_avail - offset;
1176   memcpy (readbuf, buf + offset, len);
1177
1178   return len;
1179 }
1180
1181 /* Collect data about semaphores recorded in /proc and write it
1182    into READBUF.  */
1183
1184 static LONGEST
1185 linux_xfer_osdata_sem (gdb_byte *readbuf,
1186                        ULONGEST offset, ULONGEST len)
1187 {
1188   static const char *buf;
1189   static LONGEST len_avail = -1;
1190   static struct buffer buffer;
1191
1192   if (offset == 0)
1193     {
1194       FILE *fp;
1195       
1196       if (len_avail != -1 && len_avail != 0)
1197         buffer_free (&buffer);
1198       len_avail = 0;
1199       buf = NULL;
1200       buffer_init (&buffer);
1201       buffer_grow_str (&buffer, "<osdata type=\"semaphores\">\n");
1202
1203       fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
1204       if (fp)
1205         {
1206           char buf[8192];
1207           
1208           do
1209             {
1210               if (fgets (buf, sizeof (buf), fp))
1211                 {
1212                   key_t key;
1213                   uid_t uid, cuid;
1214                   gid_t gid, cgid;
1215                   unsigned int perms, nsems;
1216                   int semid;
1217                   TIME_T otime, ctime;
1218                   int items_read;
1219                   
1220                   items_read = sscanf (buf,
1221                                        "%d %d %o %u %d %d %d %d %lld %lld",
1222                                        &key, &semid, &perms, &nsems,
1223                                        &uid, &gid, &cuid, &cgid,
1224                                        &otime, &ctime);
1225                   
1226                   if (items_read == 10)
1227                     {
1228                       char user[UT_NAMESIZE], group[UT_NAMESIZE];
1229                       char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1230                       char otime_str[32], ctime_str[32];
1231                       
1232                       user_from_uid (user, sizeof (user), uid);
1233                       group_from_gid (group, sizeof (group), gid);
1234                       user_from_uid (cuser, sizeof (cuser), cuid);
1235                       group_from_gid (cgroup, sizeof (cgroup), cgid);
1236                       
1237                       time_from_time_t (otime_str, sizeof (otime_str), otime);
1238                       time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1239                       
1240                       buffer_xml_printf (
1241                           &buffer,
1242                           "<item>"
1243                           "<column name=\"key\">%d</column>"
1244                           "<column name=\"semid\">%d</column>"
1245                           "<column name=\"permissions\">%o</column>"
1246                           "<column name=\"num semaphores\">%u</column>"
1247                           "<column name=\"user\">%s</column>"
1248                           "<column name=\"group\">%s</column>"
1249                           "<column name=\"creator user\">%s</column>"
1250                           "<column name=\"creator group\">%s</column>"
1251                           "<column name=\"last semop() time\">%s</column>"
1252                           "<column name=\"last semctl() time\">%s</column>"
1253                           "</item>",
1254                           key,
1255                           semid,
1256                           perms,
1257                           nsems,
1258                           user,
1259                           group,
1260                           cuser,
1261                           cgroup,
1262                           otime_str,
1263                           ctime_str);
1264                     }
1265                 }
1266             }
1267           while (!feof (fp));
1268
1269           fclose (fp);
1270         }
1271
1272       buffer_grow_str0 (&buffer, "</osdata>\n");
1273       buf = buffer_finish (&buffer);
1274       len_avail = strlen (buf);
1275     }
1276
1277   if (offset >= len_avail)
1278     {
1279       /* Done.  Get rid of the buffer.  */
1280       buffer_free (&buffer);
1281       buf = NULL;
1282       len_avail = 0;
1283       return 0;
1284     }
1285
1286   if (len > len_avail - offset)
1287     len = len_avail - offset;
1288   memcpy (readbuf, buf + offset, len);
1289
1290   return len;
1291 }
1292
1293 /* Collect data about message queues recorded in /proc and write it
1294    into READBUF.  */
1295
1296 static LONGEST
1297 linux_xfer_osdata_msg (gdb_byte *readbuf,
1298                        ULONGEST offset, ULONGEST len)
1299 {
1300   static const char *buf;
1301   static LONGEST len_avail = -1;
1302   static struct buffer buffer;
1303
1304   if (offset == 0)
1305     {
1306       FILE *fp;
1307       
1308       if (len_avail != -1 && len_avail != 0)
1309         buffer_free (&buffer);
1310       len_avail = 0;
1311       buf = NULL;
1312       buffer_init (&buffer);
1313       buffer_grow_str (&buffer, "<osdata type=\"message queues\">\n");
1314       
1315       fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
1316       if (fp)
1317         {
1318           char buf[8192];
1319           
1320           do
1321             {
1322               if (fgets (buf, sizeof (buf), fp))
1323                 {
1324                   key_t key;
1325                   PID_T lspid, lrpid;
1326                   uid_t uid, cuid;
1327                   gid_t gid, cgid;
1328                   unsigned int perms, cbytes, qnum;
1329                   int msqid;
1330                   TIME_T stime, rtime, ctime;
1331                   int items_read;
1332                   
1333                   items_read = sscanf (buf,
1334                                        "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld",
1335                                        &key, &msqid, &perms, &cbytes, &qnum,
1336                                        &lspid, &lrpid, &uid, &gid, &cuid, &cgid,
1337                                        &stime, &rtime, &ctime);
1338                   
1339                   if (items_read == 14)
1340                     {
1341                       char user[UT_NAMESIZE], group[UT_NAMESIZE];
1342                       char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE];
1343                       char lscmd[32], lrcmd[32];
1344                       char stime_str[32], rtime_str[32], ctime_str[32];
1345                       
1346                       user_from_uid (user, sizeof (user), uid);
1347                       group_from_gid (group, sizeof (group), gid);
1348                       user_from_uid (cuser, sizeof (cuser), cuid);
1349                       group_from_gid (cgroup, sizeof (cgroup), cgid);
1350                       
1351                       command_from_pid (lscmd, sizeof (lscmd), lspid);
1352                       command_from_pid (lrcmd, sizeof (lrcmd), lrpid);
1353                       
1354                       time_from_time_t (stime_str, sizeof (stime_str), stime);
1355                       time_from_time_t (rtime_str, sizeof (rtime_str), rtime);
1356                       time_from_time_t (ctime_str, sizeof (ctime_str), ctime);
1357                       
1358                       buffer_xml_printf (
1359                           &buffer,
1360                           "<item>"
1361                           "<column name=\"key\">%d</column>"
1362                           "<column name=\"msqid\">%d</column>"
1363                           "<column name=\"permissions\">%o</column>"
1364                           "<column name=\"num used bytes\">%u</column>"
1365                           "<column name=\"num messages\">%u</column>"
1366                           "<column name=\"last msgsnd() command\">%s</column>"
1367                           "<column name=\"last msgrcv() command\">%s</column>"
1368                           "<column name=\"user\">%s</column>"
1369                           "<column name=\"group\">%s</column>"
1370                           "<column name=\"creator user\">%s</column>"
1371                           "<column name=\"creator group\">%s</column>"
1372                           "<column name=\"last msgsnd() time\">%s</column>"
1373                           "<column name=\"last msgrcv() time\">%s</column>"
1374                           "<column name=\"last msgctl() time\">%s</column>"
1375                           "</item>",
1376                           key,
1377                           msqid,
1378                           perms,
1379                           cbytes,
1380                           qnum,
1381                           lscmd,
1382                           lrcmd,
1383                           user,
1384                           group,
1385                           cuser,
1386                           cgroup,
1387                           stime_str,
1388                           rtime_str,
1389                           ctime_str);
1390                     }
1391                 }
1392             }
1393           while (!feof (fp));
1394
1395           fclose (fp);
1396         }
1397
1398       buffer_grow_str0 (&buffer, "</osdata>\n");
1399       buf = buffer_finish (&buffer);
1400       len_avail = strlen (buf);
1401     }
1402
1403   if (offset >= len_avail)
1404     {
1405       /* Done.  Get rid of the buffer.  */
1406       buffer_free (&buffer);
1407       buf = NULL;
1408       len_avail = 0;
1409       return 0;
1410     }
1411
1412   if (len > len_avail - offset)
1413     len = len_avail - offset;
1414   memcpy (readbuf, buf + offset, len);
1415
1416   return len;
1417 }
1418
1419 /* Collect data about loaded kernel modules and write it into
1420    READBUF.  */
1421
1422 static LONGEST
1423 linux_xfer_osdata_modules (gdb_byte *readbuf,
1424                            ULONGEST offset, ULONGEST len)
1425 {
1426   static const char *buf;
1427   static LONGEST len_avail = -1;
1428   static struct buffer buffer;
1429
1430   if (offset == 0)
1431     {
1432       FILE *fp;
1433
1434       if (len_avail != -1 && len_avail != 0)
1435         buffer_free (&buffer);
1436       len_avail = 0;
1437       buf = NULL;
1438       buffer_init (&buffer);
1439       buffer_grow_str (&buffer, "<osdata type=\"modules\">\n");
1440
1441       fp = gdb_fopen_cloexec ("/proc/modules", "r");
1442       if (fp)
1443         {
1444           char buf[8192];
1445           
1446           do
1447             {
1448               if (fgets (buf, sizeof (buf), fp))
1449                 {
1450                   char *name, *dependencies, *status, *tmp;
1451                   unsigned int size;
1452                   unsigned long long address;
1453                   int uses;
1454
1455                   name = strtok (buf, " ");
1456                   if (name == NULL)
1457                     continue;
1458
1459                   tmp = strtok (NULL, " ");
1460                   if (tmp == NULL)
1461                     continue;
1462                   if (sscanf (tmp, "%u", &size) != 1)
1463                     continue;
1464
1465                   tmp = strtok (NULL, " ");
1466                   if (tmp == NULL)
1467                     continue;
1468                   if (sscanf (tmp, "%d", &uses) != 1)
1469                     continue;
1470
1471                   dependencies = strtok (NULL, " ");
1472                   if (dependencies == NULL)
1473                     continue;
1474
1475                   status = strtok (NULL, " ");
1476                   if (status == NULL)
1477                     continue;
1478
1479                   tmp = strtok (NULL, "\n");
1480                   if (tmp == NULL)
1481                     continue;
1482                   if (sscanf (tmp, "%llx", &address) != 1)
1483                     continue;
1484
1485                   buffer_xml_printf (
1486                         &buffer,
1487                         "<item>"
1488                         "<column name=\"name\">%s</column>"
1489                         "<column name=\"size\">%u</column>"
1490                         "<column name=\"num uses\">%d</column>"
1491                         "<column name=\"dependencies\">%s</column>"
1492                         "<column name=\"status\">%s</column>"
1493                         "<column name=\"address\">%llx</column>"
1494                         "</item>",
1495                         name,
1496                         size,
1497                         uses,
1498                         dependencies,
1499                         status,
1500                         address);
1501                 }
1502             }
1503           while (!feof (fp));
1504
1505           fclose (fp);
1506         }
1507
1508       buffer_grow_str0 (&buffer, "</osdata>\n");
1509       buf = buffer_finish (&buffer);
1510       len_avail = strlen (buf);
1511     }
1512
1513   if (offset >= len_avail)
1514     {
1515       /* Done.  Get rid of the buffer.  */
1516       buffer_free (&buffer);
1517       buf = NULL;
1518       len_avail = 0;
1519       return 0;
1520     }
1521
1522   if (len > len_avail - offset)
1523     len = len_avail - offset;
1524   memcpy (readbuf, buf + offset, len);
1525
1526   return len;
1527 }
1528
1529 struct osdata_type {
1530   char *type;
1531   char *title;
1532   char *description;
1533   LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
1534 } osdata_table[] = {
1535   { "processes", "Processes", "Listing of all processes",
1536     linux_xfer_osdata_processes },
1537   { "procgroups", "Process groups", "Listing of all process groups",
1538     linux_xfer_osdata_processgroups },
1539   { "threads", "Threads", "Listing of all threads",
1540     linux_xfer_osdata_threads },
1541   { "files", "File descriptors", "Listing of all file descriptors",
1542     linux_xfer_osdata_fds },
1543   { "sockets", "Sockets", "Listing of all internet-domain sockets",
1544     linux_xfer_osdata_isockets },
1545   { "shm", "Shared-memory regions", "Listing of all shared-memory regions",
1546     linux_xfer_osdata_shm },
1547   { "semaphores", "Semaphores", "Listing of all semaphores",
1548     linux_xfer_osdata_sem },
1549   { "msg", "Message queues", "Listing of all message queues",
1550     linux_xfer_osdata_msg },
1551   { "modules", "Kernel modules", "Listing of all loaded kernel modules",
1552     linux_xfer_osdata_modules },
1553   { NULL, NULL, NULL }
1554 };
1555
1556 LONGEST
1557 linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf,
1558                           ULONGEST offset, ULONGEST len)
1559 {
1560   if (!annex || *annex == '\0')
1561     {
1562       static const char *buf;
1563       static LONGEST len_avail = -1;
1564       static struct buffer buffer;
1565
1566       if (offset == 0)
1567         {
1568           int i;
1569
1570           if (len_avail != -1 && len_avail != 0)
1571             buffer_free (&buffer);
1572           len_avail = 0;
1573           buf = NULL;
1574           buffer_init (&buffer);
1575           buffer_grow_str (&buffer, "<osdata type=\"types\">\n");
1576
1577           for (i = 0; osdata_table[i].type; ++i)
1578             buffer_xml_printf (
1579                                &buffer,
1580                                "<item>"
1581                                "<column name=\"Type\">%s</column>"
1582                                "<column name=\"Description\">%s</column>"
1583                                "<column name=\"Title\">%s</column>"
1584                                "</item>",
1585                                osdata_table[i].type,
1586                                osdata_table[i].description,
1587                                osdata_table[i].title);
1588
1589           buffer_grow_str0 (&buffer, "</osdata>\n");
1590           buf = buffer_finish (&buffer);
1591           len_avail = strlen (buf);
1592         }
1593
1594       if (offset >= len_avail)
1595         {
1596           /* Done.  Get rid of the buffer.  */
1597           buffer_free (&buffer);
1598           buf = NULL;
1599           len_avail = 0;
1600           return 0;
1601         }
1602
1603       if (len > len_avail - offset)
1604         len = len_avail - offset;
1605       memcpy (readbuf, buf + offset, len);
1606
1607       return len;
1608     }
1609   else
1610     {
1611       int i;
1612
1613       for (i = 0; osdata_table[i].type; ++i)
1614         {
1615           if (strcmp (annex, osdata_table[i].type) == 0)
1616             {
1617               gdb_assert (readbuf);
1618               
1619               return (osdata_table[i].getter) (readbuf, offset, len);
1620             }
1621         }
1622
1623       return 0;
1624     }
1625 }
1626