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