From patchwork Tue Mar 11 12:42:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 34 Return-Path: X-Original-To: siddhesh@wilcox.dreamhost.com Delivered-To: siddhesh@wilcox.dreamhost.com Received: from homiemail-mx21.g.dreamhost.com (caibbdcaaahb.dreamhost.com [208.113.200.71]) by wilcox.dreamhost.com (Postfix) with ESMTP id 800F73600FA for ; Tue, 11 Mar 2014 05:44:56 -0700 (PDT) Received: by homiemail-mx21.g.dreamhost.com (Postfix, from userid 14314964) id 338D22455941; Tue, 11 Mar 2014 05:44:56 -0700 (PDT) X-Original-To: gdb@patchwork.siddhesh.in Delivered-To: x14314964@homiemail-mx21.g.dreamhost.com Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by homiemail-mx21.g.dreamhost.com (Postfix) with ESMTPS id F08372705D28 for ; Tue, 11 Mar 2014 05:44:55 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:mime-version :content-type; q=dns; s=default; b=XbOfQaB009fM2Uw2mfpAIP+5cHMap iMsutXuAkvCWMZyfG307H1R/moQ60JefS5zkBCQMpqoDTG+OUbzCIS31T5lTSneb S1/eiZUqa8DhdnUEIt7WzQxqnQHdTmOZE2pFxRejVR0/DNFMuKAqR5lbRz8vRJn5 3DjCO9gZkAFGsQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:mime-version :content-type; s=default; bh=/3+P9nzpA9IieJk9Cfrw92BfwzE=; b=nWU dublpQUBrhmlLntuHi+vFGQ68GTri6HLKDWsgwZwKXEAXmpSv2xXhAOJoMhpt9s8 IAf4MaYurMmqCDMDbcP9ZV7eiYBEZbV3jkC5BV8+vCY3ilB8XFjBCrnBfBYN8tqV Z2S5I8vXUpFOFIAg2uopb2q0fe3OevEhKSSUYmKM= Received: (qmail 5243 invoked by alias); 11 Mar 2014 12:44:54 -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 5217 invoked by uid 89); 11 Mar 2014 12:44:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL, BAYES_00 autolearn=ham version=3.3.2 X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 11 Mar 2014 12:44:51 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1WNM35-0002qK-DQ from Yao_Qi@mentor.com for gdb-patches@sourceware.org; Tue, 11 Mar 2014 05:44:47 -0700 Received: from SVR-ORW-FEM-04.mgc.mentorg.com ([147.34.97.41]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Tue, 11 Mar 2014 05:44:47 -0700 Received: from qiyao.dyndns.org.com (147.34.91.1) by svr-orw-fem-04.mgc.mentorg.com (147.34.97.41) with Microsoft SMTP Server id 14.2.247.3; Tue, 11 Mar 2014 05:44:46 -0700 From: Yao Qi To: Subject: [PATCH 1/3] Move the traceframe_available_memory code from memory_xfer_partial_1 down to the targets Date: Tue, 11 Mar 2014 20:42:09 +0800 Message-ID: <1394541731-27486-1-git-send-email-yao@codesourcery.com> MIME-Version: 1.0 X-IsSubscribed: yes X-DH-Original-To: gdb@patchwork.siddhesh.in As a follow-up to [PATCH 7/8] Adjust read_value_memory to use to_xfer_partial https://sourceware.org/ml/gdb-patches/2014-02/msg00384.html this patch moves traceframe_available_memory down to the target side. After this patch, the gdb core code is cleaner, and code on handling unavailable memory is moved to remote/tfile/ctf targets. In details, this patch moves traceframe_available_memory code from memory_xfer_partial_1 to remote target only, so remote target still uses traceframe_info mechanism to check unavailable memory, and use remote_ops to read them from read-only sections. We don't use traceframe_info mechanism for tfile and ctf target, because it is fast to iterate all traceframes from trace file, so the summary information got from traceframe_info is not necessary. This patch also moves two functions to remote.c from target.c, because they are only used in remote.c. I'll clean them up in another patch. This series is tested on x86_64-linux. gdb: 2014-03-11 Yao Qi * ctf.c (ctf_xfer_partial): Check the return value of exec_read_partial_read_only, if it is not TARGET_XFER_OK, return TARGET_XFER_UNAVAILABLE. * tracefile-tfile.c (tfile_xfer_partial): Likewise. * target.c (target_read_live_memory): Move it to remote.c. (memory_xfer_live_readonly_partial): Likewise. (memory_xfer_partial_1): Move some code to remote_read_bytes. * remote.c (target_read_live_memory): Moved from target.c. (memory_xfer_live_readonly_partial): Likewise. (remote_read_bytes): Moved from memory_xfer_partial_1. --- gdb/ctf.c | 16 +++++- gdb/remote.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++ gdb/target.c | 138 ------------------------------------------------- gdb/tracefile-tfile.c | 16 +++++- 4 files changed, 168 insertions(+), 140 deletions(-) diff --git a/gdb/ctf.c b/gdb/ctf.c index 95fd31f..ebd40d6 100644 --- a/gdb/ctf.c +++ b/gdb/ctf.c @@ -1377,6 +1377,7 @@ ctf_xfer_partial (struct target_ops *ops, enum target_object object, { struct bt_iter_pos *pos; int i = 0; + enum target_xfer_status res; gdb_assert (ctf_iter != NULL); /* Save the current position. */ @@ -1466,7 +1467,20 @@ ctf_xfer_partial (struct target_ops *ops, enum target_object object, /* Restore the position. */ bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); - return exec_read_partial_read_only (readbuf, offset, len, xfered_len); + /* Requested memory is unavailable in the context of traceframes, + and this address falls within a read-only section, fallback + to reading from executable. */ + res = exec_read_partial_read_only (readbuf, offset, len, xfered_len); + + if (res == TARGET_XFER_OK) + return TARGET_XFER_OK; + else + { + /* No use trying further, we know some memory starting + at MEMADDR isn't available. */ + *xfered_len = len; + return TARGET_XFER_UNAVAILABLE; + } } else { diff --git a/gdb/remote.c b/gdb/remote.c index e03d3bf..afe9d12 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -6824,6 +6824,87 @@ remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, ULONGEST len, packet_format[0], 1); } +/* Read memory from the live target, even if currently inspecting a + traceframe. The return is the same as that of target_read. */ + +static enum target_xfer_status +target_read_live_memory (enum target_object object, + ULONGEST memaddr, gdb_byte *myaddr, ULONGEST len, + ULONGEST *xfered_len) +{ + enum target_xfer_status ret; + struct cleanup *cleanup; + + /* Switch momentarily out of tfind mode so to access live memory. + Note that this must not clear global state, such as the frame + cache, which must still remain valid for the previous traceframe. + We may be _building_ the frame cache at this point. */ + cleanup = make_cleanup_restore_traceframe_number (); + set_traceframe_number (-1); + + ret = target_xfer_partial (current_target.beneath, object, NULL, + myaddr, NULL, memaddr, len, xfered_len); + + do_cleanups (cleanup); + return ret; +} + +/* Using the set of read-only target sections of OPS, read live + read-only memory. Note that the actual reads start from the + top-most target again. + + For interface/parameters/return description see target.h, + to_xfer_partial. */ + +static enum target_xfer_status +memory_xfer_live_readonly_partial (struct target_ops *ops, + enum target_object object, + gdb_byte *readbuf, ULONGEST memaddr, + ULONGEST len, ULONGEST *xfered_len) +{ + struct target_section *secp; + struct target_section_table *table; + + secp = target_section_by_addr (ops, memaddr); + if (secp != NULL + && (bfd_get_section_flags (secp->the_bfd_section->owner, + secp->the_bfd_section) + & SEC_READONLY)) + { + struct target_section *p; + ULONGEST memend = memaddr + len; + + table = target_get_section_table (ops); + + for (p = table->sections; p < table->sections_end; p++) + { + if (memaddr >= p->addr) + { + if (memend <= p->endaddr) + { + /* Entire transfer is within this section. */ + return target_read_live_memory (object, memaddr, + readbuf, len, xfered_len); + } + else if (memaddr >= p->endaddr) + { + /* This section ends before the transfer starts. */ + continue; + } + else + { + /* This section overlaps the transfer. Just do half. */ + len = p->endaddr - memaddr; + return target_read_live_memory (object, memaddr, + readbuf, len, xfered_len); + } + } + } + } + + return TARGET_XFER_EOF; +} + /* Read memory data directly from the remote machine. This does not use the data cache; the data cache uses this. MEMADDR is the address in the remote memory space. @@ -6847,6 +6928,63 @@ remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, ULONGEST len, if (len == 0) return 0; + if (get_traceframe_number () != -1) + { + VEC(mem_range_s) *available; + + /* If we fail to get the set of available memory, then the + target does not support querying traceframe info, and so we + attempt reading from the traceframe anyway (assuming the + target implements the old QTro packet then). */ + if (traceframe_available_memory (&available, memaddr, len)) + { + struct cleanup *old_chain; + + old_chain = make_cleanup (VEC_cleanup(mem_range_s), &available); + + if (VEC_empty (mem_range_s, available) + || VEC_index (mem_range_s, available, 0)->start != memaddr) + { + enum target_xfer_status res; + + /* Don't read into the traceframe's available + memory. */ + if (!VEC_empty (mem_range_s, available)) + { + LONGEST oldlen = len; + + len = VEC_index (mem_range_s, available, 0)->start - memaddr; + gdb_assert (len <= oldlen); + } + + do_cleanups (old_chain); + + /* This goes through the topmost target again. */ + res = memory_xfer_live_readonly_partial (&remote_ops, + TARGET_OBJECT_MEMORY, + myaddr, memaddr, + len, xfered_len); + if (res == TARGET_XFER_OK) + return TARGET_XFER_OK; + else + { + /* No use trying further, we know some memory starting + at MEMADDR isn't available. */ + *xfered_len = len; + return TARGET_XFER_UNAVAILABLE; + } + } + + /* Don't try to read more than how much is available, in + case the target implements the deprecated QTro packet to + cater for older GDBs (the target's knowledge of read-only + sections may be outdated by now). */ + len = VEC_index (mem_range_s, available, 0)->length; + + do_cleanups (old_chain); + } + } + max_buf_size = get_memory_read_packet_size (); /* The packet buffer will be large enough for the payload; get_memory_packet_size ensures this. */ diff --git a/gdb/target.c b/gdb/target.c index f7868c0..c2669c6 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -961,87 +961,6 @@ target_section_by_addr (struct target_ops *target, CORE_ADDR addr) return NULL; } -/* Read memory from the live target, even if currently inspecting a - traceframe. The return is the same as that of target_read. */ - -static enum target_xfer_status -target_read_live_memory (enum target_object object, - ULONGEST memaddr, gdb_byte *myaddr, ULONGEST len, - ULONGEST *xfered_len) -{ - enum target_xfer_status ret; - struct cleanup *cleanup; - - /* Switch momentarily out of tfind mode so to access live memory. - Note that this must not clear global state, such as the frame - cache, which must still remain valid for the previous traceframe. - We may be _building_ the frame cache at this point. */ - cleanup = make_cleanup_restore_traceframe_number (); - set_traceframe_number (-1); - - ret = target_xfer_partial (current_target.beneath, object, NULL, - myaddr, NULL, memaddr, len, xfered_len); - - do_cleanups (cleanup); - return ret; -} - -/* Using the set of read-only target sections of OPS, read live - read-only memory. Note that the actual reads start from the - top-most target again. - - For interface/parameters/return description see target.h, - to_xfer_partial. */ - -static enum target_xfer_status -memory_xfer_live_readonly_partial (struct target_ops *ops, - enum target_object object, - gdb_byte *readbuf, ULONGEST memaddr, - ULONGEST len, ULONGEST *xfered_len) -{ - struct target_section *secp; - struct target_section_table *table; - - secp = target_section_by_addr (ops, memaddr); - if (secp != NULL - && (bfd_get_section_flags (secp->the_bfd_section->owner, - secp->the_bfd_section) - & SEC_READONLY)) - { - struct target_section *p; - ULONGEST memend = memaddr + len; - - table = target_get_section_table (ops); - - for (p = table->sections; p < table->sections_end; p++) - { - if (memaddr >= p->addr) - { - if (memend <= p->endaddr) - { - /* Entire transfer is within this section. */ - return target_read_live_memory (object, memaddr, - readbuf, len, xfered_len); - } - else if (memaddr >= p->endaddr) - { - /* This section ends before the transfer starts. */ - continue; - } - else - { - /* This section overlaps the transfer. Just do half. */ - len = p->endaddr - memaddr; - return target_read_live_memory (object, memaddr, - readbuf, len, xfered_len); - } - } - } - } - - return TARGET_XFER_EOF; -} - /* Read memory from more than one valid target. A core file, for instance, could have some of memory but delegate other bits to the target below it. So, we must manually try all targets. */ @@ -1149,63 +1068,6 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, } } - /* If reading unavailable memory in the context of traceframes, and - this address falls within a read-only section, fallback to - reading from live memory. */ - if (readbuf != NULL && get_traceframe_number () != -1) - { - VEC(mem_range_s) *available; - - /* If we fail to get the set of available memory, then the - target does not support querying traceframe info, and so we - attempt reading from the traceframe anyway (assuming the - target implements the old QTro packet then). */ - if (traceframe_available_memory (&available, memaddr, len)) - { - struct cleanup *old_chain; - - old_chain = make_cleanup (VEC_cleanup(mem_range_s), &available); - - if (VEC_empty (mem_range_s, available) - || VEC_index (mem_range_s, available, 0)->start != memaddr) - { - /* Don't read into the traceframe's available - memory. */ - if (!VEC_empty (mem_range_s, available)) - { - LONGEST oldlen = len; - - len = VEC_index (mem_range_s, available, 0)->start - memaddr; - gdb_assert (len <= oldlen); - } - - do_cleanups (old_chain); - - /* This goes through the topmost target again. */ - res = memory_xfer_live_readonly_partial (ops, object, - readbuf, memaddr, - len, xfered_len); - if (res == TARGET_XFER_OK) - return TARGET_XFER_OK; - else - { - /* No use trying further, we know some memory starting - at MEMADDR isn't available. */ - *xfered_len = len; - return TARGET_XFER_UNAVAILABLE; - } - } - - /* Don't try to read more than how much is available, in - case the target implements the deprecated QTro packet to - cater for older GDBs (the target's knowledge of read-only - sections may be outdated by now). */ - len = VEC_index (mem_range_s, available, 0)->length; - - do_cleanups (old_chain); - } - } - /* Try GDB's internal data cache. */ region = lookup_mem_region (memaddr); /* region->hi == 0 means there's no upper bound. */ diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c index cbf746d..a36596f 100644 --- a/gdb/tracefile-tfile.c +++ b/gdb/tracefile-tfile.c @@ -900,6 +900,7 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object, if (get_traceframe_number () != -1) { int pos = 0; + enum target_xfer_status res; /* Iterate through the traceframe's blocks, looking for memory. */ @@ -937,7 +938,20 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object, pos += (8 + 2 + mlen); } - return exec_read_partial_read_only (readbuf, offset, len, xfered_len); + /* Requested memory is unavailable in the context of traceframes, + and this address falls within a read-only section, fallback + to reading from executable. */ + res = exec_read_partial_read_only (readbuf, offset, len, xfered_len); + + if (res == TARGET_XFER_OK) + return TARGET_XFER_OK; + else + { + /* No use trying further, we know some memory starting + at MEMADDR isn't available. */ + *xfered_len = len; + return TARGET_XFER_UNAVAILABLE; + } } else {