1 1.48 rillig /* $NetBSD: dump.c,v 1.48 2021/05/01 18:07:52 rillig Exp $ */ 2 1.2 mrg 3 1.1 darrenr /*- 4 1.1 darrenr * Copyright (c) 1988, 1993 5 1.1 darrenr * The Regents of the University of California. All rights reserved. 6 1.1 darrenr * 7 1.1 darrenr * Redistribution and use in source and binary forms, with or without 8 1.1 darrenr * modification, are permitted provided that the following conditions 9 1.1 darrenr * are met: 10 1.1 darrenr * 1. Redistributions of source code must retain the above copyright 11 1.1 darrenr * notice, this list of conditions and the following disclaimer. 12 1.1 darrenr * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 darrenr * notice, this list of conditions and the following disclaimer in the 14 1.1 darrenr * documentation and/or other materials provided with the distribution. 15 1.15 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 darrenr * may be used to endorse or promote products derived from this software 17 1.1 darrenr * without specific prior written permission. 18 1.1 darrenr * 19 1.1 darrenr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 darrenr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 darrenr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 darrenr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 darrenr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 darrenr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 darrenr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 darrenr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 darrenr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 darrenr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 darrenr * SUCH DAMAGE. 30 1.1 darrenr */ 31 1.1 darrenr 32 1.1 darrenr #include <sys/cdefs.h> 33 1.1 darrenr #ifndef lint 34 1.29 lukem __COPYRIGHT("@(#) Copyright (c) 1988, 1993\ 35 1.29 lukem The Regents of the University of California. All rights reserved."); 36 1.1 darrenr #endif /* not lint */ 37 1.1 darrenr 38 1.1 darrenr #ifndef lint 39 1.1 darrenr #if 0 40 1.1 darrenr static char sccsid[] = "@(#)kdump.c 8.4 (Berkeley) 4/28/95"; 41 1.1 darrenr #endif 42 1.48 rillig __RCSID("$NetBSD: dump.c,v 1.48 2021/05/01 18:07:52 rillig Exp $"); 43 1.1 darrenr #endif /* not lint */ 44 1.1 darrenr 45 1.1 darrenr #include <sys/param.h> 46 1.1 darrenr #define _KERNEL 47 1.1 darrenr #include <sys/errno.h> 48 1.1 darrenr #undef _KERNEL 49 1.18 enami #include <sys/ioctl.h> 50 1.1 darrenr #include <sys/time.h> 51 1.1 darrenr #include <sys/uio.h> 52 1.1 darrenr #include <sys/ktrace.h> 53 1.1 darrenr #include <sys/ptrace.h> 54 1.18 enami #include <sys/queue.h> 55 1.1 darrenr 56 1.1 darrenr #include <err.h> 57 1.1 darrenr #include <signal.h> 58 1.18 enami #include <stdarg.h> 59 1.18 enami #include <stddef.h> 60 1.1 darrenr #include <stdio.h> 61 1.1 darrenr #include <stdlib.h> 62 1.1 darrenr #include <string.h> 63 1.1 darrenr #include <unistd.h> 64 1.1 darrenr #include <vis.h> 65 1.1 darrenr 66 1.1 darrenr #include "ktrace.h" 67 1.1 darrenr #include "misc.h" 68 1.9 jdolecek #include "setemul.h" 69 1.1 darrenr 70 1.1 darrenr int timestamp, decimal, fancy = 1, tail, maxdata; 71 1.1 darrenr 72 1.18 enami int width; /* Keep track of current columns. */ 73 1.1 darrenr 74 1.1 darrenr #include <sys/syscall.h> 75 1.1 darrenr 76 1.18 enami static const char *const ptrace_ops[] = { 77 1.47 kamil PT_STRINGS 78 1.1 darrenr }; 79 1.1 darrenr 80 1.47 kamil #ifdef PT_MACHDEP_STRINGS 81 1.47 kamil static const char * const ptrace_machdep_ops[] = { PT_MACHDEP_STRINGS }; 82 1.47 kamil #endif 83 1.47 kamil 84 1.18 enami struct ktr_entry { 85 1.18 enami TAILQ_ENTRY(ktr_entry) kte_list; 86 1.18 enami struct ktr_header kte_kth; 87 1.18 enami }; 88 1.18 enami 89 1.18 enami TAILQ_HEAD(kteq, ktr_entry) ktependq = TAILQ_HEAD_INITIALIZER(ktependq); 90 1.18 enami 91 1.18 enami void argprint(const char *, register_t **, int *); 92 1.18 enami void dumpheader(struct ktr_header *); 93 1.18 enami int dumprecord(int, FILE *); 94 1.18 enami void flushpendq(struct ktr_entry *); 95 1.18 enami int fread_tail(void *, int, int, FILE *); 96 1.18 enami void genioprint(struct ktr_header *); 97 1.18 enami struct ktr_entry * 98 1.18 enami getpendq(struct ktr_header *, int, struct kteq *); 99 1.18 enami struct ktr_entry * 100 1.18 enami getrecord(FILE *); 101 1.18 enami void indent(int); 102 1.18 enami void ioctldecode(u_long); 103 1.18 enami void ktrcsw(struct ktr_entry *); 104 1.18 enami void ktremul(struct ktr_entry *); 105 1.18 enami void ktrgenio(struct ktr_entry *); 106 1.18 enami void ktrnamei(struct ktr_entry *); 107 1.18 enami void ktrpsig(struct ktr_entry *); 108 1.18 enami void ktrsyscall(struct ktr_entry *); 109 1.18 enami void ktrsysret(struct ktr_entry *); 110 1.18 enami void nameiargprint(const char *, struct ktr_header *, register_t **, int *); 111 1.18 enami void nameiprint(struct ktr_header *); 112 1.18 enami void newline(void); 113 1.18 enami void putpendq(struct ktr_entry *); 114 1.18 enami void syscallnameprint(int); 115 1.18 enami void syscallprint(struct ktr_header *); 116 1.18 enami void sysretprint(struct ktr_header *); 117 1.43 kamil int xwprintf(const char *, ...) __printflike(1, 2); 118 1.18 enami void *xrealloc(void *, size_t *, size_t); 119 1.18 enami 120 1.18 enami int 121 1.43 kamil xwprintf(const char *fmt, ...) 122 1.18 enami { 123 1.18 enami va_list ap; 124 1.18 enami int w; 125 1.18 enami 126 1.18 enami va_start(ap, fmt); 127 1.18 enami w = vprintf(fmt, ap); 128 1.18 enami if (w == -1) 129 1.18 enami warn("vprintf"); 130 1.18 enami else 131 1.18 enami width += w; 132 1.18 enami va_end(ap); 133 1.18 enami return (w); 134 1.18 enami } 135 1.1 darrenr 136 1.18 enami void 137 1.18 enami newline(void) 138 1.18 enami { 139 1.1 darrenr 140 1.18 enami if (width > 0) { 141 1.18 enami printf("\n"); 142 1.18 enami width = 0; 143 1.18 enami } 144 1.18 enami } 145 1.1 darrenr 146 1.1 darrenr void 147 1.18 enami indent(int col) 148 1.18 enami { 149 1.18 enami 150 1.18 enami while (width < col) 151 1.43 kamil if (xwprintf(" ") < 0) 152 1.18 enami break; 153 1.18 enami } 154 1.18 enami 155 1.18 enami void * 156 1.18 enami xrealloc(void *p, size_t *siz, size_t req) 157 1.18 enami { 158 1.18 enami 159 1.18 enami if (*siz < req) { 160 1.18 enami if (*siz == 0) 161 1.18 enami *siz = 1; 162 1.18 enami while (*siz < req) 163 1.18 enami *siz <<= 1; 164 1.18 enami p = realloc(p, *siz); 165 1.18 enami if (p == NULL) 166 1.18 enami err(EXIT_FAILURE, "realloc: %lu bytes", 167 1.18 enami (u_long)*siz); 168 1.18 enami } 169 1.18 enami return (p); 170 1.18 enami } 171 1.18 enami 172 1.18 enami struct ktr_entry * 173 1.18 enami getrecord(FILE *fp) 174 1.18 enami { 175 1.18 enami struct ktr_entry *kte; 176 1.18 enami struct ktr_header *kth; 177 1.18 enami char *cp; 178 1.18 enami size_t siz, len; 179 1.18 enami 180 1.18 enami siz = 0; 181 1.18 enami kte = xrealloc(NULL, &siz, sizeof(struct ktr_entry)); 182 1.18 enami kth = &kte->kte_kth; 183 1.18 enami if (fread_tail(kth, sizeof(struct ktr_header), 1, fp) == 0) { 184 1.18 enami free(kte); 185 1.18 enami return (NULL); 186 1.18 enami } 187 1.18 enami 188 1.26 christos if (kth->ktr_len < 0) 189 1.26 christos errx(EXIT_FAILURE, "bogus length 0x%x", kth->ktr_len); 190 1.18 enami len = kth->ktr_len; 191 1.18 enami if (len > 0) { 192 1.18 enami /* + 1 to ensure room for NUL terminate */ 193 1.18 enami kte = xrealloc(kte, &siz, sizeof(struct ktr_entry) + len + 1); 194 1.18 enami if (fread_tail(cp = (char *)(&kte->kte_kth + 1), 195 1.18 enami len, 1, fp) == 0) 196 1.18 enami errx(EXIT_FAILURE, "data too short"); 197 1.18 enami cp[len] = 0; 198 1.18 enami } 199 1.18 enami 200 1.18 enami return (kte); 201 1.18 enami } 202 1.18 enami 203 1.18 enami #define KTE_TYPE(kte) ((kte)->kte_kth.ktr_type) 204 1.18 enami #define KTE_PID(kte) ((kte)->kte_kth.ktr_pid) 205 1.28 ad #define KTE_LID(kte) ((kte)->kte_kth.ktr_lid) 206 1.28 ad #define KTE_MATCH(kte, type, pid, lid) \ 207 1.28 ad (KTE_TYPE(kte) == (type) && KTE_PID(kte) == (pid) && \ 208 1.28 ad KTE_LID(kte) == (lid)) 209 1.18 enami 210 1.18 enami void 211 1.18 enami putpendq(struct ktr_entry *kte) 212 1.18 enami { 213 1.18 enami 214 1.18 enami TAILQ_INSERT_TAIL(&ktependq, kte, kte_list); 215 1.18 enami } 216 1.18 enami 217 1.18 enami void 218 1.18 enami flushpendq(struct ktr_entry *us) 219 1.18 enami { 220 1.18 enami struct ktr_entry *kte, *kte_next; 221 1.35 mlelstv int pid = KTE_PID(us), lid = KTE_LID(us); 222 1.18 enami 223 1.18 enami for (kte = TAILQ_FIRST(&ktependq); kte != NULL; kte = kte_next) { 224 1.18 enami kte_next = TAILQ_NEXT(kte, kte_list); 225 1.35 mlelstv if (KTE_PID(kte) == pid || KTE_LID(kte) == lid) { 226 1.18 enami TAILQ_REMOVE(&ktependq, kte, kte_list); 227 1.18 enami free(kte); 228 1.18 enami } 229 1.18 enami } 230 1.18 enami } 231 1.18 enami 232 1.18 enami struct ktr_entry * 233 1.18 enami getpendq(struct ktr_header *us, int type, struct kteq *kteq) 234 1.18 enami { 235 1.18 enami struct ktr_entry *kte, *kte_next; 236 1.28 ad int pid = us->ktr_pid, lid = us->ktr_lid; 237 1.18 enami 238 1.18 enami if (kteq != NULL) 239 1.18 enami TAILQ_INIT(kteq); 240 1.18 enami for (kte = TAILQ_FIRST(&ktependq); kte != NULL; kte = kte_next) { 241 1.18 enami kte_next = TAILQ_NEXT(kte, kte_list); 242 1.28 ad if (KTE_MATCH(kte, type, pid, lid)) { 243 1.18 enami TAILQ_REMOVE(&ktependq, kte, kte_list); 244 1.18 enami if (kteq != NULL) 245 1.18 enami TAILQ_INSERT_TAIL(kteq, kte, kte_list); 246 1.18 enami else 247 1.18 enami break; 248 1.18 enami } 249 1.18 enami } 250 1.18 enami 251 1.18 enami return (kteq ? TAILQ_FIRST(kteq) : kte); 252 1.18 enami } 253 1.18 enami 254 1.18 enami int 255 1.18 enami dumprecord(int trpoints, FILE *fp) 256 1.1 darrenr { 257 1.18 enami struct ktr_entry *kte; 258 1.18 enami struct ktr_header *kth; 259 1.18 enami 260 1.18 enami kte = getrecord(fp); 261 1.18 enami if (kte == NULL) 262 1.18 enami return (0); 263 1.18 enami 264 1.18 enami kth = &kte->kte_kth; 265 1.18 enami if ((trpoints & (1 << kth->ktr_type)) == 0) { 266 1.18 enami free(kte); 267 1.18 enami goto out; 268 1.18 enami } 269 1.9 jdolecek 270 1.18 enami /* Update context to match currently processed record. */ 271 1.18 enami ectx_sanify(kth->ktr_pid); 272 1.9 jdolecek 273 1.18 enami switch (kth->ktr_type) { 274 1.1 darrenr case KTR_SYSCALL: 275 1.18 enami ktrsyscall(kte); 276 1.1 darrenr break; 277 1.1 darrenr case KTR_SYSRET: 278 1.18 enami ktrsysret(kte); 279 1.1 darrenr break; 280 1.1 darrenr case KTR_NAMEI: 281 1.18 enami putpendq(kte); 282 1.1 darrenr break; 283 1.1 darrenr case KTR_GENIO: 284 1.18 enami putpendq(kte); 285 1.1 darrenr break; 286 1.1 darrenr case KTR_PSIG: 287 1.18 enami ktrpsig(kte); 288 1.1 darrenr break; 289 1.1 darrenr case KTR_CSW: 290 1.18 enami ktrcsw(kte); 291 1.1 darrenr break; 292 1.1 darrenr case KTR_EMUL: 293 1.36 njoly putpendq(kte); 294 1.18 enami break; 295 1.18 enami default: 296 1.18 enami /* 297 1.18 enami * XXX: Other types added recently. 298 1.18 enami */ 299 1.18 enami free(kte); 300 1.1 darrenr break; 301 1.1 darrenr } 302 1.18 enami newline(); 303 1.1 darrenr 304 1.18 enami out: 305 1.18 enami return (1); 306 1.1 darrenr } 307 1.1 darrenr 308 1.1 darrenr void 309 1.18 enami dumpfile(const char *file, int fd, int trpoints) 310 1.1 darrenr { 311 1.1 darrenr FILE *fp; 312 1.1 darrenr 313 1.18 enami if (file == NULL || *file == 0) { 314 1.18 enami if ((fp = fdopen(fd, "r")) == NULL) 315 1.18 enami err(EXIT_FAILURE, "fdopen(%d)", fd); 316 1.18 enami } else if (strcmp(file, "-") == 0) 317 1.1 darrenr fp = stdin; 318 1.18 enami else if ((fp = fopen(file, "r")) == NULL) 319 1.18 enami err(EXIT_FAILURE, "fopen: %s", file); 320 1.1 darrenr 321 1.18 enami for (width = 0; dumprecord(trpoints, fp) != 0;) 322 1.1 darrenr if (tail) 323 1.1 darrenr (void)fflush(stdout); 324 1.18 enami 325 1.18 enami newline(); 326 1.18 enami 327 1.18 enami /* 328 1.18 enami * XXX: Dump pending KTR_SYSCALL if any? 329 1.18 enami */ 330 1.1 darrenr } 331 1.1 darrenr 332 1.1 darrenr int 333 1.18 enami fread_tail(void *buf, int size, int num, FILE *fp) 334 1.1 darrenr { 335 1.1 darrenr int i; 336 1.1 darrenr 337 1.1 darrenr while ((i = fread(buf, size, num, fp)) == 0 && tail) { 338 1.1 darrenr (void)sleep(1); 339 1.5 enami clearerr(fp); 340 1.1 darrenr } 341 1.1 darrenr return (i); 342 1.1 darrenr } 343 1.1 darrenr 344 1.1 darrenr void 345 1.18 enami dumpheader(struct ktr_header *kth) 346 1.1 darrenr { 347 1.24 christos union timeholder { 348 1.24 christos struct timeval tv; 349 1.24 christos struct timespec ts; 350 1.24 christos }; 351 1.24 christos static union timeholder prevtime; 352 1.24 christos union timeholder temp; 353 1.24 christos 354 1.38 mrg temp.tv.tv_sec = temp.tv.tv_usec = 0; 355 1.43 kamil xwprintf("%6d ", kth->ktr_pid); 356 1.32 christos if (kth->ktr_version > KTRFAC_VERSION(KTRFACv0)) 357 1.43 kamil xwprintf("%6d ", kth->ktr_lid); 358 1.43 kamil xwprintf("%-8.*s ", MAXCOMLEN, kth->ktr_comm); 359 1.1 darrenr if (timestamp) { 360 1.1 darrenr if (timestamp == 2) { 361 1.32 christos switch (kth->ktr_version) { 362 1.32 christos case KTRFAC_VERSION(KTRFACv0): 363 1.24 christos if (prevtime.tv.tv_sec == 0) 364 1.24 christos temp.tv.tv_sec = temp.tv.tv_usec = 0; 365 1.24 christos else 366 1.32 christos timersub(&kth->ktr_otv, 367 1.24 christos &prevtime.tv, &temp.tv); 368 1.32 christos prevtime.tv.tv_sec = kth->ktr_otv.tv_sec; 369 1.32 christos prevtime.tv.tv_usec = kth->ktr_otv.tv_usec; 370 1.32 christos break; 371 1.32 christos 372 1.32 christos case KTRFAC_VERSION(KTRFACv1): 373 1.30 christos if (prevtime.ts.tv_sec == 0) 374 1.30 christos temp.ts.tv_sec = temp.ts.tv_nsec = 0; 375 1.30 christos else 376 1.30 christos timespecsub(&kth->ktr_time, 377 1.30 christos &prevtime.ts, &temp.ts); 378 1.32 christos prevtime.ts.tv_sec = kth->ktr_ots.tv_sec; 379 1.32 christos prevtime.ts.tv_nsec = kth->ktr_ots.tv_nsec; 380 1.32 christos break; 381 1.32 christos 382 1.32 christos case KTRFAC_VERSION(KTRFACv2): 383 1.32 christos if (prevtime.ts.tv_sec == 0) 384 1.32 christos temp.ts.tv_sec = temp.ts.tv_nsec = 0; 385 1.32 christos else 386 1.32 christos timespecsub(&kth->ktr_time, 387 1.32 christos &prevtime.ts, &temp.ts); 388 1.32 christos prevtime.ts.tv_sec = kth->ktr_ts.tv_sec; 389 1.32 christos prevtime.ts.tv_nsec = kth->ktr_ts.tv_nsec; 390 1.32 christos break; 391 1.24 christos } 392 1.24 christos } else { 393 1.32 christos switch (kth->ktr_version) { 394 1.32 christos case KTRFAC_VERSION(KTRFACv0): 395 1.32 christos temp.tv.tv_sec = kth->ktr_otv.tv_sec; 396 1.32 christos temp.tv.tv_usec = kth->ktr_otv.tv_usec; 397 1.32 christos break; 398 1.32 christos case KTRFAC_VERSION(KTRFACv1): 399 1.32 christos temp.ts.tv_sec = kth->ktr_ots.tv_sec; 400 1.32 christos temp.ts.tv_nsec = kth->ktr_ots.tv_nsec; 401 1.32 christos break; 402 1.32 christos case KTRFAC_VERSION(KTRFACv2): 403 1.32 christos temp.ts.tv_sec = kth->ktr_ts.tv_sec; 404 1.32 christos temp.ts.tv_nsec = kth->ktr_ts.tv_nsec; 405 1.32 christos break; 406 1.32 christos } 407 1.24 christos } 408 1.32 christos if (kth->ktr_version == KTRFAC_VERSION(KTRFACv0)) 409 1.43 kamil xwprintf("%lld.%06ld ", 410 1.32 christos (long long)temp.tv.tv_sec, (long)temp.tv.tv_usec); 411 1.24 christos else 412 1.43 kamil xwprintf("%lld.%09ld ", 413 1.32 christos (long long)temp.ts.tv_sec, (long)temp.ts.tv_nsec); 414 1.1 darrenr } 415 1.1 darrenr } 416 1.1 darrenr 417 1.1 darrenr void 418 1.18 enami ioctldecode(u_long cmd) 419 1.1 darrenr { 420 1.1 darrenr char dirbuf[4], *dir = dirbuf; 421 1.1 darrenr 422 1.1 darrenr if (cmd & IOC_OUT) 423 1.1 darrenr *dir++ = 'W'; 424 1.1 darrenr if (cmd & IOC_IN) 425 1.1 darrenr *dir++ = 'R'; 426 1.1 darrenr *dir = '\0'; 427 1.1 darrenr 428 1.43 kamil xwprintf(decimal ? ", _IO%s('%c',%ld" : ", _IO%s('%c',%#lx", 429 1.10 is dirbuf, (int) ((cmd >> 8) & 0xff), cmd & 0xff); 430 1.1 darrenr if ((cmd & IOC_VOID) == 0) 431 1.43 kamil xwprintf(decimal ? ",%ld)" : ",%#lx)", 432 1.18 enami (cmd >> 16) & 0xff); 433 1.1 darrenr else 434 1.43 kamil xwprintf(")"); 435 1.1 darrenr } 436 1.1 darrenr 437 1.18 enami void 438 1.18 enami nameiargprint(const char *prefix, struct ktr_header *kth, 439 1.18 enami register_t **ap, int *argsize) 440 1.18 enami { 441 1.18 enami struct ktr_entry *kte; 442 1.18 enami 443 1.18 enami if (*argsize == 0) 444 1.18 enami errx(EXIT_FAILURE, "argument expected"); 445 1.18 enami /* 446 1.18 enami * XXX: binary emulation mode. 447 1.18 enami */ 448 1.18 enami kte = getpendq(kth, KTR_NAMEI, NULL); 449 1.18 enami if (kte == NULL) 450 1.18 enami argprint(prefix, ap, argsize); 451 1.18 enami else { 452 1.43 kamil xwprintf("%s", prefix); 453 1.18 enami nameiprint(&kte->kte_kth); 454 1.18 enami free(kte); 455 1.18 enami (*ap)++; 456 1.18 enami *argsize -= sizeof(register_t); 457 1.18 enami } 458 1.18 enami } 459 1.18 enami 460 1.18 enami void 461 1.18 enami syscallnameprint(int code) 462 1.18 enami { 463 1.18 enami 464 1.18 enami if (code >= cur_emul->nsysnames || code < 0) 465 1.43 kamil xwprintf("[%d]", code); 466 1.18 enami else 467 1.43 kamil xwprintf("%s", cur_emul->sysnames[code]); 468 1.18 enami } 469 1.18 enami 470 1.18 enami void 471 1.18 enami argprint(const char *prefix, register_t **ap, int *argsize) 472 1.18 enami { 473 1.18 enami 474 1.18 enami if (decimal) 475 1.43 kamil xwprintf("%s%ld", prefix, (long)**ap); 476 1.18 enami else 477 1.43 kamil xwprintf("%s%#lx", prefix, (long)**ap); 478 1.18 enami (*ap)++; 479 1.18 enami *argsize -= sizeof(register_t); 480 1.18 enami } 481 1.18 enami 482 1.18 enami void 483 1.18 enami syscallprint(struct ktr_header *kth) 484 1.18 enami { 485 1.18 enami struct ktr_syscall *ktr = (struct ktr_syscall *)(kth + 1); 486 1.18 enami register_t *ap; 487 1.21 he const char *s; 488 1.18 enami int argsize; 489 1.18 enami 490 1.18 enami syscallnameprint(ktr->ktr_code); 491 1.18 enami 492 1.18 enami /* 493 1.18 enami * Arguments processing. 494 1.18 enami */ 495 1.18 enami argsize = ktr->ktr_argsize; 496 1.18 enami if (argsize == 0) { 497 1.43 kamil xwprintf("("); 498 1.18 enami goto noargument; 499 1.18 enami } 500 1.18 enami 501 1.18 enami ap = (register_t *)(ktr + 1); 502 1.18 enami if (!fancy) 503 1.18 enami goto print_first; 504 1.18 enami 505 1.18 enami switch (ktr->ktr_code) { 506 1.18 enami /* 507 1.18 enami * All these have a path as the first param. 508 1.18 enami * The order is same as syscalls.master. 509 1.18 enami */ 510 1.18 enami case SYS_open: 511 1.18 enami case SYS_link: 512 1.18 enami case SYS_unlink: 513 1.18 enami case SYS_chdir: 514 1.32 christos case SYS___mknod50: 515 1.18 enami case SYS_chmod: 516 1.18 enami case SYS_chown: 517 1.18 enami case SYS_unmount: 518 1.18 enami case SYS_access: 519 1.18 enami case SYS_chflags: 520 1.18 enami case SYS_acct: 521 1.18 enami case SYS_revoke: 522 1.18 enami case SYS_symlink: 523 1.18 enami case SYS_readlink: 524 1.18 enami case SYS_execve: 525 1.18 enami case SYS_chroot: 526 1.18 enami case SYS_rename: 527 1.18 enami case SYS_mkfifo: 528 1.18 enami case SYS_mkdir: 529 1.18 enami case SYS_rmdir: 530 1.32 christos case SYS___utimes50: 531 1.37 bouyer case SYS_compat_50_quotactl: 532 1.39 dholland case SYS___quotactl: 533 1.44 christos case SYS___statvfs190: 534 1.25 martin case SYS_compat_30_getfh: 535 1.18 enami case SYS_pathconf: 536 1.18 enami case SYS_truncate: 537 1.18 enami case SYS_undelete: 538 1.18 enami case SYS___posix_rename: 539 1.18 enami case SYS_lchmod: 540 1.18 enami case SYS_lchown: 541 1.32 christos case SYS___lutimes50: 542 1.32 christos case SYS___stat50: 543 1.32 christos case SYS___lstat50: 544 1.18 enami case SYS___posix_chown: 545 1.18 enami case SYS___posix_lchown: 546 1.18 enami case SYS_lchflags: 547 1.25 martin case SYS___getfh30: 548 1.18 enami nameiargprint("(", kth, &ap, &argsize); 549 1.18 enami 550 1.18 enami /* 551 1.18 enami * 2nd argument is also pathname. 552 1.18 enami */ 553 1.18 enami switch (ktr->ktr_code) { 554 1.18 enami case SYS_link: 555 1.18 enami case SYS_rename: 556 1.18 enami case SYS___posix_rename: 557 1.18 enami nameiargprint(", ", kth, &ap, &argsize); 558 1.18 enami break; 559 1.18 enami } 560 1.18 enami break; 561 1.18 enami 562 1.18 enami case SYS_compat_16___sigaction14 : 563 1.45 mlelstv if ((int)*ap < 0 || (int)*ap >= MAXSIGNALS) 564 1.46 mlelstv xwprintf("(%d", (int)*ap); 565 1.46 mlelstv else 566 1.45 mlelstv xwprintf("(%s", signals[(int)*ap].name); 567 1.18 enami ap++; 568 1.18 enami argsize -= sizeof(register_t); 569 1.18 enami break; 570 1.18 enami 571 1.18 enami case SYS_ioctl : 572 1.18 enami argprint("(", &ap, &argsize); 573 1.18 enami if ((s = ioctlname(*ap)) != NULL) 574 1.43 kamil xwprintf(", %s", s); 575 1.18 enami else 576 1.18 enami ioctldecode(*ap); 577 1.18 enami ap++; 578 1.18 enami argsize -= sizeof(register_t); 579 1.18 enami break; 580 1.18 enami 581 1.18 enami case SYS_ptrace : 582 1.27 mrg if ((long)*ap >= 0 && 583 1.47 kamil *ap < (register_t)__arraycount(ptrace_ops)) 584 1.43 kamil xwprintf("(%s", ptrace_ops[*ap]); 585 1.47 kamil #ifdef PT_MACHDEP_STRINGS 586 1.47 kamil else if (*ap >= PT_FIRSTMACH && 587 1.47 kamil *ap - PT_FIRSTMACH < (register_t) 588 1.47 kamil __arraycount(ptrace_machdep_ops)) 589 1.47 kamil xwprintf("(%s", ptrace_machdep_ops[*ap - PT_FIRSTMACH]); 590 1.47 kamil #endif 591 1.1 darrenr else 592 1.43 kamil xwprintf("(%ld", (long)*ap); 593 1.18 enami ap++; 594 1.18 enami argsize -= sizeof(register_t); 595 1.18 enami break; 596 1.18 enami 597 1.18 enami default: 598 1.18 enami print_first: 599 1.18 enami argprint("(", &ap, &argsize); 600 1.18 enami break; 601 1.18 enami } 602 1.18 enami 603 1.18 enami /* Print rest of argument. */ 604 1.18 enami while (argsize > 0) 605 1.18 enami argprint(", ", &ap, &argsize); 606 1.18 enami 607 1.18 enami noargument: 608 1.43 kamil xwprintf(")"); 609 1.18 enami } 610 1.18 enami 611 1.18 enami void 612 1.18 enami ktrsyscall(struct ktr_entry *kte) 613 1.18 enami { 614 1.18 enami struct ktr_header *kth = &kte->kte_kth; 615 1.18 enami struct ktr_syscall *ktr = (struct ktr_syscall *)(kth + 1); 616 1.18 enami 617 1.18 enami switch (ktr->ktr_code) { 618 1.18 enami case SYS_exit: 619 1.18 enami dumpheader(kth); 620 1.18 enami syscallprint(kth); 621 1.18 enami break; 622 1.18 enami default: 623 1.18 enami putpendq(kte); 624 1.18 enami return; 625 1.1 darrenr } 626 1.1 darrenr 627 1.18 enami free(kte); 628 1.1 darrenr } 629 1.1 darrenr 630 1.1 darrenr void 631 1.18 enami sysretprint(struct ktr_header *kth) 632 1.1 darrenr { 633 1.18 enami struct ktr_sysret *ktr = (struct ktr_sysret *)(kth + 1); 634 1.18 enami register_t ret = ktr->ktr_retval; 635 1.18 enami int error = ktr->ktr_error; 636 1.1 darrenr 637 1.18 enami indent(50); 638 1.1 darrenr if (error == EJUSTRETURN) 639 1.43 kamil xwprintf(" JUSTRETURN"); 640 1.1 darrenr else if (error == ERESTART) 641 1.43 kamil xwprintf(" RESTART"); 642 1.1 darrenr else if (error) { 643 1.43 kamil xwprintf(" Err#%d", error); 644 1.45 mlelstv if (error < MAXERRNOS && error >= 0) 645 1.43 kamil xwprintf(" %s", errnos[error].name); 646 1.1 darrenr } else 647 1.18 enami switch (ktr->ktr_code) { 648 1.42 njoly case SYS_mremap: 649 1.18 enami case SYS_mmap: 650 1.43 kamil xwprintf(" = %p", (void *)(intptr_t)ret); 651 1.18 enami break; 652 1.18 enami default: 653 1.43 kamil xwprintf(" = %ld", (long)ret); 654 1.33 lukem if (kth->ktr_len > (int)offsetof(struct ktr_sysret, 655 1.18 enami ktr_retval_1) && ktr->ktr_retval_1 != 0) 656 1.43 kamil xwprintf(", %ld", (long)ktr->ktr_retval_1); 657 1.18 enami break; 658 1.18 enami } 659 1.18 enami } 660 1.18 enami 661 1.18 enami void 662 1.18 enami ktrsysret(struct ktr_entry *kte) 663 1.18 enami { 664 1.18 enami struct ktr_header *kth = &kte->kte_kth; 665 1.18 enami struct ktr_sysret *ktr = (struct ktr_sysret *)(kth + 1); 666 1.36 njoly struct ktr_entry *emul; 667 1.18 enami struct ktr_entry *genio; 668 1.22 he struct ktr_entry *syscall_ent; 669 1.18 enami 670 1.18 enami dumpheader(kth); 671 1.18 enami 672 1.18 enami /* Print syscall name and arguments. */ 673 1.22 he syscall_ent = getpendq(kth, KTR_SYSCALL, NULL); 674 1.28 ad if (syscall_ent == NULL) { 675 1.18 enami /* 676 1.48 rillig * Possibly a child of fork/vfork, or tracing of 677 1.18 enami * process started during system call. 678 1.18 enami */ 679 1.18 enami syscallnameprint(ktr->ktr_code); 680 1.28 ad } else { 681 1.22 he syscallprint(&syscall_ent->kte_kth); 682 1.22 he free(syscall_ent); 683 1.18 enami } 684 1.18 enami 685 1.18 enami /* Print return value and an error if any. */ 686 1.18 enami sysretprint(kth); 687 1.18 enami 688 1.18 enami genio = getpendq(kth, KTR_GENIO, NULL); 689 1.18 enami if (genio != NULL) { 690 1.18 enami genioprint(&genio->kte_kth); 691 1.18 enami free(genio); 692 1.18 enami } 693 1.18 enami 694 1.36 njoly emul = getpendq(kth, KTR_EMUL, NULL); 695 1.36 njoly if (emul != NULL) { 696 1.36 njoly newline(); 697 1.36 njoly ktremul(emul); 698 1.36 njoly } 699 1.36 njoly 700 1.18 enami flushpendq(kte); 701 1.18 enami free(kte); 702 1.18 enami } 703 1.18 enami 704 1.18 enami void 705 1.18 enami nameiprint(struct ktr_header *kth) 706 1.18 enami { 707 1.18 enami 708 1.43 kamil xwprintf("\"%.*s\"", kth->ktr_len, (char *)(kth + 1)); 709 1.1 darrenr } 710 1.1 darrenr 711 1.18 enami #ifdef notused 712 1.1 darrenr void 713 1.18 enami ktrnamei(struct ktr_entry *kte) 714 1.1 darrenr { 715 1.18 enami struct ktr_header *kth = &kte->kte_kth; 716 1.18 enami 717 1.18 enami dumpheader(kth); 718 1.43 kamil xwprintf("namei("); 719 1.18 enami nameiprint(kth); 720 1.43 kamil xwprintf(")"); 721 1.18 enami 722 1.18 enami free(kte); 723 1.1 darrenr } 724 1.18 enami #endif 725 1.1 darrenr 726 1.1 darrenr void 727 1.18 enami ktremul(struct ktr_entry *kte) 728 1.1 darrenr { 729 1.18 enami struct ktr_header *kth = &kte->kte_kth; 730 1.18 enami char *emul = (char *)(kth + 1); 731 1.1 darrenr 732 1.18 enami dumpheader(kth); 733 1.43 kamil xwprintf("emul(%s)", emul); 734 1.18 enami setemul(emul, kth->ktr_pid, 1); 735 1.18 enami 736 1.18 enami free(kte); 737 1.1 darrenr } 738 1.1 darrenr 739 1.1 darrenr void 740 1.18 enami genioprint(struct ktr_header *kth) 741 1.1 darrenr { 742 1.18 enami struct ktr_genio *ktr = (struct ktr_genio *)(kth + 1); 743 1.1 darrenr static int screenwidth = 0; 744 1.18 enami int datalen = kth->ktr_len - sizeof(struct ktr_genio); 745 1.18 enami /* 746 1.18 enami * Need to be unsigned type so that positive value is passed 747 1.18 enami * to vis(), which will call isgraph(). 748 1.18 enami */ 749 1.18 enami unsigned char *dp = (unsigned char *)(ktr + 1); 750 1.18 enami int w; 751 1.18 enami char visbuf[5]; 752 1.18 enami 753 1.1 darrenr if (screenwidth == 0) { 754 1.1 darrenr struct winsize ws; 755 1.1 darrenr 756 1.1 darrenr if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && 757 1.1 darrenr ws.ws_col > 8) 758 1.1 darrenr screenwidth = ws.ws_col; 759 1.1 darrenr else 760 1.1 darrenr screenwidth = 80; 761 1.1 darrenr } 762 1.1 darrenr 763 1.1 darrenr if (maxdata && datalen > maxdata) 764 1.1 darrenr datalen = maxdata; 765 1.18 enami newline(); 766 1.43 kamil xwprintf(" \""); 767 1.1 darrenr for (; datalen > 0; datalen--, dp++) { 768 1.18 enami (void) vis(visbuf, *dp, VIS_NL|VIS_TAB|VIS_CSTYLE, 769 1.18 enami /* We put NUL at the end of buffer when reading */ 770 1.18 enami *(dp + 1)); 771 1.1 darrenr visbuf[4] = '\0'; 772 1.18 enami w = strlen(visbuf); 773 1.18 enami if (width + w + 2 >= screenwidth) 774 1.1 darrenr break; 775 1.43 kamil xwprintf("%s", visbuf); 776 1.18 enami if (width + 2 >= screenwidth) 777 1.1 darrenr break; 778 1.1 darrenr } 779 1.43 kamil xwprintf("\""); 780 1.1 darrenr } 781 1.1 darrenr 782 1.18 enami #ifdef notused 783 1.1 darrenr void 784 1.18 enami ktrgenio(struct ktr_entry *kte) 785 1.1 darrenr { 786 1.18 enami struct ktr_header *kth = &kte->kte_kth; 787 1.18 enami struct ktr_genio *ktr = (struct ktr_genio *)(kth + 1); 788 1.18 enami 789 1.18 enami dumpheader(kth); 790 1.43 kamil xwprintf("genio fd %d %s", 791 1.18 enami ktr->ktr_fd, ktr->ktr_rw ? "write" : "read"); 792 1.18 enami genioprint(kth); 793 1.18 enami 794 1.18 enami free(kte); 795 1.18 enami } 796 1.18 enami #endif 797 1.18 enami 798 1.18 enami void 799 1.18 enami ktrpsig(struct ktr_entry *kte) 800 1.18 enami { 801 1.18 enami struct ktr_header *kth = &kte->kte_kth; 802 1.18 enami struct ktr_psig *psig = (struct ktr_psig *)(kth + 1); 803 1.18 enami 804 1.18 enami dumpheader(kth); 805 1.43 kamil xwprintf("SIG%s ", sys_signame[psig->signo]); 806 1.1 darrenr if (psig->action == SIG_DFL) 807 1.43 kamil xwprintf("SIG_DFL"); 808 1.1 darrenr else { 809 1.43 kamil xwprintf("caught handler=0x%lx mask=0x%lx code=0x%x", 810 1.7 sommerfe (u_long)psig->action, (unsigned long)psig->mask.__bits[0], 811 1.7 sommerfe psig->code); 812 1.1 darrenr } 813 1.18 enami 814 1.18 enami free(kte); 815 1.1 darrenr } 816 1.1 darrenr 817 1.1 darrenr void 818 1.18 enami ktrcsw(struct ktr_entry *kte) 819 1.1 darrenr { 820 1.18 enami struct ktr_header *kth = &kte->kte_kth; 821 1.18 enami struct ktr_csw *cs = (struct ktr_csw *)(kth + 1); 822 1.18 enami 823 1.18 enami dumpheader(kth); 824 1.43 kamil xwprintf("%s %s", cs->out ? "stop" : "resume", 825 1.1 darrenr cs->user ? "user" : "kernel"); 826 1.18 enami 827 1.18 enami free(kte); 828 1.1 darrenr } 829