Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(886)

Side by Side Diff: gdb/common/linux-osdata.c

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

Powered by Google App Engine
This is Rietveld 408576698