From patchwork Sat Dec 8 18:07:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philippe Waroquiers X-Patchwork-Id: 30590 Received: (qmail 5103 invoked by alias); 8 Dec 2018 18:08:15 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 5086 invoked by uid 89); 8 Dec 2018 18:08:14 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-12.6 required=5.0 tests=BAYES_00, GIT_PATCH_1, GIT_PATCH_3, RCVD_IN_DNSWL_LOW, SPF_PASS, TIME_LIMIT_EXCEEDED autolearn=unavailable version=3.3.2 spammy=ownership, UD:sa, leader, typical X-HELO: mailsec117.isp.belgacom.be Received: from mailsec117.isp.belgacom.be (HELO mailsec117.isp.belgacom.be) (195.238.20.113) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 08 Dec 2018 18:08:03 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=skynet.be; i=@skynet.be; q=dns/txt; s=securemail; t=1544292483; x=1575828483; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=h1XeLkze8bo6r3FigOQLOJYTDVpGXhMsrw7xqSFs/9w=; b=b2iQhj75cad+WNrytW69uW3cOxwabzQQt7bmlKAKr/5SRAp1azGNa1Dd A3Xw1puI5KrKqgvte1WAoxsu2tBaQg==; Received: from 184.205-67-87.adsl-dyn.isp.belgacom.be (HELO md.home) ([87.67.205.184]) by relay.skynet.be with ESMTP/TLS/DHE-RSA-AES128-GCM-SHA256; 08 Dec 2018 19:07:59 +0100 From: Philippe Waroquiers To: gdb-patches@sourceware.org Cc: Philippe Waroquiers Subject: [RFA] Fix leaks in all the linux osdata annex transfers + code factorization. Date: Sat, 8 Dec 2018 19:07:54 +0100 Message-Id: <20181208180754.2050-1-philippe.waroquiers@skynet.be> MIME-Version: 1.0 X-IsSubscribed: yes 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-08 Philippe Waroquiers * nat/linux-osdata.c : Removed various trailing spaces. (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/nat/linux-osdata.c | 1607 ++++++++++++++++------------------------ 1 file changed, 659 insertions(+), 948 deletions(-) diff --git a/gdb/nat/linux-osdata.c b/gdb/nat/linux-osdata.c index 98bded06ba..6f6724ca8e 100644 --- a/gdb/nat/linux-osdata.c +++ b/gdb/nat/linux-osdata.c @@ -1,5 +1,5 @@ /* Linux-specific functions to retrieve OS data. - + Copyright (C) 2009-2018 Free Software Foundation, Inc. This file is part of GDB. @@ -55,7 +55,7 @@ typedef long long TIME_T; #define MAX_PID_T_STRLEN (sizeof ("-9223372036854775808") - 1) /* Returns the CPU core that thread PTID is currently running on. */ - + /* Compute and return the processor core of a given thread. */ int @@ -117,9 +117,9 @@ command_from_pid (char *command, int maxlen, PID_T pid) { std::string stat_path = string_printf ("/proc/%lld/stat", pid); gdb_file_up fp = gdb_fopen_cloexec (stat_path, "r"); - + command[0] = '\0'; - + if (fp) { /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in @@ -128,7 +128,7 @@ command_from_pid (char *command, int maxlen, PID_T pid) char cmd[18]; PID_T stat_pid; int items_read = fscanf (fp.get (), "%lld %17s", &stat_pid, cmd); - + if (items_read == 2 && pid == stat_pid) { cmd[strlen (cmd) - 1] = '\0'; /* Remove trailing parenthesis. */ @@ -162,7 +162,7 @@ commandline_from_pid (PID_T pid) { char buf[1024]; size_t read_bytes = fread (buf, 1, sizeof (buf), f.get ()); - + if (read_bytes) { commandline = (char *) xrealloc (commandline, len + read_bytes + 1); @@ -206,7 +206,7 @@ static void user_from_uid (char *user, int maxlen, uid_t uid) { struct passwd *pwentry = getpwuid (uid); - + if (pwentry) { strncpy (user, pwentry->pw_name, maxlen); @@ -227,7 +227,7 @@ get_process_owner (uid_t *owner, PID_T pid) char procentry[sizeof ("/proc/") + MAX_PID_T_STRLEN]; sprintf (procentry, "/proc/%lld", pid); - + if (stat (procentry, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) { *owner = statbuf.st_uid; @@ -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; + PID_T pid; + uid_t owner; + char user[UT_NAMESIZE]; + char *command_line; + int *cores; + int task_count; + char *cores_str; + int i; - 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; + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > MAX_PID_T_STRLEN) + continue; - 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); - } - - 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); + 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"); } /* 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; + PID_T pid, pgid; - process_list.reserve (512); - - /* 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; - - sscanf (dp->d_name, "%lld", &pid); - pgid = getpgid (pid); - - if (pgid > 0) - process_list.emplace_back (pid, pgid); - } + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > MAX_PID_T_STRLEN) + continue; - closedir (dirp); + sscanf (dp->d_name, "%lld", &pid); + pgid = getpgid (pid); - /* Sort the process list. */ - std::sort (process_list.begin (), process_list.end ()); + if (pgid > 0) + process_list.emplace_back (pid, pgid); + } - 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); - } - } + closedir (dirp); - buffer_grow_str0 (&buffer, "\n"); - buf = buffer_finish (&buffer); - len_avail = strlen (buf); - } + /* Sort the process list. */ + std::sort (process_list.begin (), process_list.end ()); - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - buffer_free (&buffer); - buf = NULL; - len_avail = 0; - return 0; + 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); + } } - 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) + 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)) { - struct stat statbuf; - char procentry[sizeof ("/proc/4294967295")]; + DIR *dirp2; + PID_T pid; + char command[32]; - if (!isdigit (dp->d_name[0]) - || NAMELEN (dp) > sizeof ("4294967295") - 1) - continue; + std::string pathname + = string_printf ("/proc/%s/task", dp->d_name); - 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); - std::string pathname - = string_printf ("/proc/%s/task", dp->d_name); - - 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); - } - - 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"); } -/* 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. */ @@ -946,7 +792,7 @@ print_sockets (unsigned short family, int tcp, struct buffer *buffer) remote_address, &remote_port, &state, &uid); - + if (result == 6) { union socket_addr locaddr, remaddr; @@ -960,7 +806,7 @@ print_sockets (unsigned short family, int tcp, struct buffer *buffer) &locaddr.sin.sin_addr.s_addr); sscanf (remote_address, "%X", &remaddr.sin.sin_addr.s_addr); - + locaddr.sin.sin_port = htons (local_port); remaddr.sin.sin_port = htons (remote_port); @@ -981,7 +827,7 @@ print_sockets (unsigned short family, int tcp, struct buffer *buffer) locaddr.sin6.sin6_port = htons (local_port); remaddr.sin6.sin6_port = htons (remote_port); - + locaddr.sin6.sin6_flowinfo = 0; remaddr.sin6.sin6_flowinfo = 0; locaddr.sin6.sin6_scope_id = 0; @@ -989,9 +835,9 @@ print_sockets (unsigned short family, int tcp, struct buffer *buffer) addr_size = sizeof (struct sockaddr_in6); } - + locaddr.sa.sa_family = remaddr.sa.sa_family = family; - + result = getnameinfo (&locaddr.sa, addr_size, local_address, sizeof (local_address), local_service, sizeof (local_service), @@ -999,7 +845,7 @@ print_sockets (unsigned short family, int tcp, struct buffer *buffer) | (tcp ? 0 : NI_DGRAM)); if (result) continue; - + result = getnameinfo (&remaddr.sa, addr_size, remote_address, sizeof (remote_address), @@ -1009,9 +855,9 @@ print_sockets (unsigned short family, int tcp, struct buffer *buffer) | (tcp ? 0 : NI_DGRAM)); if (result) continue; - + user_from_uid (user, sizeof (user), uid); - + buffer_xml_printf ( buffer, "" @@ -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); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the buffer. */ - buffer_free (&buffer); - buf = NULL; - len_avail = 0; - return 0; - } + buffer_grow_str (buffer, "\n"); - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); + print_sockets (AF_INET, 1, buffer); + print_sockets (AF_INET, 0, buffer); + print_sockets (AF_INET6, 1, buffer); + print_sockets (AF_INET6, 0, buffer); - return len; + buffer_grow_str0 (buffer, "\n"); } /* Converts the time SECONDS into textual form and copies it into a @@ -1095,7 +911,7 @@ time_from_time_t (char *time, int maxlen, TIME_T seconds) else { time_t t = (time_t) seconds; - + strncpy (time, ctime (&t), maxlen); time[maxlen - 1] = '\0'; } @@ -1108,7 +924,7 @@ static void group_from_gid (char *group, int maxlen, gid_t gid) { struct group *grentry = getgrgid (gid); - + if (grentry) { strncpy (group, grentry->gr_name, maxlen); @@ -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]; + + do { - char buf[8192]; - - 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]; + + do { - char buf[8192]; - - 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]; + + do { - char buf[8192]; - - 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 (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); + 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); + + 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;