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
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; +}