[PATCH v11 3/7] Prepare linux_find_memory_regions_full & co. for move

Jan Kratochvil
2015-07-23T17:21:43Z

Prepare code for move into gdb/common/.

gdb/ChangeLog
2015-07-15 Aleksandar Ristovski <aristovski@qnx.com
Jan Kratochvil <jan.kratochvil@redhat.com>

Prepare linux_find_memory_regions_full & co. for move.
* linux-tdep.c (linux_find_memory_region_ftype): Comment.
(linux_find_memory_regions_full): Change signature and prepare
for moving to linux-maps.
(linux_find_memory_regions_data): Rename field 'obfd' to 'data'.
(linux_find_memory_regions_thunk): New.
(linux_find_memory_regions_thunk): Use 'data' field instead of 'obfd'.
(linux_find_memory_regions_gdb): New.
(linux_find_memory_regions): Rename argument 'obfd' to 'func_data'.
(linux_make_mappings_corefile_notes): Use
linux_find_memory_regions_gdb.
* target.c (read_alloc_pread_ftype): New typedef.
(target_fileio_read_alloc_1_pread): New function.
(read_alloc): Refactor from target_fileio_read_alloc_1.
(read_stralloc_func_ftype): New typedef.
(target_fileio_read_alloc_1): New implementation. Use read_alloc.
(read_stralloc): Refactored from target_fileio_read_stralloc.
(target_fileio_read_stralloc): New implementation, use read_stralloc.
---
gdb/linux-tdep.c | 121 +++++++++++++++++++++++++++++++++---------------------
gdb/target.c | 96 +++++++++++++++++++++++++++++--------------
2 files changed, 138 insertions(+), 79 deletions(-)

diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index ff3ada7..982599e 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -1098,6 +1098,10 @@ linux_core_info_proc (struct gdbarch *gdbarch, const 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,
@@ -1105,43 +1109,22 @@ typedef int linux_find_memory_region_ftype (ULONGEST vaddr, ULONGEST size,
const char *filename,
void *data);

-/* List memory regions in the inferior for a corefile. */
+/* List memory regions in the inferior PID matched to FILTERFLAGS 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 (struct gdbarch *gdbarch,
+linux_find_memory_regions_full (pid_t pid, enum filterflags filterflags,
linux_find_memory_region_ftype *func,
- void *obfd)
+ void *func_data)
{
char mapsfilename[100];
- char coredumpfilter_name[100];
- char *data, *coredumpfilterdata;
- pid_t pid;
- /* Default dump behavior of coredump_filter (0x33), according to
- Documentation/filesystems/proc.txt from the Linux kernel
- tree. */
- enum filterflags filterflags = (COREFILTER_ANON_PRIVATE
- | COREFILTER_ANON_SHARED
- | COREFILTER_ELF_HEADERS
- | COREFILTER_HUGETLB_PRIVATE);
-
- /* We need to know the real target PID to access /proc. */
- if (current_inferior ()->fake_pid_p)
- return 1;
-
- pid = current_inferior ()->pid;
-
- if (use_coredump_filter)
- {
- xsnprintf (coredumpfilter_name, sizeof (coredumpfilter_name),
- "/proc/%d/coredump_filter", pid);
- coredumpfilterdata = target_fileio_read_stralloc (NULL,
- coredumpfilter_name);
- if (coredumpfilterdata != NULL)
- {
- sscanf (coredumpfilterdata, "%x", &filterflags);
- xfree (coredumpfilterdata);
- }
- }
+ char *data;

xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/smaps", pid);
data = target_fileio_read_stralloc (NULL, mapsfilename);
@@ -1156,6 +1139,7 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,
{
struct cleanup *cleanup = make_cleanup (xfree, data);
char *line, *t;
+ int retval = 0;

line = strtok_r (data, "\n", &t);
while (line != NULL)
@@ -1270,17 +1254,20 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,

/* Invoke the callback function to create the corefile segment. */
if (should_dump_p)
- func (addr, endaddr - addr, offset, inode,
- read, write, exec, 1, /* MODIFIED is true because we
- want to dump the mapping. */
- filename, obfd);
+ retval = func (addr, endaddr - addr, offset, inode,
+ read, write, exec,
+ 1, /* MODIFIED is true because we want to dump the
+ mapping. */
+ filename, func_data);
+ if (retval != 0)
+ break;
}

do_cleanups (cleanup);
- return 0;
+ return retval;
}

- return 1;
+ return -1;
}

/* A structure for passing information through
@@ -1294,7 +1281,7 @@ struct linux_find_memory_regions_data

/* The original datum. */

- void *obfd;
+ void *data;
};

/* A callback for linux_find_memory_regions that converts between the
@@ -1308,7 +1295,48 @@ linux_find_memory_regions_thunk (ULONGEST vaddr, ULONGEST size,
{
struct linux_find_memory_regions_data *data = arg;

- return data->func (vaddr, size, read, write, exec, modified, data->obfd);
+ return data->func (vaddr, size, read, write, exec, modified, data->data);
+}
+
+/* Wrapper of linux_find_memory_regions_full handling FAKE_PID_P in GDB. */
+
+static int
+linux_find_memory_regions_gdb (struct gdbarch *gdbarch,
+ linux_find_memory_region_ftype *func,
+ void *func_data)
+{
+ pid_t pid;
+ /* Default dump behavior of coredump_filter (0x33), according to
+ Documentation/filesystems/proc.txt from the Linux kernel
+ tree. */
+ enum filterflags filterflags = (COREFILTER_ANON_PRIVATE
+ | COREFILTER_ANON_SHARED
+ | COREFILTER_ELF_HEADERS
+ | COREFILTER_HUGETLB_PRIVATE);
+
+ /* We need to know the real target PID so
+ linux_find_memory_regions_full can access /proc. */
+ if (current_inferior ()->fake_pid_p)
+ return -1;
+
+ pid = current_inferior ()->pid;
+
+ if (use_coredump_filter)
+ {
+ char coredumpfilter_name[100], *coredumpfilterdata;
+
+ xsnprintf (coredumpfilter_name, sizeof (coredumpfilter_name),
+ "/proc/%d/coredump_filter", pid);
+ coredumpfilterdata = target_fileio_read_stralloc (NULL,
+ coredumpfilter_name);
+ if (coredumpfilterdata != NULL)
+ {
+ sscanf (coredumpfilterdata, "%x", &filterflags);
+ xfree (coredumpfilterdata);
+ }
+ }
+
+ return linux_find_memory_regions_full (pid, filterflags, func, func_data);
}

/* A variant of linux_find_memory_regions_full that is suitable as the
@@ -1316,16 +1344,15 @@ linux_find_memory_regions_thunk (ULONGEST vaddr, ULONGEST size,

static int
linux_find_memory_regions (struct gdbarch *gdbarch,
- find_memory_region_ftype func, void *obfd)
+ find_memory_region_ftype func, void *func_data)
{
struct linux_find_memory_regions_data data;

data.func = func;
- data.obfd = obfd;
+ data.data = func_data;

- return linux_find_memory_regions_full (gdbarch,
- linux_find_memory_regions_thunk,
- &data);
+ return linux_find_memory_regions_gdb (gdbarch,
+ linux_find_memory_regions_thunk, &data);
}

/* Determine which signal stopped execution. */
@@ -1507,8 +1534,8 @@ linux_make_mappings_corefile_notes (struct gdbarch *gdbarch, bfd *obfd,
pack_long (buf, long_type, 1);
obstack_grow (&data_obstack, buf, TYPE_LENGTH (long_type));

- linux_find_memory_regions_full (gdbarch, linux_make_mappings_callback,
- &mapping_data);
+ linux_find_memory_regions_gdb (gdbarch, linux_make_mappings_callback,
+ &mapping_data);

if (mapping_data.file_count != 0)
{
diff --git a/gdb/target.c b/gdb/target.c
index 4e2d005..2dd3116 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -2973,6 +2973,20 @@ 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);
+
+/* Helper for target_fileio_read_alloc_1 to make it interruptible. */
+
+static int
+target_fileio_read_alloc_1_pread (int handle, gdb_byte *read_buf, int len,
+ ULONGEST offset, int *target_errno)
+{
+ QUIT;
+
+ return target_fileio_pread (handle, read_buf, len, offset, target_errno);
+}
+
/* Read target file FILENAME, in the filesystem as seen by INF. If
INF is NULL, use the filesystem seen by the debugger (GDB or, for
remote targets, the remote stub). Store the result in *BUF_P and
@@ -2982,23 +2996,14 @@ target_fileio_close_cleanup (void *opaque)
more information. */

static LONGEST
-target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
- gdb_byte **buf_p, int padding)
+read_alloc (gdb_byte **buf_p, int handle, read_alloc_pread_ftype *pread_func,
+ int padding)
{
- struct cleanup *close_cleanup;
size_t buf_alloc, buf_pos;
gdb_byte *buf;
LONGEST n;
- int fd;
int target_errno;

- fd = target_fileio_open (inf, filename, FILEIO_O_RDONLY, 0700,
- &target_errno);
- if (fd == -1)
- return -1;
-
- close_cleanup = make_cleanup (target_fileio_close_cleanup, &fd);
-
/* Start by reading up to 4K at a time. The target will throttle
this number down if necessary. */
buf_alloc = 4096;
@@ -3006,25 +3011,24 @@ target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
buf_pos = 0;
while (1)
{
- n = target_fileio_pread (fd, &buf[buf_pos],
- buf_alloc - buf_pos - padding, buf_pos,
- &target_errno);
- if (n < 0)
+ n = pread_func (handle, &buf[buf_pos], buf_alloc - buf_pos - padding,
+ buf_pos, &target_errno);
+ if (n <= 0)
{
- /* An error occurred. */
- do_cleanups (close_cleanup);
- xfree (buf);
- return -1;
- }
- else if (n == 0)
- {
- /* Read all there was. */
- do_cleanups (close_cleanup);
- if (buf_pos == 0)
+ if (n < 0 || (n == 0 && buf_pos == 0))
xfree (buf);
else
*buf_p = buf;
- return buf_pos;
+ if (n < 0)
+ {
+ /* An error occurred. */
+ return -1;
+ }
+ else
+ {
+ /* Read all there was. */
+ return buf_pos;
+ }
}

buf_pos += n;
@@ -3035,11 +3039,31 @@ target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
buf_alloc *= 2;
buf = xrealloc (buf, buf_alloc);
}
-
- QUIT;
}
}

+typedef LONGEST (read_stralloc_func_ftype) (struct inferior *inf,
+ const char *filename,
+ gdb_byte **buf_p, int padding);
+
+static LONGEST
+target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
+ gdb_byte **buf_p, int padding)
+{
+ struct cleanup *close_cleanup;
+ int fd, target_errno;
+ LONGEST retval;
+
+ fd = target_fileio_open (inf, filename, FILEIO_O_RDONLY, 0700, &target_errno);
+ if (fd == -1)
+ return -1;
+
+ close_cleanup = make_cleanup (target_fileio_close_cleanup, &fd);
+ retval = read_alloc (buf_p, fd, target_fileio_read_alloc_1_pread, padding);
+ do_cleanups (close_cleanup);
+ return retval;
+}
+
/* See target.h. */

LONGEST
@@ -3049,16 +3073,17 @@ target_fileio_read_alloc (struct inferior *inf, const char *filename,
return target_fileio_read_alloc_1 (inf, filename, buf_p, 0);
}

-/* See target.h. */
+/* Helper for target_fileio_read_stralloc. */

-char *
-target_fileio_read_stralloc (struct inferior *inf, const char *filename)
+static char *
+read_stralloc (struct inferior *inf, const char *filename,
+ read_stralloc_func_ftype *func)
{
gdb_byte *buffer;
char *bufstr;
LONGEST i, transferred;

- transferred = target_fileio_read_alloc_1 (inf, filename, &buffer, 1);
+ transferred = func (inf, filename, &buffer, 1);
bufstr = (char *) buffer;

if (transferred < 0)
@@ -3082,6 +3107,13 @@ target_fileio_read_stralloc (struct inferior *inf, const char *filename)
return bufstr;
}

+/* See target.h. */
+
+char *
+target_fileio_read_stralloc (struct inferior *inf, const char *filename)
+{
+ return read_stralloc (inf, filename, target_fileio_read_alloc_1);
+}

static int
default_region_ok_for_hw_watchpoint (struct target_ops *self,