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.

io.c 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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-2018 The strace developers.
  7. * All rights reserved.
  8. *
  9. * SPDX-License-Identifier: LGPL-2.1-or-later
  10. */
  11. #include "defs.h"
  12. #include <fcntl.h>
  13. #include <sys/uio.h>
  14. SYS_FUNC(read)
  15. {
  16. if (entering(tcp)) {
  17. printfd(tcp, tcp->u_arg[0]);
  18. tprints(", ");
  19. } else {
  20. if (syserror(tcp))
  21. printaddr(tcp->u_arg[1]);
  22. else
  23. printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
  24. tprintf(", %" PRI_klu, tcp->u_arg[2]);
  25. }
  26. return 0;
  27. }
  28. SYS_FUNC(write)
  29. {
  30. printfd(tcp, tcp->u_arg[0]);
  31. tprints(", ");
  32. printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
  33. tprintf(", %" PRI_klu, tcp->u_arg[2]);
  34. return RVAL_DECODED;
  35. }
  36. struct print_iovec_config {
  37. enum iov_decode decode_iov;
  38. kernel_ulong_t data_size;
  39. };
  40. static bool
  41. print_iovec(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
  42. {
  43. const kernel_ulong_t *iov;
  44. kernel_ulong_t iov_buf[2], len;
  45. struct print_iovec_config *c = data;
  46. if (elem_size < sizeof(iov_buf)) {
  47. iov_buf[0] = ((unsigned int *) elem_buf)[0];
  48. iov_buf[1] = ((unsigned int *) elem_buf)[1];
  49. iov = iov_buf;
  50. } else {
  51. iov = elem_buf;
  52. }
  53. tprints("{iov_base=");
  54. len = iov[1];
  55. switch (c->decode_iov) {
  56. case IOV_DECODE_STR:
  57. if (len > c->data_size)
  58. len = c->data_size;
  59. if (c->data_size != (kernel_ulong_t) -1)
  60. c->data_size -= len;
  61. printstrn(tcp, iov[0], len);
  62. break;
  63. case IOV_DECODE_NETLINK:
  64. if (len > c->data_size)
  65. len = c->data_size;
  66. if (c->data_size != (kernel_ulong_t) -1)
  67. c->data_size -= len;
  68. /* assume that the descriptor is 1st syscall argument */
  69. decode_netlink(tcp, tcp->u_arg[0], iov[0], len);
  70. break;
  71. default:
  72. printaddr(iov[0]);
  73. break;
  74. }
  75. tprintf(", iov_len=%" PRI_klu "}", iov[1]);
  76. return true;
  77. }
  78. /*
  79. * data_size limits the cumulative size of printed data.
  80. * Example: recvmsg returing a short read.
  81. */
  82. void
  83. tprint_iov_upto(struct tcb *const tcp, const kernel_ulong_t len,
  84. const kernel_ulong_t addr, const enum iov_decode decode_iov,
  85. const kernel_ulong_t data_size)
  86. {
  87. kernel_ulong_t iov[2];
  88. struct print_iovec_config config = {
  89. .decode_iov = decode_iov, .data_size = data_size
  90. };
  91. print_array(tcp, addr, len, iov, current_wordsize * 2,
  92. tfetch_mem_ignore_syserror, print_iovec, &config);
  93. }
  94. SYS_FUNC(readv)
  95. {
  96. if (entering(tcp)) {
  97. printfd(tcp, tcp->u_arg[0]);
  98. tprints(", ");
  99. } else {
  100. tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1],
  101. syserror(tcp) ? IOV_DECODE_ADDR :
  102. IOV_DECODE_STR, tcp->u_rval);
  103. tprintf(", %" PRI_klu, tcp->u_arg[2]);
  104. }
  105. return 0;
  106. }
  107. SYS_FUNC(writev)
  108. {
  109. printfd(tcp, tcp->u_arg[0]);
  110. tprints(", ");
  111. tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], IOV_DECODE_STR);
  112. tprintf(", %" PRI_klu, tcp->u_arg[2]);
  113. return RVAL_DECODED;
  114. }
  115. SYS_FUNC(pread)
  116. {
  117. if (entering(tcp)) {
  118. printfd(tcp, tcp->u_arg[0]);
  119. tprints(", ");
  120. } else {
  121. if (syserror(tcp))
  122. printaddr(tcp->u_arg[1]);
  123. else
  124. printstrn(tcp, tcp->u_arg[1], tcp->u_rval);
  125. tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
  126. printllval(tcp, "%lld", 3);
  127. }
  128. return 0;
  129. }
  130. SYS_FUNC(pwrite)
  131. {
  132. printfd(tcp, tcp->u_arg[0]);
  133. tprints(", ");
  134. printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]);
  135. tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
  136. printllval(tcp, "%lld", 3);
  137. return RVAL_DECODED;
  138. }
  139. static void
  140. print_lld_from_low_high_val(struct tcb *tcp, int arg)
  141. {
  142. #if SIZEOF_KERNEL_LONG_T > 4
  143. # ifndef current_klongsize
  144. if (current_klongsize < SIZEOF_KERNEL_LONG_T) {
  145. tprintf("%" PRI_kld, (tcp->u_arg[arg + 1] << 32)
  146. | tcp->u_arg[arg]);
  147. } else
  148. # endif /* !current_klongsize */
  149. {
  150. tprintf("%" PRI_kld, tcp->u_arg[arg]);
  151. }
  152. #else /* SIZEOF_KERNEL_LONG_T == 4 */
  153. tprintf("%lld",
  154. ((long long) tcp->u_arg[arg + 1] << 32)
  155. | ((long long) tcp->u_arg[arg]));
  156. #endif
  157. }
  158. #include "xlat/rwf_flags.h"
  159. static int
  160. do_preadv(struct tcb *tcp, const int flags_arg)
  161. {
  162. if (entering(tcp)) {
  163. printfd(tcp, tcp->u_arg[0]);
  164. tprints(", ");
  165. } else {
  166. kernel_ulong_t len =
  167. truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
  168. tprint_iov_upto(tcp, len, tcp->u_arg[1],
  169. syserror(tcp) ? IOV_DECODE_ADDR :
  170. IOV_DECODE_STR, tcp->u_rval);
  171. tprintf(", %" PRI_klu ", ", len);
  172. print_lld_from_low_high_val(tcp, 3);
  173. if (flags_arg >= 0) {
  174. tprints(", ");
  175. printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
  176. }
  177. }
  178. return 0;
  179. }
  180. SYS_FUNC(preadv)
  181. {
  182. return do_preadv(tcp, -1);
  183. }
  184. static int
  185. do_pwritev(struct tcb *tcp, const int flags_arg)
  186. {
  187. kernel_ulong_t len =
  188. truncate_kulong_to_current_wordsize(tcp->u_arg[2]);
  189. printfd(tcp, tcp->u_arg[0]);
  190. tprints(", ");
  191. tprint_iov(tcp, len, tcp->u_arg[1], IOV_DECODE_STR);
  192. tprintf(", %" PRI_klu ", ", len);
  193. print_lld_from_low_high_val(tcp, 3);
  194. if (flags_arg >= 0) {
  195. tprints(", ");
  196. printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???");
  197. }
  198. return RVAL_DECODED;
  199. }
  200. SYS_FUNC(pwritev)
  201. {
  202. return do_pwritev(tcp, -1);
  203. }
  204. /*
  205. * x32 is the only architecture where preadv2 takes 5 arguments
  206. * instead of 6, see preadv64v2 in kernel sources.
  207. * Likewise, x32 is the only architecture where pwritev2 takes 5 arguments
  208. * instead of 6, see pwritev64v2 in kernel sources.
  209. */
  210. #if defined X86_64
  211. # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 2 ? 4 : 5)
  212. #elif defined X32
  213. # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 0 ? 4 : 5)
  214. #else
  215. # define PREADV2_PWRITEV2_FLAGS_ARG_NO 5
  216. #endif
  217. SYS_FUNC(preadv2)
  218. {
  219. return do_preadv(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
  220. }
  221. SYS_FUNC(pwritev2)
  222. {
  223. return do_pwritev(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
  224. }
  225. #include "xlat/splice_flags.h"
  226. SYS_FUNC(tee)
  227. {
  228. /* int fd_in */
  229. printfd(tcp, tcp->u_arg[0]);
  230. tprints(", ");
  231. /* int fd_out */
  232. printfd(tcp, tcp->u_arg[1]);
  233. tprints(", ");
  234. /* size_t len */
  235. tprintf("%" PRI_klu ", ", tcp->u_arg[2]);
  236. /* unsigned int flags */
  237. printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
  238. return RVAL_DECODED;
  239. }
  240. SYS_FUNC(splice)
  241. {
  242. /* int fd_in */
  243. printfd(tcp, tcp->u_arg[0]);
  244. tprints(", ");
  245. /* loff_t *off_in */
  246. printnum_int64(tcp, tcp->u_arg[1], "%" PRId64);
  247. tprints(", ");
  248. /* int fd_out */
  249. printfd(tcp, tcp->u_arg[2]);
  250. tprints(", ");
  251. /* loff_t *off_out */
  252. printnum_int64(tcp, tcp->u_arg[3], "%" PRId64);
  253. tprints(", ");
  254. /* size_t len */
  255. tprintf("%" PRI_klu ", ", tcp->u_arg[4]);
  256. /* unsigned int flags */
  257. printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???");
  258. return RVAL_DECODED;
  259. }
  260. SYS_FUNC(vmsplice)
  261. {
  262. /* int fd */
  263. printfd(tcp, tcp->u_arg[0]);
  264. tprints(", ");
  265. /* const struct iovec *iov, unsigned long nr_segs */
  266. tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], IOV_DECODE_STR);
  267. tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
  268. /* unsigned int flags */
  269. printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???");
  270. return RVAL_DECODED;
  271. }