From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9613 invoked by alias); 7 Feb 2011 14:29:57 -0000 Received: (qmail 9590 invoked by uid 22791); 7 Feb 2011 14:29:53 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL,BAYES_00,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 07 Feb 2011 14:29:46 +0000 Received: (qmail 24607 invoked from network); 7 Feb 2011 14:29:44 -0000 Received: from unknown (HELO scottsdale.localnet) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 7 Feb 2011 14:29:44 -0000 To: gdb-patches@sourceware.org Subject: [unavailable values part 1, 04/17] map unavailable memory to unavailable value contents From: Pedro Alves Date: Mon, 07 Feb 2011 14:29:00 -0000 MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Message-Id: <201102071429.40838.pedro@codesourcery.com> X-IsSubscribed: yes 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 X-SW-Source: 2011-02/txt/msg00135.txt.bz2 In places where we read memory from the target to fill in a value's contents, instead, use a new read_value_memory function, that knows to mark the chunks of the value's contents that correspond to unavailable memory, as unavailable. The set of available memory is that returned by the new traceframe_available_memory function, unioned with the memory ranges defined by the read-only (bfd) sections. With this patch, not collected scalars and plain old data structures that live in memory are already shown as unavailable. E.g., with struct tuple { int a; int b; }; struct foo_s { int a, b; int array[10000]; struct tuple tarray[6]; void *ptr; int ss:1; }; struct foo2_s { int d, ef; struct foo_s foo; int s:1; static struct foo_s sfoo; const char *string; }; all memset to 0xaa, and a tracepoint with: actions collect foo2.foo.array[0] collect foo2.foo.tarray[0].a collect foo2.foo.tarray[1].a collect foo2.foo.tarray[4].b collect foo2.foo.tarray[5].b end tstart One gets: (gdb) p /x foo2 $2 = {d = , ef = , foo = {a = , b = , array = {0xaaaaaaaa, }, tarray = {{a = 0xaaaaaaaa, b = }, {a = 0xaaaaaaaa, b = }, {a = , b = }, {a = , b = }, { a = , b = 0xaaaaaaaa}, {a = , b = 0xaaaaaaaa}}, ptr = , ss = 0x0}, s = 0x0, static sfoo = {a = , b = , array = { }, tarray = {{a = , b = }, {a = , b = }, {a = , b = }, {a = , b = }, {a = , b = }, { a = , b = }}, ptr = , ss = 0x0}, string = } The sharp eye will notice there's a couple of 0x0's above. Those are bitfields, which require further fixing. Tests for all this functionality will be added later in the series (patch 12), after this and a bunch of other cases have been fixed to handle unavailable-ness. -- Pedro Alves 2011-02-07 Pedro Alves 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/dwarf2loc.c | 8 ++-- gdb/exec.c | 37 ++++++++++++++++++++++ gdb/exec.h | 12 +++++++ gdb/valops.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++----- gdb/value.h | 11 ++++++ 5 files changed, 150 insertions(+), 11 deletions(-) Index: src/gdb/valops.c =================================================================== --- src.orig/gdb/valops.c 2011-02-02 18:58:36.337899006 +0000 +++ src/gdb/valops.c 2011-02-07 11:15:02.926705996 +0000 @@ -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. */ Index: src/gdb/value.h =================================================================== --- src.orig/gdb/value.h 2011-02-07 11:12:35.406706000 +0000 +++ src/gdb/value.h 2011-02-07 11:15:02.926705996 +0000 @@ -374,6 +374,17 @@ extern int value_bytes_available (const 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" Index: src/gdb/dwarf2loc.c =================================================================== --- src.orig/gdb/dwarf2loc.c 2011-02-02 18:58:36.337899006 +0000 +++ src/gdb/dwarf2loc.c 2011-02-07 11:15:02.946706002 +0000 @@ -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: Index: src/gdb/exec.c =================================================================== --- src.orig/gdb/exec.c 2011-02-02 18:58:36.337899006 +0000 +++ src/gdb/exec.c 2011-02-07 11:15:03.046706003 +0000 @@ -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, Index: src/gdb/exec.h =================================================================== --- src.orig/gdb/exec.h 2011-02-02 18:58:36.337899006 +0000 +++ src/gdb/exec.h 2011-02-07 11:15:03.046706003 +0000 @@ -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 b 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