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