From patchwork Sun Jun 7 20:05:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kratochvil X-Patchwork-Id: 7062 Received: (qmail 105963 invoked by alias); 7 Jun 2015 20:05:18 -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 105898 invoked by uid 89); 7 Jun 2015 20:05:17 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.3 required=5.0 tests=AWL, BAYES_00, KAM_LAZY_DOMAIN_SECURITY, SPF_HELO_PASS, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Sun, 07 Jun 2015 20:05:14 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (Postfix) with ESMTPS id 6587CB6A25; Sun, 7 Jun 2015 20:05:13 +0000 (UTC) Received: from host1.jankratochvil.net (ovpn-116-44.ams2.redhat.com [10.36.116.44]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t57K5AoI014226; Sun, 7 Jun 2015 16:05:11 -0400 Subject: [PATCH v6 06/10] Prepare linux_find_memory_regions_full & co. for move From: Jan Kratochvil To: gdb-patches@sourceware.org Cc: Aleksandar Ristovski Date: Sun, 07 Jun 2015 22:05:10 +0200 Message-ID: <20150607200510.8918.28582.stgit@host1.jankratochvil.net> In-Reply-To: <20150607200422.8918.48900.stgit@host1.jankratochvil.net> References: <20150607200422.8918.48900.stgit@host1.jankratochvil.net> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-IsSubscribed: yes Hi, prepare code for move into gdb/common/. Approved by: https://sourceware.org/ml/gdb-patches/2014-05/msg00371.html Jan gdb/ChangeLog 2014-02-26 Aleksandar Ristovski 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 | 93 ++++++++++++++++++++++++++++-------------- 2 files changed, 138 insertions(+), 76 deletions(-) diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index b0981f5..4618415 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,42 +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 (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 (mapsfilename); @@ -1155,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) @@ -1269,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 @@ -1293,9 +1281,11 @@ struct linux_find_memory_regions_data /* The original datum. */ - void *obfd; + void *data; }; +static linux_find_memory_region_ftype linux_find_memory_regions_thunk; + /* A callback for linux_find_memory_regions that converts between the "full"-style callback and find_memory_region_ftype. */ @@ -1307,7 +1297,47 @@ 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 (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 @@ -1315,16 +1345,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. */ @@ -1506,8 +1535,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 306c21d..d11e7dc 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -2942,6 +2942,22 @@ 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. */ + +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. 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 @@ -2949,22 +2965,14 @@ target_fileio_close_cleanup (void *opaque) information. */ static LONGEST -target_fileio_read_alloc_1 (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 (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; @@ -2972,25 +2980,24 @@ target_fileio_read_alloc_1 (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) - { - /* An error occurred. */ - do_cleanups (close_cleanup); - xfree (buf); - return -1; - } - else if (n == 0) + n = pread_func (handle, &buf[buf_pos], buf_alloc - buf_pos - padding, + buf_pos, &target_errno); + 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; @@ -3001,11 +3008,32 @@ target_fileio_read_alloc_1 (const char *filename, buf_alloc *= 2; buf = xrealloc (buf, buf_alloc); } - - QUIT; } } +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) +{ + struct cleanup *close_cleanup; + int fd, target_errno; + LONGEST retval; + + fd = target_fileio_open (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; +} + /* Read target file FILENAME. Store the result in *BUF_P and return the size of the transferred data. See the declaration in "target.h" function for more information about the return value. */ @@ -3022,14 +3050,14 @@ 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. */ -char * -target_fileio_read_stralloc (const char *filename) +static char * +read_stralloc (const char *filename, read_stralloc_func_ftype *func) { gdb_byte *buffer; char *bufstr; LONGEST i, transferred; - transferred = target_fileio_read_alloc_1 (filename, &buffer, 1); + transferred = func (filename, &buffer, 1); bufstr = (char *) buffer; if (transferred < 0) @@ -3053,6 +3081,11 @@ target_fileio_read_stralloc (const char *filename) return bufstr; } +char * +target_fileio_read_stralloc (const char *filename) +{ + return read_stralloc (filename, target_fileio_read_alloc_1); +} static int default_region_ok_for_hw_watchpoint (struct target_ops *self,