15 Commits

Author SHA1 Message Date
df9ddd8632 Simplify errnoent and signalent
Remove personality support for errnoent and signalent as
there is nothing personality-specific in these files.

* linux/aarch64/errnoent1.h: Remove.
* linux/aarch64/signalent1.h: Likewise.
* linux/powerpc64/errnoent1.h: Likewise.
* linux/powerpc64/signalent1.h: Likewise.
* linux/riscv/errnoent1.h: Likewise.
* linux/riscv/signalent1.h: Likewise.
* linux/s390x/errnoent1.h: Likewise.
* linux/s390x/signalent1.h: Likewise.
* linux/sparc64/errnoent1.h: Likewise.
* linux/sparc64/signalent1.h: Likewise.
* linux/tile/errnoent1.h: Likewise.
* linux/tile/signalent1.h: Likewise.
* linux/x32/errnoent1.h: Likewise.
* linux/x32/signalent1.h: Likewise.
* linux/x86_64/errnoent1.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/signalent1.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* Makefile.am (EXTRA_DIST): Remove them.
* defs.h (errnoent0): Rename to errnoent.
(signalent0): Rename signalent.
(nerrnos, nsignals): Change to const variables unconditionally.
* syscall.c (errnoent0): Rename to errnoent.
(signalent0): Rename signalent.
(nerrnos, nsignals): Change to const variables unconditionally.
(nerrnos0, nsignals0): Remove.
[SUPPORTED_PERSONALITIES > 1] (errnoent1, signalent1, nerrnos1,
nsignals1): Remove.
[SUPPORTED_PERSONALITIES > 2] (errnoent2, signalent2, nerrnos2,
nsignals2): Likewise.
(set_personality): Do not assign errnoent, signalent, nerrnos,
and nsignals.
2018-05-22 01:08:31 +00:00
Eugene Syromyatnikov
7eac1da9be Introduce print_big_u64_addr
This is needed at least for bpf, btrfs, and sg_io, as 32-bit tracer
cannot figure out whether the kernel is 32-bit or 64-bit,
and its behaviour differs when it handles u64 as a pointer.

* linux/arch_defs_.h [!CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL]
(CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL): New definition, default to 0.
* linux/arm/arch_defs_.h (CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL):
Define to 1.
* linux/i386/arch_defs_.h (CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL):
Likewise.
* linux/mips/arch_defs_.h (CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL):
Likewise.
* linux/powerpc/arch_defs_.h (CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL):
Likewise.
* linux/riscv/arch_defs_.h (CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL):
Likewise.
* linux/s390/arch_defs_.h (CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL):
Likewise.
* linux/sparc/arch_defs_.h (CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL):
Likewise.
* linux/tile/arch_defs_.h (CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL):
Likewise.
* defs.h (print_big_u64_addr): New function.

Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-04-04 12:24:19 +00:00
dcfb3c0d47 Introduce raw syscall invocation wrappers
Unfortunately, syscall(3) provided by libc is too smart
for some of our needs.

* linux/raw_syscall.h: New file.
* linux/aarch64/raw_syscall.h: Likewise.
* linux/alpha/raw_syscall.h: Likewise.
* linux/arc/raw_syscall.h: Likewise.
* linux/arm/raw_syscall.h: Likewise.
* linux/avr32/raw_syscall.h: Likewise.
* linux/bfin/raw_syscall.h: Likewise.
* linux/hppa/raw_syscall.h: Likewise.
* linux/i386/raw_syscall.h: Likewise.
* linux/ia64/raw_syscall.h: Likewise.
* linux/m68k/raw_syscall.h: Likewise.
* linux/metag/raw_syscall.h: Likewise.
* linux/microblaze/raw_syscall.h: Likewise.
* linux/mips/raw_syscall.h: Likewise.
* linux/nios2/raw_syscall.h: Likewise.
* linux/or1k/raw_syscall.h: Likewise.
* linux/powerpc/raw_syscall.h: Likewise.
* linux/powerpc64/raw_syscall.h: Likewise.
* linux/riscv/raw_syscall.h: Likewise.
* linux/s390/raw_syscall.h: Likewise.
* linux/s390x/raw_syscall.h: Likewise.
* linux/sh/raw_syscall.h: Likewise.
* linux/sh64/raw_syscall.h: Likewise.
* linux/sparc/raw_syscall.h: Likewise.
* linux/sparc64/raw_syscall.h: Likewise.
* linux/tile/raw_syscall.h: Likewise.
* linux/x32/raw_syscall.h: Likewise.
* linux/x86_64/raw_syscall.h: Likewise.
* linux/xtensa/raw_syscall.h: Likewise.
* Makefile.am (EXTRA_DIST): Add them.
2018-03-23 13:43:13 +00:00
Eugene Syromyatnikov
5b5e9a7620 Implement decoding of riscv_flush_icache syscall
* linux/riscv/syscallent.h ([259]): Add riscv_flush_icache entry.
* riscv.c: New file.
* Makefile.am (strace_SOURCES): Add it.
* xlat/riscv_flush_icache_flags.in: New file.
* NEWS: Mention it.
2018-01-25 01:55:08 +00:00
Eugene Syromyatnikov
ac8241cd4f Move definition of personality macros to arch_defs_.h
* supported_personalities.h: Remove.
* defs.h: Do not include it.
* linux/arch_defs_.h [!DEFAULT_PERSONALITY] (DEFAULT_PERSONALITY): New
macro.
[!SUPPORTED_PERSONALITIES] (SUPPORTED_PERSONALITIES): Likewise.
* linux/aarch64/arch_defs_.h (SUPPORTED_PERSONALITIES): New macro.
* linux/riscv/arch_defs_.h: Likewise.
* linux/s390x/arch_defs_.h: Likewise.
* linux/sparc64/arch_defs_.h: Likewise.
* linux/x32/arch_defs_.h: Likewise.
* linux/x86_64/arch_defs_.h: Likewise.
* linux/powerpc64/arch_defs_.h: New file.
* linux/tile/arch_defs_.h: Likewise.
* Makefile.am (EXTRA_DIST): Add them.
(strace_SOURCES): Remove supported_personalities.h.

Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
2018-01-21 01:46:04 +00:00
2880a927a6 Replace NEED_UID16_PARSERS with HAVE_ARCH_UID16_SYSCALLS
* linux/arch_defs_.h [!HAVE_ARCH_UID16_SYSCALLS]
(HAVE_ARCH_UID16_SYSCALLS): New macro.
* linux/aarch64/arch_defs_.h (HAVE_ARCH_UID16_SYSCALLS): New macro.
* linux/arm/arch_defs_.h: Likewise.
* linux/i386/arch_defs_.h: Likewise.
* linux/ia64/arch_defs_.h: Likewise.
* linux/m68k/arch_defs_.h: Likewise.
* linux/s390/arch_defs_.h: Likewise.
* linux/s390x/arch_defs_.h: Likewise.
* linux/sh/arch_defs_.h: Likewise.
* linux/sparc/arch_defs_.h: Likewise.
* linux/sparc64/arch_defs_.h: Likewise.
* linux/syscall.h: Likewise.
* linux/x32/arch_defs_.h: Likewise.
* linux/x86_64/arch_defs_.h: Likewise.
* linux/bfin/arch_defs_.h: New file.
* linux/microblaze/arch_defs_.h: Likewise.
* linux/riscv/arch_defs_.h: Likewise.
* linux/sh64/arch_defs_.h: Likewise.
* Makefile.am (EXTRA_DIST): Add them.
* defs.h (NEED_UID16_PARSERS): Remove.
* linux/syscall.h: Check for HAVE_ARCH_UID16_SYSCALLS instead of
NEED_UID16_PARSERS.
* uid.c: Likewise.
2018-01-21 01:46:04 +00:00
Lazar Trsic
72aba2be32 Move is_negated_errno() to new header negated_errno.h
Move is_negated_errno() to a separate new header file negated_errno.h
and include it just for architectures which require it.

is_negated_errno() is not used on those architectures
that have a dedicated register to signal a syscall error.

The issue was raised when compiling with clang, which is more
strict regarding semantics of unused static inline functions
defined in C files and will issue a -Wunused-function warrning
if they are not used anywhere.

* syscall.c (is_negated_errno): Move to ...
* negated_errno.h: ... new file.
* Makefile.am (strace_SOURCES): Add it.
* linux/aarch64/get_error.c: Include it.
* linux/arc/get_error.c: Likewise.
* linux/arm/get_error.c: Likewise.
* linux/avr32/get_error.c: Likewise.
* linux/bfin/get_error.c: Likewise.
* linux/crisv10/get_error.c: Likewise.
* linux/hppa/get_error.c: Likewise.
* linux/i386/get_error.c: Likewise.
* linux/ia64/get_error.c: Likewise.
* linux/m68k/get_error.c: Likewise.
* linux/metag/get_error.c: Likewise.
* linux/microblaze/get_error.c: Likewise.
* linux/or1k/get_error.c: Likewise.
* linux/riscv/get_error.c: Likewise.
* linux/s390/get_error.c: Likewise.
* linux/sh/get_error.c: Likewise.
* linux/sh64/get_error.c: Likewise.
* linux/tile/get_error.c: Likewise.
* linux/x86_64/get_error.c: Likewise.
* linux/xtensa/get_error.c: Likewise.
2017-07-14 23:55:23 +00:00
c57cf9acf5 Introduce get_rt_sigframe_addr function
Add get_rt_sigframe_addr function for all supported architectures.
It is going to be used in a parser of rt_sigreturn syscall.

* defs.h (get_rt_sigframe_addr): New function prototype.
* rt_sigframe.c: New file.
* Makefile.am (strace_SOURCES): Add it.
* linux/aarch64/arch_rt_sigframe.c: New file.
* linux/alpha/arch_rt_sigframe.c: Likewise.
* linux/arc/arch_rt_sigframe.c: Likewise.
* linux/arm/arch_rt_sigframe.c: Likewise.
* linux/avr32/arch_rt_sigframe.c: Likewise.
* linux/bfin/arch_rt_sigframe.c: Likewise.
* linux/crisv10/arch_rt_sigframe.c: Likewise.
* linux/crisv32/arch_rt_sigframe.c: Likewise.
* linux/hppa/arch_rt_sigframe.c: Likewise.
* linux/i386/arch_rt_sigframe.c: Likewise.
* linux/ia64/arch_rt_sigframe.c: Likewise.
* linux/m68k/arch_rt_sigframe.c: Likewise.
* linux/metag/arch_rt_sigframe.c: Likewise.
* linux/microblaze/arch_rt_sigframe.c: Likewise.
* linux/mips/arch_rt_sigframe.c: Likewise.
* linux/nios2/arch_rt_sigframe.c: Likewise.
* linux/or1k/arch_rt_sigframe.c: Likewise.
* linux/powerpc/arch_rt_sigframe.c: Likewise.
* linux/powerpc64/arch_rt_sigframe.c: Likewise.
* linux/riscv/arch_rt_sigframe.c: Likewise.
* linux/s390/arch_rt_sigframe.c: Likewise.
* linux/s390x/arch_rt_sigframe.c: Likewise.
* linux/sh/arch_rt_sigframe.c: Likewise.
* linux/sh64/arch_rt_sigframe.c: Likewise.
* linux/sparc/arch_rt_sigframe.c: Likewise.
* linux/sparc64/arch_rt_sigframe.c: Likewise.
* linux/tile/arch_rt_sigframe.c: Likewise.
* linux/x32/arch_rt_sigframe.c: Likewise.
* linux/x86_64/arch_rt_sigframe.c: Likewise.
* linux/xtensa/arch_rt_sigframe.c: Likewise.
* Makefile.am (EXTRA_DIST): Add them.
2017-03-13 15:22:50 +00:00
8ffa3fd109 riscv: export riscv_sp_ptr
Export SP register for later use by get_rt_sigframe_addr.

* linux/riscv/arch_regs.h: New file.
* Makefile.am (EXTRA_DIST): Add it.
* linux/riscv/arch_regs.c (riscv_sp_ptr): New variable.
2017-03-10 20:06:58 +00:00
Elvira Khabirova
41d647ce67 Implement success injection
This extends fault injection syntax with :retval= option.
When :retval=VALUE is specified, the syscall number is replaced by -1
and a bogus success VALUE is returned to the callee.

* defs.h (fault_opts): Remove err field, add rval field.
(MAX_ERRNO_VALUE, FAULT_OPTS_RVAL_DEFAULT, FAULT_OPTS_RVAL_DISABLE):
New macros.
* qualify.c (parse_fault_token): Handle retval= token.
(qualify_fault): Update fault_opts initialization after the move
from struct fault_opts.err to struct fault_opts.rval.
* syscall.c (arch_set_success): New prototype.
(inject_syscall_fault_entering): Check opts->rval instead of opts->err.
(update_syscall_fault_exiting): Implement retval injection.
* strace.1: Update the section on fault injection.
* NEWS: Mention retval= option.
* linux/aarch64/set_error.c (arch_set_success): New function.
* linux/alpha/set_error.c: Likewise.
* linux/arc/set_error.c: Likewise.
* linux/arm/set_error.c: Likewise.
* linux/avr32/set_error.c: Likewise.
* linux/bfin/set_error.c: Likewise.
* linux/crisv10/set_error.c: Likewise.
* linux/hppa/set_error.c: Likewise.
* linux/i386/set_error.c: Likewise.
* linux/ia64/set_error.c: Likewise.
* linux/m68k/set_error.c: Likewise.
* linux/metag/set_error.c: Likewise.
* linux/microblaze/set_error.c: Likewise.
* linux/mips/set_error.c: Likewise.
* linux/nios2/set_error.c: Likewise.
* linux/or1k/set_error.c: Likewise.
* linux/powerpc/set_error.c: Likewise.
* linux/riscv/set_error.c: Likewise.
* linux/s390/set_error.c: Likewise.
* linux/sh/set_error.c: Likewise.
* linux/sh64/set_error.c: Likewise.
* linux/sparc/set_error.c: Likewise.
* linux/sparc64/set_error.c: Likewise.
* linux/tile/set_error.c: Likewise.
* linux/x86_64/set_error.c: Likewise.
* linux/xtensa/set_error.c: Likewise.

Closes: https://github.com/strace/strace/issues/3
2017-01-28 09:47:00 +00:00
7fa3d78319 Automatically replace kernel_(scno|ureg)_t with kernel_ulong_t
Remove temporary types created for transition from long
to kernel_ulong_t.

Automatically replace kernel_scno_t and kernel_ureg_t with
kernel_ulong_t using
$ git grep -El 'kernel_(scno|ureg)_t' |
  xargs sed -ri 's/kernel_(scno|ureg)_t/kernel_ulong_t/g'

* kernel_types.h (kernel_scno_t, kernel_ureg_t): Remove.
All users updated.
2016-12-26 10:43:34 +00:00
0547dc1ad5 Change scno type from long to unsigned long
Use an unsigned type for syscall numbers as they are not intended
for signed arithmetics.  Introduce kernel_scno_t as a typedef
to unsigned long, that could be changed later to kernel_ulong_t.

* kernel_types.h (kernel_scno_t): New type, typedef to unsigned long.
* defs.h (struct tcb): Change type of scno field from long
to kernel_scno_t.
(syscall_name): Change argument type from long to kernel_scno_t.
(scno_in_range, scno_is_valid): Change argument type from unsigned long
to kernel_scno_t.
* linux/aarch64/set_scno.c (arch_set_scno): Change scno argument type
from long to kernel_scno_t.
* linux/alpha/set_scno.c (arch_set_scno): Likewise.
* linux/arc/set_scno.c (arch_set_scno): Likewise.
* linux/arm/set_scno.c (arch_set_scno): Likewise.
* linux/avr32/set_scno.c (arch_set_scno): Likewise.
* linux/bfin/set_scno.c (arch_set_scno): Likewise.
* linux/crisv10/set_scno.c (arch_set_scno): Likewise.
* linux/hppa/set_scno.c (arch_set_scno): Likewise.
* linux/i386/set_scno.c (arch_set_scno): Likewise.
* linux/ia64/set_scno.c (arch_set_scno): Likewise.
* linux/m68k/set_scno.c (arch_set_scno): Likewise.
* linux/metag/set_scno.c (arch_set_scno): Likewise.
* linux/microblaze/set_scno.c (arch_set_scno): Likewise.
* linux/mips/set_scno.c (arch_set_scno): Likewise.
* linux/nios2/set_scno.c (arch_set_scno): Likewise.
* linux/or1k/set_scno.c (arch_set_scno): Likewise.
* linux/powerpc/set_scno.c (arch_set_scno): Likewise.
* linux/riscv/set_scno.c (arch_set_scno): Likewise.
* linux/s390/set_scno.c (arch_set_scno): Likewise.
* linux/sh/set_scno.c (arch_set_scno): Likewise.
* linux/sh64/set_scno.c (arch_set_scno): Likewise.
* linux/sparc/set_scno.c (arch_set_scno): Likewise.
* linux/tile/set_scno.c (arch_set_scno): Likewise.
* linux/x86_64/set_scno.c (arch_set_scno): Likewise.
* linux/xtensa/set_scno.c (arch_set_scno): Likewise.
* linux/aarch64/get_scno.c (arch_get_scno): Change scno variable type
from long to kernel_scno_t.
* linux/alpha/get_scno.c (arch_get_scno): Likewise.
* linux/arm/get_scno.c (arch_get_scno): Likewise.
* linux/sh/get_scno.c (arch_get_scno): Likewise.
* linux/x86_64/get_scno.c (arch_get_scno): Likewise.
* syscall.c (arch_set_scno): Likewise.
(shuffle_scno): Change return type from long to kernel_scno_t.
(syscall_name): Change argument type from long to kernel_scno_t.
2016-12-18 22:57:57 +00:00
f1d0729f17 Implement arch specific methods of changing syscall number and error code
This introduces arch_set_error and arch_set_scno functions for each
supported architecture, needed to implement syscall fault injection.

* linux/aarch64/set_error.c: New file.
* linux/aarch64/set_scno.c: Likewise.
* linux/alpha/set_error.c: Likewise.
* linux/alpha/set_scno.c: Likewise.
* linux/arc/set_error.c: Likewise.
* linux/arc/set_scno.c: Likewise.
* linux/arm/set_error.c: Likewise.
* linux/arm/set_scno.c: Likewise.
* linux/avr32/set_error.c: Likewise.
* linux/avr32/set_scno.c: Likewise.
* linux/bfin/set_error.c: Likewise.
* linux/bfin/set_scno.c: Likewise.
* linux/crisv10/set_error.c: Likewise.
* linux/crisv10/set_scno.c: Likewise.
* linux/crisv32/set_error.c: Likewise.
* linux/crisv32/set_scno.c: Likewise.
* linux/hppa/set_error.c: Likewise.
* linux/hppa/set_scno.c: Likewise.
* linux/i386/set_error.c: Likewise.
* linux/i386/set_scno.c: Likewise.
* linux/ia64/set_error.c: Likewise.
* linux/ia64/set_scno.c: Likewise.
* linux/m68k/set_error.c: Likewise.
* linux/m68k/set_scno.c: Likewise.
* linux/metag/set_error.c: Likewise.
* linux/metag/set_scno.c: Likewise.
* linux/microblaze/set_error.c: Likewise.
* linux/microblaze/set_scno.c: Likewise.
* linux/mips/set_error.c: Likewise.
* linux/mips/set_scno.c: Likewise.
* linux/nios2/set_error.c: Likewise.
* linux/nios2/set_scno.c: Likewise.
* linux/or1k/set_error.c: Likewise.
* linux/or1k/set_scno.c: Likewise.
* linux/powerpc/set_error.c: Likewise.
* linux/powerpc/set_scno.c: Likewise.
* linux/powerpc64/set_error.c: Likewise.
* linux/powerpc64/set_scno.c: Likewise.
* linux/riscv/set_error.c: Likewise.
* linux/riscv/set_scno.c: Likewise.
* linux/s390/set_error.c: Likewise.
* linux/s390/set_scno.c: Likewise.
* linux/s390x/set_error.c: Likewise.
* linux/s390x/set_scno.c: Likewise.
* linux/sh/set_error.c: Likewise.
* linux/sh/set_scno.c: Likewise.
* linux/sh64/set_error.c: Likewise.
* linux/sh64/set_scno.c: Likewise.
* linux/sparc/set_error.c: Likewise.
* linux/sparc/set_scno.c: Likewise.
* linux/sparc64/set_error.c: Likewise.
* linux/sparc64/set_scno.c: Likewise.
* linux/tile/set_error.c: Likewise.
* linux/tile/set_scno.c: Likewise.
* linux/x32/set_error.c: Likewise.
* linux/x32/set_scno.c: Likewise.
* linux/x86_64/set_error.c: Likewise.
* linux/x86_64/set_scno.c: Likewise.
* linux/xtensa/set_error.c: Likewise.
* linux/xtensa/set_scno.c: Likewise.
* Makefile.am (EXTRA_DIST): Add them.
2016-11-16 02:33:13 +00:00
a7c4ee41ff Mpersify parsers of struct stat and struct stat64
On many architectures that support multiple personalities,
struct stat differ between personalities.  While old code could handle
these differences, there are some architectures, e.g. sparc64, that also
have different struct stat64.  Rewrite parsers using mpers functionality
to fix these issues.

* fetch_struct_stat.c: New file.
* fetch_struct_stat64.c: Likewise.
* print_struct_stat.c: Likewise.
* oldstat.c: Likewise.
* stat.c: Likewise.
* stat.h: Likewise.
* stat64.c: Likewise.
* file.c: Remove.
* printstat.h: Likewise.
* linux/aarch64/stat32.h: Likewise.
* linux/powerpc64/stat32.h: Likewise.
* linux/riscv/stat32.h: Likewise.
* linux/sparc64/stat32.h: Likewise.
* linux/tile/stat32.h: Likewise.
* linux/x32/stat32.h: Likewise.
* linux/x86_64/stat32.h: Likewise.
* Makefile.am (strace_SOURCES): Add fetch_struct_stat.c,
fetch_struct_stat64.c, print_struct_stat.c, oldstat.c, stat.c, stat.h,
and stat64.c.  Remove file.c, printstat.h, linux/aarch64/stat32.h,
linux/powerpc64/stat32.h, linux/riscv/stat32.h, linux/sparc64/stat32.h,
linux/tile/stat32.h, linux/x32/stat32.h, and linux/x86_64/stat32.h.
* configure.ac (AC_CHECK_MEMBERS): Add struct stat64.st_mtime_nsec.
* defs.h (struct strace_stat): New declaration.
(print_struct_stat): New prototype.
* linux/dummy.h (sys_fstatat64): Remove.
2016-08-24 15:32:10 +00:00
Richard W.M. Jones
d8f673568b Add RISC-V architecture support
The original port of strace was done by Palmer Dabbelt
(eecs.berkeley.edu), based on strace 4.9.

* configure.ac: Define RISCV for riscv*.
* clone.c [RISCV]: Define ARG_* macros as for OR1K.
* defs.h [RISCV] (SUPPORTED_PERSONALITIES): Define to 2.
[RISCV] (NEED_UID16_PARSERS): Define to 1.
* linux/riscv/arch_regs.c: New file.
* linux/riscv/errnoent1.h: Likewise.
* linux/riscv/get_error.c: Likewise.
* linux/riscv/get_scno.c: Likewise.
* linux/riscv/get_syscall_args.c: Likewise.
* linux/riscv/ioctls_arch0.h: Likewise.
* linux/riscv/ioctls_arch1.h: Likewise.
* linux/riscv/ioctls_inc0.h: Likewise.
* linux/riscv/ioctls_inc1.h: Likewise.
* linux/riscv/signalent1.h: Likewise.
* linux/riscv/stat32.h: Likewise.
* linux/riscv/syscallent.h: Likewise.
* linux/riscv/syscallent1.h: Likewise.
* Makefile.am (EXTRA_DIST): Add them.

Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
2016-08-21 22:03:05 +00:00