xref: /freebsd-src/lib/libsysdecode/linux.c (revision a2f733abcff64628b7771a47089628b7327a88bd)
1b69ae1a3SDmitry Chagin /*-
2b69ae1a3SDmitry Chagin  * SPDX-License-Identifier: BSD-2-Clause
3b69ae1a3SDmitry Chagin  *
4ed366c37SDmitry Chagin  * Copyright (c) 2022 Dmitry Chagin <dchagin@FreeBSD.org>
5b69ae1a3SDmitry Chagin  *
6b69ae1a3SDmitry Chagin  * Redistribution and use in source and binary forms, with or without
7b69ae1a3SDmitry Chagin  * modification, are permitted provided that the following conditions
8b69ae1a3SDmitry Chagin  * are met:
9b69ae1a3SDmitry Chagin  * 1. Redistributions of source code must retain the above copyright
10b69ae1a3SDmitry Chagin  *    notice, this list of conditions and the following disclaimer.
11b69ae1a3SDmitry Chagin  * 2. Redistributions in binary form must reproduce the above copyright
12b69ae1a3SDmitry Chagin  *    notice, this list of conditions and the following disclaimer in the
13b69ae1a3SDmitry Chagin  *    documentation and/or other materials provided with the distribution.
14b69ae1a3SDmitry Chagin  *
15b69ae1a3SDmitry Chagin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16b69ae1a3SDmitry Chagin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17b69ae1a3SDmitry Chagin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18b69ae1a3SDmitry Chagin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19b69ae1a3SDmitry Chagin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20b69ae1a3SDmitry Chagin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21b69ae1a3SDmitry Chagin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22b69ae1a3SDmitry Chagin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23b69ae1a3SDmitry Chagin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24b69ae1a3SDmitry Chagin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25b69ae1a3SDmitry Chagin  * SUCH DAMAGE.
26b69ae1a3SDmitry Chagin  */
27b69ae1a3SDmitry Chagin 
28b69ae1a3SDmitry Chagin #include <sys/types.h>
29b69ae1a3SDmitry Chagin #include <sys/proc.h>
30b69ae1a3SDmitry Chagin #include <stdbool.h>
31b69ae1a3SDmitry Chagin #include <stdio.h>
32b69ae1a3SDmitry Chagin #include <sysdecode.h>
33b69ae1a3SDmitry Chagin 
34b69ae1a3SDmitry Chagin #include "support.h"
35b69ae1a3SDmitry Chagin 
36b69ae1a3SDmitry Chagin #ifdef __aarch64__
37b69ae1a3SDmitry Chagin #include <arm64/linux/linux.h>
38b69ae1a3SDmitry Chagin #elif __i386__
39b69ae1a3SDmitry Chagin #include <i386/linux/linux.h>
40b69ae1a3SDmitry Chagin #elif __amd64__
41b69ae1a3SDmitry Chagin #include <amd64/linux/linux.h>
42b69ae1a3SDmitry Chagin #else
43b69ae1a3SDmitry Chagin #error "Unsupported Linux arch"
44b69ae1a3SDmitry Chagin #endif
45b69ae1a3SDmitry Chagin 
46b69ae1a3SDmitry Chagin #include <compat/linux/linux.h>
47d2b3237eSDmitry Chagin #include <compat/linux/linux_file.h>
48*bd35e83bSDmitry Chagin #include <compat/linux/linux_fork.h>
49c8a79231SDmitry Chagin #include <compat/linux/linux_time.h>
50b69ae1a3SDmitry Chagin 
51b69ae1a3SDmitry Chagin #define	X(a,b)	{ a, #b },
52b69ae1a3SDmitry Chagin #define	XEND	{ 0, NULL }
53b69ae1a3SDmitry Chagin 
54b69ae1a3SDmitry Chagin #define	TABLE_START(n)	static struct name_table n[] = {
55b69ae1a3SDmitry Chagin #define	TABLE_ENTRY	X
56b69ae1a3SDmitry Chagin #define	TABLE_END	XEND };
57b69ae1a3SDmitry Chagin 
58b69ae1a3SDmitry Chagin #include "tables_linux.h"
59b69ae1a3SDmitry Chagin 
60b69ae1a3SDmitry Chagin #undef TABLE_START
61b69ae1a3SDmitry Chagin #undef TABLE_ENTRY
62b69ae1a3SDmitry Chagin #undef TABLE_END
63b69ae1a3SDmitry Chagin 
64f85848fcSDmitry Chagin static const char *linux_signames[] = {
65f85848fcSDmitry Chagin 	[LINUX_SIGHUP] = "SIGHUP",
66f85848fcSDmitry Chagin 	[LINUX_SIGINT] = "SIGINT",
67f85848fcSDmitry Chagin 	[LINUX_SIGQUIT] = "SIGQUIT",
68f85848fcSDmitry Chagin 	[LINUX_SIGILL] = "SIGILL",
69f85848fcSDmitry Chagin 	[LINUX_SIGTRAP] = "SIGTRAP",
70f85848fcSDmitry Chagin 	[LINUX_SIGABRT] = "SIGABRT",
71f85848fcSDmitry Chagin 	[LINUX_SIGBUS] = "SIGBUS",
72f85848fcSDmitry Chagin 	[LINUX_SIGFPE] = "SIGFPE",
73f85848fcSDmitry Chagin 	[LINUX_SIGKILL] = "SIGKILL",
74f85848fcSDmitry Chagin 	[LINUX_SIGUSR1] = "SIGUSR1",
75f85848fcSDmitry Chagin 	[LINUX_SIGSEGV] = "SIGSEGV",
76f85848fcSDmitry Chagin 	[LINUX_SIGUSR2] = "SIGUSR2",
77f85848fcSDmitry Chagin 	[LINUX_SIGPIPE] = "SIGPIPE",
78f85848fcSDmitry Chagin 	[LINUX_SIGALRM] = "SIGALRM",
79f85848fcSDmitry Chagin 	[LINUX_SIGTERM] = "SIGTERM",
80f85848fcSDmitry Chagin 	[LINUX_SIGSTKFLT] = "SIGSTKFLT",
81f85848fcSDmitry Chagin 	[LINUX_SIGCHLD] = "SIGCHLD",
82f85848fcSDmitry Chagin 	[LINUX_SIGCONT] = "SIGCONT",
83f85848fcSDmitry Chagin 	[LINUX_SIGSTOP] = "SIGSTOP",
84f85848fcSDmitry Chagin 	[LINUX_SIGTSTP] = "SIGTSTP",
85f85848fcSDmitry Chagin 	[LINUX_SIGTTIN] = "SIGTTIN",
86f85848fcSDmitry Chagin 	[LINUX_SIGTTOU] = "SIGTTOU",
87f85848fcSDmitry Chagin 	[LINUX_SIGURG] = "SIGURG",
88f85848fcSDmitry Chagin 	[LINUX_SIGXCPU] = "SIGXCPU",
89f85848fcSDmitry Chagin 	[LINUX_SIGXFSZ] = "SIGXFSZ",
90f85848fcSDmitry Chagin 	[LINUX_SIGVTALRM] = "SIGVTALRM",
91f85848fcSDmitry Chagin 	[LINUX_SIGPROF] = "SIGPROF",
92f85848fcSDmitry Chagin 	[LINUX_SIGWINCH] = "SIGWINCH",
93f85848fcSDmitry Chagin 	[LINUX_SIGIO] = "SIGIO",
94f85848fcSDmitry Chagin 	[LINUX_SIGPWR] = "SIGPWR",
95f85848fcSDmitry Chagin 	[LINUX_SIGSYS] = "SIGSYS",
96f85848fcSDmitry Chagin 
97f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN] = "SIGCANCEL",
98f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 1] = "SIGSETXID",
99f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 2] = "SIGRT2",
100f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 3] = "SIGRT3",
101f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 4] = "SIGRT4",
102f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 5] = "SIGRT5",
103f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 6] = "SIGRT6",
104f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 7] = "SIGRT7",
105f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 8] = "SIGRT8",
106f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 9] = "SIGRT9",
107f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 10] = "SIGRT10",
108f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 11] = "SIGRT11",
109f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 12] = "SIGRT12",
110f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 13] = "SIGRT13",
111f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 14] = "SIGRT14",
112f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 15] = "SIGRT15",
113f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 16] = "SIGRT16",
114f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 17] = "SIGRT17",
115f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 18] = "SIGRT18",
116f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 19] = "SIGRT19",
117f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 20] = "SIGRT20",
118f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 21] = "SIGRT21",
119f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 22] = "SIGRT22",
120f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 23] = "SIGRT23",
121f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 24] = "SIGRT24",
122f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 25] = "SIGRT25",
123f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 26] = "SIGRT26",
124f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 27] = "SIGRT27",
125f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 28] = "SIGRT28",
126f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 29] = "SIGRT29",
127f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 30] = "SIGRT30",
128f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 31] = "SIGRT31",
129f85848fcSDmitry Chagin 	[LINUX_SIGRTMIN + 32] = "SIGRTMAX",
130f85848fcSDmitry Chagin };
131f85848fcSDmitry Chagin _Static_assert(nitems(linux_signames) == LINUX_SIGRTMAX + 1,
132f85848fcSDmitry Chagin     "invalid entries count in linux_signames");
133f85848fcSDmitry Chagin 
134b69ae1a3SDmitry Chagin void
sysdecode_linux_clockid(FILE * fp,clockid_t which)135b69ae1a3SDmitry Chagin sysdecode_linux_clockid(FILE *fp, clockid_t which)
136b69ae1a3SDmitry Chagin {
137b69ae1a3SDmitry Chagin 	const char *str;
138b69ae1a3SDmitry Chagin 	clockid_t ci;
139b69ae1a3SDmitry Chagin 	pid_t pid;
140b69ae1a3SDmitry Chagin 
141b69ae1a3SDmitry Chagin 	if (which >= 0) {
142b69ae1a3SDmitry Chagin 		str = lookup_value(clockids, which);
143b69ae1a3SDmitry Chagin 		if (str == NULL)
144b69ae1a3SDmitry Chagin 			fprintf(fp, "UNKNOWN(%d)", which);
145b69ae1a3SDmitry Chagin 		else
146b69ae1a3SDmitry Chagin 			fputs(str, fp);
147b69ae1a3SDmitry Chagin 		return;
148b69ae1a3SDmitry Chagin 	}
149b69ae1a3SDmitry Chagin 	if ((which & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD_MASK) {
150b69ae1a3SDmitry Chagin 		fputs("INVALID PERTHREAD|CLOCKFD", fp);
151b69ae1a3SDmitry Chagin 		goto pidp;
152b69ae1a3SDmitry Chagin 	}
153b69ae1a3SDmitry Chagin 	ci = LINUX_CPUCLOCK_WHICH(which);
154b69ae1a3SDmitry Chagin 	if (LINUX_CPUCLOCK_PERTHREAD(which) == true)
155b69ae1a3SDmitry Chagin 		fputs("THREAD|", fp);
156b69ae1a3SDmitry Chagin 	else
157b69ae1a3SDmitry Chagin 		fputs("PROCESS|", fp);
158b69ae1a3SDmitry Chagin 	str = lookup_value(clockcpuids, ci);
159b69ae1a3SDmitry Chagin 	if (str != NULL)
160b69ae1a3SDmitry Chagin 		fputs(str, fp);
161b69ae1a3SDmitry Chagin 	else {
162b69ae1a3SDmitry Chagin 		if (ci == LINUX_CLOCKFD)
163b69ae1a3SDmitry Chagin 			fputs("CLOCKFD", fp);
164b69ae1a3SDmitry Chagin 		else
165b69ae1a3SDmitry Chagin 			fprintf(fp, "UNKNOWN(%d)", which);
166b69ae1a3SDmitry Chagin 	}
167b69ae1a3SDmitry Chagin 
168b69ae1a3SDmitry Chagin pidp:
169b69ae1a3SDmitry Chagin 	pid = LINUX_CPUCLOCK_ID(which);
170b69ae1a3SDmitry Chagin 	fprintf(fp, "(%d)", pid);
171b69ae1a3SDmitry Chagin }
172f85848fcSDmitry Chagin 
173f85848fcSDmitry Chagin const char *
sysdecode_linux_signal(int sig)174f85848fcSDmitry Chagin sysdecode_linux_signal(int sig)
175f85848fcSDmitry Chagin {
176f85848fcSDmitry Chagin 
177f85848fcSDmitry Chagin 	if ((unsigned)sig < nitems(linux_signames))
178f85848fcSDmitry Chagin 		return (linux_signames[sig]);
179f85848fcSDmitry Chagin 	return (NULL);
180f85848fcSDmitry Chagin }
181f587a2a7SDmitry Chagin 
182f587a2a7SDmitry Chagin const char *
sysdecode_linux_sigprocmask_how(int how)183f587a2a7SDmitry Chagin sysdecode_linux_sigprocmask_how(int how)
184f587a2a7SDmitry Chagin {
185f587a2a7SDmitry Chagin 
186f587a2a7SDmitry Chagin 	return (lookup_value(sigprocmaskhow, how));
187f587a2a7SDmitry Chagin }
18839de84b6SDmitry Chagin 
18939de84b6SDmitry Chagin bool
sysdecode_linux_clock_flags(FILE * fp,int flags,int * rem)19039de84b6SDmitry Chagin sysdecode_linux_clock_flags(FILE *fp, int flags, int *rem)
19139de84b6SDmitry Chagin {
19239de84b6SDmitry Chagin 
19339de84b6SDmitry Chagin 	return (print_mask_int(fp, clockflags, flags, rem));
19439de84b6SDmitry Chagin }
195d2b3237eSDmitry Chagin 
196d2b3237eSDmitry Chagin bool
sysdecode_linux_atflags(FILE * fp,int flag,int * rem)197d2b3237eSDmitry Chagin sysdecode_linux_atflags(FILE *fp, int flag, int *rem)
198d2b3237eSDmitry Chagin {
199d2b3237eSDmitry Chagin 
200d2b3237eSDmitry Chagin 	return (print_mask_int(fp, atflags, flag, rem));
201d2b3237eSDmitry Chagin }
202fde775bcSDmitry Chagin 
203fde775bcSDmitry Chagin bool
sysdecode_linux_open_flags(FILE * fp,int flags,int * rem)204fde775bcSDmitry Chagin sysdecode_linux_open_flags(FILE *fp, int flags, int *rem)
205fde775bcSDmitry Chagin {
206fde775bcSDmitry Chagin 	bool printed;
207fde775bcSDmitry Chagin 	int mode;
208fde775bcSDmitry Chagin 	uintmax_t val;
209fde775bcSDmitry Chagin 
210fde775bcSDmitry Chagin 	mode = flags & LINUX_O_ACCMODE;
211fde775bcSDmitry Chagin 	flags &= ~LINUX_O_ACCMODE;
212fde775bcSDmitry Chagin 	switch (mode) {
213fde775bcSDmitry Chagin 	case LINUX_O_RDONLY:
214fde775bcSDmitry Chagin 		fputs("O_RDONLY", fp);
215fde775bcSDmitry Chagin 		printed = true;
216fde775bcSDmitry Chagin 		mode = 0;
217fde775bcSDmitry Chagin 		break;
218fde775bcSDmitry Chagin 	case LINUX_O_WRONLY:
219fde775bcSDmitry Chagin 		fputs("O_WRONLY", fp);
220fde775bcSDmitry Chagin 		printed = true;
221fde775bcSDmitry Chagin 		mode = 0;
222fde775bcSDmitry Chagin 		break;
223fde775bcSDmitry Chagin 	case LINUX_O_RDWR:
224fde775bcSDmitry Chagin 		fputs("O_RDWR", fp);
225fde775bcSDmitry Chagin 		printed = true;
226fde775bcSDmitry Chagin 		mode = 0;
227fde775bcSDmitry Chagin 		break;
228fde775bcSDmitry Chagin 	default:
229fde775bcSDmitry Chagin 		printed = false;
230fde775bcSDmitry Chagin 	}
231fde775bcSDmitry Chagin 	val = (unsigned)flags;
232fde775bcSDmitry Chagin 	print_mask_part(fp, openflags, &val, &printed);
233fde775bcSDmitry Chagin 	if (rem != NULL)
234fde775bcSDmitry Chagin 		*rem = val | mode;
235fde775bcSDmitry Chagin 	return (printed);
236fde775bcSDmitry Chagin }
237*bd35e83bSDmitry Chagin 
238*bd35e83bSDmitry Chagin bool
sysdecode_linux_clone_flags(FILE * fp,int flags,int * rem)239*bd35e83bSDmitry Chagin sysdecode_linux_clone_flags(FILE *fp, int flags, int *rem)
240*bd35e83bSDmitry Chagin {
241*bd35e83bSDmitry Chagin 	uintmax_t val;
242*bd35e83bSDmitry Chagin 	bool printed;
243*bd35e83bSDmitry Chagin 	int sig;
244*bd35e83bSDmitry Chagin 
245*bd35e83bSDmitry Chagin 	sig = flags & LINUX_CSIGNAL;
246*bd35e83bSDmitry Chagin 	if (sig != 0)
247*bd35e83bSDmitry Chagin 		fprintf(fp, "(%s)", sysdecode_linux_signal(sig));
248*bd35e83bSDmitry Chagin 	val = (unsigned)flags & ~LINUX_CSIGNAL;
249*bd35e83bSDmitry Chagin 	print_mask_part(fp, cloneflags, &val, &printed);
250*bd35e83bSDmitry Chagin 	if (rem != NULL)
251*bd35e83bSDmitry Chagin 		*rem = val;
252*bd35e83bSDmitry Chagin 	return (printed);
253*bd35e83bSDmitry Chagin }
254