diff options
Diffstat (limited to 'gdb/gdbserver/linux-low.c')
-rw-r--r-- | gdb/gdbserver/linux-low.c | 316 |
1 files changed, 3 insertions, 313 deletions
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index d84fd68..a9cdaca 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -19,6 +19,7 @@ #include "server.h" #include "linux-low.h" +#include "linux-osdata.h" #include <sys/wait.h> #include <stdio.h> @@ -118,7 +119,6 @@ static int linux_wait_for_event (ptid_t ptid, int *wstat, int options); static void *add_lwp (ptid_t ptid); static int linux_stopped_by_watchpoint (void); static void mark_lwp_dead (struct lwp_info *lwp, int wstat); -static int linux_core_of_thread (ptid_t ptid); static void proceed_all_lwps (void); static int finish_step_over (struct lwp_info *lwp); static CORE_ADDR get_stop_pc (struct lwp_info *lwp); @@ -4387,264 +4387,11 @@ linux_read_offsets (CORE_ADDR *text_p, CORE_ADDR *data_p) #endif static int -compare_ints (const void *xa, const void *xb) -{ - int a = *(const int *)xa; - int b = *(const int *)xb; - - return a - b; -} - -static int * -unique (int *b, int *e) -{ - int *d = b; - while (++b != e) - if (*d != *b) - *++d = *b; - return ++d; -} - -/* Given PID, iterates over all threads in that process. - - Information about each thread, in a format suitable for qXfer:osdata:thread - is printed to BUFFER, if it's not NULL. BUFFER is assumed to be already - initialized, and the caller is responsible for finishing and appending '\0' - to it. - - The list of cores that threads are running on is assigned to *CORES, if it - is not NULL. If no cores are found, *CORES will be set to NULL. Caller - should free *CORES. */ - -static void -list_threads (int pid, struct buffer *buffer, char **cores) -{ - int count = 0; - int allocated = 10; - int *core_numbers = xmalloc (sizeof (int) * allocated); - char pathname[128]; - DIR *dir; - struct dirent *dp; - struct stat statbuf; - - sprintf (pathname, "/proc/%d/task", pid); - if (stat (pathname, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) - { - dir = opendir (pathname); - if (!dir) - { - free (core_numbers); - return; - } - - while ((dp = readdir (dir)) != NULL) - { - unsigned long lwp = strtoul (dp->d_name, NULL, 10); - - if (lwp != 0) - { - unsigned core = linux_core_of_thread (ptid_build (pid, lwp, 0)); - - if (core != -1) - { - char s[sizeof ("4294967295")]; - sprintf (s, "%u", core); - - if (count == allocated) - { - allocated *= 2; - core_numbers = realloc (core_numbers, - sizeof (int) * allocated); - } - core_numbers[count++] = core; - if (buffer) - buffer_xml_printf (buffer, - "<item>" - "<column name=\"pid\">%d</column>" - "<column name=\"tid\">%s</column>" - "<column name=\"core\">%s</column>" - "</item>", pid, dp->d_name, s); - } - else - { - if (buffer) - buffer_xml_printf (buffer, - "<item>" - "<column name=\"pid\">%d</column>" - "<column name=\"tid\">%s</column>" - "</item>", pid, dp->d_name); - } - } - } - closedir (dir); - } - - if (cores) - { - *cores = NULL; - if (count > 0) - { - struct buffer buffer2; - int *b; - int *e; - qsort (core_numbers, count, sizeof (int), compare_ints); - - /* Remove duplicates. */ - b = core_numbers; - e = unique (b, core_numbers + count); - - buffer_init (&buffer2); - - for (b = core_numbers; b != e; ++b) - { - char number[sizeof ("4294967295")]; - sprintf (number, "%u", *b); - buffer_xml_printf (&buffer2, "%s%s", - (b == core_numbers) ? "" : ",", number); - } - buffer_grow_str0 (&buffer2, ""); - - *cores = buffer_finish (&buffer2); - } - } - free (core_numbers); -} - -static void -show_process (int pid, const char *username, struct buffer *buffer) -{ - char pathname[128]; - FILE *f; - char cmd[MAXPATHLEN + 1]; - - sprintf (pathname, "/proc/%d/cmdline", pid); - - if ((f = fopen (pathname, "r")) != NULL) - { - size_t len = fread (cmd, 1, sizeof (cmd) - 1, f); - if (len > 0) - { - char *cores = 0; - int i; - for (i = 0; i < len; i++) - if (cmd[i] == '\0') - cmd[i] = ' '; - cmd[len] = '\0'; - - buffer_xml_printf (buffer, - "<item>" - "<column name=\"pid\">%d</column>" - "<column name=\"user\">%s</column>" - "<column name=\"command\">%s</column>", - pid, - username, - cmd); - - /* This only collects core numbers, and does not print threads. */ - list_threads (pid, NULL, &cores); - - if (cores) - { - buffer_xml_printf (buffer, - "<column name=\"cores\">%s</column>", cores); - free (cores); - } - - buffer_xml_printf (buffer, "</item>"); - } - fclose (f); - } -} - -static int linux_qxfer_osdata (const char *annex, unsigned char *readbuf, unsigned const char *writebuf, CORE_ADDR offset, int len) { - /* We make the process list snapshot when the object starts to be - read. */ - static const char *buf; - static long len_avail = -1; - static struct buffer buffer; - int processes = 0; - int threads = 0; - - DIR *dirp; - - if (strcmp (annex, "processes") == 0) - processes = 1; - else if (strcmp (annex, "threads") == 0) - threads = 1; - else - return 0; - - if (!readbuf || writebuf) - return 0; - - if (offset == 0) - { - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - buf = NULL; - buffer_init (&buffer); - if (processes) - buffer_grow_str (&buffer, "<osdata type=\"processes\">"); - else if (threads) - buffer_grow_str (&buffer, "<osdata type=\"threads\">"); - - dirp = opendir ("/proc"); - if (dirp) - { - struct dirent *dp; - while ((dp = readdir (dirp)) != NULL) - { - struct stat statbuf; - char procentry[sizeof ("/proc/4294967295")]; - - if (!isdigit (dp->d_name[0]) - || strlen (dp->d_name) > sizeof ("4294967295") - 1) - continue; - - sprintf (procentry, "/proc/%s", dp->d_name); - if (stat (procentry, &statbuf) == 0 - && S_ISDIR (statbuf.st_mode)) - { - int pid = (int) strtoul (dp->d_name, NULL, 10); - - if (processes) - { - struct passwd *entry = getpwuid (statbuf.st_uid); - show_process (pid, entry ? entry->pw_name : "?", &buffer); - } - else if (threads) - { - list_threads (pid, &buffer, NULL); - } - } - } - - closedir (dirp); - } - buffer_grow_str0 (&buffer, "</osdata>\n"); - buf = buffer_finish (&buffer); - len_avail = strlen (buf); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the data. */ - buffer_free (&buffer); - buf = NULL; - len_avail = 0; - return 0; - } - - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); - - return len; + return linux_common_xfer_osdata (annex, readbuf, offset, len); } /* Convert a native/host siginfo object, into/from the siginfo in the @@ -4907,63 +4654,6 @@ linux_qxfer_spu (const char *annex, unsigned char *readbuf, return ret; } -static int -linux_core_of_thread (ptid_t ptid) -{ - char filename[sizeof ("/proc//task//stat") - + 2 * 20 /* decimal digits for 2 numbers, max 2^64 bit each */ - + 1]; - FILE *f; - char *content = NULL; - char *p; - char *ts = 0; - int content_read = 0; - int i; - int core; - - sprintf (filename, "/proc/%d/task/%ld/stat", - ptid_get_pid (ptid), ptid_get_lwp (ptid)); - f = fopen (filename, "r"); - if (!f) - return -1; - - for (;;) - { - int n; - content = realloc (content, content_read + 1024); - n = fread (content + content_read, 1, 1024, f); - content_read += n; - if (n < 1024) - { - content[content_read] = '\0'; - break; - } - } - - p = strchr (content, '('); - - /* Skip ")". */ - if (p != NULL) - p = strchr (p, ')'); - if (p != NULL) - p++; - - /* If the first field after program name has index 0, then core number is - the field with index 36. There's no constant for that anywhere. */ - if (p != NULL) - p = strtok_r (p, " ", &ts); - for (i = 0; p != NULL && i != 36; ++i) - p = strtok_r (NULL, " ", &ts); - - if (p == NULL || sscanf (p, "%d", &core) == 0) - core = -1; - - free (content); - fclose (f); - - return core; -} - static void linux_process_qsupported (const char *query) { @@ -5111,7 +4801,7 @@ static struct target_ops linux_target_ops = { #else NULL, #endif - linux_core_of_thread, + linux_common_core_of_thread, linux_process_qsupported, linux_supports_tracepoints, linux_read_pc, |