From patchwork Sun Jun 14 19:26:30 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kratochvil X-Patchwork-Id: 7171 Received: (qmail 81070 invoked by alias); 14 Jun 2015 19:26:38 -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 81037 invoked by uid 89); 14 Jun 2015 19:26:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_40, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS 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, 14 Jun 2015 19:26:34 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id 76A9CBAEF3; Sun, 14 Jun 2015 19:26:32 +0000 (UTC) Received: from host1.jankratochvil.net (ovpn-116-41.ams2.redhat.com [10.36.116.41]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t5EJQUxM009982; Sun, 14 Jun 2015 15:26:31 -0400 Subject: [PATCH v7 06/10] Prepare linux_find_memory_regions_full & co. for move From: Jan Kratochvil To: gdb-patches@sourceware.org Cc: Aleksandar Ristovski Date: Sun, 14 Jun 2015 21:26:30 +0200 Message-ID: <20150614192630.18346.76001.stgit@host1.jankratochvil.net> In-Reply-To: <20150614192542.18346.87859.stgit@host1.jankratochvil.net> References: <20150614192542.18346.87859.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 | 96 +++++++++++++++++++++++++++++-------------- 2 files changed, 138 insertions(+), 79 deletions(-) diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index c81f71b..fb59305 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,