]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/kdump/linux.c
Merge bmake-20230414
[FreeBSD/FreeBSD.git] / usr.bin / kdump / linux.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2022 Dmitry Chagin <dchagin@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/param.h>
32 #include <sys/uio.h>
33 #include <sys/ktrace.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <stddef.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sysdecode.h>
40
41 #include "kdump.h"
42
43 #ifdef __amd64__
44 #include <amd64/linux/linux.h>
45 #include <amd64/linux32/linux32_syscall.h>
46 #elif __aarch64__
47 #include <arm64/linux/linux.h>
48 #elif __i386__
49 #include <i386/linux/linux.h>
50 #endif
51
52 #include <compat/linux/linux.h>
53 #include <compat/linux/linux_file.h>
54
55 static void
56 print_linux_signal(int signo)
57 {
58         const char *signame;
59
60         signame = sysdecode_linux_signal(signo);
61         if (signame != NULL)
62                 printf("%s", signame);
63         else
64                 printf("SIG %d", signo);
65 }
66
67 void
68 ktrsyscall_linux(struct ktr_syscall *ktr, register_t **resip,
69     int *resnarg, char *resc)
70 {
71         int narg = ktr->ktr_narg;
72         register_t *ip, *first;
73         int quad_align, quad_slots;
74         char c;
75
76         ip = first = &ktr->ktr_args[0];
77         c = *resc;
78         quad_align = 0;
79         quad_slots = 1;
80         switch (ktr->ktr_code) {
81         case LINUX_SYS_linux_faccessat:
82         case LINUX_SYS_linux_fchmodat:
83         case LINUX_SYS_linux_fchownat:
84 #ifdef LINUX_SYS_linux_newfstatat
85         case LINUX_SYS_linux_newfstatat:
86 #endif
87 #ifdef LINUX_SYS_linux_fstatat64
88         case LINUX_SYS_linux_fstatat64:
89 #endif
90 #ifdef LINUX_SYS_linux_futimesat
91         case LINUX_SYS_linux_futimesat:
92 #endif
93         case LINUX_SYS_linux_linkat:
94         case LINUX_SYS_linux_mkdirat:
95         case LINUX_SYS_linux_mknodat:
96         case LINUX_SYS_linux_openat:
97         case LINUX_SYS_linux_readlinkat:
98         case LINUX_SYS_linux_renameat:
99         case LINUX_SYS_linux_unlinkat:
100         case LINUX_SYS_linux_utimensat:
101                 putchar('(');
102                 print_integer_arg_valid(sysdecode_atfd, *ip);
103                 c = ',';
104                 ip++;
105                 narg--;
106                 break;
107         }
108         switch (ktr->ktr_code) {
109 #ifdef LINUX_SYS_linux_access
110         case LINUX_SYS_linux_access:
111 #endif
112         case LINUX_SYS_linux_faccessat:
113                 print_number(ip, narg, c);
114                 putchar(',');
115                 print_mask_arg(sysdecode_access_mode, *ip);
116                 ip++;
117                 narg--;
118                 break;
119 #ifdef LINUX_SYS_linux_chmod
120         case LINUX_SYS_linux_chmod:
121 #endif
122         case LINUX_SYS_linux_fchmodat:
123                 print_number(ip, narg, c);
124                 putchar(',');
125                 decode_filemode(*ip);
126                 ip++;
127                 narg--;
128                 break;
129         case LINUX_SYS_linux_mknodat:
130                 print_number(ip, narg, c);
131                 putchar(',');
132                 decode_filemode(*ip);
133                 ip++;
134                 narg--;
135                 break;
136 #ifdef LINUX_SYS_linux_mkdir
137         case LINUX_SYS_linux_mkdir:
138 #endif
139         case LINUX_SYS_linux_mkdirat:
140                 print_number(ip, narg, c);
141                 putchar(',');
142                 decode_filemode(*ip);
143                 ip++;
144                 narg--;
145                 break;
146         case LINUX_SYS_linux_linkat:
147         case LINUX_SYS_linux_renameat:
148         case LINUX_SYS_linux_symlinkat:
149                 print_number(ip, narg, c);
150                 putchar(',');
151                 print_integer_arg_valid(sysdecode_atfd, *ip);
152                 ip++;
153                 narg--;
154                 print_number(ip, narg, c);
155                 break;
156         case LINUX_SYS_linux_fchownat:
157                 print_number(ip, narg, c);
158                 print_number(ip, narg, c);
159                 print_number(ip, narg, c);
160                 break;
161 #ifdef LINUX_SYS_linux_newfstatat
162         case LINUX_SYS_linux_newfstatat:
163 #endif
164 #ifdef LINUX_SYS_linux_fstatat64
165         case LINUX_SYS_linux_fstatat64:
166 #endif
167         case LINUX_SYS_linux_utimensat:
168                 print_number(ip, narg, c);
169                 print_number(ip, narg, c);
170                 break;
171         case LINUX_SYS_linux_unlinkat:
172                 print_number(ip, narg, c);
173                 break;
174         case LINUX_SYS_linux_clock_gettime:
175         case LINUX_SYS_linux_clock_settime:
176         case LINUX_SYS_linux_clock_getres:
177         case LINUX_SYS_linux_timer_create:
178                 putchar('(');
179                 sysdecode_linux_clockid(stdout, *ip);
180                 c = ',';
181                 ip++;
182                 narg--;
183                 break;
184         case LINUX_SYS_linux_clock_nanosleep:
185                 putchar('(');
186                 sysdecode_linux_clockid(stdout, *ip);
187                 putchar(',');
188                 ip++;
189                 narg--;
190                 print_mask_arg0(sysdecode_linux_clock_flags, *ip);
191                 c = ',';
192                 ip++;
193                 narg--;
194                 break;
195         case LINUX_SYS_linux_kill:
196         case LINUX_SYS_linux_tkill:
197         case LINUX_SYS_linux_rt_sigqueueinfo:
198                 print_number(ip, narg, c);
199                 putchar(',');
200                 print_linux_signal(*ip);
201                 ip++;
202                 narg--;
203                 break;
204         case LINUX_SYS_linux_tgkill:
205         case LINUX_SYS_linux_rt_tgsigqueueinfo:
206                 print_number(ip, narg, c);
207                 print_number(ip, narg, c);
208                 putchar(',');
209                 print_linux_signal(*ip);
210                 ip++;
211                 narg--;
212                 break;
213 #ifdef LINUX_SYS_linux_open
214         case LINUX_SYS_linux_open:
215 #endif
216         case LINUX_SYS_linux_openat:
217                 print_number(ip, narg, c);
218                 putchar(',');
219                 print_mask_arg(sysdecode_linux_open_flags, ip[0]);
220                 if ((ip[0] & LINUX_O_CREAT) == LINUX_O_CREAT) {
221                         putchar(',');
222                         decode_filemode(ip[1]);
223                 }
224                 ip += 2;
225                 narg -= 2;
226                 break;
227         case LINUX_SYS_linux_rt_sigaction:
228                 putchar('(');
229                 print_linux_signal(*ip);
230                 ip++;
231                 narg--;
232                 c = ',';
233                 break;
234         case LINUX_SYS_linux_ftruncate:
235         case LINUX_SYS_linux_truncate:
236                 print_number(ip, narg, c);
237                 print_number64(first, ip, narg, c);
238                 break;
239         case LINUX_SYS_linux_getitimer:
240         case LINUX_SYS_linux_setitimer:
241                 putchar('(');
242                 print_integer_arg(sysdecode_itimer, *ip);
243                 ip++;
244                 narg--;
245                 c = ',';
246                 break;
247         case LINUX_SYS_linux_rt_sigprocmask:
248 #ifdef LINUX_SYS_linux_sigprocmask
249         case LINUX_SYS_linux_sigprocmask:
250 #endif
251                 putchar('(');
252                 print_integer_arg(sysdecode_linux_sigprocmask_how, *ip);
253                 ip++;
254                 narg--;
255                 c = ',';
256                 break;
257         }
258         switch (ktr->ktr_code) {
259         case LINUX_SYS_linux_fchownat:
260         case LINUX_SYS_linux_faccessat:
261         case LINUX_SYS_linux_fchmodat:
262 #ifdef LINUX_SYS_linux_newfstatat
263         case LINUX_SYS_linux_newfstatat:
264 #endif
265 #ifdef LINUX_SYS_linux_fstatat64
266         case LINUX_SYS_linux_fstatat64:
267 #endif
268         case LINUX_SYS_linux_linkat:
269         case LINUX_SYS_linux_unlinkat:
270         case LINUX_SYS_linux_utimensat:
271                 putchar(',');
272                 print_mask_arg0(sysdecode_linux_atflags, *ip);
273                 ip++;
274                 narg--;
275                 break;
276         }
277         *resc = c;
278         *resip = ip;
279         *resnarg = narg;
280 }
281
282 #if defined(__amd64__)
283 void
284 ktrsyscall_linux32(struct ktr_syscall *ktr, register_t **resip,
285     int *resnarg, char *resc)
286 {
287         int narg = ktr->ktr_narg;
288         register_t *ip, *first;
289         int quad_align, quad_slots;
290         char c;
291
292         ip = first = &ktr->ktr_args[0];
293         c = *resc;
294         quad_align = 0;
295         quad_slots = 2;
296         switch (ktr->ktr_code) {
297         case LINUX32_SYS_linux_faccessat:
298         case LINUX32_SYS_linux_fchmodat:
299         case LINUX32_SYS_linux_fchownat:
300         case LINUX32_SYS_linux_fstatat64:
301         case LINUX32_SYS_linux_futimesat:
302         case LINUX32_SYS_linux_linkat:
303         case LINUX32_SYS_linux_mkdirat:
304         case LINUX32_SYS_linux_mknodat:
305         case LINUX32_SYS_linux_openat:
306         case LINUX32_SYS_linux_readlinkat:
307         case LINUX32_SYS_linux_renameat:
308         case LINUX32_SYS_linux_unlinkat:
309         case LINUX32_SYS_linux_utimensat:
310                 putchar('(');
311                 print_integer_arg_valid(sysdecode_atfd, *ip);
312                 c = ',';
313                 ip++;
314                 narg--;
315                 break;
316         }
317         switch (ktr->ktr_code) {
318         case LINUX32_SYS_linux_access:
319         case LINUX32_SYS_linux_faccessat:
320                 print_number(ip, narg, c);
321                 putchar(',');
322                 print_mask_arg(sysdecode_access_mode, *ip);
323                 ip++;
324                 narg--;
325                 break;
326         case LINUX32_SYS_linux_chmod:
327         case LINUX32_SYS_fchmod:
328         case LINUX32_SYS_linux_fchmodat:
329                 print_number(ip, narg, c);
330                 putchar(',');
331                 decode_filemode(*ip);
332                 ip++;
333                 narg--;
334                 break;
335         case LINUX32_SYS_linux_mknodat:
336                 print_number(ip, narg, c);
337                 putchar(',');
338                 decode_filemode(*ip);
339                 ip++;
340                 narg--;
341                 break;
342         case LINUX32_SYS_linux_mkdir:
343         case LINUX32_SYS_linux_mkdirat:
344                 print_number(ip, narg, c);
345                 putchar(',');
346                 decode_filemode(*ip);
347                 ip++;
348                 narg--;
349                 break;
350         case LINUX32_SYS_linux_linkat:
351         case LINUX32_SYS_linux_renameat:
352         case LINUX32_SYS_linux_symlinkat:
353                 print_number(ip, narg, c);
354                 putchar(',');
355                 print_integer_arg_valid(sysdecode_atfd, *ip);
356                 ip++;
357                 narg--;
358                 print_number(ip, narg, c);
359                 break;
360         case LINUX32_SYS_linux_fchownat:
361                 print_number(ip, narg, c);
362                 print_number(ip, narg, c);
363                 print_number(ip, narg, c);
364                 break;
365         case LINUX32_SYS_linux_fstatat64:
366         case LINUX32_SYS_linux_utimensat:
367                 print_number(ip, narg, c);
368                 print_number(ip, narg, c);
369                 break;
370         case LINUX32_SYS_linux_unlinkat:
371                 print_number(ip, narg, c);
372                 break;
373         case LINUX32_SYS_linux_clock_gettime:
374         case LINUX32_SYS_linux_clock_settime:
375         case LINUX32_SYS_linux_clock_getres:
376         case LINUX32_SYS_linux_timer_create:
377         case LINUX32_SYS_linux_clock_gettime64:
378         case LINUX32_SYS_linux_clock_settime64:
379         case LINUX32_SYS_linux_clock_getres_time64:
380                 putchar('(');
381                 sysdecode_linux_clockid(stdout, *ip);
382                 c = ',';
383                 ip++;
384                 narg--;
385                 break;
386         case LINUX32_SYS_linux_clock_nanosleep:
387                 putchar('(');
388                 sysdecode_linux_clockid(stdout, *ip);
389                 putchar(',');
390                 ip++;
391                 narg--;
392                 print_mask_arg0(sysdecode_linux_clock_flags, *ip);
393                 c = ',';
394                 ip++;
395                 narg--;
396                 break;
397         case LINUX32_SYS_linux_kill:
398         case LINUX32_SYS_linux_tkill:
399         case LINUX32_SYS_linux_rt_sigqueueinfo:
400                 print_number(ip, narg, c);
401                 putchar(',');
402                 print_linux_signal(*ip);
403                 ip++;
404                 narg--;
405                 break;
406         case LINUX32_SYS_linux_tgkill:
407         case LINUX32_SYS_linux_rt_tgsigqueueinfo:
408                 print_number(ip, narg, c);
409                 print_number(ip, narg, c);
410                 putchar(',');
411                 print_linux_signal(*ip);
412                 ip++;
413                 narg--;
414                 break;
415         case LINUX32_SYS_linux_open:
416         case LINUX32_SYS_linux_openat:
417                 print_number(ip, narg, c);
418                 putchar(',');
419                 print_mask_arg(sysdecode_linux_open_flags, ip[0]);
420                 if ((ip[0] & LINUX_O_CREAT) == LINUX_O_CREAT) {
421                         putchar(',');
422                         decode_filemode(ip[1]);
423                 }
424                 ip += 2;
425                 narg -= 2;
426                 break;
427         case LINUX32_SYS_linux_signal:
428         case LINUX32_SYS_linux_sigaction:
429         case LINUX32_SYS_linux_rt_sigaction:
430                 putchar('(');
431                 print_linux_signal(*ip);
432                 ip++;
433                 narg--;
434                 c = ',';
435                 break;
436         case LINUX32_SYS_linux_ftruncate:
437         case LINUX32_SYS_linux_truncate:
438                 print_number(ip, narg, c);
439                 print_number64(first, ip, narg, c);
440                 break;
441         case LINUX32_SYS_linux_getitimer:
442         case LINUX32_SYS_linux_setitimer:
443                 putchar('(');
444                 print_integer_arg(sysdecode_itimer, *ip);
445                 ip++;
446                 narg--;
447                 c = ',';
448                 break;
449         case LINUX32_SYS_linux_rt_sigprocmask:
450         case LINUX32_SYS_linux_sigprocmask:
451                 putchar('(');
452                 print_integer_arg(sysdecode_linux_sigprocmask_how, *ip);
453                 ip++;
454                 narg--;
455                 c = ',';
456                 break;
457         }
458         switch (ktr->ktr_code) {
459         case LINUX32_SYS_linux_fchownat:
460         case LINUX32_SYS_linux_faccessat:
461         case LINUX32_SYS_linux_fchmodat:
462         case LINUX32_SYS_linux_fstatat64:
463         case LINUX32_SYS_linux_linkat:
464         case LINUX32_SYS_linux_unlinkat:
465         case LINUX32_SYS_linux_utimensat:
466                 putchar(',');
467                 print_mask_arg0(sysdecode_linux_atflags, *ip);
468                 ip++;
469                 narg--;
470                 break;
471         }
472         *resc = c;
473         *resip = ip;
474         *resnarg = narg;
475 }
476 #endif /* __amd64__ */
477
478 static void
479 ktrsigset(const char *name, const l_sigset_t *mask, size_t sz)
480 {
481         unsigned long i, c;
482
483         printf("%s [ ", name);
484         c = 0;
485         for (i = 1; i <= sz * CHAR_BIT; i++) {
486                 if (!LINUX_SIGISMEMBER(*mask, i))
487                         continue;
488                 if (c != 0)
489                         printf(", ");
490                 printf("%s", sysdecode_linux_signal(i));
491                 c++;
492         }
493         if (c == 0)
494                 printf("empty ]\n");
495         else
496                 printf(" ]\n");
497 }
498
499 bool
500 ktrstruct_linux(const char *name, const char *data, size_t datalen)
501 {
502         l_sigset_t mask;
503
504         if (strcmp(name, "l_sigset_t") == 0) {
505                 /* Old Linux sigset_t is one word size. */
506                 if (datalen < sizeof(int) || datalen > sizeof(l_sigset_t))
507                         return (false);
508                 memcpy(&mask, data, datalen);
509                 ktrsigset(name, &mask, datalen);
510         } else
511                 return (false);
512
513         return (true);
514 }