This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA] resubmit: cached function lookup; strict return type analysis


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:
> 
> ------------------------------
> 
> 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:

Klee, since these two changes are pretty much unrelated
(except that they both pertain to objective c), could you
please submit them separately?  Also I think the patch 
still needs to be cleaned up -- I could not apply it.
It may still contain dependencies on other changes in 
your local tree.

> 
> 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.*"
>         }
>      }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]