+2008-05-04 Pedro Alves <pedro@codesourcery.com>
+
+ * breakpoint.c (update_breakpoints_after_exec): Delete bp_longjmp
+ and bp_longjmp_resume breakpoints.
+ (breakpoint_address_is_meaningful): Claim bp_longjmp_resume as
+ meaningful.
+ (create_longjmp_breakpoint): Don't create bp_longjmp_resume
+ breakpoints. Create bp_longjmp breakpoints as momentary
+ breakpoints.
+ (enable_longjmp_breakpoint): Delete.
+ (set_longjmp_breakpoint): New.
+ (disable_longjmp_breakpoint): Delete.
+ (delete_longjmp_breakpoint): New.
+ (set_longjmp_resume_breakpoint): Delete.
+ (set_momentary_breakpoint_at_pc): New.
+ (breakpoint_re_set_one): Don't delete bp_longjmp and
+ bp_longjmp_resume breakpoints.
+ (breakpoint_re_set): Don't create longjmp and longjmp-resume
+ breakpoints.
+
+ * infrun.c (step_resume_breakpoint): Add comment.
+ (struct execution_control_state): Delete handling_longjmp member.
+ (init_execution_control_state). Don't clear handling_longjmp.
+ (context_switch): Don't context switch handling_longjmp.
+ (handle_inferior_event): If handling a bp_longjmp breakpoint,
+ create a bp_longjmp_resume breakpoint, and set it as current
+ step_resume_breakpoint, then step over the longjmp breakpoint. If
+ handling a bp_longjmp_resume breakpoint, don't delete the longjmp
+ breakpoint, delete the longjmp-resume breakpoint, and stop
+ stepping.
+ (currently_stepping): Remove handling_longjmp from expression.
+ (insert_step_resume_breakpoint_at_sal): Update comment.
+ (insert_longjmp_resume_breakpoint): New.
+
+ * breakpoint.h (set_momentary_breakpoint_at_pc): Declare.
+ (enable_longjmp_breakpoint, disable_longjmp_breakpoint): Delete
+ declarations.
+ (set_longjmp_breakpoint, delete_longjmp_breakpoint): Declare.
+ (set_longjmp_resume_breakpoint): Delete declaration.
+
+ * gdbthread.h (save_infrun_state): Remove handling_longjmp
+ parameter.
+ (load_infrun_state): Delete *handling_longjmp parameter.
+ * thread.c (save_infrun_state): Remove handling_longjmp parameter.
+ Update body.
+ (load_infrun_state): Delete *handling_longjmp parameter. Update
+ body.
+
+ * infcmd.c (disable_longjmp_breakpoint_cleanup): Delete.
+ (delete_longjmp_breakpoint_cleanup): New.
+ (step_1): Call set_longjmp_breakpoint instead of
+ enable_longjmp_breakpoint. Use delete_longjmp_breakpoint_cleanup
+ instead of disable_longjmp_breakpoint_cleanup when making cleanup.
+ (step_1_continuation): Pass thread id in the continuation args to
+ step_once.
+ (step_once): Add thread parameter. Pass thread id the the
+ continuation.
+
2008-05-04 Jan Kratochvil <jan.kratochvil@redhat.com>
Set CU BASE_ADDRESS already from partial DIEs.
static void maintenance_info_breakpoints (char *, int);
-static void create_longjmp_breakpoint (char *);
-
static void create_overlay_event_breakpoint (char *);
static int hw_breakpoint_used_count (void);
continue;
}
+ /* Longjmp and longjmp-resume breakpoints are also meaningless
+ after an exec. */
+ if (b->type == bp_longjmp || b->type == bp_longjmp_resume)
+ {
+ delete_breakpoint (b);
+ continue;
+ }
+
/* Don't delete an exec catchpoint, because else the inferior
won't stop when it ought!
bp_read_watchpoint
bp_access_watchpoint
bp_catch_exec
- bp_longjmp_resume
bp_catch_fork
bp_catch_vork */
&& type != bp_read_watchpoint
&& type != bp_access_watchpoint
&& type != bp_catch_exec
- && type != bp_longjmp_resume
&& type != bp_catch_fork
&& type != bp_catch_vfork);
}
struct breakpoint *b;
struct minimal_symbol *m;
- if (func_name == NULL)
- b = create_internal_breakpoint (0, bp_longjmp_resume);
- else
- {
- if ((m = lookup_minimal_symbol_text (func_name, NULL)) == NULL)
- return;
-
- b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m), bp_longjmp);
- }
-
- b->enable_state = bp_disabled;
- b->silent = 1;
- if (func_name)
- b->addr_string = xstrdup (func_name);
+ if ((m = lookup_minimal_symbol_text (func_name, NULL)) == NULL)
+ return;
+ set_momentary_breakpoint_at_pc (SYMBOL_VALUE_ADDRESS (m), bp_longjmp);
update_global_location_list ();
}
set_longjmp_resume_breakpoint() to figure out where we are going. */
void
-enable_longjmp_breakpoint (void)
+set_longjmp_breakpoint (void)
{
struct breakpoint *b;
- ALL_BREAKPOINTS (b)
- if (b->type == bp_longjmp)
+ if (gdbarch_get_longjmp_target_p (current_gdbarch))
{
- b->enable_state = bp_enabled;
- update_global_location_list ();
+ create_longjmp_breakpoint ("longjmp");
+ create_longjmp_breakpoint ("_longjmp");
+ create_longjmp_breakpoint ("siglongjmp");
+ create_longjmp_breakpoint ("_siglongjmp");
}
}
+/* Delete all longjmp breakpoints from THREAD. */
void
-disable_longjmp_breakpoint (void)
+delete_longjmp_breakpoint (int thread)
{
- struct breakpoint *b;
+ struct breakpoint *b, *temp;
- ALL_BREAKPOINTS (b)
- if (b->type == bp_longjmp
- || b->type == bp_longjmp_resume)
- {
- b->enable_state = bp_disabled;
- update_global_location_list ();
- }
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ if (b->type == bp_longjmp)
+ {
+ if (b->thread == thread)
+ delete_breakpoint (b);
+ }
}
static void
return i;
}
-/* Call this after hitting the longjmp() breakpoint. Use this to set
- a new breakpoint at the target of the jmp_buf.
-
- FIXME - This ought to be done by setting a temporary breakpoint
- that gets deleted automatically... */
-
-void
-set_longjmp_resume_breakpoint (CORE_ADDR pc, struct frame_id frame_id)
-{
- struct breakpoint *b;
-
- ALL_BREAKPOINTS (b)
- if (b->type == bp_longjmp_resume)
- {
- b->loc->requested_address = pc;
- b->loc->address = adjust_breakpoint_address (b->loc->requested_address,
- b->type);
- b->enable_state = bp_enabled;
- b->frame_id = frame_id;
- update_global_location_list ();
- return;
- }
-}
-
void
disable_watchpoints_before_interactive_call_start (void)
{
return b;
}
+
+struct breakpoint *
+set_momentary_breakpoint_at_pc (CORE_ADDR pc, enum bptype type)
+{
+ struct symtab_and_line sal;
+
+ sal = find_pc_line (pc, 0);
+ sal.pc = pc;
+ sal.section = find_pc_overlay (pc);
+ sal.explicit_pc = 1;
+
+ return set_momentary_breakpoint (sal, null_frame_id, type);
+}
\f
/* Tell the user we have just set a breakpoint B. */
default:
printf_filtered (_("Deleting unknown breakpoint type %d\n"), b->type);
/* fall through */
- /* Delete longjmp and overlay event breakpoints; they will be
- reset later by breakpoint_re_set. */
- case bp_longjmp:
- case bp_longjmp_resume:
+ /* Delete overlay event breakpoints; they will be reset later by
+ breakpoint_re_set. */
case bp_overlay_event:
delete_breakpoint (b);
break;
case bp_watchpoint_scope:
case bp_call_dummy:
case bp_step_resume:
+ case bp_longjmp:
+ case bp_longjmp_resume:
break;
}
}
set_language (save_language);
input_radix = save_input_radix;
-
- if (gdbarch_get_longjmp_target_p (current_gdbarch))
- {
- create_longjmp_breakpoint ("longjmp");
- create_longjmp_breakpoint ("_longjmp");
- create_longjmp_breakpoint ("siglongjmp");
- create_longjmp_breakpoint ("_siglongjmp");
- create_longjmp_breakpoint (NULL);
- }
create_overlay_event_breakpoint ("_ovly_debug_event");
}
extern struct breakpoint *set_momentary_breakpoint
(struct symtab_and_line, struct frame_id, enum bptype);
+extern struct breakpoint *set_momentary_breakpoint_at_pc
+ (CORE_ADDR pc, enum bptype type);
+
extern void set_ignore_count (int, int, int);
extern void set_default_breakpoint (int, CORE_ADDR, struct symtab *, int);
inferior_ptid. */
extern int detach_breakpoints (int);
-extern void enable_longjmp_breakpoint (void);
-extern void disable_longjmp_breakpoint (void);
+extern void set_longjmp_breakpoint (void);
+extern void delete_longjmp_breakpoint (int thread);
+
extern void enable_overlay_breakpoints (void);
extern void disable_overlay_breakpoints (void);
-extern void set_longjmp_resume_breakpoint (CORE_ADDR, struct frame_id);
/* These functions respectively disable or reenable all currently
enabled watchpoints. When disabled, the watchpoints are marked
call_disabled. When reenabled, they are marked enabled.
int current_line;
struct symtab *current_symtab;
int trap_expected;
- int handling_longjmp;
int stepping_over_breakpoint;
/* This is set TRUE when a catchpoint of a shared library event
CORE_ADDR step_range_start,
CORE_ADDR step_range_end,
const struct frame_id *step_frame_id,
- int handling_longjmp,
int another_trap,
int stepping_through_solib_after_catch,
bpstat stepping_through_solib_catchpoints,
CORE_ADDR *step_range_start,
CORE_ADDR *step_range_end,
struct frame_id *step_frame_id,
- int *handling_longjmp,
int *another_trap,
int *stepping_through_solib_affter_catch,
bpstat *stepping_through_solib_catchpoints,
static void jump_command (char *, int);
static void step_1 (int, int, char *);
-static void step_once (int skip_subroutines, int single_inst, int count);
+static void step_once (int skip_subroutines, int single_inst, int count, int thread);
static void step_1_continuation (struct continuation_arg *arg, int error_p);
static void next_command (char *, int);
}
static void
-disable_longjmp_breakpoint_cleanup (void *ignore)
+delete_longjmp_breakpoint_cleanup (void *arg)
{
- disable_longjmp_breakpoint ();
+ int thread = * (int *) arg;
+ delete_longjmp_breakpoint (thread);
}
static void
struct frame_info *frame;
struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
int async_exec = 0;
+ int *thread_p = NULL;
ERROR_NO_INFERIOR;
if (!single_inst || skip_subroutines) /* leave si command alone */
{
- enable_longjmp_breakpoint ();
- make_cleanup (disable_longjmp_breakpoint_cleanup, 0 /*ignore*/);
+ thread_p = xmalloc (sizeof (int));
+ make_cleanup (xfree, thread_p);
+
+ if (in_thread_list (inferior_ptid))
+ *thread_p = pid_to_thread_id (inferior_ptid);
+ else
+ *thread_p = -1;
+
+ set_longjmp_breakpoint ();
+
+ make_cleanup (delete_longjmp_breakpoint_cleanup, thread_p);
}
/* In synchronous case, all is well, just use the regular for loop. */
and handle them one at the time, through step_once(). */
else
{
- step_once (skip_subroutines, single_inst, count);
- /* We are running, and the contination is installed. It will
+ step_once (skip_subroutines, single_inst, count, *thread_p);
+ /* We are running, and the continuation is installed. It will
disable the longjmp breakpoint as appropriate. */
discard_cleanups (cleanups);
+ xfree (thread_p);
}
}
int count;
int skip_subroutines;
int single_inst;
+ int thread;
skip_subroutines = arg->data.integer;
single_inst = arg->next->data.integer;
count = arg->next->next->data.integer;
+ thread = arg->next->next->next->data.integer;
if (error_p || !step_multi || !stop_step)
{
that is not stepping, or there are no further steps
to make. Cleanup. */
if (!single_inst || skip_subroutines)
- disable_longjmp_breakpoint ();
+ delete_longjmp_breakpoint (thread);
step_multi = 0;
}
else
- step_once (skip_subroutines, single_inst, count - 1);
+ step_once (skip_subroutines, single_inst, count - 1, thread);
}
/* Do just one step operation. If count >1 we will have to set up a
called in case of step n with n>1, after the first step operation has
been completed.*/
static void
-step_once (int skip_subroutines, int single_inst, int count)
+step_once (int skip_subroutines, int single_inst, int count, int thread)
{
struct continuation_arg *arg1;
struct continuation_arg *arg2;
struct continuation_arg *arg3;
+ struct continuation_arg *arg4;
struct frame_info *frame;
if (count > 0)
(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
arg3 =
(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+ arg4 =
+ (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
arg1->next = arg2;
arg1->data.integer = skip_subroutines;
arg2->next = arg3;
arg2->data.integer = single_inst;
- arg3->next = NULL;
+ arg3->next = arg4;
arg3->data.integer = count;
+ arg4->next = NULL;
+ arg4->data.integer = thread;
add_intermediate_continuation (step_1_continuation, arg1);
}
}
static int stop_print_frame;
+/* Step-resume or longjmp-resume breakpoint. */
static struct breakpoint *step_resume_breakpoint = NULL;
/* This is a cached copy of the pid/waitstatus of the last event
struct symtab_and_line sal;
int current_line;
struct symtab *current_symtab;
- int handling_longjmp; /* FIXME */
ptid_t ptid;
ptid_t saved_inferior_ptid;
int step_after_step_resume_breakpoint;
static void insert_step_resume_breakpoint_at_caller (struct frame_info *);
static void insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal,
struct frame_id sr_id);
+static void insert_longjmp_resume_breakpoint (CORE_ADDR);
+
static void stop_stepping (struct execution_control_state *ecs);
static void prepare_to_wait (struct execution_control_state *ecs);
static void keep_going (struct execution_control_state *ecs);
ecs->stepping_over_breakpoint = 0;
ecs->random_signal = 0;
ecs->step_after_step_resume_breakpoint = 0;
- ecs->handling_longjmp = 0; /* FIXME */
ecs->stepping_through_solib_after_catch = 0;
ecs->stepping_through_solib_catchpoints = NULL;
ecs->sal = find_pc_line (prev_pc, 0);
stepping_over_breakpoint, step_resume_breakpoint,
step_range_start,
step_range_end, &step_frame_id,
- ecs->handling_longjmp, ecs->stepping_over_breakpoint,
+ ecs->stepping_over_breakpoint,
ecs->stepping_through_solib_after_catch,
ecs->stepping_through_solib_catchpoints,
ecs->current_line, ecs->current_symtab);
&stepping_over_breakpoint, &step_resume_breakpoint,
&step_range_start,
&step_range_end, &step_frame_id,
- &ecs->handling_longjmp, &ecs->stepping_over_breakpoint,
+ &ecs->stepping_over_breakpoint,
&ecs->stepping_through_solib_after_catch,
&ecs->stepping_through_solib_catchpoints,
&ecs->current_line, &ecs->current_symtab);
switch (what.main_action)
{
case BPSTAT_WHAT_SET_LONGJMP_RESUME:
- /* If we hit the breakpoint at longjmp, disable it for the
- duration of this command. Then, install a temporary
- breakpoint at the target of the jmp_buf. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n");
- disable_longjmp_breakpoint ();
+ /* If we hit the breakpoint at longjmp while stepping, we
+ install a momentary breakpoint at the target of the
+ jmp_buf. */
+
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n");
+
+ ecs->stepping_over_breakpoint = 1;
+
if (!gdbarch_get_longjmp_target_p (current_gdbarch)
|| !gdbarch_get_longjmp_target (current_gdbarch,
get_current_frame (), &jmp_buf_pc))
{
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "\
+infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
keep_going (ecs);
return;
}
- /* Need to blow away step-resume breakpoint, as it
- interferes with us */
+ /* We're going to replace the current step-resume breakpoint
+ with a longjmp-resume breakpoint. */
if (step_resume_breakpoint != NULL)
- {
- delete_step_resume_breakpoint (&step_resume_breakpoint);
- }
+ delete_step_resume_breakpoint (&step_resume_breakpoint);
+
+ /* Insert a breakpoint at resume address. */
+ insert_longjmp_resume_breakpoint (jmp_buf_pc);
- set_longjmp_resume_breakpoint (jmp_buf_pc, null_frame_id);
- ecs->handling_longjmp = 1; /* FIXME */
keep_going (ecs);
return;
case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME:
if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n");
- disable_longjmp_breakpoint ();
- ecs->handling_longjmp = 0; /* FIXME */
- break;
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n");
+
+ gdb_assert (step_resume_breakpoint != NULL);
+ delete_step_resume_breakpoint (&step_resume_breakpoint);
+
+ stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
+ stop_stepping (ecs);
+ return;
case BPSTAT_WHAT_SINGLE:
if (debug_infrun)
static int
currently_stepping (struct execution_control_state *ecs)
{
- return ((!ecs->handling_longjmp
- && ((step_range_end && step_resume_breakpoint == NULL)
- || stepping_over_breakpoint))
+ return (((step_range_end && step_resume_breakpoint == NULL)
+ || stepping_over_breakpoint)
|| ecs->stepping_through_solib_after_catch
|| bpstat_should_step ());
}
insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal,
struct frame_id sr_id)
{
- /* There should never be more than one step-resume breakpoint per
- thread, so we should never be setting a new
+ /* There should never be more than one step-resume or longjmp-resume
+ breakpoint per thread, so we should never be setting a new
step_resume_breakpoint when one is already active. */
gdb_assert (step_resume_breakpoint == NULL);
insert_step_resume_breakpoint_at_sal (sr_sal, frame_unwind_id (next_frame));
}
+/* Insert a "longjmp-resume" breakpoint at PC. This is used to set a
+ new breakpoint at the target of a jmp_buf. The handling of
+ longjmp-resume uses the same mechanisms used for handling
+ "step-resume" breakpoints. */
+
+static void
+insert_longjmp_resume_breakpoint (CORE_ADDR pc)
+{
+ /* There should never be more than one step-resume or longjmp-resume
+ breakpoint per thread, so we should never be setting a new
+ longjmp_resume_breakpoint when one is already active. */
+ gdb_assert (step_resume_breakpoint == NULL);
+
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: inserting longjmp-resume breakpoint at 0x%s\n",
+ paddr_nz (pc));
+
+ step_resume_breakpoint =
+ set_momentary_breakpoint_at_pc (pc, bp_longjmp_resume);
+}
+
static void
stop_stepping (struct execution_control_state *ecs)
{
+2008-05-04 Pedro Alves <pedro@codesourcery.com>
+
+ * gdb.cp/annota2.exp: Adjust to breakpoints invalidations at
+ different times.
+
2008-05-04 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.dwarf2/dw2-ranges.S: Merge the secondary section with `.fini'.
#
send_gdb "next\n"
gdb_expect {
- -re "\r\n\032\032post-prompt\r\n\r\n\032\032starting\r\n\r\n(\032\032frames-invalid\r\n\r\n)*\032\032watchpoint 3\r\n.*atchpoint 3: a.x\r\n\r\nOld value = 0\r\nNew value = 1\r\n\r\n\032\032frame-begin 0 $hex\r\n\r\n\032\032frame-function-name\r\nmain\r\n\032\032frame-args\r\n \\(\\)\r\n\032\032frame-source-begin\r\n at \r\n\032\032frame-source-file\r\n.*$srcfile\r\n\032\032frame-source-file-end\r\n:\r\n\032\032frame-source-line\r\n$decimal\r\n\032\032frame-source-end\r\n\r\n\r\n\032\032source .*$srcfile.*beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped\r\n.*$gdb_prompt$" \
+ -re "\r\n\032\032post-prompt\r\n\r\n(\032\032breakpoints-invalid\r\n\r\n)*\032\032starting\r\n\r\n(\032\032frames-invalid\r\n\r\n)*\032\032watchpoint 3\r\n.*atchpoint 3: a.x\r\n\r\nOld value = 0\r\nNew value = 1\r\n\r\n\032\032frame-begin 0 $hex\r\n\r\n\032\032frame-function-name\r\nmain\r\n\032\032frame-args\r\n \\(\\)\r\n\032\032frame-source-begin\r\n at \r\n\032\032frame-source-file\r\n.*$srcfile\r\n\032\032frame-source-file-end\r\n:\r\n\032\032frame-source-line\r\n$decimal\r\n\032\032frame-source-end\r\n\r\n\r\n\032\032source .*$srcfile.*beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped\r\n.*$gdb_prompt$" \
{ pass "watch triggered on a.x" }
- -re "\r\n\032\032post-prompt\r\n\r\n\032\032starting\r\n\r\n\032\032frames-invalid\r\n\r\n\032\032source .*$srcfile.*beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped\r\n$gdb_prompt$" \
+ -re "\r\n\032\032post-prompt\r\n\r\n(\032\032breakpoints-invalid\r\n\r\n)*\032\032starting\r\n\r\n\032\032frames-invalid\r\n\r\n\032\032source .*$srcfile.*beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped\r\n$gdb_prompt$" \
{ kfail "gdb/38" "watch triggered on a.x" }
-re ".*$gdb_prompt$" { fail "watch triggered on a.x" }
timeout { fail "watch triggered on a.x (timeout)" }
CORE_ADDR *step_range_start,
CORE_ADDR *step_range_end,
struct frame_id *step_frame_id,
- int *handling_longjmp,
int *stepping_over_breakpoint,
int *stepping_through_solib_after_catch,
bpstat *stepping_through_solib_catchpoints,
*step_range_start = tp->step_range_start;
*step_range_end = tp->step_range_end;
*step_frame_id = tp->step_frame_id;
- *handling_longjmp = tp->handling_longjmp;
*stepping_over_breakpoint = tp->stepping_over_breakpoint;
*stepping_through_solib_after_catch =
tp->stepping_through_solib_after_catch;
CORE_ADDR step_range_start,
CORE_ADDR step_range_end,
const struct frame_id *step_frame_id,
- int handling_longjmp,
int stepping_over_breakpoint,
int stepping_through_solib_after_catch,
bpstat stepping_through_solib_catchpoints,
tp->step_range_start = step_range_start;
tp->step_range_end = step_range_end;
tp->step_frame_id = (*step_frame_id);
- tp->handling_longjmp = handling_longjmp;
tp->stepping_over_breakpoint = stepping_over_breakpoint;
tp->stepping_through_solib_after_catch = stepping_through_solib_after_catch;
tp->stepping_through_solib_catchpoints = stepping_through_solib_catchpoints;