7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER START
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The contents of this file are subject to the terms of the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Common Development and Distribution License (the "License").
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You may not use this file except in compliance with the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * or http://www.opensolaris.org/os/licensing.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * See the License for the specific language governing permissions
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * and limitations under the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * When distributing Covered Code, include this CDDL HEADER in each
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If applicable, add the following below this CDDL HEADER, with the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * fields enclosed by brackets "[]" replaced with your own identifying
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * information: Portions Copyright [yyyy] [name of copyright owner]
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER END
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Use is subject to license terms.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Copyright (c) 2013, Joyent, Inc. All rights reserved.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <stdio.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <stdlib.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <unistd.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <ctype.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <fcntl.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <string.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <memory.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <errno.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <dirent.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <limits.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <signal.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/types.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/uio.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/stat.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/resource.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/param.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/stack.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/fault.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/syscall.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/sysmacros.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include "libproc.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include "Pcontrol.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include "Putil.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include "P32ton.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include "Pisadep.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiextern sigset_t blockable_sigs;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic void
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiPabort_agent(struct ps_prochandle *P)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int sysnum = P->status.pr_lwp.pr_syscall;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int stop;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("agent LWP is stopped or asleep in syscall %d\n", sysnum);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) Pstop(P, 0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi stop = Psysexit(P, sysnum, TRUE);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (Psetrun(P, 0, PRSABORT) == 0) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi while (Pwait(P, 0) == -1 && errno == EINTR)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi continue;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) Psysexit(P, sysnum, stop);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("agent LWP system call aborted\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Create the /proc agent LWP for further operations.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiint
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiPcreate_agent(struct ps_prochandle *P)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int fd;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi char pathname[PATH_MAX];
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi char *fname;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi struct {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi long cmd;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi prgregset_t regs;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi } cmd;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If not first reference, we already have the /proc agent LWP active.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->agentcnt > 0) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->agentcnt++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The agent is not available for use as a mortician or as an
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * obstetrician.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->state == PS_DEAD || P->state == PS_UNDEAD ||
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->state == PS_IDLE) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi errno = ENOENT;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (-1);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Create the special /proc agent LWP if it doesn't already exist.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Give it the registers of the representative LWP.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) Pstop(P, 0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Psync(P);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (!(P->status.pr_lwp.pr_flags & PR_AGENT)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi cmd.cmd = PCAGENT;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) memcpy(&cmd.regs, &P->status.pr_lwp.pr_reg[0],
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sizeof (P->status.pr_lwp.pr_reg));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (write(P->ctlfd, &cmd, sizeof (cmd)) != sizeof (cmd))
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* refresh the process status */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) Pstopstatus(P, PCNULL, 0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* open the agent LWP files */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) snprintf(pathname, sizeof (pathname), "%s/%d/lwp/agent/",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi procfs_path, (int)P->pid);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi fname = pathname + strlen(pathname);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) set_minfd();
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * It is difficult to know how to recover from the two errors
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * that follow. The agent LWP exists and we need to kill it,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * but we can't because we need it active in order to kill it.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * We just hope that these failures never occur.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) strcpy(fname, "lwpstatus");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((fd = open(pathname, O_RDONLY)) < 0 ||
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (fd = dupfd(fd, 0)) < 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->agentstatfd = fd;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) strcpy(fname, "lwpctl");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((fd = open(pathname, O_WRONLY)) < 0 ||
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (fd = dupfd(fd, 0)) < 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->agentctlfd = fd;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If the agent is currently asleep in a system call or stopped on
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * system call entry, attempt to abort the system call so it's ready to
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * serve.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((P->status.pr_lwp.pr_flags & PR_ASLEEP) ||
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ((P->status.pr_lwp.pr_flags & PR_STOPPED) &&
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->status.pr_lwp.pr_why == PR_SYSENTRY)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("Pcreate_agent: aborting agent syscall; lwp is %s\n",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (P->status.pr_lwp.pr_flags & PR_ASLEEP) ?
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "asleep" : "stopped");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Pabort_agent(P);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* get the agent LWP status */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->agentcnt++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (Pstopstatus(P, PCNULL, 0) != 0) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Pdestroy_agent(P);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (-1);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad:
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->agentstatfd >= 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) close(P->agentstatfd);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->agentctlfd >= 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) close(P->agentctlfd);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->agentstatfd = -1;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->agentctlfd = -1;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* refresh the process status */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) Pstopstatus(P, PCNULL, 0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (-1);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Decrement the /proc agent agent reference count.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * On last reference, destroy the agent.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiPdestroy_agent(struct ps_prochandle *P)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->agentcnt > 1)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->agentcnt--;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi else {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int flags;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Psync(P); /* Flush out any pending changes */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) Pstopstatus(P, PCNULL, 0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi flags = P->status.pr_lwp.pr_flags;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If the agent is currently asleep in a system call, attempt
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * to abort the system call so we can terminate the agent.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((flags & (PR_AGENT|PR_ASLEEP)) == (PR_AGENT|PR_ASLEEP)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("Pdestroy_agent: aborting agent syscall\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Pabort_agent(P);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The agent itself is destroyed by forcing it to execute
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * the _lwp_exit(2) system call. Close our agent descriptors
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * regardless of whether this is successful.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) pr_lwp_exit(P);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) close(P->agentctlfd);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) close(P->agentstatfd);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->agentctlfd = -1;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->agentstatfd = -1;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->agentcnt = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Now that (hopefully) the agent has exited, refresh the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * status: the representative LWP is no longer the agent.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) Pstopstatus(P, PCNULL, 0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Execute the syscall instruction.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic int
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiexecute(struct ps_prochandle *P, int sysindex)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int ctlfd = (P->agentctlfd >= 0)? P->agentctlfd : P->ctlfd;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int washeld = FALSE;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sigset_t hold; /* mask of held signals */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int cursig;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi struct {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi long cmd;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi siginfo_t siginfo;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi } ctl;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int sentry; /* old value of stop-on-syscall-entry */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sentry = Psysentry(P, sysindex, TRUE); /* set stop-on-syscall-entry */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If not already blocked, block all signals now.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (memcmp(&P->status.pr_lwp.pr_lwphold, &blockable_sigs,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sizeof (sigset_t)) != 0) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi hold = P->status.pr_lwp.pr_lwphold;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->status.pr_lwp.pr_lwphold = blockable_sigs;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->flags |= SETHOLD;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi washeld = TRUE;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If there is a current signal, remember it and cancel it.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((cursig = P->status.pr_lwp.pr_cursig) != 0) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ctl.cmd = PCSSIG;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ctl.siginfo = P->status.pr_lwp.pr_info;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (Psetrun(P, 0, PRCSIG | PRCFAULT) == -1)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi while (P->state == PS_RUN) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) Pwait(P, 0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->state != PS_STOP)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (cursig) /* restore cursig */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) write(ctlfd, &ctl, sizeof (ctl));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (washeld) { /* restore the signal mask if we set it */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->status.pr_lwp.pr_lwphold = hold;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->flags |= SETHOLD;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) Psysentry(P, sysindex, sentry); /* restore sysentry stop */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->status.pr_lwp.pr_why == PR_SYSENTRY &&
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->status.pr_lwp.pr_what == sysindex)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad:
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (-1);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Perform system call in controlled process.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiint
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiPsyscall(struct ps_prochandle *P,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sysret_t *rval, /* syscall return values */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int sysindex, /* system call index */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi uint_t nargs, /* number of arguments to system call */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi argdes_t *argp) /* argument descriptor array */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int agent_created = FALSE;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi pstatus_t save_pstatus;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi argdes_t *adp; /* pointer to argument descriptor */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int i; /* general index value */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int model; /* data model */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int error = 0; /* syscall errno */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int Perr = 0; /* local error number */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int sexit; /* old value of stop-on-syscall-exit */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi prgreg_t sp; /* adjusted stack pointer */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi prgreg_t ap; /* adjusted argument pointer */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sigset_t unblock;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) sigprocmask(SIG_BLOCK, &blockable_sigs, &unblock);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval1 = 0; /* initialize return values */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval2 = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (sysindex <= 0 || sysindex > PRMAXSYS || nargs > MAXARGS)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad1; /* programming error */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->state == PS_DEAD || P->state == PS_UNDEAD || P->state == PS_IDLE)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad1; /* dead processes can't perform system calls */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi model = P->status.pr_dmodel;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#ifndef _LP64
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* We must be a 64-bit process to deal with a 64-bit process */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (model == PR_MODEL_LP64)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad9;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#endif
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Create the /proc agent LWP in the process to do all the work.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (It may already exist; nested create/destroy is permitted
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * by virtue of the reference count.)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (Pcreate_agent(P) != 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad8;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Save agent's status to restore on exit.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi agent_created = TRUE;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi save_pstatus = P->status;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->state != PS_STOP || /* check state of LWP */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (P->status.pr_flags & PR_ASLEEP))
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad2;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (Pscantext(P)) /* bad text ? */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad3;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Validate arguments and compute the stack frame parameters.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Begin with the current stack pointer.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#ifdef _LP64
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (model == PR_MODEL_LP64) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sp = P->status.pr_lwp.pr_reg[R_SP] + STACK_BIAS;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#if defined(__amd64)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * To offset the expense of computerised subtraction, the AMD64
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ABI allows a process the use of a 128-byte area beyond the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * location pointed to by %rsp. We must advance the agent's
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * stack pointer by at least the size of this region or else it
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * may corrupt this temporary storage.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sp -= STACK_RESERVE64;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#endif
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sp = PSTACK_ALIGN64(sp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi } else {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#endif
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sp = (uint32_t)P->status.pr_lwp.pr_reg[R_SP];
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sp = PSTACK_ALIGN32(sp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#ifdef _LP64
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#endif
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * For each AT_BYREF argument, compute the necessary
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * stack space and the object's stack address.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi for (i = 0, adp = argp; i < nargs; i++, adp++) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval1 = i; /* in case of error */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi switch (adp->arg_type) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi default: /* programming error */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad4;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi case AT_BYVAL: /* simple argument */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi break;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi case AT_BYREF: /* must allocate space */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi switch (adp->arg_inout) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi case AI_INPUT:
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi case AI_OUTPUT:
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi case AI_INOUT:
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (adp->arg_object == NULL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad5; /* programming error */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi break;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi default: /* programming error */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad6;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* allocate stack space for BYREF argument */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (adp->arg_size == 0 || adp->arg_size > MAXARGL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad7; /* programming error */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#ifdef _LP64
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (model == PR_MODEL_LP64)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sp = PSTACK_ALIGN64(sp - adp->arg_size);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi else
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#endif
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sp = PSTACK_ALIGN32(sp - adp->arg_size);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi adp->arg_value = sp; /* stack address for object */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi break;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval1 = 0; /* in case of error */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Point of no return.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Perform the system call entry, adjusting %sp.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * This moves the LWP to the stopped-on-syscall-entry state
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * just before the arguments to the system call are fetched.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ap = Psyscall_setup(P, nargs, sysindex, sp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->flags |= SETREGS; /* set registers before continuing */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("Psyscall(): execute(sysindex = %d)\n", sysindex);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Execute the syscall instruction and stop on syscall entry.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (execute(P, sysindex) != 0 ||
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (!Pissyscall(P, P->status.pr_lwp.pr_reg[R_PC]) &&
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi !Pissyscall_prev(P, P->status.pr_lwp.pr_reg[R_PC], NULL)))
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad10;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("Psyscall(): copying arguments\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The LWP is stopped at syscall entry.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Copy objects to stack frame for each argument.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi for (i = 0, adp = argp; i < nargs; i++, adp++) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval1 = i; /* in case of error */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (adp->arg_type != AT_BYVAL &&
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi adp->arg_inout != AI_OUTPUT) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* copy input byref parameter to process */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (Pwrite(P, adp->arg_object, adp->arg_size,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (uintptr_t)adp->arg_value) != adp->arg_size)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad17;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval1 = 0; /* in case of error */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (Psyscall_copyinargs(P, nargs, argp, ap) != 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad18;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Complete the system call.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * This moves the LWP to the stopped-on-syscall-exit state.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("Psyscall(): set running at sysentry\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sexit = Psysexit(P, sysindex, TRUE); /* catch this syscall exit */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi do {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (Psetrun(P, 0, 0) == -1)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad21;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi while (P->state == PS_RUN)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) Pwait(P, 0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi } while (P->state == PS_STOP && P->status.pr_lwp.pr_why != PR_SYSEXIT);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) Psysexit(P, sysindex, sexit); /* restore original setting */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If the system call was _lwp_exit(), we expect that our last call
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * to Pwait() will yield ENOENT because the LWP no longer exists.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (sysindex == SYS_lwp_exit && errno == ENOENT) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("Psyscall(): _lwp_exit successful\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval1 = rval->sys_rval2 = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto out;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->state != PS_STOP || P->status.pr_lwp.pr_why != PR_SYSEXIT)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad22;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->status.pr_lwp.pr_what != sysindex)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad23;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (!Pissyscall_prev(P, P->status.pr_lwp.pr_reg[R_PC], NULL)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("Pissyscall_prev() failed\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad24;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("Psyscall(): caught at sysexit\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * For each argument.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi for (i = 0, adp = argp; i < nargs; i++, adp++) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval1 = i; /* in case of error */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (adp->arg_type != AT_BYVAL &&
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi adp->arg_inout != AI_INPUT) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* copy output byref parameter from process */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (Pread(P, adp->arg_object, adp->arg_size,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (uintptr_t)adp->arg_value) != adp->arg_size)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad25;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (Psyscall_copyoutargs(P, nargs, argp, ap) != 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto bad26;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Get the return values from the syscall.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->status.pr_lwp.pr_errno) { /* error return */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi error = P->status.pr_lwp.pr_errno;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval1 = -1L;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval2 = -1L;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("Psyscall(%d) fails with errno %d\n",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sysindex, error);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi } else { /* normal return */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval1 = P->status.pr_lwp.pr_rval1;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rval->sys_rval2 = P->status.pr_lwp.pr_rval2;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("Psyscall(%d) returns 0x%lx 0x%lx\n", sysindex,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->status.pr_lwp.pr_rval1, P->status.pr_lwp.pr_rval2);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto out;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad26: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad25: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad24: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad23: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad22: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad21: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad18: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad17: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad10: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad9: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad8: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad7: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad6: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad5: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad4: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad3: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad2: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibad1: Perr++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi error = -1;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dprintf("Psyscall(%d) fails with local error %d\n", sysindex, Perr);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiout:
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Destroy the /proc agent LWP now (or just bump down the ref count).
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (agent_created) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (P->state != PS_UNDEAD) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->status = save_pstatus;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi P->flags |= SETREGS;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Psync(P);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi Pdestroy_agent(P);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) sigprocmask(SIG_SETMASK, &unblock, NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (error);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi