📄 process.c
字号:
/* * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation * Linux for s390 port by D.J. Barrow * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com> * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: process.c,v 1.28 2001/03/28 20:29:17 wichert Exp $ */#include "defs.h"#include <fcntl.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/wait.h>#include <sys/resource.h>#include <sys/utsname.h>#include <sys/user.h>#include <sys/syscall.h>#include <signal.h>#ifdef SUNOS4#include <machine/reg.h>#endif /* SUNOS4 */#ifdef FREEBSD#include <sys/ptrace.h>#endif#if HAVE_ASM_REG_H#ifdef SPARC# define fpq kernel_fpq# define fq kernel_fq# define fpu kernel_fpu#endif#include <asm/reg.h>#ifdef SPARC# undef fpq# undef fq# undef fpu #endif#endif /* HAVE_ASM_REG_H */#ifdef HAVE_SYS_REG_H# include <sys/reg.h>#ifndef PTRACE_PEEKUSR# define PTRACE_PEEKUSR PTRACE_PEEKUSER#endif#ifndef PTRACE_POKEUSR# define PTRACE_POKEUSR PTRACE_POKEUSER#endif#elif defined(HAVE_LINUX_PTRACE_H)#undef PTRACE_SYSCALL#include <linux/ptrace.h>#endif#ifdef LINUX#include <asm/posix_types.h>#undef GETGROUPS_T#define GETGROUPS_T __kernel_gid_t#endif /* LINUX */#if defined(LINUX) && defined(IA64)# include <asm/ptrace_offsets.h># include <asm/rse.h>#endif#ifdef HAVE_PRCTL#include <sys/prctl.h>#endif#ifndef WCOREDUMP#define WCOREDUMP(status) ((status) & 0200)#endif/* WTA: this was `&& !defined(LINUXSPARC)', this seems unneeded though? */#if defined(HAVE_PRCTL)static struct xlat prctl_options[] = {#ifdef PR_MAXPROCS { PR_MAXPROCS, "PR_MAXPROCS" },#endif#ifdef PR_ISBLOCKED { PR_ISBLOCKED, "PR_ISBLOCKED" },#endif#ifdef PR_SETSTACKSIZE { PR_SETSTACKSIZE, "PR_SETSTACKSIZE" },#endif#ifdef PR_GETSTACKSIZE { PR_GETSTACKSIZE, "PR_GETSTACKSIZE" },#endif#ifdef PR_MAXPPROCS { PR_MAXPPROCS, "PR_MAXPPROCS" },#endif#ifdef PR_UNBLKONEXEC { PR_UNBLKONEXEC, "PR_UNBLKONEXEC" },#endif#ifdef PR_ATOMICSIM { PR_ATOMICSIM, "PR_ATOMICSIM" },#endif#ifdef PR_SETEXITSIG { PR_SETEXITSIG, "PR_SETEXITSIG" },#endif#ifdef PR_RESIDENT { PR_RESIDENT, "PR_RESIDENT" },#endif#ifdef PR_ATTACHADDR { PR_ATTACHADDR, "PR_ATTACHADDR" },#endif#ifdef PR_DETACHADDR { PR_DETACHADDR, "PR_DETACHADDR" },#endif#ifdef PR_TERMCHILD { PR_TERMCHILD, "PR_TERMCHILD" },#endif#ifdef PR_GETSHMASK { PR_GETSHMASK, "PR_GETSHMASK" },#endif#ifdef PR_GETNSHARE { PR_GETNSHARE, "PR_GETNSHARE" },#endif#if defined(PR_SET_PDEATHSIG) { PR_SET_PDEATHSIG, "PR_SET_PDEATHSIG" },#endif#ifdef PR_COREPID { PR_COREPID, "PR_COREPID" },#endif#ifdef PR_ATTACHADDRPERM { PR_ATTACHADDRPERM, "PR_ATTACHADDRPERM" },#endif#ifdef PR_PTHREADEXIT { PR_PTHREADEXIT, "PR_PTHREADEXIT" },#endif#ifdef PR_SET_PDEATHSIG { PR_SET_PDEATHSIG, "PR_SET_PDEATHSIG" },#endif#ifdef PR_GET_PDEATHSIG { PR_GET_PDEATHSIG, "PR_GET_PDEATHSIG" },#endif#ifdef PR_GET_UNALIGN { PR_GET_UNALIGN, "PR_GET_UNALIGN" },#endif#ifdef PR_SET_UNALIGN { PR_SET_UNALIGN, "PR_SET_UNALIGN" },#endif#ifdef PR_GET_KEEPCAPS { PR_GET_KEEPCAPS, "PR_GET_KEEP_CAPS" },#endif#ifdef PR_SET_KEEPCAPS { PR_SET_KEEPCAPS, "PR_SET_KEEP_CAPS" },#endif { 0, NULL },};const char *unalignctl_string (unsigned int ctl){ static char buf[16]; switch (ctl) {#ifdef PR_UNALIGN_NOPRINT case PR_UNALIGN_NOPRINT: return "NOPRINT";#endif#ifdef PR_UNALIGN_SIGBUS case PR_UNALIGN_SIGBUS: return "SIGBUS";#endif default: break; } sprintf(buf, "%x", ctl); return buf;}intsys_prctl(tcp)struct tcb *tcp;{ int i; if (entering(tcp)) { printxval(prctl_options, tcp->u_arg[0], "PR_???"); switch (tcp->u_arg[0]) {#ifdef PR_GETNSHARE case PR_GETNSHARE: break;#endif#ifdef PR_SET_DEATHSIG case PR_GET_PDEATHSIG: break;#endif#ifdef PR_SET_UNALIGN case PR_SET_UNALIGN: tprintf(", %s", unalignctl_string(tcp->u_arg[1])); break;#endif#ifdef PR_GET_UNALIGN case PR_GET_UNALIGN: tprintf(", %#lx", tcp->u_arg[1]); break;#endif default: for (i = 1; i < tcp->u_nargs; i++) tprintf(", %#lx", tcp->u_arg[i]); break; } } else { switch (tcp->u_arg[0]) {#ifdef PR_GET_PDEATHSIG case PR_GET_PDEATHSIG: for (i=1; i<tcp->u_nargs; i++) tprintf(", %#lx", tcp->u_arg[i]); break;#endif#ifdef PR_SET_UNALIGN case PR_SET_UNALIGN: break;#endif#ifdef PR_GET_UNALIGN case PR_GET_UNALIGN: { int ctl; umove(tcp, tcp->u_arg[1], &ctl); tcp->auxstr = unalignctl_string(ctl); return RVAL_STR; }#endif default: break; } } return 0;}#endif /* HAVE_PRCTL */intsys_gethostid(tcp)struct tcb *tcp;{ if (exiting(tcp)) return RVAL_HEX; return 0;}intsys_sethostname(tcp)struct tcb *tcp;{ if (entering(tcp)) { printpathn(tcp, tcp->u_arg[0], tcp->u_arg[1]); tprintf(", %lu", tcp->u_arg[1]); } return 0;}intsys_gethostname(tcp)struct tcb *tcp;{ if (exiting(tcp)) { if (syserror(tcp)) tprintf("%#lx", tcp->u_arg[0]); else printpath(tcp, tcp->u_arg[0]); tprintf(", %lu", tcp->u_arg[1]); } return 0;}intsys_setdomainname(tcp)struct tcb *tcp;{ if (entering(tcp)) { printpathn(tcp, tcp->u_arg[0], tcp->u_arg[1]); tprintf(", %lu", tcp->u_arg[1]); } return 0;}#if !defined(LINUX)intsys_getdomainname(tcp)struct tcb *tcp;{ if (exiting(tcp)) { if (syserror(tcp)) tprintf("%#lx", tcp->u_arg[0]); else printpath(tcp, tcp->u_arg[0]); tprintf(", %lu", tcp->u_arg[1]); } return 0;}#endif /* !LINUX */intsys_exit(tcp)struct tcb *tcp;{ if (exiting(tcp)) { fprintf(stderr, "_exit returned!\n"); return -1; } /* special case: we stop tracing this process, finish line now */ tprintf("%ld) ", tcp->u_arg[0]); tabto(acolumn); tprintf("= ?"); printtrailer(tcp); return 0;}intinternal_exit(tcp)struct tcb *tcp;{ if (entering(tcp)) tcp->flags |= TCB_EXITING; return 0;}#ifdef USE_PROCFSintsys_fork(tcp)struct tcb *tcp;{ if (exiting(tcp)) { if (getrval2(tcp)) { tcp->auxstr = "child process"; return RVAL_UDECIMAL | RVAL_STR; } } return 0;}intinternal_fork(tcp)struct tcb *tcp;{ struct tcb *tcpchild; if (exiting(tcp)) { if (getrval2(tcp)) return 0; if (!followfork) return 0; if (nprocs == MAX_PROCS) { tcp->flags &= ~TCB_FOLLOWFORK; fprintf(stderr, "sys_fork: tcb table full\n"); return 0; } else tcp->flags |= TCB_FOLLOWFORK; if (syserror(tcp)) return 0; if ((tcpchild = alloctcb(tcp->u_rval)) == NULL) { fprintf(stderr, "sys_fork: tcb table full\n"); return 0; } if (proc_open(tcpchild, 2) < 0) droptcb(tcpchild); } return 0;}#else /* !USE_PROCFS */#ifdef LINUX/* defines copied from linux/sched.h since we can't include that * ourselves (it conflicts with *lots* of libc includes) */#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */#define CLONE_VM 0x00000100 /* set if VM shared between processes */#define CLONE_FS 0x00000200 /* set if fs info shared between processes */#define CLONE_FILES 0x00000400 /* set if open files shared between processes */#define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */#define CLONE_PID 0x00001000 /* set if pid shared */#define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */#define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */static struct xlat clone_flags[] = { { CLONE_VM, "CLONE_VM" }, { CLONE_FS, "CLONE_FS" }, { CLONE_FILES, "CLONE_FILES" }, { CLONE_SIGHAND, "CLONE_SIGHAND" }, { CLONE_PID, "CLONE_PID" }, { CLONE_PTRACE, "CLONE_PTRACE" }, { CLONE_VFORK, "CLONE_VFORK" }, { CLONE_PARENT, "CLONE_PARENT" }, { 0, NULL },};intsys_clone(tcp)struct tcb *tcp;{ if (exiting(tcp)) { tprintf("child_stack=%#lx, flags=", tcp->u_arg[1]); if (printflags(clone_flags, tcp->u_arg[0]) == 0) tprintf("0"); } return 0;}#endifintsys_fork(tcp)struct tcb *tcp;{ if (exiting(tcp)) return RVAL_UDECIMAL; return 0;}intchange_syscall(tcp, new)struct tcb *tcp;int new;{#if defined(LINUX)#if defined(I386) /* Attempt to make vfork into fork, which we can follow. */ if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0) return -1; return 0;#elif defined(POWERPC) if (ptrace(PTRACE_POKEUSER, tcp->pid, (CHAR*)(4*PT_R0), new) < 0) return -1;#elif defined(S390) long pc; if (upeek(tcp->pid, PT_PSWADDR,&pc)<0) return -1; if (ptrace(PTRACE_POKETEXT, tcp->pid, (char*)(pc-4), new)<0) return -1; return 0;#elif defined(M68K) if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new)<0) return -1; return 0;#elif defined(SPARC) struct regs regs; if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)®s, 0)<0) return -1; regs.r_g1=new; if (ptrace(PTRACE_SETREGS, tcp->pid, (char*)®s, 0)<0) return -1; return 0;#elif defined(MIPS) if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new)<0) return -1; return 0;#elif defined(ALPHA) if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new)<0) return -1; return 0;#elif defined(HPPA) if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new)<0) return -1; return 0;#else#warning Do not know how to handle change_syscall for this architecture#endif /* architecture */#endif /* LINUX */ return -1;}intsetarg(tcp, argnum) struct tcb *tcp; int argnum;{#if defined (IA64) { unsigned long *bsp, *ap; if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) , 0) return -1; ap = ia64_rse_skip_regs(bsp, argnum); errno = 0; ptrace(PTRACE_POKEDATA, tcp->pid, ap, tcp->u_arg[argnum]); if (errno) return -1; }#elif defined(I386) { ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*argnum), tcp->u_arg[argnum]); if (errno) return -1; }#elif defined(MIPS) { errno = 0; if (argnum < 4) ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A0 + argnum), tcp->u_arg[argnum]); else { unsigned long *sp; if (upeek(tcp->pid, REG_SP, (long *) &sp) , 0) return -1; ptrace(PTRACE_POKEDATA, tcp->pid, (char*)(sp + argnum - 4), tcp->u_arg[argnum]); } if (errno) return -1; }#else# warning Sorry, setargs not implemented for this architecture.#endif return 0;}#ifdef SYS_cloneintinternal_clone(tcp)struct tcb *tcp;{ struct tcb *tcpchild; int pid; if (entering(tcp)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -