+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.
+
2015-07-15 Jan Kratochvil <jan.kratochvil@redhat.com>
* Makefile.in (HFILES_NO_SRCDIR): Change gdb_regex.h to
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,
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);
{
struct cleanup *cleanup = make_cleanup (xfree, data);
char *line, *t;
+ int retval = 0;
line = strtok_r (data, "\n", &t);
while (line != NULL)
/* 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
/* The original datum. */
- void *obfd;
+ void *data;
};
/* A callback for linux_find_memory_regions that converts between the
{
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
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. */
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)
{
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
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;
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;
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
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)
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,