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 Free Software Foundation, Inc.
+ 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "breakpoint.h"
+#include "tracepoint.h"
#include "target.h"
#include "regcache.h"
#include "inferior.h"
/* Perform any Ada-specific coercion first. */
if (current_language->la_language == language_ada)
- arg = ada_convert_actual (arg, type, sp);
+ arg = ada_convert_actual (arg, type, gdbarch, sp);
/* Force the value to the target if we will need its address. At
this point, we could allocate arguments on the stack instead of
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);
enum type_code code = TYPE_CODE (ftype);
struct type *value_type = NULL;
CORE_ADDR funaddr;
if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
|| TYPE_CODE (ftype) == TYPE_CODE_METHOD)
{
- funaddr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
- funaddr,
+ funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
¤t_target);
value_type = TYPE_TARGET_TYPE (ftype);
}
{
/* Handle function descriptors lacking debug info. */
int found_descriptor = 0;
+
funaddr = 0; /* pacify "gcc -Werror" */
if (VALUE_LVAL (function) == lval_memory)
{
CORE_ADDR nfunaddr;
+
funaddr = value_as_address (value_addr (function));
nfunaddr = funaddr;
- funaddr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
- funaddr,
+ funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
¤t_target);
if (funaddr != nfunaddr)
found_descriptor = 1;
if (retval_type != NULL)
*retval_type = value_type;
- return funaddr + gdbarch_deprecated_function_start_offset (current_gdbarch);
+ return funaddr + gdbarch_deprecated_function_start_offset (gdbarch);
}
/* For CALL_DUMMY_ON_STACK, push a breakpoint sequence that the called
{
{
struct symbol *symbol = find_pc_function (funaddr);
+
if (symbol)
return SYMBOL_PRINT_NAME (symbol);
}
{
/* Try the minimal symbols. */
struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (funaddr);
+
if (msymbol)
return SYMBOL_PRINT_NAME (msymbol);
}
{
char *tmp = xstrprintf (_(RAW_FUNCTION_ADDRESS_FORMAT),
hex_string (funaddr));
+
gdb_assert (strlen (tmp) + 1 <= buf_size);
strcpy (buf, tmp);
xfree (tmp);
return e;
}
+/* A cleanup function that calls delete_std_terminate_breakpoint. */
+static void
+cleanup_delete_std_terminate_breakpoint (void *ignore)
+{
+ delete_std_terminate_breakpoint ();
+}
+
/* 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
struct cleanup *args_cleanup;
struct frame_info *frame;
struct gdbarch *gdbarch;
- struct breakpoint *terminate_bp = NULL;
- struct minimal_symbol *tm;
+ struct cleanup *terminate_bp_cleanup;
ptid_t call_thread_ptid;
struct gdb_exception e;
- const char *name;
char name_buf[RAW_FUNCTION_ADDRESS_SIZE];
if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
if (!target_has_execution)
noprocess ();
+ if (get_traceframe_number () >= 0)
+ error (_("May not call functions while looking at trace frames."));
+
frame = get_current_frame ();
gdbarch = get_frame_arch (frame);
/* Ensure that the initial SP is correctly aligned. */
{
CORE_ADDR old_sp = get_frame_sp (frame);
+
if (gdbarch_frame_align_p (gdbarch))
{
sp = gdbarch_frame_align (gdbarch, old_sp);
/* Stack grows up. */
sp = gdbarch_frame_align (gdbarch, old_sp + 1);
}
- gdb_assert ((gdbarch_inner_than (gdbarch, 1, 2)
- && sp <= old_sp)
- || (gdbarch_inner_than (gdbarch, 2, 1)
- && sp >= old_sp));
+ /* SP may have underflown address zero here from OLD_SP. Memory access
+ functions will probably fail in such case but that is a target's
+ problem. */
}
else
/* FIXME: cagney/2002-09-18: Hey, you loose!
/* Tell the target specific argument pushing routine not to
expect a value. */
- target_values_type = builtin_type_void;
+ target_values_type = builtin_type (gdbarch)->builtin_void;
}
else
{
real_pc = funaddr;
dummy_addr = entry_point_address ();
- /* 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);
/* 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;
sym = lookup_minimal_symbol ("__CALL_DUMMY_ADDRESS", NULL, NULL);
real_pc = funaddr;
if (sym)
- dummy_addr = SYMBOL_VALUE_ADDRESS (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 ();
- /* 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);
/* A call dummy always consists of just a single breakpoint,
so it's address is the same as the address of the dummy. */
bp_addr = dummy_addr;
{
int i;
+
for (i = nargs - 1; i >= 0; i--)
{
int prototyped;
if (struct_return || lang_struct_return)
{
int len = TYPE_LENGTH (values_type);
+
if (gdbarch_inner_than (gdbarch, 1, 2))
{
/* Stack grows downward. Align STRUCT_ADDR and SP after
{
struct breakpoint *bpt;
struct symtab_and_line sal;
+
init_sal (&sal); /* initialize to zeroes */
+ sal.pspace = current_program_space;
sal.pc = bp_addr;
sal.section = find_pc_overlay (sal.pc);
/* Sanity. The exact same SP value is returned by
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 (sal, dummy_id, bp_call_dummy);
+ bpt = set_momentary_breakpoint (gdbarch, sal, dummy_id, bp_call_dummy);
bpt->disposition = disp_del;
}
call. Place a momentary breakpoint in the std::terminate function
and if triggered in the call, rewind. */
if (unwind_on_terminating_exception_p)
- {
- struct minimal_symbol *tm = lookup_minimal_symbol ("std::terminate()",
- NULL, NULL);
- if (tm != NULL)
- terminate_bp = set_momentary_breakpoint_at_pc
- (SYMBOL_VALUE_ADDRESS (tm), bp_breakpoint);
- }
+ 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
discard_cleanups (inf_status_cleanup);
/* Register a clean-up for unwind_on_terminating_exception_breakpoint. */
- if (terminate_bp)
- make_cleanup_delete_breakpoint (terminate_bp);
+ terminate_bp_cleanup = make_cleanup (cleanup_delete_std_terminate_breakpoint,
+ NULL);
/* - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP -
If you're looking to implement asynchronous dummy-frames, then
name);
}
- if (stopped_by_random_signal || !stop_stack_dummy)
+ if (stopped_by_random_signal || stop_stack_dummy != STOP_STACK_DUMMY)
{
const char *name = get_function_name (funaddr,
name_buf, sizeof (name_buf));
}
}
- if (!stop_stack_dummy)
+ if (stop_stack_dummy == STOP_STD_TERMINATE)
{
+ /* We must get back to the frame we were before the dummy
+ call. */
+ dummy_frame_pop (dummy_id);
- /* Check if unwind on terminating exception behaviour is on. */
- if (unwind_on_terminating_exception_p)
- {
- /* Check that the breakpoint is our special std::terminate
- breakpoint. If it is, we do not want to kill the inferior
- in an inferior function call. Rewind, and warn the
- user. */
-
- if (terminate_bp != NULL
- && (inferior_thread()->stop_bpstat->breakpoint_at->address
- == terminate_bp->loc->address))
- {
- /* We must get back to the frame we were before the
- dummy call. */
- dummy_frame_pop (dummy_id);
-
- /* We also need to restore inferior status to that before the
- dummy call. */
- restore_inferior_status (inf_status);
-
- error (_("\
+ /* We also need to restore inferior status to that before
+ the dummy call. */
+ restore_inferior_status (inf_status);
+
+ error (_("\
The program being debugged entered a std::terminate call, most likely\n\
caused by an unhandled C++ exception. GDB blocked this call in order\n\
to prevent the program from being terminated, and has restored the\n\
To change this behaviour use \"set unwind-on-terminating-exception off\".\n\
Evaluation of the expression containing the function (%s)\n\
will be abandoned."),
- name);
- }
- }
+ name);
+ }
+ else if (stop_stack_dummy == STOP_NONE)
+ {
+
/* We hit a breakpoint inside the FUNCTION.
Keep the dummy frame, the user may want to examine its state.
Discard inferior status, we're not at the same point
internal_error (__FILE__, __LINE__, _("... should not be here"));
}
+ do_cleanups (terminate_bp_cleanup);
+
/* If we get here the called FUNCTION ran to completion,
and the dummy frame has already been popped. */
{
- struct regcache *retbuf = regcache_xmalloc (gdbarch);
+ 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;