diff options
-rw-r--r-- | gdb/ChangeLog | 24 | ||||
-rw-r--r-- | gdb/aarch64-tdep.c | 37 | ||||
-rw-r--r-- | gdb/arch-utils.c | 32 | ||||
-rw-r--r-- | gdb/arch-utils.h | 4 | ||||
-rw-r--r-- | gdb/breakpoint.c | 46 | ||||
-rw-r--r-- | gdb/breakpoint.h | 5 | ||||
-rw-r--r-- | gdb/gdbarch.c | 23 | ||||
-rw-r--r-- | gdb/gdbarch.h | 7 | ||||
-rwxr-xr-x | gdb/gdbarch.sh | 4 | ||||
-rw-r--r-- | gdb/infrun.c | 4 |
10 files changed, 140 insertions, 46 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8b6da62..ee2ba1c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,27 @@ +2020-01-29 Luis Machado <luis.machado@linaro.org> + + * 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. + 2020-01-26 Tom Tromey <tom@tromey.com> * ctfread.c (struct ctf_fp_info): Reindent. diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 1631178..120c5db 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. */ @@ -3389,6 +3422,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 92d7153..04955ea 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 3fb9ad3..43d64b1 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 a7a3781..5a9352c 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 13d8102..347aeb7 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 cc8569f..d763fc8 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 */ @@ -1249,6 +1252,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *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)); fprintf_unfiltered (file, @@ -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 9f32ac2..800a4e8 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 58f6e1e..a86de96 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 22de42c..c8369cb 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -6147,8 +6147,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; |