?? signal.c
字號:
panic ("Double exception sys_sigreturn\n"); if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1 && __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))) goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); if (restore_sigcontext(regs, &frame->sc)) goto badframe; return regs->areg[2];badframe: force_sig(SIGSEGV, current); return 0;}asmlinkage int sys_rt_sigreturn(struct pt_regs *regs){ struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1]; sigset_t set; stack_t st; int ret; if (regs->depc > 64) { printk("!!!!!!! DEPC !!!!!!!\n"); return 0; } if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; ret = regs->areg[2]; if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ do_sigaltstack(&st, NULL, regs->areg[1]); return ret;badframe: force_sig(SIGSEGV, current); return 0;}/* * Set up a signal frame. *//* * Determine which stack to use.. */static inline void *get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size){ if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) sp = current->sas_ss_sp + current->sas_ss_size; return (void *)((sp - frame_size) & -16ul);}#define USE_SIGRETURN 0#define USE_RT_SIGRETURN 1static intgen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn){ unsigned int retcall; int err = 0;#if 0 /* Ignoring SA_RESTORER for now; it's supposed to be obsolete, * and the xtensa glibc doesn't use it. */ if (ka->sa.sa_flags & SA_RESTORER) { regs->pr = (unsigned long) ka->sa.sa_restorer; } else#endif /* 0 */ {#if (__NR_sigreturn > 255) || (__NR_rt_sigreturn > 255)/* The 12-bit immediate is really split up within the 24-bit MOVI * instruction. As long as the above system call numbers fit within * 8-bits, the following code works fine. See the Xtensa ISA for * details. */#error Generating the MOVI instruction below breaks!#endif retcall = use_rt_sigreturn ? __NR_rt_sigreturn : __NR_sigreturn;#ifdef __XTENSA_EB__ /* Big Endian version */ /* Generate instruction: MOVI a2, retcall */ err |= __put_user(0x22, &codemem[0]); err |= __put_user(0x0a, &codemem[1]); err |= __put_user(retcall, &codemem[2]); /* Generate instruction: SYSCALL */ err |= __put_user(0x00, &codemem[3]); err |= __put_user(0x05, &codemem[4]); err |= __put_user(0x00, &codemem[5]);#elif defined __XTENSA_EL__ /* Little Endian version */ /* Generate instruction: MOVI a2, retcall */ err |= __put_user(0x22, &codemem[0]); err |= __put_user(0xa0, &codemem[1]); err |= __put_user(retcall, &codemem[2]); /* Generate instruction: SYSCALL */ err |= __put_user(0x00, &codemem[3]); err |= __put_user(0x50, &codemem[4]); err |= __put_user(0x00, &codemem[5]);#else#error Must use compiler for Xtensa processors.#endif } /* Flush generated code out of the data cache */ if (err == 0) __flush_invalidate_cache_range((unsigned long)codemem, 6UL); return err;}static voidset_thread_state(struct pt_regs *regs, void *stack, unsigned char *retaddr, void *handler, unsigned long arg1, void *arg2, void *arg3){ /* Set up registers for signal handler */ start_thread(regs, (unsigned long) handler, (unsigned long) stack); /* Set up a stack frame for a call4 * Note: PS.CALLINC is set to one by start_thread */ regs->areg[4] = (((unsigned long) retaddr) & 0x3fffffff) | 0x40000000; regs->areg[6] = arg1; regs->areg[7] = (unsigned long) arg2; regs->areg[8] = (unsigned long) arg3;}static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs){ struct sigframe *frame; int err = 0; int signal; frame = get_sigframe(ka, regs->areg[1], sizeof(*frame)); if (regs->depc > 64) { printk("!!!!!!! DEPC !!!!!!!\n"); return; } if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; signal = current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap && sig < 32 ? current_thread_info()->exec_domain->signal_invmap[sig] : sig; err |= setup_sigcontext(&frame->sc, &frame->cpstate, regs, set->sig[0]); if (_NSIG_WORDS > 1) { err |= __copy_to_user(frame->extramask, &set->sig[1], sizeof(frame->extramask)); } /* Create sys_sigreturn syscall in stack frame */ err |= gen_return_code(frame->retcode, USE_SIGRETURN); if (err) goto give_sigsegv; /* Create signal handler execution context. * Return context not modified until this point. */ set_thread_state(regs, frame, frame->retcode, ka->sa.sa_handler, signal, &frame->sc, NULL); /* Set access mode to USER_DS. Nomenclature is outdated, but * functionality is used in uaccess.h */ set_fs(USER_DS);#if DEBUG_SIG printk("SIG deliver (%s:%d): signal=%d sp=%p pc=%08x\n", current->comm, current->pid, signal, frame, regs->pc);#endif return;give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current);}static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs){ struct rt_sigframe *frame; int err = 0; int signal; frame = get_sigframe(ka, regs->areg[1], sizeof(*frame)); if (regs->depc > 64) panic ("Double exception sys_sigreturn\n"); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; signal = current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap && sig < 32 ? current_thread_info()->exec_domain->signal_invmap[sig] : sig; err |= copy_siginfo_to_user(&frame->info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->areg[1]), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->cpstate, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* Create sys_rt_sigreturn syscall in stack frame */ err |= gen_return_code(frame->retcode, USE_RT_SIGRETURN); if (err) goto give_sigsegv; /* Create signal handler execution context. * Return context not modified until this point. */ set_thread_state(regs, frame, frame->retcode, ka->sa.sa_handler, signal, &frame->info, &frame->uc); /* Set access mode to USER_DS. Nomenclature is outdated, but * functionality is used in uaccess.h */ set_fs(USER_DS);#if DEBUG_SIG printk("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08x\n", current->comm, current->pid, signal, frame, regs->pc);#endif return;give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, 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. */int do_signal(struct pt_regs *regs, sigset_t *oldset){ siginfo_t info; int signr; struct k_sigaction ka; if (!oldset) oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* Are we from a system call? */ if (regs->syscall >= 0) { /* If so, check system call restarting.. */ switch (regs->areg[2]) { case ERESTARTNOHAND: case ERESTART_RESTARTBLOCK: regs->areg[2] = -EINTR; break; case ERESTARTSYS: if (!(ka.sa.sa_flags & SA_RESTART)) { regs->areg[2] = -EINTR; break; } /* fallthrough */ case ERESTARTNOINTR: regs->areg[2] = regs->syscall; regs->pc -= 3; } } if (signr == 0) return 0; /* no signals delivered */ /* Whee! Actually deliver the signal. */ /* Set up the stack frame */ if (ka.sa.sa_flags & SA_SIGINFO) setup_rt_frame(signr, &ka, &info, oldset, regs); else setup_frame(signr, &ka, oldset, regs); if (ka.sa.sa_flags & SA_ONESHOT) ka.sa.sa_handler = SIG_DFL; spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka.sa.sa_mask); if (!(ka.sa.sa_flags & SA_NODEFER)) sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); return 1;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -