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