@@ -1201,6 +1201,41 @@ 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;
+
+ target_mem = (gdb_byte *) alloca (insn_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, 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 +3392,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);
@@ -876,6 +876,43 @@ 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;
+ 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 false;
+
+ 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)
{
@@ -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);
@@ -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
@@ -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);
@@ -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)
{
@@ -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.
@@ -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.
@@ -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;