This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH v5 5/8] Move linux_find_memory_regions_full & co.
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: gdb-patches at sourceware dot org
- Cc: Aleksandar Ristovski <ARistovski at qnx dot com>
- Date: Wed, 19 Mar 2014 23:31:07 +0100
- Subject: [PATCH v5 5/8] Move linux_find_memory_regions_full & co.
- Authentication-results: sourceware.org; auth=none
- References: <20140319223004 dot 14668 dot 20989 dot stgit at host1 dot jankratochvil dot net>
Hi,
this should be just a move with no changes.
Jan
gdb/
2014-02-26 Aleksandar Ristovski <aristovski@qnx.com
Move linux_find_memory_regions_full & co.
* common/target-utils.c (string.h, gdb_assert.h): Include.
(read_alloc, read_stralloc): Move definitions from target.c.
* common/target-utils.h (read_alloc_pread_ftype): New typedef.
(read_alloc): New declaration.
(read_stralloc_func_ftype): New typedef.
(read_stralloc): New declaration.
* common/linux-maps.c (fcntl.h, unistd.h, target.h, gdb_assert.h)
(ctype.h, string.h, target-utils.h): Include.
(read_mapping): Move from linux-tdep.c.
[GDBSERVER] (linux_find_memory_read_stralloc_1_pread): New function.
[GDBSERVER] (linux_find_memory_read_stralloc_1): New function.
(linux_find_memory_read_stralloc): New function.
(linux_find_memory_regions_full): Move from linux-tdep.c.
* common/linux-maps.h (read_mapping): New declaration.
(linux_find_memory_region_ftype): Moved typedef from linux-tdep.c.
(linux_find_memory_regions_full): New declaration.
* linux-tdep.c (linux-maps.h): Include.
(read_mapping): Moved to common/linux-maps.c.
(linux_find_memory_region_ftype): Moved typedef to common/linux-maps.h.
(linux_find_memory_regions_full): Moved definition to
common/linux-maps.c.
* target.c (target-utils.h): Include.
(read_alloc_pread_ftype): Moved typedef to common/target-utils.h.
(read_alloc, read_stralloc): Moved definitions to
common/target-utils.c.
---
gdb/common/linux-maps.c | 197 +++++++++++++++++++++++++++++++++++++++++++++
gdb/common/linux-maps.h | 25 ++++++
gdb/common/target-utils.c | 89 ++++++++++++++++++++
gdb/common/target-utils.h | 11 +++
gdb/linux-tdep.c | 159 ------------------------------------
gdb/target.c | 98 +---------------------
6 files changed, 326 insertions(+), 253 deletions(-)
diff --git a/gdb/common/linux-maps.c b/gdb/common/linux-maps.c
index bb3eac9..4d0b973 100644
--- a/gdb/common/linux-maps.c
+++ b/gdb/common/linux-maps.c
@@ -18,8 +18,205 @@
#ifdef GDBSERVER
#include "server.h"
+#include <fcntl.h>
+#include <unistd.h>
#else
#include "defs.h"
+#include "target.h"
#endif
#include "linux-maps.h"
+#include "gdb_assert.h"
+#include <ctype.h>
+#include <string.h>
+#include "target-utils.h"
+
+/* Service function for corefiles and info proc. */
+
+void
+read_mapping (const char *line,
+ ULONGEST *addr, ULONGEST *endaddr,
+ const char **permissions, size_t *permissions_len,
+ ULONGEST *offset,
+ const char **device, size_t *device_len,
+ ULONGEST *inode,
+ const char **filename)
+{
+ const char *p = line;
+
+ *addr = strtoulst (p, &p, 16);
+ if (*p == '-')
+ p++;
+ *endaddr = strtoulst (p, &p, 16);
+
+ p = skip_spaces_const (p);
+ *permissions = p;
+ while (*p && !isspace (*p))
+ p++;
+ *permissions_len = p - *permissions;
+
+ *offset = strtoulst (p, &p, 16);
+
+ p = skip_spaces_const (p);
+ *device = p;
+ while (*p && !isspace (*p))
+ p++;
+ *device_len = p - *device;
+
+ *inode = strtoulst (p, &p, 10);
+
+ p = skip_spaces_const (p);
+ *filename = p;
+}
+
+#ifdef GDBSERVER
+
+static int
+linux_find_memory_read_stralloc_1_pread (int handle, gdb_byte *read_buf,
+ int len, ULONGEST offset,
+ int *target_errno)
+{
+ int retval = pread (handle, read_buf, len, offset);
+
+ *target_errno = errno;
+ return retval;
+}
+
+static LONGEST
+linux_find_memory_read_stralloc_1 (const char *filename, gdb_byte **buf_p,
+ int padding)
+{
+ int fd;
+ LONGEST retval;
+
+ fd = open (filename, O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ retval = read_alloc (buf_p, fd, linux_find_memory_read_stralloc_1_pread,
+ padding, NULL);
+
+ close (fd);
+
+ return retval;
+}
+
+#endif /* GDBSERVER */
+
+static char *
+linux_find_memory_read_stralloc (const char *filename)
+{
+#ifndef GDBSERVER
+ return target_fileio_read_stralloc (filename);
+#else /* GDBSERVER */
+ return read_stralloc (filename, linux_find_memory_read_stralloc_1);
+#endif /* GDBSERVER */
+}
+
+/* List memory regions in the inferior PID for a corefile. Call FUNC
+ with FUNC_DATA for each such region. Return immediately with the
+ value returned by FUNC if it is non-zero. *MEMORY_TO_FREE_PTR should
+ be registered to be freed automatically if called FUNC throws an
+ exception. MEMORY_TO_FREE_PTR can be also passed as NULL if it is
+ not used. Return -1 if error occurs, 0 if all memory regions have
+ been processed or return the value from FUNC if FUNC returns
+ non-zero. */
+
+int
+linux_find_memory_regions_full (pid_t pid, linux_find_memory_region_ftype *func,
+ void *func_data, void **memory_to_free_ptr)
+{
+ char mapsfilename[100];
+ char *data;
+
+ xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/smaps", (int) pid);
+ data = linux_find_memory_read_stralloc (mapsfilename);
+ if (data == NULL)
+ {
+ /* Older Linux kernels did not support /proc/PID/smaps. */
+ xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/maps", (int) pid);
+ data = linux_find_memory_read_stralloc (mapsfilename);
+ }
+ if (data)
+ {
+ char *line;
+ int retval = 0;
+
+ if (memory_to_free_ptr != NULL)
+ {
+ gdb_assert (*memory_to_free_ptr == NULL);
+ *memory_to_free_ptr = data;
+ }
+
+ line = strtok (data, "\n");
+ while (line)
+ {
+ ULONGEST addr, endaddr, offset, inode;
+ const char *permissions, *device, *filename;
+ size_t permissions_len, device_len;
+ int read, write, exec;
+ int modified = 0, has_anonymous = 0;
+
+ read_mapping (line, &addr, &endaddr, &permissions, &permissions_len,
+ &offset, &device, &device_len, &inode, &filename);
+
+ /* Decode permissions. */
+ read = (memchr (permissions, 'r', permissions_len) != 0);
+ write = (memchr (permissions, 'w', permissions_len) != 0);
+ exec = (memchr (permissions, 'x', permissions_len) != 0);
+
+ /* Try to detect if region was modified by parsing smaps counters. */
+ for (line = strtok (NULL, "\n");
+ line && line[0] >= 'A' && line[0] <= 'Z';
+ line = strtok (NULL, "\n"))
+ {
+ char keyword[64 + 1];
+
+ if (sscanf (line, "%64s", keyword) != 1)
+ {
+ warning (_("Error parsing {s,}maps file '%s'"), mapsfilename);
+ break;
+ }
+ if (strcmp (keyword, "Anonymous:") == 0)
+ has_anonymous = 1;
+ if (strcmp (keyword, "Shared_Dirty:") == 0
+ || strcmp (keyword, "Private_Dirty:") == 0
+ || strcmp (keyword, "Swap:") == 0
+ || strcmp (keyword, "Anonymous:") == 0)
+ {
+ unsigned long number;
+
+ if (sscanf (line, "%*s%lu", &number) != 1)
+ {
+ warning (_("Error parsing {s,}maps file '%s' number"),
+ mapsfilename);
+ break;
+ }
+ if (number != 0)
+ modified = 1;
+ }
+ }
+
+ /* Older Linux kernels did not support the "Anonymous:" counter.
+ If it is missing, we can't be sure - dump all the pages. */
+ if (!has_anonymous)
+ modified = 1;
+
+ /* Invoke the callback function to create the corefile segment. */
+ retval = func (addr, endaddr - addr, offset, inode,
+ read, write, exec, modified, filename, func_data);
+ if (retval != 0)
+ break;
+ }
+
+ if (memory_to_free_ptr != NULL)
+ {
+ gdb_assert (data == *memory_to_free_ptr);
+ *memory_to_free_ptr = NULL;
+ }
+ xfree (data);
+ return retval;
+ }
+
+ return -1;
+}
diff --git a/gdb/common/linux-maps.h b/gdb/common/linux-maps.h
index ebf6f37..03b14d3 100644
--- a/gdb/common/linux-maps.h
+++ b/gdb/common/linux-maps.h
@@ -19,4 +19,29 @@
#ifndef COMMON_LINUX_MAPS_H
#define COMMON_LINUX_MAPS_H
+extern void
+ read_mapping (const char *line,
+ ULONGEST *addr, ULONGEST *endaddr,
+ const char **permissions, size_t *permissions_len,
+ ULONGEST *offset,
+ const char **device, size_t *device_len,
+ ULONGEST *inode,
+ const char **filename);
+
+/* Callback function for linux_find_memory_regions_full. If it returns
+ non-zero linux_find_memory_regions_full returns immediately with that
+ value. */
+
+typedef int linux_find_memory_region_ftype (ULONGEST vaddr, ULONGEST size,
+ ULONGEST offset, ULONGEST inode,
+ int read, int write,
+ int exec, int modified,
+ const char *filename,
+ void *data);
+
+extern int
+ linux_find_memory_regions_full (pid_t pid,
+ linux_find_memory_region_ftype *func,
+ void *func_data, void **memory_to_free_ptr);
+
#endif /* COMMON_LINUX_MAPS_H */
diff --git a/gdb/common/target-utils.c b/gdb/common/target-utils.c
index 308996d..84d1bca 100644
--- a/gdb/common/target-utils.c
+++ b/gdb/common/target-utils.c
@@ -23,4 +23,93 @@
#include "defs.h"
#endif
+#include <string.h>
#include "target-utils.h"
+#include "gdb_assert.h"
+
+LONGEST
+read_alloc (gdb_byte **buf_p, int handle, read_alloc_pread_ftype *pread_func,
+ int padding, void **memory_to_free_ptr)
+{
+ size_t buf_alloc, buf_pos;
+ gdb_byte *buf;
+ LONGEST n;
+ int target_errno;
+
+ /* Start by reading up to 4K at a time. The target will throttle
+ this number down if necessary. */
+ buf_alloc = 4096;
+ buf = xmalloc (buf_alloc);
+ if (memory_to_free_ptr != NULL)
+ {
+ gdb_assert (*memory_to_free_ptr == NULL);
+ *memory_to_free_ptr = buf;
+ }
+ buf_pos = 0;
+ while (1)
+ {
+ n = pread_func (handle, &buf[buf_pos], buf_alloc - buf_pos - padding,
+ buf_pos, &target_errno);
+ if (n <= 0)
+ {
+ if (n < 0 || (n == 0 && buf_pos == 0))
+ xfree (buf);
+ else
+ *buf_p = buf;
+ if (memory_to_free_ptr != NULL)
+ *memory_to_free_ptr = NULL;
+ if (n < 0)
+ {
+ /* An error occurred. */
+ return -1;
+ }
+ else
+ {
+ /* Read all there was. */
+ return buf_pos;
+ }
+ }
+
+ buf_pos += n;
+
+ /* If the buffer is filling up, expand it. */
+ if (buf_alloc < buf_pos * 2)
+ {
+ buf_alloc *= 2;
+ buf = xrealloc (buf, buf_alloc);
+ if (memory_to_free_ptr != NULL)
+ *memory_to_free_ptr = buf;
+ }
+ }
+}
+
+char *
+read_stralloc (const char *filename, read_stralloc_func_ftype *func)
+{
+ gdb_byte *buffer;
+ char *bufstr;
+ LONGEST i, transferred;
+
+ transferred = func (filename, &buffer, 1);
+ bufstr = (char *) buffer;
+
+ if (transferred < 0)
+ return NULL;
+
+ if (transferred == 0)
+ return xstrdup ("");
+
+ bufstr[transferred] = 0;
+
+ /* Check for embedded NUL bytes; but allow trailing NULs. */
+ for (i = strlen (bufstr); i < transferred; i++)
+ if (bufstr[i] != 0)
+ {
+ warning (_("target file %s "
+ "contained unexpected null characters"),
+ filename);
+ break;
+ }
+
+ return bufstr;
+}
diff --git a/gdb/common/target-utils.h b/gdb/common/target-utils.h
index db33ec8..f8ca972 100644
--- a/gdb/common/target-utils.h
+++ b/gdb/common/target-utils.h
@@ -20,4 +20,15 @@
#ifndef COMMON_TARGET_UTILS_H
#define COMMON_TARGET_UTILS_H
+typedef int (read_alloc_pread_ftype) (int handle, gdb_byte *read_buf, int len,
+ ULONGEST offset, int *target_errno);
+extern LONGEST read_alloc (gdb_byte **buf_p, int handle,
+ read_alloc_pread_ftype *pread_func, int padding,
+ void **memory_to_free_ptr);
+
+typedef LONGEST (read_stralloc_func_ftype) (const char *filename,
+ gdb_byte **buf_p, int padding);
+extern char *read_stralloc (const char *filename,
+ read_stralloc_func_ftype *func);
+
#endif /* COMMON_TARGET_UTILS_H */
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index b9aba2d..d0c8761 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -32,6 +32,7 @@
#include "cli/cli-utils.h"
#include "arch-utils.h"
#include "gdb_obstack.h"
+#include "linux-maps.h"
#include <ctype.h>
@@ -274,44 +275,6 @@ linux_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid)
return normal_pid_to_str (ptid);
}
-/* Service function for corefiles and info proc. */
-
-static void
-read_mapping (const char *line,
- ULONGEST *addr, ULONGEST *endaddr,
- const char **permissions, size_t *permissions_len,
- ULONGEST *offset,
- const char **device, size_t *device_len,
- ULONGEST *inode,
- const char **filename)
-{
- const char *p = line;
-
- *addr = strtoulst (p, &p, 16);
- if (*p == '-')
- p++;
- *endaddr = strtoulst (p, &p, 16);
-
- p = skip_spaces_const (p);
- *permissions = p;
- while (*p && !isspace (*p))
- p++;
- *permissions_len = p - *permissions;
-
- *offset = strtoulst (p, &p, 16);
-
- p = skip_spaces_const (p);
- *device = p;
- while (*p && !isspace (*p))
- p++;
- *device_len = p - *device;
-
- *inode = strtoulst (p, &p, 10);
-
- p = skip_spaces_const (p);
- *filename = p;
-}
-
/* Implement the "info proc" command. */
static void
@@ -730,126 +693,6 @@ linux_core_info_proc (struct gdbarch *gdbarch, char *args,
error (_("unable to handle request"));
}
-/* Callback function for linux_find_memory_regions_full. If it returns
- non-zero linux_find_memory_regions_full returns immediately with that
- value. */
-
-typedef int linux_find_memory_region_ftype (ULONGEST vaddr, ULONGEST size,
- ULONGEST offset, ULONGEST inode,
- int read, int write,
- int exec, int modified,
- const char *filename,
- void *data);
-
-/* List memory regions in the inferior PID for a corefile. Call FUNC
- with FUNC_DATA for each such region. Return immediately with the
- value returned by FUNC if it is non-zero. *MEMORY_TO_FREE_PTR should
- be registered to be freed automatically if called FUNC throws an
- exception. MEMORY_TO_FREE_PTR can be also passed as NULL if it is
- not used. Return -1 if error occurs, 0 if all memory regions have
- been processed or return the value from FUNC if FUNC returns
- non-zero. */
-
-static int
-linux_find_memory_regions_full (pid_t pid, linux_find_memory_region_ftype *func,
- void *func_data, void **memory_to_free_ptr)
-{
- char mapsfilename[100];
- char *data;
-
- xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/smaps", (int) pid);
- data = target_fileio_read_stralloc (mapsfilename);
- if (data == NULL)
- {
- /* Older Linux kernels did not support /proc/PID/smaps. */
- xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/maps",
- (int) pid);
- data = target_fileio_read_stralloc (mapsfilename);
- }
- if (data)
- {
- char *line;
- int retval = 0;
-
- if (memory_to_free_ptr != NULL)
- {
- gdb_assert (*memory_to_free_ptr == NULL);
- *memory_to_free_ptr = data;
- }
-
- line = strtok (data, "\n");
- while (line)
- {
- ULONGEST addr, endaddr, offset, inode;
- const char *permissions, *device, *filename;
- size_t permissions_len, device_len;
- int read, write, exec;
- int modified = 0, has_anonymous = 0;
-
- read_mapping (line, &addr, &endaddr, &permissions, &permissions_len,
- &offset, &device, &device_len, &inode, &filename);
-
- /* Decode permissions. */
- read = (memchr (permissions, 'r', permissions_len) != 0);
- write = (memchr (permissions, 'w', permissions_len) != 0);
- exec = (memchr (permissions, 'x', permissions_len) != 0);
-
- /* Try to detect if region was modified by parsing smaps counters. */
- for (line = strtok (NULL, "\n");
- line && line[0] >= 'A' && line[0] <= 'Z';
- line = strtok (NULL, "\n"))
- {
- char keyword[64 + 1];
-
- if (sscanf (line, "%64s", keyword) != 1)
- {
- warning (_("Error parsing {s,}maps file '%s'"), mapsfilename);
- break;
- }
- if (strcmp (keyword, "Anonymous:") == 0)
- has_anonymous = 1;
- if (strcmp (keyword, "Shared_Dirty:") == 0
- || strcmp (keyword, "Private_Dirty:") == 0
- || strcmp (keyword, "Swap:") == 0
- || strcmp (keyword, "Anonymous:") == 0)
- {
- unsigned long number;
-
- if (sscanf (line, "%*s%lu", &number) != 1)
- {
- warning (_("Error parsing {s,}maps file '%s' number"),
- mapsfilename);
- break;
- }
- if (number != 0)
- modified = 1;
- }
- }
-
- /* Older Linux kernels did not support the "Anonymous:" counter.
- If it is missing, we can't be sure - dump all the pages. */
- if (!has_anonymous)
- modified = 1;
-
- /* Invoke the callback function to create the corefile segment. */
- retval = func (addr, endaddr - addr, offset, inode,
- read, write, exec, modified, filename, func_data);
- if (retval != 0)
- break;
- }
-
- if (memory_to_free_ptr != NULL)
- {
- gdb_assert (data == *memory_to_free_ptr);
- *memory_to_free_ptr = NULL;
- }
- xfree (data);
- return retval;
- }
-
- return -1;
-}
-
/* A structure for passing information through
linux_find_memory_regions_full. */
diff --git a/gdb/target.c b/gdb/target.c
index 06b6331..0e5ea33 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -45,6 +45,7 @@
#include "gdb/fileio.h"
#include "agent.h"
#include "auxv.h"
+#include "target-utils.h"
static void target_info (char *, int);
@@ -2952,9 +2953,6 @@ target_fileio_close_cleanup (void *opaque)
target_fileio_close (fd, &target_errno);
}
-typedef int (read_alloc_pread_ftype) (int handle, gdb_byte *read_buf, int len,
- ULONGEST offset, int *target_errno);
-
static read_alloc_pread_ftype target_fileio_read_alloc_1_pread;
/* Helper for target_fileio_read_alloc_1 to make it interruptible. */
@@ -2968,6 +2966,8 @@ target_fileio_read_alloc_1_pread (int handle, gdb_byte *read_buf, int len,
return target_fileio_pread (handle, read_buf, len, offset, target_errno);
}
+static read_stralloc_func_ftype target_fileio_read_alloc_1;
+
/* Read target file FILENAME. Store the result in *BUF_P and
return the size of the transferred data. PADDING additional bytes are
available in *BUF_P. This is a helper function for
@@ -2975,67 +2975,6 @@ target_fileio_read_alloc_1_pread (int handle, gdb_byte *read_buf, int len,
information. */
static LONGEST
-read_alloc (gdb_byte **buf_p, int handle, read_alloc_pread_ftype *pread_func,
- int padding, void **memory_to_free_ptr)
-{
- size_t buf_alloc, buf_pos;
- gdb_byte *buf;
- LONGEST n;
- int target_errno;
-
- /* Start by reading up to 4K at a time. The target will throttle
- this number down if necessary. */
- buf_alloc = 4096;
- buf = xmalloc (buf_alloc);
- if (memory_to_free_ptr != NULL)
- {
- gdb_assert (*memory_to_free_ptr == NULL);
- *memory_to_free_ptr = buf;
- }
- buf_pos = 0;
- while (1)
- {
- n = pread_func (handle, &buf[buf_pos], buf_alloc - buf_pos - padding,
- buf_pos, &target_errno);
- if (n <= 0)
- {
- if (n < 0 || (n == 0 && buf_pos == 0))
- xfree (buf);
- else
- *buf_p = buf;
- if (memory_to_free_ptr != NULL)
- *memory_to_free_ptr = NULL;
- if (n < 0)
- {
- /* An error occurred. */
- return -1;
- }
- else
- {
- /* Read all there was. */
- return buf_pos;
- }
- }
-
- buf_pos += n;
-
- /* If the buffer is filling up, expand it. */
- if (buf_alloc < buf_pos * 2)
- {
- buf_alloc *= 2;
- buf = xrealloc (buf, buf_alloc);
- if (memory_to_free_ptr != NULL)
- *memory_to_free_ptr = buf;
- }
- }
-}
-
-typedef LONGEST (read_stralloc_func_ftype) (const char *filename,
- gdb_byte **buf_p, int padding);
-
-static read_stralloc_func_ftype target_fileio_read_alloc_1;
-
-static LONGEST
target_fileio_read_alloc_1 (const char *filename,
gdb_byte **buf_p, int padding)
{
@@ -3073,37 +3012,6 @@ target_fileio_read_alloc (const char *filename, gdb_byte **buf_p)
are returned as allocated but empty strings. A warning is issued
if the result contains any embedded NUL bytes. */
-static char *
-read_stralloc (const char *filename, read_stralloc_func_ftype *func)
-{
- gdb_byte *buffer;
- char *bufstr;
- LONGEST i, transferred;
-
- transferred = func (filename, &buffer, 1);
- bufstr = (char *) buffer;
-
- if (transferred < 0)
- return NULL;
-
- if (transferred == 0)
- return xstrdup ("");
-
- bufstr[transferred] = 0;
-
- /* Check for embedded NUL bytes; but allow trailing NULs. */
- for (i = strlen (bufstr); i < transferred; i++)
- if (bufstr[i] != 0)
- {
- warning (_("target file %s "
- "contained unexpected null characters"),
- filename);
- break;
- }
-
- return bufstr;
-}
-
char *
target_fileio_read_stralloc (const char *filename)
{