From 4fa62494657f9b422edd7049c7207bd6c6849c3f Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Wed, 3 Jun 2009 18:16:44 +0000 Subject: [PATCH] * value.h (struct internalvar): Remove. (get_internalvar_integer): Add prototype. (set_internalvar_integer): Add prototype. (clear_internalvar): Add prototype. * value.c (struct internalvar): Move here. Add type member. Remove endian member. Add union_internalvar member instead of value member. (init_if_undefined_command): Use intvar->type. (create_internalvar): Do not initialize value/endian, but type. (create_internalvar_type_lazy): Call create_internalvar. (value_of_internalvar): Handle host-side internalvar contents. (set_internalvar_component): Likewise. (set_internalvar): Likewise. (get_internalvar_integer): New function. (clear_internalvar): Likewise. (set_internalvar_integer): Likewise. (preserve_values): Handle host-side internalvar contents. * breakpoint.c (set_breakpoint_count, set_tracepoint_count): Call set_internalvar_integer instead of set_internalvar. * findcmd.c (find_command): Likewise. * infrun.c (handle_inferior_event): Likewise. * source.c (forward_search_command, reverse_search_command): Likewise. * tracepoint.c (set_traceframe_num, set_tracepoint_num, set_traceframe_context): Likewise. * printcmd.c (x_command): Call clear_internalvar instead of set_internalvar. * tracepoint.c (set_traceframe_context): Likewise. * breakpoint.c (get_number_trailer): Call get_internalvar_integer instead of value_of_internalvar. * linespec.c (decode_dollar): Likewise. * expprint.c (dump_subexp_body_standard): Use internalvar_name instead of accessing internalvar private elements. * valops.c (value_assign): Copy from original source instead of accessing internalvar private elements. --- gdb/ChangeLog | 41 +++++++ gdb/breakpoint.c | 13 +- gdb/expprint.c | 2 +- gdb/findcmd.c | 4 +- gdb/infrun.c | 5 +- gdb/linespec.c | 13 +- gdb/printcmd.c | 3 +- gdb/source.c | 8 +- gdb/tracepoint.c | 35 ++---- gdb/valops.c | 2 +- gdb/value.c | 310 +++++++++++++++++++++++++++++++++-------------- gdb/value.h | 25 ++-- 12 files changed, 304 insertions(+), 157 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 378619513d..11bf9cac27 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,44 @@ +2009-06-03 Ulrich Weigand + + * value.h (struct internalvar): Remove. + (get_internalvar_integer): Add prototype. + (set_internalvar_integer): Add prototype. + (clear_internalvar): Add prototype. + + * value.c (struct internalvar): Move here. Add type member. Remove + endian member. Add union_internalvar member instead of value member. + (init_if_undefined_command): Use intvar->type. + (create_internalvar): Do not initialize value/endian, but type. + (create_internalvar_type_lazy): Call create_internalvar. + (value_of_internalvar): Handle host-side internalvar contents. + (set_internalvar_component): Likewise. + (set_internalvar): Likewise. + (get_internalvar_integer): New function. + (clear_internalvar): Likewise. + (set_internalvar_integer): Likewise. + (preserve_values): Handle host-side internalvar contents. + + * breakpoint.c (set_breakpoint_count, set_tracepoint_count): Call + set_internalvar_integer instead of set_internalvar. + * findcmd.c (find_command): Likewise. + * infrun.c (handle_inferior_event): Likewise. + * source.c (forward_search_command, reverse_search_command): Likewise. + * tracepoint.c (set_traceframe_num, set_tracepoint_num, + set_traceframe_context): Likewise. + + * printcmd.c (x_command): Call clear_internalvar instead of + set_internalvar. + * tracepoint.c (set_traceframe_context): Likewise. + + * breakpoint.c (get_number_trailer): Call get_internalvar_integer + instead of value_of_internalvar. + * linespec.c (decode_dollar): Likewise. + + * expprint.c (dump_subexp_body_standard): Use internalvar_name + instead of accessing internalvar private elements. + * valops.c (value_assign): Copy from original source instead of + accessing internalvar private elements. + 2009-06-03 Ulrich Weigand * scm-lang.c (builtin_type_scm): Remove. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 8b2d55e35b..bccfc787b6 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -368,8 +368,7 @@ void set_breakpoint_count (int num) { breakpoint_count = num; - set_internalvar (lookup_internalvar ("bpnum"), - value_from_longest (builtin_type_int32, (LONGEST) num)); + set_internalvar_integer (lookup_internalvar ("bpnum"), num); } /* Used in run_command to zero the hit count when a new run starts. */ @@ -421,16 +420,15 @@ get_number_trailer (char **pp, int trailer) to pass to lookup_internalvar(). */ char *varname; char *start = ++p; - struct value *val; + LONGEST val; while (isalnum (*p) || *p == '_') p++; varname = (char *) alloca (p - start + 1); strncpy (varname, start, p - start); varname[p - start] = '\0'; - val = value_of_internalvar (lookup_internalvar (varname)); - if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT) - retval = (int) value_as_long (val); + if (get_internalvar_integer (lookup_internalvar (varname), &val)) + retval = (int) val; else { printf_filtered (_("Convenience variable must have integer value.\n")); @@ -8275,8 +8273,7 @@ static void set_tracepoint_count (int num) { tracepoint_count = num; - set_internalvar (lookup_internalvar ("tpnum"), - value_from_longest (builtin_type_int32, (LONGEST) num)); + set_internalvar_integer (lookup_internalvar ("tpnum"), num); } void diff --git a/gdb/expprint.c b/gdb/expprint.c index 6048a387e6..e83d1011ab 100644 --- a/gdb/expprint.c +++ b/gdb/expprint.c @@ -1002,7 +1002,7 @@ dump_subexp_body_standard (struct expression *exp, fprintf_filtered (stream, "Internal var @"); gdb_print_host_address (exp->elts[elt].internalvar, stream); fprintf_filtered (stream, " (%s)", - exp->elts[elt].internalvar->name); + internalvar_name (exp->elts[elt].internalvar)); elt += 2; break; case OP_FUNCALL: diff --git a/gdb/findcmd.c b/gdb/findcmd.c index 7ae43e5dc5..09d93fced1 100644 --- a/gdb/findcmd.c +++ b/gdb/findcmd.c @@ -291,9 +291,7 @@ find_command (char *args, int from_tty) /* Record and print the results. */ - set_internalvar (lookup_internalvar ("numfound"), - value_from_longest (builtin_type_int32, - (LONGEST) found_count)); + set_internalvar_integer (lookup_internalvar ("numfound"), found_count); if (found_count > 0) { struct gdbarch *gdbarch = current_gdbarch; diff --git a/gdb/infrun.c b/gdb/infrun.c index 9b302bf0b5..3540acf9d7 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -2512,9 +2512,8 @@ handle_inferior_event (struct execution_control_state *ecs) /* Record the exit code in the convenience variable $_exitcode, so that the user can inspect this again later. */ - set_internalvar (lookup_internalvar ("_exitcode"), - value_from_longest (builtin_type_int32, - (LONGEST) ecs->ws.value.integer)); + set_internalvar_integer (lookup_internalvar ("_exitcode"), + (LONGEST) ecs->ws.value.integer); gdb_flush (gdb_stdout); target_mourn_inferior (); singlestep_breakpoints_inserted_p = 0; diff --git a/gdb/linespec.c b/gdb/linespec.c index e2018e6a22..3d0ceed84c 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -1669,7 +1669,7 @@ static struct symtabs_and_lines decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab, char ***canonical, struct symtab *file_symtab) { - struct value *valx; + LONGEST valx; int index = 0; int need_canonical = 0; struct symtabs_and_lines values; @@ -1684,10 +1684,12 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab, if (!*p) /* Reached end of token without hitting non-digit. */ { /* We have a value history reference. */ + struct value *val_history; sscanf ((copy[1] == '$') ? copy + 2 : copy + 1, "%d", &index); - valx = access_value_history ((copy[1] == '$') ? -index : index); - if (TYPE_CODE (value_type (valx)) != TYPE_CODE_INT) + val_history = access_value_history ((copy[1] == '$') ? -index : index); + if (TYPE_CODE (value_type (val_history)) != TYPE_CODE_INT) error (_("History values used in line specs must have integer values.")); + valx = value_as_long (val_history); } else { @@ -1709,8 +1711,7 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab, return minsym_found (funfirstline, msymbol); /* Not a user variable or function -- must be convenience variable. */ - valx = value_of_internalvar (lookup_internalvar (copy + 1)); - if (TYPE_CODE (value_type (valx)) != TYPE_CODE_INT) + if (!get_internalvar_integer (lookup_internalvar (copy + 1), &valx)) error (_("Convenience variables used in line specs must have integer values.")); } @@ -1718,7 +1719,7 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab, /* Either history value or convenience value from above, in valx. */ val.symtab = file_symtab ? file_symtab : default_symtab; - val.line = value_as_long (valx); + val.line = valx; val.pc = 0; values.sals = (struct symtab_and_line *) xmalloc (sizeof val); diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 4cb681f4fe..b0d7a171ad 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -1369,8 +1369,7 @@ x_command (char *exp, int from_tty) then don't fetch it now; instead mark it by voiding the $__ variable. */ if (value_lazy (last_examine_value)) - set_internalvar (lookup_internalvar ("__"), - allocate_value (builtin_type_void)); + clear_internalvar (lookup_internalvar ("__")); else set_internalvar (lookup_internalvar ("__"), last_examine_value); } diff --git a/gdb/source.c b/gdb/source.c index e1bbb7f529..e4766167b6 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -1615,9 +1615,7 @@ forward_search_command (char *regex, int from_tty) /* Match! */ fclose (stream); print_source_lines (current_source_symtab, line, line + 1, 0); - set_internalvar (lookup_internalvar ("_"), - value_from_longest (builtin_type_int32, - (LONGEST) line)); + set_internalvar_integer (lookup_internalvar ("_"), line); current_source_line = max (line - lines_to_list / 2, 1); return; } @@ -1695,9 +1693,7 @@ reverse_search_command (char *regex, int from_tty) /* Match! */ fclose (stream); print_source_lines (current_source_symtab, line, line + 1, 0); - set_internalvar (lookup_internalvar ("_"), - value_from_longest (builtin_type_int32, - (LONGEST) line)); + set_internalvar_integer (lookup_internalvar ("_"), line); current_source_line = max (line - lines_to_list / 2, 1); return; } diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 31c5f4ae15..fb686e145e 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -208,8 +208,7 @@ static void set_traceframe_num (int num) { traceframe_number = num; - set_internalvar (lookup_internalvar ("trace_frame"), - value_from_longest (builtin_type_int32, (LONGEST) num)); + set_internalvar_integer (lookup_internalvar ("trace_frame"), num); } /* Set tracepoint number to NUM. */ @@ -217,8 +216,7 @@ static void set_tracepoint_num (int num) { tracepoint_number = num; - set_internalvar (lookup_internalvar ("tracepoint"), - value_from_longest (builtin_type_int32, (LONGEST) num)); + set_internalvar_integer (lookup_internalvar ("tracepoint"), num); } /* Set externally visible debug variables for querying/printing @@ -240,13 +238,9 @@ set_traceframe_context (struct frame_info *trace_frame) traceframe_fun = 0; traceframe_sal.pc = traceframe_sal.line = 0; traceframe_sal.symtab = NULL; - set_internalvar (lookup_internalvar ("trace_func"), - allocate_value (builtin_type_void)); - set_internalvar (lookup_internalvar ("trace_file"), - allocate_value (builtin_type_void)); - set_internalvar (lookup_internalvar ("trace_line"), - value_from_longest (builtin_type_int32, - (LONGEST) - 1)); + clear_internalvar (lookup_internalvar ("trace_func")); + clear_internalvar (lookup_internalvar ("trace_file")); + set_internalvar_integer (lookup_internalvar ("trace_line"), -1); return; } @@ -257,16 +251,14 @@ set_traceframe_context (struct frame_info *trace_frame) /* Save linenumber as "$trace_line", a debugger variable visible to users. */ - set_internalvar (lookup_internalvar ("trace_line"), - value_from_longest (builtin_type_int32, - (LONGEST) traceframe_sal.line)); + set_internalvar_integer (lookup_internalvar ("trace_line"), + traceframe_sal.line); /* Save func name as "$trace_func", a debugger variable visible to users. */ - if (traceframe_fun == NULL || - SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL) - set_internalvar (lookup_internalvar ("trace_func"), - allocate_value (builtin_type_void)); + if (traceframe_fun == NULL + || SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL) + clear_internalvar (lookup_internalvar ("trace_func")); else { len = strlen (SYMBOL_LINKAGE_NAME (traceframe_fun)); @@ -285,10 +277,9 @@ set_traceframe_context (struct frame_info *trace_frame) /* Save file name as "$trace_file", a debugger variable visible to users. */ - if (traceframe_sal.symtab == NULL || - traceframe_sal.symtab->filename == NULL) - set_internalvar (lookup_internalvar ("trace_file"), - allocate_value (builtin_type_void)); + if (traceframe_sal.symtab == NULL + || traceframe_sal.symtab->filename == NULL) + clear_internalvar (lookup_internalvar ("trace_file")); else { len = strlen (traceframe_sal.symtab->filename); diff --git a/gdb/valops.c b/gdb/valops.c index f06d32c369..5907d96116 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -774,7 +774,7 @@ value_assign (struct value *toval, struct value *fromval) { case lval_internalvar: set_internalvar (VALUE_INTERNALVAR (toval), fromval); - val = value_copy (VALUE_INTERNALVAR (toval)->value); + val = value_copy (fromval); val = value_change_enclosing_type (val, value_enclosing_type (fromval)); set_value_embedded_offset (val, value_embedded_offset (fromval)); diff --git a/gdb/value.c b/gdb/value.c index 215ead54bd..e9dfe6ab86 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -878,6 +878,32 @@ show_values (char *num_exp, int from_tty) The user refers to them with a '$' prefix that does not appear in the variable names stored internally. */ +struct internalvar +{ + struct internalvar *next; + char *name; + struct type *type; + + /* True if this internalvar is the canonical name for a convenience + function. */ + int canonical; + + /* 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; + + /* 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; + } u; +}; + static struct internalvar *internalvars; /* If the variable does not already exist create it and give it the value given. @@ -906,7 +932,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 (value_type (intvar->value)) == TYPE_CODE_VOID) + if (TYPE_CODE (intvar->type) == TYPE_CODE_VOID) evaluate_expression (expr); do_cleanups (old_chain); @@ -941,11 +967,9 @@ create_internalvar (const char *name) struct internalvar *var; var = (struct internalvar *) xmalloc (sizeof (struct internalvar)); var->name = concat (name, (char *)NULL); - var->value = allocate_value (builtin_type_void); - var->endian = gdbarch_byte_order (current_gdbarch); + var->type = builtin_type_void; var->make_value = NULL; var->canonical = 0; - release_value (var->value); var->next = internalvars; internalvars = var; return var; @@ -959,14 +983,8 @@ create_internalvar (const char *name) struct internalvar * create_internalvar_type_lazy (char *name, internalvar_make_value fun) { - struct internalvar *var; - var = (struct internalvar *) xmalloc (sizeof (struct internalvar)); - var->name = concat (name, (char *)NULL); - var->value = NULL; + struct internalvar *var = create_internalvar (name); var->make_value = fun; - var->endian = gdbarch_byte_order (current_gdbarch); - var->next = internalvars; - internalvars = var; return var; } @@ -992,14 +1010,31 @@ struct value * value_of_internalvar (struct internalvar *var) { struct value *val; - int i, j; - gdb_byte temp; if (var->make_value != NULL) val = (*var->make_value) (var); else { - val = value_copy (var->value); + switch (TYPE_CODE (var->type)) + { + case TYPE_CODE_VOID: + case TYPE_CODE_INTERNAL_FUNCTION: + val = allocate_value (var->type); + break; + + case TYPE_CODE_INT: + val = value_from_longest (var->type, var->u.l); + break; + + case TYPE_CODE_PTR: + val = value_from_pointer (var->type, var->u.a); + break; + + default: + val = value_copy (var->u.v); + break; + } + if (value_lazy (val)) value_fetch_lazy (val); @@ -1013,127 +1048,210 @@ value_of_internalvar (struct internalvar *var) 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 + if (val->lval != lval_computed) { 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 - need to worry about it. + return val; +} - However, internal variables can be set up before the target endian is - known and so may become out of date. Fix it up before anybody sees. +int +get_internalvar_integer (struct internalvar *var, LONGEST *result) +{ + switch (TYPE_CODE (var->type)) + { + case TYPE_CODE_INT: + *result = var->u.l; + return 1; - Internal variables usually hold simple scalar values, and we can - correct those. More complex values (e.g. structures and floating - point types) are left alone, because they would be too complicated - to correct. */ + default: + return 0; + } +} - if (var->endian != gdbarch_byte_order (current_gdbarch)) +static int +get_internalvar_function (struct internalvar *var, + struct internal_function **result) +{ + switch (TYPE_CODE (var->type)) { - gdb_byte *array = value_contents_raw (val); - struct type *type = check_typedef (value_enclosing_type (val)); - switch (TYPE_CODE (type)) - { - case TYPE_CODE_INT: - case TYPE_CODE_PTR: - /* Reverse the bytes. */ - for (i = 0, j = TYPE_LENGTH (type) - 1; i < j; i++, j--) - { - temp = array[j]; - array[j] = array[i]; - array[i] = temp; - } - break; - } - } + case TYPE_CODE_INTERNAL_FUNCTION: + *result = var->u.f; + return 1; - return val; + default: + return 0; + } } void set_internalvar_component (struct internalvar *var, int offset, int bitpos, int bitsize, struct value *newval) { - gdb_byte *addr = value_contents_writeable (var->value) + offset; + gdb_byte *addr; - if (bitsize) - modify_field (addr, value_as_long (newval), - bitpos, bitsize); - else - memcpy (addr, value_contents (newval), TYPE_LENGTH (value_type (newval))); + switch (TYPE_CODE (var->type)) + { + 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); + + if (bitsize) + modify_field (addr + offset, + value_as_long (newval), bitpos, bitsize); + else + memcpy (addr + offset, value_contents (newval), + TYPE_LENGTH (value_type (newval))); + break; + } } void set_internalvar (struct internalvar *var, struct value *val) { - struct value *newval; + struct type *new_type = check_typedef (value_type (val)); + union internalvar_data new_data = { 0 }; if (var->canonical) error (_("Cannot overwrite convenience function %s"), var->name); - newval = value_copy (val); - newval->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 (newval)) - value_fetch_lazy (newval); - - /* Begin code which must not call error(). If var->value points to - something free'd, an error() obviously leaves a dangling pointer. - But we also get a dangling pointer if var->value points to - something in the value chain (i.e., before release_value is - called), because after the error free_all_values will get called before - long. */ - value_free (var->value); - var->value = newval; - var->endian = gdbarch_byte_order (current_gdbarch); - release_value (newval); + /* Prepare new contents. */ + switch (TYPE_CODE (new_type)) + { + case TYPE_CODE_VOID: + break; + + case TYPE_CODE_INTERNAL_FUNCTION: + gdb_assert (VALUE_LVAL (val) == lval_internalvar); + get_internalvar_function (VALUE_INTERNALVAR (val), &new_data.f); + break; + + case TYPE_CODE_INT: + new_data.l = value_as_long (val); + break; + + case TYPE_CODE_PTR: + new_data.a = value_as_address (val); + break; + + default: + new_data.v = value_copy (val); + new_data.v->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); + + /* 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); + break; + } + + /* Clean up old contents. */ + clear_internalvar (var); + + /* Switch over. */ + var->type = new_type; + var->u = new_data; /* End code which must not call error(). */ } +void +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; +} + +static void +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; +} + +void +clear_internalvar (struct internalvar *var) +{ + /* Clean up old contents. */ + switch (TYPE_CODE (var->type)) + { + case TYPE_CODE_VOID: + case TYPE_CODE_INTERNAL_FUNCTION: + case TYPE_CODE_INT: + case TYPE_CODE_PTR: + break; + + default: + value_free (var->u.v); + break; + } + + /* Set to void type. */ + var->type = builtin_type_void; +} + char * internalvar_name (struct internalvar *var) { return var->name; } -static struct value * -value_create_internal_function (const char *name, - internal_function_fn handler, - void *cookie) +static struct internal_function * +create_internal_function (const char *name, + internal_function_fn handler, void *cookie) { - struct value *result = allocate_value (internal_fn_type); - gdb_byte *addr = value_contents_writeable (result); - struct internal_function **fnp = (struct internal_function **) addr; struct internal_function *ifn = XNEW (struct internal_function); ifn->name = xstrdup (name); ifn->handler = handler; ifn->cookie = cookie; - *fnp = ifn; - return result; + return ifn; } char * value_internal_function_name (struct value *val) { - gdb_byte *addr = value_contents_writeable (val); - struct internal_function *ifn = * (struct internal_function **) addr; + struct internal_function *ifn; + int result; + + gdb_assert (VALUE_LVAL (val) == lval_internalvar); + result = get_internalvar_function (VALUE_INTERNALVAR (val), &ifn); + gdb_assert (result); + return ifn->name; } struct value * call_internal_function (struct value *func, int argc, struct value **argv) { - gdb_byte *addr = value_contents_writeable (func); - struct internal_function *ifn = * (struct internal_function **) addr; + struct internal_function *ifn; + int result; + + gdb_assert (VALUE_LVAL (func) == lval_internalvar); + result = get_internalvar_function (VALUE_INTERNALVAR (func), &ifn); + gdb_assert (result); + return (*ifn->handler) (ifn->cookie, argc, argv); } @@ -1165,9 +1283,11 @@ add_internal_function (const char *name, const char *doc, internal_function_fn handler, void *cookie) { struct cmd_list_element *cmd; + struct internal_function *ifn; struct internalvar *var = lookup_internalvar (name); - struct value *fnval = value_create_internal_function (name, handler, cookie); - set_internalvar (var, fnval); + + 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, @@ -1216,8 +1336,23 @@ preserve_values (struct objfile *objfile) preserve_one_value (cur->values[i], objfile, copied_types); for (var = internalvars; var; var = var->next) - if (var->value) - preserve_one_value (var->value, objfile, copied_types); + { + 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; + } + } for (val = values_in_python; val; val = val->next) preserve_one_value (val, objfile, copied_types); @@ -2067,6 +2202,5 @@ Placeholder command for showing help on convenience functions."), internal_fn_type = alloc_type (NULL); TYPE_CODE (internal_fn_type) = TYPE_CODE_INTERNAL_FUNCTION; - TYPE_LENGTH (internal_fn_type) = sizeof (struct internal_function *); TYPE_NAME (internal_fn_type) = ""; } diff --git a/gdb/value.h b/gdb/value.h index 456c9c86cd..fcff0ad4aa 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -309,23 +309,6 @@ extern struct value *coerce_ref (struct value *value); extern struct value *coerce_array (struct value *value); -/* Internal variables (variables for convenience of use of debugger) - are recorded as a chain of these structures. */ - -typedef struct value * (*internalvar_make_value) (struct internalvar *); - -struct internalvar -{ - struct internalvar *next; - char *name; - struct value *value; - internalvar_make_value make_value; - int endian; - /* True if this internalvar is the canonical name for a convenience - function. */ - int canonical; -}; - #include "symtab.h" @@ -538,8 +521,14 @@ extern struct value *access_value_history (int num); extern struct value *value_of_internalvar (struct internalvar *var); +extern int get_internalvar_integer (struct internalvar *var, LONGEST *l); + extern void set_internalvar (struct internalvar *var, struct value *val); +extern void set_internalvar_integer (struct internalvar *var, LONGEST l); + +extern void clear_internalvar (struct internalvar *var); + extern void set_internalvar_component (struct internalvar *var, int offset, int bitpos, int bitsize, @@ -549,6 +538,8 @@ extern struct internalvar *lookup_only_internalvar (const char *name); extern struct internalvar *create_internalvar (const char *name); +typedef struct value * (*internalvar_make_value) (struct internalvar *); + extern struct internalvar * create_internalvar_type_lazy (char *name, internalvar_make_value fun); -- 2.34.1