]> granicus.if.org Git - strace/blob - kexec.c
Mpersify parsers of utimes, futimesat, and utimensat syscalls
[strace] / kexec.c
1 #include "defs.h"
2
3 #include "xlat/kexec_load_flags.h"
4 #include "xlat/kexec_arch_values.h"
5
6 #ifndef KEXEC_ARCH_MASK
7 # define KEXEC_ARCH_MASK 0xffff0000
8 #endif
9 #ifndef KEXEC_SEGMENT_MAX
10 # define KEXEC_SEGMENT_MAX 16
11 #endif
12
13 static void
14 print_seg(const long seg_buf, const unsigned long seg_bufsz,
15           const long seg_mem, const unsigned long seg_memsz)
16 {
17         tprints("{");
18         printaddr(seg_buf);
19         tprintf(", %lu, ", seg_bufsz);
20         printaddr(seg_mem);
21         tprintf(", %lu}", seg_memsz);
22 }
23
24 static void
25 print_kexec_segments(struct tcb *tcp, const unsigned long addr,
26                      const 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 {
45                 void *buf;
46                 size_t bufsz;
47                 void *mem;
48                 size_t memsz;
49         } seg;
50 # define sizeof_seg sizeof(seg)
51 # define seg_buf seg.buf
52 # define seg_bufsz seg.bufsz
53 # define seg_mem seg.mem
54 # define seg_memsz seg.memsz
55 #endif
56         unsigned int i;
57
58         if (!len) {
59                 tprints("[]");
60                 return;
61         }
62
63         if (len > KEXEC_SEGMENT_MAX) {
64                 printaddr(addr);
65                 return;
66         }
67
68         if (umoven_or_printaddr(tcp, addr, sizeof_seg, &seg))
69                 return;
70
71         tprints("[");
72         print_seg((unsigned long) seg_buf, seg_bufsz,
73                   (unsigned long) seg_mem, seg_memsz);
74
75         for (i = 1; i < len; ++i) {
76                 tprints(", ");
77                 if (umoven_or_printaddr(tcp, addr + i * sizeof_seg,
78                                         sizeof_seg, &seg))
79                         break;
80                 print_seg((unsigned long) seg_buf, seg_bufsz,
81                           (unsigned long) seg_mem, seg_memsz);
82         }
83
84         tprints("]");
85 }
86
87 SYS_FUNC(kexec_load)
88 {
89         unsigned long n;
90
91         /* entry, nr_segments */
92         printaddr(tcp->u_arg[0]);
93         tprintf(", %lu, ", tcp->u_arg[1]);
94
95         /* segments */
96         print_kexec_segments(tcp, tcp->u_arg[2], tcp->u_arg[1]);
97         tprints(", ");
98
99         /* flags */
100         n = tcp->u_arg[3];
101         printxval(kexec_arch_values, n & KEXEC_ARCH_MASK, "KEXEC_ARCH_???");
102         n &= ~KEXEC_ARCH_MASK;
103         if (n) {
104                 tprints("|");
105                 printflags(kexec_load_flags, n, "KEXEC_???");
106         }
107
108         return RVAL_DECODED;
109 }