(root)/
strace-6.5/
src/
kexec.c
       1  /*
       2   * Copyright (c) 2014-2015 Dmitry V. Levin <ldv@strace.io>
       3   * Copyright (c) 2014-2022 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: LGPL-2.1-or-later
       7   */
       8  
       9  #include "defs.h"
      10  #include <linux/kexec.h>
      11  
      12  #include "xlat/kexec_load_flags.h"
      13  #include "xlat/kexec_arch_values.h"
      14  
      15  static bool
      16  print_seg(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
      17  {
      18  	const kernel_ulong_t *seg;
      19  	kernel_ulong_t seg_buf[4];
      20  
      21  	if (elem_size < sizeof(seg_buf)) {
      22  		for (unsigned int i = 0; i < ARRAY_SIZE(seg_buf); ++i)
      23  			seg_buf[i] = ((unsigned int *) elem_buf)[i];
      24  		seg = seg_buf;
      25  	} else {
      26  		seg = elem_buf;
      27  	}
      28  
      29  	tprint_struct_begin();
      30  	tprints_field_name("buf");
      31  	printaddr(seg[0]);
      32  	tprint_struct_next();
      33  	tprints_field_name("bufsz");
      34  	PRINT_VAL_U(seg[1]);
      35  	tprint_struct_next();
      36  	tprints_field_name("mem");
      37  	printaddr(seg[2]);
      38  	tprint_struct_next();
      39  	tprints_field_name("memsz");
      40  	PRINT_VAL_U(seg[3]);
      41  	tprint_struct_end();
      42  
      43  	return true;
      44  }
      45  
      46  static void
      47  print_kexec_segments(struct tcb *const tcp, const kernel_ulong_t addr,
      48  		     const kernel_ulong_t len)
      49  {
      50  	if (len > KEXEC_SEGMENT_MAX) {
      51  		printaddr(addr);
      52  		return;
      53  	}
      54  
      55  	kernel_ulong_t seg[4];
      56  	const size_t sizeof_seg = ARRAY_SIZE(seg) * current_wordsize;
      57  
      58  	print_array(tcp, addr, len, seg, sizeof_seg,
      59  		    tfetch_mem, print_seg, 0);
      60  }
      61  
      62  SYS_FUNC(kexec_load)
      63  {
      64  	/* entry */
      65  	printaddr(tcp->u_arg[0]);
      66  	tprint_arg_next();
      67  
      68  	/* nr_segments */
      69  	PRINT_VAL_U(tcp->u_arg[1]);
      70  	tprint_arg_next();
      71  
      72  	/* segments */
      73  	print_kexec_segments(tcp, tcp->u_arg[2], tcp->u_arg[1]);
      74  	tprint_arg_next();
      75  
      76  	/* flags */
      77  	kernel_ulong_t n = tcp->u_arg[3];
      78  	tprint_flags_begin();
      79  	printxval64(kexec_arch_values, n & KEXEC_ARCH_MASK, "KEXEC_ARCH_???");
      80  	n &= ~(kernel_ulong_t) KEXEC_ARCH_MASK;
      81  	if (n) {
      82  		tprint_flags_or();
      83  		printflags64_in(kexec_load_flags, n, "KEXEC_???");
      84  	}
      85  	tprint_flags_end();
      86  
      87  	return RVAL_DECODED;
      88  }
      89  
      90  #include "xlat/kexec_file_load_flags.h"
      91  
      92  SYS_FUNC(kexec_file_load)
      93  {
      94  	/* kernel_fd */
      95  	printfd(tcp, tcp->u_arg[0]);
      96  	tprint_arg_next();
      97  
      98  	/* initrd_fd */
      99  	printfd(tcp, tcp->u_arg[1]);
     100  	tprint_arg_next();
     101  
     102  	/* cmdline_len */
     103  	PRINT_VAL_U(tcp->u_arg[2]);
     104  	tprint_arg_next();
     105  
     106  	/* cmdline */
     107  	printstrn(tcp, tcp->u_arg[3], tcp->u_arg[2]);
     108  	tprint_arg_next();
     109  
     110  	/* flags */
     111  	printflags64(kexec_file_load_flags, tcp->u_arg[4], "KEXEC_FILE_???");
     112  
     113  	return RVAL_DECODED;
     114  }