diff options
author | Pedro Alves <palves@redhat.com> | 2011-02-14 11:22:29 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2011-02-14 11:22:29 +0000 |
commit | e6e4e7014d3721283cf0415cadb3c7f1a1200f7b (patch) | |
tree | 9107c3b03c92b237512758b98bf539c616ea90b9 /gdb/target.c | |
parent | e6ca34fcfbd6f341cb70c680d45f229cb5801eeb (diff) | |
download | gdb-e6e4e7014d3721283cf0415cadb3c7f1a1200f7b.zip gdb-e6e4e7014d3721283cf0415cadb3c7f1a1200f7b.tar.gz gdb-e6e4e7014d3721283cf0415cadb3c7f1a1200f7b.tar.bz2 |
gdb/
* target.c (target_read_live_memory): New function.
(memory_xfer_live_readonly_partial): New.
(memory_xfer_partial): If reading from a traceframe, fallback to
reading unavailable read-only memory from read-only regions of
live target memory.
* tracepoint.c (disconnect_tracing): Adjust.
(set_current_traceframe): New, factored out from
set_traceframe_number.
(set_traceframe_number): Reimplement to only change the traceframe
number on the GDB side.
(do_restore_current_traceframe_cleanup): Adjust.
(make_cleanup_restore_traceframe_number): New.
(cur_traceframe_number): New global.
(tfile_open): Set cur_traceframe_number to no traceframe.
(set_tfile_traceframe): New function.
(tfile_trace_find): If looking up a traceframe using any method
other than by number, make sure the current tfile traceframe
matches gdb's current traceframe. Update the current tfile
traceframe if the lookup succeeded.
(tfile_fetch_registers, tfile_xfer_partial)
(tfile_get_trace_state_variable_value): Make sure the remote
traceframe matches gdb's current traceframe.
* remote.c (remote_traceframe_number): New global.
(remote_open_1): Set it to -1.
(set_remote_traceframe): New function.
(remote_fetch_registers, remote_store_registers)
(remote_xfer_memory, remote_xfer_partial)
(remote_get_trace_state_variable_value): Make sure the remote
traceframe matches gdb's current traceframe.
(remote_trace_find): If looking up a traceframe using any method
other than by number, make sure the current remote traceframe
matches gdb's current traceframe. Update the current remote
traceframe if the lookup succeeded.
* infrun.c (fetch_inferior_event): Adjust.
* tracepoint.h (set_current_traceframe): Declare.
(get_traceframe_number, set_traceframe_number): Add describing
comments.
Diffstat (limited to 'gdb/target.c')
-rw-r--r-- | gdb/target.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/gdb/target.c b/gdb/target.c index edf03f1..214edb7 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1271,6 +1271,82 @@ 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 LONGEST +target_read_live_memory (enum target_object object, + ULONGEST memaddr, gdb_byte *myaddr, LONGEST len) +{ + int 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_read (current_target.beneath, object, NULL, + myaddr, memaddr, 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. */ + +static LONGEST +memory_xfer_live_readonly_partial (struct target_ops *ops, + enum target_object object, + gdb_byte *readbuf, ULONGEST memaddr, + LONGEST 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->bfd, 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); + } + 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); + } + } + } + } + + return 0; +} + /* Perform a partial memory transfer. For docs see target.h, to_xfer_partial. */ @@ -1329,6 +1405,59 @@ memory_xfer_partial (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); + if (res > 0) + return res; + + /* No use trying further, we know some memory starting + at MEMADDR isn't available. */ + return -1; + } + + /* 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. */ |