diff mbox series

[v3,8/9] selftests/arm: Add ptrace_64 test

Message ID 20240625122408.1439097-9-dev.jain@arm.com (mailing list archive)
State New
Headers show
Series A new selftests/ directory for arm compatibility testing | expand

Commit Message

Dev Jain June 25, 2024, 12:24 p.m. UTC
For a 64-bit parent debugging a 32-bit child, add tests for reading the
TLS registers, and mangling with the mode bits in CPSR.

Signed-off-by: Dev Jain <dev.jain@arm.com>
---
 tools/testing/selftests/arm/abi/ptrace_64.c   | 91 +++++++++++++++++++
 .../selftests/arm/abi/trivial_32bit_program.c | 14 +++
 2 files changed, 105 insertions(+)
 create mode 100644 tools/testing/selftests/arm/abi/ptrace_64.c
 create mode 100644 tools/testing/selftests/arm/abi/trivial_32bit_program.c

Comments

Mark Brown June 25, 2024, 6:18 p.m. UTC | #1
On Tue, Jun 25, 2024 at 05:54:07PM +0530, Dev Jain wrote:

> +static int do_child(void)
> +{
> +	if (ptrace(PTRACE_TRACEME, -1, NULL, NULL))
> +		ksft_exit_fail_perror("PTRACE_TRACEME");
> +
> +	/* SIGTRAP makes the child stop after exec; do_parent() resumes it */
> +	execv("trivial_32bit_program", NULL);
> +	return EXIT_SUCCESS;
> +}

We should check that the execv() worked, one thing that can go wrong is
partially installing the tests or trying to run the tests in a different
directory to the one where everything is installed.  I'd be inclined to
specify the path as ./ too to avoid surprises.
diff mbox series

Patch

diff --git a/tools/testing/selftests/arm/abi/ptrace_64.c b/tools/testing/selftests/arm/abi/ptrace_64.c
new file mode 100644
index 000000000000..97398cf59052
--- /dev/null
+++ b/tools/testing/selftests/arm/abi/ptrace_64.c
@@ -0,0 +1,91 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 ARM Limited.
+ *
+ * Inspired from selftests/arm64/abi/ptrace.c
+ *
+ * Author: Dev Jain <dev.jain@arm.com>
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <asm/sigcontext.h>
+#include <asm/ptrace.h>
+
+#include "ptrace.h"
+#include "../../kselftest.h"
+
+#define EXPECTED_TESTS	12
+#define NUM_TLS_REGS	2
+
+static void test_tpidr(pid_t child)
+{
+	unsigned int read_val[NUM_TLS_REGS];
+	struct iovec read_iov;
+	int ret;
+
+	memset(read_val, 0, sizeof(read_val));
+
+	read_iov.iov_base = read_val;
+
+	/* Should be able to read a single TLS register... */
+	read_iov.iov_len = 2 * sizeof(unsigned int);
+	ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_TLS, &read_iov);
+	ksft_test_result(ret == 0, "read_tls\n");
+
+	ksft_test_result(read_val[0], "read_tls_1\n");
+	ksft_test_result(!read_val[1], "cannot read_tls_2\n");
+}
+
+static void run_tests(pid_t child)
+{
+	test_tpidr(child);
+	test_user_regs(child);
+	test_hw_debug(child, NT_ARM_HW_WATCH, "NT_ARM_HW_WATCH");
+	test_hw_debug(child, NT_ARM_HW_BREAK, "NT_ARM_HW_BREAK");
+}
+
+static int do_child(void)
+{
+	if (ptrace(PTRACE_TRACEME, -1, NULL, NULL))
+		ksft_exit_fail_perror("PTRACE_TRACEME");
+
+	/* SIGTRAP makes the child stop after exec; do_parent() resumes it */
+	execv("trivial_32bit_program", NULL);
+	return EXIT_SUCCESS;
+}
+
+int main(void)
+{
+	int ret = EXIT_SUCCESS;
+	pid_t child;
+
+	srandom(getpid());
+
+	ksft_print_header();
+
+	ksft_set_plan(EXPECTED_TESTS);
+
+	child = fork();
+	if (!child)
+		return do_child();
+
+	if (do_parent(child))
+		ret = EXIT_FAILURE;
+
+	ksft_print_cnts();
+
+	return ret;
+}
diff --git a/tools/testing/selftests/arm/abi/trivial_32bit_program.c b/tools/testing/selftests/arm/abi/trivial_32bit_program.c
new file mode 100644
index 000000000000..c5ad7abb23ed
--- /dev/null
+++ b/tools/testing/selftests/arm/abi/trivial_32bit_program.c
@@ -0,0 +1,14 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 ARM Limited.
+ */
+
+#include <stdio.h>
+#include <signal.h>
+
+int main(void)
+{
+	raise(SIGSTOP);
+	raise(SIGSTOP);
+	return 0;
+}