void show_regs(struct pt_regs *regs) { unsigned long flags; const char *processor_modes[] = { "USER_26", "FIQ_26", "IRQ_26", "SVC_26", "UK4_26", "UK5_26", "UK6_26", "UK7_26", "UK8_26", "UK9_26", "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", "USER_32", "FIQ_32", "IRQ_32", "SVC_32", "UK4_32", "UK5_32", "UK6_32", "ABT_32", "UK8_32", "UK9_32", "UK10_32", "UND_32", "UK12_32", "UK13_32", "UK14_32", "SYS_32", }; flags = condition_codes(regs); printf("pc : [<%08lx>] lr : [<%08lx>]\n" "sp : %08lx ip : %08lx fp : %08lx\n", instruction_pointer(regs), regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); printf("r10: %08lx r9 : %08lx r8 : %08lx\n", regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); printf("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); printf("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); printf("Flags: %c%c%c%c", flags & CC_N_BIT ? 'N' : 'n', flags & CC_Z_BIT ? 'Z' : 'z', flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); printf(" IRQs %s FIQs %s Mode %s%s\n", interrupts_enabled(regs) ? "on" : "off", fast_interrupts_enabled(regs) ? "on" : "off", processor_modes[processor_mode(regs)], thumb_mode(regs) ? " (T)" : ""); }
static inline void setup_syscall_restart(struct pt_regs *regs) { if (regs->ARM_ORIG_r0 == -ERESTARTNOHAND || regs->ARM_ORIG_r0 == -ERESTARTSYS || regs->ARM_ORIG_r0 == -ERESTARTNOINTR || regs->ARM_ORIG_r0 == -ERESTART_RESTARTBLOCK) { /* the syscall cannot be safely restarted, return -EINTR instead */ regs->ARM_r0 = -EINTR; return; } regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; }
static inline void setup_syscall_restart(struct pt_regs *regs) { if (regs->ARM_ORIG_r0 == -ERESTARTNOHAND || regs->ARM_ORIG_r0 == -ERESTARTSYS || regs->ARM_ORIG_r0 == -ERESTARTNOINTR || regs->ARM_ORIG_r0 == -ERESTART_RESTARTBLOCK) { regs->ARM_r0 = -EINTR; return; } regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static int do_signal(struct pt_regs *regs, int syscall) { unsigned int retval = 0, continue_addr = 0, restart_addr = 0; struct ksignal ksig; int restart = 0; /* * If we were from a system call, check for system call restarting... */ if (syscall) { continue_addr = regs->ARM_pc; restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4); retval = regs->ARM_r0; /* * Prepare for system call restart. We do this here so that a * debugger will see the already changed PSW. */ switch (retval) { case -ERESTART_RESTARTBLOCK: restart -= 2; case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: restart++; regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc = restart_addr; break; } } /* * Get the signal to deliver. When running under ptrace, at this * point the debugger may change all our registers ... */ /* * Depending on the signal settings we may need to revert the * decision to restart the system call. But skip this if a * debugger has chosen to restart at a different PC. */ if (get_signal(&ksig)) { /* handler */ if (unlikely(restart) && regs->ARM_pc == restart_addr) { if (retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS && !(ksig.ka.sa.sa_flags & SA_RESTART))) { regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } } handle_signal(&ksig, regs); } else { /* no handler */ restore_saved_sigmask(); if (unlikely(restart) && regs->ARM_pc == restart_addr) { regs->ARM_pc = continue_addr; return restart; } } return 0; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static void do_signal(struct pt_regs *regs, int syscall) { struct k_sigaction ka; siginfo_t info; int signr; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return; if (try_to_freeze()) goto no_signal; single_step_clear(current); signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { sigset_t *oldset; if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { /* * A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } single_step_set(current); return; } no_signal: /* * No signal to deliver to the process - restart the syscall. */ if (syscall) { if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { regs->ARM_r0 = -EAGAIN; /* prevent multiple restarts */ if (thumb_mode(regs)) { regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_pc -= 2; } else { #if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) regs->ARM_r7 = __NR_restart_syscall; regs->ARM_pc -= 4; #else u32 __user *usp; regs->ARM_sp -= 4; usp = (u32 __user *)regs->ARM_sp; if (put_user(regs->ARM_pc, usp) == 0) { regs->ARM_pc = KERN_RESTART_CODE; } else { regs->ARM_sp += 4; force_sigsegv(0, current); } #endif } } if (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR) { setup_syscall_restart(regs); } /* If there's no signal to deliver, we just put the saved sigmask * back. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } } single_step_set(current); }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) { siginfo_t info; int signr; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return 0; if (current->flags & PF_FREEZE) { refrigerator(0); goto no_signal; } if (current->ptrace & PT_SINGLESTEP) ptrace_cancel_bpt(current); signr = get_signal_to_deliver(&info, regs, NULL); if (signr > 0) { handle_signal(signr, &info, oldset, regs, syscall); if (current->ptrace & PT_SINGLESTEP) ptrace_set_bpt(current); return 1; } no_signal: /* * No signal to deliver to the process - restart the syscall. */ if (syscall) { if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { if (thumb_mode(regs)) { regs->ARM_r7 = __NR_restart_syscall; regs->ARM_pc -= 2; } else { u32 __user *usp; regs->ARM_sp -= 12; usp = (u32 __user *)regs->ARM_sp; put_user(regs->ARM_pc, &usp[0]); /* swi __NR_restart_syscall */ put_user(0xef000000 | __NR_restart_syscall, &usp[1]); /* ldr pc, [sp], #12 */ put_user(0xe49df00c, &usp[2]); flush_icache_range((unsigned long)usp, (unsigned long)(usp + 3)); regs->ARM_pc = regs->ARM_sp + 4; } } if (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR) { restart_syscall(regs); } } if (current->ptrace & PT_SINGLESTEP) ptrace_set_bpt(current); return 0; }
static inline void restart_syscall(struct pt_regs *regs) { regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static void do_signal(struct pt_regs *regs, int syscall) { struct k_sigaction ka; siginfo_t info; int signr; sigset_t *oldset; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return; if (try_to_freeze()) goto no_signal; single_step_clear(current); if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag */ clear_thread_flag(TIF_RESTORE_SIGMASK); } single_step_set(current); return; } no_signal: /* * No signal to deliver to the process - restart the syscall. */ if (syscall) { if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { if (thumb_mode(regs)) { regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_pc -= 2; } else { #if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) regs->ARM_r7 = __NR_restart_syscall; regs->ARM_pc -= 4; #else u32 __user *usp; u32 swival = __NR_restart_syscall; regs->ARM_sp -= 12; usp = (u32 __user *)regs->ARM_sp; /* * Either we support OABI only, or we have * EABI with the OABI compat layer enabled. * In the later case we don't know if user * space is EABI or not, and if not we must * not clobber r7. Always using the OABI * syscall solves that issue and works for * all those cases. */ swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE; put_user(regs->ARM_pc, &usp[0]); /* swi __NR_restart_syscall */ put_user(0xef000000 | swival, &usp[1]); /* ldr pc, [sp], #12 */ put_user(0xe49df00c, &usp[2]); flush_icache_range((unsigned long)usp, (unsigned long)(usp + 3)); regs->ARM_pc = regs->ARM_sp + 4; #endif } } if (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR) { setup_syscall_restart(regs); } } single_step_set(current); /* if there's no signal to deliver, we just put the saved sigmask back. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) { struct k_sigaction ka; siginfo_t info; int signr; #ifdef CONFIG_PREEMPT_RT /* * Fully-preemptible kernel does not need interrupts disabled: */ local_irq_enable(); preempt_check_resched(); #endif /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return 0; if (try_to_freeze()) goto no_signal; single_step_clear(current); signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { handle_signal(signr, &ka, &info, oldset, regs, syscall); single_step_set(current); return 1; } no_signal: /* * No signal to deliver to the process - restart the syscall. */ if (syscall) { if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { if (thumb_mode(regs)) { regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_pc -= 2; } else { #if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) regs->ARM_r7 = __NR_restart_syscall; regs->ARM_pc -= 4; #else u32 __user *usp; u32 swival = __NR_restart_syscall; regs->ARM_sp -= 12; usp = (u32 __user *)regs->ARM_sp; /* * Either we supports OABI only, or we have * EABI with the OABI compat layer enabled. * In the later case we don't know if user * space is EABI or not, and if not we must * not clobber r7. Always using the OABI * syscall solves that issue and works for * all those cases. */ swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE; put_user(regs->ARM_pc, &usp[0]); /* swi __NR_restart_syscall */ put_user(0xef000000 | swival, &usp[1]); /* ldr pc, [sp], #12 */ put_user(0xe49df00c, &usp[2]); flush_icache_range((unsigned long)usp, (unsigned long)(usp + 3)); regs->ARM_pc = regs->ARM_sp + 4; #endif } } if (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR) { restart_syscall(regs); } } single_step_set(current); return 0; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static void do_signal(struct pt_regs *regs, int syscall) { unsigned int retval = 0, continue_addr = 0, restart_addr = 0; struct k_sigaction ka; siginfo_t info; int signr; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return; /* * If we were from a system call, check for system call restarting... */ if (syscall) { continue_addr = regs->ARM_pc; restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4); retval = regs->ARM_r0; /* * Prepare for system call restart. We do this here so that a * debugger will see the already changed PSW. */ switch (retval) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc = restart_addr; break; case -ERESTART_RESTARTBLOCK: regs->ARM_r0 = -EINTR; break; } } if (try_to_freeze_nowarn()) goto no_signal; /* * Get the signal to deliver. When running under ptrace, at this * point the debugger may change all our registers ... */ signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { sigset_t *oldset; /* * Depending on the signal settings we may need to revert the * decision to restart the system call. But skip this if a * debugger has chosen to restart at a different PC. */ if (regs->ARM_pc == restart_addr) { if (retval == -ERESTARTNOHAND || (retval == -ERESTARTSYS && !(ka.sa.sa_flags & SA_RESTART))) { regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } } if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { /* * A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } return; } no_signal: if (syscall) { /* * Handle restarting a different system call. As above, * if a debugger has chosen to restart at a different PC, * ignore the restart. */ if (retval == -ERESTART_RESTARTBLOCK && regs->ARM_pc == continue_addr) { if (thumb_mode(regs)) { regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_pc -= 2; } else { #if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) regs->ARM_r7 = __NR_restart_syscall; regs->ARM_pc -= 4; #else u32 __user *usp; regs->ARM_sp -= 4; usp = (u32 __user *)regs->ARM_sp; if (put_user(regs->ARM_pc, usp) == 0) { regs->ARM_pc = KERN_RESTART_CODE; } else { regs->ARM_sp += 4; force_sigsegv(0, current); } #endif } } /* If there's no signal to deliver, we just put the saved sigmask * back. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } } }
static void do_signal(struct pt_regs *regs, int syscall) { struct k_sigaction ka; siginfo_t info; int signr; if (!user_mode(regs)) return; if (try_to_freeze()) goto no_signal; single_step_clear(current); signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { sigset_t *oldset; if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } single_step_set(current); return; } no_signal: if (syscall) { if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { regs->ARM_r0 = -EAGAIN; if (thumb_mode(regs)) { regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_pc -= 2; } else { #if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) regs->ARM_r7 = __NR_restart_syscall; regs->ARM_pc -= 4; #else u32 __user *usp; regs->ARM_sp -= 4; usp = (u32 __user *)regs->ARM_sp; if (put_user(regs->ARM_pc, usp) == 0) { regs->ARM_pc = KERN_RESTART_CODE; } else { regs->ARM_sp += 4; force_sigsegv(0, current); } #endif } } if (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR) { setup_syscall_restart(regs); } if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } } single_step_set(current); }
unsigned int quadd_get_user_callchain(struct pt_regs *regs, struct quadd_callchain *callchain_data) { unsigned long fp, sp, pc, reg; struct vm_area_struct *vma, *vma_pc; unsigned long __user *tail = NULL; struct mm_struct *mm = current->mm; callchain_data->nr = 0; if (!regs || !user_mode(regs) || !mm) return 0; if (thumb_mode(regs)) return 0; fp = regs->ARM_fp; sp = regs->ARM_sp; pc = regs->ARM_pc; if (fp == 0 || fp < sp || fp & 0x3) return 0; vma = find_vma(mm, sp); if (check_vma_address(fp, vma)) return 0; if (__copy_from_user_inatomic(®, (unsigned long __user *)fp, sizeof(unsigned long))) return 0; if (reg > fp && !check_vma_address(reg, vma)) { unsigned long value; int read_lr = 0; if (!check_vma_address(fp + sizeof(unsigned long), vma)) { if (__copy_from_user_inatomic( &value, (unsigned long __user *)fp + 1, sizeof(unsigned long))) return 0; vma_pc = find_vma(mm, pc); read_lr = 1; } if (!read_lr || check_vma_address(value, vma_pc)) { /* gcc: fp --> short frame tail (fp) */ if (regs->ARM_lr < QUADD_USER_SPACE_MIN_ADDR) return 0; quadd_callchain_store(callchain_data, regs->ARM_lr); tail = (unsigned long __user *)reg; } } if (!tail) tail = (unsigned long __user *)fp; while (tail && !((unsigned long)tail & 0x3)) tail = user_backtrace(tail, callchain_data, vma); return callchain_data->nr; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static int do_signal(struct pt_regs *regs, int syscall) { unsigned int retval = 0, continue_addr = 0, restart_addr = 0; struct k_sigaction ka; siginfo_t info; int signr; int restart = 0; /* * If we were from a system call, check for system call restarting... */ if (syscall) { continue_addr = regs->ARM_pc; restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4); retval = regs->ARM_r0; /* * Prepare for system call restart. We do this here so that a * debugger will see the already changed PSW. */ switch (retval) { case -ERESTART_RESTARTBLOCK: restart -= 2; case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: restart++; regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc = restart_addr; break; } } if (try_to_freeze_nowarn()) goto no_signal; /* * Get the signal to deliver. When running under ptrace, at this * point the debugger may change all our registers ... */ signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* * Depending on the signal settings we may need to revert the * decision to restart the system call. But skip this if a * debugger has chosen to restart at a different PC. */ if (regs->ARM_pc != restart_addr) restart = 0; if (signr > 0) { if (unlikely(restart)) { if (retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS && !(ka.sa.sa_flags & SA_RESTART))) { regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } } handle_signal(signr, &ka, &info, regs); return 0; } no_signal: restore_saved_sigmask(); if (unlikely(restart)) regs->ARM_pc = continue_addr; return restart; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static void do_signal(struct pt_regs *regs, int syscall) { unsigned int retval = 0, continue_addr = 0, restart_addr = 0; struct k_sigaction ka; siginfo_t info; int signr; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return; /* * If we were from a system call, check for system call restarting... */ if (syscall) { continue_addr = regs->ARM_pc; restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4); retval = regs->ARM_r0; /* * Prepare for system call restart. We do this here so that a * debugger will see the already changed PSW. */ switch (retval) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: case -ERESTART_RESTARTBLOCK: regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc = restart_addr; break; } } /* * Get the signal to deliver. When running under ptrace, at this * point the debugger may change all our registers ... */ signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { sigset_t *oldset; /* * Depending on the signal settings we may need to revert the * decision to restart the system call. But skip this if a * debugger has chosen to restart at a different PC. */ if (regs->ARM_pc == restart_addr) { if (retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS && !(ka.sa.sa_flags & SA_RESTART))) { regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } clear_thread_flag(TIF_SYSCALL_RESTARTSYS); } if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { /* * A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } return; } if (syscall) { /* * Handle restarting a different system call. As above, * if a debugger has chosen to restart at a different PC, * ignore the restart. */ if (retval == -ERESTART_RESTARTBLOCK && regs->ARM_pc == restart_addr) set_thread_flag(TIF_SYSCALL_RESTARTSYS); } /* If there's no signal to deliver, we just put the saved sigmask * back. */ if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) set_current_blocked(¤t->saved_sigmask); }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static void do_signal(struct pt_regs *regs, int syscall) { unsigned int retval = 0, continue_addr = 0, restart_addr = 0; struct k_sigaction ka; siginfo_t info; int signr; /* * If we were from a system call, check for system call restarting... */ if (syscall) { continue_addr = regs->ARM_pc; restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4); retval = regs->ARM_r0; /* * Prepare for system call restart. We do this here so that a * debugger will see the already changed PSW. */ switch (retval) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc = restart_addr; break; case -ERESTART_RESTARTBLOCK: regs->ARM_r0 = -EINTR; break; } } /* * Get the signal to deliver. When running under ptrace, at this * point the debugger may change all our registers ... */ signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* * Depending on the signal settings we may need to revert the * decision to restart the system call. But skip this if a * debugger has chosen to restart at a different PC. */ if (regs->ARM_pc == restart_addr) { if (retval == -ERESTARTNOHAND || (retval == -ERESTARTSYS && !(ka.sa.sa_flags & SA_RESTART))) { regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } } handle_signal(signr, &ka, &info, regs); return; } if (syscall) { /* * Handle restarting a different system call. As above, * if a debugger has chosen to restart at a different PC, * ignore the restart. */ if (retval == -ERESTART_RESTARTBLOCK && regs->ARM_pc == continue_addr) { if (thumb_mode(regs)) { regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_pc -= 2; } else { #if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) regs->ARM_r7 = __NR_restart_syscall; regs->ARM_pc -= 4; #else u32 __user *usp; regs->ARM_sp -= 4; usp = (u32 __user *)regs->ARM_sp; if (put_user(regs->ARM_pc, usp) == 0) { regs->ARM_pc = KERN_RESTART_CODE; } else { regs->ARM_sp += 4; force_sigsegv(0, current); } #endif } } } restore_saved_sigmask(); }