mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-27 22:10:32 +00:00
2010-08-30 Yao Qi <yao@codesourcery.com>
* arm-linux-tdep.c (arm_linux_sigreturn_return_addr): New. (arm_linux_syscall_next_pc): New. (arm_linux_copy_svc): Use arm_linux_sigreturn_return_addr instead. (arm_linux_init_abi): Initialize syscall_next_pc. * arm-tdep.c (thumb_get_next_pc_raw): Get next pc of SWI in Thumb mode. (arm_get_next_pc_raw): Get next pc of SWI in ARM mode. * arm-tdep.h (struct gdbarch_tdep): Add a function pointer syscall_next_pc. Declare arm_frame_is_thumb.
This commit is contained in:
parent
eb34ac7a77
commit
25b41d01ea
@ -1,3 +1,14 @@
|
|||||||
|
2010-08-30 Yao Qi <yao@codesourcery.com>
|
||||||
|
|
||||||
|
* arm-linux-tdep.c (arm_linux_sigreturn_return_addr): New.
|
||||||
|
(arm_linux_syscall_next_pc): New.
|
||||||
|
(arm_linux_copy_svc): Use arm_linux_sigreturn_return_addr instead.
|
||||||
|
(arm_linux_init_abi): Initialize syscall_next_pc.
|
||||||
|
* arm-tdep.c (thumb_get_next_pc_raw): Get next pc of SWI in Thumb mode.
|
||||||
|
(arm_get_next_pc_raw): Get next pc of SWI in ARM mode.
|
||||||
|
* arm-tdep.h (struct gdbarch_tdep): Add a function pointer syscall_next_pc.
|
||||||
|
Declare arm_frame_is_thumb.
|
||||||
|
|
||||||
2010-08-30 Jan Kratochvil <jan.kratochvil@redhat.com>
|
2010-08-30 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
Code cleanup.
|
Code cleanup.
|
||||||
|
@ -630,6 +630,82 @@ arm_linux_regset_from_core_section (struct gdbarch *gdbarch,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy the value of next pc of sigreturn and rt_sigrturn into PC,
|
||||||
|
and return 1. Return 0 if it is not a rt_sigreturn/sigreturn
|
||||||
|
syscall. */
|
||||||
|
static int
|
||||||
|
arm_linux_sigreturn_return_addr (struct frame_info *frame,
|
||||||
|
unsigned long svc_number,
|
||||||
|
CORE_ADDR *pc)
|
||||||
|
{
|
||||||
|
/* Is this a sigreturn or rt_sigreturn syscall? */
|
||||||
|
if (svc_number == 119 || svc_number == 173)
|
||||||
|
{
|
||||||
|
if (get_frame_type (frame) == SIGTRAMP_FRAME)
|
||||||
|
{
|
||||||
|
*pc = frame_unwind_caller_pc (frame);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When FRAME is at a syscall instruction, return the PC of the next
|
||||||
|
instruction to be executed. */
|
||||||
|
|
||||||
|
static CORE_ADDR
|
||||||
|
arm_linux_syscall_next_pc (struct frame_info *frame)
|
||||||
|
{
|
||||||
|
CORE_ADDR pc = get_frame_pc (frame);
|
||||||
|
CORE_ADDR return_addr = 0;
|
||||||
|
int is_thumb = arm_frame_is_thumb (frame);
|
||||||
|
ULONGEST svc_number = 0;
|
||||||
|
int is_sigreturn = 0;
|
||||||
|
|
||||||
|
if (is_thumb)
|
||||||
|
{
|
||||||
|
svc_number = get_frame_register_unsigned (frame, 7);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct gdbarch *gdbarch = get_frame_arch (frame);
|
||||||
|
enum bfd_endian byte_order_for_code =
|
||||||
|
gdbarch_byte_order_for_code (gdbarch);
|
||||||
|
unsigned long this_instr =
|
||||||
|
read_memory_unsigned_integer (pc, 4, byte_order_for_code);
|
||||||
|
|
||||||
|
unsigned long svc_operand = (0x00ffffff & this_instr);
|
||||||
|
if (svc_operand) /* OABI. */
|
||||||
|
{
|
||||||
|
svc_number = svc_operand - 0x900000;
|
||||||
|
}
|
||||||
|
else /* EABI. */
|
||||||
|
{
|
||||||
|
svc_number = get_frame_register_unsigned (frame, 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is_sigreturn = arm_linux_sigreturn_return_addr (frame, svc_number,
|
||||||
|
&return_addr);
|
||||||
|
|
||||||
|
if (is_sigreturn)
|
||||||
|
return return_addr;
|
||||||
|
|
||||||
|
if (is_thumb)
|
||||||
|
{
|
||||||
|
return_addr = pc + 2;
|
||||||
|
/* Addresses for calling Thumb functions have the bit 0 set. */
|
||||||
|
return_addr |= 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return_addr = pc + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Insert a single step breakpoint at the next executed instruction. */
|
/* Insert a single step breakpoint at the next executed instruction. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -688,8 +764,11 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
|
|||||||
struct regcache *regs, struct displaced_step_closure *dsc)
|
struct regcache *regs, struct displaced_step_closure *dsc)
|
||||||
{
|
{
|
||||||
CORE_ADDR from = dsc->insn_addr;
|
CORE_ADDR from = dsc->insn_addr;
|
||||||
|
CORE_ADDR return_to = 0;
|
||||||
|
|
||||||
struct frame_info *frame;
|
struct frame_info *frame;
|
||||||
unsigned int svc_number = displaced_read_reg (regs, from, 7);
|
unsigned int svc_number = displaced_read_reg (regs, from, 7);
|
||||||
|
int is_sigreturn = 0;
|
||||||
|
|
||||||
if (debug_displaced)
|
if (debug_displaced)
|
||||||
fprintf_unfiltered (gdb_stdlog, "displaced: copying Linux svc insn %.8lx\n",
|
fprintf_unfiltered (gdb_stdlog, "displaced: copying Linux svc insn %.8lx\n",
|
||||||
@ -697,13 +776,10 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
|
|||||||
|
|
||||||
frame = get_current_frame ();
|
frame = get_current_frame ();
|
||||||
|
|
||||||
/* Is this a sigreturn or rt_sigreturn syscall? Note: these are only useful
|
is_sigreturn = arm_linux_sigreturn_return_addr(frame, svc_number,
|
||||||
for EABI. */
|
&return_to);
|
||||||
if (svc_number == 119 || svc_number == 173)
|
if (is_sigreturn)
|
||||||
{
|
{
|
||||||
if (get_frame_type (frame) == SIGTRAMP_FRAME)
|
|
||||||
{
|
|
||||||
CORE_ADDR return_to;
|
|
||||||
struct symtab_and_line sal;
|
struct symtab_and_line sal;
|
||||||
|
|
||||||
if (debug_displaced)
|
if (debug_displaced)
|
||||||
@ -711,7 +787,6 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
|
|||||||
"sigreturn/rt_sigreturn SVC call. PC in frame = %lx\n",
|
"sigreturn/rt_sigreturn SVC call. PC in frame = %lx\n",
|
||||||
(unsigned long) get_frame_pc (frame));
|
(unsigned long) get_frame_pc (frame));
|
||||||
|
|
||||||
return_to = frame_unwind_caller_pc (frame);
|
|
||||||
if (debug_displaced)
|
if (debug_displaced)
|
||||||
fprintf_unfiltered (gdb_stdlog, "displaced: unwind pc = %lx. "
|
fprintf_unfiltered (gdb_stdlog, "displaced: unwind pc = %lx. "
|
||||||
"Setting momentary breakpoint.\n", (unsigned long) return_to);
|
"Setting momentary breakpoint.\n", (unsigned long) return_to);
|
||||||
@ -743,7 +818,7 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
|
|||||||
else if (debug_displaced)
|
else if (debug_displaced)
|
||||||
fprintf_unfiltered (gdb_stdlog, "displaced: sigreturn/rt_sigreturn "
|
fprintf_unfiltered (gdb_stdlog, "displaced: sigreturn/rt_sigreturn "
|
||||||
"SVC call not in signal trampoline frame\n");
|
"SVC call not in signal trampoline frame\n");
|
||||||
}
|
|
||||||
|
|
||||||
/* Preparation: If we detect sigreturn, set momentary breakpoint at resume
|
/* Preparation: If we detect sigreturn, set momentary breakpoint at resume
|
||||||
location, else nothing.
|
location, else nothing.
|
||||||
@ -946,6 +1021,9 @@ arm_linux_init_abi (struct gdbarch_info info,
|
|||||||
set_gdbarch_displaced_step_free_closure (gdbarch,
|
set_gdbarch_displaced_step_free_closure (gdbarch,
|
||||||
simple_displaced_step_free_closure);
|
simple_displaced_step_free_closure);
|
||||||
set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
|
set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
|
||||||
|
|
||||||
|
|
||||||
|
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||||||
|
@ -270,7 +270,7 @@ arm_psr_thumb_bit (struct gdbarch *gdbarch)
|
|||||||
|
|
||||||
/* Determine if FRAME is executing in Thumb mode. */
|
/* Determine if FRAME is executing in Thumb mode. */
|
||||||
|
|
||||||
static int
|
int
|
||||||
arm_frame_is_thumb (struct frame_info *frame)
|
arm_frame_is_thumb (struct frame_info *frame)
|
||||||
{
|
{
|
||||||
CORE_ADDR cpsr;
|
CORE_ADDR cpsr;
|
||||||
@ -2828,7 +2828,16 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc, int insert_bkpt)
|
|||||||
else if ((inst1 & 0xf000) == 0xd000) /* conditional branch */
|
else if ((inst1 & 0xf000) == 0xd000) /* conditional branch */
|
||||||
{
|
{
|
||||||
unsigned long cond = bits (inst1, 8, 11);
|
unsigned long cond = bits (inst1, 8, 11);
|
||||||
if (cond != 0x0f && condition_true (cond, status)) /* 0x0f = SWI */
|
if (cond == 0x0f) /* 0x0f = SWI */
|
||||||
|
{
|
||||||
|
struct gdbarch_tdep *tdep;
|
||||||
|
tdep = gdbarch_tdep (gdbarch);
|
||||||
|
|
||||||
|
if (tdep->syscall_next_pc != NULL)
|
||||||
|
nextpc = tdep->syscall_next_pc (frame);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (cond != 0x0f && condition_true (cond, status))
|
||||||
nextpc = pc_val + (sbits (inst1, 0, 7) << 1);
|
nextpc = pc_val + (sbits (inst1, 0, 7) << 1);
|
||||||
}
|
}
|
||||||
else if ((inst1 & 0xf800) == 0xe000) /* unconditional branch */
|
else if ((inst1 & 0xf800) == 0xe000) /* unconditional branch */
|
||||||
@ -3277,7 +3286,16 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc, int insert_bkpt)
|
|||||||
case 0xc:
|
case 0xc:
|
||||||
case 0xd:
|
case 0xd:
|
||||||
case 0xe: /* coproc ops */
|
case 0xe: /* coproc ops */
|
||||||
|
break;
|
||||||
case 0xf: /* SWI */
|
case 0xf: /* SWI */
|
||||||
|
{
|
||||||
|
struct gdbarch_tdep *tdep;
|
||||||
|
tdep = gdbarch_tdep (gdbarch);
|
||||||
|
|
||||||
|
if (tdep->syscall_next_pc != NULL)
|
||||||
|
nextpc = tdep->syscall_next_pc (frame);
|
||||||
|
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -196,6 +196,10 @@ struct gdbarch_tdep
|
|||||||
struct type *arm_ext_type;
|
struct type *arm_ext_type;
|
||||||
struct type *neon_double_type;
|
struct type *neon_double_type;
|
||||||
struct type *neon_quad_type;
|
struct type *neon_quad_type;
|
||||||
|
|
||||||
|
/* Return the expected next PC if FRAME is stopped at a syscall
|
||||||
|
instruction. */
|
||||||
|
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Structures used for displaced stepping. */
|
/* Structures used for displaced stepping. */
|
||||||
@ -297,6 +301,7 @@ extern void
|
|||||||
CORE_ADDR arm_skip_stub (struct frame_info *, CORE_ADDR);
|
CORE_ADDR arm_skip_stub (struct frame_info *, CORE_ADDR);
|
||||||
CORE_ADDR arm_get_next_pc (struct frame_info *, CORE_ADDR);
|
CORE_ADDR arm_get_next_pc (struct frame_info *, CORE_ADDR);
|
||||||
int arm_software_single_step (struct frame_info *);
|
int arm_software_single_step (struct frame_info *);
|
||||||
|
int arm_frame_is_thumb (struct frame_info *frame);
|
||||||
|
|
||||||
extern struct displaced_step_closure *
|
extern struct displaced_step_closure *
|
||||||
arm_displaced_step_copy_insn (struct gdbarch *, CORE_ADDR, CORE_ADDR,
|
arm_displaced_step_copy_insn (struct gdbarch *, CORE_ADDR, CORE_ADDR,
|
||||||
|
Loading…
Reference in New Issue
Block a user