From e6ca34fcfbd6f341cb70c680d45f229cb5801eeb Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Mon, 14 Feb 2011 11:21:25 +0000 Subject: [PATCH] Mark pieces of values as unavailable if the corresponding memory is unavailable. gdb/ * valops.c: Include tracepoint.h. (value_fetch_lazy): Use read_value_memory. (read_value_memory): New. * value.h (read_value_memory): Declare. * dwarf2loc.c (read_pieced_value): Use read_value_memory. * exec.c (section_table_available_memory): New function. * exec.h (section_table_available_memory): Declare. --- gdb/ChangeLog | 13 +++++++ gdb/dwarf2loc.c | 8 ++--- gdb/exec.c | 37 ++++++++++++++++++++ gdb/exec.h | 12 +++++++ gdb/valops.c | 93 +++++++++++++++++++++++++++++++++++++++++++++---- gdb/value.h | 11 ++++++ 6 files changed, 163 insertions(+), 11 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index df7e871bd9f..1fd5b020c03 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2011-02-14 Pedro Alves + + Mark pieces of values as unavailable if the corresponding memory + is unavailable. + + * valops.c: Include tracepoint.h. + (value_fetch_lazy): Use read_value_memory. + (read_value_memory): New. + * value.h (read_value_memory): Declare. + * dwarf2loc.c (read_pieced_value): Use read_value_memory. + * exec.c (section_table_available_memory): New function. + * exec.h (section_table_available_memory): Declare. + 2011-02-14 Pedro Alves * Makefile.in (SFILES): Add memrange.c. diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index d9580c65888..0f58954d769 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -603,10 +603,10 @@ read_pieced_value (struct value *v) break; case DWARF_VALUE_MEMORY: - if (p->v.mem.in_stack_memory) - read_stack (p->v.mem.addr + source_offset, buffer, this_size); - else - read_memory (p->v.mem.addr + source_offset, buffer, this_size); + read_value_memory (v, offset, + p->v.mem.in_stack_memory, + p->v.mem.addr + source_offset, + buffer, this_size); break; case DWARF_VALUE_STACK: diff --git a/gdb/exec.c b/gdb/exec.c index 0eea1d70bd3..1cca3b336d0 100644 --- a/gdb/exec.c +++ b/gdb/exec.c @@ -572,6 +572,43 @@ map_vmap (bfd *abfd, bfd *arch) } +VEC(mem_range_s) * +section_table_available_memory (VEC(mem_range_s) *memory, + CORE_ADDR memaddr, LONGEST len, + struct target_section *sections, + struct target_section *sections_end) +{ + struct target_section *p; + ULONGEST memend = memaddr + len; + + for (p = sections; p < sections_end; p++) + { + if ((bfd_get_section_flags (p->bfd, p->the_bfd_section) + & SEC_READONLY) == 0) + continue; + + /* Copy the meta-data, adjusted. */ + if (mem_ranges_overlap (p->addr, p->endaddr - p->addr, memaddr, len)) + { + ULONGEST lo1, hi1, lo2, hi2; + struct mem_range *r; + + lo1 = memaddr; + hi1 = memaddr + len; + + lo2 = p->addr; + hi2 = p->endaddr; + + r = VEC_safe_push (mem_range_s, memory, NULL); + + r->start = max (lo1, lo2); + r->length = min (hi1, hi2) - r->start; + } + } + + return memory; +} + int section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, LONGEST len, diff --git a/gdb/exec.h b/gdb/exec.h index 8af2adf0279..a8df60878b4 100644 --- a/gdb/exec.h +++ b/gdb/exec.h @@ -23,6 +23,7 @@ #include "target.h" #include "progspace.h" +#include "memrange.h" struct target_section; struct target_ops; @@ -44,6 +45,17 @@ extern int build_section_table (struct bfd *, struct target_section **, extern int resize_section_table (struct target_section_table *, int); +/* Appends all read-only memory ranges found in the target section + table defined by SECTIONS and SECTIONS_END, starting at (and + intersected with) MEMADDR for LEN bytes. Returns the augmented + VEC. */ + +extern VEC(mem_range_s) * + section_table_available_memory (VEC(mem_range_s) *ranges, + CORE_ADDR memaddr, LONGEST len, + struct target_section *sections, + struct target_section *sections_end); + /* Read or write from mappable sections of BFD executable files. Request to transfer up to LEN 8-bit bytes of the target sections diff --git a/gdb/valops.c b/gdb/valops.c index 24c22692ead..7fa87293fad 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -38,7 +38,7 @@ #include "cp-support.h" #include "dfp.h" #include "user-regs.h" - +#include "tracepoint.h" #include #include "gdb_string.h" #include "gdb_assert.h" @@ -1009,12 +1009,8 @@ value_fetch_lazy (struct value *val) int length = TYPE_LENGTH (check_typedef (value_enclosing_type (val))); if (length) - { - if (value_stack (val)) - read_stack (addr, value_contents_all_raw (val), length); - else - read_memory (addr, value_contents_all_raw (val), length); - } + read_value_memory (val, 0, value_stack (val), + addr, value_contents_all_raw (val), length); } else if (VALUE_LVAL (val) == lval_register) { @@ -1113,6 +1109,89 @@ value_fetch_lazy (struct value *val) return 0; } +void +read_value_memory (struct value *val, int embedded_offset, + int stack, CORE_ADDR memaddr, + gdb_byte *buffer, size_t length) +{ + if (length) + { + VEC(mem_range_s) *available_memory; + + if (get_traceframe_number () < 0 + || !traceframe_available_memory (&available_memory, memaddr, length)) + { + if (stack) + read_stack (memaddr, buffer, length); + else + read_memory (memaddr, buffer, length); + } + else + { + struct target_section_table *table; + struct cleanup *old_chain; + CORE_ADDR unavail; + mem_range_s *r; + int i; + + /* Fallback to reading from read-only sections. */ + table = target_get_section_table (&exec_ops); + available_memory = + section_table_available_memory (available_memory, + memaddr, length, + table->sections, + table->sections_end); + + old_chain = make_cleanup (VEC_cleanup(mem_range_s), + &available_memory); + + normalize_mem_ranges (available_memory); + + /* Mark which bytes are unavailable, and read those which + are available. */ + + unavail = memaddr; + + for (i = 0; + VEC_iterate (mem_range_s, available_memory, i, r); + i++) + { + if (mem_ranges_overlap (r->start, r->length, + memaddr, length)) + { + CORE_ADDR lo1, hi1, lo2, hi2; + CORE_ADDR start, end; + + /* Get the intersection window. */ + lo1 = memaddr; + hi1 = memaddr + length; + lo2 = r->start; + hi2 = r->start + r->length; + start = max (lo1, lo2); + end = min (hi1, hi2); + + gdb_assert (end - memaddr <= length); + + if (start > unavail) + mark_value_bytes_unavailable (val, + (embedded_offset + + unavail - memaddr), + start - unavail); + unavail = end; + + read_memory (start, buffer + start - memaddr, end - start); + } + } + + if (unavail != memaddr + length) + mark_value_bytes_unavailable (val, + embedded_offset + unavail - memaddr, + (memaddr + length) - unavail); + + do_cleanups (old_chain); + } + } +} /* Store the contents of FROMVAL into the location of TOVAL. Return a new value with the location of TOVAL and contents of FROMVAL. */ diff --git a/gdb/value.h b/gdb/value.h index d51567eeaa5..d2eb091ef5c 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -374,6 +374,17 @@ extern int value_bytes_available (const struct value *value, extern void mark_value_bytes_unavailable (struct value *value, int offset, int length); +/* Read LENGTH bytes of memory starting at MEMADDR into BUFFER, which + is (or will be copied to) VAL's contents buffer offset by + EMBEDDED_OFFSET (that is, to &VAL->contents[EMBEDDED_OFFSET]). + Marks value contents ranges as unavailable if the corresponding + memory is likewise unavailable. STACK indicates whether the memory + is known to be stack memory. */ + +extern void read_value_memory (struct value *val, int offset, + int stack, CORE_ADDR memaddr, + gdb_byte *buffer, size_t length); + #include "symtab.h"