public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [unavailable values part 1, 04/17] map unavailable memory to unavailable value contents
@ 2011-02-07 14:29 Pedro Alves
  2011-02-14 12:00 ` Jan Kratochvil
  0 siblings, 1 reply; 4+ messages in thread
From: Pedro Alves @ 2011-02-07 14:29 UTC (permalink / raw)
  To: gdb-patches

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 = <unavailable>, ef = <unavailable>, foo = {a = <unavailable>, b = <unavailable>, array = {0xaaaaaaaa, 
      <unavailable> <repeats 9999 times>}, tarray = {{a = 0xaaaaaaaa, b = <unavailable>}, {a = 0xaaaaaaaa, 
        b = <unavailable>}, {a = <unavailable>, b = <unavailable>}, {a = <unavailable>, b = <unavailable>}, {
        a = <unavailable>, b = 0xaaaaaaaa}, {a = <unavailable>, b = 0xaaaaaaaa}}, ptr = <unavailable>, ss = 0x0}, 
  s = 0x0, static sfoo = {a = <unavailable>, b = <unavailable>, array = {<unavailable> <repeats 10000 times>}, 
    tarray = {{a = <unavailable>, b = <unavailable>}, {a = <unavailable>, b = <unavailable>}, {a = <unavailable>, 
        b = <unavailable>}, {a = <unavailable>, b = <unavailable>}, {a = <unavailable>, b = <unavailable>}, {
        a = <unavailable>, b = <unavailable>}}, ptr = <unavailable>, ss = 0x0}, string = <unavailable>}

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  <pedro@codesourcery.com>

	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 <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.  */
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);
+
 \f
 
 #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)
 }
 \f
 
+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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [unavailable values part 1, 04/17] map unavailable memory to unavailable value contents
  2011-02-07 14:29 [unavailable values part 1, 04/17] map unavailable memory to unavailable value contents Pedro Alves
@ 2011-02-14 12:00 ` Jan Kratochvil
  2011-02-14 22:14   ` Pedro Alves
  0 siblings, 1 reply; 4+ messages in thread
From: Jan Kratochvil @ 2011-02-14 12:00 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> @@ -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);

I think here should be value_contents_raw.  It is an unrelated issue.


>      }
>    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);

Cannot be table NULL?


> +	  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);
> +


> --- 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);
> +

Comment talks about EMBEDDED_OFFSET while the declaration parameter name does
not match the function definition parameter name.


> @@ -572,6 +572,43 @@ map_vmap (bfd *abfd, bfd *arch)
>  }
>  \f
>  
> +VEC(mem_range_s) *
> +section_table_available_memory (VEC(mem_range_s) *memory,
> +				CORE_ADDR memaddr, LONGEST len,

After `int', `ULONGEST' and `size_t' the type is now `LONGEST'.

Does it mean there is no intention for >2GB inferior objects handling?
I thought some Fortran simulations may use such arrays etc.


> +				struct target_section *sections,
> +				struct target_section *sections_end)
> +{
> +  struct target_section *p;
> +  ULONGEST memend = memaddr + len;

Unused variable `memend'.

> +
> +  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;
> +}


Thanks,
Jan

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [unavailable values part 1, 04/17] map unavailable memory to unavailable value contents
  2011-02-14 12:00 ` Jan Kratochvil
@ 2011-02-14 22:14   ` Pedro Alves
  2011-02-14 22:30     ` Jan Kratochvil
  0 siblings, 1 reply; 4+ messages in thread
From: Pedro Alves @ 2011-02-14 22:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Jan Kratochvil

On Monday 14 February 2011 12:00:00, Jan Kratochvil wrote:

> > +	  /* Fallback to reading from read-only sections.  */
> > +	  table = target_get_section_table (&exec_ops);
> 
> Cannot be table NULL?

The exec target always returns a non-NULL table.  It may
be empty though (sections == sections_end).

> > +	  available_memory =
> > +	    section_table_available_memory (available_memory,
> > +					    memaddr, length,
> > +					    table->sections,
> > +					    table->sections_end);
> > +

> >  
> > +/* 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);
> > +
> 
> Comment talks about EMBEDDED_OFFSET while the declaration parameter name does
> not match the function definition parameter name.

Thanks.  I've renamed s/offset/embedded_offset in the declaration.

> 
> 
> > @@ -572,6 +572,43 @@ map_vmap (bfd *abfd, bfd *arch)
> >  }
> >  \f
> >  
> > +VEC(mem_range_s) *
> > +section_table_available_memory (VEC(mem_range_s) *memory,
> > +				CORE_ADDR memaddr, LONGEST len,
> 
> After `int', `ULONGEST' and `size_t' the type is now `LONGEST'.
> 
> Does it mean there is no intention for >2GB inferior objects handling?
> I thought some Fortran simulations may use such arrays etc.

I think these parameters are the least of your troubles,
given than you'll need to fix at least all the struct value
related code for that.  Made it a ULONGEST.

> Unused variable `memend'.

Deleted.

I checked in the patch below.  Thanks!

-- 
Pedro Alves

2011-02-14  Pedro Alves  <pedro@codesourcery.com>
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

	gdb/
	* exec.c (section_table_available_memory): Change `len' parameter
	type to ULONGEST.
	* exec.h (section_table_available_memory): Ditto.
	* value.h (read_value_memory): Rename the `offset' parameter to
	`embedded_offset'.

---
 gdb/exec.c  |    3 +--
 gdb/exec.h  |    2 +-
 gdb/value.h |    2 +-
 3 files changed, 3 insertions(+), 4 deletions(-)

Index: src/gdb/exec.c
===================================================================
--- src.orig/gdb/exec.c	2011-02-14 11:20:34.000000000 +0000
+++ src/gdb/exec.c	2011-02-14 21:54:43.843995012 +0000
@@ -574,12 +574,11 @@ map_vmap (bfd *abfd, bfd *arch)
 
 VEC(mem_range_s) *
 section_table_available_memory (VEC(mem_range_s) *memory,
-				CORE_ADDR memaddr, LONGEST len,
+				CORE_ADDR memaddr, ULONGEST 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++)
     {
Index: src/gdb/exec.h
===================================================================
--- src.orig/gdb/exec.h	2011-02-14 11:20:34.000000000 +0000
+++ src/gdb/exec.h	2011-02-14 21:53:45.573994995 +0000
@@ -52,7 +52,7 @@ extern int resize_section_table (struct
 
 extern VEC(mem_range_s) *
   section_table_available_memory (VEC(mem_range_s) *ranges,
-				  CORE_ADDR memaddr, LONGEST len,
+				  CORE_ADDR memaddr, ULONGEST len,
 				  struct target_section *sections,
 				  struct target_section *sections_end);
 
Index: src/gdb/value.h
===================================================================
--- src.orig/gdb/value.h	2011-02-14 11:32:21.000000000 +0000
+++ src/gdb/value.h	2011-02-14 21:51:17.783995011 +0000
@@ -410,7 +410,7 @@ extern int value_available_contents_eq (
    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,
+extern void read_value_memory (struct value *val, int embedded_offset,
 			       int stack, CORE_ADDR memaddr,
 			       gdb_byte *buffer, size_t length);
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [unavailable values part 1, 04/17] map unavailable memory to unavailable value contents
  2011-02-14 22:14   ` Pedro Alves
@ 2011-02-14 22:30     ` Jan Kratochvil
  0 siblings, 0 replies; 4+ messages in thread
From: Jan Kratochvil @ 2011-02-14 22:30 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Mon, 14 Feb 2011 23:11:11 +0100, Pedro Alves wrote:
> On Monday 14 February 2011 12:00:00, Jan Kratochvil wrote:
> > > +	  /* Fallback to reading from read-only sections.  */
> > > +	  table = target_get_section_table (&exec_ops);
> > 
> > Cannot be table NULL?
> 
> The exec target always returns a non-NULL table.  It may
> be empty though (sections == sections_end).

Aha, I see now - due to that `&exec_ops'.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-02-14 22:23 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-07 14:29 [unavailable values part 1, 04/17] map unavailable memory to unavailable value contents Pedro Alves
2011-02-14 12:00 ` Jan Kratochvil
2011-02-14 22:14   ` Pedro Alves
2011-02-14 22:30     ` Jan Kratochvil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).