⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signal.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
setup_frame(int sig, struct k_sigaction *ka,  sigset_t *set,	    struct pt_regs * regs){	int err;	unsigned long return_ip;	struct signal_frame __user *frame;	err = 0;	frame = get_sigframe(ka, regs, sizeof(*frame));	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))		goto give_sigsegv;	err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);	if (err)		goto give_sigsegv;	if (_NSIG_WORDS > 1) {		err |= __copy_to_user(frame->extramask, &set->sig[1],				      sizeof(frame->extramask));	}	if (err)		goto give_sigsegv;	/*	 * Set up to return from user-space. If provided, use a stub	 * already located in user-space.	 */	if (ka->sa.sa_flags & SA_RESTORER) {		return_ip = (unsigned long)ka->sa.sa_restorer;	} else {		/* Trampoline - the desired return ip is in the signal return page. */		return_ip = cris_signal_return_page;		/*		 * This is movu.w __NR_sigreturn, r9; break 13;		 *		 * WE DO NOT USE IT ANY MORE! It's only left here for historical		 * reasons and because gdb uses it as a signature to notice		 * signal handler stack frames.		 */		err |= __put_user(0x9c5f,         (short __user*)(frame->retcode+0));		err |= __put_user(__NR_sigreturn, (short __user*)(frame->retcode+2));		err |= __put_user(0xe93d,         (short __user*)(frame->retcode+4));	}	if (err)		goto give_sigsegv;	/*	 * Set up registers for signal handler.	 *	 * Where the code enters now.	 * Where the code enter later.	 * First argument, signo.	 */	regs->erp = (unsigned long) ka->sa.sa_handler;	regs->srp = return_ip;	regs->r10 = sig;	/* Actually move the USP to reflect the stacked frame. */	wrusp((unsigned long)frame);	return;give_sigsegv:	if (sig == SIGSEGV)		ka->sa.sa_handler = SIG_DFL;	force_sig(SIGSEGV, current);}static voidsetup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,	       sigset_t *set, struct pt_regs * regs){	int err;	unsigned long return_ip;	struct rt_signal_frame __user *frame;	err = 0;	frame = get_sigframe(ka, regs, sizeof(*frame));	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))		goto give_sigsegv;	/* TODO: what is the current->exec_domain stuff and invmap ? */	err |= __put_user(&frame->info, &frame->pinfo);	err |= __put_user(&frame->uc, &frame->puc);	err |= copy_siginfo_to_user(&frame->info, info);	if (err)		goto give_sigsegv;	/* Clear all the bits of the ucontext we don't use.  */	err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));	if (err)		goto give_sigsegv;	/*	 * Set up to return from user-space. If provided, use a stub	 * already located in user-space.	 */	if (ka->sa.sa_flags & SA_RESTORER) {		return_ip = (unsigned long) ka->sa.sa_restorer;	} else {		/* Trampoline - the desired return ip is in the signal return page. */		return_ip = cris_signal_return_page + 6;		/*		 * This is movu.w __NR_rt_sigreturn, r9; break 13;		 *		 * WE DO NOT USE IT ANY MORE! It's only left here for historical		 * reasons and because gdb uses it as a signature to notice		 * signal handler stack frames.		 */		err |= __put_user(0x9c5f, (short __user*)(frame->retcode+0));		err |= __put_user(__NR_rt_sigreturn,				  (short __user*)(frame->retcode+2));		err |= __put_user(0xe93d, (short __user*)(frame->retcode+4));	}	if (err)		goto give_sigsegv;	/*	 * Set up registers for signal handler.	 *	 * Where the code enters now.	 * Where the code enters later.	 * First argument is signo.	 * Second argument is (siginfo_t *).	 * Third argument is unused.	 */	regs->erp = (unsigned long) ka->sa.sa_handler;	regs->srp = return_ip;	regs->r10 = sig;	regs->r11 = (unsigned long) &frame->info;	regs->r12 = 0;	/* Actually move the usp to reflect the stacked frame. */	wrusp((unsigned long)frame);	return;give_sigsegv:	if (sig == SIGSEGV)		ka->sa.sa_handler = SIG_DFL;	force_sig(SIGSEGV, current);}/* Invoke a singal handler to, well, handle the signal. */static inline voidhandle_signal(int canrestart, unsigned long sig,	      siginfo_t *info, struct k_sigaction *ka,              sigset_t *oldset, struct pt_regs * regs){	/* Check if this got called from a system call. */	if (canrestart) {		/* If so, check system call restarting. */		switch (regs->r10) {			case -ERESTART_RESTARTBLOCK:			case -ERESTARTNOHAND:				/*				 * This means that the syscall should				 * only be restarted if there was no				 * handler for the signal, and since				 * this point isn't reached unless				 * there is a handler, there's no need				 * to restart.				 */				regs->r10 = -EINTR;				break;                        case -ERESTARTSYS:				/*				 * This means restart the syscall if                                 * there is no handler, or the handler                                 * was registered with SA_RESTART.				 */				if (!(ka->sa.sa_flags & SA_RESTART)) {					regs->r10 = -EINTR;					break;				}				/* Fall through. */			case -ERESTARTNOINTR:				/*				 * This means that the syscall should                                 * be called again after the signal                                 * handler returns.				 */				RESTART_CRIS_SYS(regs);				break;                }        }	/* Set up the stack frame. */	if (ka->sa.sa_flags & SA_SIGINFO)		setup_rt_frame(sig, ka, info, oldset, regs);	else		setup_frame(sig, ka, oldset, regs);	if (ka->sa.sa_flags & SA_ONESHOT)		ka->sa.sa_handler = SIG_DFL;	spin_lock_irq(&current->sighand->siglock);	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);	if (!(ka->sa.sa_flags & SA_NODEFER))		sigaddset(&current->blocked,sig);	recalc_sigpending();	spin_unlock_irq(&current->sighand->siglock);}/* * 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. * * Also note that the regs structure given here as an argument, is the latest * pushed pt_regs. It may or may not be the same as the first pushed registers * when the initial usermode->kernelmode transition took place. Therefore * we can use user_mode(regs) to see if we came directly from kernel or user * mode below. */intdo_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs){	int signr;	siginfo_t info;        struct k_sigaction ka;	/*	 * The common case should go fast, which is why this point is	 * reached from kernel-mode. If that's the case, just return	 * without doing anything.	 */	if (!user_mode(regs))		return 1;	if (!oldset)		oldset = &current->blocked;	signr = get_signal_to_deliver(&info, &ka, regs, NULL);	if (signr > 0) {		/* Deliver the signal. */		handle_signal(canrestart, signr, &info, &ka, oldset, regs);		return 1;	}	/* Got here from a system call? */	if (canrestart) {		/* Restart the system call - no handlers present. */		if (regs->r10 == -ERESTARTNOHAND ||		    regs->r10 == -ERESTARTSYS ||		    regs->r10 == -ERESTARTNOINTR) {			RESTART_CRIS_SYS(regs);		}		if (regs->r10 == -ERESTART_RESTARTBLOCK){			regs->r10 = __NR_restart_syscall;			regs->erp -= 2;		}	}	return 0;}asmlinkage voidugdb_trap_user(struct thread_info *ti, int sig){	if (((user_regs(ti)->exs & 0xff00) >> 8) != SINGLE_STEP_INTR_VECT) {		/* Zero single-step PC if the reason we stopped wasn't a single		   step exception. This is to avoid relying on it when it isn't		   reliable. */		user_regs(ti)->spc = 0;	}	/* FIXME: Filter out false h/w breakpoint hits (i.e. EDA	   not within any configured h/w breakpoint range). Synchronize with	   what already exists for kernel debugging.  */	if (((user_regs(ti)->exs & 0xff00) >> 8) == BREAK_8_INTR_VECT) {		/* Break 8: subtract 2 from ERP unless in a delay slot. */		if (!(user_regs(ti)->erp & 0x1))			user_regs(ti)->erp -= 2;	}	sys_kill(ti->task->pid, sig);}voidkeep_debug_flags(unsigned long oldccs, unsigned long oldspc,		 struct pt_regs *regs){	if (oldccs & (1 << Q_CCS_BITNR)) {		/* Pending single step due to single-stepping the break 13		   in the signal trampoline: keep the Q flag. */		regs->ccs |= (1 << Q_CCS_BITNR);		/* S flag should be set - complain if it's not. */		if (!(oldccs & (1 << (S_CCS_BITNR + CCS_SHIFT)))) {			printk("Q flag but no S flag?");		}		regs->ccs |= (1 << (S_CCS_BITNR + CCS_SHIFT));		/* Assume the SPC is valid and interesting. */		regs->spc = oldspc;	} else if (oldccs & (1 << (S_CCS_BITNR + CCS_SHIFT))) {		/* If a h/w bp was set in the signal handler we need		   to keep the S flag. */		regs->ccs |= (1 << (S_CCS_BITNR + CCS_SHIFT));		/* Don't keep the old SPC though; if we got here due to		   a single-step, the Q flag should have been set. */	} else if (regs->spc) {		/* If we were single-stepping *before* the signal was taken,		   we don't want to restore that state now, because GDB will		   have forgotten all about it. */		regs->spc = 0;		regs->ccs &= ~(1 << (S_CCS_BITNR + CCS_SHIFT));	}}/* Set up the trampolines on the signal return page. */int __initcris_init_signal(void){	u16* data = kmalloc(PAGE_SIZE, GFP_KERNEL);	/* This is movu.w __NR_sigreturn, r9; break 13; */	data[0] = 0x9c5f;	data[1] = __NR_sigreturn;	data[2] = 0xe93d;	/* This is movu.w __NR_rt_sigreturn, r9; break 13; */	data[3] = 0x9c5f;	data[4] = __NR_rt_sigreturn;	data[5] = 0xe93d;	/* Map to userspace with appropriate permissions (no write access...) */	cris_signal_return_page = (unsigned long)          __ioremap_prot(virt_to_phys(data), PAGE_SIZE, PAGE_SIGNAL_TRAMPOLINE);	return 0;}__initcall(cris_init_signal);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -