(root)/
strace-6.5/
src/
aio.c
       1  /*
       2   * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
       3   * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
       4   * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
       5   * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
       6   * Copyright (c) 1999-2021 The strace developers.
       7   * All rights reserved.
       8   *
       9   * SPDX-License-Identifier: LGPL-2.1-or-later
      10   */
      11  
      12  #include "defs.h"
      13  #include <linux/aio_abi.h>
      14  
      15  #include "xlat/aio_cmds.h"
      16  
      17  #ifdef HAVE_STRUCT_IOCB_AIO_FLAGS
      18  # include "xlat/aio_iocb_flags.h"
      19  #endif
      20  
      21  SYS_FUNC(io_setup)
      22  {
      23  	if (entering(tcp)) {
      24  		/* nr_events */
      25  		unsigned int nr_events = tcp->u_arg[0];
      26  		PRINT_VAL_U(nr_events);
      27  		tprint_arg_next();
      28  	} else {
      29  		/* ctx_idp */
      30  		printnum_ptr(tcp, tcp->u_arg[1]);
      31  	}
      32  	return 0;
      33  }
      34  
      35  SYS_FUNC(io_destroy)
      36  {
      37  	/* ctx_id */
      38  	printaddr(tcp->u_arg[0]);
      39  
      40  	return RVAL_DECODED;
      41  }
      42  
      43  enum iocb_sub {
      44  	SUB_NONE, SUB_COMMON, SUB_VECTOR, SUB_POLL
      45  };
      46  
      47  static enum iocb_sub
      48  tprint_lio_opcode(unsigned int cmd)
      49  {
      50  	static const enum iocb_sub subs[] = {
      51  		[IOCB_CMD_PREAD]	= SUB_COMMON,
      52  		[IOCB_CMD_PWRITE]	= SUB_COMMON,
      53  		[IOCB_CMD_FSYNC]	= SUB_NONE,
      54  		[IOCB_CMD_FDSYNC]	= SUB_NONE,
      55  		[IOCB_CMD_PREADX]	= SUB_NONE,
      56  		[IOCB_CMD_POLL]		= SUB_POLL,
      57  		[IOCB_CMD_NOOP]		= SUB_NONE,
      58  		[IOCB_CMD_PREADV]	= SUB_VECTOR,
      59  		[IOCB_CMD_PWRITEV]	= SUB_VECTOR,
      60  	};
      61  
      62  	printxval_ex(aio_cmds, cmd, "IOCB_CMD_???", XLAT_STYLE_FMT_U);
      63  
      64  	return cmd < ARRAY_SIZE(subs) ? subs[cmd] : SUB_NONE;
      65  }
      66  
      67  static void
      68  print_common_flags(struct tcb *tcp, const struct iocb *cb)
      69  {
      70  /* aio_flags and aio_resfd fields are available since v2.6.22-rc1~47 */
      71  #ifdef HAVE_STRUCT_IOCB_AIO_FLAGS
      72  	if (cb->aio_flags) {
      73  		tprint_struct_next();
      74  		PRINT_FIELD_FLAGS(*cb, aio_flags, aio_iocb_flags,
      75  				  "IOCB_FLAG_???");
      76  	}
      77  
      78  	if (cb->aio_flags & IOCB_FLAG_RESFD) {
      79  		tprint_struct_next();
      80  		PRINT_FIELD_FD(*cb, aio_resfd, tcp);
      81  	} else if (cb->aio_resfd) {
      82  		tprint_struct_next();
      83  		PRINT_FIELD_X(*cb, aio_resfd);
      84  	}
      85  #endif
      86  }
      87  
      88  static bool
      89  iocb_is_valid(const struct iocb *cb)
      90  {
      91  	return cb->aio_buf == (unsigned long) cb->aio_buf &&
      92  	       cb->aio_nbytes == (size_t) cb->aio_nbytes &&
      93  	       (ssize_t) cb->aio_nbytes >= 0;
      94  }
      95  
      96  static enum iocb_sub
      97  print_iocb_header(struct tcb *tcp, const struct iocb *cb)
      98  {
      99  	enum iocb_sub sub;
     100  
     101  	PRINT_FIELD_X(*cb, aio_data);
     102  
     103  	if (cb->aio_key) {
     104  		tprint_struct_next();
     105  		PRINT_FIELD_U(*cb, aio_key);
     106  	}
     107  
     108  #ifndef HAVE_STRUCT_IOCB_AIO_RW_FLAGS
     109  # define aio_rw_flags aio_reserved1
     110  #endif
     111  	if (cb->aio_rw_flags) {
     112  		tprint_struct_next();
     113  		PRINT_FIELD_FLAGS(*cb, aio_rw_flags, rwf_flags, "RWF_???");
     114  	}
     115  
     116  	tprint_struct_next();
     117  	tprints_field_name("aio_lio_opcode");
     118  	sub = tprint_lio_opcode(cb->aio_lio_opcode);
     119  
     120  	if (cb->aio_flags & IOCB_FLAG_IOPRIO) {
     121  		tprint_struct_next();
     122  		PRINT_FIELD_OBJ_U(*cb, aio_reqprio, print_ioprio);
     123  	} else if (cb->aio_reqprio) {
     124  		tprint_struct_next();
     125  		PRINT_FIELD_D(*cb, aio_reqprio);
     126  	}
     127  
     128  	tprint_struct_next();
     129  	PRINT_FIELD_FD(*cb, aio_fildes, tcp);
     130  
     131  	return sub;
     132  }
     133  
     134  static void
     135  print_iocb(struct tcb *tcp, const struct iocb *cb)
     136  {
     137  	tprint_struct_begin();
     138  
     139  	enum iocb_sub sub = print_iocb_header(tcp, cb);
     140  
     141  	switch (sub) {
     142  	case SUB_COMMON:
     143  		if (cb->aio_lio_opcode == 1 && iocb_is_valid(cb)) {
     144  			tprint_struct_next();
     145  			PRINT_FIELD_OBJ_TCB_VAL(*cb, aio_buf, tcp,
     146  				printstrn, cb->aio_nbytes);
     147  		} else {
     148  			tprint_struct_next();
     149  			PRINT_FIELD_X(*cb, aio_buf);
     150  		}
     151  		tprint_struct_next();
     152  		PRINT_FIELD_U(*cb, aio_nbytes);
     153  		tprint_struct_next();
     154  		PRINT_FIELD_D(*cb, aio_offset);
     155  		print_common_flags(tcp, cb);
     156  		break;
     157  	case SUB_VECTOR:
     158  		if (iocb_is_valid(cb)) {
     159  			tprint_struct_next();
     160  			tprints_field_name("aio_buf");
     161  			tprint_iov(tcp, cb->aio_nbytes, cb->aio_buf,
     162  				   cb->aio_lio_opcode == 8
     163  				   ? iov_decode_str
     164  				   : iov_decode_addr);
     165  		} else {
     166  			tprint_struct_next();
     167  			PRINT_FIELD_X(*cb, aio_buf);
     168  			tprint_struct_next();
     169  			PRINT_FIELD_U(*cb, aio_nbytes);
     170  		}
     171  		tprint_struct_next();
     172  		PRINT_FIELD_D(*cb, aio_offset);
     173  		print_common_flags(tcp, cb);
     174  		break;
     175  	case SUB_POLL:
     176  		tprint_struct_next();
     177  		PRINT_FIELD_FLAGS(*cb, aio_buf, pollflags, "POLL???");
     178  		print_common_flags(tcp, cb);
     179  		break;
     180  	case SUB_NONE:
     181  		break;
     182  	}
     183  
     184  	tprint_struct_end();
     185  }
     186  
     187  static bool
     188  print_iocbp(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
     189  {
     190  	kernel_ulong_t addr;
     191  	struct iocb cb;
     192  
     193  	if (elem_size < sizeof(kernel_ulong_t)) {
     194  		addr = *(unsigned int *) elem_buf;
     195  	} else {
     196  		addr = *(kernel_ulong_t *) elem_buf;
     197  	}
     198  
     199  	if (!umove_or_printaddr(tcp, addr, &cb))
     200  		print_iocb(tcp, &cb);
     201  
     202  	return true;
     203  }
     204  
     205  SYS_FUNC(io_submit)
     206  {
     207  	const kernel_ulong_t addr = tcp->u_arg[2];
     208  	kernel_ulong_t iocbp;
     209  
     210  	/* ctx_id */
     211  	printaddr(tcp->u_arg[0]);
     212  	tprint_arg_next();
     213  
     214  	/* nr */
     215  	const kernel_long_t nr =
     216  		truncate_klong_to_current_wordsize(tcp->u_arg[1]);
     217  	PRINT_VAL_D(nr);
     218  	tprint_arg_next();
     219  
     220  	/* iocbpp */
     221  	if (nr < 0)
     222  		printaddr(addr);
     223  	else
     224  		print_array(tcp, addr, nr, &iocbp, current_wordsize,
     225  			    tfetch_mem, print_iocbp, 0);
     226  
     227  	return RVAL_DECODED;
     228  }
     229  
     230  static bool
     231  print_io_event(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
     232  {
     233  	struct io_event *event = elem_buf;
     234  
     235  	tprint_struct_begin();
     236  	PRINT_FIELD_X(*event, data);
     237  	tprint_struct_next();
     238  	PRINT_FIELD_X(*event, obj);
     239  	tprint_struct_next();
     240  	PRINT_FIELD_D(*event, res);
     241  	tprint_struct_next();
     242  	PRINT_FIELD_D(*event, res2);
     243  	tprint_struct_end();
     244  
     245  	return true;
     246  }
     247  
     248  SYS_FUNC(io_cancel)
     249  {
     250  	if (entering(tcp)) {
     251  		/* ctx_id */
     252  		printaddr(tcp->u_arg[0]);
     253  		tprint_arg_next();
     254  
     255  		/* iocb */
     256  		struct iocb cb;
     257  		if (!umove_or_printaddr(tcp, tcp->u_arg[1], &cb)) {
     258  			tprint_struct_begin();
     259  			print_iocb_header(tcp, &cb);
     260  			tprint_struct_end();
     261  		}
     262  		tprint_arg_next();
     263  	} else {
     264  		/* result */
     265  		struct io_event event;
     266  		if (!umove_or_printaddr(tcp, tcp->u_arg[2], &event))
     267  			print_io_event(tcp, &event, sizeof(event), 0);
     268  	}
     269  	return 0;
     270  }
     271  
     272  static int
     273  print_io_getevents(struct tcb *const tcp, const print_obj_by_addr_fn print_ts,
     274  		   const bool has_sig)
     275  {
     276  	if (entering(tcp)) {
     277  		kernel_long_t nr;
     278  
     279  		/* ctx_id */
     280  		printaddr(tcp->u_arg[0]);
     281  		tprint_arg_next();
     282  
     283  		/* min_nr */
     284  		nr = truncate_klong_to_current_wordsize(tcp->u_arg[1]);
     285  		PRINT_VAL_D(nr);
     286  		tprint_arg_next();
     287  
     288  		/* nr */
     289  		nr = truncate_klong_to_current_wordsize(tcp->u_arg[2]);
     290  		PRINT_VAL_D(nr);
     291  		tprint_arg_next();
     292  	} else {
     293  		/* events */
     294  		struct io_event buf;
     295  		print_array(tcp, tcp->u_arg[3], tcp->u_rval, &buf, sizeof(buf),
     296  			    tfetch_mem, print_io_event, 0);
     297  		tprint_arg_next();
     298  
     299  		/*
     300  		 * Since the timeout and sig parameters are read by the kernel
     301  		 * on entering syscall, it has to be decoded the same way
     302  		 * whether the syscall has failed or not.
     303  		 */
     304  		temporarily_clear_syserror(tcp);
     305  
     306  		/* timeout */
     307  		print_ts(tcp, tcp->u_arg[4]);
     308  
     309  		if (has_sig) {
     310  			tprint_arg_next();
     311  
     312  			/* sig */
     313  			print_kernel_sigset(tcp, tcp->u_arg[5]);
     314  		}
     315  
     316  		restore_cleared_syserror(tcp);
     317  	}
     318  	return 0;
     319  }
     320  
     321  #if HAVE_ARCH_TIME32_SYSCALLS
     322  SYS_FUNC(io_getevents_time32)
     323  {
     324  	return print_io_getevents(tcp, print_timespec32, false);
     325  }
     326  #endif
     327  
     328  #if HAVE_ARCH_OLD_TIME64_SYSCALLS
     329  SYS_FUNC(io_getevents_time64)
     330  {
     331  	return print_io_getevents(tcp, print_timespec64, false);
     332  }
     333  #endif
     334  
     335  #if HAVE_ARCH_TIME32_SYSCALLS
     336  SYS_FUNC(io_pgetevents_time32)
     337  {
     338  	return print_io_getevents(tcp, print_timespec32, true);
     339  }
     340  #endif
     341  
     342  SYS_FUNC(io_pgetevents_time64)
     343  {
     344  	return print_io_getevents(tcp, print_timespec64, true);
     345  }