Beispiel #1
0
FUNCTION VOID BRIDGE2_NAME(xrattr)
(
    TAEINT		*block,		/* in: parameter block		*/
    FORSTR		*name,		/* in: parameter name		*/
    TAEINT		*type,		/* out: parameter type		*/
    TAEINT		*n,		/* out: number of components	*/
    TAELOG		*defalt,	/* out: .TRUE. if defaulted	*/
    TAEINT		*access,	/* out: access mode if a file	*/
    TAEINT		*status	/* out: status code		*/

)
{
    struct PARBLK *parblk;
    struct VARIABLE *v;
    CODE	code;
    TEXT	c_name[STRINGSIZ+1];	/* name in C string format	*/

    parblk = (struct PARBLK *) block;
    code = s_for2c(name, c_name, 0);		/* convert name to C string	*/
    if (code != SUCCESS) goto p__bnerr;
    s_strip(c_name);			/* remove trailing blanks	*/

    v = p_find(parblk,c_name);
    if (v == NULL) goto p__bnerr;
    *defalt = (*v).v_default;		/* default in var is already TRUE/FALSE */
    *n = (*v).v_count;
    *type = (*v).v_file ? P_FILE : (*v).v_type;       /* file or other types  */
    *access = (*v).v_file ? (*v).v_filemode : P_NONE;  /* none if not file */
    *status = SUCCESS;
    return;

p__bnerr:
    *status = P_BADNAME;
    return;
}
Beispiel #2
0
FUNCTION VOID BRIDGE2_NAME(xrstr)
(
    TAEINT		*block,		/* in: parameter block		*/
    FORSTR		*name,		/* in: parameter name		*/
    TAEINT		*dimen,		/* in: dimension of string	*/
    FORSTR		*string,	/* out: FOR-77 string(s)	*/
    TAEINT		length[],	/* out: length of each string	*/
    TAEINT		*n,		/* out: number of strings	*/
    TAEINT		*status	/* out: status code		*/

)
{
    IMPORT TEXT		pm_dim[],pk_dim[],pm_type[],pk_type[];
    struct PARBLK *parblk;
    struct VARIABLE *v;
    TEXT	**s;			/* ptr to value vector in block	*/
    TEXT	c_name[STRINGSIZ+1];	/* name in C string format	*/
    COUNT	i;
    CODE	code;


    parblk = (struct PARBLK *) block;
    s_for2c(name, c_name, 0);			/* convert name to C string	*/
    s_strip(c_name);				/* remove trailing blanks	*/
    *n = 0;					/* caution in case error	*/

    v = p_find(parblk, c_name);
    if (v == NULL) goto p__bnerr;
    if ((*v).v_type != V_STRING) goto p__bterr; /* error if not string    */
    s = (TEXT **) (*v).v_cvp;			/* value pointer          */
    *status = SUCCESS;
    *n = (*v).v_count;				/* number of strings 		*/
    for (i=0; i < (*v).v_count && i < *dimen; i++)
    {
        length[i] = s_length(s[i]);		/* pass this length to caller	*/
        code = s_c2for(s[i], string, i);	/* copy string to caller	*/
        if (code != SUCCESS)
        {
            x_error((*parblk).mode, "String size overflows buffer",
                    "TAE-OVER", 0, 0, 0);
            *status = P_OVER;
            return;
        }
    }
    if ((*v).v_count > *dimen)
    {
        x_error((*parblk).mode, pm_dim, pk_dim,(uintptr_t) c_name, 0, 0);
        *status = P_BADCOUNT;		/* bad count		*/
    }
    return;

p__bnerr:
    *status = P_BADNAME;
    return;

p__bterr:
    *status = P_BADTYPE;
    x_error((*parblk).mode, pm_type, pk_type, (uintptr_t) c_name, 0, 0);
    return;
}
Beispiel #3
0
/*
 * Send a signal to one process.
 */
static int
kill_one(pid_t pid, int sig)
{
	struct proc *p;

	DPRINTF(("proc: killone pid=%d sig=%d\n", pid, sig));

	if ((p = p_find(pid)) == NULL)
		return ESRCH;
	return sendsig(p, sig);
}
Beispiel #4
0
/*
 * getpgid - get the process group ID for a process.
 *
 * If the specified pid is equal to 0, it returns the process
 * group ID of the calling process.
 */
int
sys_getpgid(pid_t pid, pid_t *retval)
{
	struct proc *p;

	ASSERT(curproc);

	if (pid == 0)
		p = curproc;
	else {
		if ((p = p_find(pid)) == NULL)
			return ESRCH;
	}
	*retval = p->p_pgrp->pg_pgid;
	return 0;
}
Beispiel #5
0
/*
 *	XRINTG.  Get integer parameters/variables.
 */
FUNCTION VOID BRIDGE2_NAME(xrintg)
(
    TAEINT		*block,		/* in: parameter block		*/
    FORSTR		*name,		/* in: parameter name		*/
    TAEINT		*dimen,		/* in: max # of values(dim of intg)	*/
    int			intg[],		/* out: array with intger var	*/
    TAEINT		*n,		/* out: integer value count	*/
    TAEINT		*status	/* out: status code		*/

)
{
    IMPORT TEXT		pm_dim[],pk_dim[],pm_type[],pk_type[];
    struct 	PARBLK 	*parblk;
    struct	VARIABLE *v;
    TEXT		c_name[STRINGSIZ+1];	/* name in C string format	*/
    COUNT		i;


    parblk = (struct PARBLK *) block;
    s_for2c(name, c_name, 0);			/* convert name to C string	*/
    s_strip(c_name);				/* remove trailing blanks	*/
    *n = 0;					/* caution in case error	*/

    v = p_find(parblk, c_name);
    if (v == NULL) goto p__bnerr;
    if ((*v).v_type != V_INTEGER) goto p__bterr;
    if ((*v).v_count > *dimen) goto p__bcerr;
    *n = (*v).v_count;
    for (i = 0; i < (*v).v_count; i++)
        intg[i] = IVAL(*v, i);
    *status = SUCCESS;
    return;

p__bnerr:
    *status = P_BADNAME;
    return;

p__bterr:
    *status = P_BADTYPE;
    x_error((*parblk).mode, pm_type, pk_type, (uintptr_t) c_name, 0, 0);
    return;

p__bcerr:
    *status = P_BADCOUNT;
    x_error((*parblk).mode, pm_dim, pk_dim, (uintptr_t) c_name, 0, 0);
    return;
}
Beispiel #6
0
/*
 * getsid - get the process group ID of a session leader.
 */
int
sys_getsid(pid_t pid, pid_t *retval)
{
	pid_t sid;
	struct proc *p, *leader;

	ASSERT(curproc);

	if (pid == 0)
		p = curproc;
	else {
		if ((p = p_find(pid)) == NULL)
			return ESRCH;
	}
	leader = p->p_pgrp->pg_session->s_leader;
	sid = leader->p_pid;

	DPRINTF(("proc: getsid sid=%d\n", sid));
	*retval = sid;
	return 0;
}
Beispiel #7
0
/*
 * setpgid - set process group ID for job control.
 *
 * If the specified pid is equal to 0, the process ID of
 * the calling process is used. Also, if pgid is 0, the process
 * ID of the indicated process is used.
 */
int
sys_setpgid(pid_t pid, pid_t pgid)
{
	struct proc *p;

	DPRINTF(("proc: setpgid pid=%d pgid=%d\n", pid, pgid));

	if (pid == 0)
		p = curproc;
	else {
		if ((p = p_find(pid)) == NULL)
			return ESRCH;
	}
	if (pgid < 0)
		return EINVAL;
	if (pgid == 0)
		pgid = p->p_pid;
	if (p->p_pgrp->pg_pgid == pgid)	/* already leader */
		return 0;
	return (enterpgrp(p, pgid));
}
Beispiel #8
0
void
db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
    const char *modif, void (*pr)(const char *, ...))
{
	register_t *fp, pc, rp;
	bool kernel_only = true;
	bool trace_thread = false;
	bool lwpaddr = false;
	db_sym_t sym;
	db_expr_t off;
	const char *name;
	const char *cp = modif;
	char c;

	if (count < 0)
		count = 65536;

	while ((c = *cp++) != 0) {
		if (c == 'a') {
			lwpaddr = true;
			trace_thread = true;
		}
		if (c == 't')
			trace_thread = true;
		if (c == 'u')
			kernel_only = false;
	}

	if (!have_addr) {
		fp = (register_t *)ddb_regs.tf_r3;
		pc = ddb_regs.tf_iioq_head;
		rp = ddb_regs.tf_rp;
	} else {
		if (trace_thread) {
			struct proc *p;
			struct user *u;
			struct lwp *l;
			if (lwpaddr) {
				l = (struct lwp *)addr;
				p = l->l_proc;
				(*pr)("trace: pid %d ", p->p_pid);
			} else {
				(*pr)("trace: pid %d ", (int)addr);
				p = p_find(addr, PFIND_LOCKED);
				if (p == NULL) {
					(*pr)("not found\n");
					return;
				}
				l = LIST_FIRST(&p->p_lwps);
				KASSERT(l != NULL);
			}
			(*pr)("lid %d ", l->l_lid);
			if (!(l->l_flag & LW_INMEM)) {
				(*pr)("swapped out\n");
				return;
			}
			u = l->l_addr;
			if (p == curproc && l == curlwp) {
				fp = (int *)ddb_regs.tf_r3;
				pc = ddb_regs.tf_iioq_head;
				rp = ddb_regs.tf_rp;
			} else {
				/* cpu_switchto fp, and return point */
				fp = (int *)(u->u_pcb.pcb_ksp -
				    (HPPA_FRAME_SIZE + 16*4));
				pc = 0;
				rp = fp[-5];
			}
			(*pr)("at %p\n", fp);
		} else {
			pc = 0;
			fp = (register_t *)addr;
			rp = fp[-5];
		}
	}

	while (fp && count--) {

#ifdef DDB_DEBUG
		pr(">> %08x %08x %08x\t", fp, pc, rp);
#endif

		if (USERMODE(pc))
			return;

		sym = db_search_symbol(pc, DB_STGY_ANY, &off);
		db_symbol_values (sym, &name, NULL);

		pr("%s() at ", name);
		db_printsym(pc, DB_STGY_PROC, pr);
		pr("\n");

		/* XXX NH - unwind info here */
		/* aue = ue_find(pc); */

		/*
		 * get rp?
		 * fp -= ue_total_frame_size(aue)
		 */

		/*
		 * if a terminal frame then report the trapframe
		 * and continue after it (if not the last one).
		 */
		if (!fp[0]) {
			register_t *scargs;
			struct trapframe *tf;
			int scoff;

			/* Stack space for syscall args */
			scoff = HPPA_FRAME_ROUND(HPPA_FRAME_SIZE + HPPA_FRAME_MAXARGS);

			scargs = (register_t *)((char *)fp - scoff);
			tf = (struct trapframe *)((char *)scargs - sizeof(*tf));

			if (tf->tf_flags & TFF_SYS)
				pr("-- syscall #%d(%x, %x, %x, %x, ...)\n",
				    tf->tf_t1, scargs[1], scargs[2],
				    scargs[3], scargs[4]);
			else
				pr("-- trap #%d%s\n", tf->tf_flags & 0x3f,
				    (tf->tf_flags & T_USER)? " from user" : "");

			if (!(tf->tf_flags & TFF_LAST)) {
				fp = (register_t *)tf->tf_r3;
				pc = tf->tf_iioq_head;
				rp = tf->tf_rp;
			} else {
				pc = 0;
				fp = 0;
			}
		} else {
			/* next frame */
			fp = (register_t *)fp[0];
			pc = rp;
			rp = fp[-5];
		}
	}

	if (count && pc) {
		db_printsym(pc, DB_STGY_XTRN, pr);
		pr(":\n");
	}
}
Beispiel #9
0
FUNCTION  FILE *z_init
(
#ifdef LARGE_PARBLK_FIX
    struct LARGE_PARBLK *block,         /* out: parameter block         */
#else
    struct	PARBLK	*block,		/* out: parameter block		*/
#endif
    FUNINT		mode		/* in: mode: P_ABORT or P_CONT  */

 )
    {
    IMPORT  FILE	*stdo_file;	/* pointer to stdout file	*/
    IMPORT  BOOL	term_std;	/* true if terminal is stdout   */
    IMPORT  CODE	applic_type;	/* application type ('c')	*/
    IMPORT  TEXT	pm_type[], pk_type[];
    struct VARIABLE	*v;
    CODE		termtype;
    COUNT		termlines;
    COUNT		termcols;
    TEXT		msgbuf[STRINGSIZ+1];
    TEXT		**stdr_ptr = 0;	/* stdrec string vector pointer	*/
    COUNT		len;
    CODE		code;
    TEXT		filemode[2];	/* create or append		*/
    FILE		*stdo_ptr;

    t_init(&termlines, &termcols, &termtype);	/* initialize terminal pkg */
#ifdef LARGE_PARBLK_FIX
    code = p_inim((struct PARBLK *)block, sizeof(struct LARGE_PARBLK), mode);    
#else
    code = p_inim(block, sizeof(struct PARBLK), mode);	
#endif
                                                /* receive parblk from TM  */
    if (code != SUCCESS)
	return (NULL);
    z_call ((struct PARBLK *)block);		/* application init	   */

    v = p_find ((struct PARBLK *)block, "_STDOUT");  /* get the string	*/	
    if ((*v).v_type != V_STRING)
      x_error ((*block).mode, pm_type, pk_type, (uintptr_t) "_STDOUT", 0, 0);
    else
	stdr_ptr = (TEXT **) (*v).v_cvp;	/* get value pointer	*/
    term_std = (s_equal(TERMINAL, stdr_ptr[0]));   /* filename = terminal ? */
#ifdef VICAR_BATCH_LOG
#ifdef VAX_VMS
    if (s_equal("SYS$OUTPUT:.;", stdr_ptr[0]))  /* alternate form of terminal */
        term_std = TRUE;
#endif
#endif
    s_copy("w", filemode);			/* assume create	    */
    if (!s_equal(stdr_ptr[1] , "CREATE"))
	s_copy("a", filemode);
#ifdef UNIX
    s_lower(stdr_ptr[0]);			/* make file name lower case */
#endif
    stdo_ptr = fopen(stdr_ptr[0], filemode);    	/* open the file */
    if (stdo_ptr == NULL)
	{
	if (mode == P_ABORT)
	    {
	    len = s_copy("Could not open standard output file ", msgbuf);
	    s_bcopy(stdr_ptr[0], &msgbuf[len], STRINGSIZ);
	    t_write(msgbuf, T_STDCC);			/* errmsg to terminal*/
	    z_exit(-1, "TAE-STDOPEN");			/* set SFI, SKEY     */
 	    }
	stdo_ptr = stdout;	/* Allow running with no terminal! */
				/* (without triggering shell-vicar) */
	}
    else
	stdo_file = stdo_ptr;			/* save stdout ptr globally */
    applic_type = C_TYPE;			/* 'c' language application */
    return (stdo_ptr);
    }
Beispiel #10
0
/*
 * Process debugging system call.
 */
int
sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval)
{
	/* {
		syscallarg(int) req;
		syscallarg(pid_t) pid;
		syscallarg(void *) addr;
		syscallarg(int) data;
	} */
	struct proc *p = l->l_proc;
	struct lwp *lt;
	struct proc *t;				/* target process */
	struct uio uio;
	struct iovec iov;
	struct ptrace_io_desc piod;
	struct ptrace_lwpinfo pl;
	struct vmspace *vm;
	int error, write, tmp, req, pheld;
	int signo;
	ksiginfo_t ksi;
#ifdef COREDUMP
	char *path;
#endif

	error = 0;
	req = SCARG(uap, req);

	/*
	 * If attaching or detaching, we need to get a write hold on the
	 * proclist lock so that we can re-parent the target process.
	 */
	mutex_enter(proc_lock);

	/* "A foolish consistency..." XXX */
	if (req == PT_TRACE_ME) {
		t = p;
		mutex_enter(t->p_lock);
	} else {
		/* Find the process we're supposed to be operating on. */
		if ((t = p_find(SCARG(uap, pid), PFIND_LOCKED)) == NULL) {
			mutex_exit(proc_lock);
			return (ESRCH);
		}

		/* XXX-elad */
		mutex_enter(t->p_lock);
		error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE,
		    t, KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
		if (error) {
			mutex_exit(proc_lock);
			mutex_exit(t->p_lock);
			return (ESRCH);
		}
	}

	/*
	 * Grab a reference on the process to prevent it from execing or
	 * exiting.
	 */
	if (!rw_tryenter(&t->p_reflock, RW_READER)) {
		mutex_exit(proc_lock);
		mutex_exit(t->p_lock);
		return EBUSY;
	}

	/* Make sure we can operate on it. */
	switch (req) {
	case  PT_TRACE_ME:
		/* Saying that you're being traced is always legal. */
		break;

	case  PT_ATTACH:
		/*
		 * You can't attach to a process if:
		 *	(1) it's the process that's doing the attaching,
		 */
		if (t->p_pid == p->p_pid) {
			error = EINVAL;
			break;
		}

		/*
		 *  (2) it's a system process
		 */
		if (t->p_flag & PK_SYSTEM) {
			error = EPERM;
			break;
		}

		/*
		 *	(3) it's already being traced, or
		 */
		if (ISSET(t->p_slflag, PSL_TRACED)) {
			error = EBUSY;
			break;
		}

		/*
		 * 	(4) the tracer is chrooted, and its root directory is
		 * 	    not at or above the root directory of the tracee
		 */
		mutex_exit(t->p_lock);	/* XXXSMP */
		tmp = proc_isunder(t, l);
		mutex_enter(t->p_lock);	/* XXXSMP */
		if (!tmp) {
			error = EPERM;
			break;
		}
		break;

	case  PT_READ_I:
	case  PT_READ_D:
	case  PT_WRITE_I:
	case  PT_WRITE_D:
	case  PT_IO:
#ifdef PT_GETREGS
	case  PT_GETREGS:
#endif
#ifdef PT_SETREGS
	case  PT_SETREGS:
#endif
#ifdef PT_GETFPREGS
	case  PT_GETFPREGS:
#endif
#ifdef PT_SETFPREGS
	case  PT_SETFPREGS:
#endif
#ifdef __HAVE_PTRACE_MACHDEP
	PTRACE_MACHDEP_REQUEST_CASES
#endif
		/*
		 * You can't read/write the memory or registers of a process
		 * if the tracer is chrooted, and its root directory is not at
		 * or above the root directory of the tracee.
		 */
		mutex_exit(t->p_lock);	/* XXXSMP */
		tmp = proc_isunder(t, l);
		mutex_enter(t->p_lock);	/* XXXSMP */
		if (!tmp) {
			error = EPERM;
			break;
		}
		/*FALLTHROUGH*/

	case  PT_CONTINUE:
	case  PT_KILL:
	case  PT_DETACH:
	case  PT_LWPINFO:
	case  PT_SYSCALL:
#ifdef COREDUMP
	case  PT_DUMPCORE:
#endif
#ifdef PT_STEP
	case  PT_STEP:
#endif
		/*
		 * You can't do what you want to the process if:
		 *	(1) It's not being traced at all,
		 */
		if (!ISSET(t->p_slflag, PSL_TRACED)) {
			error = EPERM;
			break;
		}

		/*
		 *	(2) it's being traced by procfs (which has
		 *	    different signal delivery semantics),
		 */
		if (ISSET(t->p_slflag, PSL_FSTRACE)) {
			uprintf("file system traced\n");
			error = EBUSY;
			break;
		}

		/*
		 *	(3) it's not being traced by _you_, or
		 */
		if (t->p_pptr != p) {
			uprintf("parent %d != %d\n", t->p_pptr->p_pid, p->p_pid);
			error = EBUSY;
			break;
		}

		/*
		 *	(4) it's not currently stopped.
		 */
		if (t->p_stat != SSTOP || !t->p_waited /* XXXSMP */) {
			uprintf("stat %d flag %d\n", t->p_stat,
			    !t->p_waited);
			error = EBUSY;
			break;
		}
		break;

	default:			/* It was not a legal request. */
		error = EINVAL;
		break;
	}

	if (error == 0)
		error = kauth_authorize_process(l->l_cred,
		    KAUTH_PROCESS_PTRACE, t, KAUTH_ARG(req),
		    NULL, NULL);

	if (error != 0) {
		mutex_exit(proc_lock);
		mutex_exit(t->p_lock);
		rw_exit(&t->p_reflock);
		return error;
	}

	/* Do single-step fixup if needed. */
	FIX_SSTEP(t);

	/*
	 * XXX NJWLWP
	 *
	 * The entire ptrace interface needs work to be useful to a
	 * process with multiple LWPs. For the moment, we'll kluge
	 * this; memory access will be fine, but register access will
	 * be weird.
	 */
	lt = LIST_FIRST(&t->p_lwps);
	KASSERT(lt != NULL);
	lwp_addref(lt);

	/*
	 * Which locks do we need held? XXX Ugly.
	 */
	switch (req) {
#ifdef PT_STEP
	case PT_STEP:
#endif
	case PT_CONTINUE:
	case PT_DETACH:
	case PT_KILL:
	case PT_SYSCALL:
	case PT_ATTACH:
	case PT_TRACE_ME:
		pheld = 1;
		break;
	default:
		mutex_exit(proc_lock);
		mutex_exit(t->p_lock);
		pheld = 0;
		break;
	}

	/* Now do the operation. */
	write = 0;
	*retval = 0;
	tmp = 0;

	switch (req) {
	case  PT_TRACE_ME:
		/* Just set the trace flag. */
		SET(t->p_slflag, PSL_TRACED);
		t->p_opptr = t->p_pptr;
		break;

	case  PT_WRITE_I:		/* XXX no separate I and D spaces */
	case  PT_WRITE_D:
#if defined(__HAVE_RAS)
		/*
		 * Can't write to a RAS
		 */
		if (ras_lookup(t, SCARG(uap, addr)) != (void *)-1) {
			error = EACCES;
			break;
		}
#endif
		write = 1;
		tmp = SCARG(uap, data);
		/* FALLTHROUGH */

	case  PT_READ_I:		/* XXX no separate I and D spaces */
	case  PT_READ_D:
		/* write = 0 done above. */
		iov.iov_base = (void *)&tmp;
		iov.iov_len = sizeof(tmp);
		uio.uio_iov = &iov;
		uio.uio_iovcnt = 1;
		uio.uio_offset = (off_t)(unsigned long)SCARG(uap, addr);
		uio.uio_resid = sizeof(tmp);
		uio.uio_rw = write ? UIO_WRITE : UIO_READ;
		UIO_SETUP_SYSSPACE(&uio);

		error = process_domem(l, lt, &uio);
		if (!write)
			*retval = tmp;
		break;

	case  PT_IO:
		error = copyin(SCARG(uap, addr), &piod, sizeof(piod));
		if (error)
			break;
		switch (piod.piod_op) {
		case PIOD_READ_D:
		case PIOD_READ_I:
			uio.uio_rw = UIO_READ;
			break;
		case PIOD_WRITE_D:
		case PIOD_WRITE_I:
			/*
			 * Can't write to a RAS
			 */
			if (ras_lookup(t, SCARG(uap, addr)) != (void *)-1) {
				return (EACCES);
			}
			uio.uio_rw = UIO_WRITE;
			break;
		default:
			error = EINVAL;
			break;
		}
		if (error)
			break;
		error = proc_vmspace_getref(l->l_proc, &vm);
		if (error)
			break;
		iov.iov_base = piod.piod_addr;
		iov.iov_len = piod.piod_len;
		uio.uio_iov = &iov;
		uio.uio_iovcnt = 1;
		uio.uio_offset = (off_t)(unsigned long)piod.piod_offs;
		uio.uio_resid = piod.piod_len;
		uio.uio_vmspace = vm;

		error = process_domem(l, lt, &uio);
		piod.piod_len -= uio.uio_resid;
		(void) copyout(&piod, SCARG(uap, addr), sizeof(piod));
		uvmspace_free(vm);
		break;

#ifdef COREDUMP
	case  PT_DUMPCORE:
		if ((path = SCARG(uap, addr)) != NULL) {
			char *dst;
			int len = SCARG(uap, data);
			if (len < 0 || len >= MAXPATHLEN) {
				error = EINVAL;
				break;
			}
			dst = malloc(len + 1, M_TEMP, M_WAITOK);
			if ((error = copyin(path, dst, len)) != 0) {
				free(dst, M_TEMP);
				break;
			}
			path = dst;
			path[len] = '\0';
		}
		error = coredump(lt, path);
		if (path)
			free(path, M_TEMP);
		break;
#endif

#ifdef PT_STEP
	case  PT_STEP:
		/*
		 * From the 4.4BSD PRM:
		 * "Execution continues as in request PT_CONTINUE; however
		 * as soon as possible after execution of at least one
		 * instruction, execution stops again. [ ... ]"
		 */
#endif
	case  PT_CONTINUE:
	case  PT_SYSCALL:
	case  PT_DETACH:
		if (req == PT_SYSCALL) {
			if (!ISSET(t->p_slflag, PSL_SYSCALL)) {
				SET(t->p_slflag, PSL_SYSCALL);
#ifdef __HAVE_SYSCALL_INTERN
				(*t->p_emul->e_syscall_intern)(t);
#endif
			}
		} else {
			if (ISSET(t->p_slflag, PSL_SYSCALL)) {
				CLR(t->p_slflag, PSL_SYSCALL);
#ifdef __HAVE_SYSCALL_INTERN
				(*t->p_emul->e_syscall_intern)(t);
#endif
			}
		}
		p->p_trace_enabled = trace_is_enabled(p);

		/*
		 * From the 4.4BSD PRM:
		 * "The data argument is taken as a signal number and the
		 * child's execution continues at location addr as if it
		 * incurred that signal.  Normally the signal number will
		 * be either 0 to indicate that the signal that caused the
		 * stop should be ignored, or that value fetched out of
		 * the process's image indicating which signal caused
		 * the stop.  If addr is (int *)1 then execution continues
		 * from where it stopped."
		 */

		/* Check that the data is a valid signal number or zero. */
		if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG) {
			error = EINVAL;
			break;
		}

		uvm_lwp_hold(lt);

		/* If the address parameter is not (int *)1, set the pc. */
		if ((int *)SCARG(uap, addr) != (int *)1)
			if ((error = process_set_pc(lt, SCARG(uap, addr))) != 0) {
				uvm_lwp_rele(lt);
				break;
			}

#ifdef PT_STEP
		/*
		 * Arrange for a single-step, if that's requested and possible.
		 */
		error = process_sstep(lt, req == PT_STEP);
		if (error) {
			uvm_lwp_rele(lt);
			break;
		}
#endif

		uvm_lwp_rele(lt);

		if (req == PT_DETACH) {
			CLR(t->p_slflag, PSL_TRACED|PSL_FSTRACE|PSL_SYSCALL);

			/* give process back to original parent or init */
			if (t->p_opptr != t->p_pptr) {
				struct proc *pp = t->p_opptr;
				proc_reparent(t, pp ? pp : initproc);
			}

			/* not being traced any more */
			t->p_opptr = NULL;
		}

		signo = SCARG(uap, data);
	sendsig:
		/* Finally, deliver the requested signal (or none). */
		if (t->p_stat == SSTOP) {
			/*
			 * Unstop the process.  If it needs to take a
			 * signal, make all efforts to ensure that at
			 * an LWP runs to see it.
			 */
			t->p_xstat = signo;
			proc_unstop(t);
		} else if (signo != 0) {
			KSI_INIT_EMPTY(&ksi);
			ksi.ksi_signo = signo;
			kpsignal2(t, &ksi);
		}
		break;

	case  PT_KILL:
		/* just send the process a KILL signal. */
		signo = SIGKILL;
		goto sendsig;	/* in PT_CONTINUE, above. */

	case  PT_ATTACH:
		/*
		 * Go ahead and set the trace flag.
		 * Save the old parent (it's reset in
		 *   _DETACH, and also in kern_exit.c:wait4()
		 * Reparent the process so that the tracing
		 *   proc gets to see all the action.
		 * Stop the target.
		 */
		t->p_opptr = t->p_pptr;
		if (t->p_pptr != p) {
			struct proc *parent = t->p_pptr;

			if (parent->p_lock < t->p_lock) {
				if (!mutex_tryenter(parent->p_lock)) {
					mutex_exit(t->p_lock);
					mutex_enter(parent->p_lock);
				}
			} else if (parent->p_lock > t->p_lock) {
				mutex_enter(parent->p_lock);
			}
			parent->p_slflag |= PSL_CHTRACED;
			proc_reparent(t, p);
			if (parent->p_lock != t->p_lock)
				mutex_exit(parent->p_lock);
		}
		SET(t->p_slflag, PSL_TRACED);
		signo = SIGSTOP;
		goto sendsig;

	case PT_LWPINFO:
		if (SCARG(uap, data) != sizeof(pl)) {
			error = EINVAL;
			break;
		}
		error = copyin(SCARG(uap, addr), &pl, sizeof(pl));
		if (error)
			break;
		tmp = pl.pl_lwpid;
		lwp_delref(lt);
		mutex_enter(t->p_lock);
		if (tmp == 0)
			lt = LIST_FIRST(&t->p_lwps);
		else {
			lt = lwp_find(t, tmp);
			if (lt == NULL) {
				mutex_exit(t->p_lock);
				error = ESRCH;
				break;
			}
			lt = LIST_NEXT(lt, l_sibling);
		}
		while (lt != NULL && lt->l_stat == LSZOMB)
			lt = LIST_NEXT(lt, l_sibling);
		pl.pl_lwpid = 0;
		pl.pl_event = 0;
		if (lt) {
			lwp_addref(lt);
			pl.pl_lwpid = lt->l_lid;
			if (lt->l_lid == t->p_sigctx.ps_lwp)
				pl.pl_event = PL_EVENT_SIGNAL;
		}
		mutex_exit(t->p_lock);

		error = copyout(&pl, SCARG(uap, addr), sizeof(pl));
		break;

#ifdef PT_SETREGS
	case  PT_SETREGS:
		write = 1;
#endif
#ifdef PT_GETREGS
	case  PT_GETREGS:
		/* write = 0 done above. */
#endif
#if defined(PT_SETREGS) || defined(PT_GETREGS)
		tmp = SCARG(uap, data);
		if (tmp != 0 && t->p_nlwps > 1) {
			lwp_delref(lt);
			mutex_enter(t->p_lock);
			lt = lwp_find(t, tmp);
			if (lt == NULL) {
				mutex_exit(t->p_lock);
				error = ESRCH;
				break;
			}
			lwp_addref(lt);
			mutex_exit(t->p_lock);
		}
		if (!process_validregs(lt))
			error = EINVAL;
		else {
			error = proc_vmspace_getref(l->l_proc, &vm);
			if (error)
				break;
			iov.iov_base = SCARG(uap, addr);
			iov.iov_len = sizeof(struct reg);
			uio.uio_iov = &iov;
			uio.uio_iovcnt = 1;
			uio.uio_offset = 0;
			uio.uio_resid = sizeof(struct reg);
			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
			uio.uio_vmspace = vm;

			error = process_doregs(l, lt, &uio);
			uvmspace_free(vm);
		}
		break;
#endif

#ifdef PT_SETFPREGS
	case  PT_SETFPREGS:
		write = 1;
#endif
#ifdef PT_GETFPREGS
	case  PT_GETFPREGS:
		/* write = 0 done above. */
#endif
#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
		tmp = SCARG(uap, data);
		if (tmp != 0 && t->p_nlwps > 1) {
			lwp_delref(lt);
			mutex_enter(t->p_lock);
			lt = lwp_find(t, tmp);
			if (lt == NULL) {
				mutex_exit(t->p_lock);
				error = ESRCH;
				break;
			}
			lwp_addref(lt);
			mutex_exit(t->p_lock);
		}
		if (!process_validfpregs(lt))
			error = EINVAL;
		else {
			error = proc_vmspace_getref(l->l_proc, &vm);
			if (error)
				break;
			iov.iov_base = SCARG(uap, addr);
			iov.iov_len = sizeof(struct fpreg);
			uio.uio_iov = &iov;
			uio.uio_iovcnt = 1;
			uio.uio_offset = 0;
			uio.uio_resid = sizeof(struct fpreg);
			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
			uio.uio_vmspace = vm;

			error = process_dofpregs(l, lt, &uio);
			uvmspace_free(vm);
		}
		break;
#endif

#ifdef __HAVE_PTRACE_MACHDEP
	PTRACE_MACHDEP_REQUEST_CASES
		error = ptrace_machdep_dorequest(l, lt,
		    req, SCARG(uap, addr), SCARG(uap, data));
		break;
#endif
	}

	if (pheld) {
		mutex_exit(t->p_lock);
		mutex_exit(proc_lock);
	}
	if (lt != NULL)
		lwp_delref(lt);
	rw_exit(&t->p_reflock);

	return error;
}
Beispiel #11
0
FUNCTION VOID BRIDGE2_NAME(xrfile) 
(
    TAEINT		*block,		/* in: parameter block		*/
    FORSTR		*name,		/* in: parameter name		*/
    TAEINT		*dimen,		/* in: dimension of string	*/
    FORSTR		*tae_file,	/* out: FOR-77 tae file string(s)	*/
    TAEINT		tae_length[],	/* out: length of each tae file string	*/
    FORSTR		*host_file,	/* out: FOR-77 host file string(s)	*/
    TAEINT		host_length[],	/* out: length of each host file string	*/
    TAEINT		*n,		/* out: number of strings	*/
    TAEINT		*status	/* out: status code		*/

 )
    {
    struct PARBLK 	*parblk;
    TEXT		**s;			/* ptr to value vector in block	*/
    TEXT		c_name[STRINGSIZ+1];	/* name in C string format	*/
    COUNT		i;
    struct VARIABLE	*v;		/* variable in parm block		*/
    TEXT		temp[FSPECSIZ+1];
    TAEINT 		filemode;
    CODE		code;

    parblk = (struct PARBLK *) block;
    s_for2c(name, c_name, 0);			/* convert name to C string	*/
    s_strip(c_name);				/* remove trailing blanks	*/
    *n = 0;					/* caution in case error	*/ 

    v = p_find(parblk, c_name);			/* get string			*/
    if (v == NULL) goto p__bnerr;		/* check for name error		*/
    if ((*v).v_type != V_STRING) goto p__bterr; /* check for type error		*/
    s = (TEXT **) (*v).v_cvp;			/* value pointer		*/

    if (!(*v).v_file) goto p__bterr;
    filemode = (*v).v_filemode;
    *status = SUCCESS;				
    *n = (*v).v_count;				/* number of strings		*/
    for (i=0; i < (*v).v_count && i < *dimen; i++) /* get all tae & host files	*/
	{
	tae_length[i] = s_length(s[i]);	/* pass this length to caller	*/
	code = s_c2for(s[i], tae_file, i);	/* copy tae file to caller*/
        if (code != SUCCESS)
	    {
	    x_error((*parblk).mode, "File name longer than buffer size.",
		    "TAE-OVER", 0, 0, 0);
   	    *status = P_OVER;
	    return;
	    }
	xzhost(s[i], temp, &filemode, status);	/* get host spec	*/
	if (*status != SUCCESS)
	    {
	      x_error((*parblk).mode, (TEXT *) pm_trans, (TEXT *) pk_trans, 
		      (uintptr_t) s[i], 0, 0);
	    *status = P_FAIL;			/* failed to translate	*/
	    return;
	    }
	host_length[i] = s_length(temp);	/* pass this length to caller	*/
	s_c2for(temp, host_file, i);	/* copy host file to caller	*/
	}
    if ((*v).v_count > *dimen)
	*status = P_BADCOUNT;		/* bad count			*/
    return;

p__bnerr:
    *status = P_BADNAME;
    return;

p__bterr:
    x_error((*parblk).mode, (TEXT *) pm_type, (TEXT *) pk_type, 
	    (uintptr_t) (*v).v_name, 0, 0);
    *status = P_BADTYPE;
    return;
    }
Beispiel #12
0
void
db_stack_trace_print(db_expr_t addr, bool have_addr,
		     db_expr_t count, const char *modif,
		     void (*pr)(const char *, ...))
{
	struct frame	*frame, *prevframe;
	db_addr_t	pc;
	bool		kernel_only = true;
	bool		trace_thread = false;
	bool		lwpaddr = false;
	const char	*cp = modif;
	char		c;

	if (ddb_cpuinfo == NULL)
		ddb_cpuinfo = curcpu();

	while ((c = *cp++) != 0) {
		if (c == 'a') {
			lwpaddr = true;
			trace_thread = true;
		}
		if (c == 't')
			trace_thread = true;
		if (c == 'u')
			kernel_only = false;
	}

	if (!have_addr) {
		frame = (struct frame *)DDB_TF->tf_out[6];
		pc = DDB_TF->tf_pc;
	} else {
		if (trace_thread) {
			struct proc *p;
			struct user *u;
			struct lwp *l;
			if (lwpaddr) {
				l = (struct lwp *)addr;
				p = l->l_proc;
				(*pr)("trace: pid %d ", p->p_pid);
			} else {
				(*pr)("trace: pid %d ", (int)addr);
				p = p_find(addr, PFIND_LOCKED);
				if (p == NULL) {
					(*pr)("not found\n");
					return;
				}
				l = LIST_FIRST(&p->p_lwps);
				KASSERT(l != NULL);
			}
			(*pr)("lid %d ", l->l_lid);
			if ((l->l_flag & LW_INMEM) == 0) {
				(*pr)("swapped out\n");
				return;
			}
			u = l->l_addr;
			frame = (struct frame *)u->u_pcb.pcb_sp;
			pc = u->u_pcb.pcb_pc;
			(*pr)("at %p\n", frame);
		} else {
			frame = (struct frame *)addr;
			pc = 0;
		}
	}

	while (count--) {
		int		i;
		db_expr_t	offset;
		const char	*name;
		db_addr_t	prevpc;

#define FR(framep,field) (INKERNEL(framep)			\
				? (u_int)(framep)->field	\
				: fuword(&(framep)->field))

		/* Fetch return address and arguments frame */
		prevpc = (db_addr_t)FR(frame, fr_pc);
		prevframe = (struct frame *)FR(frame, fr_fp);

		/*
		 * Switch to frame that contains arguments
		 */
		if (prevframe == NULL || (!INKERNEL(prevframe) && kernel_only))
			return;

		if ((ONINTSTACK(frame) && !ONINTSTACK(prevframe)) ||
		    (INKERNEL(frame) && !INKERNEL(prevframe))) {
			/* We're crossing a trap frame; pc = %l1 */
			prevpc = (db_addr_t)FR(frame, fr_local[1]);
		}

		name = NULL;
		if (INKERNEL(pc))
			db_find_sym_and_offset(pc, &name, &offset);
		if (name == NULL)
			(*pr)("0x%lx(", pc);
		else
			(*pr)("%s(", name);

		/*
		 * Print %i0..%i5, hope these still reflect the
		 * actual arguments somewhat...
		 */
		for (i = 0; i < 6; i++)
			(*pr)("0x%x%s", FR(frame, fr_arg[i]),
				(i < 5) ? ", " : ") at ");
		if (INKERNEL(prevpc))
			db_printsym(prevpc, DB_STGY_PROC, pr);
		else
			(*pr)("0x%lx", prevpc);
		(*pr)("\n");

		pc = prevpc;
		frame = prevframe;
	}
}
Beispiel #13
0
void
db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
    const char *modif, void (*pr)(const char *, ...))
{
#ifndef DDB_TRACE
	struct pcb *pcb;
	struct proc *p;
	struct lwp *l;

	if (!have_addr) {
		stacktrace_subr(ddb_regs.f_regs[_R_A0],
				ddb_regs.f_regs[_R_A1],
				ddb_regs.f_regs[_R_A2],
				ddb_regs.f_regs[_R_A3],
				ddb_regs.f_regs[_R_PC],
				ddb_regs.f_regs[_R_SP],
				/* non-virtual frame pointer */
				ddb_regs.f_regs[_R_S8],
				ddb_regs.f_regs[_R_RA],
				pr);
		return;
	}

	/* "trace/t" */
	(*pr)("pid %d ", (int)addr);
	p = p_find(addr, PFIND_LOCKED);
	if (p == NULL) {
		(*pr)("not found\n");
		return;
	}	
	l = LIST_FIRST(&p->p_lwps); /* XXX NJWLWP */
	if (!(l->l_flag & LW_INMEM)) {
		(*pr)("swapped out\n");
		return;
	}

	pcb = &(l->l_addr->u_pcb);
	(*pr)("at %p\n", pcb);

	stacktrace_subr(0,0,0,0,	/* no args known */
			(int)cpu_switchto,
			pcb->pcb_context[8],
			pcb->pcb_context[9],
			pcb->pcb_context[10],
			pr);
#else
/*
 * Incomplete but practically useful stack backtrace.
 */
#define	MIPS_JR_RA	0x03e00008	/* instruction code for jr ra */
#define	MIPS_JR_K0	0x03400008	/* instruction code for jr k0 */
#define	MIPS_ERET	0x42000018	/* instruction code for eret */
	unsigned va, pc, ra, sp, func;
	int insn;
	InstFmt i;
	int stacksize;
	db_addr_t offset;
	const char *name;
	extern char verylocore[];

	pc = ddb_regs.f_regs[_R_PC];
	sp = ddb_regs.f_regs[_R_SP];
	ra = ddb_regs.f_regs[_R_RA];
	do {
		va = pc;
		do {
			va -= sizeof(int);
			insn = *(int *)va;
			if (insn == MIPS_ERET)
				goto mips3_eret;
		} while (insn != MIPS_JR_RA && insn != MIPS_JR_K0);
		va += sizeof(int);
	mips3_eret:
		va += sizeof(int);
		while (*(int *)va == 0x00000000)
			va += sizeof(int);
		func = va;
		stacksize = 0;
		do {
			i.word = *(int *)va;
			if (i.IType.op == OP_SW
			    && i.IType.rs == _R_SP
			    && i.IType.rt == _R_RA)
				ra = *(int *)(sp + (short)i.IType.imm);
			if (i.IType.op == OP_ADDIU
			    && i.IType.rs == _R_SP
			    && i.IType.rt == _R_SP)
				stacksize = -(short)i.IType.imm;
			va += sizeof(int);
		} while (va < pc);

		db_find_sym_and_offset(func, &name, &offset);
		if (name == 0)
			name = "?";
		(*pr)("%s()+0x%x, called by %p, stack size %d\n",
			name, pc - func, (void *)ra, stacksize);

		if (ra == pc) {
			(*pr)("-- loop? --\n");
			return;
		}
		sp += stacksize;
		pc = ra;
	} while (pc > (unsigned)verylocore);
	if (pc < 0x80000000)
		(*pr)("-- user process --\n");
	else
		(*pr)("-- kernel entry --\n");
#endif
}
Beispiel #14
0
void
db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
		     const char *modif, void (*pr)(const char *, ...))
{
	long *frame, *lastframe;
	long *retaddr, *arg0;
	long		*argp;
	db_addr_t	callpc;
	int		is_trap;
	bool		kernel_only = true;
	bool		trace_thread = false;
	bool		lwpaddr = false;

#if 0
	if (!db_trace_symbols_found)
		db_find_trace_symbols();
#endif

	{
		const char *cp = modif;
		char c;

		while ((c = *cp++) != 0) {
			if (c == 'a') {
				lwpaddr = true;
				trace_thread = true;
			}
			if (c == 't')
				trace_thread = true;
			if (c == 'u')
				kernel_only = false;
		}
	}

	if (!have_addr) {
		frame = (long *)ddb_regs.tf_rbp;
		callpc = (db_addr_t)ddb_regs.tf_rip;
	} else {
		if (trace_thread) {
			struct proc *p;
			struct user *u;
			struct lwp *l;
			if (lwpaddr) {
				l = (struct lwp *)addr;
				p = l->l_proc;
				(*pr)("trace: pid %d ", p->p_pid);
			} else {
				(*pr)("trace: pid %d ", (int)addr);
				p = p_find(addr, PFIND_LOCKED);
				if (p == NULL) {
					(*pr)("not found\n");
					return;
				}
				l = LIST_FIRST(&p->p_lwps);
				KASSERT(l != NULL);
			}
			(*pr)("lid %d ", l->l_lid);
			if (!(l->l_flag & LW_INMEM)) {
				(*pr)("swapped out\n");
				return;
			}
			u = l->l_addr;
			if (p == curproc && l == curlwp) {
				frame = (long *)ddb_regs.tf_rbp;
				callpc = (db_addr_t)ddb_regs.tf_rip;
				(*pr)("at %p\n", frame);
			} else {
				frame = (long *)u->u_pcb.pcb_rbp;
				callpc = (db_addr_t)
				    db_get_value((long)(frame + 1), 8, false);
				(*pr)("at %p\n", frame);
				frame = (long *)*frame; /* XXXfvdl db_get_value? */
			}
		} else {
			frame = (long *)addr;
			callpc = (db_addr_t)
			    db_get_value((long)(frame + 1), 8, false);
			frame = (long *)*frame; /* XXXfvdl db_get_value? */
		}
	}
	retaddr = frame + 1;
	arg0 = frame + 2;

	lastframe = 0;
	while (count && frame != 0) {
		int		narg;
		const char *	name;
		db_expr_t	offset;
		db_sym_t	sym;
		char	*argnames[16], **argnp = NULL;
		db_addr_t	lastcallpc;

		name = "?";
		is_trap = NONE;
		offset = 0;
		sym = db_frame_info(frame, callpc, &name, &offset, &is_trap,
				    &narg);

		if (lastframe == 0 && sym == (db_sym_t)0) {
			/* Symbol not found, peek at code */
			u_long	instr = db_get_value(callpc, 4, false);

			offset = 1;
			if (instr  == 0xe5894855 ||
					/* enter: pushq %rbp, movq %rsp, %rbp */
			    (instr & 0x00ffffff) == 0x0048e589
					/* enter+1: movq %rsp, %rbp */) {
				offset = 0;
			}
		}

		if (is_trap == NONE) {
			if (db_sym_numargs(sym, &narg, argnames))
				argnp = argnames;
			else
				narg = db_numargs(frame);
		}

		(*pr)("%s(", name);

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/*
			 * We have a breakpoint before the frame is set up
			 * Use %rsp instead
			 */
			argp = &((struct x86_64_frame *)(ddb_regs.tf_rsp-8))->f_arg0;
		} else {
			argp = frame + 2;
		}

		while (narg) {
			if (argnp)
				(*pr)("%s=", *argnp++);
			(*pr)("%lx", db_get_value((long)argp, 8, false));
			argp++;
			if (--narg != 0)
				(*pr)(",");
		}
		(*pr)(") at ");
		db_printsym(callpc, DB_STGY_PROC, pr);
		(*pr)("\n");

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/* Frame really belongs to next callpc */
			struct x86_64_frame *fp = (void *)(ddb_regs.tf_rsp-8);

			lastframe = (long *)fp;
			callpc = (db_addr_t)
			    db_get_value((db_addr_t)&fp->f_retaddr, 8, false);
			continue;
		}

		lastframe = frame;
		lastcallpc = callpc;
		if (!db_nextframe(&frame, &retaddr, &arg0,
		   &callpc, frame + 2, is_trap, pr))
			break;

		if (INKERNEL((long)frame)) {
			/* staying in kernel */
			if (frame < lastframe ||
			    (frame == lastframe && callpc == lastcallpc)) {
				(*pr)("Bad frame pointer: %p\n", frame);
				break;
			}
		} else if (INKERNEL((long)lastframe)) {
			/* switch from user to kernel */
			if (kernel_only)
				break;	/* kernel stack only */
		} else {
			/* in user */
			if (frame <= lastframe) {
				(*pr)("Bad user frame pointer: %p\n",
					  frame);
				break;
			}
		}
		--count;
	}

	if (count && is_trap != NONE) {
		db_printsym(callpc, DB_STGY_XTRN, pr);
		(*pr)(":\n");
	}
}