/
githubmirror
/
strace
Обзор
Документация
Войти
/
githubmirror
/
strace
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/io.c
425 строк
9 KB
Dmitry V. Levin
Update copyright headers
05 авг 2025, 11:00
05 авг 2025, 11:00
7db24b3
Код
Авторство
О чём код?
/* * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> * Copyright (c) 1999-2025 The strace developers. * All rights reserved. * * SPDX-License-Identifier: LGPL-2.1-or-later */ #include "defs.h" #include <fcntl.h> #include <sys/uio.h> SYS_FUNC(read) { if (entering(tcp)) { /* fd */ tprints_arg_name("fd"); printfd(tcp, tcp->u_arg[0]); } else { /* buf */ tprints_arg_next_name("buf"); if (syserror(tcp)) printaddr(tcp->u_arg[1]); else printstrn(tcp, tcp->u_arg[1], tcp->u_rval); /* count */ tprints_arg_next_name("count"); PRINT_VAL_U(tcp->u_arg[2]); } return 0; } SYS_FUNC(write) { /* fd */ tprints_arg_name("fd"); printfd(tcp, tcp->u_arg[0]); /* buf */ tprints_arg_next_name("buf"); printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]); /* count */ tprints_arg_next_name("count"); PRINT_VAL_U(tcp->u_arg[2]); return RVAL_DECODED; } void iov_decode_addr(struct tcb *tcp, kernel_ulong_t addr, kernel_ulong_t size, void *opaque_data) { printaddr(addr); } void iov_decode_str(struct tcb *tcp, kernel_ulong_t addr, kernel_ulong_t size, void *opaque_data) { printstrn(tcp, addr, size); } struct print_iovec_config { kernel_ulong_t data_size; print_obj_by_addr_size_fn print_func; void *opaque_data; }; static bool print_iovec_klong(struct tcb *const tcp, const kernel_ulong_t iov_base, const kernel_ulong_t iov_len, struct print_iovec_config *const c) { kernel_ulong_t len = iov_len; if (len > c->data_size) len = c->data_size; if (c->data_size != (kernel_ulong_t) -1) c->data_size -= len; tprint_struct_begin(); tprints_field_name("iov_base"); c->print_func(tcp, iov_base, len, c->opaque_data); tprint_struct_next(); tprints_field_name("iov_len"); PRINT_VAL_U(iov_len); tprint_struct_end(); return true; } #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG static bool print_iovec_elem_int(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) { const unsigned int *const iov = elem_buf; return print_iovec_klong(tcp, iov[0], iov[1], data); } #endif #if ANY_WORDSIZE_EQUALS_TO_KERNEL_LONG static bool print_iovec_elem_klong(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) { const kernel_ulong_t *const iov = elem_buf; return print_iovec_klong(tcp, iov[0], iov[1], data); } #endif /* * data_size limits the cumulative size of printed data. * Example: recvmsg returning a short read. */ void tprint_iov_upto(struct tcb *const tcp, const kernel_ulong_t len, const kernel_ulong_t addr, const kernel_ulong_t data_size, print_obj_by_addr_size_fn print_func, void *opaque_data) { kernel_ulong_t iov[2]; struct print_iovec_config config = { .data_size = data_size, .print_func = print_func, .opaque_data = opaque_data }; const print_fn print_elem_func = #if !ANY_WORDSIZE_EQUALS_TO_KERNEL_LONG print_iovec_elem_int; #elif !ANY_WORDSIZE_LESS_THAN_KERNEL_LONG print_iovec_elem_klong; #else current_wordsize < sizeof(kernel_ulong_t) ? print_iovec_elem_int : print_iovec_elem_klong; #endif print_array(tcp, addr, len, iov, current_wordsize * 2, tfetch_mem_ignore_syserror, print_elem_func, &config); } SYS_FUNC(readv) { if (entering(tcp)) { /* fd */ tprints_arg_name("fd"); printfd(tcp, tcp->u_arg[0]); } else { /* iov */ tprints_arg_next_name("iov"); tprint_iov_upto(tcp, tcp->u_arg[2], tcp->u_arg[1], tcp->u_rval, syserror(tcp) ? iov_decode_addr : iov_decode_str, NULL); /* iovcnt */ tprints_arg_next_name("iovcnt"); PRINT_VAL_U(tcp->u_arg[2]); } return 0; } SYS_FUNC(writev) { /* fd */ tprints_arg_name("fd"); printfd(tcp, tcp->u_arg[0]); /* iov */ tprints_arg_next_name("iov"); tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], iov_decode_str); /* iovcnt */ tprints_arg_next_name("iovcnt"); PRINT_VAL_U(tcp->u_arg[2]); return RVAL_DECODED; } SYS_FUNC(pread) { if (entering(tcp)) { /* fd */ tprints_arg_name("fd"); printfd(tcp, tcp->u_arg[0]); } else { /* buf */ tprints_arg_next_name("buf"); if (syserror(tcp)) printaddr(tcp->u_arg[1]); else printstrn(tcp, tcp->u_arg[1], tcp->u_rval); /* count */ tprints_arg_next_name("count"); PRINT_VAL_U(tcp->u_arg[2]); /* offset */ tprints_arg_next_name("offset"); print_arg_lld(tcp, 3); } return 0; } SYS_FUNC(pwrite) { /* fd */ tprints_arg_name("fd"); printfd(tcp, tcp->u_arg[0]); /* buf */ tprints_arg_next_name("buf"); printstrn(tcp, tcp->u_arg[1], tcp->u_arg[2]); /* count */ tprints_arg_next_name("count"); PRINT_VAL_U(tcp->u_arg[2]); /* offset */ tprints_arg_next_name("offset"); print_arg_lld(tcp, 3); return RVAL_DECODED; } static void print_lld_from_low_high_val(struct tcb *tcp, int arg) { #if SIZEOF_KERNEL_LONG_T > 4 # ifndef current_klongsize if (current_klongsize < SIZEOF_KERNEL_LONG_T) PRINT_VAL_D((tcp->u_arg[arg + 1] << 32) | tcp->u_arg[arg]); else # endif /* !current_klongsize */ PRINT_VAL_D(tcp->u_arg[arg]); #else /* SIZEOF_KERNEL_LONG_T == 4 */ PRINT_VAL_D(((unsigned long long) tcp->u_arg[arg + 1] << 32) | ((unsigned long long) tcp->u_arg[arg])); #endif } #include "xlat/rwf_flags.h" static int do_preadv(struct tcb *tcp, const int flags_arg) { if (entering(tcp)) { /* fd */ tprints_arg_name("fd"); printfd(tcp, tcp->u_arg[0]); } else { kernel_ulong_t len = truncate_kulong_to_current_wordsize(tcp->u_arg[2]); /* iov */ tprints_arg_next_name("iov"); tprint_iov_upto(tcp, len, tcp->u_arg[1], tcp->u_rval, syserror(tcp) ? iov_decode_addr : iov_decode_str, NULL); /* iovcnt */ tprints_arg_next_name("iovcnt"); PRINT_VAL_U(len); /* offset */ tprints_arg_next_name("offset"); print_lld_from_low_high_val(tcp, 3); if (flags_arg >= 0) { /* flags */ tprints_arg_next_name("flags"); printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???"); } } return 0; } SYS_FUNC(preadv) { return do_preadv(tcp, -1); } static int do_pwritev(struct tcb *tcp, const int flags_arg) { kernel_ulong_t len = truncate_kulong_to_current_wordsize(tcp->u_arg[2]); /* fd */ tprints_arg_name("fd"); printfd(tcp, tcp->u_arg[0]); /* iov */ tprints_arg_next_name("iov"); tprint_iov(tcp, len, tcp->u_arg[1], iov_decode_str); /* iovcnt */ tprints_arg_next_name("iovcnt"); PRINT_VAL_U(len); /* offset */ tprints_arg_next_name("offset"); print_lld_from_low_high_val(tcp, 3); if (flags_arg >= 0) { /* flags */ tprints_arg_next_name("flags"); printflags(rwf_flags, tcp->u_arg[flags_arg], "RWF_???"); } return RVAL_DECODED; } SYS_FUNC(pwritev) { return do_pwritev(tcp, -1); } /* * x32 is the only architecture where preadv2 takes 5 arguments * instead of 6, see preadv64v2 in kernel sources. * Likewise, x32 is the only architecture where pwritev2 takes 5 arguments * instead of 6, see pwritev64v2 in kernel sources. */ #if defined X86_64 # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 2 ? 4 : 5) #elif defined X32 # define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 0 ? 4 : 5) #else # define PREADV2_PWRITEV2_FLAGS_ARG_NO 5 #endif SYS_FUNC(preadv2) { return do_preadv(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO); } SYS_FUNC(pwritev2) { return do_pwritev(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO); } #include "xlat/splice_flags.h" SYS_FUNC(tee) { /* int fd_in */ tprints_arg_name("fd_in"); printfd(tcp, tcp->u_arg[0]); /* int fd_out */ tprints_arg_next_name("fd_out"); printfd(tcp, tcp->u_arg[1]); /* size_t len */ tprints_arg_next_name("len"); PRINT_VAL_U(tcp->u_arg[2]); /* unsigned int flags */ tprints_arg_next_name("flags"); printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???"); return RVAL_DECODED; } SYS_FUNC(splice) { /* int fd_in */ tprints_arg_name("fd_in"); printfd(tcp, tcp->u_arg[0]); /* loff_t *off_in */ tprints_arg_next_name("off_in"); printnum_int64(tcp, tcp->u_arg[1], "%" PRId64); /* int fd_out */ tprints_arg_next_name("fd_out"); printfd(tcp, tcp->u_arg[2]); /* loff_t *off_out */ tprints_arg_next_name("off_out"); printnum_int64(tcp, tcp->u_arg[3], "%" PRId64); /* size_t len */ tprints_arg_next_name("len"); PRINT_VAL_U(tcp->u_arg[4]); /* unsigned int flags */ tprints_arg_next_name("flags"); printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???"); return RVAL_DECODED; } SYS_FUNC(vmsplice) { /* int fd */ tprints_arg_name("fd"); printfd(tcp, tcp->u_arg[0]); /* const struct iovec *iov */ tprints_arg_next_name("iov"); tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], iov_decode_str); /* unsigned long nr_segs */ tprints_arg_next_name("nr_segs"); PRINT_VAL_U(tcp->u_arg[2]); /* unsigned int flags */ tprints_arg_next_name("flags"); printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???"); return RVAL_DECODED; }