xref: /freebsd/usr.bin/kdump/linux.c (revision 39de84b6)
18a0f6d8cSDmitry Chagin /*-
28a0f6d8cSDmitry Chagin  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
38a0f6d8cSDmitry Chagin  *
48a0f6d8cSDmitry Chagin  * Copyright (c) 2022 Dmitry Chagin <dchagin@FreeBSD.org>
58a0f6d8cSDmitry Chagin  *
68a0f6d8cSDmitry Chagin  * Redistribution and use in source and binary forms, with or without
78a0f6d8cSDmitry Chagin  * modification, are permitted provided that the following conditions
88a0f6d8cSDmitry Chagin  * are met:
98a0f6d8cSDmitry Chagin  * 1. Redistributions of source code must retain the above copyright
108a0f6d8cSDmitry Chagin  *    notice, this list of conditions and the following disclaimer.
118a0f6d8cSDmitry Chagin  * 2. Redistributions in binary form must reproduce the above copyright
128a0f6d8cSDmitry Chagin  *    notice, this list of conditions and the following disclaimer in the
138a0f6d8cSDmitry Chagin  *    documentation and/or other materials provided with the distribution.
148a0f6d8cSDmitry Chagin  *
158a0f6d8cSDmitry Chagin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
168a0f6d8cSDmitry Chagin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
178a0f6d8cSDmitry Chagin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
188a0f6d8cSDmitry Chagin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
198a0f6d8cSDmitry Chagin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
208a0f6d8cSDmitry Chagin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
218a0f6d8cSDmitry Chagin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
228a0f6d8cSDmitry Chagin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
238a0f6d8cSDmitry Chagin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
248a0f6d8cSDmitry Chagin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
258a0f6d8cSDmitry Chagin  * SUCH DAMAGE.
268a0f6d8cSDmitry Chagin  */
278a0f6d8cSDmitry Chagin 
288a0f6d8cSDmitry Chagin #include <sys/cdefs.h>
298a0f6d8cSDmitry Chagin __FBSDID("$FreeBSD$");
308a0f6d8cSDmitry Chagin 
318a0f6d8cSDmitry Chagin #include <sys/param.h>
328a0f6d8cSDmitry Chagin #include <sys/uio.h>
338a0f6d8cSDmitry Chagin #include <sys/ktrace.h>
343606a213SDmitry Chagin #include <err.h>
353606a213SDmitry Chagin #include <errno.h>
368a0f6d8cSDmitry Chagin #include <stddef.h>
373606a213SDmitry Chagin #include <stdlib.h>
383606a213SDmitry Chagin #include <string.h>
398a0f6d8cSDmitry Chagin #include <sysdecode.h>
408a0f6d8cSDmitry Chagin 
418a0f6d8cSDmitry Chagin #include "kdump.h"
428a0f6d8cSDmitry Chagin 
438a0f6d8cSDmitry Chagin #ifdef __amd64__
448a0f6d8cSDmitry Chagin #include <amd64/linux/linux_syscall.h>
458a0f6d8cSDmitry Chagin #include <amd64/linux32/linux32_syscall.h>
468a0f6d8cSDmitry Chagin #elif __aarch64__
478a0f6d8cSDmitry Chagin #include <arm64/linux/linux_syscall.h>
488a0f6d8cSDmitry Chagin #elif __i386__
498a0f6d8cSDmitry Chagin #include <i386/linux/linux_syscall.h>
508a0f6d8cSDmitry Chagin #endif
518a0f6d8cSDmitry Chagin 
523606a213SDmitry Chagin #include <compat/linux/linux.h>
533606a213SDmitry Chagin 
548a0f6d8cSDmitry Chagin static void
558a0f6d8cSDmitry Chagin print_linux_signal(int signo)
568a0f6d8cSDmitry Chagin {
578a0f6d8cSDmitry Chagin 	const char *signame;
588a0f6d8cSDmitry Chagin 
598a0f6d8cSDmitry Chagin 	signame = sysdecode_linux_signal(signo);
608a0f6d8cSDmitry Chagin 	if (signame != NULL)
618a0f6d8cSDmitry Chagin 		printf("%s", signame);
628a0f6d8cSDmitry Chagin 	else
638a0f6d8cSDmitry Chagin 		printf("SIG %d", signo);
648a0f6d8cSDmitry Chagin }
658a0f6d8cSDmitry Chagin 
668a0f6d8cSDmitry Chagin void
678a0f6d8cSDmitry Chagin ktrsyscall_linux(struct ktr_syscall *ktr, register_t **resip,
688a0f6d8cSDmitry Chagin     int *resnarg, char *resc)
698a0f6d8cSDmitry Chagin {
708a0f6d8cSDmitry Chagin 	int narg = ktr->ktr_narg;
718a0f6d8cSDmitry Chagin 	register_t *ip, *first;
728a0f6d8cSDmitry Chagin 	int quad_align, quad_slots;
738a0f6d8cSDmitry Chagin 	char c;
748a0f6d8cSDmitry Chagin 
758a0f6d8cSDmitry Chagin 	ip = first = &ktr->ktr_args[0];
768a0f6d8cSDmitry Chagin 	c = *resc;
778a0f6d8cSDmitry Chagin 	quad_align = 0;
788a0f6d8cSDmitry Chagin 	quad_slots = 1;
798a0f6d8cSDmitry Chagin 	switch (ktr->ktr_code) {
808a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_clock_gettime:
818a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_clock_settime:
828a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_clock_getres:
838a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_timer_create:
848a0f6d8cSDmitry Chagin 		putchar('(');
858a0f6d8cSDmitry Chagin 		sysdecode_linux_clockid(stdout, *ip);
868a0f6d8cSDmitry Chagin 		c = ',';
878a0f6d8cSDmitry Chagin 		ip++;
888a0f6d8cSDmitry Chagin 		narg--;
898a0f6d8cSDmitry Chagin 		break;
9039de84b6SDmitry Chagin 	case LINUX_SYS_linux_clock_nanosleep:
9139de84b6SDmitry Chagin 		putchar('(');
9239de84b6SDmitry Chagin 		sysdecode_linux_clockid(stdout, *ip);
9339de84b6SDmitry Chagin 		putchar(',');
9439de84b6SDmitry Chagin 		ip++;
9539de84b6SDmitry Chagin 		narg--;
9639de84b6SDmitry Chagin 		print_mask_arg0(sysdecode_linux_clock_flags, *ip);
9739de84b6SDmitry Chagin 		c = ',';
9839de84b6SDmitry Chagin 		ip++;
9939de84b6SDmitry Chagin 		narg--;
10039de84b6SDmitry Chagin 		break;
1018a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_kill:
1028a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_tkill:
1038a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_rt_sigqueueinfo:
1048a0f6d8cSDmitry Chagin 		print_number(ip, narg, c);
1058a0f6d8cSDmitry Chagin 		putchar(',');
1068a0f6d8cSDmitry Chagin 		print_linux_signal(*ip);
1078a0f6d8cSDmitry Chagin 		ip++;
1088a0f6d8cSDmitry Chagin 		narg--;
1098a0f6d8cSDmitry Chagin 		break;
1108a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_tgkill:
1118a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_rt_tgsigqueueinfo:
1128a0f6d8cSDmitry Chagin 		print_number(ip, narg, c);
1138a0f6d8cSDmitry Chagin 		print_number(ip, narg, c);
1148a0f6d8cSDmitry Chagin 		putchar(',');
1158a0f6d8cSDmitry Chagin 		print_linux_signal(*ip);
1168a0f6d8cSDmitry Chagin 		ip++;
1178a0f6d8cSDmitry Chagin 		narg--;
1188a0f6d8cSDmitry Chagin 		break;
1198a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_rt_sigaction:
1208a0f6d8cSDmitry Chagin 		putchar('(');
1218a0f6d8cSDmitry Chagin 		print_linux_signal(*ip);
1228a0f6d8cSDmitry Chagin 		ip++;
1238a0f6d8cSDmitry Chagin 		narg--;
1248a0f6d8cSDmitry Chagin 		c = ',';
1258a0f6d8cSDmitry Chagin 		break;
1268a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_ftruncate:
1278a0f6d8cSDmitry Chagin 	case LINUX_SYS_linux_truncate:
1288a0f6d8cSDmitry Chagin 		print_number(ip, narg, c);
1298a0f6d8cSDmitry Chagin 		print_number64(first, ip, narg, c);
1308a0f6d8cSDmitry Chagin 		break;
131b9b86b67SDmitry Chagin 	case LINUX_SYS_linux_getitimer:
132b9b86b67SDmitry Chagin 	case LINUX_SYS_linux_setitimer:
133b9b86b67SDmitry Chagin 		putchar('(');
134b9b86b67SDmitry Chagin 		print_integer_arg(sysdecode_itimer, *ip);
135b9b86b67SDmitry Chagin 		ip++;
136b9b86b67SDmitry Chagin 		narg--;
137b9b86b67SDmitry Chagin 		c = ',';
138b9b86b67SDmitry Chagin 		break;
139f587a2a7SDmitry Chagin 	case LINUX_SYS_linux_rt_sigprocmask:
140f587a2a7SDmitry Chagin #ifdef LINUX_SYS_linux_sigprocmask
141f587a2a7SDmitry Chagin 	case LINUX_SYS_linux_sigprocmask:
142f587a2a7SDmitry Chagin #endif
143f587a2a7SDmitry Chagin 		putchar('(');
144f587a2a7SDmitry Chagin 		print_integer_arg(sysdecode_linux_sigprocmask_how, *ip);
145f587a2a7SDmitry Chagin 		ip++;
146f587a2a7SDmitry Chagin 		narg--;
147f587a2a7SDmitry Chagin 		c = ',';
148f587a2a7SDmitry Chagin 		break;
1498a0f6d8cSDmitry Chagin 	}
1508a0f6d8cSDmitry Chagin 	*resc = c;
1518a0f6d8cSDmitry Chagin 	*resip = ip;
1528a0f6d8cSDmitry Chagin 	*resnarg = narg;
1538a0f6d8cSDmitry Chagin }
1548a0f6d8cSDmitry Chagin 
1558a0f6d8cSDmitry Chagin #if defined(__amd64__)
1568a0f6d8cSDmitry Chagin void
1578a0f6d8cSDmitry Chagin ktrsyscall_linux32(struct ktr_syscall *ktr, register_t **resip,
1588a0f6d8cSDmitry Chagin     int *resnarg, char *resc)
1598a0f6d8cSDmitry Chagin {
1608a0f6d8cSDmitry Chagin 	int narg = ktr->ktr_narg;
1618a0f6d8cSDmitry Chagin 	register_t *ip, *first;
1628a0f6d8cSDmitry Chagin 	int quad_align, quad_slots;
1638a0f6d8cSDmitry Chagin 	char c;
1648a0f6d8cSDmitry Chagin 
1658a0f6d8cSDmitry Chagin 	ip = first = &ktr->ktr_args[0];
1668a0f6d8cSDmitry Chagin 	c = *resc;
1678a0f6d8cSDmitry Chagin 	quad_align = 0;
1688a0f6d8cSDmitry Chagin 	quad_slots = 2;
1698a0f6d8cSDmitry Chagin 	switch (ktr->ktr_code) {
1708a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_clock_gettime:
1718a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_clock_settime:
1728a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_clock_getres:
1738a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_timer_create:
1748a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_clock_gettime64:
1758a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_clock_settime64:
1768a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_clock_getres_time64:
1778a0f6d8cSDmitry Chagin 		putchar('(');
1788a0f6d8cSDmitry Chagin 		sysdecode_linux_clockid(stdout, *ip);
1798a0f6d8cSDmitry Chagin 		c = ',';
1808a0f6d8cSDmitry Chagin 		ip++;
1818a0f6d8cSDmitry Chagin 		narg--;
1828a0f6d8cSDmitry Chagin 		break;
18339de84b6SDmitry Chagin 	case LINUX32_SYS_linux_clock_nanosleep:
18439de84b6SDmitry Chagin 		putchar('(');
18539de84b6SDmitry Chagin 		sysdecode_linux_clockid(stdout, *ip);
18639de84b6SDmitry Chagin 		putchar(',');
18739de84b6SDmitry Chagin 		ip++;
18839de84b6SDmitry Chagin 		narg--;
18939de84b6SDmitry Chagin 		print_mask_arg0(sysdecode_linux_clock_flags, *ip);
19039de84b6SDmitry Chagin 		c = ',';
19139de84b6SDmitry Chagin 		ip++;
19239de84b6SDmitry Chagin 		narg--;
19339de84b6SDmitry Chagin 		break;
1948a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_kill:
1958a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_tkill:
1968a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_rt_sigqueueinfo:
1978a0f6d8cSDmitry Chagin 		print_number(ip, narg, c);
1988a0f6d8cSDmitry Chagin 		putchar(',');
1998a0f6d8cSDmitry Chagin 		print_linux_signal(*ip);
2008a0f6d8cSDmitry Chagin 		ip++;
2018a0f6d8cSDmitry Chagin 		narg--;
2028a0f6d8cSDmitry Chagin 		break;
2038a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_tgkill:
2048a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_rt_tgsigqueueinfo:
2058a0f6d8cSDmitry Chagin 		print_number(ip, narg, c);
2068a0f6d8cSDmitry Chagin 		print_number(ip, narg, c);
2078a0f6d8cSDmitry Chagin 		putchar(',');
2088a0f6d8cSDmitry Chagin 		print_linux_signal(*ip);
2098a0f6d8cSDmitry Chagin 		ip++;
2108a0f6d8cSDmitry Chagin 		narg--;
2118a0f6d8cSDmitry Chagin 		break;
2128a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_signal:
2138a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_sigaction:
2148a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_rt_sigaction:
2158a0f6d8cSDmitry Chagin 		putchar('(');
2168a0f6d8cSDmitry Chagin 		print_linux_signal(*ip);
2178a0f6d8cSDmitry Chagin 		ip++;
2188a0f6d8cSDmitry Chagin 		narg--;
2198a0f6d8cSDmitry Chagin 		c = ',';
2208a0f6d8cSDmitry Chagin 		break;
2218a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_ftruncate:
2228a0f6d8cSDmitry Chagin 	case LINUX32_SYS_linux_truncate:
2238a0f6d8cSDmitry Chagin 		print_number(ip, narg, c);
2248a0f6d8cSDmitry Chagin 		print_number64(first, ip, narg, c);
2258a0f6d8cSDmitry Chagin 		break;
226b9b86b67SDmitry Chagin 	case LINUX32_SYS_linux_getitimer:
227b9b86b67SDmitry Chagin 	case LINUX32_SYS_linux_setitimer:
228b9b86b67SDmitry Chagin 		putchar('(');
229b9b86b67SDmitry Chagin 		print_integer_arg(sysdecode_itimer, *ip);
230b9b86b67SDmitry Chagin 		ip++;
231b9b86b67SDmitry Chagin 		narg--;
232b9b86b67SDmitry Chagin 		c = ',';
233b9b86b67SDmitry Chagin 		break;
234f587a2a7SDmitry Chagin 	case LINUX32_SYS_linux_rt_sigprocmask:
235f587a2a7SDmitry Chagin 	case LINUX32_SYS_linux_sigprocmask:
236f587a2a7SDmitry Chagin 		putchar('(');
237f587a2a7SDmitry Chagin 		print_integer_arg(sysdecode_linux_sigprocmask_how, *ip);
238f587a2a7SDmitry Chagin 		ip++;
239f587a2a7SDmitry Chagin 		narg--;
240f587a2a7SDmitry Chagin 		c = ',';
241f587a2a7SDmitry Chagin 		break;
2428a0f6d8cSDmitry Chagin 	}
2438a0f6d8cSDmitry Chagin 	*resc = c;
2448a0f6d8cSDmitry Chagin 	*resip = ip;
2458a0f6d8cSDmitry Chagin 	*resnarg = narg;
2468a0f6d8cSDmitry Chagin }
2478a0f6d8cSDmitry Chagin #endif /* __amd64__ */
2483606a213SDmitry Chagin 
2493606a213SDmitry Chagin static void
2503606a213SDmitry Chagin ktrsigset(const char *name, const l_sigset_t *mask, size_t sz)
2513606a213SDmitry Chagin {
2523606a213SDmitry Chagin 	unsigned long i, c;
2533606a213SDmitry Chagin 
2543606a213SDmitry Chagin 	printf("%s [ ", name);
2553606a213SDmitry Chagin 	c = 0;
2563606a213SDmitry Chagin 	for (i = 1; i <= sz * CHAR_BIT; i++) {
2573606a213SDmitry Chagin 		if (!LINUX_SIGISMEMBER(*mask, i))
2583606a213SDmitry Chagin 			continue;
2593606a213SDmitry Chagin 		if (c != 0)
2603606a213SDmitry Chagin 			printf(", ");
2613606a213SDmitry Chagin 		printf("%s", sysdecode_linux_signal(i));
2623606a213SDmitry Chagin 		c++;
2633606a213SDmitry Chagin 	}
2643606a213SDmitry Chagin 	if (c == 0)
2653606a213SDmitry Chagin 		printf("empty ]\n");
2663606a213SDmitry Chagin 	else
2673606a213SDmitry Chagin 		printf(" ]\n");
2683606a213SDmitry Chagin }
2693606a213SDmitry Chagin 
2703606a213SDmitry Chagin bool
2713606a213SDmitry Chagin ktrstruct_linux(const char *name, const char *data, size_t datalen)
2723606a213SDmitry Chagin {
2733606a213SDmitry Chagin 	l_sigset_t mask;
2743606a213SDmitry Chagin 
2753606a213SDmitry Chagin 	if (strcmp(name, "l_sigset_t") == 0) {
2763606a213SDmitry Chagin 		/* Old Linux sigset_t is one word size. */
2773606a213SDmitry Chagin 		if (datalen < sizeof(int) || datalen > sizeof(l_sigset_t))
2783606a213SDmitry Chagin 			return (false);
2793606a213SDmitry Chagin 		memcpy(&mask, data, datalen);
2803606a213SDmitry Chagin 		ktrsigset(name, &mask, datalen);
2813606a213SDmitry Chagin 	} else
2823606a213SDmitry Chagin 		return (false);
2833606a213SDmitry Chagin 
2843606a213SDmitry Chagin 	return (true);
2853606a213SDmitry Chagin }
286