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