(root)/
strace-6.5/
src/
sg_io_v3.c
       1  /*
       2   * Copyright (c) 2007 Vladimir Nadvornik <nadvornik@suse.cz>
       3   * Copyright (c) 2007-2021 Dmitry V. Levin <ldv@strace.io>
       4   * Copyright (c) 2015 Bart Van Assche <bart.vanassche@sandisk.com>
       5   * Copyright (c) 2021-2023 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: LGPL-2.1-or-later
       9   */
      10  
      11  #include "defs.h"
      12  
      13  #ifdef HAVE_SCSI_SG_H
      14  
      15  # include DEF_MPERS_TYPE(struct_sg_io_hdr)
      16  
      17  # include <scsi/sg.h>
      18  
      19  typedef struct sg_io_hdr struct_sg_io_hdr;
      20  
      21  #endif /* HAVE_SCSI_SG_H */
      22  
      23  #include MPERS_DEFS
      24  
      25  #include "xlat/sg_io_info.h"
      26  
      27  #ifdef HAVE_SCSI_SG_H
      28  # include "xlat/sg_io_dxfer_direction.h"
      29  # include "xlat/sg_io_flags.h"
      30  
      31  static void
      32  print_sg_io_buffer(struct tcb *const tcp, const kernel_ulong_t addr,
      33  		   const unsigned int data_size, const unsigned int iovec_count)
      34  {
      35  	if (iovec_count) {
      36  		tprint_iov_upto(tcp, iovec_count, addr, data_size,
      37  				iov_decode_str, NULL);
      38  	} else {
      39  		printstr_ex(tcp, addr, data_size, QUOTE_FORCE_HEX);
      40  	}
      41  }
      42  
      43  # define PRINT_FIELD_SG_IO_BUFFER(where_, field_, size_, count_, tcp_)		\
      44  	do {									\
      45  		tprints_field_name(#field_);					\
      46  		print_sg_io_buffer((tcp_), (mpers_ptr_t)((where_).field_),	\
      47  				   (size_), (count_));				\
      48  	} while (0)
      49  
      50  static int
      51  decode_request(struct tcb *const tcp, const kernel_ulong_t arg)
      52  {
      53  	struct_sg_io_hdr sg_io;
      54  	static const size_t skip_iid =
      55  		offsetof(struct_sg_io_hdr, dxfer_direction);
      56  
      57  	tprint_struct_begin();
      58  	tprints_field_name("interface_id");
      59  	tprints_string("'S'");
      60  	tprint_struct_next();
      61  	if (umoven_or_printaddr(tcp, arg + skip_iid, sizeof(sg_io) - skip_iid,
      62  				&sg_io.dxfer_direction)) {
      63  		tprint_struct_end();
      64  		return RVAL_IOCTL_DECODED;
      65  	}
      66  
      67  	PRINT_FIELD_XVAL(sg_io, dxfer_direction, sg_io_dxfer_direction,
      68  			 "SG_DXFER_???");
      69  	tprint_struct_next();
      70  	PRINT_FIELD_U(sg_io, cmd_len);
      71  	tprint_struct_next();
      72  	PRINT_FIELD_SG_IO_BUFFER(sg_io, cmdp, sg_io.cmd_len, 0, tcp);
      73  	tprint_struct_next();
      74  	PRINT_FIELD_U(sg_io, mx_sb_len);
      75  	tprint_struct_next();
      76  	PRINT_FIELD_U(sg_io, iovec_count);
      77  	tprint_struct_next();
      78  	PRINT_FIELD_U(sg_io, dxfer_len);
      79  	tprint_struct_next();
      80  	PRINT_FIELD_U(sg_io, timeout);
      81  	tprint_struct_next();
      82  	PRINT_FIELD_FLAGS(sg_io, flags, sg_io_flags, "SG_FLAG_???");
      83  
      84  	if (sg_io.dxfer_direction == SG_DXFER_TO_DEV ||
      85  	    sg_io.dxfer_direction == SG_DXFER_TO_FROM_DEV) {
      86  		tprint_struct_next();
      87  		PRINT_FIELD_SG_IO_BUFFER(sg_io, dxferp, sg_io.dxfer_len, sg_io.iovec_count, tcp);
      88  	}
      89  
      90  	struct_sg_io_hdr *entering_sg_io = xobjdup(&sg_io);
      91  	entering_sg_io->interface_id = (unsigned char) 'S';
      92  	set_tcb_priv_data(tcp, entering_sg_io, free);
      93  
      94  	return 0;
      95  }
      96  
      97  static int
      98  decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
      99  {
     100  	struct_sg_io_hdr *entering_sg_io = get_tcb_priv_data(tcp);
     101  	struct_sg_io_hdr sg_io;
     102  
     103  	if (umove(tcp, arg, &sg_io) < 0) {
     104  		/* print i/o fields fetched on entering syscall */
     105  		if (entering_sg_io->dxfer_direction == SG_DXFER_FROM_DEV) {
     106  			tprint_struct_next();
     107  			PRINT_FIELD_PTR(*entering_sg_io, dxferp);
     108  		}
     109  		tprint_struct_next();
     110  		PRINT_FIELD_PTR(*entering_sg_io, sbp);
     111  		return RVAL_IOCTL_DECODED;
     112  	}
     113  
     114  	if (sg_io.interface_id != entering_sg_io->interface_id) {
     115  		tprint_value_changed();
     116  		PRINT_FIELD_U(sg_io, interface_id);
     117  		return RVAL_IOCTL_DECODED;
     118  	}
     119  
     120  	if (sg_io.dxfer_direction == SG_DXFER_FROM_DEV ||
     121  	    sg_io.dxfer_direction == SG_DXFER_TO_FROM_DEV) {
     122  		uint32_t din_len = sg_io.dxfer_len;
     123  		bool print_buffer = false;
     124  
     125  		if (sg_io.resid > 0 && (unsigned int) sg_io.resid <= din_len)
     126  			din_len -= sg_io.resid;
     127  
     128  		if (sg_io.dxfer_direction == SG_DXFER_FROM_DEV) {
     129  			tprint_struct_next();
     130  			print_buffer = true;
     131  		} else if (din_len) {
     132  			tprint_value_changed();
     133  			print_buffer = true;
     134  		}
     135  
     136  		if (print_buffer) {
     137  			PRINT_FIELD_SG_IO_BUFFER(sg_io, dxferp, din_len,
     138  						 sg_io.iovec_count, tcp);
     139  		}
     140  	}
     141  	tprint_struct_next();
     142  	PRINT_FIELD_X(sg_io, status);
     143  	tprint_struct_next();
     144  	PRINT_FIELD_X(sg_io, masked_status);
     145  	tprint_struct_next();
     146  	PRINT_FIELD_X(sg_io, msg_status);
     147  	tprint_struct_next();
     148  	PRINT_FIELD_U(sg_io, sb_len_wr);
     149  	tprint_struct_next();
     150  	PRINT_FIELD_SG_IO_BUFFER(sg_io, sbp, sg_io.sb_len_wr, 0, tcp);
     151  	tprint_struct_next();
     152  	PRINT_FIELD_X(sg_io, host_status);
     153  	tprint_struct_next();
     154  	PRINT_FIELD_X(sg_io, driver_status);
     155  	tprint_struct_next();
     156  	PRINT_FIELD_D(sg_io, resid);
     157  	tprint_struct_next();
     158  	PRINT_FIELD_U(sg_io, duration);
     159  	tprint_struct_next();
     160  	PRINT_FIELD_FLAGS(sg_io, info, sg_io_info, "SG_INFO_???");
     161  
     162  	return RVAL_IOCTL_DECODED;
     163  }
     164  
     165  #else /* !HAVE_SCSI_SG_H */
     166  
     167  static int
     168  decode_request(struct tcb *const tcp, const kernel_ulong_t arg)
     169  {
     170  	tprint_struct_begin();
     171  	tprints_field_name("interface_id");
     172  	tprints_string("'S'");
     173  	tprint_struct_next();
     174  	tprint_more_data_follows();
     175  	tprint_struct_end();
     176  	return RVAL_IOCTL_DECODED;
     177  }
     178  
     179  static int
     180  decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
     181  {
     182  	return 0;
     183  }
     184  
     185  #endif
     186  
     187  MPERS_PRINTER_DECL(int, decode_sg_io_v3,
     188  		   struct tcb *const tcp, const kernel_ulong_t arg)
     189  {
     190  	return entering(tcp) ? decode_request(tcp, arg)
     191  			     : decode_response(tcp, arg);
     192  }