diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2019-05-19 23:35:20 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2019-05-19 23:35:20 +0000 |
commit | d7e00d657a1f623d5f794827e4bfe6db1abaad34 (patch) | |
tree | 38817572854b0844b05ad3e4787934ccaec26005 /io_uring.c | |
parent | f625d610c7018cef0380f81e513695c66615443c (diff) | |
download | strace-d7e00d657a1f623d5f794827e4bfe6db1abaad34.tar.gz |
Implement decoding of io_uring_* syscalls
... introduced by Linux kernel commits v5.1-rc1~99^2~14,
v5.1-rc1~99^2~7, and v5.1-rc7~24^2.
* configure.ac (AC_CHECK_HEADERS): Add linux/io_uring.h.
* io_uring.c: New file.
* Makefile.am (strace_SOURCES): Add it.
* pathtrace.c (pathtrace_match_set): Add SEN_io_uring_enter,
SEN_io_uring_register, and SEN_io_uring_setup.
* xlat/uring_enter_flags.in: New file.
* xlat/uring_register_opcodes.in: Likewise.
* linux/32/syscallent.h [425, 426, 427]: Wire up io_uring_setup,
io_uring_enter, and io_uring_register.
* linux/64/syscallent.h: Likewise.
* linux/arm/syscallent.h: Likewise.
* linux/hppa/syscallent.h: Likewise.
* linux/i386/syscallent.h: Likewise.
* linux/m68k/syscallent.h: Likewise.
* linux/microblaze/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/powerpc64/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sh/syscallent.h: Likewise.
* linux/sh64/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
* linux/sparc64/syscallent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/syscallent.h: Likewise.
* linux/xtensa/syscallent.h: Likewise.
* linux/alpha/syscallent.h [535, 536, 537]: Likewise.
* linux/ia64/syscallent.h [1024 + 425, 1024 + 426, 1024 + 427]: Likewise.
* linux/mips/syscallent-n32.h [6425, 6426, 6427]: Likewise.
* linux/mips/syscallent-n64.h [5425, 5426, 5427]: Likewise.
* linux/mips/syscallent-o32.h [4425, 4426, 4427]: Likewise.
* NEWS: Mention this change.
* tests/io_uring_enter.c: New file.
* tests/io_uring_register.c: Likewise.
* tests/io_uring_setup.c: Likewise.
* tests/gen_tests.in (io_uring_enter, io_uring_register,
io_uring_setup): New entries.
* tests/pure_executables.list: Add io_uring_enter, io_uring_register,
and io_uring_setup.
* tests/.gitignore: Likewise.
Diffstat (limited to 'io_uring.c')
-rw-r--r-- | io_uring.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/io_uring.c b/io_uring.c new file mode 100644 index 000000000..0b82a0754 --- /dev/null +++ b/io_uring.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2019 Dmitry V. Levin <ldv@altlinux.org> + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +#ifdef HAVE_LINUX_IO_URING_H +# include "print_fields.h" +# include <linux/io_uring.h> +#endif + +#include "xlat/uring_setup_flags.h" +#include "xlat/uring_enter_flags.h" +#include "xlat/uring_register_opcodes.h" + +SYS_FUNC(io_uring_setup) +{ + const uint32_t nentries = tcp->u_arg[0]; + const kernel_ulong_t params_addr = tcp->u_arg[1]; + +#ifdef HAVE_LINUX_IO_URING_H + struct io_uring_params params; + + if (entering(tcp)) { + tprintf("%u, ", nentries); + + if (umove_or_printaddr(tcp, params_addr, ¶ms)) + return RVAL_DECODED | RVAL_FD; + + PRINT_FIELD_FLAGS("{", params, flags, uring_setup_flags, + "IORING_SETUP_???"); + PRINT_FIELD_X(", ", params, sq_thread_cpu); + PRINT_FIELD_U(", ", params, sq_thread_idle); + for (unsigned int i = 0; i < ARRAY_SIZE(params.resv); ++i) { + if (params.resv[i]) { + for (i = 0; i < ARRAY_SIZE(params.resv); ++i) + tprintf("%s%#x", + (i ? ", " : ", resv={"), + params.resv[i]); + tprints("}"); + break; + } + } + return 0; + } else { + if (syserror(tcp)) { + /* The remaining part of params is irrelevant. */ + } else if (umove(tcp, params_addr, ¶ms)) { + tprints(", ???"); + } else { + PRINT_FIELD_U(", ", params, sq_entries); + PRINT_FIELD_U(", ", params, cq_entries); + PRINT_FIELD_U(", sq_off={", params.sq_off, head); + PRINT_FIELD_U(", ", params.sq_off, tail); + PRINT_FIELD_U(", ", params.sq_off, ring_mask); + PRINT_FIELD_U(", ", params.sq_off, ring_entries); + PRINT_FIELD_U(", ", params.sq_off, flags); + PRINT_FIELD_U(", ", params.sq_off, dropped); + PRINT_FIELD_U(", ", params.sq_off, array); + PRINT_FIELD_U("}, cq_off={", params.cq_off, head); + PRINT_FIELD_U(", ", params.cq_off, tail); + PRINT_FIELD_U(", ", params.cq_off, ring_mask); + PRINT_FIELD_U(", ", params.cq_off, ring_entries); + PRINT_FIELD_U(", ", params.cq_off, overflow); + PRINT_FIELD_U(", ", params.cq_off, cqes); + tprints("}"); + } + tprints("}"); + } +#else /* !HAVE_LINUX_IO_URING_H */ + tprintf("%u, ", nentries); + printaddr(params_addr); +#endif + + return RVAL_DECODED | RVAL_FD; +} + +SYS_FUNC(io_uring_enter) +{ + const int fd = tcp->u_arg[0]; + const uint32_t to_submit = tcp->u_arg[1]; + const uint32_t min_complete = tcp->u_arg[2]; + const uint32_t flags = tcp->u_arg[3]; + const kernel_ulong_t sigset_addr = tcp->u_arg[4]; + const kernel_ulong_t sigset_size = tcp->u_arg[5]; + + printfd(tcp, fd); + tprintf(", %u, %u, ", to_submit, min_complete); + printflags(uring_enter_flags, flags, "IORING_ENTER_???"); + tprints(", "); + print_sigset_addr_len(tcp, sigset_addr, sigset_size); + tprintf(", %" PRI_klu, sigset_size); + + return RVAL_DECODED; +} + +static bool +print_fd_array_member(struct tcb *tcp, void *elem_buf, size_t elem_size, + void *data) +{ + printfd(tcp, *(int *) elem_buf); + return true; +} + +SYS_FUNC(io_uring_register) +{ + const int fd = tcp->u_arg[0]; + const unsigned int opcode = tcp->u_arg[1]; + const kernel_ulong_t arg = tcp->u_arg[2]; + const unsigned int nargs = tcp->u_arg[3]; + int buf; + + printfd(tcp, fd); + tprints(", "); + printxval(uring_register_opcodes, opcode, "IORING_REGISTER_???"); + tprints(", "); + switch (opcode) { + case IORING_REGISTER_BUFFERS: + tprint_iov(tcp, nargs, arg, IOV_DECODE_ADDR); + break; + case IORING_REGISTER_FILES: + print_array(tcp, arg, nargs, &buf, sizeof(buf), + tfetch_mem, print_fd_array_member, NULL); + break; + default: + printaddr(arg); + break; + } + tprintf(", %u", nargs); + + return RVAL_DECODED; +} |