(root)/
strace-6.5/
src/
io.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 <fcntl.h>
      14  #include <sys/uio.h>
      15  
      16  SYS_FUNC(read)
      17  {
      18  	if (entering(tcp)) {
      19  		/* fd */
      20  		printfd(tcp, tcp->u_arg[0]);
      21  		tprint_arg_next();
      22  	} else {
      23  		/* buf */
      24  		if (syserror(tcp))
      25  			printaddr(tcp->u_arg[1]);
      26  		else
      27  			printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
      28  		tprint_arg_next();
      29  
      30  		/* count */
      31  		PRINT_VAL_U(tcp->u_arg[2]);
      32  	}
      33  	return 0;
      34  }
      35  
      36  SYS_FUNC(write)
      37  {
      38  	/* fd */
      39  	printfd(tcp, tcp->u_arg[0]);
      40  	tprint_arg_next();
      41  
      42  	/* buf */
      43  	printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
      44  	tprint_arg_next();
      45  
      46  	/* count */
      47  	PRINT_VAL_U(tcp->u_arg[2]);
      48  
      49  	return RVAL_DECODED;
      50  }
      51  
      52  void
      53  iov_decode_addr(struct tcb *tcp, kernel_ulong_t addr, kernel_ulong_t size,
      54  	       void *opaque_data)
      55  {
      56  	printaddr(addr);
      57  }
      58  
      59  void
      60  iov_decode_str(struct tcb *tcp, kernel_ulong_t addr, kernel_ulong_t size,
      61  	       void *opaque_data)
      62  {
      63  	printstrn(tcp, addr, size);
      64  }
      65  
      66  struct print_iovec_config {
      67  	kernel_ulong_t data_size;
      68  	print_obj_by_addr_size_fn print_func;
      69  	void *opaque_data;
      70  };
      71  
      72  static bool
      73  print_iovec_klong(struct tcb *const tcp,
      74  		  const kernel_ulong_t iov_base,
      75  		  const kernel_ulong_t iov_len,
      76  		  struct print_iovec_config *const c)
      77  {
      78  	kernel_ulong_t len = iov_len;
      79  
      80  	if (len > c->data_size)
      81  		len = c->data_size;
      82  	if (c->data_size != (kernel_ulong_t) -1)
      83  		c->data_size -= len;
      84  
      85  	tprint_struct_begin();
      86  	tprints_field_name("iov_base");
      87  	c->print_func(tcp, iov_base, len, c->opaque_data);
      88  	tprint_struct_next();
      89  
      90  	tprints_field_name("iov_len");
      91  	PRINT_VAL_U(iov_len);
      92  	tprint_struct_end();
      93  
      94  	return true;
      95  }
      96  
      97  #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
      98  static bool
      99  print_iovec_elem_int(struct tcb *tcp, void *elem_buf, size_t elem_size,
     100  		     void *data)
     101  {
     102  	const unsigned int *const iov = elem_buf;
     103  	return print_iovec_klong(tcp, iov[0], iov[1], data);
     104  }
     105  #endif
     106  
     107  #if ANY_WORDSIZE_EQUALS_TO_KERNEL_LONG
     108  static bool
     109  print_iovec_elem_klong(struct tcb *tcp, void *elem_buf, size_t elem_size,
     110  		       void *data)
     111  {
     112  	const kernel_ulong_t *const iov = elem_buf;
     113  	return print_iovec_klong(tcp, iov[0], iov[1], data);
     114  }
     115  #endif
     116  
     117  /*
     118   * data_size limits the cumulative size of printed data.
     119   * Example: recvmsg returning a short read.
     120   */
     121  void
     122  tprint_iov_upto(struct tcb *const tcp, const kernel_ulong_t len,
     123  		const kernel_ulong_t addr,
     124  		const kernel_ulong_t data_size,
     125  		print_obj_by_addr_size_fn print_func,
     126  		void *opaque_data)
     127  {
     128  	kernel_ulong_t iov[2];
     129  	struct print_iovec_config config = {
     130  		.data_size = data_size,
     131  		.print_func = print_func,
     132  		.opaque_data = opaque_data
     133  	};
     134  	const print_fn print_elem_func =
     135  #if !ANY_WORDSIZE_EQUALS_TO_KERNEL_LONG
     136  			print_iovec_elem_int;
     137  #elif !ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
     138  			print_iovec_elem_klong;
     139  #else
     140  		current_wordsize < sizeof(kernel_ulong_t) ?
     141  			print_iovec_elem_int :
     142  			print_iovec_elem_klong;
     143  #endif
     144  
     145  	print_array(tcp, addr, len, iov, current_wordsize * 2,
     146  		    tfetch_mem_ignore_syserror, print_elem_func, &config);
     147  }
     148  
     149  SYS_FUNC(readv)
     150  {
     151  	if (entering(tcp)) {
     152  		/* fd */
     153  		printfd(tcp, tcp->u_arg[0]);
     154  		tprint_arg_next();
     155  	} else {
     156  		/* iov */
     157  		tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1], tcp->u_rval,
     158  				syserror(tcp) ? iov_decode_addr
     159  					      : iov_decode_str,
     160  				NULL);
     161  		tprint_arg_next();
     162  
     163  		/* iovcnt */
     164  		PRINT_VAL_U(tcp->u_arg[2]);
     165  	}
     166  	return 0;
     167  }
     168  
     169  SYS_FUNC(writev)
     170  {
     171  	/* fd */
     172  	printfd(tcp, tcp->u_arg[0]);
     173  	tprint_arg_next();
     174  
     175  	/* iov */
     176  	tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], iov_decode_str);
     177  	tprint_arg_next();
     178  
     179  	/* iovcnt */
     180  	PRINT_VAL_U(tcp->u_arg[2]);
     181  
     182  	return RVAL_DECODED;
     183  }
     184  
     185  SYS_FUNC(pread)
     186  {
     187  	if (entering(tcp)) {
     188  		/* fd */
     189  		printfd(tcp, tcp->u_arg[0]);
     190  		tprint_arg_next();
     191  	} else {
     192  		/* buf */
     193  		if (syserror(tcp))
     194  			printaddr(tcp->u_arg[1]);
     195  		else
     196  			printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
     197  		tprint_arg_next();
     198  
     199  		/* count */
     200  		PRINT_VAL_U(tcp->u_arg[2]);
     201  		tprint_arg_next();
     202  
     203  		/* offset */
     204  		print_arg_lld(tcp, 3);
     205  	}
     206  	return 0;
     207  }
     208  
     209  SYS_FUNC(pwrite)
     210  {
     211  	/* fd */
     212  	printfd(tcp, tcp->u_arg[0]);
     213  	tprint_arg_next();
     214  
     215  	/* buf */
     216  	printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
     217  	tprint_arg_next();
     218  
     219  	/* count */
     220  	PRINT_VAL_U(tcp->u_arg[2]);
     221  	tprint_arg_next();
     222  
     223  	/* offset */
     224  	print_arg_lld(tcp, 3);
     225  
     226  	return RVAL_DECODED;
     227  }
     228  
     229  static void
     230  print_lld_from_low_high_val(struct tcb *tcp, int arg)
     231  {
     232  #if SIZEOF_KERNEL_LONG_T > 4
     233  # ifndef current_klongsize
     234  	if (current_klongsize < SIZEOF_KERNEL_LONG_T)
     235  		PRINT_VAL_D((tcp->u_arg[arg + 1] << 32) | tcp->u_arg[arg]);
     236  	else
     237  # endif /* !current_klongsize */
     238  		PRINT_VAL_D(tcp->u_arg[arg]);
     239  #else /* SIZEOF_KERNEL_LONG_T == 4 */
     240  	PRINT_VAL_D(((unsigned long long) tcp->u_arg[arg + 1] << 32) |
     241  		    ((unsigned long long) tcp->u_arg[arg]));
     242  #endif
     243  }
     244  
     245  #include "xlat/rwf_flags.h"
     246  
     247  static int
     248  do_preadv(struct tcb *tcp, const int flags_arg)
     249  {
     250  	if (entering(tcp)) {
     251  		/* fd */
     252  		printfd(tcp, tcp->u_arg[0]);
     253  		tprint_arg_next();
     254  	} else {
     255  		kernel_ulong_t len =
     256  			truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
     257  
     258  		/* iov */
     259  		tprint_iov_upto(tcp, len, tcp->u_arg[1], tcp->u_rval,
     260  				syserror(tcp) ? iov_decode_addr
     261  					      : iov_decode_str,
     262  				NULL);
     263  		tprint_arg_next();
     264  
     265  		/* iovcnt */
     266  		PRINT_VAL_U(len);
     267  		tprint_arg_next();
     268  
     269  		/* offset */
     270  		print_lld_from_low_high_val(tcp, 3);
     271  
     272  		if (flags_arg >= 0) {
     273  			tprint_arg_next();
     274  
     275  			/* flags */
     276  			printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
     277  		}
     278  	}
     279  	return 0;
     280  }
     281  
     282  SYS_FUNC(preadv)
     283  {
     284  	return do_preadv(tcp, -1);
     285  }
     286  
     287  static int
     288  do_pwritev(struct tcb *tcp, const int flags_arg)
     289  {
     290  	kernel_ulong_t len =
     291  		truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
     292  
     293  	/* fd */
     294  	printfd(tcp, tcp->u_arg[0]);
     295  	tprint_arg_next();
     296  
     297  	/* iov */
     298  	tprint_iov(tcp, len, tcp->u_arg[1], iov_decode_str);
     299  	tprint_arg_next();
     300  
     301  	/* iovcnt */
     302  	PRINT_VAL_U(len);
     303  	tprint_arg_next();
     304  
     305  	/* offset */
     306  	print_lld_from_low_high_val(tcp, 3);
     307  
     308  	if (flags_arg >= 0) {
     309  		tprint_arg_next();
     310  
     311  		/* flags */
     312  		printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
     313  	}
     314  
     315  	return RVAL_DECODED;
     316  }
     317  
     318  SYS_FUNC(pwritev)
     319  {
     320  	return do_pwritev(tcp, -1);
     321  }
     322  
     323  /*
     324   * x32 is the only architecture where preadv2 takes 5 arguments
     325   * instead of 6, see preadv64v2 in kernel sources.
     326   * Likewise, x32 is the only architecture where pwritev2 takes 5 arguments
     327   * instead of 6, see pwritev64v2 in kernel sources.
     328   */
     329  
     330  #if defined X86_64
     331  # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 2 ? 4 : 5)
     332  #elif defined X32
     333  # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 0 ? 4 : 5)
     334  #else
     335  # define PREADV2_PWRITEV2_FLAGS_ARG_NO 5
     336  #endif
     337  
     338  SYS_FUNC(preadv2)
     339  {
     340  	return do_preadv(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
     341  }
     342  
     343  SYS_FUNC(pwritev2)
     344  {
     345  	return do_pwritev(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
     346  }
     347  
     348  #include "xlat/splice_flags.h"
     349  
     350  SYS_FUNC(tee)
     351  {
     352  	/* int fd_in */
     353  	printfd(tcp, tcp->u_arg[0]);
     354  	tprint_arg_next();
     355  
     356  	/* int fd_out */
     357  	printfd(tcp, tcp->u_arg[1]);
     358  	tprint_arg_next();
     359  
     360  	/* size_t len */
     361  	PRINT_VAL_U(tcp->u_arg[2]);
     362  	tprint_arg_next();
     363  
     364  	/* unsigned int flags */
     365  	printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
     366  
     367  	return RVAL_DECODED;
     368  }
     369  
     370  SYS_FUNC(splice)
     371  {
     372  	/* int fd_in */
     373  	printfd(tcp, tcp->u_arg[0]);
     374  	tprint_arg_next();
     375  
     376  	/* loff_t *off_in */
     377  	printnum_int64(tcp, tcp->u_arg[1], "%" PRId64);
     378  	tprint_arg_next();
     379  
     380  	/* int fd_out */
     381  	printfd(tcp, tcp->u_arg[2]);
     382  	tprint_arg_next();
     383  
     384  	/* loff_t *off_out */
     385  	printnum_int64(tcp, tcp->u_arg[3], "%" PRId64);
     386  	tprint_arg_next();
     387  
     388  	/* size_t len */
     389  	PRINT_VAL_U(tcp->u_arg[4]);
     390  	tprint_arg_next();
     391  
     392  	/* unsigned int flags */
     393  	printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???");
     394  
     395  	return RVAL_DECODED;
     396  }
     397  
     398  SYS_FUNC(vmsplice)
     399  {
     400  	/* int fd */
     401  	printfd(tcp, tcp->u_arg[0]);
     402  	tprint_arg_next();
     403  
     404  	/* const struct iovec *iov */
     405  	tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], iov_decode_str);
     406  	tprint_arg_next();
     407  
     408  	/* unsigned long nr_segs */
     409  	PRINT_VAL_U(tcp->u_arg[2]);
     410  	tprint_arg_next();
     411  
     412  	/* unsigned int flags */
     413  	printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
     414  
     415  	return RVAL_DECODED;
     416  }