X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Finfcall.c;h=5553fc9779179b32504b8382ee168437b0dd960f;hb=e76b224615f88255a3fd20d613983dde6cc240b3;hp=50fae6d64f531a0c04ece078742530ffeb80c586;hpb=3d6e9d2336c9ffcedb10f89631981a23dd518e8e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infcall.c b/gdb/infcall.c index 50fae6d64f..5553fc9779 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -41,7 +41,7 @@ #include "interps.h" #include "thread-fsm.h" #include -#include "common/scope-exit.h" +#include "gdbsupport/scope-exit.h" /* If we can't find a function's name from its address, we print this instead. */ @@ -55,6 +55,17 @@ asynchronous inferior function call implementation, and that in turn means restructuring the code so that it is event driven. */ +static bool may_call_functions_p = true; +static void +show_may_call_functions_p (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + fprintf_filtered (file, + _("Permission to call functions in the program is %s.\n"), + value); +} + /* 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 @@ -75,7 +86,7 @@ trust the debug information; the user can override this behavior with "set coerce-float-to-double 0". */ -static int coerce_float_to_double_p = 1; +static bool coerce_float_to_double_p = true; static void show_coerce_float_to_double_p (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -93,7 +104,7 @@ show_coerce_float_to_double_p (struct ui_file *file, int from_tty, The default is to stop in the frame where the signal was received. */ -static int unwind_on_signal_p = 0; +static bool unwind_on_signal_p = false; static void show_unwind_on_signal_p (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -116,7 +127,7 @@ show_unwind_on_signal_p (struct ui_file *file, int from_tty, The default is to unwind the frame if a std::terminate call is made. */ -static int unwind_on_terminating_exception_p = 1; +static bool unwind_on_terminating_exception_p = true; static void show_unwind_on_terminating_exception_p (struct ui_file *file, int from_tty, @@ -134,13 +145,11 @@ show_unwind_on_terminating_exception_p (struct ui_file *file, int from_tty, for arguments to be passed to C, Ada or Fortran functions. If PARAM_TYPE is non-NULL, it is the expected parameter type. - IS_PROTOTYPED is non-zero if the function declaration is prototyped. - SP is the stack pointer were additional data can be pushed (updating - its value as needed). */ + IS_PROTOTYPED is non-zero if the function declaration is prototyped. */ static struct value * value_arg_coerce (struct gdbarch *gdbarch, struct value *arg, - struct type *param_type, int is_prototyped, CORE_ADDR *sp) + struct type *param_type, int is_prototyped) { const struct builtin_type *builtin = builtin_type (gdbarch); struct type *arg_type = check_typedef (value_type (arg)); @@ -378,7 +387,7 @@ get_function_name (CORE_ADDR funaddr, char *buf, int buf_size) struct symbol *symbol = find_pc_function (funaddr); if (symbol) - return SYMBOL_PRINT_NAME (symbol); + return symbol->print_name (); } { @@ -386,7 +395,7 @@ get_function_name (CORE_ADDR funaddr, char *buf, int buf_size) struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (funaddr); if (msymbol.minsym) - return MSYMBOL_PRINT_NAME (msymbol.minsym); + return msymbol.minsym->print_name (); } { @@ -568,7 +577,7 @@ static struct gdb_exception run_inferior_call (struct call_thread_fsm *sm, struct thread_info *call_thread, CORE_ADDR real_pc) { - struct gdb_exception caught_error = exception_none; + struct gdb_exception caught_error; int saved_in_infcall = call_thread->control.in_infcall; ptid_t call_thread_ptid = call_thread->ptid; enum prompt_state saved_prompt_state = current_ui->prompt_state; @@ -597,7 +606,7 @@ run_inferior_call (struct call_thread_fsm *sm, /* We want to print return value, please... */ call_thread->control.proceed_to_finish = 1; - TRY + try { proceed (real_pc, GDB_SIGNAL_0); @@ -605,11 +614,10 @@ run_inferior_call (struct call_thread_fsm *sm, target supports asynchronous execution. */ wait_sync_command_done (); } - CATCH (e, RETURN_MASK_ALL) + catch (gdb_exception &e) { - caught_error = e; + caught_error = std::move (e); } - END_CATCH /* If GDB has the prompt blocked before, then ensure that it remains so. normal_stop calls async_enable_stdin, so reset the prompt @@ -660,6 +668,42 @@ run_inferior_call (struct call_thread_fsm *sm, return caught_error; } +/* Reserve space on the stack for a value of the given type. + Return the address of the allocated space. + Make certain that the value is correctly aligned. + The SP argument is modified. */ + +static CORE_ADDR +reserve_stack_space (const type *values_type, CORE_ADDR &sp) +{ + struct frame_info *frame = get_current_frame (); + struct gdbarch *gdbarch = get_frame_arch (frame); + CORE_ADDR addr = 0; + + if (gdbarch_inner_than (gdbarch, 1, 2)) + { + /* Stack grows downward. Align STRUCT_ADDR and SP after + making space. */ + sp -= TYPE_LENGTH (values_type); + if (gdbarch_frame_align_p (gdbarch)) + sp = gdbarch_frame_align (gdbarch, sp); + addr = sp; + } + else + { + /* Stack grows upward. Align the frame, allocate space, and + then again, re-align the frame??? */ + if (gdbarch_frame_align_p (gdbarch)) + sp = gdbarch_frame_align (gdbarch, sp); + addr = sp; + sp += TYPE_LENGTH (values_type); + if (gdbarch_frame_align_p (gdbarch)) + sp = gdbarch_frame_align (gdbarch, sp); + } + + return addr; +} + /* See infcall.h. */ struct value * @@ -681,7 +725,7 @@ call_function_by_hand (struct value *function, 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). + ARGS is a vector of values of arguments. 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 @@ -709,6 +753,10 @@ call_function_by_hand_dummy (struct value *function, struct gdb_exception e; char name_buf[RAW_FUNCTION_ADDRESS_SIZE]; + if (!may_call_functions_p) + error (_("Cannot call functions in the program: " + "may-call-functions is off.")); + if (!target_has_execution) noprocess (); @@ -732,6 +780,27 @@ call_function_by_hand_dummy (struct value *function, if (!gdbarch_push_dummy_call_p (gdbarch)) error (_("This target does not support function calls.")); + /* Find the function type and do a sanity check. */ + type *ftype; + type *values_type; + CORE_ADDR funaddr = find_function_addr (function, &values_type, &ftype); + + if (values_type == NULL) + values_type = default_return_type; + if (values_type == NULL) + { + const char *name = get_function_name (funaddr, + name_buf, sizeof (name_buf)); + error (_("'%s' has unknown return type; " + "cast the call to its declared return type"), + name); + } + + values_type = check_typedef (values_type); + + if (args.size () < TYPE_NFIELDS (ftype)) + error (_("Too few arguments in function call.")); + /* A holder for the inferior status. This is only needed while we're preparing the inferior function call. */ infcall_control_state_up inf_status (save_infcall_control_state ()); @@ -772,7 +841,7 @@ call_function_by_hand_dummy (struct value *function, 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 + surprisingly, 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. @@ -837,23 +906,6 @@ call_function_by_hand_dummy (struct value *function, } } - type *ftype; - type *values_type; - CORE_ADDR funaddr = find_function_addr (function, &values_type, &ftype); - - if (values_type == NULL) - values_type = default_return_type; - if (values_type == NULL) - { - const char *name = get_function_name (funaddr, - name_buf, sizeof (name_buf)); - error (_("'%s' has unknown return type; " - "cast the call to its declared return type"), - name); - } - - values_type = check_typedef (values_type); - /* Are we returning a value using a structure return? */ if (gdbarch_return_in_first_hidden_param_p (gdbarch, values_type)) @@ -931,9 +983,6 @@ call_function_by_hand_dummy (struct value *function, internal_error (__FILE__, __LINE__, _("bad switch")); } - if (args.size () < TYPE_NFIELDS (ftype)) - error (_("Too few arguments in function call.")); - for (int i = args.size () - 1; i >= 0; i--) { int prototyped; @@ -969,15 +1018,14 @@ call_function_by_hand_dummy (struct value *function, param_type = NULL; args[i] = value_arg_coerce (gdbarch, args[i], - param_type, prototyped, &sp); + param_type, prototyped); if (param_type != NULL && language_pass_by_reference (param_type)) args[i] = value_addr (args[i]); } /* Reserve space for the return structure to be written on the - stack, if necessary. Make certain that the value is correctly - aligned. + stack, if necessary. While evaluating expressions, we reserve space on the stack for return values of class type even if the language ABI and the target @@ -992,28 +1040,7 @@ call_function_by_hand_dummy (struct value *function, if (return_method != return_method_normal || (stack_temporaries && class_or_union_p (values_type))) - { - if (gdbarch_inner_than (gdbarch, 1, 2)) - { - /* Stack grows downward. Align STRUCT_ADDR and SP after - making space for the return value. */ - sp -= TYPE_LENGTH (values_type); - if (gdbarch_frame_align_p (gdbarch)) - sp = gdbarch_frame_align (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 (gdbarch)) - sp = gdbarch_frame_align (gdbarch, sp); - struct_addr = sp; - sp += TYPE_LENGTH (values_type); - if (gdbarch_frame_align_p (gdbarch)) - sp = gdbarch_frame_align (gdbarch, sp); - } - } + struct_addr = reserve_stack_space (values_type, sp); std::vector new_args; if (return_method == return_method_hidden_param) @@ -1196,7 +1223,7 @@ When the function is done executing, GDB will silently stop."), e.what (), name); case RETURN_QUIT: default: - throw_exception (e); + throw_exception (std::move (e)); } } @@ -1360,17 +1387,28 @@ When the function is done executing, GDB will silently stop."), void _initialize_infcall (void) { + add_setshow_boolean_cmd ("may-call-functions", no_class, + &may_call_functions_p, _("\ +Set permission to call functions in the program."), _("\ +Show permission to call functions in the program."), _("\ +When this permission is on, GDB may call functions in the program.\n\ +Otherwise, any sort of attempt to call a function in the program\n\ +will result in an error."), + NULL, + show_may_call_functions_p, + &setlist, &showlist); + add_setshow_boolean_cmd ("coerce-float-to-double", class_obscure, &coerce_float_to_double_p, _("\ Set coercion of floats to doubles when calling functions."), _("\ -Show coercion of floats to doubles when calling functions"), _("\ +Show coercion of floats to doubles when calling functions."), _("\ 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"), +The default is to perform the conversion."), NULL, show_coerce_float_to_double_p, &setlist, &showlist);