2009-02-06  Jim Blandy  <jimb@codesourcery.com>
	    Daniel Jacobowitz  <dan@codesourcery.com>
	    Vladimir Prus  <vladimir@codesourcery.com>
	    Pedro Alves  <pedro@codesourcery.com>

	* defs.h (enum lval_type): New value: lval_computed.
	* value.h (struct lval_funcs): New type.
	(allocate_computed_value, value_computed_funcs)
	(value_computed_closure): New declarations.
	* value.c (struct value): Add a structure to the location union
	for computed lvalues, containing 'funcs' and 'closure' members.
	(allocate_computed_value, value_computed_funcs)
	(value_computed_closure): New functions.
	(value_free): For computed lvalues, call the closure's
	'free_closure' function before freeing the value itself.
	(value_copy): If we're copying an lval_computed value, call the
	closure's 'copy_closure' function.
	(set_value_component_location): If the original value is a
	computed lvalue, then call the closure's 'copy_closure' function.
	(value_of_internalvar): If an internal variable's value is a
	computed lvalue, make retrieving its value produce an equivalent
	computed lvalue.
	* valops.c (value_fetch_lazy): Unlazy computed lvalues by calling
	their read function.
	(value_assign): Assign to computed lvalues by calling their write
	function.

gdb/doc/
2009-02-06  Pedro Alves  <pedro@codesourcery.com>

	* gdbint.texinfo (Values): New chapter.
This commit is contained in:
Pedro Alves 2009-02-06 22:50:52 +00:00
parent 117de6a924
commit 5f5233d48e
7 changed files with 278 additions and 5 deletions

View File

@ -1,3 +1,30 @@
2009-02-06 Jim Blandy <jimb@codesourcery.com>
Daniel Jacobowitz <dan@codesourcery.com>
Vladimir Prus <vladimir@codesourcery.com>
Pedro Alves <pedro@codesourcery.com>
* defs.h (enum lval_type): New value: lval_computed.
* value.h (struct lval_funcs): New type.
(allocate_computed_value, value_computed_funcs)
(value_computed_closure): New declarations.
* value.c (struct value): Add a structure to the location union
for computed lvalues, containing 'funcs' and 'closure' members.
(allocate_computed_value, value_computed_funcs)
(value_computed_closure): New functions.
(value_free): For computed lvalues, call the closure's
'free_closure' function before freeing the value itself.
(value_copy): If we're copying an lval_computed value, call the
closure's 'copy_closure' function.
(set_value_component_location): If the original value is a
computed lvalue, then call the closure's 'copy_closure' function.
(value_of_internalvar): If an internal variable's value is a
computed lvalue, make retrieving its value produce an equivalent
computed lvalue.
* valops.c (value_fetch_lazy): Unlazy computed lvalues by calling
their read function.
(value_assign): Assign to computed lvalues by calling their write
function.
2009-02-06 Pedro Alves <pedro@codesourcery.com>
* linux-nat.c (linux_nat_wait): Adjust.

View File

@ -652,7 +652,10 @@ enum lval_type
/* In a gdb internal variable. */
lval_internalvar,
/* Part of a gdb internal variable (structure field). */
lval_internalvar_component
lval_internalvar_component,
/* Value's bits are fetched and stored using functions provided by
its creator. */
lval_computed
};
/* Control types for commands */

View File

@ -1,3 +1,7 @@
2009-02-06 Pedro Alves <pedro@codesourcery.com>
* gdbint.texinfo (Values): New chapter.
2009-02-06 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Python API): Add entry for Commands In Python.

View File

@ -73,6 +73,7 @@ as the mechanisms that adapt @value{GDBN} to specific hosts and targets.
* Algorithms::
* User Interface::
* libgdb::
* Values::
* Stack Frames::
* Symbol Handling::
* Language Support::
@ -1831,6 +1832,101 @@ the query interface. Each function is parameterized by a @code{ui-out}
builder. The result of the query is constructed using that builder
before the query function returns.
@node Values
@chapter Values
@section Values
@cindex values
@cindex @code{value} structure
@value{GDBN} uses @code{struct value}, or @dfn{values}, as an internal
abstraction for the representation of a variety of inferior objects
and @value{GDBN} convenience objects.
Values have an associated @code{struct type}, that describes a virtual
view of the raw data or object stored in or accessed through the
value.
A value is in addition discriminated by its lvalue-ness, given its
@code{enum lval_type} enumeration type:
@cindex @code{lval_type} enumeration, for values.
@table @code
@item @code{not_lval}
This value is not an lval. It can't be assigned to.
@item @code{lval_memory}
This value represents an object in memory.
@item @code{lval_register}
This value represents an object that lives in a register.
@item @code{lval_internalvar}
Represents the value of an internal variable.
@item @code{lval_internalvar_component}
Represents part of a @value{GDBN} internal variable. E.g., a
structure field.
@cindex computed values
@item @code{lval_computed}
These are ``computed'' values. They allow creating specialized value
objects for specific purposes, all abstracted away from the core value
support code. The creator of such a value writes specialized
functions to handle the reading and writing to/from the value's
backend data, and optionally, a ``copy operator'' and a
``destructor''.
Pointers to these functions are stored in a @code{struct lval_funcs}
instance (declared in @file{value.h}), and passed to the
@code{allocate_computed_value} function, as in the example below.
@smallexample
static void
nil_value_read (struct value *v)
@{
/* This callback reads data from some backend, and stores it in V.
In this case, we always read null data. You'll want to fill in
something more interesting. */
memset (value_contents_all_raw (v),
value_offset (v),
TYPE_LENGTH (value_type (v)));
@}
static void
nil_value_write (struct value *v, struct value *fromval)
@{
/* Takes the data from FROMVAL and stores it in the backend of V. */
to_oblivion (value_contents_all_raw (fromval),
value_offset (v),
TYPE_LENGTH (value_type (fromval)));
@}
static struct lval_funcs nil_value_funcs =
@{
nil_value_read,
nil_value_write
@};
struct value *
make_nil_value (void)
@{
struct type *type;
struct value *v;
type = make_nils_type ();
v = allocate_computed_value (type, &nil_value_funcs, NULL);
return v;
@}
@end smallexample
See the implementation of the @code{$_siginfo} convenience variable in
@file{infrun.c} as a real example use of lval_computed.
@end table
@node Stack Frames
@chapter Stack Frames

View File

@ -727,6 +727,8 @@ value_fetch_lazy (struct value *val)
watchpoints from trying to watch the saved frame pointer. */
value_free_to_mark (mark);
}
else if (VALUE_LVAL (val) == lval_computed)
value_computed_funcs (val)->read (val);
else
internal_error (__FILE__, __LINE__, "Unexpected lazy value type.");
@ -895,7 +897,15 @@ value_assign (struct value *toval, struct value *fromval)
observer_notify_target_changed (&current_target);
break;
}
case lval_computed:
{
struct lval_funcs *funcs = value_computed_funcs (toval);
funcs->write (toval, fromval);
}
break;
default:
error (_("Left operand of assignment is not an lvalue."));
}

View File

@ -63,6 +63,15 @@ struct value
/* Pointer to internal variable. */
struct internalvar *internalvar;
/* If lval == lval_computed, this is a set of function pointers
to use to access and describe the value, and a closure pointer
for them to use. */
struct
{
struct lval_funcs *funcs; /* Functions to call. */
void *closure; /* Closure for those functions to use. */
} computed;
} location;
/* Describes offset of a value within lval of a structure in bytes.
@ -296,6 +305,20 @@ value_remove_from_list (struct value **head, struct value *val)
}
}
struct value *
allocate_computed_value (struct type *type,
struct lval_funcs *funcs,
void *closure)
{
struct value *v = allocate_value (type);
VALUE_LVAL (v) = lval_computed;
v->location.computed.funcs = funcs;
v->location.computed.closure = closure;
set_value_lazy (v, 1);
return v;
}
/* Accessor methods. */
struct value *
@ -458,6 +481,22 @@ set_value_pointed_to_offset (struct value *value, int val)
value->pointed_to_offset = val;
}
struct lval_funcs *
value_computed_funcs (struct value *v)
{
gdb_assert (VALUE_LVAL (v) == lval_computed);
return v->location.computed.funcs;
}
void *
value_computed_closure (struct value *v)
{
gdb_assert (VALUE_LVAL (v) == lval_computed);
return v->location.computed.closure;
}
enum lval_type *
deprecated_value_lval_hack (struct value *value)
{
@ -512,7 +551,17 @@ void
value_free (struct value *val)
{
if (val)
xfree (val->contents);
{
if (VALUE_LVAL (val) == lval_computed)
{
struct lval_funcs *funcs = val->location.computed.funcs;
if (funcs->free_closure)
funcs->free_closure (val);
}
xfree (val->contents);
}
xfree (val);
}
@ -625,6 +674,13 @@ value_copy (struct value *arg)
TYPE_LENGTH (value_enclosing_type (arg)));
}
if (VALUE_LVAL (val) == lval_computed)
{
struct lval_funcs *funcs = val->location.computed.funcs;
if (funcs->copy_closure)
val->location.computed.closure = funcs->copy_closure (val);
}
return val;
}
@ -635,7 +691,15 @@ set_value_component_location (struct value *component, struct value *whole)
VALUE_LVAL (component) = lval_internalvar_component;
else
VALUE_LVAL (component) = VALUE_LVAL (whole);
component->location = whole->location;
if (VALUE_LVAL (whole) == lval_computed)
{
struct lval_funcs *funcs = whole->location.computed.funcs;
if (funcs->copy_closure)
component->location.computed.closure = funcs->copy_closure (whole);
}
}
@ -872,8 +936,23 @@ value_of_internalvar (struct internalvar *var)
val = value_copy (var->value);
if (value_lazy (val))
value_fetch_lazy (val);
VALUE_LVAL (val) = lval_internalvar;
VALUE_INTERNALVAR (val) = var;
/* If the variable's value is a computed lvalue, we want references
to it to produce another computed lvalue, where referencces and
assignments actually operate through the computed value's
functions.
This means that internal variables with computed values behave a
little differently from other internal variables: assignments to
them don't just replace the previous value altogether. At the
moment, this seems like the behavior we want. */
if (var->value->lval == lval_computed)
VALUE_LVAL (val) = lval_computed;
else
{
VALUE_LVAL (val) = lval_internalvar;
VALUE_INTERNALVAR (val) = var;
}
/* Values are always stored in the target's byte order. When connected to a
target this will most likely always be correct, so there's normally no

View File

@ -142,6 +142,60 @@ extern void set_value_pointed_to_offset (struct value *value, int val);
extern int value_embedded_offset (struct value *value);
extern void set_value_embedded_offset (struct value *value, int val);
/* For lval_computed values, this structure holds functions used to
retrieve and set the value (or portions of the value).
For each function, 'V' is the 'this' pointer: an lval_funcs
function F may always assume that the V it receives is an
lval_computed value, and has F in the appropriate slot of its
lval_funcs structure. */
struct lval_funcs
{
/* Fill in VALUE's contents. This is used to "un-lazy" values. If
a problem arises in obtaining VALUE's bits, this function should
call 'error'. */
void (*read) (struct value *v);
/* Handle an assignment TOVAL = FROMVAL by writing the value of
FROMVAL to TOVAL's location. The contents of TOVAL have not yet
been updated. If a problem arises in doing so, this function
should call 'error'. */
void (*write) (struct value *toval, struct value *fromval);
/* Return a duplicate of VALUE's closure, for use in a new value.
This may simply return the same closure, if VALUE's is
reference-counted or statically allocated.
This may be NULL, in which case VALUE's closure is re-used in the
new value. */
void *(*copy_closure) (struct value *v);
/* Drop VALUE's reference to its closure. Maybe this frees the
closure; maybe this decrements a reference count; maybe the
closure is statically allocated and this does nothing.
This may be NULL, in which case no action is taken to free
VALUE's closure. */
void (*free_closure) (struct value *v);
};
/* Create a computed lvalue, with type TYPE, function pointers FUNCS,
and closure CLOSURE. */
extern struct value *allocate_computed_value (struct type *type,
struct lval_funcs *funcs,
void *closure);
/* If VALUE is lval_computed, return its lval_funcs structure. */
extern struct lval_funcs *value_computed_funcs (struct value *value);
/* If VALUE is lval_computed, return its closure. The meaning of the
returned value depends on the functions VALUE uses. */
extern void *value_computed_closure (struct value *value);
/* If zero, contents of this value are in the contents field. If
nonzero, contents are in inferior. If the lval field is lval_memory,
the contents are in inferior memory at location.address plus offset.