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

📄 process.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */#include <stdlib.h>#include <unistd.h>#include <sched.h>#include <errno.h>#include <string.h>#include <sys/mman.h>#include <sys/ptrace.h>#include <sys/wait.h>#include <asm/unistd.h>#include "as-layout.h"#include "chan_user.h"#include "kern_constants.h"#include "mem.h"#include "os.h"#include "process.h"#include "proc_mm.h"#include "ptrace_user.h"#include "registers.h"#include "skas.h"#include "skas_ptrace.h"#include "user.h"#include "sysdep/stub.h"int is_skas_winch(int pid, int fd, void *data){	if (pid != getpgrp())		return 0;	register_winch_irq(-1, fd, -1, data, 0);	return 1;}static int ptrace_dump_regs(int pid){        unsigned long regs[MAX_REG_NR];        int i;        if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)                return -errno;	printk(UM_KERN_ERR "Stub registers -\n");	for (i = 0; i < ARRAY_SIZE(regs); i++)		printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]);        return 0;}/* * Signals that are OK to receive in the stub - we'll just continue it. * SIGWINCH will happen when UML is inside a detached screen. */#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH))/* Signals that the stub will finish with - anything else is an error */#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP))void wait_stub_done(int pid){	int n, status, err;	while (1) {		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));		if ((n < 0) || !WIFSTOPPED(status))			goto bad_wait;		if (((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0)			break;		err = ptrace(PTRACE_CONT, pid, 0, 0);		if (err)			panic("wait_stub_done : continue failed, errno = %d\n",			      errno);	}	if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)		return;bad_wait:	err = ptrace_dump_regs(pid);	if (err)		printk(UM_KERN_ERR "Failed to get registers from stub, "		       "errno = %d\n", -err);	panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, "	      "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status);}extern unsigned long current_stub_stack(void);void get_skas_faultinfo(int pid, struct faultinfo * fi){	int err;	if (ptrace_faultinfo) {		err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);		if (err)			panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "			      "errno = %d\n", errno);		/* Special handling for i386, which has different structs */		if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))			memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,			       sizeof(struct faultinfo) -			       sizeof(struct ptrace_faultinfo));	}	else {		err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);		if (err)			panic("Failed to continue stub, pid = %d, errno = %d\n",			      pid, errno);		wait_stub_done(pid);		/*		 * faultinfo is prepared by the stub-segv-handler at start of		 * the stub stack page. We just have to copy it.		 */		memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));	}}static void handle_segv(int pid, struct uml_pt_regs * regs){	get_skas_faultinfo(pid, &regs->faultinfo);	segv(regs->faultinfo, 0, 1, NULL);}/* * To use the same value of using_sysemu as the caller, ask it that value * (in local_using_sysemu */static void handle_trap(int pid, struct uml_pt_regs *regs,			int local_using_sysemu){	int err, status;	/* Mark this as a syscall */	UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp);	if (!local_using_sysemu)	{		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,			     __NR_getpid);		if (err < 0)			panic("handle_trap - nullifying syscall failed, "			      "errno = %d\n", errno);		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);		if (err < 0)			panic("handle_trap - continuing to end of syscall "			      "failed, errno = %d\n", errno);		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));		if ((err < 0) || !WIFSTOPPED(status) ||		   (WSTOPSIG(status) != SIGTRAP + 0x80)) {                        err = ptrace_dump_regs(pid);                        if (err)                                printk(UM_KERN_ERR "Failed to get registers "				       "from process, errno = %d\n", -err);			panic("handle_trap - failed to wait at end of syscall, "			      "errno = %d, status = %d\n", errno, status);                }	}	handle_syscall(regs);}extern int __syscall_stub_start;static int userspace_tramp(void *stack){	void *addr;	int err;	ptrace(PTRACE_TRACEME, 0, 0, 0);	signal(SIGTERM, SIG_DFL);	err = set_interval();	if (err)		panic("userspace_tramp - setting timer failed, errno = %d\n",		      err);	if (!proc_mm) {		/*		 * This has a pte, but it can't be mapped in with the usual		 * tlb_flush mechanism because this is part of that mechanism		 */		int fd;		unsigned long long offset;		fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);		addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE,			      PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);		if (addr == MAP_FAILED) {			printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, "			       "errno = %d\n", STUB_CODE, errno);			exit(1);		}		if (stack != NULL) {			fd = phys_mapping(to_phys(stack), &offset);			addr = mmap((void *) STUB_DATA,				    UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,				    MAP_FIXED | MAP_SHARED, fd, offset);			if (addr == MAP_FAILED) {				printk(UM_KERN_ERR "mapping segfault stack "				       "at 0x%lx failed, errno = %d\n",				       STUB_DATA, errno);				exit(1);			}		}	}	if (!ptrace_faultinfo && (stack != NULL)) {		struct sigaction sa;		unsigned long v = STUB_CODE +				  (unsigned long) stub_segv_handler -				  (unsigned long) &__syscall_stub_start;		set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);		sigemptyset(&sa.sa_mask);		sigaddset(&sa.sa_mask, SIGIO);		sigaddset(&sa.sa_mask, SIGWINCH);		sigaddset(&sa.sa_mask, SIGVTALRM);		sigaddset(&sa.sa_mask, SIGUSR1);		sa.sa_flags = SA_ONSTACK;		sa.sa_handler = (void *) v;		sa.sa_restorer = NULL;		if (sigaction(SIGSEGV, &sa, NULL) < 0)			panic("userspace_tramp - setting SIGSEGV handler "			      "failed - errno = %d\n", errno);	}	kill(os_getpid(), SIGSTOP);	return 0;}/* Each element set once, and only accessed by a single processor anyway */#undef NR_CPUS#define NR_CPUS 1int userspace_pid[NR_CPUS];int start_userspace(unsigned long stub_stack){	void *stack;	unsigned long sp;	int pid, status, n, flags;	stack = mmap(NULL, UM_KERN_PAGE_SIZE,		     PROT_READ | PROT_WRITE | PROT_EXEC,		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);	if (stack == MAP_FAILED)		panic("start_userspace : mmap failed, errno = %d", errno);	sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);	flags = CLONE_FILES;	if (proc_mm)		flags |= CLONE_VM;	else		flags |= SIGCHLD;	pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);	if (pid < 0)		panic("start_userspace : clone failed, errno = %d", errno);	do {		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));		if (n < 0)			panic("start_userspace : wait failed, errno = %d",			      errno);	} while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));	if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))		panic("start_userspace : expected SIGSTOP, got status = %d",		      status);	if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,		   (void *) PTRACE_O_TRACESYSGOOD) < 0)		panic("start_userspace : PTRACE_OLDSETOPTIONS failed, "		      "errno = %d\n", errno);	if (munmap(stack, UM_KERN_PAGE_SIZE) < 0)		panic("start_userspace : munmap failed, errno = %d\n", errno);	return pid;}void userspace(struct uml_pt_regs *regs){	struct itimerval timer;	unsigned long long nsecs, now;	int err, status, op, pid = userspace_pid[0];	/* To prevent races if using_sysemu changes under us.*/	int local_using_sysemu;	if (getitimer(ITIMER_VIRTUAL, &timer))		printk("Failed to get itimer, errno = %d\n", errno);	nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC +		timer.it_value.tv_usec * UM_NSEC_PER_USEC;	nsecs += os_nsecs();	while (1) {		restore_registers(pid, regs);		/* Now we set local_using_sysemu to be used for one loop */		local_using_sysemu = get_using_sysemu();		op = SELECT_PTRACE_OPERATION(local_using_sysemu,					     singlestepping(NULL));

⌨️ 快捷键说明

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