diff options
author | Dmitry V. Levin <ldv@strace.io> | 2022-01-09 20:00:00 +0000 |
---|---|---|
committer | WANG Xuerui <git@xen0n.name> | 2022-01-13 19:43:37 +0800 |
commit | 2bf68c3b08ba82f4f41035e58149c06d2421cbd6 (patch) | |
tree | dd81da9cd11ae3f6c7f1ad03e6a2e6b786fff1e0 | |
parent | 665f7bb525b2a800257af5d3d83b796e6cd9ddbe (diff) | |
download | strace-2bf68c3b08ba82f4f41035e58149c06d2421cbd6.tar.gz |
loongarch64: implement NT_PRSTATUS and NT_FPREGSET regsets decoding
* src/linux/loongarch64/arch_fpregset.c: New file.
* src/linux/loongarch64/arch_fpregset.h: Likewise.
* src/linux/loongarch64/arch_prstatus_regset.c: Likewise.
* src/linux/loongarch64/arch_prstatus_regset.h: Likewise.
* src/Makefile.am (EXTRA_DIST): Add them.
* tests/ptrace.c [__loongarch__] (TRACEE_REGS_STRUCT): Define.
(print_prstatus_regset, print_fpregset) [__loongarch__]: Update
expected output.
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/linux/loongarch64/arch_fpregset.c | 36 | ||||
-rw-r--r-- | src/linux/loongarch64/arch_fpregset.h | 15 | ||||
-rw-r--r-- | src/linux/loongarch64/arch_prstatus_regset.c | 45 | ||||
-rw-r--r-- | src/linux/loongarch64/arch_prstatus_regset.h | 15 | ||||
-rw-r--r-- | tests/ptrace.c | 61 |
6 files changed, 175 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 4344a1ce2..dc9fd93e7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -647,6 +647,10 @@ EXTRA_DIST = \ linux/ia64/syscallent_base_nr.h \ linux/ia64/userent.h \ linux/loongarch64/arch_defs_.h \ + linux/loongarch64/arch_fpregset.c \ + linux/loongarch64/arch_fpregset.h \ + linux/loongarch64/arch_prstatus_regset.c \ + linux/loongarch64/arch_prstatus_regset.h \ linux/loongarch64/arch_regs.c \ linux/loongarch64/get_error.c \ linux/loongarch64/get_scno.c \ diff --git a/src/linux/loongarch64/arch_fpregset.c b/src/linux/loongarch64/arch_fpregset.c new file mode 100644 index 000000000..0a5ed0a18 --- /dev/null +++ b/src/linux/loongarch64/arch_fpregset.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +static void +arch_decode_fpregset(struct tcb *const tcp, + const kernel_ulong_t addr, + const kernel_ulong_t size) +{ + struct_fpregset regs; + const size_t fetch_size = MIN(sizeof(regs), size); + + if (!size || size & 7) { + printaddr(addr); + } else if (!umoven_or_printaddr(tcp, addr, fetch_size, ®s)) { + tprint_struct_begin(); + PRINT_FIELD_ARRAY_UPTO(regs, fpr, fetch_size / 8, tcp, + print_xint_array_member); + if (fetch_size > offsetof(struct_fpregset, fcc)) { + tprint_struct_next(); + PRINT_FIELD_X(regs, fcc); + } + if (fetch_size > offsetof(struct_fpregset, fcsr)) { + tprint_struct_next(); + PRINT_FIELD_X(regs, fcsr); + } + if (size > sizeof(regs)) { + tprint_struct_next(); + tprint_more_data_follows(); + } + tprint_struct_end(); + } +} diff --git a/src/linux/loongarch64/arch_fpregset.h b/src/linux/loongarch64/arch_fpregset.h new file mode 100644 index 000000000..998b40f81 --- /dev/null +++ b/src/linux/loongarch64/arch_fpregset.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021-2022 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef STRACE_ARCH_FPREGSET_H +# define STRACE_ARCH_FPREGSET_H + +typedef struct user_fp_state struct_fpregset; + +# define HAVE_ARCH_FPREGSET 1 + +#endif /* !STRACE_ARCH_FPREGSET_H */ diff --git a/src/linux/loongarch64/arch_prstatus_regset.c b/src/linux/loongarch64/arch_prstatus_regset.c new file mode 100644 index 000000000..eb83c5993 --- /dev/null +++ b/src/linux/loongarch64/arch_prstatus_regset.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021-2022 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +static void +arch_decode_prstatus_regset(struct tcb *const tcp, + const kernel_ulong_t addr, + const kernel_ulong_t size) +{ + struct_prstatus_regset regs; + const size_t fetch_size = MIN(sizeof(regs), size); + + if (!size || size & 7) { + printaddr(addr); + } else if (!umoven_or_printaddr(tcp, addr, fetch_size, ®s)) { + tprint_struct_begin(); + PRINT_FIELD_ARRAY_UPTO(regs, regs, + fetch_size / 8, tcp, + print_xint_array_member); + if (fetch_size > offsetof(struct_prstatus_regset, csr_era)) { + tprint_struct_next(); + PRINT_FIELD_X(regs, csr_era); + } + if (fetch_size > offsetof(struct_prstatus_regset, csr_badv)) { + tprint_struct_next(); + PRINT_FIELD_X(regs, csr_badv); + } + const size_t offset_of_reserved = + offsetof(struct_prstatus_regset, reserved); + if (fetch_size > offset_of_reserved) { + tprint_struct_next(); + PRINT_FIELD_ARRAY_UPTO(regs, reserved, + (fetch_size - offset_of_reserved) / 8, + tcp, print_xint_array_member); + } + if (size > sizeof(regs)) { + tprint_struct_next(); + tprint_more_data_follows(); + } + tprint_struct_end(); + } +} diff --git a/src/linux/loongarch64/arch_prstatus_regset.h b/src/linux/loongarch64/arch_prstatus_regset.h new file mode 100644 index 000000000..e7eb64b6c --- /dev/null +++ b/src/linux/loongarch64/arch_prstatus_regset.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021-2022 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef STRACE_ARCH_PRSTATUS_REGSET_H +# define STRACE_ARCH_PRSTATUS_REGSET_H + +typedef struct user_pt_regs struct_prstatus_regset; + +# define HAVE_ARCH_PRSTATUS_REGSET 1 + +#endif /* !STRACE_ARCH_PRSTATUS_REGSET_H */ diff --git a/tests/ptrace.c b/tests/ptrace.c index e53639c1b..cd3d59c32 100644 --- a/tests/ptrace.c +++ b/tests/ptrace.c @@ -205,7 +205,7 @@ test_peeksiginfo(int pid, const unsigned long bad_request) # define TRACEE_REGS_STRUCT struct pt_regs #elif defined __arm__ # define TRACEE_REGS_STRUCT struct pt_regs -#elif defined __arm64__ || defined __aarch64__ +#elif defined __arm64__ || defined __aarch64__ || defined __loongarch__ # define TRACEE_REGS_STRUCT struct user_pt_regs #elif defined __s390__ || defined __s390x__ # define TRACEE_REGS_STRUCT s390_regs @@ -843,11 +843,47 @@ print_prstatus_regset(const void *const rs, const size_t size) PRINT_FIELD_X(*regs, cp0_cause); } +# elif defined __loongarch__ + + if (size > offsetof(TRACEE_REGS_STRUCT, regs)) { + const size_t len = size - offsetof(TRACEE_REGS_STRUCT, regs); + fputs("regs=[", stdout); + for (unsigned int i = 0; i < ARRAY_SIZE(regs->regs); ++i) { + if (len > i * sizeof(regs->regs[i])) { + if (i) + fputs(", ", stdout); + PRINT_VAL_X(regs->regs[i]); + } + } + fputs("]", stdout); + } + if (size >= offsetofend(TRACEE_REGS_STRUCT, csr_era)) { + fputs(", ", stdout); + PRINT_FIELD_X(*regs, csr_era); + } + if (size >= offsetofend(TRACEE_REGS_STRUCT, csr_badv)) { + fputs(", ", stdout); + PRINT_FIELD_X(*regs, csr_badv); + } + if (size > offsetof(TRACEE_REGS_STRUCT, reserved)) { + const size_t len = size - offsetof(TRACEE_REGS_STRUCT, reserved); + fputs(", reserved=[", stdout); + for (unsigned int i = 0; i < ARRAY_SIZE(regs->reserved); ++i) { + if (len > i * sizeof(regs->reserved[i])) { + if (i) + fputs(", ", stdout); + PRINT_VAL_X(regs->reserved[i]); + } + } + fputs("]", stdout); + } + # endif /* __aarch64__ || __arm64__ || __arm__ || __i386__ || + __loongarch__ || __mips__ || __powerpc64__ || __powerpc__ || @@ -1085,6 +1121,8 @@ typedef struct { uint64_t fpscr; } ppc_fpregs_struct; # define TRACEE_REGS_STRUCT ppc_fpregs_struct +#elif defined __loongarch__ +# define TRACEE_REGS_STRUCT struct user_fp_state #endif static void @@ -1228,8 +1266,29 @@ print_fpregset(const void *const rs, const size_t size) PRINT_FIELD_X(*regs, fpscr); } +# elif defined __loongarch__ + + fputs("fpr=[", stdout); + for (unsigned int i = 0; i < ARRAY_SIZE(regs->fpr); ++i) { + if (size > i * sizeof(regs->fpr[i])) { + if (i) + fputs(", ", stdout); + PRINT_VAL_X(regs->fpr[i]); + } + } + fputs("]", stdout); + if (size >= offsetofend(TRACEE_REGS_STRUCT, fcc)) { + fputs(", ", stdout); + PRINT_FIELD_X(*regs, fcc); + } + if (size >= offsetofend(TRACEE_REGS_STRUCT, fcsr)) { + fputs(", ", stdout); + PRINT_FIELD_X(*regs, fcsr); + } + # endif /* __i386__ || + __loongarch__ || __powerpc64__ || __powerpc__ || __x86_64__ |