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