int arm_breakpoint_at (CORE_ADDR where) { if (arm_is_thumb_mode ()) { /* Thumb mode. */ unsigned short insn; (*the_target->read_memory) (where, (unsigned char *) &insn, 2); if (insn == thumb_breakpoint) return 1; if (insn == thumb2_breakpoint[0]) { (*the_target->read_memory) (where + 2, (unsigned char *) &insn, 2); if (insn == thumb2_breakpoint[1]) return 1; } } else { /* ARM mode. */ unsigned long insn; (*the_target->read_memory) (where, (unsigned char *) &insn, 4); if (insn == arm_abi_breakpoint) return 1; if (insn == arm_eabi_breakpoint) return 1; } return 0; }
static void arm_get_syscall_trapinfo (struct regcache *regcache, int *sysno) { if (arm_is_thumb_mode ()) collect_register_by_name (regcache, "r7", sysno); else { unsigned long pc; unsigned long insn; collect_register_by_name (regcache, "pc", &pc); if ((*the_target->read_memory) (pc - 4, (unsigned char *) &insn, 4)) *sysno = UNKNOWN_SYSCALL; else { unsigned long svc_operand = (0x00ffffff & insn); if (svc_operand) { /* OABI */ *sysno = svc_operand - 0x900000; } else { /* EABI */ collect_register_by_name (regcache, "r7", sysno); } } } }
int arm_breakpoint_kind_from_current_state (CORE_ADDR *pcptr) { if (arm_is_thumb_mode ()) { *pcptr = MAKE_THUMB_ADDR (*pcptr); return arm_breakpoint_kind_from_pc (pcptr); } else { return arm_breakpoint_kind_from_pc (pcptr); } }
/* When PC is at a syscall instruction, return the PC of the next instruction to be executed. */ static CORE_ADDR get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self) { CORE_ADDR next_pc = 0; CORE_ADDR pc = regcache_read_pc (self->regcache); int is_thumb = arm_is_thumb_mode (); ULONGEST svc_number = 0; struct regcache *regcache = self->regcache; if (is_thumb) { collect_register (regcache, 7, &svc_number); next_pc = pc + 2; } else { unsigned long this_instr; unsigned long svc_operand; target_read_memory (pc, (unsigned char *) &this_instr, 4); svc_operand = (0x00ffffff & this_instr); if (svc_operand) /* OABI. */ { svc_number = svc_operand - 0x900000; } else /* EABI. */ { collect_register (regcache, 7, &svc_number); } next_pc = pc + 4; } /* This is a sigreturn or sigreturn_rt syscall. */ if (svc_number == __NR_sigreturn || svc_number == __NR_rt_sigreturn) { /* SIGRETURN or RT_SIGRETURN may affect the arm thumb mode, so update IS_THUMB. */ next_pc = arm_sigreturn_next_pc (regcache, svc_number, &is_thumb); } /* Addresses for calling Thumb functions have the bit 0 set. */ if (is_thumb) next_pc = MAKE_THUMB_ADDR (next_pc); return next_pc; }
/* Wrapper of arm_is_thumb_mode for get_next_pcs. */ static int get_next_pcs_is_thumb (struct arm_get_next_pcs *self) { return arm_is_thumb_mode (); }