diff options
author | Yao Qi <yao.qi@arm.com> | 2016-05-23 17:32:56 +0100 |
---|---|---|
committer | Yao Qi <yao.qi@linaro.org> | 2016-05-23 17:32:56 +0100 |
commit | 7eb895307f53af3435440d3fe67c0e4e679d99b2 (patch) | |
tree | f00e0024cc8dbc112a7c99c5b604e0a7dd9501ab /gdb/gdbarch.c | |
parent | 0f6ed0e0efe2c4dcd35b0e483dc3b5da7fe4edf0 (diff) | |
download | gdb-7eb895307f53af3435440d3fe67c0e4e679d99b2.zip gdb-7eb895307f53af3435440d3fe67c0e4e679d99b2.tar.gz gdb-7eb895307f53af3435440d3fe67c0e4e679d99b2.tar.bz2 |
Skip unwritable frames in command "finish"
Nowadays, GDB can't insert breakpoint on the return address of the
exception handler on ARM M-profile, because the address is a magic
one 0xfffffff9,
(gdb) bt
#0 CT32B1_IRQHandler () at ../src/timer.c:67
#1 <signal handler called>
#2 main () at ../src/timer.c:127
(gdb) info frame
Stack level 0, frame at 0x200ffa8:
pc = 0x4ec in CT32B1_IRQHandler (../src/timer.c:67); saved pc = 0xfffffff9
called by frame at 0x200ffc8
source language c.
Arglist at 0x200ffa0, args:
Locals at 0x200ffa0, Previous frame's sp is 0x200ffa8
Saved registers:
r7 at 0x200ffa0, lr at 0x200ffa4
(gdb) x/x 0xfffffff9
0xfffffff9: Cannot access memory at address 0xfffffff9
(gdb) finish
Run till exit from #0 CT32B1_IRQHandler () at ../src/timer.c:67
Ed:15: Target error from Set break/watch: Et:96: Pseudo-address (0xFFFFFFxx) for EXC_RETURN is invalid (GDB error?)
Warning:
Cannot insert hardware breakpoint 0.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.
Command aborted.
even some debug probe can't set hardware breakpoint on the magic
address too,
(gdb) hbreak *0xfffffff9
Hardware assisted breakpoint 2 at 0xfffffff9
(gdb) c
Continuing.
Ed:15: Target error from Set break/watch: Et:96: Pseudo-address (0xFFFFFFxx) for EXC_RETURN is invalid (GDB error?)
Warning:
Cannot insert hardware breakpoint 2.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.
Command aborted.
The problem described above is quite similar to PR 8841, in which GDB
can't set breakpoint on signal trampoline, which is mapped to a read-only
page by kernel. The rationale of this patch is to skip "unwritable"
frames when looking for caller frames in command "finish", and a new
gdbarch method code_of_frame_writable is added. This patch fixes
the problem on ARM cortex-m target, but it can be used to fix
PR 8841 too.
gdb:
2016-05-10 Yao Qi <yao.qi@arm.com>
* arch-utils.c (default_code_of_frame_writable): New function.
* arch-utils.h (default_code_of_frame_writable): Declare.
* arm-tdep.c (arm_code_of_frame_writable): New function.
(arm_gdbarch_init): Install gdbarch method
code_of_frame_writable if the target is M-profile.
* frame.c (skip_unwritable_frames): New function.
* frame.h (skip_unwritable_frames): Declare.
* gdbarch.sh (code_of_frame_writable): New.
* gdbarch.c, gdbarch.h: Re-generated.
* infcmd.c (finish_command): Call skip_unwritable_frames.
Diffstat (limited to 'gdb/gdbarch.c')
-rw-r--r-- | gdb/gdbarch.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index bd0b48c..313502b 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -205,6 +205,7 @@ struct gdbarch gdbarch_push_dummy_call_ftype *push_dummy_call; int call_dummy_location; gdbarch_push_dummy_code_ftype *push_dummy_code; + gdbarch_code_of_frame_writable_ftype *code_of_frame_writable; gdbarch_print_registers_info_ftype *print_registers_info; gdbarch_print_float_info_ftype *print_float_info; gdbarch_print_vector_info_ftype *print_vector_info; @@ -387,6 +388,7 @@ gdbarch_alloc (const struct gdbarch_info *info, gdbarch->dwarf2_reg_to_regnum = no_op_reg_to_regnum; gdbarch->deprecated_fp_regnum = -1; gdbarch->call_dummy_location = AT_ENTRY_POINT; + gdbarch->code_of_frame_writable = default_code_of_frame_writable; gdbarch->print_registers_info = default_print_registers_info; gdbarch->print_float_info = default_print_float_info; gdbarch->register_sim_regno = legacy_register_sim_regno; @@ -552,6 +554,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of push_dummy_call, has predicate. */ /* Skip verify of call_dummy_location, invalid_p == 0 */ /* Skip verify of push_dummy_code, has predicate. */ + /* Skip verify of code_of_frame_writable, invalid_p == 0 */ /* Skip verify of print_registers_info, invalid_p == 0 */ /* Skip verify of print_float_info, invalid_p == 0 */ /* Skip verify of print_vector_info, has predicate. */ @@ -804,6 +807,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: char_signed = %s\n", plongest (gdbarch->char_signed)); fprintf_unfiltered (file, + "gdbarch_dump: code_of_frame_writable = <%s>\n", + host_address_to_string (gdbarch->code_of_frame_writable)); + fprintf_unfiltered (file, "gdbarch_dump: coff_make_msymbol_special = <%s>\n", host_address_to_string (gdbarch->coff_make_msymbol_special)); fprintf_unfiltered (file, @@ -2314,6 +2320,23 @@ set_gdbarch_push_dummy_code (struct gdbarch *gdbarch, gdbarch->push_dummy_code = push_dummy_code; } +int +gdbarch_code_of_frame_writable (struct gdbarch *gdbarch, struct frame_info *frame) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->code_of_frame_writable != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_code_of_frame_writable called\n"); + return gdbarch->code_of_frame_writable (gdbarch, frame); +} + +void +set_gdbarch_code_of_frame_writable (struct gdbarch *gdbarch, + gdbarch_code_of_frame_writable_ftype code_of_frame_writable) +{ + gdbarch->code_of_frame_writable = code_of_frame_writable; +} + void gdbarch_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, int regnum, int all) { |