|
|
17e05a9 |
http://sourceware.org/ml/gdb-patches/2010-02/msg00625.html
|
|
|
17e05a9 |
Subject: RFC: fix bug with std::terminate handler
|
|
|
17e05a9 |
|
|
|
17e05a9 |
I would appreciate comments on this patch.
|
|
|
17e05a9 |
|
|
|
17e05a9 |
This comes from an automatically-reported bug in the Red Hat bugzilla:
|
|
|
17e05a9 |
|
|
|
17e05a9 |
https://bugzilla.redhat.com/show_bug.cgi?id=562975
|
|
|
17e05a9 |
|
|
|
17e05a9 |
call_function_by_hand installs a momentary breakpoint on std::terminate,
|
|
|
17e05a9 |
and then deletes it later. However, this can cause a double deletion of
|
|
|
17e05a9 |
the breakpoint. In the bug, the called function is dlopen, which causes
|
|
|
17e05a9 |
gdb to enter solib_add, which calls breakpoint_re_set, deleting the
|
|
|
17e05a9 |
momentary breakpoint.
|
|
|
17e05a9 |
|
|
|
17e05a9 |
This fix works by creating the momentary breakpoint with an internal
|
|
|
17e05a9 |
breakpoint number, and then trying to delete the breakpoint by number.
|
|
|
17e05a9 |
|
|
|
17e05a9 |
This bug does not always manifest in a crash. In fact, I couldn't make
|
|
|
17e05a9 |
it crash here, but I could observe the problem under valgrind.
|
|
|
17e05a9 |
|
|
|
17e05a9 |
Built and regtested on x86-64 (compile farm). I also manually verified
|
|
|
17e05a9 |
it using valgrind.
|
|
|
17e05a9 |
|
|
|
17e05a9 |
I think this patch is mildly ugly, due to the introduction of
|
|
|
17e05a9 |
set_momentary_breakpoint_at_pc_with_number. However, in the absence of
|
|
|
17e05a9 |
comments, I plan to check it in after a reasonable waiting period.
|
|
|
17e05a9 |
|
|
|
17e05a9 |
Tom
|
|
|
17e05a9 |
|
|
|
17e05a9 |
2010-02-25 Tom Tromey <tromey@redhat.com>
|
|
|
17e05a9 |
|
|
|
17e05a9 |
* infcall.c (do_delete_breakpoint_by_number): New function.
|
|
|
17e05a9 |
(call_function_by_hand): Refer to momentary breakpoint by number.
|
|
|
17e05a9 |
* breakpoint.h (set_momentary_breakpoint_at_pc_with_number):
|
|
|
17e05a9 |
Declare.
|
|
|
17e05a9 |
* breakpoint.c (set_momentary_breakpoint_at_pc_with_number): New
|
|
|
17e05a9 |
function.
|
|
|
17e05a9 |
|
|
|
17e05a9 |
Index: gdb-7.0.1/gdb/breakpoint.c
|
|
|
17e05a9 |
===================================================================
|
|
|
17e05a9 |
--- gdb-7.0.1.orig/gdb/breakpoint.c 2010-03-12 00:26:46.000000000 +0100
|
|
|
17e05a9 |
+++ gdb-7.0.1/gdb/breakpoint.c 2010-03-12 00:26:54.000000000 +0100
|
|
|
17e05a9 |
@@ -5647,6 +5647,20 @@ set_momentary_breakpoint_at_pc (struct g
|
|
|
17e05a9 |
|
|
|
17e05a9 |
return set_momentary_breakpoint (gdbarch, sal, null_frame_id, type);
|
|
|
17e05a9 |
}
|
|
|
17e05a9 |
+
|
|
|
17e05a9 |
+/* Like set_momentary_breakpoint_at_pc, but ensure that the new
|
|
|
17e05a9 |
+ breakpoint has a number. */
|
|
|
17e05a9 |
+
|
|
|
17e05a9 |
+struct breakpoint *
|
|
|
17e05a9 |
+set_momentary_breakpoint_at_pc_with_number (struct gdbarch *gdbarch,
|
|
|
17e05a9 |
+ CORE_ADDR pc,
|
|
|
17e05a9 |
+ enum bptype type)
|
|
|
17e05a9 |
+{
|
|
|
17e05a9 |
+ struct breakpoint *result = set_momentary_breakpoint_at_pc (gdbarch, pc,
|
|
|
17e05a9 |
+ type);
|
|
|
17e05a9 |
+ result->number = internal_breakpoint_number--;
|
|
|
17e05a9 |
+ return result;
|
|
|
17e05a9 |
+}
|
|
|
17e05a9 |
|
|
|
17e05a9 |
|
|
|
17e05a9 |
/* Tell the user we have just set a breakpoint B. */
|
|
|
17e05a9 |
Index: gdb-7.0.1/gdb/breakpoint.h
|
|
|
17e05a9 |
===================================================================
|
|
|
17e05a9 |
--- gdb-7.0.1.orig/gdb/breakpoint.h 2010-03-12 00:26:46.000000000 +0100
|
|
|
17e05a9 |
+++ gdb-7.0.1/gdb/breakpoint.h 2010-03-12 00:26:54.000000000 +0100
|
|
|
17e05a9 |
@@ -741,6 +741,9 @@ extern struct breakpoint *set_momentary_
|
|
|
17e05a9 |
extern struct breakpoint *set_momentary_breakpoint_at_pc
|
|
|
17e05a9 |
(struct gdbarch *, CORE_ADDR pc, enum bptype type);
|
|
|
17e05a9 |
|
|
|
17e05a9 |
+extern struct breakpoint *set_momentary_breakpoint_at_pc_with_number
|
|
|
17e05a9 |
+ (struct gdbarch *, CORE_ADDR pc, enum bptype type);
|
|
|
17e05a9 |
+
|
|
|
17e05a9 |
extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint *bpkt);
|
|
|
17e05a9 |
|
|
|
17e05a9 |
extern void set_ignore_count (int, int, int);
|
|
|
17e05a9 |
Index: gdb-7.0.1/gdb/infcall.c
|
|
|
17e05a9 |
===================================================================
|
|
|
17e05a9 |
--- gdb-7.0.1.orig/gdb/infcall.c 2010-03-12 00:26:46.000000000 +0100
|
|
|
17e05a9 |
+++ gdb-7.0.1/gdb/infcall.c 2010-03-12 00:27:31.000000000 +0100
|
|
|
17e05a9 |
@@ -410,6 +410,18 @@ run_inferior_call (struct thread_info *c
|
|
|
17e05a9 |
return e;
|
|
|
17e05a9 |
}
|
|
|
17e05a9 |
|
|
|
17e05a9 |
+/* A cleanup function that deletes a breakpoint, if it still exists,
|
|
|
17e05a9 |
+ given the breakpoint's number. */
|
|
|
17e05a9 |
+
|
|
|
17e05a9 |
+static void
|
|
|
17e05a9 |
+do_delete_breakpoint_by_number (void *arg)
|
|
|
17e05a9 |
+{
|
|
|
17e05a9 |
+ int *num = arg;
|
|
|
17e05a9 |
+ struct breakpoint *bp = get_breakpoint (*num);
|
|
|
17e05a9 |
+ if (bp)
|
|
|
17e05a9 |
+ delete_breakpoint (bp);
|
|
|
17e05a9 |
+}
|
|
|
17e05a9 |
+
|
|
|
17e05a9 |
/* All this stuff with a dummy frame may seem unnecessarily complicated
|
|
|
17e05a9 |
(why not just save registers in GDB?). The purpose of pushing a dummy
|
|
|
17e05a9 |
frame which looks just like a real frame is so that if you call a
|
|
|
17e05a9 |
@@ -447,7 +459,8 @@ call_function_by_hand (struct value *fun
|
|
|
17e05a9 |
struct cleanup *args_cleanup;
|
|
|
17e05a9 |
struct frame_info *frame;
|
|
|
17e05a9 |
struct gdbarch *gdbarch;
|
|
|
17e05a9 |
- struct breakpoint *terminate_bp = NULL;
|
|
|
17e05a9 |
+ int terminate_bp_num = 0;
|
|
|
17e05a9 |
+ CORE_ADDR terminate_bp_addr = 0;
|
|
|
17e05a9 |
struct minimal_symbol *tm;
|
|
|
17e05a9 |
struct cleanup *terminate_bp_cleanup = NULL;
|
|
|
17e05a9 |
ptid_t call_thread_ptid;
|
|
|
17e05a9 |
@@ -764,8 +777,13 @@ call_function_by_hand (struct value *fun
|
|
|
17e05a9 |
struct minimal_symbol *tm = lookup_minimal_symbol ("std::terminate()",
|
|
|
17e05a9 |
NULL, NULL);
|
|
|
17e05a9 |
if (tm != NULL)
|
|
|
17e05a9 |
- terminate_bp = set_momentary_breakpoint_at_pc
|
|
|
17e05a9 |
+ {
|
|
|
17e05a9 |
+ struct breakpoint *bp;
|
|
|
17e05a9 |
+ bp = set_momentary_breakpoint_at_pc_with_number
|
|
|
17e05a9 |
(gdbarch, SYMBOL_VALUE_ADDRESS (tm), bp_breakpoint);
|
|
|
17e05a9 |
+ terminate_bp_num = bp->number;
|
|
|
17e05a9 |
+ terminate_bp_addr = bp->loc->address;
|
|
|
17e05a9 |
+ }
|
|
|
17e05a9 |
}
|
|
|
17e05a9 |
|
|
|
17e05a9 |
/* Everything's ready, push all the info needed to restore the
|
|
|
17e05a9 |
@@ -779,8 +797,9 @@ call_function_by_hand (struct value *fun
|
|
|
17e05a9 |
discard_cleanups (inf_status_cleanup);
|
|
|
17e05a9 |
|
|
|
17e05a9 |
/* Register a clean-up for unwind_on_terminating_exception_breakpoint. */
|
|
|
17e05a9 |
- if (terminate_bp)
|
|
|
17e05a9 |
- terminate_bp_cleanup = make_cleanup_delete_breakpoint (terminate_bp);
|
|
|
17e05a9 |
+ if (terminate_bp_num != 0)
|
|
|
17e05a9 |
+ terminate_bp_cleanup = make_cleanup (do_delete_breakpoint_by_number,
|
|
|
17e05a9 |
+ &terminate_bp_num);
|
|
|
17e05a9 |
|
|
|
17e05a9 |
/* - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP -
|
|
|
17e05a9 |
If you're looking to implement asynchronous dummy-frames, then
|
|
|
17e05a9 |
@@ -946,9 +965,9 @@ When the function is done executing, GDB
|
|
|
17e05a9 |
in an inferior function call. Rewind, and warn the
|
|
|
17e05a9 |
user. */
|
|
|
17e05a9 |
|
|
|
17e05a9 |
- if (terminate_bp != NULL
|
|
|
17e05a9 |
+ if (terminate_bp_num != 0
|
|
|
17e05a9 |
&& (inferior_thread()->stop_bpstat->breakpoint_at->address
|
|
|
17e05a9 |
- == terminate_bp->loc->address))
|
|
|
17e05a9 |
+ == terminate_bp_addr))
|
|
|
17e05a9 |
{
|
|
|
17e05a9 |
/* We must get back to the frame we were before the
|
|
|
17e05a9 |
dummy call. */
|
|
|
17e05a9 |
@@ -997,7 +1016,7 @@ When the function is done executing, GDB
|
|
|
17e05a9 |
|
|
|
17e05a9 |
/* If we get here and the std::terminate() breakpoint has been set,
|
|
|
17e05a9 |
it has to be cleaned manually. */
|
|
|
17e05a9 |
- if (terminate_bp)
|
|
|
17e05a9 |
+ if (terminate_bp_num != 0)
|
|
|
17e05a9 |
do_cleanups (terminate_bp_cleanup);
|
|
|
17e05a9 |
|
|
|
17e05a9 |
/* If we get here the called FUNCTION ran to completion,
|