aboutsummaryrefslogtreecommitdiff
path: root/gdb/valops.c
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2003-04-21 16:48:41 +0000
committerAndrew Cagney <cagney@redhat.com>2003-04-21 16:48:41 +0000
commit04714b914fe6e2deaf384c77a286df8e95545a73 (patch)
tree4b98b0f2c1c1012101b7a9b559249ac8266080c2 /gdb/valops.c
parent6c6532f75378f1b6d80caf34c2a6ad05d7c4feb1 (diff)
downloadgdb-04714b914fe6e2deaf384c77a286df8e95545a73.zip
gdb-04714b914fe6e2deaf384c77a286df8e95545a73.tar.gz
gdb-04714b914fe6e2deaf384c77a286df8e95545a73.tar.bz2
2003-04-21 Andrew Cagney <cagney@redhat.com>
* infcall.c: New file. * infcall.h: New file. * valarith.c: Include "infcall.h". * scm-lang.c, objc-lang.cm, hppa-tdep.c, gcore.c: Ditto. * eval.c, ada-valprint.c, ada-lang.c: Ditto. * Makefile.in (valarith.o, scm-lang.o): Update dependencies. (objc-lang.o, hppa-tdep.o, gcore.o): Update dependencies. (eval.o, ada-valprint.o, ada-lang.o): Update dependencies. (SFILES): Add "infcall.c" (COMMON_OBS): Add "infcall.o". (infcall.o): Specify dependencies. * value.h (call_function_by_hand): Delete declaration. * inferior.h (run_stack_dummy): Delete declaration. * infcmd.c (breakpoint_auto_delete_contents): Move to "infcall.c". (run_stack_dummy): Move to "infcall.c", merged into call_function_by_hand. * valops.c (call_function_by_hand): Moved to "infcall.c". (find_function_addr, value_arg_coerce): Ditto. (unwindonsignal_p, coerce_float_to_double): Ditto. (_initialize_valops): Move "set/show coerce-float-to-double", and "set/show unwindonsignal" commands to "infcall.c". * v850-tdep.c, target.h: Update comments. * sparc-tdep.c (sparc_fix_call_dummy): Update comments. * sh-tdep.c (sh_init_extra_frame_info): Update comments. (sh64_init_extra_frame_info): Update comments. * mn10300-tdep.c: Update comments. * mcore-tdep.c (mcore_init_extra_frame_info): Update comments. * config/sparc/tm-sparc.h: Update comments. * breakpoint.h: Update comments. * avr-tdep.c (avr_init_extra_frame_info): Update comments. * arm-tdep.c: Update comment.
Diffstat (limited to 'gdb/valops.c')
-rw-r--r--gdb/valops.c829
1 files changed, 1 insertions, 828 deletions
diff --git a/gdb/valops.c b/gdb/valops.c
index a2a2e97..d8261c8 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -34,6 +34,7 @@
#include "regcache.h"
#include "cp-abi.h"
#include "block.h"
+#include "infcall.h"
#include <errno.h>
#include "gdb_string.h"
@@ -49,10 +50,6 @@ extern int overload_debug;
static int typecmp (int staticp, int varargs, int nargs,
struct field t1[], struct value *t2[]);
-static CORE_ADDR find_function_addr (struct value *, struct type **);
-static struct value *value_arg_coerce (struct value *, struct type *, int);
-
-
static CORE_ADDR value_push (CORE_ADDR, struct value *);
static struct value *search_struct_field (char *, struct value *, int,
@@ -84,37 +81,6 @@ static int auto_abandon = 0;
int overload_resolution = 0;
-/* This boolean tells what gdb should do if a signal is received while in
- a function called from gdb (call dummy). If set, gdb unwinds the stack
- and restore the context to what as it was before the call.
- The default is to stop in the frame where the signal was received. */
-
-int unwind_on_signal_p = 0;
-
-/* How you should pass arguments to a function depends on whether it
- was defined in K&R style or prototype style. If you define a
- function using the K&R syntax that takes a `float' argument, then
- callers must pass that argument as a `double'. If you define the
- function using the prototype syntax, then you must pass the
- argument as a `float', with no promotion.
-
- Unfortunately, on certain older platforms, the debug info doesn't
- indicate reliably how each function was defined. A function type's
- TYPE_FLAG_PROTOTYPED flag may be clear, even if the function was
- defined in prototype style. When calling a function whose
- TYPE_FLAG_PROTOTYPED flag is clear, GDB consults this flag to decide
- what to do.
-
- For modern targets, it is proper to assume that, if the prototype
- flag is clear, that can be trusted: `float' arguments should be
- promoted to `double'. For some older targets, if the prototype
- flag is clear, that doesn't tell us anything. The default is to
- trust the debug information; the user can override this behavior
- with "set coerce-float-to-double 0". */
-
-static int coerce_float_to_double;
-
-
/* Find the address of function name NAME in the inferior. */
struct value *
@@ -1089,774 +1055,6 @@ legacy_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
return sp;
}
-/* Perform the standard coercions that are specified
- for arguments to be passed to C functions.
-
- If PARAM_TYPE is non-NULL, it is the expected parameter type.
- IS_PROTOTYPED is non-zero if the function declaration is prototyped. */
-
-static struct value *
-value_arg_coerce (struct value *arg, struct type *param_type,
- int is_prototyped)
-{
- register struct type *arg_type = check_typedef (VALUE_TYPE (arg));
- register struct type *type
- = param_type ? check_typedef (param_type) : arg_type;
-
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_REF:
- if (TYPE_CODE (arg_type) != TYPE_CODE_REF
- && TYPE_CODE (arg_type) != TYPE_CODE_PTR)
- {
- arg = value_addr (arg);
- VALUE_TYPE (arg) = param_type;
- return arg;
- }
- break;
- case TYPE_CODE_INT:
- case TYPE_CODE_CHAR:
- case TYPE_CODE_BOOL:
- case TYPE_CODE_ENUM:
- /* If we don't have a prototype, coerce to integer type if necessary. */
- if (!is_prototyped)
- {
- if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
- type = builtin_type_int;
- }
- /* Currently all target ABIs require at least the width of an integer
- type for an argument. We may have to conditionalize the following
- type coercion for future targets. */
- if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
- type = builtin_type_int;
- break;
- case TYPE_CODE_FLT:
- if (!is_prototyped && coerce_float_to_double)
- {
- if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double))
- type = builtin_type_double;
- else if (TYPE_LENGTH (type) > TYPE_LENGTH (builtin_type_double))
- type = builtin_type_long_double;
- }
- break;
- case TYPE_CODE_FUNC:
- type = lookup_pointer_type (type);
- break;
- case TYPE_CODE_ARRAY:
- /* Arrays are coerced to pointers to their first element, unless
- they are vectors, in which case we want to leave them alone,
- because they are passed by value. */
- if (current_language->c_style_arrays)
- if (!TYPE_VECTOR (type))
- type = lookup_pointer_type (TYPE_TARGET_TYPE (type));
- break;
- case TYPE_CODE_UNDEF:
- case TYPE_CODE_PTR:
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- case TYPE_CODE_VOID:
- case TYPE_CODE_SET:
- case TYPE_CODE_RANGE:
- case TYPE_CODE_STRING:
- case TYPE_CODE_BITSTRING:
- case TYPE_CODE_ERROR:
- case TYPE_CODE_MEMBER:
- case TYPE_CODE_METHOD:
- case TYPE_CODE_COMPLEX:
- default:
- break;
- }
-
- return value_cast (type, arg);
-}
-
-/* Determine a function's address and its return type from its value.
- Calls error() if the function is not valid for calling. */
-
-static CORE_ADDR
-find_function_addr (struct value *function, struct type **retval_type)
-{
- register struct type *ftype = check_typedef (VALUE_TYPE (function));
- register enum type_code code = TYPE_CODE (ftype);
- struct type *value_type;
- CORE_ADDR funaddr;
-
- /* If it's a member function, just look at the function
- part of it. */
-
- /* Determine address to call. */
- if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
- {
- funaddr = VALUE_ADDRESS (function);
- value_type = TYPE_TARGET_TYPE (ftype);
- }
- else if (code == TYPE_CODE_PTR)
- {
- funaddr = value_as_address (function);
- ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
- if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
- || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
- {
- funaddr = CONVERT_FROM_FUNC_PTR_ADDR (funaddr);
- value_type = TYPE_TARGET_TYPE (ftype);
- }
- else
- value_type = builtin_type_int;
- }
- else if (code == TYPE_CODE_INT)
- {
- /* Handle the case of functions lacking debugging info.
- Their values are characters since their addresses are char */
- if (TYPE_LENGTH (ftype) == 1)
- funaddr = value_as_address (value_addr (function));
- else
- /* Handle integer used as address of a function. */
- funaddr = (CORE_ADDR) value_as_long (function);
-
- value_type = builtin_type_int;
- }
- else
- error ("Invalid data type for function to be called.");
-
- *retval_type = value_type;
- return funaddr;
-}
-
-/* All this stuff with a dummy frame may seem unnecessarily complicated
- (why not just save registers in GDB?). The purpose of pushing a dummy
- frame which looks just like a real frame is so that if you call a
- function and then hit a breakpoint (get a signal, etc), "backtrace"
- will look right. Whether the backtrace needs to actually show the
- stack at the time the inferior function was called is debatable, but
- it certainly needs to not display garbage. So if you are contemplating
- making dummy frames be different from normal frames, consider that. */
-
-/* Perform a function call in the inferior.
- ARGS is a vector of values of arguments (NARGS of them).
- FUNCTION is a value, the function to be called.
- Returns a value representing what the function returned.
- May fail to return, if a breakpoint or signal is hit
- during the execution of the function.
-
- ARGS is modified to contain coerced values. */
-
-struct value *
-call_function_by_hand (struct value *function, int nargs, struct value **args)
-{
- register CORE_ADDR sp;
- register int i;
- int rc;
- CORE_ADDR start_sp;
- /* CALL_DUMMY is an array of words (REGISTER_SIZE), but each word
- is in host byte order. Before calling FIX_CALL_DUMMY, we byteswap it
- and remove any extra bytes which might exist because ULONGEST is
- bigger than REGISTER_SIZE.
-
- NOTE: This is pretty wierd, as the call dummy is actually a
- sequence of instructions. But CISC machines will have
- to pack the instructions into REGISTER_SIZE units (and
- so will RISC machines for which INSTRUCTION_SIZE is not
- REGISTER_SIZE).
-
- NOTE: This is pretty stupid. CALL_DUMMY should be in strict
- target byte order. */
-
- static ULONGEST *dummy;
- int sizeof_dummy1;
- char *dummy1;
- CORE_ADDR dummy_addr;
- CORE_ADDR old_sp;
- struct type *value_type;
- unsigned char struct_return;
- CORE_ADDR struct_addr = 0;
- struct regcache *retbuf;
- struct cleanup *retbuf_cleanup;
- struct inferior_status *inf_status;
- struct cleanup *inf_status_cleanup;
- CORE_ADDR funaddr;
- int using_gcc; /* Set to version of gcc in use, or zero if not gcc */
- CORE_ADDR real_pc;
- struct type *param_type = NULL;
- struct type *ftype = check_typedef (SYMBOL_TYPE (function));
- int n_method_args = 0;
-
- dummy = alloca (SIZEOF_CALL_DUMMY_WORDS);
- sizeof_dummy1 = REGISTER_SIZE * SIZEOF_CALL_DUMMY_WORDS / sizeof (ULONGEST);
- dummy1 = alloca (sizeof_dummy1);
- memcpy (dummy, CALL_DUMMY_WORDS, SIZEOF_CALL_DUMMY_WORDS);
-
- if (!target_has_execution)
- noprocess ();
-
- /* Create a cleanup chain that contains the retbuf (buffer
- containing the register values). This chain is create BEFORE the
- inf_status chain so that the inferior status can cleaned up
- (restored or discarded) without having the retbuf freed. */
- retbuf = regcache_xmalloc (current_gdbarch);
- retbuf_cleanup = make_cleanup_regcache_xfree (retbuf);
-
- /* A cleanup for the inferior status. Create this AFTER the retbuf
- so that this can be discarded or applied without interfering with
- the regbuf. */
- inf_status = save_inferior_status (1);
- inf_status_cleanup = make_cleanup_restore_inferior_status (inf_status);
-
- if (DEPRECATED_PUSH_DUMMY_FRAME_P ())
- {
- /* DEPRECATED_PUSH_DUMMY_FRAME is responsible for saving the
- inferior registers (and frame_pop() for restoring them). (At
- least on most machines) they are saved on the stack in the
- inferior. */
- DEPRECATED_PUSH_DUMMY_FRAME;
- }
- else
- {
- /* FIXME: cagney/2003-02-26: Step zero of this little tinker is
- to extract the generic dummy frame code from the architecture
- vector. Hence this direct call.
-
- A follow-on change is to modify this interface so that it takes
- thread OR frame OR tpid as a parameter, and returns a dummy
- frame handle. The handle can then be used further down as a
- parameter SAVE_DUMMY_FRAME_TOS. Hmm, thinking about it, since
- everything is ment to be using generic dummy frames, why not
- even use some of the dummy frame code to here - do a regcache
- dup and then pass the duped regcache, along with all the other
- stuff, at one single point.
-
- In fact, you can even save the structure's return address in the
- dummy frame and fix one of those nasty lost struct return edge
- conditions. */
- generic_push_dummy_frame ();
- }
-
- old_sp = read_sp ();
-
- /* Ensure that the initial SP is correctly aligned. */
- if (gdbarch_frame_align_p (current_gdbarch))
- {
- /* NOTE: cagney/2002-09-18:
-
- On a RISC architecture, a void parameterless generic dummy
- frame (i.e., no parameters, no result) typically does not
- need to push anything the stack and hence can leave SP and
- FP. Similarly, a framelss (possibly leaf) function does not
- push anything on the stack and, hence, that too can leave FP
- and SP unchanged. As a consequence, a sequence of void
- parameterless generic dummy frame calls to frameless
- functions will create a sequence of effectively identical
- frames (SP, FP and TOS and PC the same). This, not
- suprisingly, results in what appears to be a stack in an
- infinite loop --- when GDB tries to find a generic dummy
- frame on the internal dummy frame stack, it will always find
- the first one.
-
- To avoid this problem, the code below always grows the stack.
- That way, two dummy frames can never be identical. It does
- burn a few bytes of stack but that is a small price to pay
- :-). */
- sp = gdbarch_frame_align (current_gdbarch, old_sp);
- if (sp == old_sp)
- {
- if (INNER_THAN (1, 2))
- /* Stack grows down. */
- sp = gdbarch_frame_align (current_gdbarch, old_sp - 1);
- else
- /* Stack grows up. */
- sp = gdbarch_frame_align (current_gdbarch, old_sp + 1);
- }
- gdb_assert ((INNER_THAN (1, 2) && sp <= old_sp)
- || (INNER_THAN (2, 1) && sp >= old_sp));
- }
- else
- /* FIXME: cagney/2002-09-18: Hey, you loose! Who knows how badly
- aligned the SP is! Further, per comment above, if the generic
- dummy frame ends up empty (because nothing is pushed) GDB won't
- be able to correctly perform back traces. If a target is
- having trouble with backtraces, first thing to do is add
- FRAME_ALIGN() to its architecture vector. After that, try
- adding SAVE_DUMMY_FRAME_TOS() and modifying
- DEPRECATED_FRAME_CHAIN so that when the next outer frame is a
- generic dummy, it returns the current frame's base. */
- sp = old_sp;
-
- if (INNER_THAN (1, 2))
- {
- /* Stack grows down */
- sp -= sizeof_dummy1;
- start_sp = sp;
- }
- else
- {
- /* Stack grows up */
- start_sp = sp;
- sp += sizeof_dummy1;
- }
-
- /* NOTE: cagney/2002-09-10: Don't bother re-adjusting the stack
- after allocating space for the call dummy. A target can specify
- a SIZEOF_DUMMY1 (via SIZEOF_CALL_DUMMY_WORDS) such that all local
- alignment requirements are met. */
-
- 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++)
- store_unsigned_integer (&dummy1[i * REGISTER_SIZE],
- REGISTER_SIZE,
- (ULONGEST) dummy[i]);
-
-#ifdef GDB_TARGET_IS_HPPA
- real_pc = FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
- value_type, using_gcc);
-#else
- if (FIX_CALL_DUMMY_P ())
- {
- /* gdb_assert (CALL_DUMMY_LOCATION == ON_STACK) true? */
- FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args, value_type,
- using_gcc);
- }
- real_pc = start_sp;
-#endif
-
- switch (CALL_DUMMY_LOCATION)
- {
- case ON_STACK:
- dummy_addr = start_sp;
- write_memory (start_sp, (char *) dummy1, sizeof_dummy1);
- if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
- generic_save_call_dummy_addr (start_sp, start_sp + sizeof_dummy1);
- break;
- case AT_ENTRY_POINT:
- real_pc = funaddr;
- dummy_addr = CALL_DUMMY_ADDRESS ();
- if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
- /* NOTE: cagney/2002-04-13: The entry point is going to be
- modified with a single breakpoint. */
- generic_save_call_dummy_addr (CALL_DUMMY_ADDRESS (),
- CALL_DUMMY_ADDRESS () + 1);
- break;
- default:
- internal_error (__FILE__, __LINE__, "bad switch");
- }
-
-#ifdef lint
- sp = old_sp; /* It really is used, for some ifdef's... */
-#endif
-
- if (nargs < TYPE_NFIELDS (ftype))
- error ("too few arguments in function call");
-
- for (i = nargs - 1; i >= 0; i--)
- {
- int prototyped;
-
- /* FIXME drow/2002-05-31: Should just always mark methods as
- prototyped. Can we respect TYPE_VARARGS? Probably not. */
- if (TYPE_CODE (ftype) == TYPE_CODE_METHOD)
- prototyped = 1;
- else
- prototyped = TYPE_PROTOTYPED (ftype);
-
- if (i < TYPE_NFIELDS (ftype))
- args[i] = value_arg_coerce (args[i], TYPE_FIELD_TYPE (ftype, i),
- prototyped);
- else
- args[i] = value_arg_coerce (args[i], NULL, 0);
-
- /*elz: this code is to handle the case in which the function to be called
- has a pointer to function as parameter and the corresponding actual argument
- is the address of a function and not a pointer to function variable.
- In aCC compiled code, the calls through pointers to functions (in the body
- of the function called by hand) are made via $$dyncall_external which
- requires some registers setting, this is taken care of if we call
- via a function pointer variable, but not via a function address.
- In cc this is not a problem. */
-
- if (using_gcc == 0)
- if (param_type && TYPE_CODE (ftype) != TYPE_CODE_METHOD)
- /* if this parameter is a pointer to function */
- if (TYPE_CODE (param_type) == TYPE_CODE_PTR)
- if (TYPE_CODE (TYPE_TARGET_TYPE (param_type)) == TYPE_CODE_FUNC)
- /* elz: FIXME here should go the test about the compiler used
- to compile the target. We want to issue the error
- message only if the compiler used was HP's aCC.
- If we used HP's cc, then there is no problem and no need
- to return at this point */
- if (using_gcc == 0) /* && compiler == aCC */
- /* go see if the actual parameter is a variable of type
- pointer to function or just a function */
- if (args[i]->lval == not_lval)
- {
- char *arg_name;
- if (find_pc_partial_function ((CORE_ADDR) args[i]->aligner.contents[0], &arg_name, NULL, NULL))
- error ("\
-You cannot use function <%s> as argument. \n\
-You must use a pointer to function type variable. Command ignored.", arg_name);
- }
- }
-
- if (REG_STRUCT_HAS_ADDR_P ())
- {
- /* This is a machine like the sparc, where we may need to pass a
- pointer to the structure, not the structure itself. */
- for (i = nargs - 1; i >= 0; i--)
- {
- struct type *arg_type = check_typedef (VALUE_TYPE (args[i]));
- if ((TYPE_CODE (arg_type) == TYPE_CODE_STRUCT
- || TYPE_CODE (arg_type) == TYPE_CODE_UNION
- || TYPE_CODE (arg_type) == TYPE_CODE_ARRAY
- || TYPE_CODE (arg_type) == TYPE_CODE_STRING
- || TYPE_CODE (arg_type) == TYPE_CODE_BITSTRING
- || TYPE_CODE (arg_type) == TYPE_CODE_SET
- || (TYPE_CODE (arg_type) == TYPE_CODE_FLT
- && TYPE_LENGTH (arg_type) > 8)
- )
- && REG_STRUCT_HAS_ADDR (using_gcc, arg_type))
- {
- CORE_ADDR addr;
- int len; /* = TYPE_LENGTH (arg_type); */
- int aligned_len;
- arg_type = check_typedef (VALUE_ENCLOSING_TYPE (args[i]));
- len = TYPE_LENGTH (arg_type);
-
- if (STACK_ALIGN_P ())
- /* MVS 11/22/96: I think at least some of this
- stack_align code is really broken. Better to let
- PUSH_ARGUMENTS adjust the stack in a target-defined
- manner. */
- aligned_len = STACK_ALIGN (len);
- else
- aligned_len = len;
- if (INNER_THAN (1, 2))
- {
- /* stack grows downward */
- sp -= aligned_len;
- /* ... so the address of the thing we push is the
- stack pointer after we push it. */
- addr = sp;
- }
- else
- {
- /* The stack grows up, so the address of the thing
- we push is the stack pointer before we push it. */
- addr = sp;
- sp += aligned_len;
- }
- /* Push the structure. */
- write_memory (addr, VALUE_CONTENTS_ALL (args[i]), len);
- /* The value we're going to pass is the address of the
- thing we just pushed. */
- /*args[i] = value_from_longest (lookup_pointer_type (value_type),
- (LONGEST) addr); */
- args[i] = value_from_pointer (lookup_pointer_type (arg_type),
- addr);
- }
- }
- }
-
-
- /* Reserve space for the return structure to be written on the
- stack, if necessary. Make certain that the value is correctly
- aligned. */
-
- if (struct_return)
- {
- int len = TYPE_LENGTH (value_type);
- if (STACK_ALIGN_P ())
- /* NOTE: cagney/2003-03-22: Should rely on frame align, rather
- than stack align to force the alignment of the stack. */
- len = STACK_ALIGN (len);
- if (INNER_THAN (1, 2))
- {
- /* Stack grows downward. Align STRUCT_ADDR and SP after
- making space for the return value. */
- sp -= len;
- if (gdbarch_frame_align_p (current_gdbarch))
- sp = gdbarch_frame_align (current_gdbarch, sp);
- struct_addr = sp;
- }
- else
- {
- /* Stack grows upward. Align the frame, allocate space, and
- then again, re-align the frame??? */
- if (gdbarch_frame_align_p (current_gdbarch))
- sp = gdbarch_frame_align (current_gdbarch, sp);
- struct_addr = sp;
- sp += len;
- if (gdbarch_frame_align_p (current_gdbarch))
- sp = gdbarch_frame_align (current_gdbarch, sp);
- }
- }
-
- /* elz: on HPPA no need for this extra alignment, maybe it is needed
- on other architectures. This is because all the alignment is
- taken care of in the above code (ifdef REG_STRUCT_HAS_ADDR) and
- in hppa_push_arguments */
- /* NOTE: cagney/2003-03-24: The below code is very broken. Given an
- odd sized parameter the below will mis-align the stack. As was
- suggested back in '96, better to let PUSH_ARGUMENTS handle it. */
- if (DEPRECATED_EXTRA_STACK_ALIGNMENT_NEEDED)
- {
- /* MVS 11/22/96: I think at least some of this stack_align code
- is really broken. Better to let push_dummy_call() adjust the
- stack in a target-defined manner. */
- if (STACK_ALIGN_P () && INNER_THAN (1, 2))
- {
- /* If stack grows down, we must leave a hole at the top. */
- int len = 0;
-
- for (i = nargs - 1; i >= 0; i--)
- len += TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
- if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
- len += DEPRECATED_CALL_DUMMY_STACK_ADJUST;
- sp -= STACK_ALIGN (len) - len;
- }
- }
-
- /* Create the dummy stack frame. Pass in the call dummy address as,
- presumably, the ABI code knows where, in the call dummy, the
- return address should be pointed. */
- if (gdbarch_push_dummy_call_p (current_gdbarch))
- /* When there is no push_dummy_call method, should this code
- simply error out. That would the implementation of this method
- for all ABIs (which is probably a good thing). */
- sp = gdbarch_push_dummy_call (current_gdbarch, current_regcache,
- dummy_addr, nargs, args, sp, struct_return,
- struct_addr);
- else if (DEPRECATED_PUSH_ARGUMENTS_P ())
- /* Keep old targets working. */
- sp = DEPRECATED_PUSH_ARGUMENTS (nargs, args, sp, struct_return,
- struct_addr);
- else
- sp = legacy_push_arguments (nargs, args, sp, struct_return, struct_addr);
-
- if (DEPRECATED_PUSH_RETURN_ADDRESS_P ())
- /* for targets that use no CALL_DUMMY */
- /* There are a number of targets now which actually don't write
- any CALL_DUMMY instructions into the target, but instead just
- save the machine state, push the arguments, and jump directly
- to the callee function. Since this doesn't actually involve
- executing a JSR/BSR instruction, the return address must be set
- up by hand, either by pushing onto the stack or copying into a
- return-address register as appropriate. Formerly this has been
- done in PUSH_ARGUMENTS, but that's overloading its
- functionality a bit, so I'm making it explicit to do it here. */
- sp = DEPRECATED_PUSH_RETURN_ADDRESS (real_pc, sp);
-
- /* NOTE: cagney/2003-03-23: Diable this code when there is a
- push_dummy_call() method. Since that method will have already
- handled any alignment issues, the code below is entirely
- redundant. */
- if (!gdbarch_push_dummy_call_p (current_gdbarch)
- && STACK_ALIGN_P () && !INNER_THAN (1, 2))
- {
- /* If stack grows up, we must leave a hole at the bottom, note
- that sp already has been advanced for the arguments! */
- if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
- sp += DEPRECATED_CALL_DUMMY_STACK_ADJUST;
- sp = STACK_ALIGN (sp);
- }
-
-/* XXX This seems wrong. For stacks that grow down we shouldn't do
- anything here! */
- /* MVS 11/22/96: I think at least some of this stack_align code is
- really broken. Better to let PUSH_ARGUMENTS adjust the stack in
- a target-defined manner. */
- if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
- if (INNER_THAN (1, 2))
- {
- /* stack grows downward */
- sp -= DEPRECATED_CALL_DUMMY_STACK_ADJUST;
- }
-
- /* Store the address at which the structure is supposed to be
- written. */
- /* NOTE: 2003-03-24: Since PUSH_ARGUMENTS can (and typically does)
- store the struct return address, this call is entirely redundant. */
- if (struct_return && DEPRECATED_STORE_STRUCT_RETURN_P ())
- DEPRECATED_STORE_STRUCT_RETURN (struct_addr, sp);
-
- /* Write the stack pointer. This is here because the statements above
- might fool with it. On SPARC, this write also stores the register
- window into the right place in the new stack frame, which otherwise
- wouldn't happen. (See store_inferior_registers in sparc-nat.c.) */
- /* NOTE: cagney/2003-03-23: Disable this code when there is a
- push_dummy_call() method. Since that method will have already
- stored the stack pointer (as part of creating the fake call
- frame), and none of the code following that code adjusts the
- stack-pointer value, the below call is entirely redundant. */
- if (DEPRECATED_DUMMY_WRITE_SP_P ())
- DEPRECATED_DUMMY_WRITE_SP (sp);
-
- if (SAVE_DUMMY_FRAME_TOS_P ())
- SAVE_DUMMY_FRAME_TOS (sp);
-
- {
- char *name;
- struct symbol *symbol;
-
- name = NULL;
- symbol = find_pc_function (funaddr);
- if (symbol)
- {
- name = SYMBOL_PRINT_NAME (symbol);
- }
- else
- {
- /* Try the minimal symbols. */
- struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (funaddr);
-
- if (msymbol)
- {
- name = SYMBOL_PRINT_NAME (msymbol);
- }
- }
- if (name == NULL)
- {
- char format[80];
- sprintf (format, "at %s", local_hex_format ());
- name = alloca (80);
- /* FIXME-32x64: assumes funaddr fits in a long. */
- sprintf (name, format, (unsigned long) funaddr);
- }
-
- /* Execute the stack dummy routine, calling FUNCTION.
- When it is done, discard the empty frame
- after storing the contents of all regs into retbuf. */
- rc = run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf);
-
- if (rc == 1)
- {
- /* We stopped inside the FUNCTION because of a random signal.
- Further execution of the FUNCTION is not allowed. */
-
- if (unwind_on_signal_p)
- {
- /* The user wants the context restored. */
-
- /* We must get back to the frame we were before the dummy
- call. */
- frame_pop (get_current_frame ());
-
- /* FIXME: Insert a bunch of wrap_here; name can be very long if it's
- a C++ name with arguments and stuff. */
- error ("\
-The program being debugged was signaled while in a function called from GDB.\n\
-GDB has restored the context to what it was before the call.\n\
-To change this behavior use \"set unwindonsignal off\"\n\
-Evaluation of the expression containing the function (%s) will be abandoned.",
- name);
- }
- else
- {
- /* The user wants to stay in the frame where we stopped (default).*/
-
- /* If we restored the inferior status (via the cleanup),
- we would print a spurious error message (Unable to
- restore previously selected frame), would write the
- registers from the inf_status (which is wrong), and
- would do other wrong things. */
- discard_cleanups (inf_status_cleanup);
- discard_inferior_status (inf_status);
-
- /* FIXME: Insert a bunch of wrap_here; name can be very long if it's
- a C++ name with arguments and stuff. */
- error ("\
-The program being debugged was signaled while in a function called from GDB.\n\
-GDB remains in the frame where the signal was received.\n\
-To change this behavior use \"set unwindonsignal on\"\n\
-Evaluation of the expression containing the function (%s) will be abandoned.",
- name);
- }
- }
-
- if (rc == 2)
- {
- /* We hit a breakpoint inside the FUNCTION. */
-
- /* If we restored the inferior status (via the cleanup), we
- would print a spurious error message (Unable to restore
- previously selected frame), would write the registers from
- the inf_status (which is wrong), and would do other wrong
- things. */
- discard_cleanups (inf_status_cleanup);
- discard_inferior_status (inf_status);
-
- /* The following error message used to say "The expression
- which contained the function call has been discarded." It
- is a hard concept to explain in a few words. Ideally, GDB
- would be able to resume evaluation of the expression when
- the function finally is done executing. Perhaps someday
- this will be implemented (it would not be easy). */
-
- /* FIXME: Insert a bunch of wrap_here; name can be very long if it's
- a C++ name with arguments and stuff. */
- error ("\
-The program being debugged stopped while in a function called from GDB.\n\
-When the function (%s) is done executing, GDB will silently\n\
-stop (instead of continuing to evaluate the expression containing\n\
-the function call).", name);
- }
-
- /* If we get here the called FUNCTION run to completion. */
-
- /* Restore the inferior status, via its cleanup. At this stage,
- leave the RETBUF alone. */
- do_cleanups (inf_status_cleanup);
-
- /* Figure out the value returned by the function. */
- /* elz: I defined this new macro for the hppa architecture only.
- this gives us a way to get the value returned by the function
- from the stack, at the same address we told the function to put
- it. We cannot assume on the pa that r28 still contains the
- address of the returned structure. Usually this will be
- overwritten by the callee. I don't know about other
- architectures, so I defined this macro */
-#ifdef VALUE_RETURNED_FROM_STACK
- if (struct_return)
- {
- do_cleanups (retbuf_cleanup);
- return VALUE_RETURNED_FROM_STACK (value_type, struct_addr);
- }
-#endif
- /* NOTE: cagney/2002-09-10: Only when the stack has been correctly
- aligned (using frame_align()) do we can trust STRUCT_ADDR and
- fetch the return value direct from the stack. This lack of
- trust comes about because legacy targets have a nasty habit of
- silently, and local to PUSH_ARGUMENTS(), moving STRUCT_ADDR.
- For such targets, just hope that value_being_returned() can
- find the adjusted value. */
- if (struct_return && gdbarch_frame_align_p (current_gdbarch))
- {
- struct value *retval = value_at (value_type, struct_addr, NULL);
- do_cleanups (retbuf_cleanup);
- return retval;
- }
- else
- {
- struct value *retval = value_being_returned (value_type, retbuf,
- struct_return);
- do_cleanups (retbuf_cleanup);
- return retval;
- }
- }
-}
-
/* Create a value for an array by allocating space in the inferior, copying
the data into that space, and then setting up an array value.
@@ -3485,29 +2683,4 @@ _initialize_valops (void)
&setlist),
&showlist);
overload_resolution = 1;
-
- add_show_from_set (
- add_set_cmd ("unwindonsignal", no_class, var_boolean,
- (char *) &unwind_on_signal_p,
-"Set unwinding of stack if a signal is received while in a call dummy.\n\
-The unwindonsignal lets the user determine what gdb should do if a signal\n\
-is received while in a function called from gdb (call dummy). If set, gdb\n\
-unwinds the stack and restore the context to what as it was before the call.\n\
-The default is to stop in the frame where the signal was received.", &setlist),
- &showlist);
-
- add_show_from_set
- (add_set_cmd ("coerce-float-to-double", class_obscure, var_boolean,
- (char *) &coerce_float_to_double,
- "Set coercion of floats to doubles when calling functions\n"
- "Variables of type float should generally be converted to doubles before\n"
- "calling an unprototyped function, and left alone when calling a prototyped\n"
- "function. However, some older debug info formats do not provide enough\n"
- "information to determine that a function is prototyped. If this flag is\n"
- "set, GDB will perform the conversion for a function it considers\n"
- "unprototyped.\n"
- "The default is to perform the conversion.\n",
- &setlist),
- &showlist);
- coerce_float_to_double = 1;
}