From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11876 invoked by alias); 24 Mar 2016 01:17:59 -0000 Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org Received: (qmail 11856 invoked by uid 89); 24 Mar 2016 01:17:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.1 required=5.0 tests=BAYES_00,SPF_HELO_PASS,T_RP_MATCHES_RCVD,UNSUBSCRIBE_BODY autolearn=no version=3.3.2 spammy=sk:check_e, mips16, MIPS16, significantly X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 24 Mar 2016 01:17:56 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id BFEA764396; Thu, 24 Mar 2016 01:17:54 +0000 (UTC) Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u2O1HrtQ027405; Wed, 23 Mar 2016 21:17:53 -0400 From: Pedro Alves Subject: Re: JIT debugging (Attach and speed) To: Yichao Yu References: <56F168D7.9050405@redhat.com> <56F16F8F.9050404@redhat.com> <56F1759F.3070100@redhat.com> <56F17A23.90909@redhat.com> <56F2DF69.9030908@redhat.com> <56F2F31F.4000104@redhat.com> Cc: gdb@sourceware.org, Paul Pluzhnikov Message-ID: <56F34041.2000301@redhat.com> Date: Thu, 24 Mar 2016 01:17:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-SW-Source: 2016-03/txt/msg00045.txt.bz2 On 03/23/2016 08:51 PM, Yichao Yu wrote: > Also, it looks like gdb is trying to get info about the current frame? > Can this be disabled for this breakpoint since it's not a "real" one? Excellent suggestion. Seems like we can avoid computing a frame unless we're stepping, or presenting a stop. The prototype patch below (also in users/palves/jit-speedup, along with the attach fixes), simply delays computing a frame until it's necessary, and it cuts down the time for: gdb ---args ./testsuite/outputs/gdb.base/jit/jit-main ./testsuite/outputs/gdb.base/jit/jit-solib.so 2000 from "takes too long so I canceled it" minutes, to around 2 seconds, for me. There's one hack though -- I commented out the skip_inline_frames call... We'll need to handle that some other way, or in some other place. As is, this regresses some inline tests, naturally... Having a pending breakpoint that is never resolved slows things down significantly again though... The perf profile shows that breakpoint_re_set ends up calling parse_linespec which wants the selected block, which wants the selected frame, and then we're back at the same... Maybe we could reconsider how pending breakpoints are re-parsed, and which context they're parsed in. Not sure. Still, very promising. ----------- >From a1e599495aafd10ae0505558343136f90b291038 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 23 Mar 2016 18:11:45 +0000 Subject: [PATCH] Avoid creating a frame in internal stops This speeds up JIT library loading by ${a lot}. --- gdb/breakpoint.c | 3 +- gdb/infrun.c | 98 ++++++++++++++++++++++++++++++-------------------------- 2 files changed, 54 insertions(+), 47 deletions(-) diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index f99a7ab..ed708a9 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -5792,8 +5792,7 @@ handle_jit_event (void) breakpoint_re_set. */ target_terminal_ours_for_output (); - frame = get_current_frame (); - gdbarch = get_frame_arch (frame); + gdbarch = get_regcache_arch (get_current_regcache ()); jit_event_handler (gdbarch); diff --git a/gdb/infrun.c b/gdb/infrun.c index 696105d..6067cb0 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -5608,8 +5608,6 @@ finish_step_over (struct execution_control_state *ecs) static void handle_signal_stop (struct execution_control_state *ecs) { - struct frame_info *frame; - struct gdbarch *gdbarch; int stopped_by_watchpoint; enum stop_kind stop_soon; int random_signal; @@ -5717,10 +5715,6 @@ handle_signal_stop (struct execution_control_state *ecs) deprecated_context_hook (ptid_to_global_thread_id (ecs->ptid)); } - /* At this point, get hold of the now-current thread's frame. */ - frame = get_current_frame (); - gdbarch = get_frame_arch (frame); - /* Pull the single step breakpoints out of the target. */ if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP) { @@ -5774,7 +5768,7 @@ handle_signal_stop (struct execution_control_state *ecs) it in a moment. */ if (stopped_by_watchpoint && (target_have_steppable_watchpoint - || gdbarch_have_nonsteppable_watchpoint (gdbarch))) + || gdbarch_have_nonsteppable_watchpoint (get_regcache_arch (get_current_regcache ())))) { /* At this point, we are stopped at an instruction which has attempted to write to a piece of memory under control of @@ -5838,27 +5832,25 @@ handle_signal_stop (struct execution_control_state *ecs) user had set a breakpoint on that inlined code, the missing skip_inline_frames call would break things. Fortunately that's an extremely unlikely scenario. */ +#if 0 if (!pc_at_non_inline_function (aspace, stop_pc, &ecs->ws) && !(ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP && ecs->event_thread->control.trap_expected && pc_at_non_inline_function (aspace, ecs->event_thread->prev_pc, &ecs->ws))) - { - skip_inline_frames (ecs->ptid); - - /* Re-fetch current thread's frame in case that invalidated - the frame cache. */ - frame = get_current_frame (); - gdbarch = get_frame_arch (frame); - } + skip_inline_frames (ecs->ptid); +#endif } if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP && ecs->event_thread->control.trap_expected - && gdbarch_single_step_through_delay_p (gdbarch) + && gdbarch_single_step_through_delay_p (get_regcache_arch (get_current_regcache ())) && currently_stepping (ecs->event_thread)) { + struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ()); + struct frame_info *frame = get_current_frame (); + /* We're trying to step off a breakpoint. Turns out that we're also on an instruction that needs to be stepped multiple times before it's been fully executing. E.g., architectures @@ -5946,6 +5938,9 @@ handle_signal_stop (struct execution_control_state *ecs) been removed. */ if (random_signal && target_stopped_by_sw_breakpoint ()) { + struct frame_info *frame = get_current_frame (); + struct gdbarch *gdbarch = get_frame_arch (frame); + if (program_breakpoint_here_p (gdbarch, stop_pc)) { struct regcache *regcache; @@ -6051,6 +6046,7 @@ handle_signal_stop (struct execution_control_state *ecs) && ecs->event_thread->control.trap_expected && ecs->event_thread->control.step_resume_breakpoint == NULL) { + struct frame_info *frame = get_current_frame (); int was_in_line; /* We were just starting a new sequence, attempting to @@ -6105,11 +6101,14 @@ handle_signal_stop (struct execution_control_state *ecs) if (ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0 && (pc_in_thread_step_range (stop_pc, ecs->event_thread) - || ecs->event_thread->control.step_range_end == 1) - && frame_id_eq (get_stack_frame_id (frame), - ecs->event_thread->control.step_stack_frame_id) - && ecs->event_thread->control.step_resume_breakpoint == NULL) + || ecs->event_thread->control.step_range_end == 1)) { + struct frame_info *frame = get_current_frame (); + + if (frame_id_eq (get_stack_frame_id (frame), + ecs->event_thread->control.step_stack_frame_id) + && ecs->event_thread->control.step_resume_breakpoint == NULL) + { /* The inferior is about to take a signal that will take it out of the single step range. Set a breakpoint at the current PC (which is presumably where the signal handler @@ -6131,6 +6130,7 @@ handle_signal_stop (struct execution_control_state *ecs) ecs->event_thread->control.trap_expected = 0; keep_going (ecs); return; + } } /* Note: step_resume_breakpoint may be non-NULL. This occures @@ -6164,16 +6164,11 @@ static void process_event_stop_test (struct execution_control_state *ecs) { struct symtab_and_line stop_pc_sal; - struct frame_info *frame; - struct gdbarch *gdbarch; CORE_ADDR jmp_buf_pc; struct bpstat_what what; /* Handle cases caused by hitting a breakpoint. */ - frame = get_current_frame (); - gdbarch = get_frame_arch (frame); - what = bpstat_what (ecs->event_thread->control.stop_bpstat); if (what.call_dummy) @@ -6185,12 +6180,6 @@ process_event_stop_test (struct execution_control_state *ecs) bp_jit_event). Run them now. */ bpstat_run_callbacks (ecs->event_thread->control.stop_bpstat); - /* If we hit an internal event that triggers symbol changes, the - current frame will be invalidated within bpstat_what (e.g., if we - hit an internal solib event). Re-fetch it. */ - frame = get_current_frame (); - gdbarch = get_frame_arch (frame); - switch (what.main_action) { case BPSTAT_WHAT_SET_LONGJMP_RESUME: @@ -6207,6 +6196,8 @@ process_event_stop_test (struct execution_control_state *ecs) if (what.is_longjmp) { struct value *arg_value; + struct frame_info *frame = get_current_frame (); + struct gdbarch *gdbarch = get_frame_arch (frame); /* If we set the longjmp breakpoint via a SystemTap probe, then use it to extract the arguments. The destination PC @@ -6233,7 +6224,11 @@ process_event_stop_test (struct execution_control_state *ecs) insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc); } else - check_exception_resume (ecs, frame); + { + struct frame_info *frame = get_current_frame (); + + check_exception_resume (ecs, frame); + } keep_going (ecs); return; @@ -6333,7 +6328,7 @@ process_event_stop_test (struct execution_control_state *ecs) keep_going (ecs); return; } - fill_in_stop_func (gdbarch, ecs); + fill_in_stop_func (get_regcache_arch (get_current_regcache ()), ecs); if (stop_pc == ecs->stop_func_start && execution_direction == EXEC_REVERSE) { @@ -6450,12 +6445,7 @@ process_event_stop_test (struct execution_control_state *ecs) return; } - /* Re-fetch current thread's frame in case the code above caused - the frame cache to be re-initialized, making our FRAME variable - a dangling pointer. */ - frame = get_current_frame (); - gdbarch = get_frame_arch (frame); - fill_in_stop_func (gdbarch, ecs); + fill_in_stop_func (get_regcache_arch (get_current_regcache ()), ecs); /* If stepping through a line, keep going if still within it. @@ -6469,9 +6459,11 @@ process_event_stop_test (struct execution_control_state *ecs) if (pc_in_thread_step_range (stop_pc, ecs->event_thread) && (execution_direction != EXEC_REVERSE - || frame_id_eq (get_frame_id (frame), + || frame_id_eq (get_frame_id (get_current_frame ()), ecs->event_thread->control.step_frame_id))) { + struct gdbarch *gdbarch = get_frame_arch (get_current_frame ()); + if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: stepping inside range [%s-%s]\n", @@ -6514,6 +6506,7 @@ process_event_stop_test (struct execution_control_state *ecs) && ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE && in_solib_dynsym_resolve_code (stop_pc)) { + struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ()); CORE_ADDR pc_after_resolver = gdbarch_skip_solib_resolver (gdbarch, stop_pc); @@ -6529,7 +6522,7 @@ process_event_stop_test (struct execution_control_state *ecs) init_sal (&sr_sal); sr_sal.pc = pc_after_resolver; - sr_sal.pspace = get_frame_program_space (frame); + sr_sal.pspace = current_program_space; insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal, null_frame_id); @@ -6542,7 +6535,7 @@ process_event_stop_test (struct execution_control_state *ecs) if (ecs->event_thread->control.step_range_end != 1 && (ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE || ecs->event_thread->control.step_over_calls == STEP_OVER_ALL) - && get_frame_type (frame) == SIGTRAMP_FRAME) + && get_frame_type (get_current_frame ()) == SIGTRAMP_FRAME) { if (debug_infrun) fprintf_unfiltered (gdb_stdlog, @@ -6561,12 +6554,14 @@ process_event_stop_test (struct execution_control_state *ecs) /* macro/2012-04-25: This needs to come before the subroutine call check below as on some targets return trampolines look like subroutine calls (MIPS16 return thunks). */ - if (gdbarch_in_solib_return_trampoline (gdbarch, + if (gdbarch_in_solib_return_trampoline (get_regcache_arch (get_current_regcache ()), stop_pc, ecs->stop_func_name) && ecs->event_thread->control.step_over_calls != STEP_OVER_NONE) { /* Determine where this trampoline returns. */ CORE_ADDR real_stop_pc; + struct frame_info *frame = get_current_frame (); + struct gdbarch *gdbarch = get_frame_arch (frame); real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc); @@ -6615,7 +6610,7 @@ process_event_stop_test (struct execution_control_state *ecs) initial outermost frame, before sp was valid, would have code_addr == &_start. See the comment in frame_id_eq for more. */ - if (!frame_id_eq (get_stack_frame_id (frame), + if (!frame_id_eq (get_stack_frame_id (get_current_frame ()), ecs->event_thread->control.step_stack_frame_id) && (frame_id_eq (frame_unwind_caller_id (get_current_frame ()), ecs->event_thread->control.step_stack_frame_id) @@ -6625,6 +6620,8 @@ process_event_stop_test (struct execution_control_state *ecs) != find_pc_function (stop_pc))))) { CORE_ADDR real_stop_pc; + struct frame_info *frame = get_current_frame (); + struct gdbarch *gdbarch = get_frame_arch (frame); if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: stepped into subroutine\n"); @@ -6787,6 +6784,9 @@ process_event_stop_test (struct execution_control_state *ecs) if (execution_direction == EXEC_REVERSE && ecs->event_thread->control.step_over_calls != STEP_OVER_NONE) { + struct frame_info *frame = get_current_frame (); + struct gdbarch *gdbarch = get_frame_arch (frame); + if (gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc) || (ecs->stop_func_start == 0 && in_solib_dynsym_resolve_code (stop_pc))) @@ -6825,6 +6825,9 @@ process_event_stop_test (struct execution_control_state *ecs) && ecs->stop_func_name == NULL && stop_pc_sal.line == 0) { + struct frame_info *frame = get_current_frame (); + struct gdbarch *gdbarch = get_frame_arch (frame); + if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: stepped into undebuggable function\n"); @@ -6969,7 +6972,12 @@ process_event_stop_test (struct execution_control_state *ecs) ecs->event_thread->control.step_range_start = stop_pc_sal.pc; ecs->event_thread->control.step_range_end = stop_pc_sal.end; ecs->event_thread->control.may_range_step = 1; - set_step_info (frame, stop_pc_sal); + + { + struct frame_info *frame = get_current_frame (); + struct gdbarch *gdbarch = get_frame_arch (frame); + set_step_info (frame, stop_pc_sal); + } if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: keep going\n"); -- 2.5.5