* arm-linux-tdep.c (arm_linux_software_single_step): New.

(arm_linux_init_abi): Use it.
	* arm-tdep.c (arm_get_next_pc): Make global.  Handle all-ones
	condition correctly.
	* arm-tdep.h (arm_get_next_pc): Declare.
	* Makefile.in (arm-linux-tdep.o): Update.
This commit is contained in:
Daniel Jacobowitz 2007-09-27 18:48:33 +00:00
parent 7c52e0e865
commit daddc3c15f
5 changed files with 58 additions and 8 deletions

View file

@ -1,3 +1,12 @@
2007-09-27 Daniel Jacobowitz <dan@codesourcery.com>
* arm-linux-tdep.c (arm_linux_software_single_step): New.
(arm_linux_init_abi): Use it.
* arm-tdep.c (arm_get_next_pc): Make global. Handle all-ones
condition correctly.
* arm-tdep.h (arm_get_next_pc): Declare.
* Makefile.in (arm-linux-tdep.o): Update.
2007-09-26 Vladimir Prus <vladimir@codesourcery.com>
* varobj.c (install_new_value): Don't

View file

@ -1805,7 +1805,7 @@ arm-linux-nat.o: arm-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
arm-linux-tdep.o: arm-linux-tdep.c $(defs_h) $(target_h) $(value_h) \
$(gdbtypes_h) $(floatformat_h) $(gdbcore_h) $(frame_h) $(regcache_h) \
$(doublest_h) $(solib_svr4_h) $(osabi_h) $(arm_tdep_h) \
$(regset_h) $(arm_linux_tdep_h) \
$(regset_h) $(arm_linux_tdep_h) $(breakpoint_h) \
$(glibc_tdep_h) $(trad_frame_h) $(tramp_frame_h) $(gdb_string_h)
armnbsd-nat.o: armnbsd-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) \
$(regcache_h) $(target_h) $(gdb_string_h) $(arm_tdep_h) $(inf_ptrace_h)

View file

@ -32,6 +32,7 @@
#include "regset.h"
#include "trad-frame.h"
#include "tramp-frame.h"
#include "breakpoint.h"
#include "arm-tdep.h"
#include "arm-linux-tdep.h"
@ -568,6 +569,26 @@ arm_linux_regset_from_core_section (struct gdbarch *gdbarch,
return NULL;
}
/* Insert a single step breakpoint at the next executed instruction. */
int
arm_linux_software_single_step (struct frame_info *frame)
{
CORE_ADDR next_pc = arm_get_next_pc (frame, get_frame_pc (frame));
/* The Linux kernel offers some user-mode helpers in a high page. We can
not read this page (as of 2.6.23), and even if we could then we couldn't
set breakpoints in it, and even if we could then the atomic operations
would fail when interrupted. They are all called as functions and return
to the address in LR, so step to there instead. */
if (next_pc > 0xffff0000)
next_pc = get_frame_register_unsigned (frame, ARM_LR_REGNUM);
insert_single_step_breakpoint (next_pc);
return 1;
}
static void
arm_linux_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch)
@ -604,7 +625,7 @@ arm_linux_init_abi (struct gdbarch_info info,
(gdbarch, svr4_ilp32_fetch_link_map_offsets);
/* Single stepping. */
set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
set_gdbarch_software_single_step (gdbarch, arm_linux_software_single_step);
/* Shared library handling. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);

View file

@ -1664,7 +1664,7 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
return nextpc;
}
static CORE_ADDR
CORE_ADDR
arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
{
unsigned long pc_val;
@ -1680,7 +1680,30 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
status = get_frame_register_unsigned (frame, ARM_PS_REGNUM);
nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */
if (condition_true (bits (this_instr, 28, 31), status))
if (bits (this_instr, 28, 31) == INST_NV)
switch (bits (this_instr, 24, 27))
{
case 0xa:
case 0xb:
{
/* Branch with Link and change to Thumb. */
nextpc = BranchDest (pc, this_instr);
nextpc |= bit (this_instr, 24) << 1;
nextpc = gdbarch_addr_bits_remove (current_gdbarch, nextpc);
if (nextpc == pc)
error (_("Infinite loop detected"));
break;
}
case 0xc:
case 0xd:
case 0xe:
/* Coprocessor register transfer. */
if (bits (this_instr, 12, 15) == 15)
error (_("Invalid update to pc in instruction"));
break;
}
else if (condition_true (bits (this_instr, 28, 31), status))
{
switch (bits (this_instr, 24, 27))
{
@ -1886,10 +1909,6 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
{
nextpc = BranchDest (pc, this_instr);
/* BLX */
if (bits (this_instr, 28, 31) == INST_NV)
nextpc |= bit (this_instr, 24) << 1;
nextpc = gdbarch_addr_bits_remove (current_gdbarch, nextpc);
if (nextpc == pc)
error (_("Infinite loop detected"));

View file

@ -181,6 +181,7 @@ struct gdbarch_tdep
#endif
CORE_ADDR arm_skip_stub (struct frame_info *, CORE_ADDR);
CORE_ADDR arm_get_next_pc (struct frame_info *, CORE_ADDR);
int arm_software_single_step (struct frame_info *);
/* Functions exported from armbsd-tdep.h. */