1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*7c478bd9Sstevel@tonic-gate #include <unistd.h> 36*7c478bd9Sstevel@tonic-gate #include <ctype.h> 37*7c478bd9Sstevel@tonic-gate #include <string.h> 38*7c478bd9Sstevel@tonic-gate #include <memory.h> 39*7c478bd9Sstevel@tonic-gate #include <errno.h> 40*7c478bd9Sstevel@tonic-gate #include <limits.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/stack.h> 43*7c478bd9Sstevel@tonic-gate #include <signal.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h> 45*7c478bd9Sstevel@tonic-gate #include <libproc.h> 46*7c478bd9Sstevel@tonic-gate #include <priv.h> 47*7c478bd9Sstevel@tonic-gate #include "ramdata.h" 48*7c478bd9Sstevel@tonic-gate #include "systable.h" 49*7c478bd9Sstevel@tonic-gate #include "print.h" 50*7c478bd9Sstevel@tonic-gate #include "proto.h" 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate /* 53*7c478bd9Sstevel@tonic-gate * Actions to take when process stops. 54*7c478bd9Sstevel@tonic-gate */ 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate /* 57*7c478bd9Sstevel@tonic-gate * Function prototypes for static routines in this module. 58*7c478bd9Sstevel@tonic-gate */ 59*7c478bd9Sstevel@tonic-gate int stopsig(private_t *); 60*7c478bd9Sstevel@tonic-gate void showpaths(private_t *, const struct systable *); 61*7c478bd9Sstevel@tonic-gate void showargs(private_t *, int); 62*7c478bd9Sstevel@tonic-gate void dumpargs(private_t *, long, const char *); 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* 65*7c478bd9Sstevel@tonic-gate * Report an lwp to be sleeping (if true). 66*7c478bd9Sstevel@tonic-gate */ 67*7c478bd9Sstevel@tonic-gate void 68*7c478bd9Sstevel@tonic-gate report_sleeping(private_t *pri, int dotrace) 69*7c478bd9Sstevel@tonic-gate { 70*7c478bd9Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 71*7c478bd9Sstevel@tonic-gate int sys = Lsp->pr_syscall; 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate if (!prismember(&trace, sys) || !dotrace || 74*7c478bd9Sstevel@tonic-gate !(Lsp->pr_flags & (PR_ASLEEP|PR_VFORKP))) { 75*7c478bd9Sstevel@tonic-gate /* Make sure we catch sysexit even if we're not tracing it. */ 76*7c478bd9Sstevel@tonic-gate (void) Psysexit(Proc, sys, TRUE); 77*7c478bd9Sstevel@tonic-gate return; 78*7c478bd9Sstevel@tonic-gate } 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate pri->length = 0; 81*7c478bd9Sstevel@tonic-gate pri->Errno = 0; 82*7c478bd9Sstevel@tonic-gate pri->ErrPriv = PRIV_NONE; 83*7c478bd9Sstevel@tonic-gate pri->Rval1 = pri->Rval2 = 0; 84*7c478bd9Sstevel@tonic-gate (void) sysentry(pri, dotrace); 85*7c478bd9Sstevel@tonic-gate make_pname(pri, 0); 86*7c478bd9Sstevel@tonic-gate putpname(pri); 87*7c478bd9Sstevel@tonic-gate timestamp(pri); 88*7c478bd9Sstevel@tonic-gate pri->length += printf("%s", pri->sys_string); 89*7c478bd9Sstevel@tonic-gate pri->sys_leng = 0; 90*7c478bd9Sstevel@tonic-gate *pri->sys_string = '\0'; 91*7c478bd9Sstevel@tonic-gate pri->length >>= 3; 92*7c478bd9Sstevel@tonic-gate if (Lsp->pr_flags & PR_VFORKP) 93*7c478bd9Sstevel@tonic-gate pri->length += 2; 94*7c478bd9Sstevel@tonic-gate if (pri->length >= 4) 95*7c478bd9Sstevel@tonic-gate (void) fputc(' ', stdout); 96*7c478bd9Sstevel@tonic-gate for (; pri->length < 4; pri->length++) 97*7c478bd9Sstevel@tonic-gate (void) fputc('\t', stdout); 98*7c478bd9Sstevel@tonic-gate if (Lsp->pr_flags & PR_VFORKP) 99*7c478bd9Sstevel@tonic-gate (void) fputs("(waiting for child to exit()/exec()...)\n", 100*7c478bd9Sstevel@tonic-gate stdout); 101*7c478bd9Sstevel@tonic-gate else 102*7c478bd9Sstevel@tonic-gate (void) fputs("(sleeping...)\n", stdout); 103*7c478bd9Sstevel@tonic-gate pri->length = 0; 104*7c478bd9Sstevel@tonic-gate if (prismember(&verbose, sys)) { 105*7c478bd9Sstevel@tonic-gate int raw = prismember(&rawout, sys); 106*7c478bd9Sstevel@tonic-gate pri->Errno = 1; 107*7c478bd9Sstevel@tonic-gate expound(pri, 0, raw); 108*7c478bd9Sstevel@tonic-gate pri->Errno = 0; 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate Flush(); 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * requested() gets called for these reasons: 115*7c478bd9Sstevel@tonic-gate * flag == JOBSIG: report nothing; change state to JOBSTOP 116*7c478bd9Sstevel@tonic-gate * flag == JOBSTOP: report "Continued ..." 117*7c478bd9Sstevel@tonic-gate * default: report sleeping system call 118*7c478bd9Sstevel@tonic-gate * 119*7c478bd9Sstevel@tonic-gate * It returns a new flag: JOBSTOP or SLEEPING or 0. 120*7c478bd9Sstevel@tonic-gate */ 121*7c478bd9Sstevel@tonic-gate int 122*7c478bd9Sstevel@tonic-gate requested(private_t *pri, int flag, int dotrace) 123*7c478bd9Sstevel@tonic-gate { 124*7c478bd9Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 125*7c478bd9Sstevel@tonic-gate int sig = Lsp->pr_cursig; 126*7c478bd9Sstevel@tonic-gate int newflag = 0; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate switch (flag) { 129*7c478bd9Sstevel@tonic-gate case JOBSIG: 130*7c478bd9Sstevel@tonic-gate return (JOBSTOP); 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate case JOBSTOP: 133*7c478bd9Sstevel@tonic-gate if (dotrace && !cflag && prismember(&signals, sig)) { 134*7c478bd9Sstevel@tonic-gate pri->length = 0; 135*7c478bd9Sstevel@tonic-gate putpname(pri); 136*7c478bd9Sstevel@tonic-gate timestamp(pri); 137*7c478bd9Sstevel@tonic-gate (void) printf(" Continued with signal #%d, %s", 138*7c478bd9Sstevel@tonic-gate sig, signame(pri, sig)); 139*7c478bd9Sstevel@tonic-gate if (Lsp->pr_action.sa_handler == SIG_DFL) 140*7c478bd9Sstevel@tonic-gate (void) printf(" [default]"); 141*7c478bd9Sstevel@tonic-gate else if (Lsp->pr_action.sa_handler == SIG_IGN) 142*7c478bd9Sstevel@tonic-gate (void) printf(" [ignored]"); 143*7c478bd9Sstevel@tonic-gate else 144*7c478bd9Sstevel@tonic-gate (void) printf(" [caught]"); 145*7c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 146*7c478bd9Sstevel@tonic-gate Flush(); 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate newflag = 0; 149*7c478bd9Sstevel@tonic-gate break; 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate default: 152*7c478bd9Sstevel@tonic-gate newflag = SLEEPING; 153*7c478bd9Sstevel@tonic-gate if (!cflag) 154*7c478bd9Sstevel@tonic-gate report_sleeping(pri, dotrace); 155*7c478bd9Sstevel@tonic-gate break; 156*7c478bd9Sstevel@tonic-gate } 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate return (newflag); 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate int 162*7c478bd9Sstevel@tonic-gate jobcontrol(private_t *pri, int dotrace) 163*7c478bd9Sstevel@tonic-gate { 164*7c478bd9Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 165*7c478bd9Sstevel@tonic-gate int sig = stopsig(pri); 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate if (sig == 0) 168*7c478bd9Sstevel@tonic-gate return (0); 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate if (dotrace && !cflag && /* not just counting */ 171*7c478bd9Sstevel@tonic-gate prismember(&signals, sig)) { /* tracing this signal */ 172*7c478bd9Sstevel@tonic-gate int sys; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate pri->length = 0; 175*7c478bd9Sstevel@tonic-gate putpname(pri); 176*7c478bd9Sstevel@tonic-gate timestamp(pri); 177*7c478bd9Sstevel@tonic-gate (void) printf(" Stopped by signal #%d, %s", 178*7c478bd9Sstevel@tonic-gate sig, signame(pri, sig)); 179*7c478bd9Sstevel@tonic-gate if ((Lsp->pr_flags & PR_ASLEEP) && 180*7c478bd9Sstevel@tonic-gate (sys = Lsp->pr_syscall) > 0 && sys <= PRMAXSYS) 181*7c478bd9Sstevel@tonic-gate (void) printf(", in %s()", 182*7c478bd9Sstevel@tonic-gate sysname(pri, sys, getsubcode(pri))); 183*7c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 184*7c478bd9Sstevel@tonic-gate Flush(); 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate return (JOBSTOP); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate /* 191*7c478bd9Sstevel@tonic-gate * Return the signal the process stopped on iff process is already stopped on 192*7c478bd9Sstevel@tonic-gate * PR_JOBCONTROL or is stopped on PR_SIGNALLED or PR_REQUESTED with a current 193*7c478bd9Sstevel@tonic-gate * signal that will cause a JOBCONTROL stop when the process is set running. 194*7c478bd9Sstevel@tonic-gate */ 195*7c478bd9Sstevel@tonic-gate int 196*7c478bd9Sstevel@tonic-gate stopsig(private_t *pri) 197*7c478bd9Sstevel@tonic-gate { 198*7c478bd9Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 199*7c478bd9Sstevel@tonic-gate int sig = 0; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate if (Lsp->pr_flags & PR_STOPPED) { 202*7c478bd9Sstevel@tonic-gate switch (Lsp->pr_why) { 203*7c478bd9Sstevel@tonic-gate case PR_JOBCONTROL: 204*7c478bd9Sstevel@tonic-gate sig = Lsp->pr_what; 205*7c478bd9Sstevel@tonic-gate if (sig < 0 || sig > PRMAXSIG) 206*7c478bd9Sstevel@tonic-gate sig = 0; 207*7c478bd9Sstevel@tonic-gate break; 208*7c478bd9Sstevel@tonic-gate case PR_SIGNALLED: 209*7c478bd9Sstevel@tonic-gate case PR_REQUESTED: 210*7c478bd9Sstevel@tonic-gate if (Lsp->pr_action.sa_handler == SIG_DFL) { 211*7c478bd9Sstevel@tonic-gate switch (Lsp->pr_cursig) { 212*7c478bd9Sstevel@tonic-gate case SIGSTOP: 213*7c478bd9Sstevel@tonic-gate sig = SIGSTOP; 214*7c478bd9Sstevel@tonic-gate break; 215*7c478bd9Sstevel@tonic-gate case SIGTSTP: 216*7c478bd9Sstevel@tonic-gate case SIGTTIN: 217*7c478bd9Sstevel@tonic-gate case SIGTTOU: 218*7c478bd9Sstevel@tonic-gate if (!(Lsp->pr_flags & PR_ORPHAN)) 219*7c478bd9Sstevel@tonic-gate sig = Lsp->pr_cursig; 220*7c478bd9Sstevel@tonic-gate break; 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate break; 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate return (sig); 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate int 231*7c478bd9Sstevel@tonic-gate signalled(private_t *pri, int flag, int dotrace) 232*7c478bd9Sstevel@tonic-gate { 233*7c478bd9Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 234*7c478bd9Sstevel@tonic-gate int sig = Lsp->pr_what; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate if (sig <= 0 || sig > PRMAXSIG) /* check bounds */ 237*7c478bd9Sstevel@tonic-gate return (0); 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate if (dotrace && cflag) { /* just counting */ 240*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&count_lock); 241*7c478bd9Sstevel@tonic-gate Cp->sigcount[sig]++; 242*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&count_lock); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate if (sig == SIGCONT && (flag == JOBSIG || flag == JOBSTOP)) 246*7c478bd9Sstevel@tonic-gate flag = requested(pri, JOBSTOP, dotrace); 247*7c478bd9Sstevel@tonic-gate else if ((flag = jobcontrol(pri, dotrace)) == 0 && 248*7c478bd9Sstevel@tonic-gate !cflag && dotrace && 249*7c478bd9Sstevel@tonic-gate prismember(&signals, sig)) { 250*7c478bd9Sstevel@tonic-gate int sys; 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate pri->length = 0; 253*7c478bd9Sstevel@tonic-gate putpname(pri); 254*7c478bd9Sstevel@tonic-gate timestamp(pri); 255*7c478bd9Sstevel@tonic-gate (void) printf(" Received signal #%d, %s", 256*7c478bd9Sstevel@tonic-gate sig, signame(pri, sig)); 257*7c478bd9Sstevel@tonic-gate if ((Lsp->pr_flags & PR_ASLEEP) && 258*7c478bd9Sstevel@tonic-gate (sys = Lsp->pr_syscall) > 0 && sys <= PRMAXSYS) 259*7c478bd9Sstevel@tonic-gate (void) printf(", in %s()", 260*7c478bd9Sstevel@tonic-gate sysname(pri, sys, getsubcode(pri))); 261*7c478bd9Sstevel@tonic-gate if (Lsp->pr_action.sa_handler == SIG_DFL) 262*7c478bd9Sstevel@tonic-gate (void) printf(" [default]"); 263*7c478bd9Sstevel@tonic-gate else if (Lsp->pr_action.sa_handler == SIG_IGN) 264*7c478bd9Sstevel@tonic-gate (void) printf(" [ignored]"); 265*7c478bd9Sstevel@tonic-gate else 266*7c478bd9Sstevel@tonic-gate (void) printf(" [caught]"); 267*7c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 268*7c478bd9Sstevel@tonic-gate if (Lsp->pr_info.si_code != 0 || 269*7c478bd9Sstevel@tonic-gate Lsp->pr_info.si_pid != 0) 270*7c478bd9Sstevel@tonic-gate print_siginfo(pri, &Lsp->pr_info); 271*7c478bd9Sstevel@tonic-gate Flush(); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate if (flag == JOBSTOP) 275*7c478bd9Sstevel@tonic-gate flag = JOBSIG; 276*7c478bd9Sstevel@tonic-gate return (flag); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate int 280*7c478bd9Sstevel@tonic-gate faulted(private_t *pri, int dotrace) 281*7c478bd9Sstevel@tonic-gate { 282*7c478bd9Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 283*7c478bd9Sstevel@tonic-gate int flt = Lsp->pr_what; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate if ((uint_t)flt > PRMAXFAULT || !prismember(&faults, flt) || !dotrace) 286*7c478bd9Sstevel@tonic-gate return (0); 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&count_lock); 289*7c478bd9Sstevel@tonic-gate Cp->fltcount[flt]++; 290*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&count_lock); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate if (cflag) /* just counting */ 293*7c478bd9Sstevel@tonic-gate return (1); 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate pri->length = 0; 296*7c478bd9Sstevel@tonic-gate putpname(pri); 297*7c478bd9Sstevel@tonic-gate timestamp(pri); 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate (void) printf(" Incurred fault #%d, %s %%pc = 0x%.8lX", 300*7c478bd9Sstevel@tonic-gate flt, proc_fltname(flt, pri->flt_name, sizeof (pri->flt_name)), 301*7c478bd9Sstevel@tonic-gate (long)Lsp->pr_reg[R_PC]); 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate if (flt == FLTPAGE) 304*7c478bd9Sstevel@tonic-gate (void) printf(" addr = 0x%.8lX", 305*7c478bd9Sstevel@tonic-gate (long)Lsp->pr_info.si_addr); 306*7c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 307*7c478bd9Sstevel@tonic-gate if (Lsp->pr_info.si_signo != 0) 308*7c478bd9Sstevel@tonic-gate print_siginfo(pri, &Lsp->pr_info); 309*7c478bd9Sstevel@tonic-gate Flush(); 310*7c478bd9Sstevel@tonic-gate return (1); 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate /* 314*7c478bd9Sstevel@tonic-gate * Set up pri->sys_nargs and pri->sys_args[] (syscall args). 315*7c478bd9Sstevel@tonic-gate */ 316*7c478bd9Sstevel@tonic-gate void 317*7c478bd9Sstevel@tonic-gate setupsysargs(private_t *pri, int what) 318*7c478bd9Sstevel@tonic-gate { 319*7c478bd9Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 320*7c478bd9Sstevel@tonic-gate int nargs; 321*7c478bd9Sstevel@tonic-gate int i; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate #if sparc 324*7c478bd9Sstevel@tonic-gate /* determine whether syscall is indirect */ 325*7c478bd9Sstevel@tonic-gate pri->sys_indirect = (Lsp->pr_reg[R_G1] == SYS_syscall)? 1 : 0; 326*7c478bd9Sstevel@tonic-gate #else 327*7c478bd9Sstevel@tonic-gate pri->sys_indirect = 0; 328*7c478bd9Sstevel@tonic-gate #endif 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate (void) memset(pri->sys_args, 0, sizeof (pri->sys_args)); 331*7c478bd9Sstevel@tonic-gate if (what != Lsp->pr_syscall) { /* assertion */ 332*7c478bd9Sstevel@tonic-gate (void) printf("%s\t*** Inconsistent syscall: %d vs %d ***\n", 333*7c478bd9Sstevel@tonic-gate pri->pname, what, Lsp->pr_syscall); 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate nargs = Lsp->pr_nsysarg; 336*7c478bd9Sstevel@tonic-gate for (i = 0; 337*7c478bd9Sstevel@tonic-gate i < nargs && i < sizeof (pri->sys_args) / sizeof (pri->sys_args[0]); 338*7c478bd9Sstevel@tonic-gate i++) 339*7c478bd9Sstevel@tonic-gate pri->sys_args[i] = Lsp->pr_sysarg[i]; 340*7c478bd9Sstevel@tonic-gate pri->sys_nargs = nargs; 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate #define ISREAD(code) \ 344*7c478bd9Sstevel@tonic-gate ((code) == SYS_read || (code) == SYS_pread || \ 345*7c478bd9Sstevel@tonic-gate (code) == SYS_pread64 || (code) == SYS_readv || \ 346*7c478bd9Sstevel@tonic-gate (code) == SYS_recv || (code) == SYS_recvfrom) 347*7c478bd9Sstevel@tonic-gate #define ISWRITE(code) \ 348*7c478bd9Sstevel@tonic-gate ((code) == SYS_write || (code) == SYS_pwrite || \ 349*7c478bd9Sstevel@tonic-gate (code) == SYS_pwrite64 || (code) == SYS_writev || \ 350*7c478bd9Sstevel@tonic-gate (code) == SYS_send || (code) == SYS_sendto) 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * Return TRUE iff syscall is being traced. 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate int 356*7c478bd9Sstevel@tonic-gate sysentry(private_t *pri, int dotrace) 357*7c478bd9Sstevel@tonic-gate { 358*7c478bd9Sstevel@tonic-gate pid_t pid = Pstatus(Proc)->pr_pid; 359*7c478bd9Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 360*7c478bd9Sstevel@tonic-gate long arg; 361*7c478bd9Sstevel@tonic-gate int nargs; 362*7c478bd9Sstevel@tonic-gate int i; 363*7c478bd9Sstevel@tonic-gate int x; 364*7c478bd9Sstevel@tonic-gate int len; 365*7c478bd9Sstevel@tonic-gate char *s; 366*7c478bd9Sstevel@tonic-gate const struct systable *stp; 367*7c478bd9Sstevel@tonic-gate int what = Lsp->pr_what; 368*7c478bd9Sstevel@tonic-gate int subcode; 369*7c478bd9Sstevel@tonic-gate int istraced; 370*7c478bd9Sstevel@tonic-gate int raw; 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate /* for reporting sleeping system calls */ 373*7c478bd9Sstevel@tonic-gate if (what == 0 && (Lsp->pr_flags & (PR_ASLEEP|PR_VFORKP))) 374*7c478bd9Sstevel@tonic-gate what = Lsp->pr_syscall; 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* protect ourself from operating system error */ 377*7c478bd9Sstevel@tonic-gate if (what <= 0 || what > PRMAXSYS) 378*7c478bd9Sstevel@tonic-gate what = 0; 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate /* 381*7c478bd9Sstevel@tonic-gate * Set up the system call arguments (pri->sys_nargs & pri->sys_args[]). 382*7c478bd9Sstevel@tonic-gate */ 383*7c478bd9Sstevel@tonic-gate setupsysargs(pri, what); 384*7c478bd9Sstevel@tonic-gate nargs = pri->sys_nargs; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate /* get systable entry for this syscall */ 387*7c478bd9Sstevel@tonic-gate subcode = getsubcode(pri); 388*7c478bd9Sstevel@tonic-gate stp = subsys(what, subcode); 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate if (nargs > stp->nargs) 391*7c478bd9Sstevel@tonic-gate nargs = stp->nargs; 392*7c478bd9Sstevel@tonic-gate pri->sys_nargs = nargs; 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate /* fetch and remember first argument if it's a string */ 395*7c478bd9Sstevel@tonic-gate pri->sys_valid = FALSE; 396*7c478bd9Sstevel@tonic-gate if (nargs > 0 && stp->arg[0] == STG) { 397*7c478bd9Sstevel@tonic-gate long offset; 398*7c478bd9Sstevel@tonic-gate uint32_t offset32; 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate /* 401*7c478bd9Sstevel@tonic-gate * Special case for exit from exec(). 402*7c478bd9Sstevel@tonic-gate * The address in pri->sys_args[0] refers to the old process 403*7c478bd9Sstevel@tonic-gate * image. We must fetch the string from the new image. 404*7c478bd9Sstevel@tonic-gate */ 405*7c478bd9Sstevel@tonic-gate if (Lsp->pr_why == PR_SYSEXIT && 406*7c478bd9Sstevel@tonic-gate (Lsp->pr_what == SYS_execve || 407*7c478bd9Sstevel@tonic-gate Lsp->pr_what == SYS_exec)) { 408*7c478bd9Sstevel@tonic-gate psinfo_t psinfo; 409*7c478bd9Sstevel@tonic-gate long argv; 410*7c478bd9Sstevel@tonic-gate auxv_t auxv[32]; 411*7c478bd9Sstevel@tonic-gate int naux; 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate offset = 0; 414*7c478bd9Sstevel@tonic-gate naux = proc_get_auxv(pid, auxv, 32); 415*7c478bd9Sstevel@tonic-gate for (i = 0; i < naux; i++) { 416*7c478bd9Sstevel@tonic-gate if (auxv[i].a_type == AT_SUN_EXECNAME) { 417*7c478bd9Sstevel@tonic-gate offset = (long)auxv[i].a_un.a_ptr; 418*7c478bd9Sstevel@tonic-gate break; 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate if (offset == 0 && 422*7c478bd9Sstevel@tonic-gate proc_get_psinfo(pid, &psinfo) == 0) { 423*7c478bd9Sstevel@tonic-gate argv = (long)psinfo.pr_argv; 424*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_LP64) 425*7c478bd9Sstevel@tonic-gate (void) Pread(Proc, &offset, 426*7c478bd9Sstevel@tonic-gate sizeof (offset), argv); 427*7c478bd9Sstevel@tonic-gate else { 428*7c478bd9Sstevel@tonic-gate offset32 = 0; 429*7c478bd9Sstevel@tonic-gate (void) Pread(Proc, &offset32, 430*7c478bd9Sstevel@tonic-gate sizeof (offset32), argv); 431*7c478bd9Sstevel@tonic-gate offset = offset32; 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate } else { 435*7c478bd9Sstevel@tonic-gate offset = pri->sys_args[0]; 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate if ((s = fetchstring(pri, offset, PATH_MAX)) != NULL) { 438*7c478bd9Sstevel@tonic-gate pri->sys_valid = TRUE; 439*7c478bd9Sstevel@tonic-gate len = strlen(s); 440*7c478bd9Sstevel@tonic-gate /* reallocate if necessary */ 441*7c478bd9Sstevel@tonic-gate while (len >= pri->sys_psize) { 442*7c478bd9Sstevel@tonic-gate free(pri->sys_path); 443*7c478bd9Sstevel@tonic-gate pri->sys_path = my_malloc(pri->sys_psize *= 2, 444*7c478bd9Sstevel@tonic-gate "pathname buffer"); 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate (void) strcpy(pri->sys_path, s); /* remember pathname */ 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate istraced = dotrace && prismember(&trace, what); 451*7c478bd9Sstevel@tonic-gate raw = prismember(&rawout, what); 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /* force tracing of read/write buffer dump syscalls */ 454*7c478bd9Sstevel@tonic-gate if (!istraced && nargs > 2) { 455*7c478bd9Sstevel@tonic-gate int fdp1 = (int)pri->sys_args[0] + 1; 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate if (ISREAD(what)) { 458*7c478bd9Sstevel@tonic-gate if (prismember(&readfd, fdp1)) 459*7c478bd9Sstevel@tonic-gate istraced = TRUE; 460*7c478bd9Sstevel@tonic-gate } else if (ISWRITE(what)) { 461*7c478bd9Sstevel@tonic-gate if (prismember(&writefd, fdp1)) 462*7c478bd9Sstevel@tonic-gate istraced = TRUE; 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate pri->sys_leng = 0; 467*7c478bd9Sstevel@tonic-gate if (cflag || !istraced) /* just counting */ 468*7c478bd9Sstevel@tonic-gate *pri->sys_string = 0; 469*7c478bd9Sstevel@tonic-gate else { 470*7c478bd9Sstevel@tonic-gate int argprinted = FALSE; 471*7c478bd9Sstevel@tonic-gate const char *name; 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate name = sysname(pri, what, raw ? -1 : subcode); 474*7c478bd9Sstevel@tonic-gate grow(pri, strlen(name) + 1); 475*7c478bd9Sstevel@tonic-gate pri->sys_leng = snprintf(pri->sys_string, pri->sys_ssize, 476*7c478bd9Sstevel@tonic-gate "%s(", name); 477*7c478bd9Sstevel@tonic-gate for (i = 0; i < nargs; i++) { 478*7c478bd9Sstevel@tonic-gate arg = pri->sys_args[i]; 479*7c478bd9Sstevel@tonic-gate x = stp->arg[i]; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate if (x == STG && !raw && 482*7c478bd9Sstevel@tonic-gate i == 0 && pri->sys_valid) { /* already fetched */ 483*7c478bd9Sstevel@tonic-gate escape_string(pri, pri->sys_path); 484*7c478bd9Sstevel@tonic-gate argprinted = TRUE; 485*7c478bd9Sstevel@tonic-gate } else if (x != HID || raw) { 486*7c478bd9Sstevel@tonic-gate if (argprinted) 487*7c478bd9Sstevel@tonic-gate outstring(pri, ", "); 488*7c478bd9Sstevel@tonic-gate if (x == LLO) 489*7c478bd9Sstevel@tonic-gate (*Print[x])(pri, raw, arg, 490*7c478bd9Sstevel@tonic-gate pri->sys_args[++i]); 491*7c478bd9Sstevel@tonic-gate else 492*7c478bd9Sstevel@tonic-gate (*Print[x])(pri, raw, arg); 493*7c478bd9Sstevel@tonic-gate /* 494*7c478bd9Sstevel@tonic-gate * if nothing printed, then don't print ", " 495*7c478bd9Sstevel@tonic-gate */ 496*7c478bd9Sstevel@tonic-gate if (x == NOV) 497*7c478bd9Sstevel@tonic-gate argprinted = FALSE; 498*7c478bd9Sstevel@tonic-gate else 499*7c478bd9Sstevel@tonic-gate argprinted = TRUE; 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate outstring(pri, ")"); 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate return (istraced); 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate #undef ISREAD 508*7c478bd9Sstevel@tonic-gate #undef ISWRITE 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate /* 511*7c478bd9Sstevel@tonic-gate * sysexit() returns non-zero if anything was printed. 512*7c478bd9Sstevel@tonic-gate */ 513*7c478bd9Sstevel@tonic-gate int 514*7c478bd9Sstevel@tonic-gate sysexit(private_t *pri, int dotrace) 515*7c478bd9Sstevel@tonic-gate { 516*7c478bd9Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 517*7c478bd9Sstevel@tonic-gate int what = Lsp->pr_what; 518*7c478bd9Sstevel@tonic-gate struct syscount *scp; 519*7c478bd9Sstevel@tonic-gate const struct systable *stp; 520*7c478bd9Sstevel@tonic-gate int subcode; 521*7c478bd9Sstevel@tonic-gate int istraced; 522*7c478bd9Sstevel@tonic-gate int raw; 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate /* protect ourself from operating system error */ 525*7c478bd9Sstevel@tonic-gate if (what <= 0 || what > PRMAXSYS) 526*7c478bd9Sstevel@tonic-gate return (0); 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate /* 529*7c478bd9Sstevel@tonic-gate * If we aren't supposed to be tracing this one, then 530*7c478bd9Sstevel@tonic-gate * delete it from the traced signal set. We got here 531*7c478bd9Sstevel@tonic-gate * because the process was sleeping in an untraced syscall. 532*7c478bd9Sstevel@tonic-gate */ 533*7c478bd9Sstevel@tonic-gate if (!prismember(&traceeven, what)) { 534*7c478bd9Sstevel@tonic-gate (void) Psysexit(Proc, what, FALSE); 535*7c478bd9Sstevel@tonic-gate return (0); 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate /* pick up registers & set pri->Errno before anything else */ 539*7c478bd9Sstevel@tonic-gate pri->Errno = Lsp->pr_errno; 540*7c478bd9Sstevel@tonic-gate pri->ErrPriv = Lsp->pr_errpriv; 541*7c478bd9Sstevel@tonic-gate pri->Rval1 = Lsp->pr_rval1; 542*7c478bd9Sstevel@tonic-gate pri->Rval2 = Lsp->pr_rval2; 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate switch (what) { 545*7c478bd9Sstevel@tonic-gate case SYS_exit: /* these are traced on entry */ 546*7c478bd9Sstevel@tonic-gate case SYS_lwp_exit: 547*7c478bd9Sstevel@tonic-gate case SYS_evtrapret: 548*7c478bd9Sstevel@tonic-gate case SYS_context: 549*7c478bd9Sstevel@tonic-gate istraced = dotrace && prismember(&trace, what); 550*7c478bd9Sstevel@tonic-gate break; 551*7c478bd9Sstevel@tonic-gate case SYS_exec: /* these are normally traced on entry */ 552*7c478bd9Sstevel@tonic-gate case SYS_execve: 553*7c478bd9Sstevel@tonic-gate istraced = dotrace && prismember(&trace, what); 554*7c478bd9Sstevel@tonic-gate if (pri->exec_string && *pri->exec_string) { 555*7c478bd9Sstevel@tonic-gate if (!cflag && istraced) { /* print exec() string now */ 556*7c478bd9Sstevel@tonic-gate if (pri->exec_pname[0] != '\0') 557*7c478bd9Sstevel@tonic-gate (void) fputs(pri->exec_pname, stdout); 558*7c478bd9Sstevel@tonic-gate timestamp(pri); 559*7c478bd9Sstevel@tonic-gate (void) fputs(pri->exec_string, stdout); 560*7c478bd9Sstevel@tonic-gate } 561*7c478bd9Sstevel@tonic-gate pri->exec_pname[0] = '\0'; 562*7c478bd9Sstevel@tonic-gate pri->exec_string[0] = '\0'; 563*7c478bd9Sstevel@tonic-gate break; 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 566*7c478bd9Sstevel@tonic-gate default: 567*7c478bd9Sstevel@tonic-gate /* we called sysentry() in main() for these */ 568*7c478bd9Sstevel@tonic-gate if (what == SYS_open || what == SYS_open64) 569*7c478bd9Sstevel@tonic-gate istraced = dotrace && prismember(&trace, what); 570*7c478bd9Sstevel@tonic-gate else 571*7c478bd9Sstevel@tonic-gate istraced = sysentry(pri, dotrace) && dotrace; 572*7c478bd9Sstevel@tonic-gate pri->length = 0; 573*7c478bd9Sstevel@tonic-gate if (!cflag && istraced) { 574*7c478bd9Sstevel@tonic-gate putpname(pri); 575*7c478bd9Sstevel@tonic-gate timestamp(pri); 576*7c478bd9Sstevel@tonic-gate pri->length += printf("%s", pri->sys_string); 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate pri->sys_leng = 0; 579*7c478bd9Sstevel@tonic-gate *pri->sys_string = '\0'; 580*7c478bd9Sstevel@tonic-gate break; 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate /* get systable entry for this syscall */ 584*7c478bd9Sstevel@tonic-gate subcode = getsubcode(pri); 585*7c478bd9Sstevel@tonic-gate stp = subsys(what, subcode); 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate if (cflag && istraced) { 588*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&count_lock); 589*7c478bd9Sstevel@tonic-gate scp = Cp->syscount[what]; 590*7c478bd9Sstevel@tonic-gate if (subcode != -1 && 591*7c478bd9Sstevel@tonic-gate (what != SYS_open && what != SYS_open64 && 592*7c478bd9Sstevel@tonic-gate what != SYS_lwp_create)) 593*7c478bd9Sstevel@tonic-gate scp += subcode; 594*7c478bd9Sstevel@tonic-gate scp->count++; 595*7c478bd9Sstevel@tonic-gate accumulate(&scp->stime, &Lsp->pr_stime, &pri->syslast); 596*7c478bd9Sstevel@tonic-gate accumulate(&Cp->usrtotal, &Lsp->pr_utime, &pri->usrlast); 597*7c478bd9Sstevel@tonic-gate pri->syslast = Lsp->pr_stime; 598*7c478bd9Sstevel@tonic-gate pri->usrlast = Lsp->pr_utime; 599*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&count_lock); 600*7c478bd9Sstevel@tonic-gate } 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate if (!cflag && istraced) { 603*7c478bd9Sstevel@tonic-gate if ((what == SYS_forkall || 604*7c478bd9Sstevel@tonic-gate what == SYS_vfork || 605*7c478bd9Sstevel@tonic-gate what == SYS_fork1) && 606*7c478bd9Sstevel@tonic-gate pri->Errno == 0 && pri->Rval2 != 0) { 607*7c478bd9Sstevel@tonic-gate pri->length &= ~07; 608*7c478bd9Sstevel@tonic-gate if (what == SYS_forkall) 609*7c478bd9Sstevel@tonic-gate pri->length -= 8; 610*7c478bd9Sstevel@tonic-gate else 611*7c478bd9Sstevel@tonic-gate (void) fputc('\t', stdout); 612*7c478bd9Sstevel@tonic-gate pri->length += 613*7c478bd9Sstevel@tonic-gate 15 + printf("\t(returning as child ...)"); 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate if (what == SYS_lwp_create && 616*7c478bd9Sstevel@tonic-gate pri->Errno == 0 && pri->Rval1 == 0) { 617*7c478bd9Sstevel@tonic-gate pri->length &= ~07; 618*7c478bd9Sstevel@tonic-gate pri->length += 619*7c478bd9Sstevel@tonic-gate 7 + printf("\t(returning as new lwp ...)"); 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate if (pri->Errno != 0 || 622*7c478bd9Sstevel@tonic-gate (what != SYS_exec && what != SYS_execve)) { 623*7c478bd9Sstevel@tonic-gate /* prepare to print the return code */ 624*7c478bd9Sstevel@tonic-gate pri->length >>= 3; 625*7c478bd9Sstevel@tonic-gate if (pri->length >= 6) 626*7c478bd9Sstevel@tonic-gate (void) fputc(' ', stdout); 627*7c478bd9Sstevel@tonic-gate for (; pri->length < 6; pri->length++) 628*7c478bd9Sstevel@tonic-gate (void) fputc('\t', stdout); 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate pri->length = 0; 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate raw = prismember(&rawout, what); 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate if (pri->Errno != 0) { /* error in syscall */ 636*7c478bd9Sstevel@tonic-gate if (istraced) { 637*7c478bd9Sstevel@tonic-gate if (cflag) 638*7c478bd9Sstevel@tonic-gate scp->error++; 639*7c478bd9Sstevel@tonic-gate else { 640*7c478bd9Sstevel@tonic-gate const char *ename = errname(pri->Errno); 641*7c478bd9Sstevel@tonic-gate const char *privname; 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate (void) printf("Err#%d", pri->Errno); 644*7c478bd9Sstevel@tonic-gate if (ename != NULL) { 645*7c478bd9Sstevel@tonic-gate (void) fputc(' ', stdout); 646*7c478bd9Sstevel@tonic-gate (void) fputs(ename, stdout); 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate switch (pri->ErrPriv) { 649*7c478bd9Sstevel@tonic-gate case PRIV_NONE: 650*7c478bd9Sstevel@tonic-gate privname = NULL; 651*7c478bd9Sstevel@tonic-gate break; 652*7c478bd9Sstevel@tonic-gate case PRIV_ALL: 653*7c478bd9Sstevel@tonic-gate privname = "ALL"; 654*7c478bd9Sstevel@tonic-gate break; 655*7c478bd9Sstevel@tonic-gate case PRIV_MULTIPLE: 656*7c478bd9Sstevel@tonic-gate privname = "MULTIPLE"; 657*7c478bd9Sstevel@tonic-gate break; 658*7c478bd9Sstevel@tonic-gate case PRIV_ALLZONE: 659*7c478bd9Sstevel@tonic-gate privname = "ZONE"; 660*7c478bd9Sstevel@tonic-gate break; 661*7c478bd9Sstevel@tonic-gate default: 662*7c478bd9Sstevel@tonic-gate privname = priv_getbynum(pri->ErrPriv); 663*7c478bd9Sstevel@tonic-gate break; 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate if (privname != NULL) 666*7c478bd9Sstevel@tonic-gate (void) printf(" [%s]", privname); 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate } else { 672*7c478bd9Sstevel@tonic-gate /* show arguments on successful exec */ 673*7c478bd9Sstevel@tonic-gate if (what == SYS_exec || what == SYS_execve) { 674*7c478bd9Sstevel@tonic-gate if (!cflag && istraced) 675*7c478bd9Sstevel@tonic-gate showargs(pri, raw); 676*7c478bd9Sstevel@tonic-gate } else if (!cflag && istraced) { 677*7c478bd9Sstevel@tonic-gate const char *fmt = NULL; 678*7c478bd9Sstevel@tonic-gate long rv1 = pri->Rval1; 679*7c478bd9Sstevel@tonic-gate long rv2 = pri->Rval2; 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate #ifdef _LP64 682*7c478bd9Sstevel@tonic-gate /* 683*7c478bd9Sstevel@tonic-gate * 32-bit system calls return 32-bit values. We 684*7c478bd9Sstevel@tonic-gate * later mask out the upper bits if we want to 685*7c478bd9Sstevel@tonic-gate * print these as unsigned values. 686*7c478bd9Sstevel@tonic-gate */ 687*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_ILP32) { 688*7c478bd9Sstevel@tonic-gate rv1 = (int)rv1; 689*7c478bd9Sstevel@tonic-gate rv2 = (int)rv2; 690*7c478bd9Sstevel@tonic-gate } 691*7c478bd9Sstevel@tonic-gate #endif 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate switch (what) { 694*7c478bd9Sstevel@tonic-gate case SYS_llseek: 695*7c478bd9Sstevel@tonic-gate rv1 &= 0xffffffff; 696*7c478bd9Sstevel@tonic-gate rv2 &= 0xffffffff; 697*7c478bd9Sstevel@tonic-gate #ifdef _LONG_LONG_LTOH /* first long of a longlong is the low order */ 698*7c478bd9Sstevel@tonic-gate if (rv2 != 0) { 699*7c478bd9Sstevel@tonic-gate long temp = rv1; 700*7c478bd9Sstevel@tonic-gate fmt = "= 0x%lX%.8lX"; 701*7c478bd9Sstevel@tonic-gate rv1 = rv2; 702*7c478bd9Sstevel@tonic-gate rv2 = temp; 703*7c478bd9Sstevel@tonic-gate break; 704*7c478bd9Sstevel@tonic-gate } 705*7c478bd9Sstevel@tonic-gate #else /* the other way around */ 706*7c478bd9Sstevel@tonic-gate if (rv1 != 0) { 707*7c478bd9Sstevel@tonic-gate fmt = "= 0x%lX%.8lX"; 708*7c478bd9Sstevel@tonic-gate break; 709*7c478bd9Sstevel@tonic-gate } 710*7c478bd9Sstevel@tonic-gate rv1 = rv2; /* ugly */ 711*7c478bd9Sstevel@tonic-gate #endif 712*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 713*7c478bd9Sstevel@tonic-gate case SYS_lseek: 714*7c478bd9Sstevel@tonic-gate case SYS_ulimit: 715*7c478bd9Sstevel@tonic-gate if (rv1 & 0xff000000) { 716*7c478bd9Sstevel@tonic-gate #ifdef _LP64 717*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_ILP32) 718*7c478bd9Sstevel@tonic-gate rv1 &= 0xffffffff; 719*7c478bd9Sstevel@tonic-gate #endif 720*7c478bd9Sstevel@tonic-gate fmt = "= 0x%.8lX"; 721*7c478bd9Sstevel@tonic-gate } 722*7c478bd9Sstevel@tonic-gate break; 723*7c478bd9Sstevel@tonic-gate case SYS_signal: 724*7c478bd9Sstevel@tonic-gate if (raw) 725*7c478bd9Sstevel@tonic-gate /* EMPTY */; 726*7c478bd9Sstevel@tonic-gate else if (rv1 == (int)SIG_DFL) 727*7c478bd9Sstevel@tonic-gate fmt = "= SIG_DFL"; 728*7c478bd9Sstevel@tonic-gate else if (rv1 == (int)SIG_IGN) 729*7c478bd9Sstevel@tonic-gate fmt = "= SIG_IGN"; 730*7c478bd9Sstevel@tonic-gate else if (rv1 == (int)SIG_HOLD) 731*7c478bd9Sstevel@tonic-gate fmt = "= SIG_HOLD"; 732*7c478bd9Sstevel@tonic-gate break; 733*7c478bd9Sstevel@tonic-gate case SYS_sigtimedwait: 734*7c478bd9Sstevel@tonic-gate if (raw) 735*7c478bd9Sstevel@tonic-gate /* EMPTY */; 736*7c478bd9Sstevel@tonic-gate else if ((fmt = rawsigname(pri, rv1)) != NULL) { 737*7c478bd9Sstevel@tonic-gate rv1 = (long)fmt; /* filthy */ 738*7c478bd9Sstevel@tonic-gate fmt = "= %s"; 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate break; 741*7c478bd9Sstevel@tonic-gate case SYS_port: 742*7c478bd9Sstevel@tonic-gate #ifdef _LP64 743*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_LP64) { 744*7c478bd9Sstevel@tonic-gate rv2 = rv1 & 0xffffffff; 745*7c478bd9Sstevel@tonic-gate rv1 = rv1 >> 32; 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate #endif 748*7c478bd9Sstevel@tonic-gate break; 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate if (fmt == NULL) { 752*7c478bd9Sstevel@tonic-gate switch (stp->rval[0]) { 753*7c478bd9Sstevel@tonic-gate case HEX: 754*7c478bd9Sstevel@tonic-gate #ifdef _LP64 755*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_ILP32) 756*7c478bd9Sstevel@tonic-gate rv1 &= 0xffffffff; 757*7c478bd9Sstevel@tonic-gate #endif 758*7c478bd9Sstevel@tonic-gate fmt = "= 0x%.8lX"; 759*7c478bd9Sstevel@tonic-gate break; 760*7c478bd9Sstevel@tonic-gate case HHX: 761*7c478bd9Sstevel@tonic-gate #ifdef _LP64 762*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_ILP32) 763*7c478bd9Sstevel@tonic-gate rv1 &= 0xffffffff; 764*7c478bd9Sstevel@tonic-gate #endif 765*7c478bd9Sstevel@tonic-gate fmt = "= 0x%.4lX"; 766*7c478bd9Sstevel@tonic-gate break; 767*7c478bd9Sstevel@tonic-gate case OCT: 768*7c478bd9Sstevel@tonic-gate #ifdef _LP64 769*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_ILP32) 770*7c478bd9Sstevel@tonic-gate rv1 &= 0xffffffff; 771*7c478bd9Sstevel@tonic-gate #endif 772*7c478bd9Sstevel@tonic-gate fmt = "= %#lo"; 773*7c478bd9Sstevel@tonic-gate break; 774*7c478bd9Sstevel@tonic-gate default: 775*7c478bd9Sstevel@tonic-gate fmt = "= %ld"; 776*7c478bd9Sstevel@tonic-gate break; 777*7c478bd9Sstevel@tonic-gate } 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate (void) printf(fmt, rv1, rv2); 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate switch (stp->rval[1]) { 783*7c478bd9Sstevel@tonic-gate case NOV: 784*7c478bd9Sstevel@tonic-gate fmt = NULL; 785*7c478bd9Sstevel@tonic-gate break; 786*7c478bd9Sstevel@tonic-gate case HEX: 787*7c478bd9Sstevel@tonic-gate #ifdef _LP64 788*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_ILP32) 789*7c478bd9Sstevel@tonic-gate rv2 &= 0xffffffff; 790*7c478bd9Sstevel@tonic-gate #endif 791*7c478bd9Sstevel@tonic-gate fmt = " [0x%.8lX]"; 792*7c478bd9Sstevel@tonic-gate break; 793*7c478bd9Sstevel@tonic-gate case HHX: 794*7c478bd9Sstevel@tonic-gate #ifdef _LP64 795*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_ILP32) 796*7c478bd9Sstevel@tonic-gate rv2 &= 0xffffffff; 797*7c478bd9Sstevel@tonic-gate #endif 798*7c478bd9Sstevel@tonic-gate fmt = " [0x%.4lX]"; 799*7c478bd9Sstevel@tonic-gate break; 800*7c478bd9Sstevel@tonic-gate case OCT: 801*7c478bd9Sstevel@tonic-gate #ifdef _LP64 802*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_ILP32) 803*7c478bd9Sstevel@tonic-gate rv2 &= 0xffffffff; 804*7c478bd9Sstevel@tonic-gate #endif 805*7c478bd9Sstevel@tonic-gate fmt = " [%#lo]"; 806*7c478bd9Sstevel@tonic-gate break; 807*7c478bd9Sstevel@tonic-gate default: 808*7c478bd9Sstevel@tonic-gate fmt = " [%ld]"; 809*7c478bd9Sstevel@tonic-gate break; 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate if (fmt != NULL) 813*7c478bd9Sstevel@tonic-gate (void) printf(fmt, rv2); 814*7c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate if (what == SYS_forkall || 818*7c478bd9Sstevel@tonic-gate what == SYS_vfork || 819*7c478bd9Sstevel@tonic-gate what == SYS_fork1) { 820*7c478bd9Sstevel@tonic-gate if (pri->Rval2 == 0) /* child was created */ 821*7c478bd9Sstevel@tonic-gate pri->child = pri->Rval1; 822*7c478bd9Sstevel@tonic-gate else if (cflag && istraced) /* this is the child */ 823*7c478bd9Sstevel@tonic-gate scp->count--; 824*7c478bd9Sstevel@tonic-gate } 825*7c478bd9Sstevel@tonic-gate if (what == SYS_lwp_create && pri->Rval1 == 0 && 826*7c478bd9Sstevel@tonic-gate cflag && istraced) /* this is the created lwp */ 827*7c478bd9Sstevel@tonic-gate scp->count--; 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate #define ISREAD(code) \ 831*7c478bd9Sstevel@tonic-gate ((code) == SYS_read || (code) == SYS_pread || (code) == SYS_pread64 || \ 832*7c478bd9Sstevel@tonic-gate (code) == SYS_recv || (code) == SYS_recvfrom) 833*7c478bd9Sstevel@tonic-gate #define ISWRITE(code) \ 834*7c478bd9Sstevel@tonic-gate ((code) == SYS_write || (code) == SYS_pwrite || \ 835*7c478bd9Sstevel@tonic-gate (code) == SYS_pwrite64 || (code) == SYS_send || (code) == SYS_sendto) 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate if (!cflag && istraced) { 838*7c478bd9Sstevel@tonic-gate int fdp1 = (int)pri->sys_args[0] + 1; /* filedescriptor + 1 */ 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate if (raw) { 841*7c478bd9Sstevel@tonic-gate if (what != SYS_exec && what != SYS_execve) 842*7c478bd9Sstevel@tonic-gate showpaths(pri, stp); 843*7c478bd9Sstevel@tonic-gate if (ISREAD(what) || ISWRITE(what)) { 844*7c478bd9Sstevel@tonic-gate if (pri->iob_buf[0] != '\0') 845*7c478bd9Sstevel@tonic-gate (void) printf("%s 0x%.8lX: %s\n", 846*7c478bd9Sstevel@tonic-gate pri->pname, pri->sys_args[1], 847*7c478bd9Sstevel@tonic-gate pri->iob_buf); 848*7c478bd9Sstevel@tonic-gate } 849*7c478bd9Sstevel@tonic-gate } 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate /* 852*7c478bd9Sstevel@tonic-gate * Show buffer contents for read()/pread() or write()/pwrite(). 853*7c478bd9Sstevel@tonic-gate * IOBSIZE bytes have already been shown; 854*7c478bd9Sstevel@tonic-gate * don't show them again unless there's more. 855*7c478bd9Sstevel@tonic-gate */ 856*7c478bd9Sstevel@tonic-gate if ((ISREAD(what) && pri->Errno == 0 && 857*7c478bd9Sstevel@tonic-gate prismember(&readfd, fdp1)) || 858*7c478bd9Sstevel@tonic-gate (ISWRITE(what) && prismember(&writefd, fdp1))) { 859*7c478bd9Sstevel@tonic-gate long nb = ISWRITE(what) ? pri->sys_args[2] : pri->Rval1; 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate if (nb > IOBSIZE) { 862*7c478bd9Sstevel@tonic-gate /* enter region of lengthy output */ 863*7c478bd9Sstevel@tonic-gate if (nb > MYBUFSIZ / 4) 864*7c478bd9Sstevel@tonic-gate Eserialize(); 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate showbuffer(pri, pri->sys_args[1], nb); 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate /* exit region of lengthy output */ 869*7c478bd9Sstevel@tonic-gate if (nb > MYBUFSIZ / 4) 870*7c478bd9Sstevel@tonic-gate Xserialize(); 871*7c478bd9Sstevel@tonic-gate } 872*7c478bd9Sstevel@tonic-gate } 873*7c478bd9Sstevel@tonic-gate #undef ISREAD 874*7c478bd9Sstevel@tonic-gate #undef ISWRITE 875*7c478bd9Sstevel@tonic-gate /* 876*7c478bd9Sstevel@tonic-gate * Do verbose interpretation if requested. 877*7c478bd9Sstevel@tonic-gate * If buffer contents for read or write have been requested and 878*7c478bd9Sstevel@tonic-gate * this is a readv() or writev(), force verbose interpretation. 879*7c478bd9Sstevel@tonic-gate */ 880*7c478bd9Sstevel@tonic-gate /* XXX add SYS_sendmsg and SYS_recvmsg */ 881*7c478bd9Sstevel@tonic-gate if (prismember(&verbose, what) || 882*7c478bd9Sstevel@tonic-gate (what == SYS_readv && pri->Errno == 0 && 883*7c478bd9Sstevel@tonic-gate prismember(&readfd, fdp1)) || 884*7c478bd9Sstevel@tonic-gate ((what == SYS_writev || what == SYS_sendfilev) && 885*7c478bd9Sstevel@tonic-gate prismember(&writefd, fdp1))) 886*7c478bd9Sstevel@tonic-gate expound(pri, pri->Rval1, raw); 887*7c478bd9Sstevel@tonic-gate } 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate return (!cflag && istraced); 890*7c478bd9Sstevel@tonic-gate } 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate void 893*7c478bd9Sstevel@tonic-gate showpaths(private_t *pri, const struct systable *stp) 894*7c478bd9Sstevel@tonic-gate { 895*7c478bd9Sstevel@tonic-gate int i; 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate for (i = 0; i < pri->sys_nargs; i++) { 898*7c478bd9Sstevel@tonic-gate if ((stp->arg[i] == STG) || 899*7c478bd9Sstevel@tonic-gate (stp->arg[i] == RST && !pri->Errno) || 900*7c478bd9Sstevel@tonic-gate (stp->arg[i] == RLK && !pri->Errno && pri->Rval1 > 0)) { 901*7c478bd9Sstevel@tonic-gate long addr = pri->sys_args[i]; 902*7c478bd9Sstevel@tonic-gate int maxleng = 903*7c478bd9Sstevel@tonic-gate (stp->arg[i] == RLK)? (int)pri->Rval1 : PATH_MAX; 904*7c478bd9Sstevel@tonic-gate char *s; 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate if (i == 0 && pri->sys_valid) /* already fetched */ 907*7c478bd9Sstevel@tonic-gate s = pri->sys_path; 908*7c478bd9Sstevel@tonic-gate else 909*7c478bd9Sstevel@tonic-gate s = fetchstring(pri, addr, 910*7c478bd9Sstevel@tonic-gate maxleng > PATH_MAX ? PATH_MAX : maxleng); 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate if (s != (char *)NULL) 913*7c478bd9Sstevel@tonic-gate (void) printf("%s 0x%.8lX: \"%s\"\n", 914*7c478bd9Sstevel@tonic-gate pri->pname, addr, s); 915*7c478bd9Sstevel@tonic-gate } 916*7c478bd9Sstevel@tonic-gate } 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate /* 920*7c478bd9Sstevel@tonic-gate * Display arguments to successful exec(). 921*7c478bd9Sstevel@tonic-gate */ 922*7c478bd9Sstevel@tonic-gate void 923*7c478bd9Sstevel@tonic-gate showargs(private_t *pri, int raw) 924*7c478bd9Sstevel@tonic-gate { 925*7c478bd9Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 926*7c478bd9Sstevel@tonic-gate int nargs; 927*7c478bd9Sstevel@tonic-gate long ap; 928*7c478bd9Sstevel@tonic-gate int ptrsize; 929*7c478bd9Sstevel@tonic-gate int fail; 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate pri->length = 0; 932*7c478bd9Sstevel@tonic-gate ptrsize = (data_model == PR_MODEL_LP64)? 8 : 4; 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) /* XX64 */ 935*7c478bd9Sstevel@tonic-gate ap = (long)Lsp->pr_reg[R_SP]; 936*7c478bd9Sstevel@tonic-gate fail = (Pread(Proc, &nargs, sizeof (nargs), ap) != sizeof (nargs)); 937*7c478bd9Sstevel@tonic-gate ap += ptrsize; 938*7c478bd9Sstevel@tonic-gate #endif /* i386 */ 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate #if sparc 941*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_LP64) { 942*7c478bd9Sstevel@tonic-gate int64_t xnargs; 943*7c478bd9Sstevel@tonic-gate ap = (long)(Lsp->pr_reg[R_SP]) + 16 * sizeof (int64_t) 944*7c478bd9Sstevel@tonic-gate + STACK_BIAS; 945*7c478bd9Sstevel@tonic-gate fail = (Pread(Proc, &xnargs, sizeof (xnargs), ap) != 946*7c478bd9Sstevel@tonic-gate sizeof (xnargs)); 947*7c478bd9Sstevel@tonic-gate nargs = (int)xnargs; 948*7c478bd9Sstevel@tonic-gate } else { 949*7c478bd9Sstevel@tonic-gate ap = (long)(Lsp->pr_reg[R_SP]) + 16 * sizeof (int32_t); 950*7c478bd9Sstevel@tonic-gate fail = (Pread(Proc, &nargs, sizeof (nargs), ap) != 951*7c478bd9Sstevel@tonic-gate sizeof (nargs)); 952*7c478bd9Sstevel@tonic-gate } 953*7c478bd9Sstevel@tonic-gate ap += ptrsize; 954*7c478bd9Sstevel@tonic-gate #endif /* sparc */ 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate if (fail) { 957*7c478bd9Sstevel@tonic-gate (void) printf("\n%s\t*** Bad argument list? ***\n", pri->pname); 958*7c478bd9Sstevel@tonic-gate return; 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate (void) printf(" argc = %d\n", nargs); 962*7c478bd9Sstevel@tonic-gate if (raw) 963*7c478bd9Sstevel@tonic-gate showpaths(pri, &systable[SYS_exec]); 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate show_cred(pri, FALSE); 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate if (aflag || eflag) { /* dump args or environment */ 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate /* enter region of (potentially) lengthy output */ 970*7c478bd9Sstevel@tonic-gate Eserialize(); 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate if (aflag) /* dump the argument list */ 973*7c478bd9Sstevel@tonic-gate dumpargs(pri, ap, "argv:"); 974*7c478bd9Sstevel@tonic-gate ap += (nargs+1) * ptrsize; 975*7c478bd9Sstevel@tonic-gate if (eflag) /* dump the environment */ 976*7c478bd9Sstevel@tonic-gate dumpargs(pri, ap, "envp:"); 977*7c478bd9Sstevel@tonic-gate 978*7c478bd9Sstevel@tonic-gate /* exit region of lengthy output */ 979*7c478bd9Sstevel@tonic-gate Xserialize(); 980*7c478bd9Sstevel@tonic-gate } 981*7c478bd9Sstevel@tonic-gate } 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate void 984*7c478bd9Sstevel@tonic-gate dumpargs(private_t *pri, long ap, const char *str) 985*7c478bd9Sstevel@tonic-gate { 986*7c478bd9Sstevel@tonic-gate char *string; 987*7c478bd9Sstevel@tonic-gate unsigned int leng = 0; 988*7c478bd9Sstevel@tonic-gate int ptrsize; 989*7c478bd9Sstevel@tonic-gate long arg = 0; 990*7c478bd9Sstevel@tonic-gate char *argaddr; 991*7c478bd9Sstevel@tonic-gate char badaddr[32]; 992*7c478bd9Sstevel@tonic-gate 993*7c478bd9Sstevel@tonic-gate if (interrupt) 994*7c478bd9Sstevel@tonic-gate return; 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate #ifdef _LP64 997*7c478bd9Sstevel@tonic-gate if (data_model == PR_MODEL_LP64) { 998*7c478bd9Sstevel@tonic-gate argaddr = (char *)&arg; 999*7c478bd9Sstevel@tonic-gate ptrsize = 8; 1000*7c478bd9Sstevel@tonic-gate } else { 1001*7c478bd9Sstevel@tonic-gate #if defined(_LITTLE_ENDIAN) 1002*7c478bd9Sstevel@tonic-gate argaddr = (char *)&arg; 1003*7c478bd9Sstevel@tonic-gate #else 1004*7c478bd9Sstevel@tonic-gate argaddr = (char *)&arg + 4; 1005*7c478bd9Sstevel@tonic-gate #endif 1006*7c478bd9Sstevel@tonic-gate ptrsize = 4; 1007*7c478bd9Sstevel@tonic-gate } 1008*7c478bd9Sstevel@tonic-gate #else 1009*7c478bd9Sstevel@tonic-gate argaddr = (char *)&arg; 1010*7c478bd9Sstevel@tonic-gate ptrsize = 4; 1011*7c478bd9Sstevel@tonic-gate #endif 1012*7c478bd9Sstevel@tonic-gate putpname(pri); 1013*7c478bd9Sstevel@tonic-gate (void) fputc(' ', stdout); 1014*7c478bd9Sstevel@tonic-gate (void) fputs(str, stdout); 1015*7c478bd9Sstevel@tonic-gate leng += 1 + strlen(str); 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate while (!interrupt) { 1018*7c478bd9Sstevel@tonic-gate if (Pread(Proc, argaddr, ptrsize, ap) != ptrsize) { 1019*7c478bd9Sstevel@tonic-gate (void) printf("\n%s\t*** Bad argument list? ***\n", 1020*7c478bd9Sstevel@tonic-gate pri->pname); 1021*7c478bd9Sstevel@tonic-gate return; 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate ap += ptrsize; 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gate if (arg == 0) 1026*7c478bd9Sstevel@tonic-gate break; 1027*7c478bd9Sstevel@tonic-gate string = fetchstring(pri, arg, PATH_MAX); 1028*7c478bd9Sstevel@tonic-gate if (string == NULL) { 1029*7c478bd9Sstevel@tonic-gate (void) sprintf(badaddr, "BadAddress:0x%.8lX", arg); 1030*7c478bd9Sstevel@tonic-gate string = badaddr; 1031*7c478bd9Sstevel@tonic-gate } 1032*7c478bd9Sstevel@tonic-gate if ((leng += strlen(string)) < 63) { 1033*7c478bd9Sstevel@tonic-gate (void) fputc(' ', stdout); 1034*7c478bd9Sstevel@tonic-gate leng++; 1035*7c478bd9Sstevel@tonic-gate } else { 1036*7c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 1037*7c478bd9Sstevel@tonic-gate leng = 0; 1038*7c478bd9Sstevel@tonic-gate putpname(pri); 1039*7c478bd9Sstevel@tonic-gate (void) fputs(" ", stdout); 1040*7c478bd9Sstevel@tonic-gate leng += 2 + strlen(string); 1041*7c478bd9Sstevel@tonic-gate } 1042*7c478bd9Sstevel@tonic-gate (void) fputs(string, stdout); 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 1045*7c478bd9Sstevel@tonic-gate } 1046*7c478bd9Sstevel@tonic-gate 1047*7c478bd9Sstevel@tonic-gate /* 1048*7c478bd9Sstevel@tonic-gate * Display contents of read() or write() buffer. 1049*7c478bd9Sstevel@tonic-gate */ 1050*7c478bd9Sstevel@tonic-gate void 1051*7c478bd9Sstevel@tonic-gate showbuffer(private_t *pri, long offset, long count) 1052*7c478bd9Sstevel@tonic-gate { 1053*7c478bd9Sstevel@tonic-gate char buffer[320]; 1054*7c478bd9Sstevel@tonic-gate int nbytes; 1055*7c478bd9Sstevel@tonic-gate char *buf; 1056*7c478bd9Sstevel@tonic-gate int n; 1057*7c478bd9Sstevel@tonic-gate 1058*7c478bd9Sstevel@tonic-gate while (count > 0 && !interrupt) { 1059*7c478bd9Sstevel@tonic-gate nbytes = (count < sizeof (buffer))? count : sizeof (buffer); 1060*7c478bd9Sstevel@tonic-gate if ((nbytes = Pread(Proc, buffer, nbytes, offset)) <= 0) 1061*7c478bd9Sstevel@tonic-gate break; 1062*7c478bd9Sstevel@tonic-gate count -= nbytes; 1063*7c478bd9Sstevel@tonic-gate offset += nbytes; 1064*7c478bd9Sstevel@tonic-gate buf = buffer; 1065*7c478bd9Sstevel@tonic-gate while (nbytes > 0 && !interrupt) { 1066*7c478bd9Sstevel@tonic-gate char obuf[65]; 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate n = (nbytes < 32)? nbytes : 32; 1069*7c478bd9Sstevel@tonic-gate showbytes(buf, n, obuf); 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate putpname(pri); 1072*7c478bd9Sstevel@tonic-gate (void) fputs(" ", stdout); 1073*7c478bd9Sstevel@tonic-gate (void) fputs(obuf, stdout); 1074*7c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 1075*7c478bd9Sstevel@tonic-gate nbytes -= n; 1076*7c478bd9Sstevel@tonic-gate buf += n; 1077*7c478bd9Sstevel@tonic-gate } 1078*7c478bd9Sstevel@tonic-gate } 1079*7c478bd9Sstevel@tonic-gate } 1080*7c478bd9Sstevel@tonic-gate 1081*7c478bd9Sstevel@tonic-gate void 1082*7c478bd9Sstevel@tonic-gate showbytes(const char *buf, int n, char *obuf) 1083*7c478bd9Sstevel@tonic-gate { 1084*7c478bd9Sstevel@tonic-gate int c; 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate while (--n >= 0) { 1087*7c478bd9Sstevel@tonic-gate int c1 = '\\'; 1088*7c478bd9Sstevel@tonic-gate int c2; 1089*7c478bd9Sstevel@tonic-gate 1090*7c478bd9Sstevel@tonic-gate switch (c = (*buf++ & 0xff)) { 1091*7c478bd9Sstevel@tonic-gate case '\0': 1092*7c478bd9Sstevel@tonic-gate c2 = '0'; 1093*7c478bd9Sstevel@tonic-gate break; 1094*7c478bd9Sstevel@tonic-gate case '\b': 1095*7c478bd9Sstevel@tonic-gate c2 = 'b'; 1096*7c478bd9Sstevel@tonic-gate break; 1097*7c478bd9Sstevel@tonic-gate case '\t': 1098*7c478bd9Sstevel@tonic-gate c2 = 't'; 1099*7c478bd9Sstevel@tonic-gate break; 1100*7c478bd9Sstevel@tonic-gate case '\n': 1101*7c478bd9Sstevel@tonic-gate c2 = 'n'; 1102*7c478bd9Sstevel@tonic-gate break; 1103*7c478bd9Sstevel@tonic-gate case '\v': 1104*7c478bd9Sstevel@tonic-gate c2 = 'v'; 1105*7c478bd9Sstevel@tonic-gate break; 1106*7c478bd9Sstevel@tonic-gate case '\f': 1107*7c478bd9Sstevel@tonic-gate c2 = 'f'; 1108*7c478bd9Sstevel@tonic-gate break; 1109*7c478bd9Sstevel@tonic-gate case '\r': 1110*7c478bd9Sstevel@tonic-gate c2 = 'r'; 1111*7c478bd9Sstevel@tonic-gate break; 1112*7c478bd9Sstevel@tonic-gate default: 1113*7c478bd9Sstevel@tonic-gate if (isprint(c)) { 1114*7c478bd9Sstevel@tonic-gate c1 = ' '; 1115*7c478bd9Sstevel@tonic-gate c2 = c; 1116*7c478bd9Sstevel@tonic-gate } else { 1117*7c478bd9Sstevel@tonic-gate c1 = c>>4; 1118*7c478bd9Sstevel@tonic-gate c1 += (c1 < 10)? '0' : 'A'-10; 1119*7c478bd9Sstevel@tonic-gate c2 = c&0xf; 1120*7c478bd9Sstevel@tonic-gate c2 += (c2 < 10)? '0' : 'A'-10; 1121*7c478bd9Sstevel@tonic-gate } 1122*7c478bd9Sstevel@tonic-gate break; 1123*7c478bd9Sstevel@tonic-gate } 1124*7c478bd9Sstevel@tonic-gate *obuf++ = (char)c1; 1125*7c478bd9Sstevel@tonic-gate *obuf++ = (char)c2; 1126*7c478bd9Sstevel@tonic-gate } 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate *obuf = '\0'; 1129*7c478bd9Sstevel@tonic-gate } 1130