1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*0Sstevel@tonic-gate /* All Rights Reserved */ 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <stdio.h> 34*0Sstevel@tonic-gate #include <stdlib.h> 35*0Sstevel@tonic-gate #include <unistd.h> 36*0Sstevel@tonic-gate #include <ctype.h> 37*0Sstevel@tonic-gate #include <string.h> 38*0Sstevel@tonic-gate #include <signal.h> 39*0Sstevel@tonic-gate #include <stropts.h> 40*0Sstevel@tonic-gate #include <errno.h> 41*0Sstevel@tonic-gate #include <sys/types.h> 42*0Sstevel@tonic-gate #include <sys/termio.h> 43*0Sstevel@tonic-gate #include <libproc.h> 44*0Sstevel@tonic-gate #include "ramdata.h" 45*0Sstevel@tonic-gate #include "proto.h" 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate /* 48*0Sstevel@tonic-gate * Routines related to interprocess communication 49*0Sstevel@tonic-gate * among the truss processes which are controlling 50*0Sstevel@tonic-gate * multiple traced processes. 51*0Sstevel@tonic-gate */ 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate /* 54*0Sstevel@tonic-gate * Function prototypes for static routines in this module. 55*0Sstevel@tonic-gate */ 56*0Sstevel@tonic-gate void Ecritical(int); 57*0Sstevel@tonic-gate void Xcritical(int); 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate /* 60*0Sstevel@tonic-gate * Ensure everyone keeps out of each other's way 61*0Sstevel@tonic-gate * while writing lines of trace output. 62*0Sstevel@tonic-gate */ 63*0Sstevel@tonic-gate void 64*0Sstevel@tonic-gate Flush() 65*0Sstevel@tonic-gate { 66*0Sstevel@tonic-gate /* 67*0Sstevel@tonic-gate * Except for regions bounded by Eserialize()/Xserialize(), 68*0Sstevel@tonic-gate * this is the only place anywhere in the program where a 69*0Sstevel@tonic-gate * write() to the trace output file takes place, so here 70*0Sstevel@tonic-gate * is where we detect errors writing to the output. 71*0Sstevel@tonic-gate */ 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate errno = 0; 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate Ecritical(0); 76*0Sstevel@tonic-gate (void) fflush(stdout); 77*0Sstevel@tonic-gate Xcritical(0); 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate if (ferror(stdout) && errno) /* error on write(), probably EPIPE */ 80*0Sstevel@tonic-gate interrupt = SIGTERM; /* post an interrupt */ 81*0Sstevel@tonic-gate } 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate /* 84*0Sstevel@tonic-gate * Eserialize() and Xserialize() are used to bracket 85*0Sstevel@tonic-gate * a region which may produce large amounts of output, 86*0Sstevel@tonic-gate * such as showargs()/dumpargs(). 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate void 90*0Sstevel@tonic-gate Eserialize() 91*0Sstevel@tonic-gate { 92*0Sstevel@tonic-gate /* serialize output */ 93*0Sstevel@tonic-gate Ecritical(0); 94*0Sstevel@tonic-gate } 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate void 97*0Sstevel@tonic-gate Xserialize() 98*0Sstevel@tonic-gate { 99*0Sstevel@tonic-gate (void) fflush(stdout); 100*0Sstevel@tonic-gate Xcritical(0); 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate /* 104*0Sstevel@tonic-gate * Enter critical region --- Wait on mutex, lock out other processes. 105*0Sstevel@tonic-gate * Lock zero is used to serialize output in situations where multiple processes 106*0Sstevel@tonic-gate * may be writing to stdout/stderr and order must be preserved. Most of these 107*0Sstevel@tonic-gate * are in expound.c 108*0Sstevel@tonic-gate * Lock one is used to protect the table of processes currently being traced 109*0Sstevel@tonic-gate * every time a pid is added or removed from the table Ecritical(1)/Xcritical(1) 110*0Sstevel@tonic-gate * get called. 111*0Sstevel@tonic-gate */ 112*0Sstevel@tonic-gate void 113*0Sstevel@tonic-gate Ecritical(int num) 114*0Sstevel@tonic-gate { 115*0Sstevel@tonic-gate int rv; 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate if (num == 0) 118*0Sstevel@tonic-gate rv = mutex_lock(&gps->ps_mutex0); 119*0Sstevel@tonic-gate else if (num == 1) 120*0Sstevel@tonic-gate rv = mutex_lock(&gps->ps_mutex1); 121*0Sstevel@tonic-gate else 122*0Sstevel@tonic-gate abend("Invalid mutex specified", NULL); 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate if (rv != 0) { 125*0Sstevel@tonic-gate char mnum[2]; 126*0Sstevel@tonic-gate mnum[0] = '0' + num; 127*0Sstevel@tonic-gate mnum[1] = '\0'; 128*0Sstevel@tonic-gate errno = rv; 129*0Sstevel@tonic-gate perror(command); 130*0Sstevel@tonic-gate errmsg("cannot grab mutex #", mnum); 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate /* 135*0Sstevel@tonic-gate * Exit critical region --- 136*0Sstevel@tonic-gate * Release other processes waiting on mutex. 137*0Sstevel@tonic-gate */ 138*0Sstevel@tonic-gate void 139*0Sstevel@tonic-gate Xcritical(int num) 140*0Sstevel@tonic-gate { 141*0Sstevel@tonic-gate int rv; 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate if (num == 0) 144*0Sstevel@tonic-gate rv = mutex_unlock(&gps->ps_mutex0); 145*0Sstevel@tonic-gate else if (num == 1) 146*0Sstevel@tonic-gate rv = mutex_unlock(&gps->ps_mutex1); 147*0Sstevel@tonic-gate else 148*0Sstevel@tonic-gate abend("Invalid mutex specified", NULL); 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate if (rv != 0) { 152*0Sstevel@tonic-gate char mnum[2]; 153*0Sstevel@tonic-gate mnum[0] = '0' + num; 154*0Sstevel@tonic-gate mnum[1] = '\0'; 155*0Sstevel@tonic-gate errno = rv; 156*0Sstevel@tonic-gate perror(command); 157*0Sstevel@tonic-gate errmsg("cannot release mutex #", mnum); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate } 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate /* 162*0Sstevel@tonic-gate * Add process to set of those being traced. 163*0Sstevel@tonic-gate */ 164*0Sstevel@tonic-gate void 165*0Sstevel@tonic-gate procadd(pid_t spid, const char *lwplist) 166*0Sstevel@tonic-gate { 167*0Sstevel@tonic-gate int i; 168*0Sstevel@tonic-gate int j = -1; 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate if (gps == NULL) 171*0Sstevel@tonic-gate return; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate Ecritical(1); 174*0Sstevel@tonic-gate for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) { 175*0Sstevel@tonic-gate if (gps->tpid[i] == 0) { 176*0Sstevel@tonic-gate if (j == -1) /* remember first vacant slot */ 177*0Sstevel@tonic-gate j = i; 178*0Sstevel@tonic-gate if (gps->spid[i] == 0) /* this slot is better */ 179*0Sstevel@tonic-gate break; 180*0Sstevel@tonic-gate } 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate if (i < sizeof (gps->tpid) / sizeof (gps->tpid[0])) 183*0Sstevel@tonic-gate j = i; 184*0Sstevel@tonic-gate if (j >= 0) { 185*0Sstevel@tonic-gate gps->tpid[j] = getpid(); 186*0Sstevel@tonic-gate gps->spid[j] = spid; 187*0Sstevel@tonic-gate gps->lwps[j] = lwplist; 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate Xcritical(1); 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate /* 193*0Sstevel@tonic-gate * Delete process from set of those being traced. 194*0Sstevel@tonic-gate */ 195*0Sstevel@tonic-gate void 196*0Sstevel@tonic-gate procdel() 197*0Sstevel@tonic-gate { 198*0Sstevel@tonic-gate int i; 199*0Sstevel@tonic-gate pid_t tpid; 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate if (gps == NULL) 202*0Sstevel@tonic-gate return; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate tpid = getpid(); 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate Ecritical(1); 207*0Sstevel@tonic-gate for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) { 208*0Sstevel@tonic-gate if (gps->tpid[i] == tpid) { 209*0Sstevel@tonic-gate gps->tpid[i] = 0; 210*0Sstevel@tonic-gate break; 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate Xcritical(1); 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate /* 217*0Sstevel@tonic-gate * Determine if the lwp for this process should be traced. 218*0Sstevel@tonic-gate */ 219*0Sstevel@tonic-gate int 220*0Sstevel@tonic-gate lwptrace(pid_t spid, lwpid_t lwpid) 221*0Sstevel@tonic-gate { 222*0Sstevel@tonic-gate int i; 223*0Sstevel@tonic-gate pid_t tpid; 224*0Sstevel@tonic-gate const char *lwps; 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate if (gps == NULL) 227*0Sstevel@tonic-gate return (0); 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate tpid = getpid(); 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate Ecritical(1); 232*0Sstevel@tonic-gate for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) { 233*0Sstevel@tonic-gate if (gps->tpid[i] == tpid && 234*0Sstevel@tonic-gate gps->spid[i] == spid) 235*0Sstevel@tonic-gate break; 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate lwps = gps->lwps[i]; 238*0Sstevel@tonic-gate Xcritical(1); 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate return (proc_lwp_in_set(lwps, lwpid)); 241*0Sstevel@tonic-gate } 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate /* 244*0Sstevel@tonic-gate * Check for open of a /proc/nnnnn file. 245*0Sstevel@tonic-gate * Return 0 if this is not an open of a /proc file. 246*0Sstevel@tonic-gate * Return 1 if the process opened itself. 247*0Sstevel@tonic-gate * Return 2 if the process failed to open another process 248*0Sstevel@tonic-gate * in truss's set of controlled processes. 249*0Sstevel@tonic-gate * Return 3 if the process successfully opened another process 250*0Sstevel@tonic-gate * in truss's set of controlled processes. 251*0Sstevel@tonic-gate * We notify and wait for the other controlling truss process 252*0Sstevel@tonic-gate * to terminate before returning in cases 2 and 3. 253*0Sstevel@tonic-gate */ 254*0Sstevel@tonic-gate /* ARGSUSED */ 255*0Sstevel@tonic-gate int 256*0Sstevel@tonic-gate checkproc(private_t *pri) 257*0Sstevel@tonic-gate { 258*0Sstevel@tonic-gate char *path = pri->sys_path; 259*0Sstevel@tonic-gate const pstatus_t *Psp = Pstatus(Proc); 260*0Sstevel@tonic-gate struct ps_lwphandle *Lwp = pri->Lwp; 261*0Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 262*0Sstevel@tonic-gate int what = Lsp->pr_what; /* SYS_open or SYS_open64 */ 263*0Sstevel@tonic-gate int err = Lsp->pr_errno; 264*0Sstevel@tonic-gate int pid; 265*0Sstevel@tonic-gate int i; 266*0Sstevel@tonic-gate const char *dirname; 267*0Sstevel@tonic-gate char *next; 268*0Sstevel@tonic-gate char *sp1; 269*0Sstevel@tonic-gate char *sp2; 270*0Sstevel@tonic-gate prgreg_t pc; 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate /* 273*0Sstevel@tonic-gate * A bit heuristic ... 274*0Sstevel@tonic-gate * Test for the cases: 275*0Sstevel@tonic-gate * 1234 276*0Sstevel@tonic-gate * 1234/as 277*0Sstevel@tonic-gate * 1234/ctl 278*0Sstevel@tonic-gate * 1234/lwp/24/lwpctl 279*0Sstevel@tonic-gate * .../1234 280*0Sstevel@tonic-gate * .../1234/as 281*0Sstevel@tonic-gate * .../1234/ctl 282*0Sstevel@tonic-gate * .../1234/lwp/24/lwpctl 283*0Sstevel@tonic-gate * Insert a '\0', if necessary, so the path becomes ".../1234". 284*0Sstevel@tonic-gate * 285*0Sstevel@tonic-gate * Along the way, watch out for /proc/self and /proc/1234/lwp/agent 286*0Sstevel@tonic-gate */ 287*0Sstevel@tonic-gate if ((sp1 = strrchr(path, '/')) == NULL) /* last component */ 288*0Sstevel@tonic-gate /* EMPTY */; 289*0Sstevel@tonic-gate else if (isdigit(*(sp1+1))) { 290*0Sstevel@tonic-gate sp1 += strlen(sp1); 291*0Sstevel@tonic-gate while (--sp1 > path && isdigit(*sp1)) 292*0Sstevel@tonic-gate ; 293*0Sstevel@tonic-gate if (*sp1 != '/') 294*0Sstevel@tonic-gate return (0); 295*0Sstevel@tonic-gate } else if (strcmp(sp1+1, "as") == 0 || 296*0Sstevel@tonic-gate strcmp(sp1+1, "ctl") == 0) { 297*0Sstevel@tonic-gate *sp1 = '\0'; 298*0Sstevel@tonic-gate } else if (strcmp(sp1+1, "lwpctl") == 0) { 299*0Sstevel@tonic-gate /* 300*0Sstevel@tonic-gate * .../1234/lwp/24/lwpctl 301*0Sstevel@tonic-gate * ............ ^-- sp1 302*0Sstevel@tonic-gate */ 303*0Sstevel@tonic-gate if (sp1-6 >= path && strncmp(sp1-6, "/agent", 6) == 0) 304*0Sstevel@tonic-gate sp1 -= 6; 305*0Sstevel@tonic-gate else { 306*0Sstevel@tonic-gate while (--sp1 > path && isdigit(*sp1)) 307*0Sstevel@tonic-gate ; 308*0Sstevel@tonic-gate } 309*0Sstevel@tonic-gate if (*sp1 != '/' || 310*0Sstevel@tonic-gate (sp1 -= 4) <= path || 311*0Sstevel@tonic-gate strncmp(sp1, "/lwp", 4) != 0) 312*0Sstevel@tonic-gate return (0); 313*0Sstevel@tonic-gate *sp1 = '\0'; 314*0Sstevel@tonic-gate } else if (strcmp(sp1+1, "self") != 0) { 315*0Sstevel@tonic-gate return (0); 316*0Sstevel@tonic-gate } 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate if ((sp2 = strrchr(path, '/')) == NULL) 319*0Sstevel@tonic-gate dirname = path; 320*0Sstevel@tonic-gate else 321*0Sstevel@tonic-gate dirname = sp2 + 1; 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate if (strcmp(dirname, "self") == 0) { 324*0Sstevel@tonic-gate pid = Psp->pr_pid; 325*0Sstevel@tonic-gate } else if ((pid = strtol(dirname, &next, 10)) < 0 || 326*0Sstevel@tonic-gate *next != '\0') { /* dirname not a number */ 327*0Sstevel@tonic-gate if (sp1 != NULL) 328*0Sstevel@tonic-gate *sp1 = '/'; 329*0Sstevel@tonic-gate return (0); 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate if (sp2 == NULL) 332*0Sstevel@tonic-gate dirname = "."; 333*0Sstevel@tonic-gate else { 334*0Sstevel@tonic-gate *sp2 = '\0'; 335*0Sstevel@tonic-gate dirname = path; 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate if (!Pisprocdir(Proc, dirname) || /* file not in a /proc directory */ 339*0Sstevel@tonic-gate pid == getpid() || /* process opened truss's /proc file */ 340*0Sstevel@tonic-gate pid == 0) { /* process opened process 0 */ 341*0Sstevel@tonic-gate if (sp1 != NULL) 342*0Sstevel@tonic-gate *sp1 = '/'; 343*0Sstevel@tonic-gate if (sp2 != NULL) 344*0Sstevel@tonic-gate *sp2 = '/'; 345*0Sstevel@tonic-gate return (0); 346*0Sstevel@tonic-gate } 347*0Sstevel@tonic-gate if (sp1 != NULL) 348*0Sstevel@tonic-gate *sp1 = '/'; 349*0Sstevel@tonic-gate if (sp2 != NULL) 350*0Sstevel@tonic-gate *sp2 = '/'; 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate /* 353*0Sstevel@tonic-gate * Process did open a /proc file --- 354*0Sstevel@tonic-gate */ 355*0Sstevel@tonic-gate if (pid == Psp->pr_pid) { /* process opened its own /proc file */ 356*0Sstevel@tonic-gate /* 357*0Sstevel@tonic-gate * In SunOS 5.6 and beyond, self-opens always succeed. 358*0Sstevel@tonic-gate */ 359*0Sstevel@tonic-gate return (1); 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate /* 363*0Sstevel@tonic-gate * Search for a matching pid in our set of controlled processes. 364*0Sstevel@tonic-gate */ 365*0Sstevel@tonic-gate for (i = 0; i < sizeof (gps->tpid)/sizeof (gps->tpid[0]); i++) { 366*0Sstevel@tonic-gate if (gps->spid[i] == pid) { 367*0Sstevel@tonic-gate pid = gps->tpid[i]; 368*0Sstevel@tonic-gate break; 369*0Sstevel@tonic-gate } 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate if (i >= sizeof (gps->tpid) / sizeof (gps->tpid[0])) { 372*0Sstevel@tonic-gate /* 373*0Sstevel@tonic-gate * The process opened a /proc file, but not one we care about. 374*0Sstevel@tonic-gate */ 375*0Sstevel@tonic-gate return (0); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate /* 379*0Sstevel@tonic-gate * Notify and wait for the controlling process to terminate. 380*0Sstevel@tonic-gate */ 381*0Sstevel@tonic-gate while (pid && gps->tpid[i] == pid) { 382*0Sstevel@tonic-gate if (kill(pid, SIGUSR1) == -1) 383*0Sstevel@tonic-gate break; 384*0Sstevel@tonic-gate (void) usleep(1000000); 385*0Sstevel@tonic-gate } 386*0Sstevel@tonic-gate Ecritical(1); 387*0Sstevel@tonic-gate if (gps->tpid[i] == 0) 388*0Sstevel@tonic-gate gps->spid[i] = 0; 389*0Sstevel@tonic-gate Xcritical(1); 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate if (err) { /* prepare to reissue the failed open() system call */ 392*0Sstevel@tonic-gate #if defined(__sparc) 393*0Sstevel@tonic-gate (void) Lgetareg(Lwp, R_PC, &pc); 394*0Sstevel@tonic-gate if (pri->sys_indirect) { 395*0Sstevel@tonic-gate (void) Lputareg(Lwp, R_G1, (prgreg_t)SYS_syscall); 396*0Sstevel@tonic-gate (void) Lputareg(Lwp, R_O0, (prgreg_t)what); 397*0Sstevel@tonic-gate for (i = 0; i < 5; i++) 398*0Sstevel@tonic-gate (void) Lputareg(Lwp, R_O1+i, pri->sys_args[i]); 399*0Sstevel@tonic-gate } else { 400*0Sstevel@tonic-gate (void) Lputareg(Lwp, R_G1, (prgreg_t)what); 401*0Sstevel@tonic-gate for (i = 0; i < 6; i++) 402*0Sstevel@tonic-gate (void) Lputareg(Lwp, R_O0+i, pri->sys_args[i]); 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate (void) Lputareg(Lwp, R_nPC, pc); 405*0Sstevel@tonic-gate #elif defined(__amd64) 406*0Sstevel@tonic-gate (void) Lgetareg(Lwp, R_PC, &pc); 407*0Sstevel@tonic-gate (void) Lputareg(Lwp, REG_RAX, (prgreg_t)what); 408*0Sstevel@tonic-gate #elif defined(__i386) 409*0Sstevel@tonic-gate (void) Lgetareg(Lwp, R_PC, &pc); 410*0Sstevel@tonic-gate (void) Lputareg(Lwp, EAX, (prgreg_t)what); 411*0Sstevel@tonic-gate #else 412*0Sstevel@tonic-gate #error "unrecognized architecture" 413*0Sstevel@tonic-gate #endif 414*0Sstevel@tonic-gate (void) Pissyscall_prev(Proc, pc, (uintptr_t *)&pc); 415*0Sstevel@tonic-gate (void) Lputareg(Lwp, R_PC, pc); 416*0Sstevel@tonic-gate return (2); 417*0Sstevel@tonic-gate } 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate return (3); 420*0Sstevel@tonic-gate } 421