From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3112 invoked by alias); 5 Apr 2013 13:03:14 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 3011 invoked by uid 89); 5 Apr 2013 13:03:14 -0000 X-Spam-SWARE-Status: No, score=-4.5 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,TW_XS autolearn=ham version=3.3.1 Received: from na3sys009aog131.obsmtp.com (HELO na3sys009aog131.obsmtp.com) (74.125.149.247) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Fri, 05 Apr 2013 13:03:09 +0000 Received: from mx20.qnx.com ([72.1.200.103]) (using TLSv1) by na3sys009aob131.postini.com ([74.125.148.12]) with SMTP ID DSNKUV7Li0d4t5yT/2XDKS171otrN+vClrTd@postini.com; Fri, 05 Apr 2013 06:03:09 PDT Received: by mx20.qnx.com (Postfix, from userid 500) id B7E3120E59; Fri, 5 Apr 2013 09:03:05 -0400 (EDT) Received: from exhts.ott.qnx.com (exch1 [10.222.2.137]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by mx20.qnx.com (Postfix) with ESMTPS id 9449120A8B; Fri, 5 Apr 2013 09:03:04 -0400 (EDT) Received: from [10.222.96.215] (10.222.2.5) by EXCH1.ott.qnx.com (10.222.2.137) with Microsoft SMTP Server id 14.2.318.4; Fri, 5 Apr 2013 09:03:04 -0400 Message-ID: <515ECB07.4000806@qnx.com> Date: Fri, 05 Apr 2013 15:37:00 -0000 From: Aleksandar Ristovski User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130308 Thunderbird/17.0.4 MIME-Version: 1.0 Newsgroups: gmane.comp.gdb.patches To: Jan Kratochvil CC: "gdb-patches@sourceware.org" Subject: Re: [patch 5/6] Move linux_find_memory_regions_full & co. References: <51278984.3070208@qnx.com> <20130310210831.GF21130@host2.jankratochvil.net> <514C56D0.3020805@qnx.com> <20130326165839.GB12291@host2.jankratochvil.net> <515353C8.5080100@qnx.com> <20130328201347.GA9375@host2.jankratochvil.net> <5159E3FD.1030308@qnx.com> <20130401195610.GA21391@host2.jankratochvil.net> In-Reply-To: <20130401195610.GA21391@host2.jankratochvil.net> Content-Type: multipart/mixed; boundary="------------000004000509050105080503" X-Virus-Found: No X-SW-Source: 2013-04/txt/msg00122.txt.bz2 Message-ID: <20130405153700.5FUhTfMjyn2Jq2_YiTbYZBefOP9ybnJoXrONklBOqF0@z> --------------000004000509050105080503 Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit Content-length: 364 Rebased to master e96bd93d436e464a532a7e1161e1d201c9fc50c7 On 13-04-01 03:56 PM, Jan Kratochvil wrote: > On Mon, 01 Apr 2013 21:46:05 +0200, Aleksandar Ristovski wrote: >> Done, waiting for your feedback on #4/6 to proceed with commit. > > BTW the patchset should get checked in only as a whole, only some parts of it > have no benefit to the user. > > > Jan > --------------000004000509050105080503 Content-Type: text/x-patch; name="0005-Move-linux_find_memory_regions_full-co.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0005-Move-linux_find_memory_regions_full-co.patch" Content-length: 19240 >From 43124b3998f6eb8985e828d0fd78107fd0d1e7e4 Mon Sep 17 00:00:00 2001 From: Aleksandar Ristovski Date: Wed, 27 Mar 2013 09:54:36 -0400 Subject: [PATCH 5/8] Move linux_find_memory_regions_full & co. * common/common-utils.c (read_alloc, read_stralloc): Move definitions from target.c. * common/common-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): Include. (read_mapping): Move from linux-tdep.c. (linux_find_memory_read_stralloc_1_pread): New function. (linux_find_memory_read_stralloc_1): New function. (linux_find_memory_read_stralloc): New function. * 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 (read_alloc_pread_ftype): Moved typedef to common/common-utils.h. (read_alloc, read_stralloc): Moved definitions to common/common-utils.c. --- gdb/common/common-utils.c | 88 +++++++++++++++++++++ gdb/common/common-utils.h | 11 +++ gdb/common/linux-maps.c | 186 +++++++++++++++++++++++++++++++++++++++++++++ gdb/common/linux-maps.h | 25 ++++++ gdb/linux-tdep.c | 148 +----------------------------------- gdb/target.c | 93 ----------------------- 6 files changed, 311 insertions(+), 240 deletions(-) diff --git a/gdb/common/common-utils.c b/gdb/common/common-utils.c index c123ed7..31234fa 100644 --- a/gdb/common/common-utils.c +++ b/gdb/common/common-utils.c @@ -348,3 +348,91 @@ skip_spaces_const (const char *chp) chp++; return chp; } + +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/common-utils.h b/gdb/common/common-utils.h index 2c95d34..c7f8162 100644 --- a/gdb/common/common-utils.h +++ b/gdb/common/common-utils.h @@ -91,4 +91,15 @@ extern char *skip_spaces (char *inp); extern const char *skip_spaces_const (const char *inp); +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 diff --git a/gdb/common/linux-maps.c b/gdb/common/linux-maps.c index efb0875..a2566e1 100644 --- a/gdb/common/linux-maps.c +++ b/gdb/common/linux-maps.c @@ -18,8 +18,194 @@ #ifdef GDBSERVER #include "server.h" +#include +#include #else #include "defs.h" +#include "target.h" #endif #include "linux-maps.h" +#include "gdb_assert.h" +#include +#include + +/* 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 filename[100]; + char *data; + + xsnprintf (filename, sizeof filename, "/proc/%d/smaps", (int) pid); + data = linux_find_memory_read_stralloc (filename); + if (data == NULL) + { + /* Older Linux kernels did not support /proc/PID/smaps. */ + xsnprintf (filename, sizeof filename, "/proc/%d/maps", (int) pid); + data = linux_find_memory_read_stralloc (filename); + } + 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]; + unsigned long number; + + if (sscanf (line, "%64s%lu kB\n", keyword, &number) != 2) + { + warning (_("Error parsing {s,}maps file '%s'"), filename); + break; + } + if (strcmp (keyword, "Anonymous:") == 0) + has_anonymous = 1; + if (number != 0 && (strcmp (keyword, "Shared_Dirty:") == 0 + || strcmp (keyword, "Private_Dirty:") == 0 + || strcmp (keyword, "Swap:") == 0 + || strcmp (keyword, "Anonymous:") == 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 da426e5..e989376 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/linux-tdep.c b/gdb/linux-tdep.c index c48f4ec..4544e5f 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -33,6 +33,7 @@ #include "arch-utils.h" #include "gdb_obstack.h" #include "cli/cli-utils.h" +#include "linux-maps.h" #include @@ -207,44 +208,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 @@ -661,115 +624,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 filename[100]; - char *data; - - xsnprintf (filename, sizeof filename, "/proc/%d/smaps", (int) pid); - data = target_fileio_read_stralloc (filename); - if (data == NULL) - { - /* Older Linux kernels did not support /proc/PID/smaps. */ - xsnprintf (filename, sizeof filename, "/proc/%d/maps", (int) pid); - data = target_fileio_read_stralloc (filename); - } - 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]; - unsigned long number; - - if (sscanf (line, "%64s%lu kB\n", keyword, &number) != 2) - { - warning (_("Error parsing {s,}maps file '%s'"), filename); - break; - } - if (strcmp (keyword, "Anonymous:") == 0) - has_anonymous = 1; - if (number != 0 && (strcmp (keyword, "Shared_Dirty:") == 0 - || strcmp (keyword, "Private_Dirty:") == 0 - || strcmp (keyword, "Swap:") == 0 - || strcmp (keyword, "Anonymous:") == 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 ed0f3bf..0dbac02 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -3493,65 +3493,6 @@ target_fileio_read_alloc_1_pread (int handle, gdb_byte *read_buf, int len, target_fileio_read_alloc; see the declaration of that function for more information. */ -typedef int (read_alloc_pread_ftype) (int handle, gdb_byte *read_buf, int len, - ULONGEST offset, int *target_errno); - -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; - } - } -} - static LONGEST target_fileio_read_alloc_1 (const char *filename, gdb_byte **buf_p, int padding) @@ -3590,40 +3531,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. */ -typedef LONGEST (read_stralloc_func_ftype) (const char *filename, - gdb_byte **buf_p, int padding); - -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) { -- 1.7.10.4 --------------000004000509050105080503--