📄 process.c
字号:
/* * Copy a thread.. */intcopy_thread(int nr, unsigned long clone_flags, unsigned long usp, unsigned long unused, struct task_struct *p, struct pt_regs *regs){ struct pt_regs *childregs, *kregs; extern void ret_from_fork(void); unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE; p->set_child_tid = p->clear_child_tid = NULL; /* Copy registers */ sp -= sizeof(struct pt_regs); childregs = (struct pt_regs *) sp; *childregs = *regs; if ((childregs->msr & MSR_PR) == 0) { /* for kernel thread, set stackptr in new task */ childregs->gpr[1] = sp + sizeof(struct pt_regs); p->thread.regs = NULL; /* no user register state */ clear_ti_thread_flag(p->thread_info, TIF_32BIT);#ifdef CONFIG_PPC_ISERIES set_ti_thread_flag(p->thread_info, TIF_RUN_LIGHT);#endif } else { childregs->gpr[1] = usp; p->thread.regs = childregs; if (clone_flags & CLONE_SETTLS) { if (test_thread_flag(TIF_32BIT)) childregs->gpr[2] = childregs->gpr[6]; else childregs->gpr[13] = childregs->gpr[6]; } } childregs->gpr[3] = 0; /* Result from fork() */ sp -= STACK_FRAME_OVERHEAD; /* * The way this works is that at some point in the future * some task will call _switch to switch to the new task. * That will pop off the stack frame created below and start * the new task running at ret_from_fork. The new task will * do some house keeping and then return from the fork or clone * system call, using the stack frame created above. */ sp -= sizeof(struct pt_regs); kregs = (struct pt_regs *) sp; sp -= STACK_FRAME_OVERHEAD; p->thread.ksp = sp; /* * The PPC64 ABI makes use of a TOC to contain function * pointers. The function (ret_from_except) is actually a pointer * to the TOC entry. The first entry is a pointer to the actual * function. */ kregs->nip = *((unsigned long *)ret_from_fork); return 0;}/* * Set up a thread for executing a new program */void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp){ unsigned long entry, toc, load_addr = regs->gpr[2]; /* fdptr is a relocated pointer to the function descriptor for * the elf _start routine. The first entry in the function * descriptor is the entry address of _start and the second * entry is the TOC value we need to use. */ set_fs(USER_DS); __get_user(entry, (unsigned long __user *)fdptr); __get_user(toc, (unsigned long __user *)fdptr+1); /* Check whether the e_entry function descriptor entries * need to be relocated before we can use them. */ if ( load_addr != 0 ) { entry += load_addr; toc += load_addr; } regs->nip = entry; regs->gpr[1] = sp; regs->gpr[2] = toc; regs->msr = MSR_USER64;#ifndef CONFIG_SMP if (last_task_used_math == current) last_task_used_math = 0;#endif /* CONFIG_SMP */ memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); current->thread.fpscr = 0;#ifdef CONFIG_ALTIVEC#ifndef CONFIG_SMP if (last_task_used_altivec == current) last_task_used_altivec = 0;#endif /* CONFIG_SMP */ memset(current->thread.vr, 0, sizeof(current->thread.vr)); current->thread.vscr.u[0] = 0; current->thread.vscr.u[1] = 0; current->thread.vscr.u[2] = 0; current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */ current->thread.vrsave = 0; current->thread.used_vr = 0;#endif /* CONFIG_ALTIVEC */}int set_fpexc_mode(struct task_struct *tsk, unsigned int val){ struct pt_regs *regs = tsk->thread.regs; if (val > PR_FP_EXC_PRECISE) return -EINVAL; tsk->thread.fpexc_mode = __pack_fe01(val); if (regs != NULL && (regs->msr & MSR_FP) != 0) regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1)) | tsk->thread.fpexc_mode; return 0;}int get_fpexc_mode(struct task_struct *tsk, unsigned long adr){ unsigned int val; val = __unpack_fe01(tsk->thread.fpexc_mode); return put_user(val, (unsigned int __user *) adr);}int sys_clone(unsigned long clone_flags, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs){ unsigned long parent_tidptr = 0; unsigned long child_tidptr = 0; if (p2 == 0) p2 = regs->gpr[1]; /* stack pointer for child */ if (clone_flags & (CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) { parent_tidptr = p3; child_tidptr = p5; if (test_thread_flag(TIF_32BIT)) { parent_tidptr &= 0xffffffff; child_tidptr &= 0xffffffff; } } return do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0, (int __user *)parent_tidptr, (int __user *)child_tidptr);}int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs){ return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);}int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs){ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);}int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs *regs){ int error; char * filename; filename = getname((char __user *) a0); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; flush_fp_to_thread(current); flush_altivec_to_thread(current); error = do_execve(filename, (char __user * __user *) a1, (char __user * __user *) a2, regs); if (error == 0) current->ptrace &= ~PT_DTRACE; putname(filename);out: return error;}static int kstack_depth_to_print = 64;static int validate_sp(unsigned long sp, struct task_struct *p, unsigned long nbytes){ unsigned long stack_page = (unsigned long)p->thread_info; if (sp >= stack_page + sizeof(struct thread_struct) && sp <= stack_page + THREAD_SIZE - nbytes) return 1;#ifdef CONFIG_IRQSTACKS stack_page = (unsigned long) hardirq_ctx[task_cpu(p)]; if (sp >= stack_page + sizeof(struct thread_struct) && sp <= stack_page + THREAD_SIZE - nbytes) return 1; stack_page = (unsigned long) softirq_ctx[task_cpu(p)]; if (sp >= stack_page + sizeof(struct thread_struct) && sp <= stack_page + THREAD_SIZE - nbytes) return 1;#endif return 0;}unsigned long get_wchan(struct task_struct *p){ unsigned long ip, sp; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; sp = p->thread.ksp; if (!validate_sp(sp, p, 112)) return 0; do { sp = *(unsigned long *)sp; if (!validate_sp(sp, p, 112)) return 0; if (count > 0) { ip = *(unsigned long *)(sp + 16); if (!in_sched_functions(ip)) return ip; } } while (count++ < 16); return 0;}void show_stack(struct task_struct *p, unsigned long *_sp){ unsigned long ip, newsp, lr; int count = 0; unsigned long sp = (unsigned long)_sp; int firstframe = 1; if (sp == 0) { if (p) { sp = p->thread.ksp; } else { sp = __get_SP(); p = current; } } lr = 0; printk("Call Trace:\n"); do { if (!validate_sp(sp, p, 112)) return; _sp = (unsigned long *) sp; newsp = _sp[0]; ip = _sp[2]; if (!firstframe || ip != lr) { printk("[%016lx] [%016lx] ", sp, ip); print_symbol("%s", ip); if (firstframe) printk(" (unreliable)"); printk("\n"); } firstframe = 0; /* * See if this is an exception frame. * We look for the "regshere" marker in the current frame. */ if (validate_sp(sp, p, sizeof(struct pt_regs) + 400) && _sp[12] == 0x7265677368657265ul) { struct pt_regs *regs = (struct pt_regs *) (sp + STACK_FRAME_OVERHEAD); printk("--- Exception: %lx", regs->trap); print_symbol(" at %s\n", regs->nip); lr = regs->link; print_symbol(" LR = %s\n", lr); firstframe = 1; } sp = newsp; } while (count++ < kstack_depth_to_print);}void dump_stack(void){ show_stack(current, (unsigned long *)__get_SP());}EXPORT_SYMBOL(dump_stack);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -