From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5807 invoked by alias); 29 Jan 2020 01:49:41 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 5799 invoked by uid 89); 29 Jan 2020 01:49:40 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy=ADDR, aarch64tdepc, aarch64-tdep.c, UD:aarch64-tdep.c X-HELO: mail-qt1-f194.google.com Received: from mail-qt1-f194.google.com (HELO mail-qt1-f194.google.com) (209.85.160.194) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 29 Jan 2020 01:49:37 +0000 Received: by mail-qt1-f194.google.com with SMTP id h12so12046165qtu.1 for ; Tue, 28 Jan 2020 17:49:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=pE9qv/RzNjEnIvnB7J87ERWMvvCNCrLjVzWjFZ197VA=; b=dnrU65j0TdrtLcpVMy0rjktueLDETO3c9JiziNnOXx8Ba9lmnsJpN6X+OK48FGaxaI CGqLro1aM2mcxv7TwQ7oi7G5RrT3TUmziuCDPMh3ObS661J45NwFbWPHj4NIiRav68DF SrPjdVRqQzFZkjftg9Y9l37D5RiVYNK5K7ApIjdGsG8D9+qQ8Hx3HWWuu9bFdeYlrlY6 0N7KeNh0X3GK0y9AV6NBQ7oniEW9RqvTEKpIKXAsHYS5iJYEFt0Gr9Y/pivOUZ9HMVvD A47dnxW1M4tAB62iq8VgQpfp1Qx8DamiJfV6uAY74GbLkzDo/PKTWSF0GH2GiZjQaXQ+ ebWw== Return-Path: Received: from [192.168.0.185] ([191.251.164.76]) by smtp.gmail.com with ESMTPSA id c8sm277983qtp.13.2020.01.28.17.49.32 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Jan 2020 17:49:34 -0800 (PST) Subject: Re: [PATCH 1/2,v3] [AArch64] Recognize more program breakpoint patterns To: Alan Hayward Cc: "gdb-patches\\@sourceware.org" , Simon Marchi , "tankut.baris.aktemur@intel.com" , nd References: <20200115115137.17771-1-luis.machado@linaro.org> <20200115115137.17771-2-luis.machado@linaro.org> <6D31397B-CC16-4ADA-BAC1-085718BC84E4@arm.com> From: Luis Machado Message-ID: Date: Wed, 29 Jan 2020 02:43:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.4.1 MIME-Version: 1.0 In-Reply-To: <6D31397B-CC16-4ADA-BAC1-085718BC84E4@arm.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit X-IsSubscribed: yes X-SW-Source: 2020-01/txt/msg00914.txt.bz2 Thanks Alan. Any other feedback? On 1/21/20 8:32 AM, Alan Hayward wrote: > I’m happy with this from AArch64 side. > > Alan. > >> On 15 Jan 2020, at 11:51, Luis Machado wrote: >> >> New in v3: >> >> - Code cleanups based on reviews. >> >> New in v2: >> >> - Fixed misc problems based on reviews. >> - Switched to using gdbarch_program_breakpoint_here_p as opposed to >> gdbarch_insn_is_breakpoint. >> - Fixed matching of brk instructions. Previously the mask was incorrect, which >> was showing up as a few failures in the testsuite. Now it is clean. >> - New testcase (separate patch). >> - Moved program_breakpoint_here () to arch-utils.c and made it the default >> implementation of gdbarch_program_breakpoint_here_p. >> >> -- >> >> It was reported to me that program breakpoints (permanent ones inserted into >> the code itself) other than the one GDB uses for AArch64 (0xd4200000) do not >> generate visible stops when continuing, and GDB will continue spinning >> infinitely. >> >> This happens because GDB, upon hitting one of those program breakpoints, thinks >> the SIGTRAP came from a delayed breakpoint hit... >> >> (gdb) x/i $pc >> => 0x4005c0 : brk #0x90f >> (gdb) c >> Continuing. >> infrun: clear_proceed_status_thread (process 14198) >> infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT) >> infrun: proceed: resuming process 14198 >> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14198] at 0x4005c0 >> infrun: infrun_async(1) >> infrun: prepare_to_wait >> infrun: target_wait (-1.0.0, status) = >> infrun: 14198.14198.0 [process 14198], >> infrun: status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: stop_pc = 0x4005c0 >> infrun: delayed software breakpoint trap, ignoring >> infrun: no stepping, continue >> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14198] at 0x4005c0 >> infrun: prepare_to_wait >> infrun: target_wait (-1.0.0, status) = >> infrun: 14198.14198.0 [process 14198], >> infrun: status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: stop_pc = 0x4005c0 >> infrun: delayed software breakpoint trap, ignoring >> infrun: no stepping, continue >> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14198] at 0x4005c0 >> infrun: prepare_to_wait >> infrun: target_wait (-1.0.0, status) = >> infrun: 14198.14198.0 [process 14198], >> infrun: status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: stop_pc = 0x4005c0 >> infrun: delayed software breakpoint trap, ignoring >> infrun: no stepping, continue >> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14198] at 0x4005c0 >> infrun: prepare_to_wait >> infrun: target_wait (-1.0.0, status) = >> infrun: 14198.14198.0 [process 14198], >> infrun: status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: stop_pc = 0x4005c0 >> infrun: delayed software breakpoint trap, ignoring >> infrun: no stepping, continue >> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14198] at 0x4005c0 >> infrun: prepare_to_wait >> infrun: target_wait (-1.0.0, status) = >> infrun: 14198.14198.0 [process 14198], >> infrun: status->kind = stopped, signal = GDB_SIGNAL_TRAP >> ... >> >> ... which is not the case. >> >> If the program breakpoint is one GDB recognizes, then it will stop when it >> hits it. >> >> (gdb) x/i $pc >> => 0x4005c0 : brk #0x0 >> (gdb) c >> Continuing. >> infrun: clear_proceed_status_thread (process 14193) >> infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT) >> infrun: proceed: resuming process 14193 >> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14193] at 0x4005c0 >> infrun: infrun_async(1) >> infrun: prepare_to_wait >> infrun: target_wait (-1.0.0, status) = >> infrun: 14193.14193.0 [process 14193], >> infrun: status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: stop_pc = 0x4005c0 >> infrun: random signal (GDB_SIGNAL_TRAP) >> infrun: stop_waiting >> infrun: stop_all_threads >> infrun: stop_all_threads, pass=0, iterations=0 >> infrun: process 14193 not executing >> infrun: stop_all_threads, pass=1, iterations=1 >> infrun: process 14193 not executing >> infrun: stop_all_threads done >> >> Program received signal SIGTRAP, Trace/breakpoint trap. >> problem_function () at brk_0.c:7 >> 7 asm("brk %0\n\t" ::"n"(0x0)); >> infrun: infrun_async(0) >> >> Otherwise GDB will keep trying to resume the inferior and will keep >> seeing the SIGTRAP's, without stopping. >> >> To the user it appears GDB has gone into an infinite loop, interruptible only >> by Ctrl-C. >> >> Also, windbg seems to use a different variation of AArch64 breakpoint compared >> to GDB. This causes problems when debugging Windows on ARM binaries, when >> program breakpoints are being used. >> >> The proposed patch creates a new gdbarch method (gdbarch_program_breakpoint_here_p) >> that tells GDB whether the underlying instruction is a breakpoint instruction >> or not. >> >> This is more general than only checking for the instruction GDB uses as >> breakpoint. >> >> The existing logic is still preserved for targets that do not implement this >> new gdbarch method. >> >> The end result is like so: >> >> (gdb) x/i $pc >> => 0x4005c0 : brk #0x90f >> (gdb) c >> Continuing. >> infrun: clear_proceed_status_thread (process 16417) >> infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT) >> infrun: proceed: resuming process 16417 >> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 16417] at 0x4005c0 >> infrun: infrun_async(1) >> infrun: prepare_to_wait >> infrun: target_wait (-1.0.0, status) = >> infrun: 16417.16417.0 [process 16417], >> infrun: status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP >> infrun: stop_pc = 0x4005c0 >> infrun: random signal (GDB_SIGNAL_TRAP) >> infrun: stop_waiting >> infrun: stop_all_threads >> infrun: stop_all_threads, pass=0, iterations=0 >> infrun: process 16417 not executing >> infrun: stop_all_threads, pass=1, iterations=1 >> infrun: process 16417 not executing >> infrun: stop_all_threads done >> >> Program received signal SIGTRAP, Trace/breakpoint trap. >> problem_function () at brk.c:7 >> 7 asm("brk %0\n\t" ::"n"(0x900 + 0xf)); >> infrun: infrun_async(0) >> >> gdb/ChangeLog: >> >> 2020-01-15 Luis Machado >> >> * aarch64-tdep.c (BRK_INSN_MASK): Define to 0xffe0001f. >> (BRK_INSN_MASK): Define to 0xd4200000. >> (aarch64_program_breakpoint_here_p): New function. >> (aarch64_gdbarch_init): Set gdbarch_program_breakpoint_here_p hook. >> * arch-utils.c (default_program_breakpoint_here_p): Moved from >> breakpoint.c. >> * arch-utils.h (default_program_breakpoint_here_p): Moved from >> breakpoint.h >> * breakpoint.c (bp_loc_is_permanent): Changed return type to bool and >> call gdbarch_program_breakpoint_here_p. >> (program_breakpoint_here): Moved to arch-utils.c, renamed to >> default_program_breakpoint_here_p, changed return type to bool and >> simplified. >> * breakpoint.h (program_breakpoint_here): Moved prototype to >> arch-utils.h, renamed to default_program_breakpoint_here_p and changed >> return type to bool. >> * gdbarch.c: Regenerate. >> * gdbarch.h: Regenerate. >> * gdbarch.sh (program_breakpoint_here_p): New method. >> * infrun.c (handle_signal_stop): Call >> gdbarch_program_breakpoint_here_p. >> --- >> gdb/aarch64-tdep.c | 37 +++++++++++++++++++++++++++++++++++++ >> gdb/arch-utils.c | 32 ++++++++++++++++++++++++++++++++ >> gdb/arch-utils.h | 4 ++++ >> gdb/breakpoint.c | 46 +++++++--------------------------------------- >> gdb/breakpoint.h | 5 ----- >> gdb/gdbarch.c | 23 +++++++++++++++++++++++ >> gdb/gdbarch.h | 7 +++++++ >> gdb/gdbarch.sh | 4 ++++ >> gdb/infrun.c | 4 ++-- >> 9 files changed, 116 insertions(+), 46 deletions(-) >> >> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c >> index 8451a916dc..7f32df3ec0 100644 >> --- a/gdb/aarch64-tdep.c >> +++ b/gdb/aarch64-tdep.c >> @@ -1201,6 +1201,39 @@ aarch64_execute_dwarf_cfa_vendor_op (struct gdbarch *gdbarch, gdb_byte op, >> return false; >> } >> >> +/* Used for matching BRK instructions for AArch64. */ >> +static constexpr uint32_t BRK_INSN_MASK = 0xffe0001f; >> +static constexpr uint32_t BRK_INSN_BASE = 0xd4200000; >> + >> +/* Implementation of gdbarch_program_breakpoint_here_p for aarch64. */ >> + >> +static bool >> +aarch64_program_breakpoint_here_p (gdbarch *gdbarch, CORE_ADDR address) >> +{ >> + const uint32_t insn_len = 4; >> + gdb_byte target_mem[4]; >> + >> + /* Enable the automatic memory restoration from breakpoints while >> + we read the memory. Otherwise we may find temporary breakpoints, ones >> + inserted by GDB, and flag them as permanent breakpoints. */ >> + scoped_restore restore_memory >> + = make_scoped_restore_show_memory_breakpoints (0); >> + >> + if (target_read_memory (address, target_mem, insn_len) == 0) >> + { >> + uint32_t insn = >> + (uint32_t) extract_unsigned_integer (target_mem, insn_len, >> + gdbarch_byte_order_for_code (gdbarch)); >> + >> + /* Check if INSN is a BRK instruction pattern. There are multiple choices >> + of such instructions with different immediate values. Different OS' >> + may use a different variation, but they have the same outcome. */ >> + return ((insn & BRK_INSN_MASK) == BRK_INSN_BASE); >> + } >> + >> + return false; >> +} >> + >> /* When arguments must be pushed onto the stack, they go on in reverse >> order. The code below implements a FILO (stack) to do this. */ >> >> @@ -3357,6 +3390,10 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) >> set_gdbarch_execute_dwarf_cfa_vendor_op (gdbarch, >> aarch64_execute_dwarf_cfa_vendor_op); >> >> + /* Permanent/Program breakpoint handling. */ >> + set_gdbarch_program_breakpoint_here_p (gdbarch, >> + aarch64_program_breakpoint_here_p); >> + >> /* Add some default predicates. */ >> frame_unwind_append_unwinder (gdbarch, &aarch64_stub_unwind); >> dwarf2_append_unwinders (gdbarch); >> diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c >> index 92d7153ccb..04955ea847 100644 >> --- a/gdb/arch-utils.c >> +++ b/gdb/arch-utils.c >> @@ -876,6 +876,38 @@ int default_insn_is_jump (struct gdbarch *gdbarch, CORE_ADDR addr) >> return 0; >> } >> >> +/* See arch-utils.h. */ >> + >> +bool >> +default_program_breakpoint_here_p (struct gdbarch *gdbarch, >> + CORE_ADDR address) >> +{ >> + int len; >> + const gdb_byte *bpoint = gdbarch_breakpoint_from_pc (gdbarch, &address, &len); >> + >> + /* Software breakpoints unsupported? */ >> + if (bpoint == nullptr) >> + return false; >> + >> + gdb_byte *target_mem = (gdb_byte *) alloca (len); >> + >> + /* Enable the automatic memory restoration from breakpoints while >> + we read the memory. Otherwise we may find temporary breakpoints, ones >> + inserted by GDB, and flag them as permanent breakpoints. */ >> + scoped_restore restore_memory >> + = make_scoped_restore_show_memory_breakpoints (0); >> + >> + if (target_read_memory (address, target_mem, len) == 0) >> + { >> + /* Check if this is a breakpoint instruction for this architecture, >> + including ones used by GDB. */ >> + if (memcmp (target_mem, bpoint, len) == 0) >> + return true; >> + } >> + >> + return false; >> +} >> + >> void >> default_skip_permanent_breakpoint (struct regcache *regcache) >> { >> diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h >> index 3fb9ad317a..43d64b1f4f 100644 >> --- a/gdb/arch-utils.h >> +++ b/gdb/arch-utils.h >> @@ -228,6 +228,10 @@ extern int default_insn_is_call (struct gdbarch *, CORE_ADDR); >> extern int default_insn_is_ret (struct gdbarch *, CORE_ADDR); >> extern int default_insn_is_jump (struct gdbarch *, CORE_ADDR); >> >> +/* Default implementation of gdbarch_program_breakpoint_here_p. */ >> +extern bool default_program_breakpoint_here_p (struct gdbarch *gdbarch, >> + CORE_ADDR addr); >> + >> /* Do-nothing version of vsyscall_range. Returns false. */ >> >> extern int default_vsyscall_range (struct gdbarch *gdbarch, struct mem_range *range); >> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c >> index a7a378131a..5a9352c26f 100644 >> --- a/gdb/breakpoint.c >> +++ b/gdb/breakpoint.c >> @@ -8515,7 +8515,7 @@ mention (struct breakpoint *b) >> } >> >> >> -static int bp_loc_is_permanent (struct bp_location *loc); >> +static bool bp_loc_is_permanent (struct bp_location *loc); >> >> static struct bp_location * >> add_location_to_breakpoint (struct breakpoint *b, >> @@ -8581,42 +8581,10 @@ add_location_to_breakpoint (struct breakpoint *b, >> } >> >> >> -/* See breakpoint.h. */ >> - >> -int >> -program_breakpoint_here_p (struct gdbarch *gdbarch, CORE_ADDR address) >> -{ >> - int len; >> - CORE_ADDR addr; >> - const gdb_byte *bpoint; >> - gdb_byte *target_mem; >> - >> - addr = address; >> - bpoint = gdbarch_breakpoint_from_pc (gdbarch, &addr, &len); >> - >> - /* Software breakpoints unsupported? */ >> - if (bpoint == NULL) >> - return 0; >> - >> - target_mem = (gdb_byte *) alloca (len); >> - >> - /* Enable the automatic memory restoration from breakpoints while >> - we read the memory. Otherwise we could say about our temporary >> - breakpoints they are permanent. */ >> - scoped_restore restore_memory >> - = make_scoped_restore_show_memory_breakpoints (0); >> +/* Return true if LOC is pointing to a permanent breakpoint, >> + return false otherwise. */ >> >> - if (target_read_memory (address, target_mem, len) == 0 >> - && memcmp (target_mem, bpoint, len) == 0) >> - return 1; >> - >> - return 0; >> -} >> - >> -/* Return 1 if LOC is pointing to a permanent breakpoint, >> - return 0 otherwise. */ >> - >> -static int >> +static bool >> bp_loc_is_permanent (struct bp_location *loc) >> { >> gdb_assert (loc != NULL); >> @@ -8624,14 +8592,14 @@ bp_loc_is_permanent (struct bp_location *loc) >> /* If we have a non-breakpoint-backed catchpoint or a software >> watchpoint, just return 0. We should not attempt to read from >> the addresses the locations of these breakpoint types point to. >> - program_breakpoint_here_p, below, will attempt to read >> + gdbarch_program_breakpoint_here_p, below, will attempt to read >> memory. */ >> if (!bl_address_is_meaningful (loc)) >> - return 0; >> + return false; >> >> scoped_restore_current_pspace_and_thread restore_pspace_thread; >> switch_to_program_space_and_thread (loc->pspace); >> - return program_breakpoint_here_p (loc->gdbarch, loc->address); >> + return gdbarch_program_breakpoint_here_p (loc->gdbarch, loc->address); >> } >> >> /* Build a command list for the dprintf corresponding to the current >> diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h >> index 13d8102c17..347aeb75f3 100644 >> --- a/gdb/breakpoint.h >> +++ b/gdb/breakpoint.h >> @@ -1194,11 +1194,6 @@ enum breakpoint_here >> >> /* Prototypes for breakpoint-related functions. */ >> >> -/* Return 1 if there's a program/permanent breakpoint planted in >> - memory at ADDRESS, return 0 otherwise. */ >> - >> -extern int program_breakpoint_here_p (struct gdbarch *gdbarch, CORE_ADDR address); >> - >> extern enum breakpoint_here breakpoint_here_p (const address_space *, >> CORE_ADDR); >> >> diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c >> index cc8569f5c9..d763fc85e6 100644 >> --- a/gdb/gdbarch.c >> +++ b/gdb/gdbarch.c >> @@ -345,6 +345,7 @@ struct gdbarch >> gdbarch_insn_is_call_ftype *insn_is_call; >> gdbarch_insn_is_ret_ftype *insn_is_ret; >> gdbarch_insn_is_jump_ftype *insn_is_jump; >> + gdbarch_program_breakpoint_here_p_ftype *program_breakpoint_here_p; >> gdbarch_auxv_parse_ftype *auxv_parse; >> gdbarch_print_auxv_entry_ftype *print_auxv_entry; >> gdbarch_vsyscall_range_ftype *vsyscall_range; >> @@ -464,6 +465,7 @@ gdbarch_alloc (const struct gdbarch_info *info, >> gdbarch->insn_is_call = default_insn_is_call; >> gdbarch->insn_is_ret = default_insn_is_ret; >> gdbarch->insn_is_jump = default_insn_is_jump; >> + gdbarch->program_breakpoint_here_p = default_program_breakpoint_here_p; >> gdbarch->print_auxv_entry = default_print_auxv_entry; >> gdbarch->vsyscall_range = default_vsyscall_range; >> gdbarch->infcall_mmap = default_infcall_mmap; >> @@ -708,6 +710,7 @@ verify_gdbarch (struct gdbarch *gdbarch) >> /* Skip verify of insn_is_call, invalid_p == 0 */ >> /* Skip verify of insn_is_ret, invalid_p == 0 */ >> /* Skip verify of insn_is_jump, invalid_p == 0 */ >> + /* Skip verify of program_breakpoint_here_p, invalid_p == 0 */ >> /* Skip verify of auxv_parse, has predicate. */ >> /* Skip verify of print_auxv_entry, invalid_p == 0 */ >> /* Skip verify of vsyscall_range, invalid_p == 0 */ >> @@ -1248,6 +1251,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) >> fprintf_unfiltered (file, >> "gdbarch_dump: process_record_signal = <%s>\n", >> host_address_to_string (gdbarch->process_record_signal)); >> + fprintf_unfiltered (file, >> + "gdbarch_dump: program_breakpoint_here_p = <%s>\n", >> + host_address_to_string (gdbarch->program_breakpoint_here_p)); >> fprintf_unfiltered (file, >> "gdbarch_dump: ps_regnum = %s\n", >> plongest (gdbarch->ps_regnum)); >> @@ -4928,6 +4934,23 @@ set_gdbarch_insn_is_jump (struct gdbarch *gdbarch, >> gdbarch->insn_is_jump = insn_is_jump; >> } >> >> +bool >> +gdbarch_program_breakpoint_here_p (struct gdbarch *gdbarch, CORE_ADDR address) >> +{ >> + gdb_assert (gdbarch != NULL); >> + gdb_assert (gdbarch->program_breakpoint_here_p != NULL); >> + if (gdbarch_debug >= 2) >> + fprintf_unfiltered (gdb_stdlog, "gdbarch_program_breakpoint_here_p called\n"); >> + return gdbarch->program_breakpoint_here_p (gdbarch, address); >> +} >> + >> +void >> +set_gdbarch_program_breakpoint_here_p (struct gdbarch *gdbarch, >> + gdbarch_program_breakpoint_here_p_ftype program_breakpoint_here_p) >> +{ >> + gdbarch->program_breakpoint_here_p = program_breakpoint_here_p; >> +} >> + >> int >> gdbarch_auxv_parse_p (struct gdbarch *gdbarch) >> { >> diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h >> index 9f32ac23ab..800a4e8b16 100644 >> --- a/gdb/gdbarch.h >> +++ b/gdb/gdbarch.h >> @@ -1545,6 +1545,13 @@ typedef int (gdbarch_insn_is_jump_ftype) (struct gdbarch *gdbarch, CORE_ADDR add >> extern int gdbarch_insn_is_jump (struct gdbarch *gdbarch, CORE_ADDR addr); >> extern void set_gdbarch_insn_is_jump (struct gdbarch *gdbarch, gdbarch_insn_is_jump_ftype *insn_is_jump); >> >> +/* Return true if there's a program/permanent breakpoint planted in >> + memory at ADDRESS, return false otherwise. */ >> + >> +typedef bool (gdbarch_program_breakpoint_here_p_ftype) (struct gdbarch *gdbarch, CORE_ADDR address); >> +extern bool gdbarch_program_breakpoint_here_p (struct gdbarch *gdbarch, CORE_ADDR address); >> +extern void set_gdbarch_program_breakpoint_here_p (struct gdbarch *gdbarch, gdbarch_program_breakpoint_here_p_ftype *program_breakpoint_here_p); >> + >> /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR. >> Return 0 if *READPTR is already at the end of the buffer. >> Return -1 if there is insufficient buffer for a whole entry. >> diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh >> index 0be3e88bb2..66b54dd700 100755 >> --- a/gdb/gdbarch.sh >> +++ b/gdb/gdbarch.sh >> @@ -1152,6 +1152,10 @@ m;int;insn_is_ret;CORE_ADDR addr;addr;;default_insn_is_ret;;0 >> # Return non-zero if the instruction at ADDR is a jump; zero otherwise. >> m;int;insn_is_jump;CORE_ADDR addr;addr;;default_insn_is_jump;;0 >> >> +# Return true if there's a program/permanent breakpoint planted in >> +# memory at ADDRESS, return false otherwise. >> +m;bool;program_breakpoint_here_p;CORE_ADDR address;address;;default_program_breakpoint_here_p;;0 >> + >> # Read one auxv entry from *READPTR, not reading locations >= ENDPTR. >> # Return 0 if *READPTR is already at the end of the buffer. >> # Return -1 if there is insufficient buffer for a whole entry. >> diff --git a/gdb/infrun.c b/gdb/infrun.c >> index a8636284f1..494324d72b 100644 >> --- a/gdb/infrun.c >> +++ b/gdb/infrun.c >> @@ -6157,8 +6157,8 @@ handle_signal_stop (struct execution_control_state *ecs) >> been removed. */ >> if (random_signal && target_stopped_by_sw_breakpoint ()) >> { >> - if (program_breakpoint_here_p (gdbarch, >> - ecs->event_thread->suspend.stop_pc)) >> + if (gdbarch_program_breakpoint_here_p (gdbarch, >> + ecs->event_thread->suspend.stop_pc)) >> { >> struct regcache *regcache; >> int decr_pc; >> -- >> 2.17.1 >> >