X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Finfcall.c;h=139c361aa403fb59b16886d13e2b03fa0228f1f4;hb=0e1862bb401f47716446aef143b2bf7a4563f541;hp=ca23704a7141839b21a874ba57c446f270b4dc89;hpb=07be84bf8f6a00301ce539a651d1bc717e402b8f;p=binutils-gdb.git diff --git a/gdb/infcall.c b/gdb/infcall.c index ca23704a714..139c361aa40 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -1,8 +1,6 @@ /* Perform an inferior function call, for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2015 Free Software Foundation, Inc. This file is part of GDB. @@ -25,19 +23,19 @@ #include "target.h" #include "regcache.h" #include "inferior.h" -#include "gdb_assert.h" +#include "infrun.h" #include "block.h" #include "gdbcore.h" #include "language.h" #include "objfiles.h" #include "gdbcmd.h" #include "command.h" -#include "gdb_string.h" #include "infcall.h" #include "dummy-frame.h" #include "ada-lang.h" #include "gdbthread.h" -#include "exceptions.h" +#include "event-top.h" +#include "observer.h" /* If we can't find a function's name from its address, we print this instead. */ @@ -90,7 +88,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. */ -int unwind_on_signal_p = 0; +static int unwind_on_signal_p = 0; static void show_unwind_on_signal_p (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -161,7 +159,7 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg, struct value *new_value; if (TYPE_CODE (arg_type) == TYPE_CODE_REF) - return value_cast_pointers (type, arg); + return value_cast_pointers (type, arg, 0); /* Cast the value to the reference's target type, and then convert it back to a reference. This will issue an error @@ -215,7 +213,6 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg, case TYPE_CODE_SET: case TYPE_CODE_RANGE: case TYPE_CODE_STRING: - case TYPE_CODE_BITSTRING: case TYPE_CODE_ERROR: case TYPE_CODE_MEMBERPTR: case TYPE_CODE_METHODPTR: @@ -252,7 +249,8 @@ find_function_addr (struct value *function, struct type **retval_type) struct type *ftype = check_typedef (value_type (function)); struct gdbarch *gdbarch = get_type_arch (ftype); struct type *value_type = NULL; - CORE_ADDR funaddr; + /* Initialize it just to avoid a GCC false warning. */ + CORE_ADDR funaddr = 0; /* If it's a member function, just look at the function part of it. */ @@ -357,10 +355,10 @@ get_function_name (CORE_ADDR funaddr, char *buf, int buf_size) { /* Try the minimal symbols. */ - struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (funaddr); + struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (funaddr); - if (msymbol) - return SYMBOL_PRINT_NAME (msymbol); + if (msymbol.minsym) + return MSYMBOL_PRINT_NAME (msymbol.minsym); } { @@ -385,36 +383,76 @@ get_function_name (CORE_ADDR funaddr, char *buf, int buf_size) static struct gdb_exception run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc) { - volatile struct gdb_exception e; - int saved_async = 0; + struct gdb_exception caught_error = exception_none; int saved_in_infcall = call_thread->control.in_infcall; ptid_t call_thread_ptid = call_thread->ptid; - char *saved_target_shortname = xstrdup (target_shortname); + int saved_sync_execution = sync_execution; + int was_running = call_thread->state == THREAD_RUNNING; + + /* Infcalls run synchronously, in the foreground. */ + if (target_can_async_p ()) + sync_execution = 1; call_thread->control.in_infcall = 1; - clear_proceed_status (); + clear_proceed_status (0); disable_watchpoints_before_interactive_call_start (); - /* We want stop_registers, please... */ + /* We want to print return value, please... */ call_thread->control.proceed_to_finish = 1; - if (target_can_async_p ()) - saved_async = target_async_mask (0); + TRY + { + int was_sync = sync_execution; + + proceed (real_pc, GDB_SIGNAL_0); - TRY_CATCH (e, RETURN_MASK_ALL) - proceed (real_pc, TARGET_SIGNAL_0, 0); + /* Inferior function calls are always synchronous, even if the + target supports asynchronous execution. Do here what + `proceed' itself does in sync mode. */ + if (target_can_async_p ()) + { + wait_for_inferior (); + normal_stop (); + /* If GDB was previously in sync execution mode, then ensure + that it remains so. normal_stop calls + async_enable_stdin, so reset it again here. In other + cases, stdin will be re-enabled by + inferior_event_handler, when an exception is thrown. */ + if (was_sync) + async_disable_stdin (); + } + } + CATCH (e, RETURN_MASK_ALL) + { + caught_error = e; + } + END_CATCH /* At this point the current thread may have changed. Refresh CALL_THREAD as it could be invalid if its thread has exited. */ call_thread = find_thread_ptid (call_thread_ptid); - /* Don't restore the async mask if the target has changed, - saved_async is for the original target. */ - if (saved_async - && strcmp (saved_target_shortname, target_shortname) == 0) - target_async_mask (saved_async); + /* If the infcall does NOT succeed, normal_stop will have already + finished the thread states. However, on success, normal_stop + defers here, so that we can set back the thread states to what + they were before the call. Note that we must also finish the + state of new threads that might have spawned while the call was + running. The main cases to handle are: + + - "(gdb) print foo ()", or any other command that evaluates an + expression at the prompt. (The thread was marked stopped before.) + + - "(gdb) break foo if return_false()" or similar cases where we + do an infcall while handling an event (while the thread is still + marked running). In this example, whether the condition + evaluates true and thus we'll present a user-visible stop is + decided elsewhere. */ + if (!was_running + && ptid_equal (call_thread_ptid, inferior_ptid) + && stop_stack_dummy == STOP_STACK_DUMMY) + finish_thread_state (user_visible_resume_ptid (0)); enable_watchpoints_after_interactive_call_stop (); @@ -423,7 +461,7 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc) If all error()s out of proceed ended up calling normal_stop (and perhaps they should; it already does in the special case of error out of resume()), then we wouldn't need this. */ - if (e.reason < 0) + if (caught_error.reason < 0) { if (call_thread != NULL) breakpoint_auto_delete (call_thread->control.stop_bpstat); @@ -432,9 +470,9 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc) if (call_thread != NULL) call_thread->control.in_infcall = saved_in_infcall; - xfree (saved_target_shortname); + sync_execution = saved_sync_execution; - return e; + return caught_error; } /* A cleanup function that calls delete_std_terminate_breakpoint. */ @@ -444,6 +482,104 @@ cleanup_delete_std_terminate_breakpoint (void *ignore) delete_std_terminate_breakpoint (); } +/* See infcall.h. */ + +struct value * +call_function_by_hand (struct value *function, int nargs, struct value **args) +{ + return call_function_by_hand_dummy (function, nargs, args, NULL, NULL); +} + +/* Data for dummy_frame_context_saver. Structure can be freed only + after both dummy_frame_context_saver_dtor and + dummy_frame_context_saver_drop have been called for it. */ + +struct dummy_frame_context_saver +{ + /* Inferior registers fetched before associated dummy_frame got freed + and before any other destructors of associated dummy_frame got called. + It is initialized to NULL. */ + struct regcache *retbuf; + + /* It is 1 if this dummy_frame_context_saver_drop has been already + called. */ + int drop_done; +}; + +/* Free struct dummy_frame_context_saver. */ + +static void +dummy_frame_context_saver_free (struct dummy_frame_context_saver *saver) +{ + regcache_xfree (saver->retbuf); + xfree (saver); +} + +/* Destructor for associated dummy_frame. */ + +static void +dummy_frame_context_saver_dtor (void *data_voidp, int registers_valid) +{ + struct dummy_frame_context_saver *data = data_voidp; + + gdb_assert (data->retbuf == NULL); + + if (data->drop_done) + dummy_frame_context_saver_free (data); + else if (registers_valid) + data->retbuf = regcache_dup (get_current_regcache ()); +} + +/* Caller is no longer interested in this + struct dummy_frame_context_saver. After its associated dummy_frame + gets freed struct dummy_frame_context_saver can be also freed. */ + +void +dummy_frame_context_saver_drop (struct dummy_frame_context_saver *saver) +{ + saver->drop_done = 1; + + if (!find_dummy_frame_dtor (dummy_frame_context_saver_dtor, saver)) + dummy_frame_context_saver_free (saver); +} + +/* Stub dummy_frame_context_saver_drop compatible with make_cleanup. */ + +void +dummy_frame_context_saver_cleanup (void *data) +{ + struct dummy_frame_context_saver *saver = data; + + dummy_frame_context_saver_drop (saver); +} + +/* Fetch RETBUF field of possibly opaque DTOR_DATA. + RETBUF must not be NULL. */ + +struct regcache * +dummy_frame_context_saver_get_regs (struct dummy_frame_context_saver *saver) +{ + gdb_assert (saver->retbuf != NULL); + return saver->retbuf; +} + +/* Register provider of inferior registers at the time DUMMY_ID frame of + PTID gets freed (before inferior registers get restored to those + before dummy_frame). */ + +struct dummy_frame_context_saver * +dummy_frame_context_saver_setup (struct frame_id dummy_id, ptid_t ptid) +{ + struct dummy_frame_context_saver *saver; + + saver = xmalloc (sizeof (*saver)); + saver->retbuf = NULL; + saver->drop_done = 0; + register_dummy_frame_dtor (dummy_id, inferior_ptid, + dummy_frame_context_saver_dtor, saver); + return saver; +} + /* 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 @@ -463,11 +599,14 @@ cleanup_delete_std_terminate_breakpoint (void *ignore) ARGS is modified to contain coerced values. */ struct value * -call_function_by_hand (struct value *function, int nargs, struct value **args) +call_function_by_hand_dummy (struct value *function, + int nargs, struct value **args, + dummy_frame_dtor_ftype *dummy_dtor, + void *dummy_dtor_data) { CORE_ADDR sp; struct type *values_type, *target_values_type; - unsigned char struct_return = 0, lang_struct_return = 0; + unsigned char struct_return = 0, hidden_first_param_p = 0; CORE_ADDR struct_addr = 0; struct infcall_control_state *inf_status; struct cleanup *inf_status_cleanup; @@ -484,6 +623,9 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) ptid_t call_thread_ptid; struct gdb_exception e; char name_buf[RAW_FUNCTION_ADDRESS_SIZE]; + int stack_temporaries = thread_stack_temporaries_enabled_p (inferior_ptid); + struct dummy_frame_context_saver *context_saver; + struct cleanup *context_saver_cleanup; if (TYPE_CODE (ftype) == TYPE_CODE_PTR) ftype = check_typedef (TYPE_TARGET_TYPE (ftype)); @@ -494,6 +636,9 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) if (get_traceframe_number () >= 0) error (_("May not call functions while looking at trace frames.")); + if (execution_direction == EXEC_REVERSE) + error (_("Cannot call functions in reverse mode.")); + frame = get_current_frame (); gdbarch = get_frame_arch (frame); @@ -579,13 +724,40 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) If the ABI specifies a "Red Zone" (see the doco) the code below will quietly trash it. */ sp = old_sp; + + /* Skip over the stack temporaries that might have been generated during + the evaluation of an expression. */ + if (stack_temporaries) + { + struct value *lastval; + + lastval = get_last_thread_stack_temporary (inferior_ptid); + if (lastval != NULL) + { + CORE_ADDR lastval_addr = value_address (lastval); + + if (gdbarch_inner_than (gdbarch, 1, 2)) + { + gdb_assert (sp >= lastval_addr); + sp = lastval_addr; + } + else + { + gdb_assert (sp <= lastval_addr); + sp = lastval_addr + TYPE_LENGTH (value_type (lastval)); + } + + if (gdbarch_frame_align_p (gdbarch)) + sp = gdbarch_frame_align (gdbarch, sp); + } + } } funaddr = find_function_addr (function, &values_type); if (!values_type) values_type = builtin_type (gdbarch)->builtin_int; - CHECK_TYPEDEF (values_type); + values_type = check_typedef (values_type); /* Are we returning a value using a structure return (passing a hidden argument pointing to storage) or a normal value return? @@ -598,9 +770,9 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) the first argument is passed in out0 but the hidden structure return pointer would normally be passed in r8. */ - if (language_pass_by_reference (values_type)) + if (gdbarch_return_in_first_hidden_param_p (gdbarch, values_type)) { - lang_struct_return = 1; + hidden_first_param_p = 1; /* Tell the target specific argument pushing routine not to expect a value. */ @@ -608,26 +780,50 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) } else { - struct_return = using_struct_return (gdbarch, - value_type (function), values_type); + struct_return = using_struct_return (gdbarch, function, values_type); target_values_type = values_type; } + observer_notify_inferior_call_pre (inferior_ptid, funaddr); + /* Determine the location of the breakpoint (and possibly other stuff) that the called function will return to. The SPARC, for a function returning a structure or union, needs to make space for not just the breakpoint but also an extra word containing the size (?) of the structure being passed. */ - /* The actual breakpoint (at BP_ADDR) is inserted separatly so there - is no need to write that out. */ - switch (gdbarch_call_dummy_location (gdbarch)) { case ON_STACK: - sp = push_dummy_code (gdbarch, sp, funaddr, - args, nargs, target_values_type, - &real_pc, &bp_addr, get_current_regcache ()); + { + const gdb_byte *bp_bytes; + CORE_ADDR bp_addr_as_address; + int bp_size; + + /* Be careful BP_ADDR is in inferior PC encoding while + BP_ADDR_AS_ADDRESS is a plain memory address. */ + + sp = push_dummy_code (gdbarch, sp, funaddr, args, nargs, + target_values_type, &real_pc, &bp_addr, + get_current_regcache ()); + + /* Write a legitimate instruction at the point where the infcall + breakpoint is going to be inserted. While this instruction + is never going to be executed, a user investigating the + memory from GDB would see this instruction instead of random + uninitialized bytes. We chose the breakpoint instruction + as it may look as the most logical one to the user and also + valgrind 3.7.0 needs it for proper vgdb inferior calls. + + If software breakpoints are unsupported for this target we + leave the user visible memory content uninitialized. */ + + bp_addr_as_address = bp_addr; + bp_bytes = gdbarch_breakpoint_from_pc (gdbarch, &bp_addr_as_address, + &bp_size); + if (bp_bytes != NULL) + write_memory (bp_addr_as_address, bp_bytes, bp_size); + } break; case AT_ENTRY_POINT: { @@ -635,35 +831,12 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) real_pc = funaddr; dummy_addr = entry_point_address (); + /* A call dummy always consists of just a single breakpoint, so - its address is the same as the address of the dummy. */ - bp_addr = dummy_addr; - break; - } - case AT_SYMBOL: - /* Some executables define a symbol __CALL_DUMMY_ADDRESS whose - address is the location where the breakpoint should be - placed. Once all targets are using the overhauled frame code - this can be deleted - ON_STACK is a better option. */ - { - struct minimal_symbol *sym; - CORE_ADDR dummy_addr; + its address is the same as the address of the dummy. - sym = lookup_minimal_symbol ("__CALL_DUMMY_ADDRESS", NULL, NULL); - real_pc = funaddr; - if (sym) - { - dummy_addr = SYMBOL_VALUE_ADDRESS (sym); - /* Make certain that the address points at real code, and not - a function descriptor. */ - dummy_addr = gdbarch_convert_from_func_ptr_addr (gdbarch, - dummy_addr, - ¤t_target); - } - else - dummy_addr = entry_point_address (); - /* A call dummy always consists of just a single breakpoint, - so it's address is the same as the address of the dummy. */ + The actual breakpoint is inserted separatly so there is no need to + write that out. */ bp_addr = dummy_addr; break; } @@ -706,17 +879,27 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) /* Reserve space for the return structure to be written on the stack, if necessary. Make certain that the value is correctly - aligned. */ + aligned. - if (struct_return || lang_struct_return) - { - int len = TYPE_LENGTH (values_type); + While evaluating expressions, we reserve space on the stack for + return values of class type even if the language ABI and the target + ABI do not require that the return value be passed as a hidden first + argument. This is because we want to store the return value as an + on-stack temporary while the expression is being evaluated. This + enables us to have chained function calls in expressions. + + Keeping the return values as on-stack temporaries while the expression + is being evaluated is OK because the thread is stopped until the + expression is completely evaluated. */ + if (struct_return || hidden_first_param_p + || (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 -= len; + sp -= TYPE_LENGTH (values_type); if (gdbarch_frame_align_p (gdbarch)) sp = gdbarch_frame_align (gdbarch, sp); struct_addr = sp; @@ -728,13 +911,13 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) if (gdbarch_frame_align_p (gdbarch)) sp = gdbarch_frame_align (gdbarch, sp); struct_addr = sp; - sp += len; + sp += TYPE_LENGTH (values_type); if (gdbarch_frame_align_p (gdbarch)) sp = gdbarch_frame_align (gdbarch, sp); } } - if (lang_struct_return) + if (hidden_first_param_p) { struct value **new_args; @@ -772,7 +955,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) inferior. That way it breaks when it returns. */ { - struct breakpoint *bpt; + struct breakpoint *bpt, *longjmp_b; struct symtab_and_line sal; init_sal (&sal); /* initialize to zeroes */ @@ -783,7 +966,22 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) PUSH_DUMMY_CALL, saved as the dummy-frame TOS, and used by dummy_id to form the frame ID's stack address. */ bpt = set_momentary_breakpoint (gdbarch, sal, dummy_id, bp_call_dummy); + + /* set_momentary_breakpoint invalidates FRAME. */ + frame = NULL; + bpt->disposition = disp_del; + gdb_assert (bpt->related_breakpoint == bpt); + + longjmp_b = set_longjmp_breakpoint_for_call_dummy (); + if (longjmp_b) + { + /* Link BPT into the chain of LONGJMP_B. */ + bpt->related_breakpoint = longjmp_b; + while (longjmp_b->related_breakpoint != bpt->related_breakpoint) + longjmp_b = longjmp_b->related_breakpoint; + longjmp_b->related_breakpoint = bpt; + } } /* Create a breakpoint in std::terminate. @@ -801,16 +999,26 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) if (unwind_on_terminating_exception_p) set_std_terminate_breakpoint (); - /* Everything's ready, push all the info needed to restore the - caller (and identify the dummy-frame) onto the dummy-frame - stack. */ - dummy_frame_push (caller_state, &dummy_id); - /* Discard both inf_status and caller_state cleanups. From this point on we explicitly restore the associated state or discard it. */ discard_cleanups (inf_status_cleanup); + /* Everything's ready, push all the info needed to restore the + caller (and identify the dummy-frame) onto the dummy-frame + stack. */ + dummy_frame_push (caller_state, &dummy_id, inferior_ptid); + if (dummy_dtor != NULL) + register_dummy_frame_dtor (dummy_id, inferior_ptid, + dummy_dtor, dummy_dtor_data); + + /* dummy_frame_context_saver_setup must be called last so that its + saving of inferior registers gets called first (before possible + DUMMY_DTOR destructor). */ + context_saver = dummy_frame_context_saver_setup (dummy_id, inferior_ptid); + context_saver_cleanup = make_cleanup (dummy_frame_context_saver_cleanup, + context_saver); + /* Register a clean-up for unwind_on_terminating_exception_breakpoint. */ terminate_bp_cleanup = make_cleanup (cleanup_delete_std_terminate_breakpoint, NULL); @@ -833,6 +1041,8 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) e = run_inferior_call (tp, real_pc); } + observer_notify_inferior_call_post (call_thread_ptid, funaddr); + /* Rethrow an error if we got one trying to run the inferior. */ if (e.reason < 0) @@ -915,8 +1125,11 @@ When the function is done executing, GDB will silently stop."), if (stopped_by_random_signal || stop_stack_dummy != STOP_STACK_DUMMY) { - const char *name = get_function_name (funaddr, - name_buf, sizeof (name_buf)); + /* Make a copy as NAME may be in an objfile freed by dummy_frame_pop. */ + char *name = xstrdup (get_function_name (funaddr, + name_buf, sizeof (name_buf))); + make_cleanup (xfree, name); + if (stopped_by_random_signal) { @@ -930,7 +1143,7 @@ When the function is done executing, GDB will silently stop."), /* We must get back to the frame we were before the dummy call. */ - dummy_frame_pop (dummy_id); + dummy_frame_pop (dummy_id, call_thread_ptid); /* We also need to restore inferior status to that before the dummy call. */ @@ -971,7 +1184,7 @@ When the function is done executing, GDB will silently stop."), { /* We must get back to the frame we were before the dummy call. */ - dummy_frame_pop (dummy_id); + dummy_frame_pop (dummy_id, call_thread_ptid); /* We also need to restore inferior status to that before the dummy call. */ @@ -1022,46 +1235,51 @@ When the function is done executing, GDB will silently stop."), and the dummy frame has already been popped. */ { - struct address_space *aspace = get_regcache_aspace (stop_registers); - struct regcache *retbuf = regcache_xmalloc (gdbarch, aspace); - struct cleanup *retbuf_cleanup = make_cleanup_regcache_xfree (retbuf); struct value *retval = NULL; - regcache_cpy_no_passthrough (retbuf, stop_registers); - /* Inferior call is successful. Restore the inferior status. At this stage, leave the RETBUF alone. */ restore_infcall_control_state (inf_status); - /* Figure out the value returned by the function. */ - retval = allocate_value (values_type); - - if (lang_struct_return) - read_value_memory (retval, 0, 1, struct_addr, - value_contents_raw (retval), - TYPE_LENGTH (values_type)); - else if (TYPE_CODE (target_values_type) != TYPE_CODE_VOID) + if (TYPE_CODE (values_type) == TYPE_CODE_VOID) + retval = allocate_value (values_type); + else if (struct_return || hidden_first_param_p) { - /* If the function returns void, don't bother fetching the - return value. */ - switch (gdbarch_return_value (gdbarch, value_type (function), - target_values_type, NULL, NULL, NULL)) + if (stack_temporaries) { - case RETURN_VALUE_REGISTER_CONVENTION: - case RETURN_VALUE_ABI_RETURNS_ADDRESS: - case RETURN_VALUE_ABI_PRESERVES_ADDRESS: - gdbarch_return_value (gdbarch, value_type (function), values_type, - retbuf, value_contents_raw (retval), NULL); - break; - case RETURN_VALUE_STRUCT_CONVENTION: + retval = value_from_contents_and_address (values_type, NULL, + struct_addr); + push_thread_stack_temporary (inferior_ptid, retval); + } + else + { + retval = allocate_value (values_type); read_value_memory (retval, 0, 1, struct_addr, value_contents_raw (retval), TYPE_LENGTH (values_type)); - break; + } + } + else + { + retval = allocate_value (values_type); + gdbarch_return_value (gdbarch, function, values_type, + dummy_frame_context_saver_get_regs (context_saver), + value_contents_raw (retval), NULL); + if (stack_temporaries && class_or_union_p (values_type)) + { + /* Values of class type returned in registers are copied onto + the stack and their lval_type set to lval_memory. This is + required because further evaluation of the expression + could potentially invoke methods on the return value + requiring GDB to evaluate the "this" pointer. To evaluate + the this pointer, GDB needs the memory address of the + value. */ + value_force_lval (retval, struct_addr); + push_thread_stack_temporary (inferior_ptid, retval); } } - do_cleanups (retbuf_cleanup); + do_cleanups (context_saver_cleanup); gdb_assert (retval); return retval;