summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@strace.io>2022-01-09 20:00:00 +0000
committerWANG Xuerui <git@xen0n.name>2022-01-13 19:43:37 +0800
commit2bf68c3b08ba82f4f41035e58149c06d2421cbd6 (patch)
treedd81da9cd11ae3f6c7f1ad03e6a2e6b786fff1e0
parent665f7bb525b2a800257af5d3d83b796e6cd9ddbe (diff)
downloadstrace-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.am4
-rw-r--r--src/linux/loongarch64/arch_fpregset.c36
-rw-r--r--src/linux/loongarch64/arch_fpregset.h15
-rw-r--r--src/linux/loongarch64/arch_prstatus_regset.c45
-rw-r--r--src/linux/loongarch64/arch_prstatus_regset.h15
-rw-r--r--tests/ptrace.c61
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, &regs)) {
+ 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, &regs)) {
+ 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__