]> granicus.if.org Git - strace/blob - kexec.c
tests: add a test for -yy option
[strace] / kexec.c
1 #include "defs.h"
2 #include <linux/kexec.h>
3
4 #include "xlat/kexec_arch_values.h"
5 #include "xlat/kexec_flags.h"
6
7 static void
8 print_kexec_segments(struct tcb *tcp, unsigned long addr, unsigned long len)
9 {
10 #if SUPPORTED_PERSONALITIES > 1
11         union {
12                 struct { u_int32_t buf, bufsz, mem, memsz; } seg32;
13                 struct { u_int64_t buf, bufsz, mem, memsz; } seg64;
14         } seg;
15 # define sizeof_seg \
16         (current_wordsize == 4 ? sizeof(seg.seg32) : sizeof(seg.seg64))
17 # define seg_buf \
18         (current_wordsize == 4 ? (uint64_t) seg.seg32.buf : seg.seg64.buf)
19 # define seg_bufsz \
20         (current_wordsize == 4 ? (uint64_t) seg.seg32.bufsz : seg.seg64.bufsz)
21 # define seg_mem \
22         (current_wordsize == 4 ? (uint64_t) seg.seg32.mem : seg.seg64.mem)
23 # define seg_memsz \
24         (current_wordsize == 4 ? (uint64_t) seg.seg32.memsz : seg.seg64.memsz)
25 #else
26         struct kexec_segment seg;
27 # define sizeof_seg sizeof(seg)
28 # define seg_buf seg.buf
29 # define seg_bufsz seg.bufsz
30 # define seg_mem seg.mem
31 # define seg_memsz seg.memsz
32 #endif
33         unsigned int i, failed;
34
35         if (!len) {
36                 tprints("[]");
37                 return;
38         }
39
40         if (len > KEXEC_SEGMENT_MAX) {
41                 tprintf("%#lx", addr);
42                 return;
43         }
44
45         failed = 0;
46         tprints("[");
47         for (i = 0; i < len; ++i) {
48                 if (i)
49                         tprints(", ");
50                 if (umoven(tcp, addr + i * sizeof_seg, sizeof_seg,
51                            (char *) &seg) < 0) {
52                         tprints("?");
53                         failed = 1;
54                         break;
55                 }
56                 tprintf("{%#lx, %lu, %#lx, %lu}",
57                         (long) seg_buf, (unsigned long) seg_bufsz,
58                         (long) seg_mem, (unsigned long) seg_memsz);
59         }
60         tprints("]");
61         if (failed)
62                 tprintf(" %#lx", addr);
63 }
64
65 int
66 sys_kexec_load(struct tcb *tcp)
67 {
68         unsigned long n;
69
70         if (exiting(tcp))
71                 return 0;
72
73         /* entry, nr_segments */
74         tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
75
76         /* segments */
77         print_kexec_segments(tcp, tcp->u_arg[2], tcp->u_arg[1]);
78         tprints(", ");
79
80         /* flags */
81         n = tcp->u_arg[3];
82         printxval(kexec_arch_values, n & KEXEC_ARCH_MASK, "KEXEC_ARCH_???");
83         n &= ~KEXEC_ARCH_MASK;
84         if (n) {
85                 tprints("|");
86                 printflags(kexec_flags, n, "KEXEC_???");
87         }
88
89         return 0;
90 }