Home | History | Annotate | Download | only in strace
      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 }
     91