Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sg_io_v4.c 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Copyright (c) 2015 Bart Van Assche <bart.vanassche@sandisk.com>
  3. * Copyright (c) 2015-2018 Dmitry V. Levin <ldv@altlinux.org>
  4. * All rights reserved.
  5. *
  6. * SPDX-License-Identifier: LGPL-2.1-or-later
  7. */
  8. #include "defs.h"
  9. #ifdef HAVE_LINUX_BSG_H
  10. # include "print_fields.h"
  11. # include <linux/bsg.h>
  12. # include "xlat/bsg_protocol.h"
  13. # include "xlat/bsg_subprotocol.h"
  14. # include "xlat/bsg_flags.h"
  15. static void
  16. print_sg_io_buffer(struct tcb *const tcp, const kernel_ulong_t addr,
  17. const unsigned int data_size, const unsigned int iovec_count)
  18. {
  19. if (iovec_count) {
  20. tprint_iov_upto(tcp, iovec_count, addr, IOV_DECODE_STR,
  21. data_size);
  22. } else {
  23. printstr_ex(tcp, addr, data_size, QUOTE_FORCE_HEX);
  24. }
  25. }
  26. # define PRINT_FIELD_SG_IO_BUFFER(prefix_, where_, field_, size_, count_, tcp_) \
  27. do { \
  28. STRACE_PRINTF("%s%s=", (prefix_), #field_); \
  29. print_sg_io_buffer((tcp_), (where_).field_, (size_), (count_)); \
  30. } while (0)
  31. static int
  32. decode_request(struct tcb *const tcp, const kernel_ulong_t arg)
  33. {
  34. struct sg_io_v4 sg_io;
  35. static const size_t skip_iid = offsetof(struct sg_io_v4, protocol);
  36. tprints("{guard='Q', ");
  37. if (umoven_or_printaddr(tcp, arg + skip_iid, sizeof(sg_io) - skip_iid,
  38. &sg_io.protocol)) {
  39. tprints("}");
  40. return RVAL_IOCTL_DECODED;
  41. }
  42. PRINT_FIELD_XVAL("", sg_io, protocol, bsg_protocol, "BSG_PROTOCOL_???");
  43. PRINT_FIELD_XVAL(", ", sg_io, subprotocol, bsg_subprotocol,
  44. "BSG_SUB_PROTOCOL_???");
  45. PRINT_FIELD_U(", ", sg_io, request_len);
  46. PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, request, sg_io.request_len,
  47. 0, tcp);
  48. PRINT_FIELD_X(", ", sg_io, request_tag);
  49. PRINT_FIELD_U(", ", sg_io, request_attr);
  50. PRINT_FIELD_U(", ", sg_io, request_priority);
  51. PRINT_FIELD_U(", ", sg_io, request_extra);
  52. PRINT_FIELD_U(", ", sg_io, max_response_len);
  53. PRINT_FIELD_U(", ", sg_io, dout_iovec_count);
  54. PRINT_FIELD_U(", ", sg_io, dout_xfer_len);
  55. PRINT_FIELD_U(", ", sg_io, din_iovec_count);
  56. PRINT_FIELD_U(", ", sg_io, din_xfer_len);
  57. PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, dout_xferp, sg_io.dout_xfer_len,
  58. sg_io.dout_iovec_count, tcp);
  59. PRINT_FIELD_U(", ", sg_io, timeout);
  60. PRINT_FIELD_FLAGS(", ", sg_io, flags, bsg_flags, "BSG_FLAG_???");
  61. PRINT_FIELD_X(", ", sg_io, usr_ptr);
  62. struct sg_io_v4 *entering_sg_io = malloc(sizeof(*entering_sg_io));
  63. if (entering_sg_io) {
  64. memcpy(entering_sg_io, &sg_io, sizeof(sg_io));
  65. entering_sg_io->guard = (unsigned char) 'Q';
  66. set_tcb_priv_data(tcp, entering_sg_io, free);
  67. }
  68. return 0;
  69. }
  70. static int
  71. decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
  72. {
  73. struct sg_io_v4 *entering_sg_io = get_tcb_priv_data(tcp);
  74. struct sg_io_v4 sg_io;
  75. uint32_t din_len;
  76. if (umove(tcp, arg, &sg_io) < 0) {
  77. /* print i/o fields fetched on entering syscall */
  78. PRINT_FIELD_X(", ", *entering_sg_io, response);
  79. PRINT_FIELD_X(", ", *entering_sg_io, din_xferp);
  80. return RVAL_IOCTL_DECODED;
  81. }
  82. if (sg_io.guard != entering_sg_io->guard) {
  83. PRINT_FIELD_U(" => ", sg_io, guard);
  84. return RVAL_IOCTL_DECODED;
  85. }
  86. PRINT_FIELD_U(", ", sg_io, response_len);
  87. PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, response, sg_io.response_len,
  88. 0, tcp);
  89. din_len = sg_io.din_xfer_len;
  90. if (sg_io.din_resid > 0 && (unsigned int) sg_io.din_resid <= din_len)
  91. din_len -= sg_io.din_resid;
  92. PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, din_xferp, din_len,
  93. sg_io.din_iovec_count, tcp);
  94. PRINT_FIELD_X(", ", sg_io, driver_status);
  95. PRINT_FIELD_X(", ", sg_io, transport_status);
  96. PRINT_FIELD_X(", ", sg_io, device_status);
  97. PRINT_FIELD_U(", ", sg_io, retry_delay);
  98. PRINT_FIELD_FLAGS(", ", sg_io, info, sg_io_info, "SG_INFO_???");
  99. PRINT_FIELD_U(", ", sg_io, duration);
  100. PRINT_FIELD_U(", ", sg_io, response_len);
  101. PRINT_FIELD_D(", ", sg_io, din_resid);
  102. PRINT_FIELD_D(", ", sg_io, dout_resid);
  103. PRINT_FIELD_X(", ", sg_io, generated_tag);
  104. return RVAL_IOCTL_DECODED;
  105. }
  106. #else /* !HAVE_LINUX_BSG_H */
  107. static int
  108. decode_request(struct tcb *const tcp, const kernel_ulong_t arg)
  109. {
  110. tprints("{guard='Q', ...}");
  111. return RVAL_IOCTL_DECODED;
  112. }
  113. static int
  114. decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
  115. {
  116. return 0;
  117. }
  118. #endif
  119. int
  120. decode_sg_io_v4(struct tcb *const tcp, const kernel_ulong_t arg)
  121. {
  122. return entering(tcp) ? decode_request(tcp, arg)
  123. : decode_response(tcp, arg);
  124. }