A Wednesday 14 May 2008 19:16:23, Pedro Alves wrote: > A Wednesday 14 May 2008 19:00:18, Ulrich Weigand wrote: > > I'm now wondering how we should handle this. Should be > > implement an ad-hoc solution to retrieve the guard, which > > may break in the future if glibc changes? Should we require > > use of LD_POINTER_GUARD=0 (which switches off the pointer > > guard mechanism) to enable debugging? Am I overlooking some > > defined interface to get at the value? > > No, you're not. There is none. And still > LD_POINTER_GUARD=0 doesn't help when attaching to an already > running target. > > > Why are we using the get_longjmp_target mechanism instead of > > just stepping through longjmp until we see where we come out? > > You tell me. :-) I had assumed there was a reason. Perhaps > to support longjumping to a different stack, but that's hardly > a portable and frequent use case. This seems to be the path > to go. Alright, here is a quick hack at it. If this is the path to go, we can remove a bunch of gdbarch_get_longjmp_target implementations, and the code around longjmp_resume breakpoints. The patch implements the "keep stepping if going through a longjmp", and also, if landing somewhere inner than the current step-resume, we keep stepping, which is an alternative and simple implementation of what I proposed here: http://sourceware.org/ml/gdb-patches/2008-04/msg00162.html Tested on x86_64-unknown-linux-gnu. The longjmp.exp passes all ok, and we become immune to pointer mangling. I've also simplified a bit the test, removing stuff that wasn't adding any value. One thing, why do I need to call get_frame_type before calling frame_unwind_id (first thing after frame cache invalidation)? If I don't do that, I hit this gdb_assert: static void frame_cleanup_after_sniffer (void *arg) { ... /* No sniffer should extend the frame chain; sniff based on what is already certain. */ gdb_assert (!frame->prev_p); #0 internal_error (file=0x7558a1 "../../src/gdb/frame.c", line=1808, string=0x755946 "%s: Assertion `%s' failed.") at ../../src/gdb/utils.c:779 #1 0x00000000005b5b6a in frame_cleanup_after_sniffer (arg=0xafbd40) at ../../src/gdb/frame.c:1808 #2 0x00000000004570ed in do_my_cleanups (pmy_chain=0xa9b900, old_chain=0xb13d10) at ../../src/gdb/utils.c:320 #3 0x000000000045709d in do_cleanups (old_chain=0xb13d10) at ../../src/gdb/utils.c:303 #4 0x00000000005b62d3 in frame_unwind_find_by_frame (this_frame=0xafbd40, this_cache=0xafbd48) at ../../src/gdb/frame-unwind.c:105 #5 0x00000000005b2e7f in get_frame_id (fi=0xafbd40) at ../../src/gdb/frame.c:258 #6 0x00000000005b4c6a in get_prev_frame_1 (this_frame=0xafbd40) at ../../src/gdb/frame.c:1188 #7 0x00000000005b2f72 in frame_unwind_id (next_frame=0xafbd40) at ../../src/gdb/frame.c:279 #8 0x0000000000503b00 in handle_inferior_event (ecs=0x7fffd6bca510) at ../../src/gdb/infrun.c:2605 #9 0x00000000005016cb in wait_for_inferior (treat_exec_as_sigtrap=0) at ../../src/gdb/infrun.c:1482 #10 0x000000000050142d in proceed (addr=18446744073709551615, siggnal=TARGET_SIGNAL_DEFAULT, step=1) at ../../src/gdb/infrun.c:1273 #11 0x00000000004fd64f in step_1 (skip_subroutines=1, single_inst=0, count_string=0x0) at ../../src/gdb/infcmd.c:784 #12 0x00000000004fd32e in next_command (count_string=0x0, from_tty=1) at ../../src/gdb/infcmd.c:678 ... The first call to frame_unwind_id a bit below happens to have a get_frame_type call before, by chance, if (step_range_end != 1 && (step_over_calls == STEP_OVER_UNDEBUGGABLE || step_over_calls == STEP_OVER_ALL) >>> && get_frame_type (get_current_frame ()) == SIGTRAMP_FRAME) { if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: stepped into signal trampoline\n"); /* The inferior, while doing a "step" or "next", has ended up in a signal trampoline (either by a signal being delivered or by the signal handler returning). Just single-step until the inferior leaves the trampoline (either by calling the handler or returning). */ keep_going (ecs); return; } /* Check for subroutine calls. The check for the current frame equalling the step ID is not necessary - the check of the previous frame's ID is sufficient - but it is a common case and cheaper than checking the previous frame's ID. NOTE: frame_id_eq will never report two invalid frame IDs as being equal, so to get into this block, both the current and previous frame must have valid frame IDs. */ if (!frame_id_eq (get_frame_id (get_current_frame ()), step_frame_id) >>> && frame_id_eq (frame_unwind_id (get_current_frame ()), step_frame_id)) { -- Pedro Alves