diff options
Diffstat (limited to 'gdb/value.c')
-rw-r--r-- | gdb/value.c | 330 |
1 files changed, 208 insertions, 122 deletions
diff --git a/gdb/value.c b/gdb/value.c index 7566921..01066e9 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -222,9 +222,6 @@ static struct value_history_chunk *value_history_chain; static int value_history_count; /* Abs number of last entry stored */ -/* The type of internal functions. */ - -static struct type *internal_fn_type; /* List of all value objects currently allocated (except for those released by calls to release_value) @@ -882,25 +879,67 @@ struct internalvar { struct internalvar *next; char *name; - struct type *type; - /* True if this internalvar is the canonical name for a convenience - function. */ - int canonical; + /* We support various different kinds of content of an internal variable. + enum internalvar_kind specifies the kind, and union internalvar_data + provides the data associated with this particular kind. */ + + enum internalvar_kind + { + /* The internal variable is empty. */ + INTERNALVAR_VOID, + + /* The value of the internal variable is provided directly as + a GDB value object. */ + INTERNALVAR_VALUE, + + /* A fresh value is computed via a call-back routine on every + access to the internal variable. */ + INTERNALVAR_MAKE_VALUE, - /* If this function is non-NULL, it is used to compute a fresh value - on every access to the internalvar. */ - internalvar_make_value make_value; + /* The internal variable holds a GDB internal convenience function. */ + INTERNALVAR_FUNCTION, + + /* The variable holds a simple scalar value. */ + INTERNALVAR_SCALAR, + + /* The variable holds a GDB-provided string. */ + INTERNALVAR_STRING, + + } kind; - /* To reduce dependencies on target properties (like byte order) that - may change during the lifetime of an internal variable, we store - simple scalar values as host objects. */ union internalvar_data { - struct value *v; - struct internal_function *f; - LONGEST l; - CORE_ADDR a; + /* A value object used with INTERNALVAR_VALUE. */ + struct value *value; + + /* The call-back routine used with INTERNALVAR_MAKE_VALUE. */ + internalvar_make_value make_value; + + /* The internal function used with INTERNALVAR_FUNCTION. */ + struct + { + struct internal_function *function; + /* True if this is the canonical name for the function. */ + int canonical; + } fn; + + /* A scalar value used with INTERNALVAR_SCALAR. */ + struct + { + /* If type is non-NULL, it will be used as the type to generate + a value for this internal variable. If type is NULL, a default + integer type for the architecture is used. */ + struct type *type; + union + { + LONGEST l; /* Used with TYPE_CODE_INT and NULL types. */ + CORE_ADDR a; /* Used with TYPE_CODE_PTR types. */ + } val; + } scalar; + + /* A string value used with INTERNALVAR_STRING. */ + char *string; } u; }; @@ -932,7 +971,7 @@ init_if_undefined_command (char* args, int from_tty) /* Only evaluate the expression if the lvalue is void. This may still fail if the expresssion is invalid. */ - if (TYPE_CODE (intvar->type) == TYPE_CODE_VOID) + if (intvar->kind == INTERNALVAR_VOID) evaluate_expression (expr); do_cleanups (old_chain); @@ -967,9 +1006,7 @@ create_internalvar (const char *name) struct internalvar *var; var = (struct internalvar *) xmalloc (sizeof (struct internalvar)); var->name = concat (name, (char *)NULL); - var->type = builtin_type_void; - var->make_value = NULL; - var->canonical = 0; + var->kind = INTERNALVAR_VOID; var->next = internalvars; internalvars = var; return var; @@ -984,7 +1021,8 @@ struct internalvar * create_internalvar_type_lazy (char *name, internalvar_make_value fun) { struct internalvar *var = create_internalvar (name); - var->make_value = fun; + var->kind = INTERNALVAR_MAKE_VALUE; + var->u.make_value = fun; return var; } @@ -1006,53 +1044,77 @@ lookup_internalvar (const char *name) return create_internalvar (name); } +/* Return current value of internal variable VAR. For variables that + are not inherently typed, use a value type appropriate for GDBARCH. */ + struct value * -value_of_internalvar (struct internalvar *var) +value_of_internalvar (struct gdbarch *gdbarch, struct internalvar *var) { struct value *val; - if (var->make_value != NULL) - val = (*var->make_value) (var); - else + switch (var->kind) { - switch (TYPE_CODE (var->type)) - { - case TYPE_CODE_VOID: - case TYPE_CODE_INTERNAL_FUNCTION: - val = allocate_value (var->type); - break; + case INTERNALVAR_VOID: + val = allocate_value (builtin_type (gdbarch)->builtin_void); + break; - case TYPE_CODE_INT: - val = value_from_longest (var->type, var->u.l); - break; + case INTERNALVAR_FUNCTION: + val = allocate_value (builtin_type (gdbarch)->internal_fn); + break; - case TYPE_CODE_PTR: - val = value_from_pointer (var->type, var->u.a); - break; + case INTERNALVAR_SCALAR: + if (!var->u.scalar.type) + val = value_from_longest (builtin_type (gdbarch)->builtin_int, + var->u.scalar.val.l); + else if (TYPE_CODE (var->u.scalar.type) == TYPE_CODE_INT) + val = value_from_longest (var->u.scalar.type, var->u.scalar.val.l); + else if (TYPE_CODE (var->u.scalar.type) == TYPE_CODE_PTR) + val = value_from_pointer (var->u.scalar.type, var->u.scalar.val.a); + else + internal_error (__FILE__, __LINE__, "bad type"); + break; - default: - val = value_copy (var->u.v); - break; - } + case INTERNALVAR_STRING: + val = value_cstring (var->u.string, strlen (var->u.string), + builtin_type (gdbarch)->builtin_char); + break; + case INTERNALVAR_VALUE: + val = value_copy (var->u.value); if (value_lazy (val)) value_fetch_lazy (val); + break; - /* 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 (val->lval != lval_computed) - { - VALUE_LVAL (val) = lval_internalvar; - VALUE_INTERNALVAR (val) = var; - } + case INTERNALVAR_MAKE_VALUE: + val = (*var->u.make_value) (gdbarch, var); + break; + + default: + internal_error (__FILE__, __LINE__, "bad kind"); + } + + /* Change the VALUE_LVAL to lval_internalvar so that future operations + on this value go back to affect the original internal variable. + + Do not do this for INTERNALVAR_MAKE_VALUE variables, as those have + no underlying modifyable state in the internal variable. + + Likewise, if the variable's value is a computed lvalue, we want + references to it to produce another computed lvalue, where + references 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->kind != INTERNALVAR_MAKE_VALUE + && val->lval != lval_computed) + { + VALUE_LVAL (val) = lval_internalvar; + VALUE_INTERNALVAR (val) = var; } return val; @@ -1061,11 +1123,16 @@ value_of_internalvar (struct internalvar *var) int get_internalvar_integer (struct internalvar *var, LONGEST *result) { - switch (TYPE_CODE (var->type)) + switch (var->kind) { - case TYPE_CODE_INT: - *result = var->u.l; - return 1; + case INTERNALVAR_SCALAR: + if (var->u.scalar.type == NULL + || TYPE_CODE (var->u.scalar.type) == TYPE_CODE_INT) + { + *result = var->u.scalar.val.l; + return 1; + } + /* Fall through. */ default: return 0; @@ -1076,10 +1143,10 @@ static int get_internalvar_function (struct internalvar *var, struct internal_function **result) { - switch (TYPE_CODE (var->type)) + switch (var->kind) { - case TYPE_CODE_INTERNAL_FUNCTION: - *result = var->u.f; + case INTERNALVAR_FUNCTION: + *result = var->u.fn.function; return 1; default: @@ -1093,17 +1160,10 @@ set_internalvar_component (struct internalvar *var, int offset, int bitpos, { gdb_byte *addr; - switch (TYPE_CODE (var->type)) + switch (var->kind) { - case TYPE_CODE_VOID: - case TYPE_CODE_INTERNAL_FUNCTION: - case TYPE_CODE_INT: - case TYPE_CODE_PTR: - /* We can never get a component of a basic type. */ - internal_error (__FILE__, __LINE__, "set_internalvar_component"); - - default: - addr = value_contents_writeable (var->u.v); + case INTERNALVAR_VALUE: + addr = value_contents_writeable (var->u.value); if (bitsize) modify_field (addr + offset, @@ -1112,52 +1172,65 @@ set_internalvar_component (struct internalvar *var, int offset, int bitpos, memcpy (addr + offset, value_contents (newval), TYPE_LENGTH (value_type (newval))); break; + + default: + /* We can never get a component of any other kind. */ + internal_error (__FILE__, __LINE__, "set_internalvar_component"); } } void set_internalvar (struct internalvar *var, struct value *val) { - struct type *new_type = check_typedef (value_type (val)); + enum internalvar_kind new_kind; union internalvar_data new_data = { 0 }; - if (var->canonical) + if (var->kind == INTERNALVAR_FUNCTION && var->u.fn.canonical) error (_("Cannot overwrite convenience function %s"), var->name); /* Prepare new contents. */ - switch (TYPE_CODE (new_type)) + switch (TYPE_CODE (check_typedef (value_type (val)))) { case TYPE_CODE_VOID: + new_kind = INTERNALVAR_VOID; break; case TYPE_CODE_INTERNAL_FUNCTION: gdb_assert (VALUE_LVAL (val) == lval_internalvar); - get_internalvar_function (VALUE_INTERNALVAR (val), &new_data.f); + new_kind = INTERNALVAR_FUNCTION; + get_internalvar_function (VALUE_INTERNALVAR (val), + &new_data.fn.function); + /* Copies created here are never canonical. */ break; case TYPE_CODE_INT: - new_data.l = value_as_long (val); + new_kind = INTERNALVAR_SCALAR; + new_data.scalar.type = value_type (val); + new_data.scalar.val.l = value_as_long (val); break; case TYPE_CODE_PTR: - new_data.a = value_as_address (val); + new_kind = INTERNALVAR_SCALAR; + new_data.scalar.type = value_type (val); + new_data.scalar.val.a = value_as_address (val); break; default: - new_data.v = value_copy (val); - new_data.v->modifiable = 1; + new_kind = INTERNALVAR_VALUE; + new_data.value = value_copy (val); + new_data.value->modifiable = 1; /* Force the value to be fetched from the target now, to avoid problems later when this internalvar is referenced and the target is gone or has changed. */ - if (value_lazy (new_data.v)) - value_fetch_lazy (new_data.v); + if (value_lazy (new_data.value)) + value_fetch_lazy (new_data.value); /* Release the value from the value chain to prevent it from being deleted by free_all_values. From here on this function should not call error () until new_data is installed into the var->u to avoid leaking memory. */ - release_value (new_data.v); + release_value (new_data.value); break; } @@ -1165,7 +1238,7 @@ set_internalvar (struct internalvar *var, struct value *val) clear_internalvar (var); /* Switch over. */ - var->type = new_type; + var->kind = new_kind; var->u = new_data; /* End code which must not call error(). */ } @@ -1176,9 +1249,19 @@ set_internalvar_integer (struct internalvar *var, LONGEST l) /* Clean up old contents. */ clear_internalvar (var); - /* Use a platform-independent 32-bit integer type. */ - var->type = builtin_type_int32; - var->u.l = l; + var->kind = INTERNALVAR_SCALAR; + var->u.scalar.type = NULL; + var->u.scalar.val.l = l; +} + +void +set_internalvar_string (struct internalvar *var, const char *string) +{ + /* Clean up old contents. */ + clear_internalvar (var); + + var->kind = INTERNALVAR_STRING; + var->u.string = xstrdup (string); } static void @@ -1187,29 +1270,32 @@ set_internalvar_function (struct internalvar *var, struct internal_function *f) /* Clean up old contents. */ clear_internalvar (var); - var->type = internal_fn_type; - var->u.f = f; + var->kind = INTERNALVAR_FUNCTION; + var->u.fn.function = f; + var->u.fn.canonical = 1; + /* Variables installed here are always the canonical version. */ } void clear_internalvar (struct internalvar *var) { /* Clean up old contents. */ - switch (TYPE_CODE (var->type)) + switch (var->kind) { - case TYPE_CODE_VOID: - case TYPE_CODE_INTERNAL_FUNCTION: - case TYPE_CODE_INT: - case TYPE_CODE_PTR: + case INTERNALVAR_VALUE: + value_free (var->u.value); + break; + + case INTERNALVAR_STRING: + xfree (var->u.string); break; default: - value_free (var->u.v); break; } - /* Set to void type. */ - var->type = builtin_type_void; + /* Reset to void kind. */ + var->kind = INTERNALVAR_VOID; } char * @@ -1288,7 +1374,6 @@ add_internal_function (const char *name, const char *doc, ifn = create_internal_function (name, handler, cookie); set_internalvar_function (var, ifn); - var->canonical = 1; cmd = add_cmd (xstrdup (name), no_class, function_command, (char *) doc, &functionlist); @@ -1311,6 +1396,26 @@ preserve_one_value (struct value *value, struct objfile *objfile, copied_types); } +/* Likewise for internal variable VAR. */ + +static void +preserve_one_internalvar (struct internalvar *var, struct objfile *objfile, + htab_t copied_types) +{ + switch (var->kind) + { + case INTERNALVAR_SCALAR: + if (var->u.scalar.type && TYPE_OBJFILE (var->u.scalar.type) == objfile) + var->u.scalar.type + = copy_type_recursive (objfile, var->u.scalar.type, copied_types); + break; + + case INTERNALVAR_VALUE: + preserve_one_value (var->u.value, objfile, copied_types); + break; + } +} + /* Update the internal variables and value history when OBJFILE is discarded; we must copy the types out of the objfile. New global types will be created for every convenience variable which currently points to @@ -1336,23 +1441,7 @@ preserve_values (struct objfile *objfile) preserve_one_value (cur->values[i], objfile, copied_types); for (var = internalvars; var; var = var->next) - { - if (TYPE_OBJFILE (var->type) == objfile) - var->type = copy_type_recursive (objfile, var->type, copied_types); - - switch (TYPE_CODE (var->type)) - { - case TYPE_CODE_VOID: - case TYPE_CODE_INTERNAL_FUNCTION: - case TYPE_CODE_INT: - case TYPE_CODE_PTR: - break; - - default: - preserve_one_value (var->u.v, objfile, copied_types); - break; - } - } + preserve_one_internalvar (var, objfile, copied_types); for (val = values_in_python; val; val = val->next) preserve_one_value (val, objfile, copied_types); @@ -1363,6 +1452,7 @@ preserve_values (struct objfile *objfile) static void show_convenience (char *ignore, int from_tty) { + struct gdbarch *gdbarch = current_gdbarch; struct internalvar *var; int varseen = 0; struct value_print_options opts; @@ -1375,7 +1465,7 @@ show_convenience (char *ignore, int from_tty) varseen = 1; } printf_filtered (("$%s = "), var->name); - value_print (value_of_internalvar (var), gdb_stdout, + value_print (value_of_internalvar (gdbarch, var), gdb_stdout, &opts); printf_filtered (("\n")); } @@ -2172,8 +2262,4 @@ VARIABLE is already initialized.")); add_prefix_cmd ("function", no_class, function_command, _("\ Placeholder command for showing help on convenience functions."), &functionlist, "function ", 0, &cmdlist); - - internal_fn_type = alloc_type (NULL); - TYPE_CODE (internal_fn_type) = TYPE_CODE_INTERNAL_FUNCTION; - TYPE_NAME (internal_fn_type) = "<internal function>"; } |