diff options
Diffstat (limited to 'gdb/breakpoint.c')
-rw-r--r-- | gdb/breakpoint.c | 105 |
1 files changed, 95 insertions, 10 deletions
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 58102ec..813080a 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -353,7 +353,7 @@ static int overlay_events_enabled; #define ALL_TRACEPOINTS(B) \ for (B = breakpoint_chain; B; B = B->next) \ - if ((B)->type == bp_tracepoint) + if (tracepoint_type (B)) /* Chains of all breakpoints defined. */ @@ -422,6 +422,14 @@ clear_breakpoint_hit_counts (void) b->hit_count = 0; } +/* Encapsulate tests for different types of tracepoints. */ + +static int +tracepoint_type (const struct breakpoint *b) +{ + return (b->type == bp_tracepoint || b->type == bp_fast_tracepoint); +} + /* Default address, symtab and line to put a breakpoint at for "break" command with no arg. if default_breakpoint_valid is zero, the other three are @@ -1282,7 +1290,7 @@ should_be_inserted (struct bp_location *bpt) /* Tracepoints are inserted by the target at a time of its choosing, not by us. */ - if (bpt->owner->type == bp_tracepoint) + if (tracepoint_type (bpt->owner)) return 0; return 1; @@ -2977,6 +2985,7 @@ print_it_typical (bpstat bs) case bp_watchpoint_scope: case bp_call_dummy: case bp_tracepoint: + case bp_fast_tracepoint: case bp_jit_event: default: result = PRINT_UNKNOWN; @@ -3322,7 +3331,7 @@ bpstat_check_location (const struct bp_location *bl, /* By definition, the inferior does not report stops at tracepoints. */ - if (b->type == bp_tracepoint) + if (tracepoint_type (b)) return 0; if (b->type != bp_watchpoint @@ -3914,11 +3923,12 @@ bpstat_what (bpstat bs) retval.call_dummy = 1; break; case bp_tracepoint: + case bp_fast_tracepoint: /* Tracepoint hits should not be reported back to GDB, and if one got through somehow, it should have been filtered out already. */ internal_error (__FILE__, __LINE__, - _("bpstat_what: bp_tracepoint encountered")); + _("bpstat_what: tracepoint encountered")); break; } current_action = table[(int) bs_class][(int) current_action]; @@ -4044,6 +4054,7 @@ print_one_breakpoint_location (struct breakpoint *b, {bp_longjmp_master, "longjmp master"}, {bp_catchpoint, "catchpoint"}, {bp_tracepoint, "tracepoint"}, + {bp_fast_tracepoint, "fast tracepoint"}, {bp_jit_event, "jit events"}, }; @@ -4173,6 +4184,7 @@ print_one_breakpoint_location (struct breakpoint *b, case bp_overlay_event: case bp_longjmp_master: case bp_tracepoint: + case bp_fast_tracepoint: case bp_jit_event: if (opts.addressprint) { @@ -4258,7 +4270,7 @@ print_one_breakpoint_location (struct breakpoint *b, because the condition is an internal implementation detail that we do not want to expose to the user. */ annotate_field (7); - if (b->type == bp_tracepoint) + if (tracepoint_type (b)) ui_out_text (uiout, "\ttrace only if "); else ui_out_text (uiout, "\tstop only if "); @@ -4451,7 +4463,7 @@ user_settable_breakpoint (const struct breakpoint *b) return (b->type == bp_breakpoint || b->type == bp_catchpoint || b->type == bp_hardware_breakpoint - || b->type == bp_tracepoint + || tracepoint_type (b) || b->type == bp_watchpoint || b->type == bp_read_watchpoint || b->type == bp_access_watchpoint @@ -4804,6 +4816,7 @@ allocate_bp_location (struct breakpoint *bpt) { case bp_breakpoint: case bp_tracepoint: + case bp_fast_tracepoint: case bp_until: case bp_finish: case bp_longjmp: @@ -4900,7 +4913,7 @@ set_breakpoint_location_function (struct bp_location *loc) { if (loc->owner->type == bp_breakpoint || loc->owner->type == bp_hardware_breakpoint - || loc->owner->type == bp_tracepoint) + || tracepoint_type (loc->owner)) { find_pc_partial_function (loc->address, &(loc->function_name), NULL, NULL); @@ -5159,7 +5172,7 @@ disable_breakpoints_in_shlibs (void) to insert those breakpoints and fail. */ if (((b->type == bp_breakpoint) || (b->type == bp_hardware_breakpoint) - || (b->type == bp_tracepoint)) + || (tracepoint_type (b))) && loc->pspace == current_program_space && !loc->shlib_disabled #ifdef PC_SOLIB @@ -6091,6 +6104,16 @@ mention (struct breakpoint *b) printf_filtered (_(" %d"), b->number); say_where = 1; break; + case bp_fast_tracepoint: + if (ui_out_is_mi_like_p (uiout)) + { + say_where = 0; + break; + } + printf_filtered (_("Fast tracepoint")); + printf_filtered (_(" %d"), b->number); + say_where = 1; + break; case bp_until: case bp_finish: @@ -6593,6 +6616,38 @@ breakpoint_sals_to_pc (struct symtabs_and_lines *sals, resolve_sal_pc (&sals->sals[i]); } +/* Fast tracepoints may have restrictions on valid locations. For + instance, a fast tracepoint using a jump instead of a trap will + likely have to overwrite more bytes than a trap would, and so can + only be placed where the instruction is longer than the jump, or a + multi-instruction sequence does not have a jump into the middle of + it, etc. */ + +static void +check_fast_tracepoint_sals (struct gdbarch *gdbarch, + struct symtabs_and_lines *sals) +{ + int i, rslt; + struct symtab_and_line *sal; + char *msg; + struct cleanup *old_chain; + + for (i = 0; i < sals->nelts; i++) + { + sal = &sals->sals[i]; + + rslt = gdbarch_fast_tracepoint_valid_at (gdbarch, sal->pc, + NULL, &msg); + old_chain = make_cleanup (xfree, msg); + + if (!rslt) + error (_("May not have a fast tracepoint at 0x%s%s"), + paddress (gdbarch, sal->pc), (msg ? msg : "")); + + do_cleanups (old_chain); + } +} + static void do_captured_parse_breakpoint (struct ui_out *ui, void *data) { @@ -6794,9 +6849,13 @@ break_command_really (struct gdbarch *gdbarch, breakpoint_sals_to_pc (&sals, addr_start); type_wanted = (traceflag - ? bp_tracepoint + ? (hardwareflag ? bp_fast_tracepoint : bp_tracepoint) : (hardwareflag ? bp_hardware_breakpoint : bp_breakpoint)); + /* Fast tracepoints may have additional restrictions on location. */ + if (type_wanted == bp_fast_tracepoint) + check_fast_tracepoint_sals (gdbarch, &sals); + /* Verify that condition can be parsed, before setting any breakpoints. Allocate a separate condition expression for each breakpoint. */ @@ -8970,6 +9029,7 @@ breakpoint_re_set_one (void *bint) case bp_breakpoint: case bp_hardware_breakpoint: case bp_tracepoint: + case bp_fast_tracepoint: /* Do not attempt to re-set breakpoints disabled during startup. */ if (b->enable_state == bp_startup_disabled) return 0; @@ -9369,6 +9429,7 @@ disable_command (char *args, int from_tty) continue; case bp_breakpoint: case bp_tracepoint: + case bp_fast_tracepoint: case bp_catchpoint: case bp_hardware_breakpoint: case bp_watchpoint: @@ -9462,6 +9523,7 @@ enable_command (char *args, int from_tty) continue; case bp_breakpoint: case bp_tracepoint: + case bp_fast_tracepoint: case bp_catchpoint: case bp_hardware_breakpoint: case bp_watchpoint: @@ -9769,6 +9831,22 @@ trace_command (char *arg, int from_tty) set_tracepoint_count (breakpoint_count); } +void +ftrace_command (char *arg, int from_tty) +{ + break_command_really (get_current_arch (), + arg, + NULL, 0, 1 /* parse arg */, + 0 /* tempflag */, 1 /* hardwareflag */, + 1 /* traceflag */, + 0 /* Ignore count */, + pending_break_support, + NULL, + from_tty, + 1 /* enabled */); + set_tracepoint_count (breakpoint_count); +} + /* Print information on tracepoint number TPNUM_EXP, or all if omitted. */ @@ -9846,7 +9924,7 @@ delete_trace_command (char *arg, int from_tty) { ALL_BREAKPOINTS_SAFE (b, temp) { - if (b->type == bp_tracepoint + if (tracepoint_type (b) && b->number >= 0) delete_breakpoint (b); } @@ -10501,6 +10579,13 @@ Do \"help tracepoints\" for info on other tracepoint commands.")); add_com_alias ("tra", "trace", class_alias, 1); add_com_alias ("trac", "trace", class_alias, 1); + c = add_com ("ftrace", class_breakpoint, ftrace_command, _("\ +Set a fast tracepoint at specified line or function.\n\ +\n" +BREAK_ARGS_HELP ("ftrace") "\n\ +Do \"help tracepoints\" for info on other tracepoint commands.")); + set_cmd_completer (c, location_completer); + add_info ("tracepoints", tracepoints_info, _("\ Status of tracepoints, or tracepoint number NUMBER.\n\ Convenience variable \"$tpnum\" contains the number of the\n\ |