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