X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Farm-linux-tdep.c;h=e416e28fefa3a3e9361ce66d6feaa14a14986d94;hb=ed443b61e1f6e4eb7919fe9122dd947d1e87e767;hp=6050bdf9531de502f776f7374fd6e651244351c4;hpb=1b451dda5f8905b26bafafe00423335d4fffe8dd;p=binutils-gdb.git diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index 6050bdf9531..e416e28fefa 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -265,12 +265,17 @@ static const gdb_byte arm_linux_thumb2_le_breakpoint[] = { 0xf0, 0xf7, 0x00, 0xa /* Syscall number for rt_sigreturn. */ #define ARM_RT_SIGRETURN 173 +static CORE_ADDR + arm_linux_get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self, + CORE_ADDR pc); + /* Operation function pointers for get_next_pcs. */ static struct arm_get_next_pcs_ops arm_linux_get_next_pcs_ops = { arm_get_next_pcs_read_memory_unsigned_integer, - arm_get_next_pcs_syscall_next_pc, + arm_linux_get_next_pcs_syscall_next_pc, arm_get_next_pcs_addr_bits_remove, - arm_get_next_pcs_is_thumb + arm_get_next_pcs_is_thumb, + arm_linux_get_next_pcs_fixup, }; static void @@ -778,10 +783,12 @@ arm_linux_sigreturn_return_addr (struct frame_info *frame, } /* Find the value of the next PC after a sigreturn or rt_sigreturn syscall - based on current processor state. */ + based on current processor state. In addition, set IS_THUMB depending + on whether we will return to ARM or Thumb code. */ + static CORE_ADDR arm_linux_sigreturn_next_pc (struct regcache *regcache, - unsigned long svc_number) + unsigned long svc_number, int *is_thumb) { ULONGEST sp; unsigned long sp_data; @@ -790,6 +797,7 @@ arm_linux_sigreturn_next_pc (struct regcache *regcache, enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int pc_offset = 0; int is_sigreturn = 0; + CORE_ADDR cpsr; gdb_assert (svc_number == ARM_SIGRETURN || svc_number == ARM_RT_SIGRETURN); @@ -803,6 +811,10 @@ arm_linux_sigreturn_next_pc (struct regcache *regcache, next_pc = read_memory_unsigned_integer (sp + pc_offset, 4, byte_order); + /* Set IS_THUMB according the CPSR saved on the stack. */ + cpsr = read_memory_unsigned_integer (sp + pc_offset + 4, 4, byte_order); + *is_thumb = ((cpsr & arm_psr_thumb_bit (gdbarch)) != 0); + return next_pc; } @@ -859,26 +871,23 @@ arm_linux_get_syscall_number (struct gdbarch *gdbarch, return svc_number; } -/* When the processor is at a syscall instruction, return the PC of the - next instruction to be executed. */ - static CORE_ADDR -arm_linux_syscall_next_pc (struct regcache *regcache) +arm_linux_get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self, + CORE_ADDR pc) { - CORE_ADDR pc = regcache_read_pc (regcache); CORE_ADDR next_pc = 0; - int is_thumb = arm_is_thumb (regcache); + int is_thumb = arm_is_thumb (self->regcache); ULONGEST svc_number = 0; - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = get_regcache_arch (self->regcache); if (is_thumb) { - svc_number = regcache_raw_get_unsigned (regcache, 7); + svc_number = regcache_raw_get_unsigned (self->regcache, 7); next_pc = pc + 2; } else { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = get_regcache_arch (self->regcache); enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch); unsigned long this_instr = @@ -891,14 +900,19 @@ arm_linux_syscall_next_pc (struct regcache *regcache) } else /* EABI. */ { - svc_number = regcache_raw_get_unsigned (regcache, 7); + svc_number = regcache_raw_get_unsigned (self->regcache, 7); } next_pc = pc + 4; } if (svc_number == ARM_SIGRETURN || svc_number == ARM_RT_SIGRETURN) - next_pc = arm_linux_sigreturn_next_pc (regcache, svc_number); + { + /* SIGRETURN or RT_SIGRETURN may affect the arm thumb mode, so + update IS_THUMB. */ + next_pc = arm_linux_sigreturn_next_pc (self->regcache, svc_number, + &is_thumb); + } /* Addresses for calling Thumb functions have the bit 0 set. */ if (is_thumb) @@ -934,21 +948,10 @@ arm_linux_software_single_step (struct frame_info *frame) 1, regcache); - next_pcs = arm_get_next_pcs (&next_pcs_ctx, regcache_read_pc (regcache)); + next_pcs = arm_get_next_pcs (&next_pcs_ctx); for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++) - { - /* 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 (pc > 0xffff0000) - pc = get_frame_register_unsigned (frame, ARM_LR_REGNUM); - - arm_insert_single_step_breakpoint (gdbarch, aspace, pc); - } + arm_insert_single_step_breakpoint (gdbarch, aspace, pc); do_cleanups (old_chain); @@ -1115,8 +1118,7 @@ arm_catch_kernel_helper_return (struct gdbarch *gdbarch, CORE_ADDR from, /* Linux-specific displaced step instruction copying function. Detects when the program has stepped into a Linux kernel helper routine (which must be - handled as a special case), falling back to arm_displaced_step_copy_insn() - if it hasn't. */ + handled as a special case). */ static struct displaced_step_closure * arm_linux_displaced_step_copy_insn (struct gdbarch *gdbarch, @@ -1485,8 +1487,6 @@ arm_linux_init_abi (struct gdbarch_info info, set_gdbarch_stap_parse_special_token (gdbarch, arm_stap_parse_special_token); - tdep->syscall_next_pc = arm_linux_syscall_next_pc; - /* `catch syscall' */ set_xml_syscall_file_name (gdbarch, "syscalls/arm-linux.xml"); set_gdbarch_get_syscall_number (gdbarch, arm_linux_get_syscall_number);