aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog13
-rw-r--r--gdb/dwarf2loc.c8
-rw-r--r--gdb/exec.c37
-rw-r--r--gdb/exec.h12
-rw-r--r--gdb/valops.c93
-rw-r--r--gdb/value.h11
6 files changed, 163 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index df7e871..1fd5b02 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,18 @@
2011-02-14 Pedro Alves <pedro@codesourcery.com>
+ 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 <pedro@codesourcery.com>
+
* Makefile.in (SFILES): Add memrange.c.
(HFILES_NO_SRCDIR): Add memrange.h.
(COMMON_OBS): Add memrange.o.
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index d9580c6..0f58954 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 0eea1d7..1cca3b3 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 8af2adf..a8df608 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 24c2269..7fa8729 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 <errno.h>
#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 d51567e..d2eb091 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"