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