From 750b258ef80992e76a3b03fe57dc9517e63de7f5 Mon Sep 17 00:00:00 2001 From: Philippe Waroquiers Date: Sat, 8 Dec 2018 17:28:31 +0100 Subject: [PATCH] Fix leaks in all the linux osdata annex transfers + code factorization. Valgrind reports leaks in all linux osdata annex transfers of linux-osdata.c. A typical leak (this one is of gdb.base/info-os) is: ==10592== VALGRIND_GDB_ERROR_BEGIN ==10592== 65,536 bytes in 1 blocks are definitely lost in loss record 3,175 of 3,208 ==10592== at 0x4C2E273: realloc (vg_replace_malloc.c:826) ==10592== by 0x409B0C: xrealloc (common-utils.c:62) ==10592== by 0x408BC3: buffer_grow(buffer*, char const*, unsigned long) [clone .part.1] (buffer.c:40) ==10592== by 0x5263DF: linux_xfer_osdata_processes(unsigned char*, unsigned long, unsigned long) (linux-osdata.c:370) ==10592== by 0x520875: linux_nat_xfer_osdata (linux-nat.c:4214) ... The leaks are created because the linux_xfer_osdata_* functions transfer the ownership of their 'static struct buffer' memory to their 'static char *buf' local var, but then call buffer_free instead of xfree-ing buf. I see no reason why the ownership of the memory has to be transferred from a local var to another local var, so the fix consists in dropping the 'static char *buf' and accessing the struct buffer memory where needed. Also, because this bug was replicated in all functions, and there was a non neglectible amount of duplicated code, the setup and usage of the 'static struct buffer' is factorized in a new function common_getter. The buffer for a specific annex is now a member of the struct osdata_type instead of being a static var of each linux_xfer_osdata_* function. Thanks to this, all the linux_xfer_osdata_* do not have anymore any logic related to the partial transfer of data: they now only build the xml data in a struct buffer. This all removes about 300 SLOC. Note: git diff/git format-patch shows a lot of differences only due to space changes/indentation changes. So, git diff -w helps to look only at the relevant differences. gdb/ChangeLog 2018-12-11 Philippe Waroquiers * nat/linux-osdata.c (common_getter): New function. (struct osdata_type): Change getter to take_snapshot. Add LONGEST len_avail and struct buffer buffer. Change all elements in the initializer. Add an element for the list of types. (linux_xfer_osdata_info_os_types): New function. (linux_common_xfer_osdata): Use common_getter for the list of types. Replace getter call by common_getter. (linux_xfer_osdata_cpus): Remove args READBUF, OFFSET, LEN. Add arg BUFFER. Only keep the code that adds data in BUFFER. (linux_xfer_osdata_fds): Likewise. (linux_xfer_osdata_modules): Likewise. (linux_xfer_osdata_msg): Likewise. (linux_xfer_osdata_processes): Likewise. (linux_xfer_osdata_processgroups): Likewise. (linux_xfer_osdata_sem): Likewise. (linux_xfer_osdata_shm): Likewise. (linux_xfer_osdata_isockets): Likewise. (linux_xfer_osdata_threads): Likewise. --- gdb/ChangeLog | 22 + gdb/nat/linux-osdata.c | 1569 ++++++++++++++++++++---------------------------- 2 files changed, 662 insertions(+), 929 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 04904c6..3d35d3b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,27 @@ 2018-12-11 Philippe Waroquiers + * nat/linux-osdata.c (common_getter): New function. + (struct osdata_type): Change getter to take_snapshot. + Add LONGEST len_avail and struct buffer buffer. + Change all elements in the initializer. + Add an element for the list of types. + (linux_xfer_osdata_info_os_types): New function. + (linux_common_xfer_osdata): Use common_getter for the list of types. + Replace getter call by common_getter. + (linux_xfer_osdata_cpus): Remove args READBUF, OFFSET, LEN. + Add arg BUFFER. Only keep the code that adds data in BUFFER. + (linux_xfer_osdata_fds): Likewise. + (linux_xfer_osdata_modules): Likewise. + (linux_xfer_osdata_msg): Likewise. + (linux_xfer_osdata_processes): Likewise. + (linux_xfer_osdata_processgroups): Likewise. + (linux_xfer_osdata_sem): Likewise. + (linux_xfer_osdata_shm): Likewise. + (linux_xfer_osdata_isockets): Likewise. + (linux_xfer_osdata_threads): Likewise. + +2018-12-11 Philippe Waroquiers + * nat/linux-osdata.c: Removed various trailing spaces. 2018-12-10 Andrew Burgess diff --git a/gdb/nat/linux-osdata.c b/gdb/nat/linux-osdata.c index 62ab42d..baca7fe 100644 --- a/gdb/nat/linux-osdata.c +++ b/gdb/nat/linux-osdata.c @@ -278,114 +278,83 @@ get_cores_used_by_process (PID_T pid, int *cores, const int num_cores) return task_count; } -static LONGEST -linux_xfer_osdata_processes (gdb_byte *readbuf, - ULONGEST offset, ULONGEST len) +static void +linux_xfer_osdata_processes (struct buffer *buffer) { - /* We make the process list snapshot when the object starts to be read. */ - static const char *buf; - static LONGEST len_avail = -1; - static struct buffer buffer; + DIR *dirp; - if (offset == 0) - { - DIR *dirp; + buffer_grow_str (buffer, "\n"); - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - buf = NULL; - buffer_init (&buffer); - buffer_grow_str (&buffer, "\n"); + dirp = opendir ("/proc"); + if (dirp) + { + const int num_cores = sysconf (_SC_NPROCESSORS_ONLN); + struct dirent *dp; - dirp = opendir ("/proc"); - if (dirp) + while ((dp = readdir (dirp)) != NULL) { - const int num_cores = sysconf (_SC_NPROCESSORS_ONLN); - struct dirent *dp; - - while ((dp = readdir (dirp)) != NULL) - { - PID_T pid; - uid_t owner; - char user[UT_NAMESIZE]; - char *command_line; - int *cores; - int task_count; - char *cores_str; - int i; - - if (!isdigit (dp->d_name[0]) - || NAMELEN (dp) > MAX_PID_T_STRLEN) - continue; + PID_T pid; + uid_t owner; + char user[UT_NAMESIZE]; + char *command_line; + int *cores; + int task_count; + char *cores_str; + int i; - sscanf (dp->d_name, "%lld", &pid); - command_line = commandline_from_pid (pid); - - if (get_process_owner (&owner, pid) == 0) - user_from_uid (user, sizeof (user), owner); - else - strcpy (user, "?"); - - /* Find CPU cores used by the process. */ - cores = XCNEWVEC (int, num_cores); - task_count = get_cores_used_by_process (pid, cores, num_cores); - cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1); - - for (i = 0; i < num_cores && task_count > 0; ++i) - if (cores[i]) - { - char core_str[sizeof ("4294967295")]; - - sprintf (core_str, "%d", i); - strcat (cores_str, core_str); - - task_count -= cores[i]; - if (task_count > 0) - strcat (cores_str, ","); - } - - xfree (cores); - - buffer_xml_printf ( - &buffer, - "" - "%lld" - "%s" - "%s" - "%s" - "", - pid, - user, - command_line ? command_line : "", - cores_str); - - xfree (command_line); - xfree (cores_str); - } + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > MAX_PID_T_STRLEN) + continue; - closedir (dirp); + sscanf (dp->d_name, "%lld", &pid); + command_line = commandline_from_pid (pid); + + if (get_process_owner (&owner, pid) == 0) + user_from_uid (user, sizeof (user), owner); + else + strcpy (user, "?"); + + /* Find CPU cores used by the process. */ + cores = XCNEWVEC (int, num_cores); + task_count = get_cores_used_by_process (pid, cores, num_cores); + cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1); + + for (i = 0; i < num_cores && task_count > 0; ++i) + if (cores[i]) + { + char core_str[sizeof ("4294967295")]; + + sprintf (core_str, "%d", i); + strcat (cores_str, core_str); + + task_count -= cores[i]; + if (task_count > 0) + strcat (cores_str, ","); + } + + xfree (cores); + + buffer_xml_printf + (buffer, + "" + "%lld" + "%s" + "%s" + "%s" + "", + pid, + user, + command_line ? command_line : "", + cores_str); + + xfree (command_line); + xfree (cores_str); } - buffer_grow_str0 (&buffer, "\n"); - buf = buffer_finish (&buffer); - len_avail = strlen (buf); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - buffer_free (&buffer); - buf = NULL; - len_avail = 0; - return 0; + closedir (dirp); } - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); - - return len; + buffer_grow_str0 (buffer, "\n"); } /* A simple PID/PGID pair. */ @@ -425,428 +394,305 @@ struct pid_pgid_entry PID_T pid, pgid; }; -/* Collect all process groups from /proc. */ +/* Collect all process groups from /proc in BUFFER. */ -static LONGEST -linux_xfer_osdata_processgroups (gdb_byte *readbuf, - ULONGEST offset, ULONGEST len) +static void +linux_xfer_osdata_processgroups (struct buffer *buffer) { - /* We make the process list snapshot when the object starts to be read. */ - static const char *buf; - static LONGEST len_avail = -1; - static struct buffer buffer; + DIR *dirp; - if (offset == 0) + buffer_grow_str (buffer, "\n"); + + dirp = opendir ("/proc"); + if (dirp) { - DIR *dirp; + std::vector process_list; + struct dirent *dp; - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - buf = NULL; - buffer_init (&buffer); - buffer_grow_str (&buffer, "\n"); + process_list.reserve (512); - dirp = opendir ("/proc"); - if (dirp) + /* Build list consisting of PIDs followed by their + associated PGID. */ + while ((dp = readdir (dirp)) != NULL) { - std::vector process_list; - struct dirent *dp; - - process_list.reserve (512); + PID_T pid, pgid; - /* Build list consisting of PIDs followed by their - associated PGID. */ - while ((dp = readdir (dirp)) != NULL) - { - PID_T pid, pgid; - - if (!isdigit (dp->d_name[0]) - || NAMELEN (dp) > MAX_PID_T_STRLEN) - continue; + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > MAX_PID_T_STRLEN) + continue; - sscanf (dp->d_name, "%lld", &pid); - pgid = getpgid (pid); + sscanf (dp->d_name, "%lld", &pid); + pgid = getpgid (pid); - if (pgid > 0) - process_list.emplace_back (pid, pgid); - } + if (pgid > 0) + process_list.emplace_back (pid, pgid); + } - closedir (dirp); + closedir (dirp); - /* Sort the process list. */ - std::sort (process_list.begin (), process_list.end ()); + /* Sort the process list. */ + std::sort (process_list.begin (), process_list.end ()); - for (const pid_pgid_entry &entry : process_list) - { - PID_T pid = entry.pid; - PID_T pgid = entry.pgid; - char leader_command[32]; - char *command_line; - - command_from_pid (leader_command, sizeof (leader_command), pgid); - command_line = commandline_from_pid (pid); - - buffer_xml_printf ( - &buffer, - "" - "%lld" - "%s" - "%lld" - "%s" - "", - pgid, - leader_command, - pid, - command_line ? command_line : ""); - - xfree (command_line); - } + for (const pid_pgid_entry &entry : process_list) + { + PID_T pid = entry.pid; + PID_T pgid = entry.pgid; + char leader_command[32]; + char *command_line; + + command_from_pid (leader_command, sizeof (leader_command), pgid); + command_line = commandline_from_pid (pid); + + buffer_xml_printf + (buffer, + "" + "%lld" + "%s" + "%lld" + "%s" + "", + pgid, + leader_command, + pid, + command_line ? command_line : ""); + + xfree (command_line); } - - buffer_grow_str0 (&buffer, "\n"); - buf = buffer_finish (&buffer); - len_avail = strlen (buf); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - 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; + buffer_grow_str0 (buffer, "\n"); } /* Collect all the threads in /proc by iterating through processes and - then tasks within each process. */ + then tasks within each process in BUFFER. */ -static LONGEST -linux_xfer_osdata_threads (gdb_byte *readbuf, - ULONGEST offset, ULONGEST len) +static void +linux_xfer_osdata_threads (struct buffer *buffer) { - /* We make the process list snapshot when the object starts to be read. */ - static const char *buf; - static LONGEST len_avail = -1; - static struct buffer buffer; + DIR *dirp; - if (offset == 0) - { - DIR *dirp; + buffer_grow_str (buffer, "\n"); - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - buf = NULL; - buffer_init (&buffer); - buffer_grow_str (&buffer, "\n"); + dirp = opendir ("/proc"); + if (dirp) + { + struct dirent *dp; - dirp = opendir ("/proc"); - if (dirp) + while ((dp = readdir (dirp)) != NULL) { - struct dirent *dp; + struct stat statbuf; + char procentry[sizeof ("/proc/4294967295")]; - while ((dp = readdir (dirp)) != NULL) - { - struct stat statbuf; - char procentry[sizeof ("/proc/4294967295")]; + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > sizeof ("4294967295") - 1) + continue; - if (!isdigit (dp->d_name[0]) - || NAMELEN (dp) > sizeof ("4294967295") - 1) - continue; + xsnprintf (procentry, sizeof (procentry), "/proc/%s", + dp->d_name); + if (stat (procentry, &statbuf) == 0 + && S_ISDIR (statbuf.st_mode)) + { + DIR *dirp2; + PID_T pid; + char command[32]; - xsnprintf (procentry, sizeof (procentry), "/proc/%s", - dp->d_name); - if (stat (procentry, &statbuf) == 0 - && S_ISDIR (statbuf.st_mode)) - { - DIR *dirp2; - PID_T pid; - char command[32]; + std::string pathname + = string_printf ("/proc/%s/task", dp->d_name); - std::string pathname - = string_printf ("/proc/%s/task", dp->d_name); + pid = atoi (dp->d_name); + command_from_pid (command, sizeof (command), pid); - pid = atoi (dp->d_name); - command_from_pid (command, sizeof (command), pid); + dirp2 = opendir (pathname.c_str ()); - dirp2 = opendir (pathname.c_str ()); + if (dirp2) + { + struct dirent *dp2; - if (dirp2) + while ((dp2 = readdir (dirp2)) != NULL) { - struct dirent *dp2; - - while ((dp2 = readdir (dirp2)) != NULL) - { - PID_T tid; - int core; - - if (!isdigit (dp2->d_name[0]) - || NAMELEN (dp2) > sizeof ("4294967295") - 1) - continue; - - tid = atoi (dp2->d_name); - core = linux_common_core_of_thread (ptid_t (pid, tid, 0)); - - buffer_xml_printf ( - &buffer, - "" - "%lld" - "%s" - "%lld" - "%d" - "", - pid, - command, - tid, - core); - } - - closedir (dirp2); + PID_T tid; + int core; + + if (!isdigit (dp2->d_name[0]) + || NAMELEN (dp2) > sizeof ("4294967295") - 1) + continue; + + tid = atoi (dp2->d_name); + core = linux_common_core_of_thread (ptid_t (pid, tid, 0)); + + buffer_xml_printf + (buffer, + "" + "%lld" + "%s" + "%lld" + "%d" + "", + pid, + command, + tid, + core); } + + closedir (dirp2); } } - - closedir (dirp); } - buffer_grow_str0 (&buffer, "\n"); - buf = buffer_finish (&buffer); - len_avail = strlen (buf); + closedir (dirp); } - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - 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; + buffer_grow_str0 (buffer, "\n"); } -/* Collect data about the cpus/cores on the system */ +/* Collect data about the cpus/cores on the system in BUFFER. */ -static LONGEST -linux_xfer_osdata_cpus (gdb_byte *readbuf, - ULONGEST offset, ULONGEST len) +static void +linux_xfer_osdata_cpus (struct buffer *buffer) { - static const char *saved_buf; - static LONGEST len_avail = -1; - static struct buffer buffer; + int first_item = 1; - if (offset == 0) - { - int first_item = 1; + buffer_grow_str (buffer, "\n"); - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - saved_buf = NULL; - buffer_init (&buffer); - buffer_grow_str (&buffer, "\n"); + gdb_file_up fp = gdb_fopen_cloexec ("/proc/cpuinfo", "r"); + if (fp != NULL) + { + char buf[8192]; - gdb_file_up fp = gdb_fopen_cloexec ("/proc/cpuinfo", "r"); - if (fp != NULL) + do { - char buf[8192]; - - do + if (fgets (buf, sizeof (buf), fp.get ())) { - if (fgets (buf, sizeof (buf), fp.get ())) - { - char *key, *value; - int i = 0; + char *key, *value; + int i = 0; - key = strtok (buf, ":"); - if (key == NULL) - continue; - - value = strtok (NULL, ":"); - if (value == NULL) - continue; + key = strtok (buf, ":"); + if (key == NULL) + continue; - while (key[i] != '\t' && key[i] != '\0') - i++; + value = strtok (NULL, ":"); + if (value == NULL) + continue; - key[i] = '\0'; + while (key[i] != '\t' && key[i] != '\0') + i++; - i = 0; - while (value[i] != '\t' && value[i] != '\0') - i++; + key[i] = '\0'; - value[i] = '\0'; + i = 0; + while (value[i] != '\t' && value[i] != '\0') + i++; - if (strcmp (key, "processor") == 0) - { - if (first_item) - buffer_grow_str (&buffer, ""); - else - buffer_grow_str (&buffer, ""); + value[i] = '\0'; - first_item = 0; - } + if (strcmp (key, "processor") == 0) + { + if (first_item) + buffer_grow_str (buffer, ""); + else + buffer_grow_str (buffer, ""); - buffer_xml_printf (&buffer, - "%s", - key, - value); + first_item = 0; } - } - while (!feof (fp.get ())); - if (first_item == 0) - buffer_grow_str (&buffer, ""); + buffer_xml_printf (buffer, + "%s", + key, + value); + } } + while (!feof (fp.get ())); - buffer_grow_str0 (&buffer, "\n"); - saved_buf = buffer_finish (&buffer); - len_avail = strlen (saved_buf); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - buffer_free (&buffer); - saved_buf = NULL; - len_avail = 0; - return 0; + if (first_item == 0) + buffer_grow_str (buffer, ""); } - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, saved_buf + offset, len); - - return len; + buffer_grow_str0 (buffer, "\n"); } /* Collect all the open file descriptors found in /proc and put the details - found about them into READBUF. */ + found about them into BUFFER. */ -static LONGEST -linux_xfer_osdata_fds (gdb_byte *readbuf, - ULONGEST offset, ULONGEST len) +static void +linux_xfer_osdata_fds (struct buffer *buffer) { - /* We make the process list snapshot when the object starts to be read. */ - static const char *saved_buf; - static LONGEST len_avail = -1; - static struct buffer buffer; + DIR *dirp; - if (offset == 0) - { - DIR *dirp; + buffer_grow_str (buffer, "\n"); - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - saved_buf = NULL; - buffer_init (&buffer); - buffer_grow_str (&buffer, "\n"); + dirp = opendir ("/proc"); + if (dirp) + { + struct dirent *dp; - dirp = opendir ("/proc"); - if (dirp) + while ((dp = readdir (dirp)) != NULL) { - struct dirent *dp; + struct stat statbuf; + char procentry[sizeof ("/proc/4294967295")]; - while ((dp = readdir (dirp)) != NULL) - { - struct stat statbuf; - char procentry[sizeof ("/proc/4294967295")]; + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > sizeof ("4294967295") - 1) + continue; - if (!isdigit (dp->d_name[0]) - || NAMELEN (dp) > sizeof ("4294967295") - 1) - continue; + xsnprintf (procentry, sizeof (procentry), "/proc/%s", + dp->d_name); + if (stat (procentry, &statbuf) == 0 + && S_ISDIR (statbuf.st_mode)) + { + DIR *dirp2; + PID_T pid; + char command[32]; - xsnprintf (procentry, sizeof (procentry), "/proc/%s", - dp->d_name); - if (stat (procentry, &statbuf) == 0 - && S_ISDIR (statbuf.st_mode)) - { - DIR *dirp2; - PID_T pid; - char command[32]; + pid = atoi (dp->d_name); + command_from_pid (command, sizeof (command), pid); - pid = atoi (dp->d_name); - command_from_pid (command, sizeof (command), pid); + std::string pathname + = string_printf ("/proc/%s/fd", dp->d_name); + dirp2 = opendir (pathname.c_str ()); - std::string pathname - = string_printf ("/proc/%s/fd", dp->d_name); - dirp2 = opendir (pathname.c_str ()); + if (dirp2) + { + struct dirent *dp2; - if (dirp2) + while ((dp2 = readdir (dirp2)) != NULL) { - struct dirent *dp2; - - while ((dp2 = readdir (dirp2)) != NULL) - { - char buf[1000]; - ssize_t rslt; - - if (!isdigit (dp2->d_name[0])) - continue; - - std::string fdname - = string_printf ("%s/%s", pathname.c_str (), - dp2->d_name); - rslt = readlink (fdname.c_str (), buf, - sizeof (buf) - 1); - if (rslt >= 0) - buf[rslt] = '\0'; - - buffer_xml_printf ( - &buffer, - "" - "%s" - "%s" - "%s" - "%s" - "", - dp->d_name, - command, - dp2->d_name, - (rslt >= 0 ? buf : dp2->d_name)); - } - - closedir (dirp2); + char buf[1000]; + ssize_t rslt; + + if (!isdigit (dp2->d_name[0])) + continue; + + std::string fdname + = string_printf ("%s/%s", pathname.c_str (), + dp2->d_name); + rslt = readlink (fdname.c_str (), buf, + sizeof (buf) - 1); + if (rslt >= 0) + buf[rslt] = '\0'; + + buffer_xml_printf + (buffer, + "" + "%s" + "%s" + "%s" + "%s" + "", + dp->d_name, + command, + dp2->d_name, + (rslt >= 0 ? buf : dp2->d_name)); } + + closedir (dirp2); } } - - closedir (dirp); } - buffer_grow_str0 (&buffer, "\n"); - saved_buf = buffer_finish (&buffer); - len_avail = strlen (saved_buf); + closedir (dirp); } - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - buffer_free (&buffer); - saved_buf = NULL; - len_avail = 0; - return 0; - } - - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, saved_buf + offset, len); - - return len; + buffer_grow_str0 (buffer, "\n"); } /* Returns the socket state STATE in textual form. */ @@ -1039,49 +885,19 @@ print_sockets (unsigned short family, int tcp, struct buffer *buffer) } } -/* Collect data about internet sockets and write it into READBUF. */ +/* Collect data about internet sockets and write it into BUFFER. */ -static LONGEST -linux_xfer_osdata_isockets (gdb_byte *readbuf, - ULONGEST offset, ULONGEST len) +static void +linux_xfer_osdata_isockets (struct buffer *buffer) { - static const char *buf; - static LONGEST len_avail = -1; - static struct buffer buffer; - - if (offset == 0) - { - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - buf = NULL; - buffer_init (&buffer); - buffer_grow_str (&buffer, "\n"); - - print_sockets (AF_INET, 1, &buffer); - print_sockets (AF_INET, 0, &buffer); - print_sockets (AF_INET6, 1, &buffer); - print_sockets (AF_INET6, 0, &buffer); - - buffer_grow_str0 (&buffer, "\n"); - buf = buffer_finish (&buffer); - len_avail = strlen (buf); - } + buffer_grow_str (buffer, "\n"); - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - buffer_free (&buffer); - buf = NULL; - len_avail = 0; - return 0; - } + print_sockets (AF_INET, 1, buffer); + print_sockets (AF_INET, 0, buffer); + print_sockets (AF_INET6, 1, buffer); + print_sockets (AF_INET6, 0, buffer); - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); - - return len; + buffer_grow_str0 (buffer, "\n"); } /* Converts the time SECONDS into textual form and copies it into a @@ -1120,546 +936,444 @@ group_from_gid (char *group, int maxlen, gid_t gid) } /* Collect data about shared memory recorded in /proc and write it - into READBUF. */ + into BUFFER. */ -static LONGEST -linux_xfer_osdata_shm (gdb_byte *readbuf, - ULONGEST offset, ULONGEST len) +static void +linux_xfer_osdata_shm (struct buffer *buffer) { - static const char *saved_buf; - static LONGEST len_avail = -1; - static struct buffer buffer; + buffer_grow_str (buffer, "\n"); - if (offset == 0) + gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r"); + if (fp) { - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - saved_buf = NULL; - buffer_init (&buffer); - buffer_grow_str (&buffer, "\n"); - - gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r"); - if (fp) - { - char buf[8192]; + char buf[8192]; - do + do + { + if (fgets (buf, sizeof (buf), fp.get ())) { - if (fgets (buf, sizeof (buf), fp.get ())) + key_t key; + uid_t uid, cuid; + gid_t gid, cgid; + PID_T cpid, lpid; + int shmid, size, nattch; + TIME_T atime, dtime, ctime; + unsigned int perms; + int items_read; + + items_read = sscanf (buf, + "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld", + &key, &shmid, &perms, &size, + &cpid, &lpid, + &nattch, + &uid, &gid, &cuid, &cgid, + &atime, &dtime, &ctime); + + if (items_read == 14) { - key_t key; - uid_t uid, cuid; - gid_t gid, cgid; - PID_T cpid, lpid; - int shmid, size, nattch; - TIME_T atime, dtime, ctime; - unsigned int perms; - int items_read; - - items_read = sscanf (buf, - "%d %d %o %d %lld %lld %d %u %u %u %u %lld %lld %lld", - &key, &shmid, &perms, &size, - &cpid, &lpid, - &nattch, - &uid, &gid, &cuid, &cgid, - &atime, &dtime, &ctime); - - if (items_read == 14) - { - char user[UT_NAMESIZE], group[UT_NAMESIZE]; - char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE]; - char ccmd[32], lcmd[32]; - char atime_str[32], dtime_str[32], ctime_str[32]; - - user_from_uid (user, sizeof (user), uid); - group_from_gid (group, sizeof (group), gid); - user_from_uid (cuser, sizeof (cuser), cuid); - group_from_gid (cgroup, sizeof (cgroup), cgid); - - command_from_pid (ccmd, sizeof (ccmd), cpid); - command_from_pid (lcmd, sizeof (lcmd), lpid); - - time_from_time_t (atime_str, sizeof (atime_str), atime); - time_from_time_t (dtime_str, sizeof (dtime_str), dtime); - time_from_time_t (ctime_str, sizeof (ctime_str), ctime); - - buffer_xml_printf ( - &buffer, - "" - "%d" - "%d" - "%o" - "%d" - "%s" - "%s" - "%d" - "%s" - "%s" - "%s" - "%s" - "%s" - "%s" - "%s" - "", - key, - shmid, - perms, - size, - ccmd, - lcmd, - nattch, - user, - group, - cuser, - cgroup, - atime_str, - dtime_str, - ctime_str); - } + char user[UT_NAMESIZE], group[UT_NAMESIZE]; + char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE]; + char ccmd[32], lcmd[32]; + char atime_str[32], dtime_str[32], ctime_str[32]; + + user_from_uid (user, sizeof (user), uid); + group_from_gid (group, sizeof (group), gid); + user_from_uid (cuser, sizeof (cuser), cuid); + group_from_gid (cgroup, sizeof (cgroup), cgid); + + command_from_pid (ccmd, sizeof (ccmd), cpid); + command_from_pid (lcmd, sizeof (lcmd), lpid); + + time_from_time_t (atime_str, sizeof (atime_str), atime); + time_from_time_t (dtime_str, sizeof (dtime_str), dtime); + time_from_time_t (ctime_str, sizeof (ctime_str), ctime); + + buffer_xml_printf + (buffer, + "" + "%d" + "%d" + "%o" + "%d" + "%s" + "%s" + "%d" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "", + key, + shmid, + perms, + size, + ccmd, + lcmd, + nattch, + user, + group, + cuser, + cgroup, + atime_str, + dtime_str, + ctime_str); } } - while (!feof (fp.get ())); } - - buffer_grow_str0 (&buffer, "\n"); - saved_buf = buffer_finish (&buffer); - len_avail = strlen (saved_buf); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - buffer_free (&buffer); - saved_buf = NULL; - len_avail = 0; - return 0; + while (!feof (fp.get ())); } - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, saved_buf + offset, len); - - return len; + buffer_grow_str0 (buffer, "\n"); } /* Collect data about semaphores recorded in /proc and write it - into READBUF. */ + into BUFFER. */ -static LONGEST -linux_xfer_osdata_sem (gdb_byte *readbuf, - ULONGEST offset, ULONGEST len) +static void +linux_xfer_osdata_sem (struct buffer *buffer) { - static const char *saved_buf; - static LONGEST len_avail = -1; - static struct buffer buffer; + buffer_grow_str (buffer, "\n"); - if (offset == 0) + gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r"); + if (fp) { - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - saved_buf = NULL; - buffer_init (&buffer); - buffer_grow_str (&buffer, "\n"); - - gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r"); - if (fp) - { - char buf[8192]; + char buf[8192]; - do + do + { + if (fgets (buf, sizeof (buf), fp.get ())) { - if (fgets (buf, sizeof (buf), fp.get ())) + key_t key; + uid_t uid, cuid; + gid_t gid, cgid; + unsigned int perms, nsems; + int semid; + TIME_T otime, ctime; + int items_read; + + items_read = sscanf (buf, + "%d %d %o %u %d %d %d %d %lld %lld", + &key, &semid, &perms, &nsems, + &uid, &gid, &cuid, &cgid, + &otime, &ctime); + + if (items_read == 10) { - key_t key; - uid_t uid, cuid; - gid_t gid, cgid; - unsigned int perms, nsems; - int semid; - TIME_T otime, ctime; - int items_read; - - items_read = sscanf (buf, - "%d %d %o %u %d %d %d %d %lld %lld", - &key, &semid, &perms, &nsems, - &uid, &gid, &cuid, &cgid, - &otime, &ctime); - - if (items_read == 10) - { - char user[UT_NAMESIZE], group[UT_NAMESIZE]; - char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE]; - char otime_str[32], ctime_str[32]; - - user_from_uid (user, sizeof (user), uid); - group_from_gid (group, sizeof (group), gid); - user_from_uid (cuser, sizeof (cuser), cuid); - group_from_gid (cgroup, sizeof (cgroup), cgid); - - time_from_time_t (otime_str, sizeof (otime_str), otime); - time_from_time_t (ctime_str, sizeof (ctime_str), ctime); - - buffer_xml_printf ( - &buffer, - "" - "%d" - "%d" - "%o" - "%u" - "%s" - "%s" - "%s" - "%s" - "%s" - "%s" - "", - key, - semid, - perms, - nsems, - user, - group, - cuser, - cgroup, - otime_str, - ctime_str); - } + char user[UT_NAMESIZE], group[UT_NAMESIZE]; + char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE]; + char otime_str[32], ctime_str[32]; + + user_from_uid (user, sizeof (user), uid); + group_from_gid (group, sizeof (group), gid); + user_from_uid (cuser, sizeof (cuser), cuid); + group_from_gid (cgroup, sizeof (cgroup), cgid); + + time_from_time_t (otime_str, sizeof (otime_str), otime); + time_from_time_t (ctime_str, sizeof (ctime_str), ctime); + + buffer_xml_printf + (buffer, + "" + "%d" + "%d" + "%o" + "%u" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "", + key, + semid, + perms, + nsems, + user, + group, + cuser, + cgroup, + otime_str, + ctime_str); } } - while (!feof (fp.get ())); } - - buffer_grow_str0 (&buffer, "\n"); - saved_buf = buffer_finish (&buffer); - len_avail = strlen (saved_buf); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - buffer_free (&buffer); - saved_buf = NULL; - len_avail = 0; - return 0; + while (!feof (fp.get ())); } - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, saved_buf + offset, len); - - return len; + buffer_grow_str0 (buffer, "\n"); } /* Collect data about message queues recorded in /proc and write it - into READBUF. */ + into BUFFER. */ -static LONGEST -linux_xfer_osdata_msg (gdb_byte *readbuf, - ULONGEST offset, ULONGEST len) +static void +linux_xfer_osdata_msg (struct buffer *buffer) { - static const char *saved_buf; - static LONGEST len_avail = -1; - static struct buffer buffer; + buffer_grow_str (buffer, "\n"); - if (offset == 0) + gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r"); + if (fp) { - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - saved_buf = NULL; - buffer_init (&buffer); - buffer_grow_str (&buffer, "\n"); - - gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r"); - if (fp) - { - char buf[8192]; + char buf[8192]; - do + do + { + if (fgets (buf, sizeof (buf), fp.get ())) { - if (fgets (buf, sizeof (buf), fp.get ())) + key_t key; + PID_T lspid, lrpid; + uid_t uid, cuid; + gid_t gid, cgid; + unsigned int perms, cbytes, qnum; + int msqid; + TIME_T stime, rtime, ctime; + int items_read; + + items_read = sscanf (buf, + "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld", + &key, &msqid, &perms, &cbytes, &qnum, + &lspid, &lrpid, &uid, &gid, &cuid, &cgid, + &stime, &rtime, &ctime); + + if (items_read == 14) { - key_t key; - PID_T lspid, lrpid; - uid_t uid, cuid; - gid_t gid, cgid; - unsigned int perms, cbytes, qnum; - int msqid; - TIME_T stime, rtime, ctime; - int items_read; - - items_read = sscanf (buf, - "%d %d %o %u %u %lld %lld %d %d %d %d %lld %lld %lld", - &key, &msqid, &perms, &cbytes, &qnum, - &lspid, &lrpid, &uid, &gid, &cuid, &cgid, - &stime, &rtime, &ctime); - - if (items_read == 14) - { - char user[UT_NAMESIZE], group[UT_NAMESIZE]; - char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE]; - char lscmd[32], lrcmd[32]; - char stime_str[32], rtime_str[32], ctime_str[32]; - - user_from_uid (user, sizeof (user), uid); - group_from_gid (group, sizeof (group), gid); - user_from_uid (cuser, sizeof (cuser), cuid); - group_from_gid (cgroup, sizeof (cgroup), cgid); - - command_from_pid (lscmd, sizeof (lscmd), lspid); - command_from_pid (lrcmd, sizeof (lrcmd), lrpid); - - time_from_time_t (stime_str, sizeof (stime_str), stime); - time_from_time_t (rtime_str, sizeof (rtime_str), rtime); - time_from_time_t (ctime_str, sizeof (ctime_str), ctime); - - buffer_xml_printf ( - &buffer, - "" - "%d" - "%d" - "%o" - "%u" - "%u" - "%s" - "%s" - "%s" - "%s" - "%s" - "%s" - "%s" - "%s" - "%s" - "", - key, - msqid, - perms, - cbytes, - qnum, - lscmd, - lrcmd, - user, - group, - cuser, - cgroup, - stime_str, - rtime_str, - ctime_str); - } + char user[UT_NAMESIZE], group[UT_NAMESIZE]; + char cuser[UT_NAMESIZE], cgroup[UT_NAMESIZE]; + char lscmd[32], lrcmd[32]; + char stime_str[32], rtime_str[32], ctime_str[32]; + + user_from_uid (user, sizeof (user), uid); + group_from_gid (group, sizeof (group), gid); + user_from_uid (cuser, sizeof (cuser), cuid); + group_from_gid (cgroup, sizeof (cgroup), cgid); + + command_from_pid (lscmd, sizeof (lscmd), lspid); + command_from_pid (lrcmd, sizeof (lrcmd), lrpid); + + time_from_time_t (stime_str, sizeof (stime_str), stime); + time_from_time_t (rtime_str, sizeof (rtime_str), rtime); + time_from_time_t (ctime_str, sizeof (ctime_str), ctime); + + buffer_xml_printf + (buffer, + "" + "%d" + "%d" + "%o" + "%u" + "%u" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "", + key, + msqid, + perms, + cbytes, + qnum, + lscmd, + lrcmd, + user, + group, + cuser, + cgroup, + stime_str, + rtime_str, + ctime_str); } } - while (!feof (fp.get ())); } - - buffer_grow_str0 (&buffer, "\n"); - saved_buf = buffer_finish (&buffer); - len_avail = strlen (saved_buf); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - buffer_free (&buffer); - saved_buf = NULL; - len_avail = 0; - return 0; + while (!feof (fp.get ())); } - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, saved_buf + offset, len); - - return len; + buffer_grow_str0 (buffer, "\n"); } /* Collect data about loaded kernel modules and write it into - READBUF. */ + BUFFER. */ -static LONGEST -linux_xfer_osdata_modules (gdb_byte *readbuf, - ULONGEST offset, ULONGEST len) +static void +linux_xfer_osdata_modules (struct buffer *buffer) { - static const char *saved_buf; - static LONGEST len_avail = -1; - static struct buffer buffer; + buffer_grow_str (buffer, "\n"); - if (offset == 0) + gdb_file_up fp = gdb_fopen_cloexec ("/proc/modules", "r"); + if (fp) { - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - saved_buf = NULL; - buffer_init (&buffer); - buffer_grow_str (&buffer, "\n"); - - gdb_file_up fp = gdb_fopen_cloexec ("/proc/modules", "r"); - if (fp) - { - char buf[8192]; + char buf[8192]; - do + do + { + if (fgets (buf, sizeof (buf), fp.get ())) { - if (fgets (buf, sizeof (buf), fp.get ())) - { - char *name, *dependencies, *status, *tmp; - unsigned int size; - unsigned long long address; - int uses; + char *name, *dependencies, *status, *tmp; + unsigned int size; + unsigned long long address; + int uses; - name = strtok (buf, " "); - if (name == NULL) - continue; + name = strtok (buf, " "); + if (name == NULL) + continue; - tmp = strtok (NULL, " "); - if (tmp == NULL) - continue; - if (sscanf (tmp, "%u", &size) != 1) - continue; + tmp = strtok (NULL, " "); + if (tmp == NULL) + continue; + if (sscanf (tmp, "%u", &size) != 1) + continue; - tmp = strtok (NULL, " "); - if (tmp == NULL) - continue; - if (sscanf (tmp, "%d", &uses) != 1) - continue; + tmp = strtok (NULL, " "); + if (tmp == NULL) + continue; + if (sscanf (tmp, "%d", &uses) != 1) + continue; - dependencies = strtok (NULL, " "); - if (dependencies == NULL) - continue; + dependencies = strtok (NULL, " "); + if (dependencies == NULL) + continue; - status = strtok (NULL, " "); - if (status == NULL) - continue; + status = strtok (NULL, " "); + if (status == NULL) + continue; - tmp = strtok (NULL, "\n"); - if (tmp == NULL) - continue; - if (sscanf (tmp, "%llx", &address) != 1) - continue; + tmp = strtok (NULL, "\n"); + if (tmp == NULL) + continue; + if (sscanf (tmp, "%llx", &address) != 1) + continue; - buffer_xml_printf ( - &buffer, - "" - "%s" - "%u" - "%d" - "%s" - "%s" - "%llx" - "", - name, - size, - uses, - dependencies, - status, - address); - } + buffer_xml_printf (buffer, + "" + "%s" + "%u" + "%d" + "%s" + "%s" + "%llx" + "", + name, + size, + uses, + dependencies, + status, + address); } - while (!feof (fp.get ())); } - - buffer_grow_str0 (&buffer, "\n"); - saved_buf = buffer_finish (&buffer); - len_avail = strlen (saved_buf); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - buffer_free (&buffer); - saved_buf = NULL; - len_avail = 0; - return 0; + while (!feof (fp.get ())); } - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, saved_buf + offset, len); - - return len; + buffer_grow_str0 (buffer, "\n"); } +static void +linux_xfer_osdata_info_os_types (struct buffer *buffer); + struct osdata_type { const char *type; const char *title; const char *description; - LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, ULONGEST len); + void (*take_snapshot) (struct buffer *buffer); + LONGEST len_avail; + struct buffer buffer; } osdata_table[] = { + { "types", "Types", "Listing of info os types you can list", + linux_xfer_osdata_info_os_types, -1 }, { "cpus", "CPUs", "Listing of all cpus/cores on the system", - linux_xfer_osdata_cpus }, + linux_xfer_osdata_cpus, -1 }, { "files", "File descriptors", "Listing of all file descriptors", - linux_xfer_osdata_fds }, + linux_xfer_osdata_fds, -1 }, { "modules", "Kernel modules", "Listing of all loaded kernel modules", - linux_xfer_osdata_modules }, + linux_xfer_osdata_modules, -1 }, { "msg", "Message queues", "Listing of all message queues", - linux_xfer_osdata_msg }, + linux_xfer_osdata_msg, -1 }, { "processes", "Processes", "Listing of all processes", - linux_xfer_osdata_processes }, + linux_xfer_osdata_processes, -1 }, { "procgroups", "Process groups", "Listing of all process groups", - linux_xfer_osdata_processgroups }, + linux_xfer_osdata_processgroups, -1 }, { "semaphores", "Semaphores", "Listing of all semaphores", - linux_xfer_osdata_sem }, + linux_xfer_osdata_sem, -1 }, { "shm", "Shared-memory regions", "Listing of all shared-memory regions", - linux_xfer_osdata_shm }, + linux_xfer_osdata_shm, -1 }, { "sockets", "Sockets", "Listing of all internet-domain sockets", - linux_xfer_osdata_isockets }, + linux_xfer_osdata_isockets, -1 }, { "threads", "Threads", "Listing of all threads", - linux_xfer_osdata_threads }, + linux_xfer_osdata_threads, -1 }, { NULL, NULL, NULL } }; -LONGEST -linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf, - ULONGEST offset, ULONGEST len) +/* Collect data about all types info os can show in BUFFER. */ + +static void +linux_xfer_osdata_info_os_types (struct buffer *buffer) { - if (!annex || *annex == '\0') - { - static const char *buf; - static LONGEST len_avail = -1; - static struct buffer buffer; + buffer_grow_str (buffer, "\n"); + + /* Start the below loop at 1, as we do not want to list ourselves. */ + for (int i = 1; osdata_table[i].type; ++i) + buffer_xml_printf (buffer, + "" + "%s" + "%s" + "%s" + "", + osdata_table[i].type, + osdata_table[i].description, + osdata_table[i].title); + + buffer_grow_str0 (buffer, "\n"); +} - if (offset == 0) - { - int i; - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - buf = NULL; - buffer_init (&buffer); - buffer_grow_str (&buffer, "\n"); - - for (i = 0; osdata_table[i].type; ++i) - buffer_xml_printf ( - &buffer, - "" - "%s" - "%s" - "%s" - "", - osdata_table[i].type, - osdata_table[i].description, - osdata_table[i].title); - - buffer_grow_str0 (&buffer, "\n"); - buf = buffer_finish (&buffer); - len_avail = strlen (buf); - } +/* Copies up to LEN bytes in READBUF from offset OFFSET in OSD->BUFFER. + If OFFSET is zero, first calls OSD->TAKE_SNAPSHOT. */ - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - buffer_free (&buffer); - buf = NULL; - len_avail = 0; - return 0; - } +static LONGEST +common_getter (struct osdata_type *osd, + gdb_byte *readbuf, ULONGEST offset, ULONGEST len) +{ + gdb_assert (readbuf); + + if (offset == 0) + { + if (osd->len_avail != -1 && osd->len_avail != 0) + buffer_free (&osd->buffer); + osd->len_avail = 0; + buffer_init (&osd->buffer); + (osd->take_snapshot) (&osd->buffer); + osd->len_avail = strlen (osd->buffer.buffer); + } + if (offset >= osd->len_avail) + { + /* Done. Get rid of the buffer. */ + buffer_free (&osd->buffer); + osd->len_avail = 0; + return 0; + } + if (len > osd->len_avail - offset) + len = osd->len_avail - offset; + memcpy (readbuf, osd->buffer.buffer + offset, len); - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); + return len; + +} - return len; +LONGEST +linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf, + ULONGEST offset, ULONGEST len) +{ + if (!annex || *annex == '\0') + { + return common_getter (&osdata_table[0], + readbuf, offset, len); } else { @@ -1668,11 +1382,8 @@ linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf, for (i = 0; osdata_table[i].type; ++i) { if (strcmp (annex, osdata_table[i].type) == 0) - { - gdb_assert (readbuf); - - return (osdata_table[i].getter) (readbuf, offset, len); - } + return common_getter (&osdata_table[i], + readbuf, offset, len); } return 0; -- 2.7.4