kdump.c 48.6 KB
Newer Older
1
/*-
2
3
 * SPDX-License-Identifier: BSD-3-Clause
 *
4
5
6
7
8
9
10
11
12
13
14
 * Copyright (c) 1988, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
Warner Losh's avatar
Warner Losh committed
15
 * 3. Neither the name of the University nor the names of its contributors
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef lint
33
static const char copyright[] =
34
35
36
37
38
"@(#) Copyright (c) 1988, 1993\n\
	The Regents of the University of California.  All rights reserved.\n";
#endif /* not lint */

#ifndef lint
39
#if 0
40
static char sccsid[] = "@(#)kdump.c	8.1 (Berkeley) 6/6/93";
41
#endif
42
#endif /* not lint */
David E. O'Brien's avatar
David E. O'Brien committed
43
44
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
45

46
#define _WANT_KERNEL_ERRNO
47
48
49
50
#ifdef __LP64__
#define	_WANT_KEVENT32
#endif
#define	_WANT_FREEBSD11_KEVENT
Dmitry Chagin's avatar
Dmitry Chagin committed
51
#define	_WANT_FREEBSD_BITSET
52
#include <sys/param.h>
53
#include <sys/capsicum.h>
Dmitry Chagin's avatar
Dmitry Chagin committed
54
55
#include <sys/_bitset.h>
#include <sys/bitset.h>
56
57
58
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/uio.h>
59
#include <sys/event.h>
60
#include <sys/ktrace.h>
61
#include <sys/mman.h>
62
#include <sys/ioctl.h>
63
#include <sys/socket.h>
64
#include <sys/stat.h>
65
#include <sys/sysent.h>
66
#include <sys/umtx.h>
67
#include <sys/un.h>
68
#include <sys/queue.h>
69
#include <sys/wait.h>
70
#ifdef WITH_CASPER
71
72
#include <sys/nv.h>
#endif
73
#include <arpa/inet.h>
74
#include <netinet/in.h>
75
#include <ctype.h>
76
#include <capsicum_helpers.h>
77
#include <err.h>
78
79
#include <grp.h>
#include <inttypes.h>
80
#include <locale.h>
81
#include <netdb.h>
Pawel Jakub Dawidek's avatar
Pawel Jakub Dawidek committed
82
#include <nl_types.h>
83
#include <pwd.h>
84
#include <stddef.h>
85
86
87
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
88
#include <sysdecode.h>
89
#include <time.h>
90
91
#include <unistd.h>
#include <vis.h>
92
#include "ktrace.h"
93
#include "kdump.h"
94

95
#ifdef WITH_CASPER
96
97
98
99
100
101
#include <libcasper.h>

#include <casper/cap_grp.h>
#include <casper/cap_pwd.h>
#endif

102
int fetchprocinfo(struct ktr_header *, u_int *);
103
u_int findabi(struct ktr_header *);
104
int fread_tail(void *, int, int);
105
void dumpheader(struct ktr_header *, u_int);
106
107
void ktrsyscall(struct ktr_syscall *, u_int);
void ktrsysret(struct ktr_sysret *, u_int);
108
void ktrnamei(char *, int);
Peter Wemm's avatar
Peter Wemm committed
109
110
void hexdump(char *, int, int);
void visdump(char *, int, int);
111
void ktrgenio(struct ktr_genio *, int);
112
void ktrpsig(struct ktr_psig *);
113
void ktrcsw(struct ktr_csw *);
114
void ktrcsw_old(struct ktr_csw_old *);
115
void ktruser(int, void *);
116
void ktrcaprights(cap_rights_t *);
117
void ktritimerval(struct itimerval *it);
118
119
120
void ktrsockaddr(struct sockaddr *);
void ktrstat(struct stat *);
void ktrstruct(char *, size_t);
121
void ktrcapfail(struct ktr_cap_fail *);
122
123
void ktrfault(struct ktr_fault *);
void ktrfaultend(struct ktr_faultend *);
124
125
void ktrkevent(struct kevent *);
void ktrstructarray(struct ktr_struct_array *, size_t);
Dmitry Chagin's avatar
Dmitry Chagin committed
126
void ktrbitset(char *, struct bitset *, size_t);
127
128
void ktrsyscall_freebsd(struct ktr_syscall *ktr, register_t **resip,
    int *resnarg, char *resc, u_int sv_flags);
129
130
void usage(void);

131
132
133
134
135
#define	TIMESTAMP_NONE		0x0
#define	TIMESTAMP_ABSOLUTE	0x1
#define	TIMESTAMP_ELAPSED	0x2
#define	TIMESTAMP_RELATIVE	0x4

136
137
bool decimal, fancy = true, resolv;
static bool abiflag, suppressdata, syscallno, tail, threads;
138
static int timestamp, maxdata;
139
140
static const char *tracefile = DEF_TRACEFILE;
static struct ktr_header ktr_header;
141

142
#define TIME_FORMAT	"%b %e %T %Y"
143
144
#define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)

145
146
147
148
149
150
151
struct proc_info
{
	TAILQ_ENTRY(proc_info)	info;
	u_int			sv_flags;
	pid_t			pid;
};

152
static TAILQ_HEAD(trace_procs, proc_info) trace_procs;
153

154
#ifdef WITH_CASPER
155
static cap_channel_t *cappwd, *capgrp;
156

157
158
159
160
161
162
163
164
static int
cappwdgrp_setup(cap_channel_t **cappwdp, cap_channel_t **capgrpp)
{
	cap_channel_t *capcas, *cappwdloc, *capgrploc;
	const char *cmds[1], *fields[1];

	capcas = cap_init();
	if (capcas == NULL) {
165
166
		err(1, "unable to create casper process");
		exit(1);
167
168
169
170
171
172
173
174
175
176
	}
	cappwdloc = cap_service_open(capcas, "system.pwd");
	capgrploc = cap_service_open(capcas, "system.grp");
	/* Casper capability no longer needed. */
	cap_close(capcas);
	if (cappwdloc == NULL || capgrploc == NULL) {
		if (cappwdloc == NULL)
			warn("unable to open system.pwd service");
		if (capgrploc == NULL)
			warn("unable to open system.grp service");
177
		exit(1);
178
179
180
	}
	/* Limit system.pwd to only getpwuid() function and pw_name field. */
	cmds[0] = "getpwuid";
181
182
	if (cap_pwd_limit_cmds(cappwdloc, cmds, 1) < 0)
		err(1, "unable to limit system.pwd service");
183
	fields[0] = "pw_name";
184
185
	if (cap_pwd_limit_fields(cappwdloc, fields, 1) < 0)
		err(1, "unable to limit system.pwd service");
186
187
	/* Limit system.grp to only getgrgid() function and gr_name field. */
	cmds[0] = "getgrgid";
188
189
	if (cap_grp_limit_cmds(capgrploc, cmds, 1) < 0)
		err(1, "unable to limit system.grp service");
190
	fields[0] = "gr_name";
191
192
	if (cap_grp_limit_fields(capgrploc, fields, 1) < 0)
		err(1, "unable to limit system.grp service");
193
194
195
196
197

	*cappwdp = cappwdloc;
	*capgrpp = capgrploc;
	return (0);
}
198
#endif	/* WITH_CASPER */
199

200
void
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
print_integer_arg(const char *(*decoder)(int), int value)
{
	const char *str;

	str = decoder(value);
	if (str != NULL)
		printf("%s", str);
	else {
		if (decimal)
			printf("<invalid=%d>", value);
		else
			printf("<invalid=%#x>", value);
	}
}

/* Like print_integer_arg but unknown values are treated as valid. */
217
void
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
print_integer_arg_valid(const char *(*decoder)(int), int value)
{
	const char *str;

	str = decoder(value);
	if (str != NULL)
		printf("%s", str);
	else {
		if (decimal)
			printf("%d", value);
		else
			printf("%#x", value);
	}
}

233
bool
234
235
236
237
238
239
240
print_mask_arg_part(bool (*decoder)(FILE *, int, int *), int value, int *rem)
{

	printf("%#x<", value);
	return (decoder(stdout, value, rem));
}

241
void
242
243
244
245
246
print_mask_arg(bool (*decoder)(FILE *, int, int *), int value)
{
	bool invalid;
	int rem;

247
	invalid = !print_mask_arg_part(decoder, value, &rem);
248
249
250
251
252
	printf(">");
	if (invalid)
		printf("<invalid>%u", rem);
}

253
void
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
print_mask_arg0(bool (*decoder)(FILE *, int, int *), int value)
{
	bool invalid;
	int rem;

	if (value == 0) {
		printf("0");
		return;
	}
	printf("%#x<", value);
	invalid = !decoder(stdout, value, &rem);
	printf(">");
	if (invalid)
		printf("<invalid>%u", rem);
}

static void
decode_fileflags(fflags_t value)
{
	bool invalid;
	fflags_t rem;

	if (value == 0) {
		printf("0");
		return;
	}
	printf("%#x<", value);
	invalid = !sysdecode_fileflags(stdout, value, &rem);
	printf(">");
	if (invalid)
		printf("<invalid>%u", rem);
}

287
void
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
decode_filemode(int value)
{
	bool invalid;
	int rem;

	if (value == 0) {
		printf("0");
		return;
	}
	printf("%#o<", value);
	invalid = !sysdecode_filemode(stdout, value, &rem);
	printf(">");
	if (invalid)
		printf("<invalid>%u", rem);
}

304
void
305
306
307
308
309
310
311
312
313
314
315
316
print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), uint32_t value)
{
	bool invalid;
	uint32_t rem;

	printf("%#x<", value);
	invalid = !decoder(stdout, value, &rem);
	printf(">");
	if (invalid)
		printf("<invalid>%u", rem);
}

317
void
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
print_mask_argul(bool (*decoder)(FILE *, u_long, u_long *), u_long value)
{
	bool invalid;
	u_long rem;

	if (value == 0) {
		printf("0");
		return;
	}
	printf("%#lx<", value);
	invalid = !decoder(stdout, value, &rem);
	printf(">");
	if (invalid)
		printf("<invalid>%lu", rem);
}

334
335
int
main(int argc, char *argv[])
336
337
{
	int ch, ktrlen, size;
338
	void *m;
339
	int trpoints = ALL_POINTS;
340
	int drop_logged;
Peter Wemm's avatar
Peter Wemm committed
341
	pid_t pid = 0;
342
	u_int sv_flags;
343

344
	setlocale(LC_CTYPE, "");
Andrey A. Chernov's avatar
Andrey A. Chernov committed
345

346
347
	timestamp = TIMESTAMP_NONE;

348
	while ((ch = getopt(argc,argv,"f:dElm:np:AHRrSsTt:")) != -1)
349
		switch (ch) {
350
		case 'A':
351
			abiflag = true;
352
			break;
353
354
355
356
		case 'f':
			tracefile = optarg;
			break;
		case 'd':
357
			decimal = true;
358
359
			break;
		case 'l':
360
			tail = true;
361
362
363
364
365
			break;
		case 'm':
			maxdata = atoi(optarg);
			break;
		case 'n':
366
			fancy = false;
367
			break;
Peter Wemm's avatar
Peter Wemm committed
368
369
370
		case 'p':
			pid = atoi(optarg);
			break;
371
		case 'r':
372
			resolv = true;
373
			break;
374
		case 'S':
375
			syscallno = true;
376
			break;
377
		case 's':
378
			suppressdata = true;
379
			break;
380
		case 'E':
381
			timestamp |= TIMESTAMP_ELAPSED;
382
			break;
383
		case 'H':
384
			threads = true;
385
			break;
386
		case 'R':
387
			timestamp |= TIMESTAMP_RELATIVE;
388
389
			break;
		case 'T':
390
			timestamp |= TIMESTAMP_ABSOLUTE;
391
392
393
			break;
		case 't':
			trpoints = getpoints(optarg);
394
395
			if (trpoints < 0)
				errx(1, "unknown trace point in %s", optarg);
396
397
398
399
400
			break;
		default:
			usage();
		}

401
	if (argc > optind)
402
403
		usage();

404
	m = malloc(size = 1025);
405
406
	if (m == NULL)
		errx(1, "%s", strerror(ENOMEM));
Simon J. Gerraty's avatar
Simon J. Gerraty committed
407
	if (strcmp(tracefile, "-") != 0)
408
409
		if (!freopen(tracefile, "r", stdin))
			err(1, "%s", tracefile);
Pawel Jakub Dawidek's avatar
Pawel Jakub Dawidek committed
410

411
412
413
	caph_cache_catpages();
	caph_cache_tzdata();

414
#ifdef WITH_CASPER
415
	if (resolv) {
416
417
418
419
420
		if (cappwdgrp_setup(&cappwd, &capgrp) < 0) {
			cappwd = NULL;
			capgrp = NULL;
		}
	}
421
	if (!resolv || (cappwd != NULL && capgrp != NULL)) {
422
		if (caph_enter() < 0)
423
424
425
			err(1, "unable to enter capability mode");
	}
#else
426
	if (!resolv) {
427
		if (caph_enter() < 0)
428
429
			err(1, "unable to enter capability mode");
	}
430
#endif
431
432
	if (caph_limit_stdio() == -1)
		err(1, "unable to limit stdio");
Pawel Jakub Dawidek's avatar
Pawel Jakub Dawidek committed
433

434
	TAILQ_INIT(&trace_procs);
435
	drop_logged = 0;
436
	while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
437
438
		if (ktr_header.ktr_type & KTR_DROP) {
			ktr_header.ktr_type &= ~KTR_DROP;
439
			if (!drop_logged && threads) {
440
				printf(
441
442
443
444
445
				    "%6jd %6jd %-8.*s Events dropped.\n",
				    (intmax_t)ktr_header.ktr_pid,
				    ktr_header.ktr_tid > 0 ?
				    (intmax_t)ktr_header.ktr_tid : 0,
				    MAXCOMLEN, ktr_header.ktr_comm);
446
447
				drop_logged = 1;
			} else if (!drop_logged) {
448
				printf("%6jd %-8.*s Events dropped.\n",
449
				    (intmax_t)ktr_header.ktr_pid, MAXCOMLEN,
450
451
452
453
				    ktr_header.ktr_comm);
				drop_logged = 1;
			}
		}
454
455
		if ((ktrlen = ktr_header.ktr_len) < 0)
			errx(1, "bogus length 0x%x", ktrlen);
456
		if (ktrlen > size) {
457
			m = realloc(m, ktrlen+1);
458
459
			if (m == NULL)
				errx(1, "%s", strerror(ENOMEM));
460
461
			size = ktrlen;
		}
462
463
		if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
			errx(1, "data too short");
464
465
		if (fetchprocinfo(&ktr_header, (u_int *)m) != 0)
			continue;
466
467
		if (pid && ktr_header.ktr_pid != pid &&
		    ktr_header.ktr_tid != pid)
Peter Wemm's avatar
Peter Wemm committed
468
			continue;
469
470
		if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
			continue;
471
472
		sv_flags = findabi(&ktr_header);
		dumpheader(&ktr_header, sv_flags);
473
		drop_logged = 0;
474
475
		switch (ktr_header.ktr_type) {
		case KTR_SYSCALL:
476
			ktrsyscall((struct ktr_syscall *)m, sv_flags);
477
478
			break;
		case KTR_SYSRET:
479
			ktrsysret((struct ktr_sysret *)m, sv_flags);
480
481
			break;
		case KTR_NAMEI:
482
		case KTR_SYSCTL:
483
484
485
486
487
488
			ktrnamei(m, ktrlen);
			break;
		case KTR_GENIO:
			ktrgenio((struct ktr_genio *)m, ktrlen);
			break;
		case KTR_PSIG:
489
			ktrpsig((struct ktr_psig *)m);
490
491
			break;
		case KTR_CSW:
492
493
494
495
			if (ktrlen == sizeof(struct ktr_csw_old))
				ktrcsw_old((struct ktr_csw_old *)m);
			else
				ktrcsw((struct ktr_csw *)m);
496
			break;
497
		case KTR_USER:
498
			ktruser(ktrlen, m);
499
			break;
500
501
502
		case KTR_STRUCT:
			ktrstruct(m, ktrlen);
			break;
503
504
		case KTR_CAPFAIL:
			ktrcapfail((struct ktr_cap_fail *)m);
505
506
507
508
509
510
511
			break;
		case KTR_FAULT:
			ktrfault((struct ktr_fault *)m);
			break;
		case KTR_FAULTEND:
			ktrfaultend((struct ktr_faultend *)m);
			break;
512
513
514
		case KTR_STRUCT_ARRAY:
			ktrstructarray((struct ktr_struct_array *)m, ktrlen);
			break;
515
516
517
		default:
			printf("\n");
			break;
518
519
		}
		if (tail)
520
			fflush(stdout);
521
	}
522
	return 0;
523
524
}

525
526
int
fread_tail(void *buf, int size, int num)
527
528
529
530
{
	int i;

	while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
531
		sleep(1);
532
533
534
535
536
		clearerr(stdin);
	}
	return (i);
}

537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
int
fetchprocinfo(struct ktr_header *kth, u_int *flags)
{
	struct proc_info *pi;

	switch (kth->ktr_type) {
	case KTR_PROCCTOR:
		TAILQ_FOREACH(pi, &trace_procs, info) {
			if (pi->pid == kth->ktr_pid) {
				TAILQ_REMOVE(&trace_procs, pi, info);
				break;
			}
		}
		pi = malloc(sizeof(struct proc_info));
		if (pi == NULL)
			errx(1, "%s", strerror(ENOMEM));
		pi->sv_flags = *flags;
		pi->pid = kth->ktr_pid;
		TAILQ_INSERT_TAIL(&trace_procs, pi, info);
		return (1);

	case KTR_PROCDTOR:
		TAILQ_FOREACH(pi, &trace_procs, info) {
			if (pi->pid == kth->ktr_pid) {
				TAILQ_REMOVE(&trace_procs, pi, info);
				free(pi);
				break;
			}
		}
		return (1);
	}

	return (0);
}

u_int
573
findabi(struct ktr_header *kth)
574
575
576
577
578
{
	struct proc_info *pi;

	TAILQ_FOREACH(pi, &trace_procs, info) {
		if (pi->pid == kth->ktr_pid) {
579
			return (pi->sv_flags);
580
581
		}
	}
582
	return (0);
583
584
}

585
void
586
dumpheader(struct ktr_header *kth, u_int sv_flags)
587
588
{
	static char unknown[64];
589
590
	static struct timeval prevtime, prevtime_e;
	struct timeval temp;
591
592
	const char *abi;
	const char *arch;
593
	const char *type;
594
	const char *sign;
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

	switch (kth->ktr_type) {
	case KTR_SYSCALL:
		type = "CALL";
		break;
	case KTR_SYSRET:
		type = "RET ";
		break;
	case KTR_NAMEI:
		type = "NAMI";
		break;
	case KTR_GENIO:
		type = "GIO ";
		break;
	case KTR_PSIG:
		type = "PSIG";
		break;
	case KTR_CSW:
613
		type = "CSW ";
614
		break;
615
616
617
	case KTR_USER:
		type = "USER";
		break;
618
	case KTR_STRUCT:
619
	case KTR_STRUCT_ARRAY:
620
621
		type = "STRU";
		break;
622
623
624
	case KTR_SYSCTL:
		type = "SCTL";
		break;
625
626
627
	case KTR_CAPFAIL:
		type = "CAP ";
		break;
628
629
630
631
632
633
	case KTR_FAULT:
		type = "PFLT";
		break;
	case KTR_FAULTEND:
		type = "PRET";
		break;
634
	default:
635
		sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
636
637
638
		type = unknown;
	}

639
640
641
642
643
644
645
646
647
	/*
	 * The ktr_tid field was previously the ktr_buffer field, which held
	 * the kernel pointer value for the buffer associated with data
	 * following the record header.  It now holds a threadid, but only
	 * for trace files after the change.  Older trace files still contain
	 * kernel pointers.  Detect this and suppress the results by printing
	 * negative tid's as 0.
	 */
	if (threads)
648
		printf("%6jd %6jd %-8.*s ", (intmax_t)kth->ktr_pid,
649
650
		    kth->ktr_tid > 0 ? (intmax_t)kth->ktr_tid : 0,
		    MAXCOMLEN, kth->ktr_comm);
651
	else
652
		printf("%6jd %-8.*s ", (intmax_t)kth->ktr_pid, MAXCOMLEN,
653
		    kth->ktr_comm);
654
655
656
657
658
659
660
661
        if (timestamp) {
		if (timestamp & TIMESTAMP_ABSOLUTE) {
			printf("%jd.%06ld ", (intmax_t)kth->ktr_time.tv_sec,
			    kth->ktr_time.tv_usec);
		}
		if (timestamp & TIMESTAMP_ELAPSED) {
			if (prevtime_e.tv_sec == 0)
				prevtime_e = kth->ktr_time;
662
663
664
			timersub(&kth->ktr_time, &prevtime_e, &temp);
			printf("%jd.%06ld ", (intmax_t)temp.tv_sec,
			    temp.tv_usec);
665
		}
666
		if (timestamp & TIMESTAMP_RELATIVE) {
667
668
			if (prevtime.tv_sec == 0)
				prevtime = kth->ktr_time;
669
670
			if (timercmp(&kth->ktr_time, &prevtime, <)) {
				timersub(&prevtime, &kth->ktr_time, &temp);
671
672
				sign = "-";
			} else {
673
				timersub(&kth->ktr_time, &prevtime, &temp);
674
675
				sign = "";
			}
676
677
678
			prevtime = kth->ktr_time;
			printf("%s%jd.%06ld ", sign, (intmax_t)temp.tv_sec,
			    temp.tv_usec);
679
680
		}
	}
681
	printf("%s  ", type);
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
	if (abiflag != 0) {
		switch (sv_flags & SV_ABI_MASK) {
		case SV_ABI_LINUX:
			abi = "L";
			break;
		case SV_ABI_FREEBSD:
			abi = "F";
			break;
		default:
			abi = "U";
			break;
		}

		if ((sv_flags & SV_LP64) != 0)
			arch = "64";
		else if ((sv_flags & SV_ILP32) != 0)
			arch = "32";
		else
			arch = "00";

		printf("%s%s  ", abi, arch);
	}
704
705
706
707
}

#include <sys/syscall.h>

708
709
710
711
712
713
714
715
716
717
718
719
720
721
static void
ioctlname(unsigned long val)
{
	const char *str;

	str = sysdecode_ioctlname(val);
	if (str != NULL)
		printf("%s", str);
	else if (decimal)
		printf("%lu", val);
	else
		printf("%#lx", val);
}

722
723
724
725
726
static enum sysdecode_abi
syscallabi(u_int sv_flags)
{

	if (sv_flags == 0)
727
		return (SYSDECODE_ABI_FREEBSD);
728
729
	switch (sv_flags & SV_ABI_MASK) {
	case SV_ABI_FREEBSD:
730
		return (SYSDECODE_ABI_FREEBSD);
731
	case SV_ABI_LINUX:
732
#ifdef __LP64__
733
		if (sv_flags & SV_ILP32)
734
			return (SYSDECODE_ABI_LINUX32);
735
#endif
736
		return (SYSDECODE_ABI_LINUX);
737
	default:
738
		return (SYSDECODE_ABI_UNKNOWN);
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
	}
}

static void
syscallname(u_int code, u_int sv_flags)
{
	const char *name;

	name = sysdecode_syscallname(syscallabi(sv_flags), code);
	if (name == NULL)
		printf("[%d]", code);
	else {
		printf("%s", name);
		if (syscallno)
			printf("[%d]", code);
	}
}

757
758
759
760
761
762
763
764
765
766
767
768
static void
print_signal(int signo)
{
	const char *signame;

	signame = sysdecode_signal(signo);
	if (signame != NULL)
		printf("%s", signame);
	else
		printf("SIG %d", signo);
}

769
void
770
ktrsyscall(struct ktr_syscall *ktr, u_int sv_flags)
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
{
	int narg = ktr->ktr_narg;
	register_t *ip;

	syscallname(ktr->ktr_code, sv_flags);
	ip = &ktr->ktr_args[0];
	if (narg) {
		char c = '(';
		if (fancy) {
			switch (sv_flags & SV_ABI_MASK) {
			case SV_ABI_FREEBSD:
				ktrsyscall_freebsd(ktr, &ip, &narg, &c,
				    sv_flags);
				break;
#ifdef SYSDECODE_HAVE_LINUX
			case SV_ABI_LINUX:
#ifdef __amd64__
				if (sv_flags & SV_ILP32)
					ktrsyscall_linux32(ktr, &ip,
					    &narg, &c);
				else
#endif
				ktrsyscall_linux(ktr, &ip, &narg, &c);
				break;
#endif /* SYSDECODE_HAVE_LINUX */
			}
		}
		while (narg > 0)
			print_number(ip, narg, c);
		putchar(')');
	}
	putchar('\n');
}

void
ktrsyscall_freebsd(struct ktr_syscall *ktr, register_t **resip,
    int *resnarg, char *resc, u_int sv_flags)
808
{
809
	int narg = ktr->ktr_narg;
810
	register_t *ip, *first;
811
	intmax_t arg;
812
	int quad_align, quad_slots;
813

814
	ip = first = &ktr->ktr_args[0];
815
816
	char c = *resc;

817
818
819
820
821
822
823
824
			quad_align = 0;
			if (sv_flags & SV_ILP32) {
#ifdef __powerpc__
				quad_align = 1;
#endif
				quad_slots = 2;
			} else
				quad_slots = 1;
825
			switch (ktr->ktr_code) {
826
			case SYS_bindat:
827
			case SYS_chflagsat:
828
			case SYS_connectat:
829
830
831
832
833
834
835
836
837
838
839
840
841
			case SYS_faccessat:
			case SYS_fchmodat:
			case SYS_fchownat:
			case SYS_fstatat:
			case SYS_futimesat:
			case SYS_linkat:
			case SYS_mkdirat:
			case SYS_mkfifoat:
			case SYS_mknodat:
			case SYS_openat:
			case SYS_readlinkat:
			case SYS_renameat:
			case SYS_unlinkat:
842
			case SYS_utimensat:
843
				putchar('(');
844
				print_integer_arg_valid(sysdecode_atfd, *ip);
845
846
847
848
849
				c = ',';
				ip++;
				narg--;
				break;
			}
850
851
			switch (ktr->ktr_code) {
			case SYS_ioctl: {
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
852
				print_number(ip, narg, c);
853
				putchar(c);
854
				ioctlname(*ip);
855
856
857
				c = ',';
				ip++;
				narg--;
858
859
860
				break;
			}
			case SYS_ptrace:
861
				putchar('(');
862
				print_integer_arg(sysdecode_ptrace_request, *ip);
863
864
865
				c = ',';
				ip++;
				narg--;
866
867
868
				break;
			case SYS_access:
			case SYS_eaccess:
869
			case SYS_faccessat:
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
870
				print_number(ip, narg, c);
871
				putchar(',');
872
				print_mask_arg(sysdecode_access_mode, *ip);
873
874
				ip++;
				narg--;
875
				break;
876
877
878
879
880
881
882
883
			case SYS_close_range:
				print_number(ip, narg, c);
				print_number(ip, narg, c);
				putchar(',');
				print_mask_arg(sysdecode_close_range_flags, *ip);
				ip += 3;
				narg -= 3;
				break;
884
			case SYS_open:
885
			case SYS_openat:
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
886
				print_number(ip, narg, c);
887
				putchar(',');
888
889
890
891
892
				print_mask_arg(sysdecode_open_flags, ip[0]);
				if ((ip[0] & O_CREAT) == O_CREAT) {
					putchar(',');
					decode_filemode(ip[1]);
				}
893
894
895
896
				ip += 2;
				narg -= 2;
				break;
			case SYS_wait4:
897
898
				print_number(ip, narg, c);
				print_number(ip, narg, c);
899
900
901
902
				putchar(',');
				print_mask_arg0(sysdecode_wait4_options, *ip);
				ip++;
				narg--;
903
904
905
				break;
			case SYS_wait6:
				putchar('(');
906
				print_integer_arg(sysdecode_idtype, *ip);
907
908
909
				c = ',';
				ip++;
				narg--;
910
				print_number64(first, ip, narg, c);
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
911
				print_number(ip, narg, c);
912
				putchar(',');
913
				print_mask_arg(sysdecode_wait6_options, *ip);
914
915
				ip++;
				narg--;
916
917
918
919
				break;
			case SYS_chmod:
			case SYS_fchmod:
			case SYS_lchmod:
920
			case SYS_fchmodat:
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
921
				print_number(ip, narg, c);
922
				putchar(',');
923
				decode_filemode(*ip);
924
925
				ip++;
				narg--;
926
				break;
927
			case SYS_mknodat:
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
928
				print_number(ip, narg, c);
929
				putchar(',');
930
				decode_filemode(*ip);
931
932
				ip++;
				narg--;
933
934
				break;
			case SYS_getfsstat:
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
935
936
				print_number(ip, narg, c);
				print_number(ip, narg, c);
937
				putchar(',');
938
				print_integer_arg(sysdecode_getfsstat_mode, *ip);
939
940
				ip++;
				narg--;
941
942
				break;
			case SYS_mount:
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
943
944
				print_number(ip, narg, c);
				print_number(ip, narg, c);
945
				putchar(',');
946
				print_mask_arg(sysdecode_mount_flags, *ip);
947
948
				ip++;
				narg--;
949
950
				break;
			case SYS_unmount:
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
951
				print_number(ip, narg, c);
952
				putchar(',');
953
				print_mask_arg(sysdecode_mount_flags, *ip);
954
955
				ip++;
				narg--;
956
957
958
				break;
			case SYS_recvmsg:
			case SYS_sendmsg:
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
959
960
				print_number(ip, narg, c);
				print_number(ip, narg, c);
961
				putchar(',');
962
				print_mask_arg0(sysdecode_msg_flags, *ip);
963
964
				ip++;
				narg--;
965
966
967
				break;
			case SYS_recvfrom:
			case SYS_sendto:
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
968
969
970
				print_number(ip, narg, c);
				print_number(ip, narg, c);
				print_number(ip, narg, c);
971
				putchar(',');
972
				print_mask_arg0(sysdecode_msg_flags, *ip);
973
974
				ip++;
				narg--;
975
976
				break;
			case SYS_chflags:
977
			case SYS_chflagsat:
978
979
			case SYS_fchflags:
			case SYS_lchflags:
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
980
				print_number(ip, narg, c);
981
				putchar(',');
982
				decode_fileflags(*ip);
983
984
				ip++;
				narg--;
985
986
				break;
			case SYS_kill:
Dag-Erling Smørgrav's avatar
Dag-Erling Smørgrav committed
987
				print_number(ip, narg, c);
988
				putchar(',');
989
				print_signal(*ip);
990
991
				ip++;
				narg--;
992
993
				break;
			case SYS_reboot:
994
				putchar('(');
995
				print_mask_arg(sysdecode_reboot_howto, *ip);
996
997
				ip++;
				narg--;
998
999
				break;
			case SYS_umask:
1000
				putchar('(');
For faster browsing, not all history is shown. View entire blame