From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17056 invoked by alias); 9 Apr 2013 15:29:00 -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 17029 invoked by uid 89); 9 Apr 2013 15:29:00 -0000 X-Spam-SWARE-Status: No, score=-4.6 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 na3sys009aog117.obsmtp.com (HELO na3sys009aog117.obsmtp.com) (74.125.149.242) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Tue, 09 Apr 2013 15:28:58 +0000 Received: from mx20.qnx.com ([72.1.200.103]) (using TLSv1) by na3sys009aob117.postini.com ([74.125.148.12]) with SMTP ID DSNKUWQztgCykAwyQqRA+SJkEXzm+s4wCnmC@postini.com; Tue, 09 Apr 2013 08:28:58 PDT Received: by mx20.qnx.com (Postfix, from userid 500) id A9608210F4; Tue, 9 Apr 2013 11:28:53 -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 8753A20E1C; Tue, 9 Apr 2013 11:28:52 -0400 (EDT) Received: from qnxws8996.ott.qnx.com (10.222.2.5) by EXCH1.ott.qnx.com (10.222.2.137) with Microsoft SMTP Server id 14.2.318.4; Tue, 9 Apr 2013 11:28:52 -0400 From: Aleksandar Ristovski To: CC: , Aleksandar Ristovski Subject: [PATCH 5/8] Move linux_find_memory_regions_full & co. Date: Tue, 09 Apr 2013 16:48:00 -0000 Message-ID: <1365521265-28870-6-git-send-email-ARistovski@qnx.com> In-Reply-To: <1365521265-28870-1-git-send-email-ARistovski@qnx.com> References: <1365521265-28870-1-git-send-email-ARistovski@qnx.com> MIME-Version: 1.0 Content-Type: text/plain X-SW-Source: 2013-04/txt/msg00234.txt.bz2 Most notable change: read_alloc and read_stralloc are moved to new common-target.[ch] files. * common/common-target.c (gdb_assert.h, gdb_string.h): Include. (read_alloc, read_stralloc): Move definitions from target.c. * common/common-target.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, common-target.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 (common-target.h): Include. (read_alloc_pread_ftype): Moved typedef to common/common-target.h. (read_alloc, read_stralloc): Moved definitions to common/common-target.c. --- gdb/common/common-target.c | 89 +++++++++++++++++++++ gdb/common/common-target.h | 11 +++ gdb/common/linux-maps.c | 187 ++++++++++++++++++++++++++++++++++++++++++++ gdb/common/linux-maps.h | 25 ++++++ gdb/linux-tdep.c | 159 +------------------------------------ gdb/target.c | 94 +--------------------- 6 files changed, 314 insertions(+), 251 deletions(-) diff --git a/gdb/common/common-target.c b/gdb/common/common-target.c index a24953e..d0b3138 100644 --- a/gdb/common/common-target.c +++ b/gdb/common/common-target.c @@ -24,4 +24,93 @@ #endif #include "common-target.h" +#include "gdb_assert.h" +#include "gdb_string.h" + +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-target.h b/gdb/common/common-target.h index f56cb72..21f21ef 100644 --- a/gdb/common/common-target.h +++ b/gdb/common/common-target.h @@ -20,5 +20,16 @@ #ifndef COMMON_COMMON_TARGET_H #define COMMON_COMMON_TARGET_H +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 /* COMMON_COMMON_TARGET_H */ diff --git a/gdb/common/linux-maps.c b/gdb/common/linux-maps.c index efb0875..3fcd316 100644 --- a/gdb/common/linux-maps.c +++ b/gdb/common/linux-maps.c @@ -18,8 +18,195 @@ #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 +#include "common-target.h" + +/* 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 77c98d2..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,126 +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 mapsfilename[100]; - char *data; - - xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/smaps", (int) pid); - data = target_fileio_read_stralloc (mapsfilename); - if (data == NULL) - { - /* Older Linux kernels did not support /proc/PID/smaps. */ - xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/maps", - (int) pid); - data = target_fileio_read_stralloc (mapsfilename); - } - 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]; - - if (sscanf (line, "%64s", keyword) != 1) - { - warning (_("Error parsing {s,}maps file '%s'"), mapsfilename); - break; - } - if (strcmp (keyword, "Anonymous:") == 0) - has_anonymous = 1; - if (strcmp (keyword, "Shared_Dirty:") == 0 - || strcmp (keyword, "Private_Dirty:") == 0 - || strcmp (keyword, "Swap:") == 0 - || strcmp (keyword, "Anonymous:") == 0) - { - unsigned long number; - - if (sscanf (line, "%*s%lu", &number) != 1) - { - warning (_("Error parsing {s,}maps file '%s' number"), - mapsfilename); - break; - } - if (number != 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 b5b5ee2..1a7e091 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -43,6 +43,7 @@ #include "tracepoint.h" #include "gdb/fileio.h" #include "agent.h" +#include "common-target.h" static void target_info (char *, int); @@ -3493,65 +3494,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 +3532,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