1 /* Linux-specific functions to retrieve OS data.
3 Copyright (C) 2009-2012 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
26 #include "linux-osdata.h"
28 #include <sys/types.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
43 #include "xml-utils.h"
45 #include "gdb_assert.h"
46 #include "gdb_dirent.h"
48 /* Compute and return the processor core of a given thread. */
51 linux_common_core_of_thread (ptid_t ptid
)
53 char filename
[sizeof ("/proc//task//stat")
54 + 2 * 20 /* decimal digits for 2 numbers, max 2^64 bit each */
64 sprintf (filename
, "/proc/%d/task/%ld/stat",
65 ptid_get_pid (ptid
), ptid_get_lwp (ptid
));
66 f
= fopen (filename
, "r");
73 content
= xrealloc (content
, content_read
+ 1024);
74 n
= fread (content
+ content_read
, 1, 1024, f
);
78 content
[content_read
] = '\0';
83 p
= strchr (content
, '(');
91 /* If the first field after program name has index 0, then core number is
92 the field with index 36. There's no constant for that anywhere. */
94 p
= strtok_r (p
, " ", &ts
);
95 for (i
= 0; p
!= NULL
&& i
!= 36; ++i
)
96 p
= strtok_r (NULL
, " ", &ts
);
98 if (p
== NULL
|| sscanf (p
, "%d", &core
) == 0)
108 command_from_pid (char *command
, int maxlen
, pid_t pid
)
110 char *stat_path
= xstrprintf ("/proc/%d/stat", pid
);
111 FILE *fp
= fopen (stat_path
, "r");
117 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
118 include/linux/sched.h in the Linux kernel sources) plus two
119 (for the brackets). */
122 int items_read
= fscanf (fp
, "%d %32s", &stat_pid
, cmd
);
124 if (items_read
== 2 && pid
== stat_pid
)
126 cmd
[strlen (cmd
) - 1] = '\0'; /* Remove trailing parenthesis. */
127 strncpy (command
, cmd
+ 1, maxlen
); /* Ignore leading parenthesis. */
134 /* Return the PID if a /proc entry for the process cannot be found. */
135 snprintf (command
, maxlen
, "%d", pid
);
138 command
[maxlen
- 1] = '\0'; /* Ensure string is null-terminated. */
143 /* Returns the command-line of the process with the given PID. The returned
144 string needs to be freed using xfree after use. */
147 commandline_from_pid (pid_t pid
)
149 char *pathname
= xstrprintf ("/proc/%d/cmdline", pid
);
150 char *commandline
= NULL
;
151 FILE *f
= fopen (pathname
, "r");
160 size_t read_bytes
= fread (buf
, 1, sizeof (buf
), f
);
164 commandline
= (char *) xrealloc (commandline
, len
+ read_bytes
+ 1);
165 memcpy (commandline
+ len
, buf
, read_bytes
);
176 /* Replace null characters with spaces. */
177 for (i
= 0; i
< len
; ++i
)
178 if (commandline
[i
] == '\0')
179 commandline
[i
] = ' ';
181 commandline
[len
] = '\0';
185 /* Return the command in square brackets if the command-line is empty. */
186 commandline
= (char *) xmalloc (32);
187 commandline
[0] = '[';
188 command_from_pid (commandline
+ 1, 31, pid
);
190 len
= strlen (commandline
);
192 strcat (commandline
, "]");
202 user_from_uid (char *user
, int maxlen
, uid_t uid
)
204 struct passwd
*pwentry
= getpwuid (uid
);
208 strncpy (user
, pwentry
->pw_name
, maxlen
);
209 user
[maxlen
- 1] = '\0'; /* Ensure that the user name is null-terminated. */
216 get_process_owner (uid_t
*owner
, pid_t pid
)
219 char procentry
[sizeof ("/proc/4294967295")];
221 sprintf (procentry
, "/proc/%d", pid
);
223 if (stat (procentry
, &statbuf
) == 0 && S_ISDIR (statbuf
.st_mode
))
225 *owner
= statbuf
.st_uid
;
233 get_number_of_cpu_cores (void)
236 FILE *f
= fopen ("/proc/cpuinfo", "r");
241 char *p
= fgets (buf
, sizeof (buf
), f
);
243 if (p
&& strncmp (buf
, "processor", 9) == 0)
252 /* CORES points to an array of at least get_number_of_cpu_cores () elements. */
255 get_cores_used_by_process (pid_t pid
, int *cores
)
257 char taskdir
[sizeof ("/proc/4294967295/task")];
262 sprintf (taskdir
, "/proc/%d/task", pid
);
263 dir
= opendir (taskdir
);
266 while ((dp
= readdir (dir
)) != NULL
)
271 if (!isdigit (dp
->d_name
[0])
272 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
275 tid
= atoi (dp
->d_name
);
276 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
292 linux_xfer_osdata_processes (gdb_byte
*readbuf
,
293 ULONGEST offset
, LONGEST len
)
295 /* We make the process list snapshot when the object starts to be read. */
296 static const char *buf
;
297 static LONGEST len_avail
= -1;
298 static struct buffer buffer
;
304 if (len_avail
!= -1 && len_avail
!= 0)
305 buffer_free (&buffer
);
308 buffer_init (&buffer
);
309 buffer_grow_str (&buffer
, "<osdata type=\"processes\">\n");
311 dirp
= opendir ("/proc");
314 const int num_cores
= get_number_of_cpu_cores ();
317 while ((dp
= readdir (dirp
)) != NULL
)
321 char user
[UT_NAMESIZE
];
328 if (!isdigit (dp
->d_name
[0])
329 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
332 sscanf (dp
->d_name
, "%d", &pid
);
333 command_line
= commandline_from_pid (pid
);
335 if (get_process_owner (&owner
, pid
) == 0)
336 user_from_uid (user
, sizeof (user
), owner
);
340 /* Find CPU cores used by the process. */
341 cores
= (int *) xcalloc (num_cores
, sizeof (int));
342 task_count
= get_cores_used_by_process (pid
, cores
);
343 cores_str
= (char *) xcalloc (task_count
, sizeof ("4294967295") + 1);
345 for (i
= 0; i
< num_cores
&& task_count
> 0; ++i
)
348 char core_str
[sizeof ("4294967205")];
350 sprintf (core_str
, "%d", i
);
351 strcat (cores_str
, core_str
);
353 task_count
-= cores
[i
];
355 strcat (cores_str
, ",");
363 "<column name=\"pid\">%d</column>"
364 "<column name=\"user\">%s</column>"
365 "<column name=\"command\">%s</column>"
366 "<column name=\"cores\">%s</column>"
370 command_line
? command_line
: "",
373 xfree (command_line
);
380 buffer_grow_str0 (&buffer
, "</osdata>\n");
381 buf
= buffer_finish (&buffer
);
382 len_avail
= strlen (buf
);
385 if (offset
>= len_avail
)
387 /* Done. Get rid of the buffer. */
388 buffer_free (&buffer
);
394 if (len
> len_avail
- offset
)
395 len
= len_avail
- offset
;
396 memcpy (readbuf
, buf
+ offset
, len
);
402 linux_xfer_osdata_threads (gdb_byte
*readbuf
,
403 ULONGEST offset
, LONGEST len
)
405 /* We make the process list snapshot when the object starts to be read. */
406 static const char *buf
;
407 static LONGEST len_avail
= -1;
408 static struct buffer buffer
;
414 if (len_avail
!= -1 && len_avail
!= 0)
415 buffer_free (&buffer
);
418 buffer_init (&buffer
);
419 buffer_grow_str (&buffer
, "<osdata type=\"threads\">\n");
421 dirp
= opendir ("/proc");
426 while ((dp
= readdir (dirp
)) != NULL
)
429 char procentry
[sizeof ("/proc/4294967295")];
431 if (!isdigit (dp
->d_name
[0])
432 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
435 sprintf (procentry
, "/proc/%s", dp
->d_name
);
436 if (stat (procentry
, &statbuf
) == 0
437 && S_ISDIR (statbuf
.st_mode
))
444 pathname
= xstrprintf ("/proc/%s/task", dp
->d_name
);
446 pid
= atoi (dp
->d_name
);
447 command_from_pid (command
, sizeof (command
), pid
);
449 dirp2
= opendir (pathname
);
455 while ((dp2
= readdir (dirp2
)) != NULL
)
460 if (!isdigit (dp2
->d_name
[0])
461 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
464 tid
= atoi (dp2
->d_name
);
465 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
470 "<column name=\"pid\">%d</column>"
471 "<column name=\"command\">%s</column>"
472 "<column name=\"tid\">%d</column>"
473 "<column name=\"core\">%d</column>"
491 buffer_grow_str0 (&buffer
, "</osdata>\n");
492 buf
= buffer_finish (&buffer
);
493 len_avail
= strlen (buf
);
496 if (offset
>= len_avail
)
498 /* Done. Get rid of the buffer. */
499 buffer_free (&buffer
);
505 if (len
> len_avail
- offset
)
506 len
= len_avail
- offset
;
507 memcpy (readbuf
, buf
+ offset
, len
);
515 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, LONGEST len
);
517 { "processes", "Listing of all processes", linux_xfer_osdata_processes
},
518 { "threads", "Listing of all threads", linux_xfer_osdata_threads
},
523 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
524 ULONGEST offset
, LONGEST len
)
526 if (!annex
|| *annex
== '\0')
528 static const char *buf
;
529 static LONGEST len_avail
= -1;
530 static struct buffer buffer
;
536 if (len_avail
!= -1 && len_avail
!= 0)
537 buffer_free (&buffer
);
540 buffer_init (&buffer
);
541 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
543 for (i
= 0; osdata_table
[i
].type
; ++i
)
547 "<column name=\"Type\">%s</column>"
548 "<column name=\"Description\">%s</column>"
550 osdata_table
[i
].type
,
551 osdata_table
[i
].description
);
553 buffer_grow_str0 (&buffer
, "</osdata>\n");
554 buf
= buffer_finish (&buffer
);
555 len_avail
= strlen (buf
);
558 if (offset
>= len_avail
)
560 /* Done. Get rid of the buffer. */
561 buffer_free (&buffer
);
567 if (len
> len_avail
- offset
)
568 len
= len_avail
- offset
;
569 memcpy (readbuf
, buf
+ offset
, len
);
577 for (i
= 0; osdata_table
[i
].type
; ++i
)
579 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
581 gdb_assert (readbuf
);
583 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);