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.

aio.c 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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-2019 The strace developers.
  7. * All rights reserved.
  8. *
  9. * SPDX-License-Identifier: LGPL-2.1-or-later
  10. */
  11. #include "defs.h"
  12. #include "print_fields.h"
  13. #include <linux/aio_abi.h>
  14. #include "xlat/aio_cmds.h"
  15. #ifdef HAVE_STRUCT_IOCB_AIO_FLAGS
  16. # include "xlat/aio_iocb_flags.h"
  17. #endif
  18. #ifdef HAVE_STRUCT_IOCB_AIO_RW_FLAGS
  19. # define AIO_RW_FLAGS_FIELD aio_rw_flags
  20. #else
  21. # define AIO_RW_FLAGS_FIELD aio_reserved1
  22. #endif
  23. SYS_FUNC(io_setup)
  24. {
  25. if (entering(tcp))
  26. tprintf("%u, ", (unsigned int) tcp->u_arg[0]);
  27. else
  28. printnum_ptr(tcp, tcp->u_arg[1]);
  29. return 0;
  30. }
  31. SYS_FUNC(io_destroy)
  32. {
  33. printaddr(tcp->u_arg[0]);
  34. return RVAL_DECODED;
  35. }
  36. enum iocb_sub {
  37. SUB_NONE, SUB_COMMON, SUB_VECTOR, SUB_POLL
  38. };
  39. static enum iocb_sub
  40. tprint_lio_opcode(unsigned int cmd)
  41. {
  42. static const enum iocb_sub subs[] = {
  43. [IOCB_CMD_PREAD] = SUB_COMMON,
  44. [IOCB_CMD_PWRITE] = SUB_COMMON,
  45. [IOCB_CMD_FSYNC] = SUB_NONE,
  46. [IOCB_CMD_FDSYNC] = SUB_NONE,
  47. [IOCB_CMD_PREADX] = SUB_NONE,
  48. [IOCB_CMD_POLL] = SUB_POLL,
  49. [IOCB_CMD_NOOP] = SUB_NONE,
  50. [IOCB_CMD_PREADV] = SUB_VECTOR,
  51. [IOCB_CMD_PWRITEV] = SUB_VECTOR,
  52. };
  53. printxval_ex(aio_cmds, cmd, "IOCB_CMD_???", XLAT_STYLE_FMT_U);
  54. return cmd < ARRAY_SIZE(subs) ? subs[cmd] : SUB_NONE;
  55. }
  56. static void
  57. print_common_flags(struct tcb *tcp, const struct iocb *cb)
  58. {
  59. /* aio_flags and aio_resfd fields are available since v2.6.22-rc1~47 */
  60. #ifdef HAVE_STRUCT_IOCB_AIO_FLAGS
  61. if (cb->aio_flags)
  62. PRINT_FIELD_FLAGS(", ", *cb, aio_flags, aio_iocb_flags,
  63. "IOCB_FLAG_???");
  64. if (cb->aio_flags & IOCB_FLAG_RESFD)
  65. PRINT_FIELD_FD(", ", *cb, aio_resfd, tcp);
  66. else if (cb->aio_resfd)
  67. PRINT_FIELD_X(", ", *cb, aio_resfd);
  68. #endif
  69. }
  70. static bool
  71. iocb_is_valid(const struct iocb *cb)
  72. {
  73. return cb->aio_buf == (unsigned long) cb->aio_buf &&
  74. cb->aio_nbytes == (size_t) cb->aio_nbytes &&
  75. (ssize_t) cb->aio_nbytes >= 0;
  76. }
  77. static enum iocb_sub
  78. print_iocb_header(struct tcb *tcp, const struct iocb *cb)
  79. {
  80. enum iocb_sub sub;
  81. PRINT_FIELD_X("", *cb, aio_data);
  82. if (cb->aio_key)
  83. PRINT_FIELD_U(", ", *cb, aio_key);
  84. if (cb->AIO_RW_FLAGS_FIELD) {
  85. tprints(", aio_rw_flags=");
  86. printflags(rwf_flags, cb->AIO_RW_FLAGS_FIELD, "RWF_???");
  87. }
  88. tprints(", aio_lio_opcode=");
  89. sub = tprint_lio_opcode(cb->aio_lio_opcode);
  90. if (cb->aio_flags & IOCB_FLAG_IOPRIO) {
  91. tprints(", aio_reqprio=");
  92. print_ioprio(zero_extend_signed_to_ull(cb->aio_reqprio));
  93. } else if (cb->aio_reqprio) {
  94. PRINT_FIELD_D(", ", *cb, aio_reqprio);
  95. }
  96. PRINT_FIELD_FD(", ", *cb, aio_fildes, tcp);
  97. return sub;
  98. }
  99. static void
  100. print_iocb(struct tcb *tcp, const struct iocb *cb)
  101. {
  102. tprints("{");
  103. enum iocb_sub sub = print_iocb_header(tcp, cb);
  104. switch (sub) {
  105. case SUB_COMMON:
  106. if (cb->aio_lio_opcode == 1 && iocb_is_valid(cb)) {
  107. PRINT_FIELD_STRN(", ", *cb, aio_buf,
  108. cb->aio_nbytes, tcp);
  109. } else {
  110. PRINT_FIELD_X(", ", *cb, aio_buf);
  111. }
  112. PRINT_FIELD_U(", ", *cb, aio_nbytes);
  113. PRINT_FIELD_D(", ", *cb, aio_offset);
  114. print_common_flags(tcp, cb);
  115. break;
  116. case SUB_VECTOR:
  117. if (iocb_is_valid(cb)) {
  118. tprints(", aio_buf=");
  119. tprint_iov(tcp, cb->aio_nbytes, cb->aio_buf,
  120. cb->aio_lio_opcode == 8
  121. ? IOV_DECODE_STR
  122. : IOV_DECODE_ADDR);
  123. } else {
  124. PRINT_FIELD_X(", ", *cb, aio_buf);
  125. PRINT_FIELD_U(", ", *cb, aio_nbytes);
  126. }
  127. PRINT_FIELD_D(", ", *cb, aio_offset);
  128. print_common_flags(tcp, cb);
  129. break;
  130. case SUB_POLL:
  131. PRINT_FIELD_FLAGS(", ", *cb, aio_buf, pollflags, "POLL???");
  132. print_common_flags(tcp, cb);
  133. break;
  134. case SUB_NONE:
  135. break;
  136. }
  137. tprints("}");
  138. }
  139. static bool
  140. print_iocbp(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
  141. {
  142. kernel_ulong_t addr;
  143. struct iocb cb;
  144. if (elem_size < sizeof(kernel_ulong_t)) {
  145. addr = *(unsigned int *) elem_buf;
  146. } else {
  147. addr = *(kernel_ulong_t *) elem_buf;
  148. }
  149. if (!umove_or_printaddr(tcp, addr, &cb))
  150. print_iocb(tcp, &cb);
  151. return true;
  152. }
  153. SYS_FUNC(io_submit)
  154. {
  155. const kernel_long_t nr =
  156. truncate_klong_to_current_wordsize(tcp->u_arg[1]);
  157. const kernel_ulong_t addr = tcp->u_arg[2];
  158. kernel_ulong_t iocbp;
  159. printaddr(tcp->u_arg[0]);
  160. tprintf(", %" PRI_kld ", ", nr);
  161. if (nr < 0)
  162. printaddr(addr);
  163. else
  164. print_array(tcp, addr, nr, &iocbp, current_wordsize,
  165. tfetch_mem, print_iocbp, 0);
  166. return RVAL_DECODED;
  167. }
  168. static bool
  169. print_io_event(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
  170. {
  171. struct io_event *event = elem_buf;
  172. PRINT_FIELD_X("{", *event, data);
  173. PRINT_FIELD_X(", ", *event, obj);
  174. PRINT_FIELD_D(", ", *event, res);
  175. PRINT_FIELD_D(", ", *event, res2);
  176. tprints("}");
  177. return true;
  178. }
  179. SYS_FUNC(io_cancel)
  180. {
  181. if (entering(tcp)) {
  182. printaddr(tcp->u_arg[0]);
  183. tprints(", ");
  184. struct iocb cb;
  185. if (!umove_or_printaddr(tcp, tcp->u_arg[1], &cb)) {
  186. tprints("{");
  187. print_iocb_header(tcp, &cb);
  188. tprints("}");
  189. }
  190. tprints(", ");
  191. } else {
  192. struct io_event event;
  193. if (!umove_or_printaddr(tcp, tcp->u_arg[2], &event))
  194. print_io_event(tcp, &event, sizeof(event), 0);
  195. }
  196. return 0;
  197. }
  198. static int
  199. print_io_getevents(struct tcb *const tcp, const print_obj_by_addr_fn print_ts,
  200. const bool has_usig)
  201. {
  202. if (entering(tcp)) {
  203. printaddr(tcp->u_arg[0]);
  204. tprintf(", %" PRI_kld ", %" PRI_kld ", ",
  205. truncate_klong_to_current_wordsize(tcp->u_arg[1]),
  206. truncate_klong_to_current_wordsize(tcp->u_arg[2]));
  207. } else {
  208. struct io_event buf;
  209. print_array(tcp, tcp->u_arg[3], tcp->u_rval, &buf, sizeof(buf),
  210. tfetch_mem, print_io_event, 0);
  211. tprints(", ");
  212. /*
  213. * Since the timeout and usig parameters are read by the kernel
  214. * on entering syscall, it has to be decoded the same way
  215. * whether the syscall has failed or not.
  216. */
  217. temporarily_clear_syserror(tcp);
  218. print_ts(tcp, tcp->u_arg[4]);
  219. if (has_usig) {
  220. tprints(", ");
  221. print_aio_sigset(tcp, tcp->u_arg[5]);
  222. }
  223. restore_cleared_syserror(tcp);
  224. }
  225. return 0;
  226. }
  227. #if HAVE_ARCH_TIME32_SYSCALLS
  228. SYS_FUNC(io_getevents_time32)
  229. {
  230. return print_io_getevents(tcp, print_timespec32, false);
  231. }
  232. #endif
  233. #if HAVE_ARCH_OLD_TIME64_SYSCALLS
  234. SYS_FUNC(io_getevents_time64)
  235. {
  236. return print_io_getevents(tcp, print_timespec64, false);
  237. }
  238. #endif
  239. #if HAVE_ARCH_TIME32_SYSCALLS
  240. SYS_FUNC(io_pgetevents_time32)
  241. {
  242. return print_io_getevents(tcp, print_timespec32, true);
  243. }
  244. #endif
  245. SYS_FUNC(io_pgetevents_time64)
  246. {
  247. return print_io_getevents(tcp, print_timespec64, true);
  248. }