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; }
static CORE_ADDR arm_linux_push_arguments (int nargs, struct value **args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr) { char *fp; int argnum, argreg, nstack_size; /* Walk through the list of args and determine how large a temporary stack is required. Need to take care here as structs may be passed on the stack, and we have to to push them. */ nstack_size = -4 * REGISTER_SIZE; /* Some arguments go into A1-A4. */ if (struct_return) /* The struct address goes in A1. */ nstack_size += REGISTER_SIZE; /* Walk through the arguments and add their size to nstack_size. */ for (argnum = 0; argnum < nargs; argnum++) { int len; struct type *arg_type; arg_type = check_typedef (VALUE_TYPE (args[argnum])); len = TYPE_LENGTH (arg_type); /* ANSI C code passes float arguments as integers, K&R code passes float arguments as doubles. Correct for this here. */ if (TYPE_CODE_FLT == TYPE_CODE (arg_type) && REGISTER_SIZE == len) nstack_size += FP_REGISTER_VIRTUAL_SIZE; else nstack_size += len; } /* Allocate room on the stack, and initialize our stack frame pointer. */ fp = NULL; if (nstack_size > 0) { sp -= nstack_size; fp = (char *) sp; } /* Initialize the integer argument register pointer. */ argreg = ARM_A1_REGNUM; /* The struct_return pointer occupies the first parameter passing register. */ if (struct_return) write_register (argreg++, struct_addr); /* Process arguments from left to right. Store as many as allowed in the parameter passing registers (A1-A4), and save the rest on the temporary stack. */ for (argnum = 0; argnum < nargs; argnum++) { int len; char *val; CORE_ADDR regval; enum type_code typecode; struct type *arg_type, *target_type; arg_type = check_typedef (VALUE_TYPE (args[argnum])); target_type = TYPE_TARGET_TYPE (arg_type); len = TYPE_LENGTH (arg_type); typecode = TYPE_CODE (arg_type); val = (char *) VALUE_CONTENTS (args[argnum]); /* ANSI C code passes float arguments as integers, K&R code passes float arguments as doubles. The .stabs record for for ANSI prototype floating point arguments records the type as FP_INTEGER, while a K&R style (no prototype) .stabs records the type as FP_FLOAT. In this latter case the compiler converts the float arguments to double before calling the function. */ if (TYPE_CODE_FLT == typecode && REGISTER_SIZE == len) { DOUBLEST dblval; dblval = extract_floating (val, len); len = TARGET_DOUBLE_BIT / TARGET_CHAR_BIT; val = alloca (len); store_floating (val, len, dblval); } /* If the argument is a pointer to a function, and it is a Thumb function, set the low bit of the pointer. */ if (TYPE_CODE_PTR == typecode && NULL != target_type && TYPE_CODE_FUNC == TYPE_CODE (target_type)) { CORE_ADDR regval = extract_address (val, len); if (arm_pc_is_thumb (regval)) store_address (val, len, MAKE_THUMB_ADDR (regval)); } /* Copy the argument to general registers or the stack in register-sized pieces. Large arguments are split between registers and stack. */ while (len > 0) { int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE; if (argreg <= ARM_LAST_ARG_REGNUM) { /* It's an argument being passed in a general register. */ regval = extract_address (val, partial_len); write_register (argreg++, regval); } else { /* Push the arguments onto the stack. */ write_memory ((CORE_ADDR) fp, val, REGISTER_SIZE); fp += REGISTER_SIZE; } len -= partial_len; val += partial_len; } } /* Return adjusted stack pointer. */ return sp; }
CORE_ADDR arm_linux_get_next_pcs_fixup (struct arm_get_next_pcs *self, CORE_ADDR nextpc) { /* 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 (tail) called as functions and return to the address in LR. However, when GDB single step this instruction, this instruction isn't executed yet, and LR may not be updated yet. In other words, GDB can get the target address from LR if this instruction isn't BL or BLX. */ if (nextpc > 0xffff0000) { int bl_blx_p = 0; CORE_ADDR pc = regcache_read_pc (self->regcache); int pc_incr = 0; if (self->ops->is_thumb (self)) { unsigned short inst1 = self->ops->read_mem_uint (pc, 2, self->byte_order_for_code); if (bits (inst1, 8, 15) == 0x47 && bit (inst1, 7)) { /* BLX Rm */ bl_blx_p = 1; pc_incr = 2; } else if (thumb_insn_size (inst1) == 4) { unsigned short inst2; inst2 = self->ops->read_mem_uint (pc + 2, 2, self->byte_order_for_code); if ((inst1 & 0xf800) == 0xf000 && bits (inst2, 14, 15) == 0x3) { /* BL <label> and BLX <label> */ bl_blx_p = 1; pc_incr = 4; } } pc_incr = MAKE_THUMB_ADDR (pc_incr); } else { unsigned int insn = self->ops->read_mem_uint (pc, 4, self->byte_order_for_code); if (bits (insn, 28, 31) == INST_NV) { if (bits (insn, 25, 27) == 0x5) /* BLX <label> */ bl_blx_p = 1; } else { if (bits (insn, 24, 27) == 0xb /* BL <label> */ || bits (insn, 4, 27) == 0x12fff3 /* BLX Rm */) bl_blx_p = 1; } pc_incr = 4; } /* If the instruction BL or BLX, the target address is the following instruction of BL or BLX, otherwise, the target address is in LR already. */ if (bl_blx_p) nextpc = pc + pc_incr; else nextpc = regcache_raw_get_unsigned (self->regcache, ARM_LR_REGNUM); } return nextpc; }