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"
49 linux_common_core_of_thread (ptid_t ptid
)
51 char filename
[sizeof ("/proc//task//stat")
52 + 2 * 20 /* decimal digits for 2 numbers, max 2^64 bit each */
62 sprintf (filename
, "/proc/%d/task/%ld/stat",
63 ptid_get_pid (ptid
), ptid_get_lwp (ptid
));
64 f
= fopen (filename
, "r");
71 content
= xrealloc (content
, content_read
+ 1024);
72 n
= fread (content
+ content_read
, 1, 1024, f
);
76 content
[content_read
] = '\0';
81 p
= strchr (content
, '(');
89 /* If the first field after program name has index 0, then core number is
90 the field with index 36. There's no constant for that anywhere. */
92 p
= strtok_r (p
, " ", &ts
);
93 for (i
= 0; p
!= NULL
&& i
!= 36; ++i
)
94 p
= strtok_r (NULL
, " ", &ts
);
96 if (p
== NULL
|| sscanf (p
, "%d", &core
) == 0)
106 command_from_pid (char *command
, int maxlen
, pid_t pid
)
108 char *stat_path
= xstrprintf ("/proc/%d/stat", pid
);
109 FILE *fp
= fopen (stat_path
, "r");
115 /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in
116 include/linux/sched.h in the Linux kernel sources) plus two
117 (for the brackets). */
120 int items_read
= fscanf (fp
, "%d %32s", &stat_pid
, cmd
);
122 if (items_read
== 2 && pid
== stat_pid
)
124 cmd
[strlen (cmd
) - 1] = '\0'; /* Remove trailing parenthesis. */
125 strncpy (command
, cmd
+ 1, maxlen
); /* Ignore leading parenthesis. */
132 /* Return the PID if a /proc entry for the process cannot be found. */
133 snprintf (command
, maxlen
, "%d", pid
);
136 command
[maxlen
- 1] = '\0'; /* Ensure string is null-terminated. */
141 /* Returns the command-line of the process with the given PID. The returned
142 string needs to be freed using xfree after use. */
145 commandline_from_pid (pid_t pid
)
147 char *pathname
= xstrprintf ("/proc/%d/cmdline", pid
);
148 char *commandline
= NULL
;
149 FILE *f
= fopen (pathname
, "r");
158 size_t read_bytes
= fread (buf
, 1, sizeof (buf
), f
);
162 commandline
= (char *) xrealloc (commandline
, len
+ read_bytes
+ 1);
163 memcpy (commandline
+ len
, buf
, read_bytes
);
174 /* Replace null characters with spaces. */
175 for (i
= 0; i
< len
; ++i
)
176 if (commandline
[i
] == '\0')
177 commandline
[i
] = ' ';
179 commandline
[len
] = '\0';
183 /* Return the command in square brackets if the command-line is empty. */
184 commandline
= (char *) xmalloc (32);
185 commandline
[0] = '[';
186 command_from_pid (commandline
+ 1, 31, pid
);
188 len
= strlen (commandline
);
190 strcat (commandline
, "]");
200 user_from_uid (char *user
, int maxlen
, uid_t uid
)
202 struct passwd
*pwentry
= getpwuid (uid
);
206 strncpy (user
, pwentry
->pw_name
, maxlen
);
207 user
[maxlen
- 1] = '\0'; /* Ensure that the user name is null-terminated. */
214 get_process_owner (uid_t
*owner
, pid_t pid
)
217 char procentry
[sizeof ("/proc/4294967295")];
219 sprintf (procentry
, "/proc/%d", pid
);
221 if (stat (procentry
, &statbuf
) == 0 && S_ISDIR (statbuf
.st_mode
))
223 *owner
= statbuf
.st_uid
;
231 get_number_of_cpu_cores (void)
234 FILE *f
= fopen ("/proc/cpuinfo", "r");
239 char *p
= fgets (buf
, sizeof (buf
), f
);
241 if (p
&& strncmp (buf
, "processor", 9) == 0)
250 /* CORES points to an array of at least get_number_of_cpu_cores () elements. */
253 get_cores_used_by_process (pid_t pid
, int *cores
)
255 char taskdir
[sizeof ("/proc/4294967295/task")];
260 sprintf (taskdir
, "/proc/%d/task", pid
);
261 dir
= opendir (taskdir
);
264 while ((dp
= readdir (dir
)) != NULL
)
269 if (!isdigit (dp
->d_name
[0])
270 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
273 tid
= atoi (dp
->d_name
);
274 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
290 linux_xfer_osdata_processes (gdb_byte
*readbuf
,
291 ULONGEST offset
, LONGEST len
)
293 /* We make the process list snapshot when the object starts to be read. */
294 static const char *buf
;
295 static LONGEST len_avail
= -1;
296 static struct buffer buffer
;
302 if (len_avail
!= -1 && len_avail
!= 0)
303 buffer_free (&buffer
);
306 buffer_init (&buffer
);
307 buffer_grow_str (&buffer
, "<osdata type=\"processes\">\n");
309 dirp
= opendir ("/proc");
312 const int num_cores
= get_number_of_cpu_cores ();
315 while ((dp
= readdir (dirp
)) != NULL
)
319 char user
[UT_NAMESIZE
];
326 if (!isdigit (dp
->d_name
[0])
327 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
330 sscanf (dp
->d_name
, "%d", &pid
);
331 command_line
= commandline_from_pid (pid
);
333 if (get_process_owner (&owner
, pid
) == 0)
334 user_from_uid (user
, sizeof (user
), owner
);
338 /* Find CPU cores used by the process. */
339 cores
= (int *) xcalloc (num_cores
, sizeof (int));
340 task_count
= get_cores_used_by_process (pid
, cores
);
341 cores_str
= (char *) xcalloc (task_count
, sizeof ("4294967295") + 1);
343 for (i
= 0; i
< num_cores
&& task_count
> 0; ++i
)
346 char core_str
[sizeof ("4294967205")];
348 sprintf (core_str
, "%d", i
);
349 strcat (cores_str
, core_str
);
351 task_count
-= cores
[i
];
353 strcat (cores_str
, ",");
361 "<column name=\"pid\">%d</column>"
362 "<column name=\"user\">%s</column>"
363 "<column name=\"command\">%s</column>"
364 "<column name=\"cores\">%s</column>"
368 command_line
? command_line
: "",
371 xfree (command_line
);
378 buffer_grow_str0 (&buffer
, "</osdata>\n");
379 buf
= buffer_finish (&buffer
);
380 len_avail
= strlen (buf
);
383 if (offset
>= len_avail
)
385 /* Done. Get rid of the buffer. */
386 buffer_free (&buffer
);
392 if (len
> len_avail
- offset
)
393 len
= len_avail
- offset
;
394 memcpy (readbuf
, buf
+ offset
, len
);
400 linux_xfer_osdata_threads (gdb_byte
*readbuf
,
401 ULONGEST offset
, LONGEST len
)
403 /* We make the process list snapshot when the object starts to be read. */
404 static const char *buf
;
405 static LONGEST len_avail
= -1;
406 static struct buffer buffer
;
412 if (len_avail
!= -1 && len_avail
!= 0)
413 buffer_free (&buffer
);
416 buffer_init (&buffer
);
417 buffer_grow_str (&buffer
, "<osdata type=\"threads\">\n");
419 dirp
= opendir ("/proc");
424 while ((dp
= readdir (dirp
)) != NULL
)
427 char procentry
[sizeof ("/proc/4294967295")];
429 if (!isdigit (dp
->d_name
[0])
430 || NAMELEN (dp
) > sizeof ("4294967295") - 1)
433 sprintf (procentry
, "/proc/%s", dp
->d_name
);
434 if (stat (procentry
, &statbuf
) == 0
435 && S_ISDIR (statbuf
.st_mode
))
442 pathname
= xstrprintf ("/proc/%s/task", dp
->d_name
);
444 pid
= atoi (dp
->d_name
);
445 command_from_pid (command
, sizeof (command
), pid
);
447 dirp2
= opendir (pathname
);
453 while ((dp2
= readdir (dirp2
)) != NULL
)
458 if (!isdigit (dp2
->d_name
[0])
459 || NAMELEN (dp2
) > sizeof ("4294967295") - 1)
462 tid
= atoi (dp2
->d_name
);
463 core
= linux_common_core_of_thread (ptid_build (pid
, tid
, 0));
468 "<column name=\"pid\">%d</column>"
469 "<column name=\"command\">%s</column>"
470 "<column name=\"tid\">%d</column>"
471 "<column name=\"core\">%d</column>"
489 buffer_grow_str0 (&buffer
, "</osdata>\n");
490 buf
= buffer_finish (&buffer
);
491 len_avail
= strlen (buf
);
494 if (offset
>= len_avail
)
496 /* Done. Get rid of the buffer. */
497 buffer_free (&buffer
);
503 if (len
> len_avail
- offset
)
504 len
= len_avail
- offset
;
505 memcpy (readbuf
, buf
+ offset
, len
);
513 LONGEST (*getter
) (gdb_byte
*readbuf
, ULONGEST offset
, LONGEST len
);
515 { "processes", "Listing of all processes", linux_xfer_osdata_processes
},
516 { "threads", "Listing of all threads", linux_xfer_osdata_threads
},
521 linux_common_xfer_osdata (const char *annex
, gdb_byte
*readbuf
,
522 ULONGEST offset
, LONGEST len
)
524 if (!annex
|| *annex
== '\0')
526 static const char *buf
;
527 static LONGEST len_avail
= -1;
528 static struct buffer buffer
;
534 if (len_avail
!= -1 && len_avail
!= 0)
535 buffer_free (&buffer
);
538 buffer_init (&buffer
);
539 buffer_grow_str (&buffer
, "<osdata type=\"types\">\n");
541 for (i
= 0; osdata_table
[i
].type
; ++i
)
545 "<column name=\"Type\">%s</column>"
546 "<column name=\"Description\">%s</column>"
548 osdata_table
[i
].type
,
549 osdata_table
[i
].description
);
551 buffer_grow_str0 (&buffer
, "</osdata>\n");
552 buf
= buffer_finish (&buffer
);
553 len_avail
= strlen (buf
);
556 if (offset
>= len_avail
)
558 /* Done. Get rid of the buffer. */
559 buffer_free (&buffer
);
565 if (len
> len_avail
- offset
)
566 len
= len_avail
- offset
;
567 memcpy (readbuf
, buf
+ offset
, len
);
575 for (i
= 0; osdata_table
[i
].type
; ++i
)
577 if (strcmp (annex
, osdata_table
[i
].type
) == 0)
579 gdb_assert (readbuf
);
581 return (osdata_table
[i
].getter
) (readbuf
, offset
, len
);