This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [RFA] resubmit: cached function lookup; strict return type analysis
- From: Michael Snyder <msnyder at redhat dot com>
- To: Klee Dienes <klee at apple dot com>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Thu, 10 Jan 2002 15:32:40 -0800
- Subject: Re: [RFA] resubmit: cached function lookup; strict return type analysis
- Organization: Red Hat, Inc.
- References: <200201082318.SAA28963@department-of-alchemy.mit.edu>
Klee Dienes wrote:
>
> Hi! I sent this a while back (12 December), but hadn't heard anything
> in a bit, so I figured I'd resubmit. I've since updated the patch to
> use the 'struct value *' and 'struct cached_value *' instead of
> 'value_ptr' and 'cached_value_ptr', and updated it to be against the
> most recent source tree, but otherwise it's the same as the patch I
> submitted in December:
Klee, the patch will not apply to my source tree.
Are you sure it doesn't depend on other changes in your tree?
>
> ------------------------------
>
> The following patch overlaps a bit with the previous one (it requires
> the symnbol_generation support), but otherwise it should be
> standalone. I'm mainly submitting it now because it is required by
> some of the Objective-C patches, but is significant enough in it's own
> right that I wanted to address any issues with it separately rather
> than as part of the Objective-C submission.
>
> There are two primary things changed by the patch:
>
> 1) is that functions in the target used by GDB ("malloc",
> "scm_lookup_cstr", and later a ton of Objective-C functions) now have
> their values cached and re-used unless the symbol table has changed
> in-between calls. This is a performance win overall, and a particular
> win when dispatching Objective-C method calls and looking up
> Objective-C type information from the runtime.
>
> 2) is potentially a bit more controversial. It adds "expected return
> type" support to the target function call interface. The "expected
> return type" is specified using cast syntax; it is ignored if actual
> type information for the function is available. If no type
> information is provided for a function, the user is now required to
> provide an expected return type using the cast syntax, or get an
> error.
>
> Some examples:
>
> (gdb) print fabs (3.0) (no type information present)
> Unable to call function at 0x%lx: no return type information available.
> To call this function anyway, you can cast the return type explicitly
> (e.g. 'print (float) fabs (3.0)').
>
> (gdb) print (float) fabs (-3.12) (no type information present)
> $1 = 3.11999989
>
> (gdb) print (int) fabs (-3.12) (no type information present)
> $2 = 1074329026
> (here, the return value of `fabs' has been interpreted as an int
> ... not cast to one)
>
> (gdb) print (int) fabs (-3.12) (type information present)
> $3 = -3
> (since type information was available, the return value was
> interpreted as a float, then cast to an int).
>
> (gdb) print (struct stat) fabs (-3.12) (no type information present)
> Cannot access memory at address 0xf5c28f6
> (this causes an error, since the struct return convention is being
> misused)
>
> struct s { int i; int j; };
> struct s f (void) { struct s ss = { 3, 1 }; return ss; }
>
> (gdb) print f () (no type information present)
> Unable to call function at 0x%lx: no return type information available.
> To call this function anyway, you can cast the return type explicitly
> (e.g. 'print (float) fabs (3.0)').
>
> (gdb) print (struct s) f (3.0) (no type information present)
> $4 = {i = 3, j = 1}
>
> (gdb) print (float) f (3.0) (no type information present)
> Program received signal SIGSEGV, Segmentation fault.
> 0x0804841d in f ()
> (here we lied to GDB about the return type, causing it to generate
> incorrect struct return code).
>
> Compare this to the old behavior:
>
> (gdb) print fabs (3.0) (no type information present)
> $1 = 1074266112
> (GDB has no type information available, so it assumes 'int').
>
> (gdb) print (float) fabs (-3.12) (no type information present)
> $2 = 1.07426611e+09
> (GDB still assumes the function returns 'int', then casts the result
> to a float).
>
> struct s { int i; int j; };
> struct s f (void) { struct s ss = { 3, 1 }; return ss; }
>
> (gdb) print f ()
> Program received signal SIGSEGV, Segmentation fault.
> 0x0804841d in f ()
> (here there is no way out ... no matter what we pass in as the return
> value to f(), GDB will generate the calling convention for a function
> returning int)
>
> The reason I suggest 2) might be controversial is that the old
> behavior can be convenient in the general case. A lot of functions
> *do* return int, and when debugging programs without symbols, it can
> be annoying to have to declare the return type, just to make the rare
> case when functions return floats/structs behave correctly. But I'd
> argue that it's not *that* big a deal to cast a return value, and
> correctness must always take priority.
>
> We've been using a variant of this patch at Apple for a little over a
> year; it seems to be working. The test suite shows four additional
> unexpected successes when I run it with this patch, but I figure
> that's probably OK.
>
> I haven't included documentation patches ... where (if anywhere) would
> you suggest I include them? I wasn't able to find a compelling spot.
> Or perhaps one could argue that the new behavior is simply "correct,"
> and the new message you get from print fabs (3.0) is enough.
>
> ------------------------------
>
> 2001-12-12 Klee Dienes <kdienes@apple.com>
>
> * breakpoint.c (breakpoint_re_set, breakpoint_re_set_all,
> breakpoint_update): Instead of re-parsing all deferred breakpoints
> every time breakpoint_re_set is called, increment a generation
> number. When breakpoints need to be up-to-date, call
> breakpoint_update. This prevents unnecessary re-parsing of
> breakpoint information (and massive future-break spam) when
> multiple shared libraries are loaded at the same time.
>
> * breakpoint.h: export symbol_generation, breakpoint_update.
>
> * eval.c (evaluate_subexp_standard): when called with
> EVAL_AVOID_SIDE_EFFECTS, return the passed-in `expect_type' if the
> type of the evaluated expression is unknown. Also update to use
> the new `call_function_by_hand_expecting_type' interface.
>
> * gdbtypes.c, gdbtypes.h: add new type
> builtin_type_voidptrfuncptr.
>
> * parse.c, parse.h: export msym_{text,data,unknown}_symbol_type.
> Make them of type TYPE_CODE_ERROR instead of TYPE_CODE_INT.
>
> * scm-lang.c (scm_lookup_name): update to use new interface to
> find_function_in_inferior.
>
> * valops.c (create_cached_function, lookup_cached_function): add.
> These functions create a new data type (a `cached_value'), whose
> purpose is to store the lookup of commonly used symbols GDB needs
> from the inferior. For example, evaluating the expression 'print
> "hello"' causes GDB to call `malloc' in the target. Looking up
> the symbol for `malloc' takes a non-trivial amount of time, and
> has no need to be done if the symbols have not changed.
> create/lookup_cached_function allow GDB to cache the results of
> these lookups; re-looking them up only when the symbols have
> changed.
> (find_function_in_inferior): add a default type as second
> argument. This type will be used for the returned value if no
> type information is available for the function (previously, the
> type was assumed to be (char *) (*).
> (hand_function_call): add new `expect_type' parameter. This type
> will be used as the return type for the function if no type
> information is available.
> (call_function_by_hand_expecting_type): like
> call_function_by_hand, but uses the new `expect_type' interface to
> hand_function_call.
> (call_function_by_hand): implement as a wrapper to
> call_function_by_hand_expecting_type.
> (value_allocate_space_in_inferior): use new cached_function
> interface.
> (find_function_addr): if asked the return type of a function with
> type TYPE_CODE_ERROR, return TYPE_CODE_ERROR.
>
> * value.h (call_function_by_hand_expecting_type): add.
> (cached_value) add.
> (create_cached_function) add.
> (lookup_cached_function) add.
> (find_function_in_inferior) update to new signature.
>
> Index: gdb/breakpoint.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/breakpoint.c,v
> retrieving revision 1.57
> diff -u -r1.57 breakpoint.c
> --- breakpoint.c 2001/11/11 16:39:59 1.57
> +++ breakpoint.c 2002/01/08 22:43:28
> @@ -70,8 +70,12 @@
>
> static void ignore_command (char *, int);
>
> +void breakpoint_update (void);
> +
> static int breakpoint_re_set_one (PTR);
>
> +static void breakpoint_re_set_all (void);
> +
> static void clear_command (char *, int);
>
> static void catch_command (char *, int);
> @@ -720,6 +724,7 @@
> static char message1[] = "Error inserting catchpoint %d:\n";
> static char message[sizeof (message1) + 30];
>
> + breakpoint_update ();
>
> ALL_BREAKPOINTS_SAFE (b, temp)
> {
> @@ -7187,9 +7192,26 @@
> return 0;
> }
>
> -/* Re-set all breakpoints after symbols have been re-loaded. */
> +unsigned int symbol_generation = 1;
> +static unsigned int breakpoint_generation = 0;
> +
> +void breakpoint_update (void)
> +{
> + if (breakpoint_generation != symbol_generation) {
> + breakpoint_re_set_all ();
> + breakpoint_generation = symbol_generation;
> + }
> +}
> +
> void
> breakpoint_re_set (void)
> +{
> + symbol_generation++;
> +}
> +
> +/* Re-set all breakpoints after symbols have been re-loaded. */
> +static void
> +breakpoint_re_set_all (void)
> {
> struct breakpoint *b, *temp;
> enum language save_language;
> Index: gdb/breakpoint.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/breakpoint.h,v
> retrieving revision 1.10
> diff -u -r1.10 breakpoint.h
> --- breakpoint.h 2001/10/20 23:54:29 1.10
> +++ breakpoint.h 2002/01/08 22:43:28
> @@ -305,6 +305,8 @@
>
> typedef struct bpstats *bpstat;
>
> +extern unsigned int symbol_generation;
> +
> /* Interface: */
> /* Clear a bpstat so that it says we are not at any breakpoint.
> Also free any storage that is part of a bpstat. */
> @@ -525,6 +527,8 @@
> extern int breakpoint_thread_match (CORE_ADDR, ptid_t);
>
> extern void until_break_command (char *, int);
> +
> +extern void breakpoint_update (void);
>
> extern void breakpoint_re_set (void);
>
> Index: gdb/c-valprint.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/c-valprint.c,v
> retrieving revision 1.11
> diff -u -r1.11 c-valprint.c
> --- c-valprint.c 2001/11/10 20:44:37 1.11
> +++ c-valprint.c 2002/01/08 22:43:28
> @@ -449,7 +449,7 @@
> break;
>
> case TYPE_CODE_ERROR:
> - fprintf_filtered (stream, "<error type>");
> + fprintf_filtered (stream, "<unknown type>");
> break;
>
> case TYPE_CODE_UNDEF:
> Index: gdb/eval.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/eval.c,v
> retrieving revision 1.19
> diff -u -r1.19 eval.c
> --- eval.c 2002/01/04 17:51:38 1.19
> +++ eval.c 2002/01/08 22:43:29
> @@ -928,15 +928,20 @@
> gdb isn't asked for it's opinion (ie. through "whatis"),
> it won't offer it. */
>
> - struct type *ftype =
> + struct type *type =
> TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0]));
>
> - if (ftype)
> - return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
> + if (type)
> + {
> + if ((TYPE_CODE (type) == TYPE_CODE_ERROR) && expect_type)
> + return allocate_value (expect_type);
> + else
> + return allocate_value (type);
> + }
> else
> error ("Expression of type other than \"Function returning ...\" used as function");
> }
> - return call_function_by_hand (argvec[0], nargs, argvec + 1);
> + return call_function_by_hand_expecting_type (argvec[0], expect_type, nargs, argvec + 1);
> /* pai: FIXME save value from call_function_by_hand, then adjust pc by adjust_fn_pc if +ve */
>
> case OP_F77_UNDETERMINED_ARGLIST:
> Index: gdb/gdbtypes.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/gdbtypes.c,v
> retrieving revision 1.35
> diff -u -r1.35 gdbtypes.c
> --- gdbtypes.c 2001/12/20 03:26:08 1.35
> +++ gdbtypes.c 2002/01/08 22:43:29
> @@ -96,6 +96,7 @@
> struct type *builtin_type_void_func_ptr;
> struct type *builtin_type_CORE_ADDR;
> struct type *builtin_type_bfd_vma;
> +struct type *builtin_type_voidptrfuncptr;
>
> int opaque_type_resolution = 1;
> int overload_debug = 0;
> @@ -3209,6 +3210,8 @@
> init_type (TYPE_CODE_INT, TARGET_BFD_VMA_BIT / 8,
> TYPE_FLAG_UNSIGNED,
> "__bfd_vma", (struct objfile *) NULL);
> + builtin_type_voidptrfuncptr =
> + lookup_pointer_type (lookup_function_type (lookup_pointer_type (builtin_type_void)));
> }
>
>
> Index: gdb/gdbtypes.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/gdbtypes.h,v
> retrieving revision 1.21
> diff -u -r1.21 gdbtypes.h
> --- gdbtypes.h 2001/12/10 06:17:01 1.21
> +++ gdbtypes.h 2002/01/08 22:43:30
> @@ -930,6 +930,7 @@
> bit address type even though the TARGET has a 64 bit pointer type
> (cf MIPS). */
> extern struct type *builtin_type_bfd_vma;
> +extern struct type *builtin_type_voidptrfuncptr;
>
> /* Explicit sizes - see C9X <intypes.h> for naming scheme */
> extern struct type *builtin_type_int8;
> Index: gdb/parse.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/parse.c,v
> retrieving revision 1.17
> diff -u -r1.17 parse.c
> --- parse.c 2001/11/15 01:55:59 1.17
> +++ parse.c 2002/01/08 22:43:30
> @@ -399,9 +399,9 @@
> based on the language, but they no longer have names like "int", so
> the initial rationale is gone. */
>
> -static struct type *msym_text_symbol_type;
> -static struct type *msym_data_symbol_type;
> -static struct type *msym_unknown_symbol_type;
> +struct type *msym_text_symbol_type;
> +struct type *msym_data_symbol_type;
> +struct type *msym_unknown_symbol_type;
>
> void
> write_exp_msymbol (struct minimal_symbol *msymbol,
> @@ -1359,13 +1359,13 @@
> int i;
>
> msym_text_symbol_type =
> - init_type (TYPE_CODE_FUNC, 1, 0, "<text variable, no debug info>", NULL);
> - TYPE_TARGET_TYPE (msym_text_symbol_type) = builtin_type_int;
> + init_type (TYPE_CODE_FUNC, 0, 0, "<text variable, no debug info>", NULL);
> + TYPE_TARGET_TYPE (msym_text_symbol_type) = builtin_type_error;
> msym_data_symbol_type =
> - init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
> + init_type (TYPE_CODE_ERROR, 0, 0,
> "<data variable, no debug info>", NULL);
> msym_unknown_symbol_type =
> - init_type (TYPE_CODE_INT, 1, 0,
> + init_type (TYPE_CODE_ERROR, 0, 0,
> "<variable (not text or data), no debug info>",
> NULL);
>
> Index: gdb/parser-defs.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/parser-defs.h,v
> retrieving revision 1.6
> diff -u -r1.6 parser-defs.h
> --- parser-defs.h 2001/11/15 01:55:59 1.6
> +++ parser-defs.h 2002/01/08 22:43:30
> @@ -39,6 +39,10 @@
> extern int expout_size;
> extern int expout_ptr;
>
> +extern struct type *msym_text_symbol_type;
> +extern struct type *msym_data_symbol_type;
> +extern struct type *msym_unknown_symbol_type;
> +
> /* If this is nonzero, this block is used as the lexical context
> for symbol names. */
>
> Index: gdb/scm-lang.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/scm-lang.c,v
> retrieving revision 1.7
> diff -u -r1.7 scm-lang.c
> --- scm-lang.c 2002/01/04 05:20:08 1.7
> +++ scm-lang.c 2002/01/08 22:43:30
> @@ -169,7 +169,7 @@
> /* FIXME in this case, we should try lookup_symbol first */
> args[2] = value_from_longest (builtin_type_scm, SCM_EOL);
>
> - func = find_function_in_inferior ("scm_lookup_cstr");
> + func = find_function_in_inferior ("scm_lookup_cstr", builtin_type_voidptrfuncptr);
> val = call_function_by_hand (func, 3, args);
> if (!value_logical_not (val))
> return value_ind (val);
> @@ -192,7 +192,7 @@
> write_memory (iaddr, str, len);
> /* FIXME - should find and pass env */
> write_memory (iaddr + len, "", 1);
> - func = find_function_in_inferior ("scm_evstr");
> + func = find_function_in_inferior ("scm_evstr", builtin_type_voidptrfuncptr);
> return call_function_by_hand (func, 1, &addr);
> }
>
> Index: gdb/valops.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/valops.c,v
> retrieving revision 1.49
> diff -u -r1.49 valops.c
> --- valops.c 2002/01/08 02:09:31 1.49
> +++ valops.c 2002/01/08 22:43:31
> @@ -33,6 +33,7 @@
> #include "gdbcmd.h"
> #include "regcache.h"
> #include "cp-abi.h"
> +#include "parser-defs.h"
>
> #include <errno.h>
> #include "gdb_string.h"
> @@ -89,11 +90,49 @@
> int unwind_on_signal_p = 0;
>
>
>
> +struct cached_value *
> +create_cached_function (char *name, struct type *type)
> +{
> + struct cached_value cached_value *ptr;
> +
> + ptr = (struct cached_value *) xmalloc (sizeof (struct cached_value));
> + ptr->name = xstrdup (name);
> + ptr->type = type;
> + memset (&ptr->val, 0, sizeof (struct value));
> + ptr->generation = (unsigned int) -1;
> +
> + return ptr;
> +}
> +
> +struct value *
> +lookup_cached_function (struct cached_value *cval)
> +{
> + struct value *val = NULL;
> + struct value *next = NULL;
> +
> + if (cval->generation != symbol_generation)
> + {
> + val = find_function_in_inferior (cval->name, cval->type);
> + cval->val = *val;
> + cval->val.next = NULL;
> + cval->generation = symbol_generation;
> + }
> +
> + val = allocate_value (cval->val.type);
> + next = val->next;
> + *val = cval->val;
> + val->next = next;
> +
> + return val;
> +}
>
> -/* Find the address of function name NAME in the inferior. */
> +/* Find the address of function name NAME in the inferior. If no type
> + information is available for NAME, use `type' as the type for the
> + resulting value.
> +*/
>
> struct value *
> -find_function_in_inferior (char *name)
> +find_function_in_inferior (char *name, struct type *type)
> {
> register struct symbol *sym;
> sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
> @@ -111,20 +150,18 @@
> struct minimal_symbol *msymbol = lookup_minimal_symbol (name, NULL, NULL);
> if (msymbol != NULL)
> {
> - struct type *type;
> - CORE_ADDR maddr;
> - type = lookup_pointer_type (builtin_type_char);
> - type = lookup_function_type (type);
> - type = lookup_pointer_type (type);
> - maddr = SYMBOL_VALUE_ADDRESS (msymbol);
> - return value_from_pointer (type, maddr);
> + if (type != NULL)
> + return value_from_longest (type, (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
> + else
> + return value_from_longest (lookup_pointer_type (msym_text_symbol_type),
> + (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
> }
> else
> {
> if (!target_has_execution)
> error ("evaluation of this expression requires the target program to be active");
> else
> - error ("evaluation of this expression requires the program to have a function \"%s\".", name);
> + error ("evaluation of this expression requires the program to have a function named \"%s\".", name);
> }
> }
> }
> @@ -136,10 +173,14 @@
> value_allocate_space_in_inferior (int len)
> {
> struct value *blocklen;
> - struct value *val = find_function_in_inferior ("malloc");
> + struct value *val;
> + static struct cached_value *fval = NULL;
> +
> + if (fval == NULL)
> + fval = create_cached_function ("malloc", builtin_type_voidptrfuncptr);
>
> blocklen = value_from_longest (builtin_type_int, (LONGEST) len);
> - val = call_function_by_hand (val, 1, &blocklen);
> + val = call_function_by_hand (lookup_cached_function (fval), 1, &blocklen);
> if (value_logical_not (val))
> {
> if (!target_has_execution)
> @@ -1261,6 +1302,11 @@
>
> value_type = builtin_type_int;
> }
> + else if (code == TYPE_CODE_ERROR)
> + {
> + value_type = builtin_type_error;
> + funaddr = (CORE_ADDR) -1;
> + }
> else
> error ("Invalid data type for function to be called.");
>
> @@ -1287,7 +1333,8 @@
> ARGS is modified to contain coerced values. */
>
> static struct value *
> -hand_function_call (struct value *function, int nargs, struct value **args)
> +hand_function_call (struct value *function,
> + struct type *expect_type, int nargs, struct value **args)
> {
> register CORE_ADDR sp;
> register int i;
> @@ -1334,6 +1381,32 @@
> inf_status = save_inferior_status (1);
> old_chain = make_cleanup_restore_inferior_status (inf_status);
>
> + funaddr = find_function_addr (function, &value_type);
> + CHECK_TYPEDEF (value_type);
> +
> + if ((value_type == NULL) || (value_type->code == TYPE_CODE_ERROR))
> + value_type = expect_type;
> +
> + if ((value_type == NULL) || (value_type->code == TYPE_CODE_ERROR))
> + error ("Unable to call function at 0x%lx: no return type information available.\n"
> + "To call this function anyway, you can cast the return type explicitly\n"
> + "(e.g. 'print (float) fabs (3.0)')",
> + (unsigned long) funaddr);
> +
> + CHECK_TYPEDEF (value_type);
> +
> + {
> + struct block *b = block_for_pc (funaddr);
> + /* If compiled without -g, assume GCC 2. */
> + using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
> + }
> +
> + /* Are we returning a value using a structure return or a normal
> + value return? */
> +
> + struct_return = using_struct_return (function, funaddr, value_type,
> + using_gcc);
> +
> /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
> (and POP_FRAME for restoring them). (At least on most machines)
> they are saved on the stack in the inferior. */
> @@ -1354,21 +1427,6 @@
> sp += sizeof_dummy1;
> }
>
> - funaddr = find_function_addr (function, &value_type);
> - CHECK_TYPEDEF (value_type);
> -
> - {
> - struct block *b = block_for_pc (funaddr);
> - /* If compiled without -g, assume GCC 2. */
> - using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
> - }
> -
> - /* Are we returning a value using a structure return or a normal
> - value return? */
> -
> - struct_return = using_struct_return (function, funaddr, value_type,
> - using_gcc);
> -
> /* Create a call sequence customized for this function
> and the number of arguments for it. */
> for (i = 0; i < (int) (SIZEOF_CALL_DUMMY_WORDS / sizeof (dummy[0])); i++)
> @@ -1786,16 +1844,23 @@
> }
>
> struct value *
> -call_function_by_hand (struct value *function, int nargs, struct value **args)
> +call_function_by_hand (struct value *function,
> + struct tyep *expect_type, int nargs, struct value **args)
> {
> if (CALL_DUMMY_P)
> {
> - return hand_function_call (function, nargs, args);
> + return hand_function_call (function, expect_type, nargs, args);
> }
> else
> {
> error ("Cannot invoke functions on this machine.");
> }
> +}
> +
> +struct value *
> +call_function_by_hand (struct value *function, int nargs, struct value **args)
> +{
> + call_function_by_hand_expecting_type (function, NULL, nargs, args);
> }
>
>
>
> Index: gdb/value.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/value.h,v
> retrieving revision 1.26
> diff -u -r1.26 value.h
> --- value.h 2002/01/04 23:21:38 1.26
> +++ value.h 2002/01/08 22:43:32
> @@ -466,7 +466,7 @@
>
> /* C++ */
>
> -extern struct value *value_of_this (int complain);
> +extern struct value *value_of_local (char *name, int complain);
>
> extern struct value *value_x_binop (struct value *arg1, struct value *arg2,
> enum exp_opcode op,
> @@ -529,6 +529,9 @@
> extern void print_variable_value (struct symbol * var,
> struct frame_info * frame,
> struct ui_file *stream);
> +extern void
> +print_variable_value (struct symbol *var, struct frame_info *frame,
> + struct ui_file *stream);
>
> extern int check_field (struct value *, const char *);
>
> @@ -554,6 +557,11 @@
> extern struct value *call_function_by_hand (struct value *, int,
> struct value **);
>
> +extern struct value *
> +call_function_by_hand_expecting_type (struct value *,
> + struct type *, int,
> + struct value **, int);
> +
> extern int default_coerce_float_to_double (struct type *, struct type *);
>
> extern int standard_coerce_float_to_double (struct type *, struct type *);
> @@ -563,13 +571,26 @@
>
> extern void find_rt_vbase_offset (struct type *, struct type *, char *, int,
> int *, int *);
> +
> +extern CORE_ADDR find_function_addr (struct value *, struct type **);
>
> -extern struct value *find_function_in_inferior (char *);
> +extern struct value *find_function_in_inferior (char *, struct type *);
>
> extern struct value *value_allocate_space_in_inferior (int);
>
> extern CORE_ADDR default_push_arguments (int nargs, struct value ** args,
> CORE_ADDR sp, int struct_return,
> CORE_ADDR struct_addr);
> +struct cached_value
> +{
> + char *name;
> + struct type *type;
> + struct value val;
> + unsigned int generation;
> +};
> +
> +extern struct cached_value *create_cached_function (char *, struct type *);
> +
> +extern struct value *lookup_cached_function (struct cached_value *cval);
>
> #endif /* !defined (VALUE_H) */
> Index: gdb/testsuite/gdb.asm/asm-source.exp
> ===================================================================
> RCS file: /cvs/src/src/gdb/testsuite/gdb.asm/asm-source.exp,v
> retrieving revision 1.16
> diff -u -r1.16 asm-source.exp
> --- asm-source.exp 2001/12/20 22:12:20 1.16
> +++ asm-source.exp 2002/01/08 22:43:32
> @@ -215,10 +215,12 @@
> "Make selected stack frame return now\?.*" "y"
>
> # See if we can look at a global variable
> -gdb_test "print globalvar" ".* = 11" "look at global variable"
> +gdb_test "print globalvar" ".* = (11|<unknown type>)" "look at global variable"
> +gdb_test "print (int) globalvar" ".* = 11" "look at global variable"
>
> # See if we can look at a static variable
> -gdb_test "print staticvar" ".* = 5" "look at static variable"
> +gdb_test "print staticvar" ".* = (5|<unknown type>)" "look at static variable"
> +gdb_test "print (int) staticvar" ".* = 5" "look at static variable"
>
> # See if we can look at a static function
> gdb_test "disassem foostatic" ".*<foostatic>:.*End of assembler dump." \
> Index: gdb/testsuite/gdb.base/nodebug.exp
> ===================================================================
> RCS file: /cvs/src/src/gdb/testsuite/gdb.base/nodebug.exp,v
> retrieving revision 1.2
> diff -u -r1.2 nodebug.exp
> --- nodebug.exp 2001/03/06 08:21:50 1.2
> +++ nodebug.exp 2002/01/08 22:43:36
> @@ -77,23 +77,24 @@
> gdb_test "whatis top" \
> "(<(text variable|function), no debug info>|short \\(int\\)|short \\(\\))"
> if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
> - gdb_test "ptype top" "(short|int) \\((|void|int|<non-float parameter>|<non-float parameter>, <non-float parameter>)\\)"
> + gdb_test "ptype top" "(short|int|<unknown type>) \\((|void|int|<non-float parameter>|<non-float parameter>, <non-float parameter>)\\)"
>
> if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix5*" }
> setup_xfail "mips-sgi-irix6*"
> gdb_test "p middle" \
> - "\{(<(text variable|function), no debug info>|short \\(int\\)|short \\(\\))\} \[0-9a-fx]* <middle(\\(int\\)|)>"
> + "\{(<(text variable|function), no debug info>|<unknown type>|short \\(int\\)|short \\(\\))\} \[0-9a-fx]* <middle(\\(int\\)|)>"
> if {!$gcc_compiled} then { setup_xfail "mips-sgi-irix5*" }
> setup_xfail "mips-sgi-irix6*"
> gdb_test "whatis middle" \
> - "(<(text variable|function), no debug info>|short \\(int\\)|short \\(\\))"
> + "(<(text variable|function), no debug info>|<unknown type>|short \\(int\\)|short \\(\\))"
> setup_xfail "mips-sgi-irix6*"
> - gdb_test "ptype middle" "(short|int) \\((|void|int|<non-float parameter>|<non-float parameter>, <non-float parameter>)\\)"
> + gdb_test "ptype middle" "(short|int|<unknown type>) \\((|void|int|<non-float parameter>|<non-float parameter>, <non-float parameter>)\\)"
>
> - gdb_test "p dataglobal" "= 3"
> + gdb_test "p dataglobal" "(= 3|<unknown type>)"
> + gdb_test "p (int) dataglobal" "= 3"
> gdb_test "whatis dataglobal" \
> - "<(data variable|variable), no debug info>|int"
> - gdb_test "ptype dataglobal" "<(data variable|variable), no debug info>|int"
> + "<(data variable|variable), no debug info>|<unknown type>|int"
> + gdb_test "ptype dataglobal" "<(data variable|variable), no debug info>|<unknown type>|int"
>
> # The only symbol xcoff puts out for statics is for the TOC entry.
> # Possible, but hairy, for gdb to deal. Right now it doesn't, it
> @@ -102,37 +103,40 @@
> setup_xfail "powerpc*-*-aix*"
> if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
> if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
> - gdb_test "p datalocal" "= 4"
> + gdb_test "p datalocal" "(= 4|<unknown type>)"
> + gdb_test "p (int) datalocal" "4"
> setup_xfail "rs6000*-*-aix*"
> setup_xfail "powerpc*-*-aix*"
> if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
> if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
> - gdb_test "whatis datalocal" "<(data variable|variable), no debug info>"
> + gdb_test "whatis datalocal" "<(data variable|variable), no debug info>|<unknown type>"
> setup_xfail "rs6000*-*-aix*"
> setup_xfail "powerpc*-*-aix*"
> if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
> if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
> - gdb_test "ptype datalocal" "<(data variable|variable), no debug info>"
> + gdb_test "ptype datalocal" "<(data variable|variable), no debug info>|<unknown type>"
>
> - gdb_test "p bssglobal" "= 0"
> - gdb_test "whatis bssglobal" "<(data variable|variable), no debug info>|int"
> - gdb_test "ptype bssglobal" "<(data variable|variable), no debug info>|int"
> + gdb_test "p bssglobal" "(= 0|<unknown type>)"
> + gdb_test "p (int) bssglobal" "= 0"
> + gdb_test "whatis bssglobal" "<(data variable|variable), no debug info>|<unknown type>|int"
> + gdb_test "ptype bssglobal" "<(data variable|variable), no debug info>|<unknown type>|int"
>
> setup_xfail "rs6000*-*-aix*"
> setup_xfail "powerpc*-*-aix*"
> if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
> if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
> - gdb_test "p bsslocal" "= 0"
> + gdb_test "p bsslocal" "(= 0|<unknown type>)"
> + gdb_test "p (int) bsslocal" "= 0"
> setup_xfail "rs6000*-*-aix*"
> setup_xfail "powerpc*-*-aix*"
> if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
> if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
> - gdb_test "whatis bsslocal" "<(data variable|variable), no debug info>"
> + gdb_test "whatis bsslocal" "<(data variable|variable), no debug info>|<unknown type>"
> setup_xfail "rs6000*-*-aix*"
> setup_xfail "powerpc*-*-aix*"
> if {!$gcc_compiled} then { setup_xfail "hppa*-*-hpux*" }
> if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
> - gdb_test "ptype bsslocal" "<(data variable|variable), no debug info>"
> + gdb_test "ptype bsslocal" "<(data variable|variable), no debug info>|<unknown type>"
>
> if {$gcc_compiled} then { setup_xfail "mips-sgi-irix6*" }
> gdb_test "backtrace 10" "#0.*inner.*#1.*middle.*#2.*top.*#3.*main.*" \
> @@ -167,7 +171,9 @@
> # We need to up this because this can be really slow on some boards.
> # (malloc() is called as part of the test).
> set timeout 60;
> - gdb_test {p/c array_index("abcdef",2)} " = 99 'c'"
> + gdb_test {p/c (int) array_index("abcdef",2)} " = 99 'c'"
> + gdb_test {p/c array_index("abcdef",2)} \
> + "Unable to call function .* no return type information available.*"
> }
> }