/* * Check decoding of ptrace syscall. * * Copyright (c) 2016 Dmitry V. Levin * Copyright (c) 2016-2021 The strace developers. * All rights reserved. * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "tests.h" #include "scno.h" #include "print_fields.h" #include #include "ptrace.h" #include #include #include #include #include #include #include #include #include #include #include "cur_audit_arch.h" #include "xlat.h" #define XLAT_MACROS_ONLY # include "xlat/elf_em.h" #undef XLAT_MACROS_ONLY #include "xlat/audit_arch.h" static const char *errstr; static long do_ptrace(const unsigned long request, const unsigned int pid, const unsigned long addr, const unsigned long data) { const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL; const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL; const kernel_ulong_t arg1 = request; const kernel_ulong_t arg2 = fill | pid; const kernel_ulong_t arg3 = addr; const kernel_ulong_t arg4 = data; long rc = syscall(__NR_ptrace, arg1, arg2, arg3, arg4, bad, bad); errstr = sprintrc(rc); return rc; } #if defined PTRACE_GETREGS || defined PTRACE_GETREGS64 || defined PTRACE_GETFPREGS static long do_ptrace_regs(const unsigned long request, const unsigned int pid, const unsigned long regs_addr) { const unsigned long bad = (unsigned long) 0xdeadbeefdeadbeefULL; # ifdef __sparc__ const unsigned long arg_addr = regs_addr; const unsigned long arg_data = bad; # else const unsigned long arg_addr = bad; const unsigned long arg_data = regs_addr; # endif return do_ptrace(request, pid, arg_addr, arg_data); } #endif /* PTRACE_GETREGS || PTRACE_GETREGS64 || PTRACE_GETFPREGS */ #ifndef PTRACE_PEEKSIGINFO_SHARED # define PTRACE_PEEKSIGINFO_SHARED (1 << 0) #endif static void test_peeksiginfo(int pid, const unsigned long bad_request) { do_ptrace(PTRACE_PEEKSIGINFO, pid, 0, bad_request); printf("ptrace(" XLAT_FMT ", %d, NULL, %#lx) = %s\n", XLAT_ARGS(PTRACE_PEEKSIGINFO), pid, bad_request, errstr); struct psi { unsigned long long off; unsigned int flags, nr; }; TAIL_ALLOC_OBJECT_CONST_PTR(struct psi, psi); psi->off = 0xdeadbeeffacefeedULL; psi->flags = 1; psi->nr = 42; do_ptrace(PTRACE_PEEKSIGINFO, pid, (uintptr_t) psi, bad_request); printf("ptrace(" XLAT_FMT ", %d, {off=%llu" ", flags=" XLAT_FMT ", nr=%u}, %#lx) = %s\n", XLAT_ARGS(PTRACE_PEEKSIGINFO), pid, psi->off, XLAT_ARGS(PTRACE_PEEKSIGINFO_SHARED), psi->nr, bad_request, errstr); pid = fork(); if (pid < 0) perror_msg_and_fail("fork"); if (!pid) { sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR1); sigaddset(&mask, SIGUSR2); sigaddset(&mask, SIGALRM); if (sigprocmask(SIG_BLOCK, &mask, NULL)) perror_msg_and_fail("sigprocmask"); raise(SIGUSR1); raise(SIGUSR2); raise(SIGALRM); if (do_ptrace(PTRACE_TRACEME, 0, 0, 0)) perror_msg_and_fail("child: PTRACE_TRACEME"); raise(SIGSTOP); _exit(0); } const unsigned int nsigs = 4; const uid_t uid = geteuid(); siginfo_t *sigs = tail_alloc(sizeof(*sigs) * nsigs); psi->off = 0; psi->flags = 0; psi->nr = nsigs; for (;;) { int status, tracee, saved; errno = 0; tracee = wait(&status); if (tracee <= 0) { if (errno == EINTR) continue; saved = errno; kill(pid, SIGKILL); errno = saved; perror_msg_and_fail("wait"); } if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) break; error_msg_and_fail("unexpected exit status %#x", WEXITSTATUS(status)); } if (WIFSIGNALED(status)) error_msg_and_fail("unexpected signal %u", WTERMSIG(status)); if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) { kill(pid, SIGKILL); error_msg_and_fail("unexpected wait status %#x", status); } long rc = do_ptrace(PTRACE_PEEKSIGINFO, pid, (uintptr_t) psi, (uintptr_t) sigs); if (rc < 0) { printf("ptrace(" XLAT_FMT ", %d, {off=%llu, flags=0" ", nr=%u}, %p) = %s\n", XLAT_ARGS(PTRACE_PEEKSIGINFO), pid, psi->off, psi->nr, sigs, errstr); } else { printf("ptrace(" XLAT_FMT ", %d" ", {off=%llu, flags=0, nr=%u}" ", [{si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT ", si_pid=%d, si_uid=%d}" ", {si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT ", si_pid=%d, si_uid=%d}" ", {si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT ", si_pid=%d, si_uid=%d}" "]) = %s\n", XLAT_ARGS(PTRACE_PEEKSIGINFO), pid, psi->off, psi->nr, XLAT_ARGS(SIGUSR1), XLAT_ARGS(SI_TKILL), pid, (int) uid, XLAT_ARGS(SIGUSR2), XLAT_ARGS(SI_TKILL), pid, (int) uid, XLAT_ARGS(SIGALRM), XLAT_ARGS(SI_TKILL), pid, (int) uid, errstr); } if (do_ptrace(PTRACE_CONT, pid, 0, 0)) { saved = errno; kill(pid, SIGKILL); errno = saved; perror_msg_and_fail("ptrace"); } printf("ptrace(" XLAT_FMT ", %d, NULL, 0) = 0\n", XLAT_ARGS(PTRACE_CONT), pid); } } #undef TRACEE_REGS_STRUCT #if defined __x86_64__ || defined __i386__ # define TRACEE_REGS_STRUCT struct user_regs_struct #elif defined __powerpc__ || defined __powerpc64__ # define TRACEE_REGS_STRUCT struct pt_regs #elif defined __arm__ # define TRACEE_REGS_STRUCT struct pt_regs #elif defined __arm64__ || defined __aarch64__ # define TRACEE_REGS_STRUCT struct user_pt_regs #elif defined __s390__ || defined __s390x__ # define TRACEE_REGS_STRUCT s390_regs #elif defined __sparc__ # ifdef __arch64__ typedef struct { unsigned long g[8]; unsigned long o[8]; unsigned long l[8]; unsigned long i[8]; unsigned long tstate; unsigned long tpc; unsigned long tnpc; unsigned long y; } sparc64_regs; # define TRACEE_REGS_STRUCT sparc64_regs # else /* sparc32 */ typedef struct { unsigned int g[8]; unsigned int o[8]; unsigned int l[8]; unsigned int i[8]; unsigned int psr; unsigned int pc; unsigned int npc; unsigned int y; unsigned int wim; unsigned int tbr; } sparc32_regs; # define TRACEE_REGS_STRUCT sparc32_regs # endif #elif defined __riscv # define TRACEE_REGS_STRUCT struct user_regs_struct #elif defined __mips__ typedef struct { # ifdef LINUX_MIPSO32 unsigned long unused[6]; # endif unsigned long regs[32]; unsigned long lo; unsigned long hi; unsigned long cp0_epc; unsigned long cp0_badvaddr; unsigned long cp0_status; unsigned long cp0_cause; } mips_regs; # define TRACEE_REGS_STRUCT mips_regs #endif static void print_prstatus_regset(const void *const rs, const size_t size) { if (!size || size % sizeof(kernel_ulong_t)) { printf("%p", rs); return; } #ifdef TRACEE_REGS_STRUCT const TRACEE_REGS_STRUCT *const regs = rs; fputs("{", stdout); # if defined __x86_64__ PRINT_FIELD_X(*regs, r15); if (size >= offsetofend(TRACEE_REGS_STRUCT, r14)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, r14); } if (size >= offsetofend(TRACEE_REGS_STRUCT, r13)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, r13); } if (size >= offsetofend(TRACEE_REGS_STRUCT, r12)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, r12); } if (size >= offsetofend(TRACEE_REGS_STRUCT, rbp)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, rbp); } if (size >= offsetofend(TRACEE_REGS_STRUCT, rbx)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, rbx); } if (size >= offsetofend(TRACEE_REGS_STRUCT, r11)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, r11); } if (size >= offsetofend(TRACEE_REGS_STRUCT, r10)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, r10); } if (size >= offsetofend(TRACEE_REGS_STRUCT, r9)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, r9); } if (size >= offsetofend(TRACEE_REGS_STRUCT, r8)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, r8); } if (size >= offsetofend(TRACEE_REGS_STRUCT, rax)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, rax); } if (size >= offsetofend(TRACEE_REGS_STRUCT, rcx)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, rcx); } if (size >= offsetofend(TRACEE_REGS_STRUCT, rdx)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, rdx); } if (size >= offsetofend(TRACEE_REGS_STRUCT, rsi)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, rsi); } if (size >= offsetofend(TRACEE_REGS_STRUCT, rdi)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, rdi); } if (size >= offsetofend(TRACEE_REGS_STRUCT, orig_rax)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, orig_rax); } if (size >= offsetofend(TRACEE_REGS_STRUCT, rip)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, rip); } if (size >= offsetofend(TRACEE_REGS_STRUCT, cs)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, cs); } if (size >= offsetofend(TRACEE_REGS_STRUCT, eflags)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, eflags); } if (size >= offsetofend(TRACEE_REGS_STRUCT, rsp)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, rsp); } if (size >= offsetofend(TRACEE_REGS_STRUCT, ss)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, ss); } if (size >= offsetofend(TRACEE_REGS_STRUCT, fs_base)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, fs_base); } if (size >= offsetofend(TRACEE_REGS_STRUCT, gs_base)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, gs_base); } if (size >= offsetofend(TRACEE_REGS_STRUCT, ds)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, ds); } if (size >= offsetofend(TRACEE_REGS_STRUCT, es)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, es); } if (size >= offsetofend(TRACEE_REGS_STRUCT, fs)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, fs); } if (size >= offsetofend(TRACEE_REGS_STRUCT, gs)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, gs); } # elif defined __i386__ PRINT_FIELD_X(*regs, ebx); if (size >= offsetofend(TRACEE_REGS_STRUCT, ecx)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, ecx); } if (size >= offsetofend(TRACEE_REGS_STRUCT, edx)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, edx); } if (size >= offsetofend(TRACEE_REGS_STRUCT, esi)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, esi); } if (size >= offsetofend(TRACEE_REGS_STRUCT, edi)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, edi); } if (size >= offsetofend(TRACEE_REGS_STRUCT, ebp)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, ebp); } if (size >= offsetofend(TRACEE_REGS_STRUCT, eax)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, eax); } if (size >= offsetofend(TRACEE_REGS_STRUCT, xds)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, xds); } if (size >= offsetofend(TRACEE_REGS_STRUCT, xes)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, xes); } if (size >= offsetofend(TRACEE_REGS_STRUCT, xfs)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, xfs); } if (size >= offsetofend(TRACEE_REGS_STRUCT, xgs)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, xgs); } if (size >= offsetofend(TRACEE_REGS_STRUCT, orig_eax)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, orig_eax); } if (size >= offsetofend(TRACEE_REGS_STRUCT, eip)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, eip); } if (size >= offsetofend(TRACEE_REGS_STRUCT, xcs)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, xcs); } if (size >= offsetofend(TRACEE_REGS_STRUCT, eflags)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, eflags); } if (size >= offsetofend(TRACEE_REGS_STRUCT, esp)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, esp); } if (size >= offsetofend(TRACEE_REGS_STRUCT, xss)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, xss); } # elif defined __powerpc__ || defined __powerpc64__ fputs("gpr=[", stdout); for (unsigned int i = 0; i < ARRAY_SIZE(regs->gpr); ++i) { if (size > i * sizeof(regs->gpr[i])) { if (i) fputs(", ", stdout); PRINT_VAL_X(regs->gpr[i]); } } fputs("]", stdout); if (size >= offsetofend(TRACEE_REGS_STRUCT, nip)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, nip); } if (size >= offsetofend(TRACEE_REGS_STRUCT, msr)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, msr); } if (size >= offsetofend(TRACEE_REGS_STRUCT, orig_gpr3)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, orig_gpr3); } if (size >= offsetofend(TRACEE_REGS_STRUCT, ctr)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, ctr); } if (size >= offsetofend(TRACEE_REGS_STRUCT, link)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, link); } if (size >= offsetofend(TRACEE_REGS_STRUCT, xer)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, xer); } if (size >= offsetofend(TRACEE_REGS_STRUCT, ccr)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, ccr); } # ifdef __powerpc64__ if (size >= offsetofend(TRACEE_REGS_STRUCT, softe)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, softe); } # else if (size >= offsetofend(TRACEE_REGS_STRUCT, mq)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, mq); } # endif if (size >= offsetofend(TRACEE_REGS_STRUCT, trap)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, trap); } if (size >= offsetofend(TRACEE_REGS_STRUCT, dar)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, dar); } if (size >= offsetofend(TRACEE_REGS_STRUCT, dsisr)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, dsisr); } if (size >= offsetofend(TRACEE_REGS_STRUCT, result)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, result); } # elif defined __arm__ fputs("uregs=[", stdout); for (unsigned int i = 0; i < ARRAY_SIZE(regs->uregs); ++i) { if (size > i * sizeof(regs->uregs[i])) { if (i) fputs(", ", stdout); PRINT_VAL_X(regs->uregs[i]); } } fputs("]", stdout); # elif defined __arm64__ || defined __aarch64__ fputs("regs=[", stdout); for (unsigned int i = 0; i < ARRAY_SIZE(regs->regs); ++i) { if (size > i * sizeof(regs->regs[i])) { if (i) fputs(", ", stdout); PRINT_VAL_X(regs->regs[i]); } } fputs("]", stdout); if (size >= offsetofend(TRACEE_REGS_STRUCT, sp)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, sp); } if (size >= offsetofend(TRACEE_REGS_STRUCT, pc)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, pc); } if (size >= offsetofend(TRACEE_REGS_STRUCT, pstate)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, pstate); } # elif defined __s390__ || defined __s390x__ fputs("psw={", stdout); PRINT_FIELD_X(regs->psw, mask); if (size >= sizeof(regs->psw)) { fputs(", ", stdout); PRINT_FIELD_X(regs->psw, addr); } fputs("}", stdout); if (size > offsetof(TRACEE_REGS_STRUCT, gprs)) { const size_t len = size - offsetof(TRACEE_REGS_STRUCT, gprs); fputs(", gprs=[", stdout); for (unsigned int i = 0; i < ARRAY_SIZE(regs->gprs); ++i) { if (len > i * sizeof(regs->gprs[i])) { if (i) fputs(", ", stdout); PRINT_VAL_X(regs->gprs[i]); } } fputs("]", stdout); } if (size > offsetof(TRACEE_REGS_STRUCT, acrs)) { const size_t len = size - offsetof(TRACEE_REGS_STRUCT, acrs); fputs(", acrs=[", stdout); for (unsigned int i = 0; i < ARRAY_SIZE(regs->acrs); ++i) { if (len > i * sizeof(regs->acrs[i])) { if (i) fputs(", ", stdout); PRINT_VAL_X(regs->acrs[i]); } } fputs("]", stdout); } if (size >= offsetofend(TRACEE_REGS_STRUCT, orig_gpr2)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, orig_gpr2); } # elif defined __sparc__ fputs("g=[", stdout); for (unsigned int j = 0; j < ARRAY_SIZE(regs->g); ++j) { if (size > j * sizeof(regs->g[j])) { if (j) fputs(", ", stdout); PRINT_VAL_X(regs->g[j]); } } fputs("]", stdout); if (size > offsetof(TRACEE_REGS_STRUCT, o)) { const size_t len = size - offsetof(TRACEE_REGS_STRUCT, o); fputs(", o=[", stdout); for (unsigned int j = 0; j < ARRAY_SIZE(regs->o); ++j) { if (len > j * sizeof(regs->o[j])) { if (j) fputs(", ", stdout); PRINT_VAL_X(regs->o[j]); } } fputs("]", stdout); } if (size > offsetof(TRACEE_REGS_STRUCT, l)) { const size_t len = size - offsetof(TRACEE_REGS_STRUCT, l); fputs(", l=[", stdout); for (unsigned int j = 0; j < ARRAY_SIZE(regs->l); ++j) { if (len > j * sizeof(regs->l[j])) { if (j) fputs(", ", stdout); PRINT_VAL_X(regs->l[j]); } } fputs("]", stdout); } if (size > offsetof(TRACEE_REGS_STRUCT, i)) { const size_t len = size - offsetof(TRACEE_REGS_STRUCT, i); fputs(", i=[", stdout); for (unsigned int j = 0; j < ARRAY_SIZE(regs->i); ++j) { if (len > j * sizeof(regs->i[j])) { if (j) fputs(", ", stdout); PRINT_VAL_X(regs->i[j]); } } fputs("]", stdout); } # ifdef __arch64__ if (size >= offsetofend(TRACEE_REGS_STRUCT, tstate)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, tstate); } if (size >= offsetofend(TRACEE_REGS_STRUCT, tpc)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, tpc); } if (size >= offsetofend(TRACEE_REGS_STRUCT, tnpc)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, tnpc); } if (size >= offsetofend(TRACEE_REGS_STRUCT, y)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, y); } # else /* sparc32 */ if (size >= offsetofend(TRACEE_REGS_STRUCT, psr)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, psr); } if (size >= offsetofend(TRACEE_REGS_STRUCT, pc)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, pc); } if (size >= offsetofend(TRACEE_REGS_STRUCT, npc)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, npc); } if (size >= offsetofend(TRACEE_REGS_STRUCT, y)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, y); } if (size >= offsetofend(TRACEE_REGS_STRUCT, wim)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, wim); } if (size >= offsetofend(TRACEE_REGS_STRUCT, tbr)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, tbr); } # endif # elif defined __riscv PRINT_FIELD_X(*regs, pc); if (size >= offsetofend(TRACEE_REGS_STRUCT, ra)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, ra); } if (size >= offsetofend(TRACEE_REGS_STRUCT, sp)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, sp); } if (size >= offsetofend(TRACEE_REGS_STRUCT, gp)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, gp); } if (size >= offsetofend(TRACEE_REGS_STRUCT, tp)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, tp); } if (size >= offsetofend(TRACEE_REGS_STRUCT, t0)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, t0); } if (size >= offsetofend(TRACEE_REGS_STRUCT, t1)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, t1); } if (size >= offsetofend(TRACEE_REGS_STRUCT, t2)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, t2); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s0)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s0); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s1)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s1); } if (size >= offsetofend(TRACEE_REGS_STRUCT, a0)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, a0); } if (size >= offsetofend(TRACEE_REGS_STRUCT, a1)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, a1); } if (size >= offsetofend(TRACEE_REGS_STRUCT, a2)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, a2); } if (size >= offsetofend(TRACEE_REGS_STRUCT, a3)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, a3); } if (size >= offsetofend(TRACEE_REGS_STRUCT, a4)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, a4); } if (size >= offsetofend(TRACEE_REGS_STRUCT, a5)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, a5); } if (size >= offsetofend(TRACEE_REGS_STRUCT, a6)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, a6); } if (size >= offsetofend(TRACEE_REGS_STRUCT, a7)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, a7); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s2)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s2); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s3)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s3); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s4)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s4); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s5)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s5); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s6)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s6); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s7)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s7); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s8)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s8); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s9)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s9); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s10)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s10); } if (size >= offsetofend(TRACEE_REGS_STRUCT, s11)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, s11); } if (size >= offsetofend(TRACEE_REGS_STRUCT, t3)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, t3); } if (size >= offsetofend(TRACEE_REGS_STRUCT, t4)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, t4); } if (size >= offsetofend(TRACEE_REGS_STRUCT, t5)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, t5); } if (size >= offsetofend(TRACEE_REGS_STRUCT, t6)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, t6); } # elif defined __mips__ 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, lo)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, lo); } if (size >= offsetofend(TRACEE_REGS_STRUCT, hi)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, hi); } if (size >= offsetofend(TRACEE_REGS_STRUCT, cp0_epc)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, cp0_epc); } if (size >= offsetofend(TRACEE_REGS_STRUCT, cp0_badvaddr)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, cp0_badvaddr); } if (size >= offsetofend(TRACEE_REGS_STRUCT, cp0_status)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, cp0_status); } if (size >= offsetofend(TRACEE_REGS_STRUCT, cp0_cause)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, cp0_cause); } # endif /* __aarch64__ || __arm64__ || __arm__ || __i386__ || __mips__ || __powerpc64__ || __powerpc__ || __riscv || __s390__ || __s390x__ || __sparc__ || __x86_64__ */ if (size > sizeof(*regs)) fputs(", ...", stdout); fputs("}", stdout); #else /* !TRACEE_REGS_STRUCT */ printf("%p", rs); #endif /* TRACEE_REGS_STRUCT */ } #ifdef PTRACE_GETREGS static void print_pt_regs(const void *const rs, const size_t size) { # if defined __mips__ const struct pt_regs *const regs = rs; if (size != sizeof(*regs)) error_msg_and_fail("expected size %zu, got size %zu", sizeof(*regs), size); fputs("{regs=[", stdout); for (unsigned int j = 0; j < ARRAY_SIZE(regs->regs); ++j) { if (j) fputs(", ", stdout); printf("%#llx", (unsigned long long) regs->regs[j]); } fputs("], ", stdout); PRINT_FIELD_X(*regs, lo); fputs(", ", stdout); PRINT_FIELD_X(*regs, hi); fputs(", ", stdout); PRINT_FIELD_X(*regs, cp0_epc); fputs(", ", stdout); PRINT_FIELD_X(*regs, cp0_badvaddr); fputs(", ", stdout); PRINT_FIELD_X(*regs, cp0_status); fputs(", ", stdout); PRINT_FIELD_X(*regs, cp0_cause); fputs("}", stdout); # elif defined __sparc__ # ifdef __arch64__ printf("%p", rs); # else const struct { unsigned int psr; unsigned int pc; unsigned int npc; unsigned int y; unsigned int u_regs[15]; } *const regs = rs; if (size != sizeof(*regs)) error_msg_and_fail("expected size %zu, got size %zu", sizeof(*regs), size); printf("{psr=%#x, pc=%#x, npc=%#x, y=%#x, u_regs=[", regs->psr, regs->pc, regs->npc, regs->y); for (unsigned int j = 0; j < ARRAY_SIZE(regs->u_regs); ++j) { if (j) fputs(", ", stdout); printf("%#x", regs->u_regs[j]); } fputs("]}", stdout); # endif /* !__arch64__ */ # elif defined TRACEE_REGS_STRUCT if (size != sizeof(TRACEE_REGS_STRUCT)) error_msg_and_fail("expected size %zu, got size %zu", sizeof(TRACEE_REGS_STRUCT), size); print_prstatus_regset(rs, size); # else /* !TRACEE_REGS_STRUCT */ printf("%p", rs); # endif } static void do_getregs_setregs(const int pid, void *const regbuf, const unsigned int regsize, unsigned int *const actual_size) { if (do_ptrace_regs(PTRACE_GETREGS, pid, (uintptr_t) regbuf)) { printf("ptrace(" XLAT_FMT ", %d, %p) = %s\n", XLAT_ARGS(PTRACE_GETREGS), pid, regbuf, errstr); return; /* skip PTRACE_SETREGS */ } else { printf("ptrace(" XLAT_FMT ", %d, ", XLAT_ARGS(PTRACE_GETREGS), pid); print_pt_regs(regbuf, regsize); printf(") = %s\n", errstr); if (*actual_size) return; /* skip PTRACE_SETREGS */ else *actual_size = regsize; } # if defined __sparc__ && !defined __arch64__ /* * On sparc32 PTRACE_SETREGS of size greater than 120 * has interesting side effects. */ if (regsize > 120) return; # endif /* __sparc__ && !__arch64__ */ do_ptrace_regs(PTRACE_SETREGS, pid, (uintptr_t) regbuf); printf("ptrace(" XLAT_FMT ", %d, ", XLAT_ARGS(PTRACE_SETREGS), pid); print_pt_regs(regbuf, regsize); printf(") = %s\n", errstr); } #endif /* PTRACE_GETREGS */ #ifdef PTRACE_GETREGS64 static void print_pt_regs64(const void *const rs, const size_t size) { # if defined __powerpc__ || defined __powerpc64__ # ifdef __powerpc64__ const struct pt_regs *const regs = rs; # else /* __powerpc__ */ const struct { unsigned long long gpr[32]; unsigned long long nip; unsigned long long msr; unsigned long long orig_gpr3; unsigned long long ctr; unsigned long long link; unsigned long long xer; unsigned long long ccr; unsigned long long softe; unsigned long long trap; unsigned long long dar; unsigned long long dsisr; unsigned long long result; } *const regs = rs; # endif /* __powerpc__ */ if (size != sizeof(*regs)) error_msg_and_fail("expected size %zu, got size %zu", sizeof(*regs), size); for (unsigned int j = 0; j < ARRAY_SIZE(regs->gpr); ++j) printf("%s%#llx", j ? ", " : "{gpr=[", (unsigned long long) regs->gpr[j]); printf("], nip=%#llx", (unsigned long long) regs->nip); printf(", msr=%#llx", (unsigned long long) regs->msr); printf(", orig_gpr3=%#llx", (unsigned long long) regs->orig_gpr3); printf(", ctr=%#llx", (unsigned long long) regs->ctr); printf(", link=%#llx", (unsigned long long) regs->link); printf(", xer=%#llx", (unsigned long long) regs->xer); printf(", ccr=%#llx", (unsigned long long) regs->ccr); printf(", softe=%#llx", (unsigned long long) regs->softe); printf(", trap=%#llx", (unsigned long long) regs->trap); printf(", dar=%#llx", (unsigned long long) regs->dar); printf(", dsisr=%#llx", (unsigned long long) regs->dsisr); printf(", result=%#llx}", (unsigned long long) regs->result); # elif defined __sparc__ && defined __arch64__ const struct { unsigned long u_regs[16]; unsigned long tstate; unsigned long tpc; unsigned long tnpc; } *const regs = rs; if (size != sizeof(*regs)) error_msg_and_fail("expected size %zu, got size %zu", sizeof(*regs), size); for (unsigned int j = 0; j < ARRAY_SIZE(regs->u_regs); ++j) printf("%s%#lx", j ? ", " : "{u_regs=[", regs->u_regs[j]); printf("], tstate=%#lx", regs->tstate); printf(", tpc=%#lx", regs->tpc); printf(", tnpc=%#lx}", regs->tnpc); # else /* !(__powerpc__ || __powerpc64__ || (__sparc__ && __arch64__)) */ printf("%p", rs); # endif } static void do_getregs64_setregs64(const int pid, void *const regbuf, const unsigned int regsize, unsigned int *const actual_size) { if (do_ptrace_regs(PTRACE_GETREGS64, pid, (uintptr_t) regbuf)) { printf("ptrace(" XLAT_FMT ", %d, %p) = %s\n", XLAT_ARGS(PTRACE_GETREGS64), pid, regbuf, errstr); return; /* skip PTRACE_SETREGS64 */ } else { printf("ptrace(" XLAT_FMT ", %d, ", XLAT_ARGS(PTRACE_GETREGS64), pid); print_pt_regs64(regbuf, regsize); printf(") = %s\n", errstr); if (*actual_size) return; /* skip PTRACE_SETREGS64 */ else *actual_size = regsize; } do_ptrace_regs(PTRACE_SETREGS64, pid, (uintptr_t) regbuf); printf("ptrace(" XLAT_FMT ", %d, ", XLAT_ARGS(PTRACE_SETREGS64), pid); print_pt_regs64(regbuf, regsize); printf(") = %s\n", errstr); } #endif /* PTRACE_GETREGS64 */ #if defined __powerpc__ || defined __powerpc64__ # define FPREGSET_SLOT_SIZE sizeof(uint64_t) #else # define FPREGSET_SLOT_SIZE sizeof(kernel_ulong_t) #endif #undef TRACEE_REGS_STRUCT #if defined __x86_64__ || defined __i386__ # define TRACEE_REGS_STRUCT struct user_fpregs_struct #elif defined __powerpc__ || defined __powerpc64__ typedef struct { uint64_t fpr[32]; uint64_t fpscr; } ppc_fpregs_struct; # define TRACEE_REGS_STRUCT ppc_fpregs_struct #endif static void print_fpregset(const void *const rs, const size_t size) { if (!size || size % FPREGSET_SLOT_SIZE) { printf("%p", rs); return; } #ifdef TRACEE_REGS_STRUCT const TRACEE_REGS_STRUCT *const regs = rs; fputs("{", stdout); # if defined __i386__ PRINT_FIELD_X(*regs, cwd); if (size >= offsetofend(TRACEE_REGS_STRUCT, swd)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, swd); } if (size >= offsetofend(TRACEE_REGS_STRUCT, twd)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, twd); } if (size >= offsetofend(TRACEE_REGS_STRUCT, fip)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, fip); } if (size >= offsetofend(TRACEE_REGS_STRUCT, fcs)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, fcs); } if (size >= offsetofend(TRACEE_REGS_STRUCT, foo)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, foo); } if (size >= offsetofend(TRACEE_REGS_STRUCT, fos)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, fos); } if (size > offsetof(TRACEE_REGS_STRUCT, st_space)) { const size_t len = size - offsetof(TRACEE_REGS_STRUCT, st_space); fputs(", st_space=[", stdout); for (unsigned int i = 0; i < ARRAY_SIZE(regs->st_space); ++i) { if (len > i * sizeof(regs->st_space[i])) { if (i) fputs(", ", stdout); PRINT_VAL_X(regs->st_space[i]); } } fputs("]", stdout); } # elif defined __x86_64__ PRINT_FIELD_X(*regs, cwd); if (size >= offsetofend(TRACEE_REGS_STRUCT, swd)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, swd); } if (size >= offsetofend(TRACEE_REGS_STRUCT, ftw)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, ftw); } if (size >= offsetofend(TRACEE_REGS_STRUCT, fop)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, fop); } if (size >= offsetofend(TRACEE_REGS_STRUCT, rip)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, rip); } if (size >= offsetofend(TRACEE_REGS_STRUCT, rdp)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, rdp); } if (size >= offsetofend(TRACEE_REGS_STRUCT, mxcsr)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, mxcsr); } if (size >= offsetofend(TRACEE_REGS_STRUCT, mxcr_mask)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, mxcr_mask); } if (size > offsetof(TRACEE_REGS_STRUCT, st_space)) { const size_t len = size - offsetof(TRACEE_REGS_STRUCT, st_space); fputs(", st_space=[", stdout); for (unsigned int i = 0; i < ARRAY_SIZE(regs->st_space); ++i) { if (len > i * sizeof(regs->st_space[i])) { if (i) fputs(", ", stdout); PRINT_VAL_X(regs->st_space[i]); } } fputs("]", stdout); } if (size > offsetof(TRACEE_REGS_STRUCT, xmm_space)) { const size_t len = size - offsetof(TRACEE_REGS_STRUCT, xmm_space); fputs(", xmm_space=[", stdout); for (unsigned int i = 0; i < ARRAY_SIZE(regs->xmm_space); ++i) { if (len > i * sizeof(regs->xmm_space[i])) { if (i) fputs(", ", stdout); PRINT_VAL_X(regs->xmm_space[i]); } } fputs("]", stdout); } if (size > offsetof(TRACEE_REGS_STRUCT, padding)) { const size_t len = size - offsetof(TRACEE_REGS_STRUCT, padding); fputs(", padding=[", stdout); for (unsigned int i = 0; i < ARRAY_SIZE(regs->padding); ++i) { if (len > i * sizeof(regs->padding[i])) { if (i) fputs(", ", stdout); PRINT_VAL_X(regs->padding[i]); } } fputs("]", stdout); } # elif defined __powerpc__ || defined __powerpc64__ 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, fpscr)) { fputs(", ", stdout); PRINT_FIELD_X(*regs, fpscr); } # endif /* __i386__ || __powerpc64__ || __powerpc__ || __x86_64__ */ if (size > sizeof(*regs)) fputs(", ...", stdout); fputs("}", stdout); #else /* !TRACEE_REGS_STRUCT */ printf("%p", rs); #endif /* TRACEE_REGS_STRUCT */ } #ifdef PTRACE_GETFPREGS static void print_pt_fpregs(const void *const rs, const size_t size) { # ifdef TRACEE_REGS_STRUCT if (size != sizeof(TRACEE_REGS_STRUCT)) error_msg_and_fail("expected size %zu, got size %zu", sizeof(TRACEE_REGS_STRUCT), size); print_fpregset(rs, size); # else /* !TRACEE_REGS_STRUCT */ printf("%p", rs); # endif } static void do_getfpregs_setfpregs(const int pid, void *const regbuf, const unsigned int regsize, unsigned int *const actual_size) { if (do_ptrace_regs(PTRACE_GETFPREGS, pid, (uintptr_t) regbuf)) { printf("ptrace(" XLAT_FMT ", %d, %p) = %s\n", XLAT_ARGS(PTRACE_GETFPREGS), pid, regbuf, errstr); return; /* skip PTRACE_SETFPREGS */ } else { printf("ptrace(" XLAT_FMT ", %d, ", XLAT_ARGS(PTRACE_GETFPREGS), pid); print_pt_fpregs(regbuf, regsize); printf(") = %s\n", errstr); if (*actual_size) return; /* skip PTRACE_SETFPREGS */ else *actual_size = regsize; } do_ptrace_regs(PTRACE_SETFPREGS, pid, (uintptr_t) regbuf); printf("ptrace(" XLAT_FMT ", %d, ", XLAT_ARGS(PTRACE_SETFPREGS), pid); print_pt_fpregs(regbuf, regsize); printf(") = %s\n", errstr); } #endif /* PTRACE_GETFPREGS */ static void do_getregset_setregset(const int pid, const unsigned int nt, const char *const nt_str, void *const regbuf, const unsigned int regsize, unsigned int *actual_size, struct iovec *const iov, void (*print_regset_fn)(const void *, size_t)) { iov->iov_base = regbuf; iov->iov_len = regsize; do_ptrace(PTRACE_GETREGSET, pid, nt, (uintptr_t) iov); if (iov->iov_len == regsize) { printf("ptrace(" XLAT_FMT ", %d, " XLAT_FMT ", {iov_base=", XLAT_ARGS(PTRACE_GETREGSET), pid, XLAT_SEL(nt, nt_str)); print_regset_fn(iov->iov_base, iov->iov_len); printf(", iov_len=%lu}) = %s\n", (unsigned long) iov->iov_len, errstr); if (*actual_size) return; /* skip PTRACE_SETREGSET */ } else { printf("ptrace(" XLAT_FMT ", %d, " XLAT_FMT ", {iov_base=", XLAT_ARGS(PTRACE_GETREGSET), pid, XLAT_SEL(nt, nt_str)); print_regset_fn(iov->iov_base, iov->iov_len); printf(", iov_len=%u => %lu}) = %s\n", regsize, (unsigned long) iov->iov_len, errstr); if (*actual_size) error_msg_and_fail("iov_len changed again" " from %u to %lu", regsize, (unsigned long) iov->iov_len); *actual_size = iov->iov_len; } #if defined __sparc__ && !defined __arch64__ /* * On sparc32 PTRACE_SETREGSET NT_PRSTATUS of size greater than 120 * has interesting side effects. */ if (nt == 1 && regsize > 120) return; #endif /* __sparc__ && !__arch64__ */ iov->iov_len = regsize; do_ptrace(PTRACE_SETREGSET, pid, nt, (uintptr_t) iov); if (iov->iov_len == regsize) { printf("ptrace(" XLAT_FMT ", %d, " XLAT_FMT ", {iov_base=", XLAT_ARGS(PTRACE_SETREGSET), pid, XLAT_SEL(nt, nt_str)); print_regset_fn(iov->iov_base, regsize); printf(", iov_len=%lu}) = %s\n", (unsigned long) iov->iov_len, errstr); } else { printf("ptrace(" XLAT_FMT ", %d, " XLAT_FMT ", {iov_base=", XLAT_ARGS(PTRACE_SETREGSET), pid, XLAT_SEL(nt, nt_str)); print_regset_fn(iov->iov_base, regsize); printf(", iov_len=%u => %lu}) = %s\n", regsize, (unsigned long) iov->iov_len, errstr); } } static void test_getregset_setregset(int pid) { TAIL_ALLOC_OBJECT_CONST_PTR(struct iovec, iov); unsigned long addr = (uintptr_t) (iov + 1); iov->iov_base = (void *) addr; iov->iov_len = sizeof(kernel_ulong_t); do_ptrace(PTRACE_GETREGSET, pid, 1, (uintptr_t) iov); printf("ptrace(" XLAT_FMT ", %d, " XLAT_KNOWN(0x1, "NT_PRSTATUS") ", {iov_base=%p, iov_len=%lu}) = %s\n", XLAT_ARGS(PTRACE_GETREGSET), pid, iov->iov_base, (unsigned long) iov->iov_len, errstr); do_ptrace(PTRACE_SETREGSET, pid, 3, (uintptr_t) iov); printf("ptrace(" XLAT_FMT ", %d, " XLAT_KNOWN(0x3, "NT_PRPSINFO") ", {iov_base=%p, iov_len=%lu}) = %s\n", XLAT_ARGS(PTRACE_SETREGSET), pid, iov->iov_base, (unsigned long) iov->iov_len, errstr); #ifdef PTRACE_GETREGS do_ptrace_regs(PTRACE_GETREGS, pid, addr); printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n", XLAT_ARGS(PTRACE_GETREGS), pid, addr, errstr); #endif #ifdef PTRACE_SETREGS do_ptrace_regs(PTRACE_SETREGS, pid, addr); printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n", XLAT_ARGS(PTRACE_SETREGS), pid, addr, errstr); #endif #ifdef PTRACE_GETFPREGS do_ptrace_regs(PTRACE_GETFPREGS, pid, addr); printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n", XLAT_ARGS(PTRACE_GETFPREGS), pid, addr, errstr); #endif #ifdef PTRACE_SETFPREGS do_ptrace_regs(PTRACE_SETFPREGS, pid, addr); printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n", XLAT_ARGS(PTRACE_SETFPREGS), pid, addr, errstr); #endif for (; addr > (uintptr_t) iov; --addr) { do_ptrace(PTRACE_GETREGSET, pid, 1, addr); printf("ptrace(" XLAT_FMT ", %d, " XLAT_KNOWN(0x1, "NT_PRSTATUS") ", %#lx) = %s\n", XLAT_ARGS(PTRACE_GETREGSET), pid, addr, errstr); do_ptrace(PTRACE_SETREGSET, pid, 2, addr); printf("ptrace(" XLAT_FMT ", %d, " XLAT_KNOWN(0x2, "NT_FPREGSET") ", %#lx) = %s\n", XLAT_ARGS(PTRACE_SETREGSET), pid, addr, errstr); } pid = fork(); if (pid < 0) perror_msg_and_fail("fork"); if (!pid) { if (do_ptrace(PTRACE_TRACEME, 0, 0, 0)) perror_msg_and_fail("child: PTRACE_TRACEME"); raise(SIGSTOP); if (chdir("")) { ; } _exit(0); } const unsigned int regset_buf_size = 4096 - 64; char *const regset_buf_endptr = midtail_alloc(0, regset_buf_size); for (;;) { int status, tracee, saved; errno = 0; tracee = wait(&status); if (tracee <= 0) { if (errno == EINTR) continue; saved = errno; kill(pid, SIGKILL); errno = saved; perror_msg_and_fail("wait"); } if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) break; error_msg_and_fail("unexpected exit status %#x", WEXITSTATUS(status)); } if (WIFSIGNALED(status)) error_msg_and_fail("unexpected signal %u", WTERMSIG(status)); if (!WIFSTOPPED(status)) { kill(pid, SIGKILL); error_msg_and_fail("unexpected wait status %#x", status); } static unsigned int actual_prstatus_size; for (unsigned int i = actual_prstatus_size; i <= regset_buf_size && (!actual_prstatus_size || actual_prstatus_size + 1 >= i); ++i) { do_getregset_setregset(pid, 1, "NT_PRSTATUS", regset_buf_endptr - i, i, &actual_prstatus_size, iov, print_prstatus_regset); } /* * In an unlikely case NT_PRSTATUS is not supported, * use regset_buf_size. */ if (!actual_prstatus_size) actual_prstatus_size = regset_buf_size; static unsigned int actual_fpregset_size; for (unsigned int i = actual_fpregset_size; i <= regset_buf_size && (!actual_fpregset_size || actual_fpregset_size + 1 >= i); ++i) { do_getregset_setregset(pid, 2, "NT_FPREGSET", regset_buf_endptr - i, i, &actual_fpregset_size, iov, print_fpregset); } /* * In an unlikely case NT_FPREGSET is not supported, * use regset_buf_size. */ if (!actual_fpregset_size) actual_fpregset_size = regset_buf_size; #ifdef PTRACE_GETREGS static unsigned int actual_pt_regs_size # ifdef __mips__ /* * For some reason MIPS kernels do not report * PTRACE_GETREGS EFAULT errors. */ = 38 * 8 # endif ; for (unsigned int i = actual_pt_regs_size; i <= (actual_pt_regs_size ?: regset_buf_size); ++i) { do_getregs_setregs(pid, regset_buf_endptr - i, i, &actual_pt_regs_size); } /* * In an unlikely case PTRACE_GETREGS is not supported, * use regset_buf_size. */ if (!actual_pt_regs_size) actual_pt_regs_size = regset_buf_size; #endif #ifdef PTRACE_GETREGS64 static unsigned int actual_pt_regs64_size; for (unsigned int i = actual_pt_regs64_size; i <= (actual_pt_regs64_size ?: regset_buf_size); ++i) { do_getregs64_setregs64(pid, regset_buf_endptr - i, i, &actual_pt_regs64_size); } /* * In an unlikely case PTRACE_GETREGS64 is not supported, * use regset_buf_size. */ if (!actual_pt_regs64_size) actual_pt_regs64_size = regset_buf_size; #endif #ifdef PTRACE_GETFPREGS static unsigned int actual_pt_fpregs_size # ifdef __mips__ /* * For some reason MIPS kernels do not report * PTRACE_GETFPREGS EFAULT errors. */ = 33 * 8 # endif ; for (unsigned int i = actual_pt_fpregs_size; i <= (actual_pt_fpregs_size ?: regset_buf_size); ++i) { do_getfpregs_setfpregs(pid, regset_buf_endptr - i, i, &actual_pt_fpregs_size); } /* * In an unlikely case PTRACE_GETFPREGS is not supported, * use regset_buf_size. */ if (!actual_pt_fpregs_size) actual_pt_fpregs_size = regset_buf_size; #endif if (WSTOPSIG(status) == SIGSTOP) kill(pid, SIGCONT); if (do_ptrace(PTRACE_SYSCALL, pid, 0, 0)) { saved = errno; kill(pid, SIGKILL); errno = saved; perror_msg_and_fail("ptrace"); } printf("ptrace(" XLAT_FMT ", %d, NULL, 0) = 0\n", XLAT_ARGS(PTRACE_SYSCALL), pid); } } #if defined __arm64__ || defined __aarch64__ static void check_compat_ptrace_req(const unsigned int req, const char *const s, const int pid) { do_ptrace(req, pid, 0, 0); printf("ptrace(%#x" NRAW(" /* ") "%s" NRAW(" */") ", %d, NULL, NULL) = %s\n", req, NRAW(s), pid, errstr); do_ptrace(req, pid, 0xbadc0deddeadface, 0xfacefeeddecaffed); printf("ptrace(%#x" NRAW(" /* ") "%s" NRAW(" */") ", %d, 0xbadc0deddeadface, 0xfacefeeddecaffed) = %s\n", req, NRAW(s), pid, errstr); } static void test_compat_ptrace(const int pid) { check_compat_ptrace_req(12, "COMPAT_PTRACE_GETREGS", pid); check_compat_ptrace_req(13, "COMPAT_PTRACE_SETREGS", pid); check_compat_ptrace_req(14, "COMPAT_PTRACE_GETFPREGS", pid); check_compat_ptrace_req(15, "COMPAT_PTRACE_SETFPREGS", pid); check_compat_ptrace_req(22, "COMPAT_PTRACE_GET_THREAD_AREA", pid); check_compat_ptrace_req(23, "COMPAT_PTRACE_SET_SYSCALL", pid); check_compat_ptrace_req(27, "COMPAT_PTRACE_GETVFPREGS", pid); check_compat_ptrace_req(28, "COMPAT_PTRACE_SETVFPREGS", pid); check_compat_ptrace_req(29, "COMPAT_PTRACE_GETHBPREGS", pid); check_compat_ptrace_req(30, "COMPAT_PTRACE_SETHBPREGS", pid); } #else /* !(__arm64__ || __aarch64__) */ static void test_compat_ptrace(const int pid) {} #endif int main(void) { const unsigned long bad_request = (unsigned long) 0xdeadbeeffffffeedULL; const unsigned long bad_data = (unsigned long) 0xdeadcafefffff00dULL; const int pid = getpid(); TAIL_ALLOC_OBJECT_CONST_PTR(uint64_t, filter_off); const unsigned int sigset_size = get_sigset_size(); void *const k_set = tail_alloc(sigset_size); TAIL_ALLOC_OBJECT_CONST_PTR(siginfo_t, sip); do_ptrace(bad_request, pid, 0, 0); printf("ptrace(%#lx" NRAW(" /* PTRACE_??? */") ", %d, NULL, NULL) = %s\n", bad_request, pid, errstr); do_ptrace(PTRACE_PEEKDATA, pid, bad_request, bad_data); #ifdef IA64 printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n", XLAT_ARGS(PTRACE_PEEKDATA), pid, bad_request, errstr); #else printf("ptrace(" XLAT_FMT ", %d, %#lx, %#lx) = %s\n", XLAT_ARGS(PTRACE_PEEKDATA), pid, bad_request, bad_data, errstr); #endif do_ptrace(PTRACE_PEEKTEXT, pid, bad_request, bad_data); #ifdef IA64 printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n", XLAT_ARGS(PTRACE_PEEKTEXT), pid, bad_request, errstr); #else printf("ptrace(" XLAT_FMT ", %d, %#lx, %#lx) = %s\n", XLAT_ARGS(PTRACE_PEEKTEXT), pid, bad_request, bad_data, errstr); #endif do_ptrace(PTRACE_PEEKUSER, pid, bad_request, bad_data); #ifdef IA64 printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n", XLAT_ARGS(PTRACE_PEEKUSER), pid, bad_request, errstr); #else printf("ptrace(" XLAT_FMT ", %d, %#lx, %#lx) = %s\n", XLAT_ARGS(PTRACE_PEEKUSER), pid, bad_request, bad_data, errstr); #endif do_ptrace(PTRACE_POKEUSER, pid, bad_request, bad_data); printf("ptrace(" XLAT_FMT ", %d, %#lx, %#lx) = %s\n", XLAT_ARGS(PTRACE_POKEUSER), pid, bad_request, bad_data, errstr); do_ptrace(PTRACE_ATTACH, pid, 0, 0); printf("ptrace(" XLAT_FMT ", %d) = %s\n", XLAT_ARGS(PTRACE_ATTACH), pid, errstr); do_ptrace(PTRACE_INTERRUPT, pid, 0, 0); printf("ptrace(" XLAT_FMT ", %d) = %s\n", XLAT_ARGS(PTRACE_INTERRUPT), pid, errstr); do_ptrace(PTRACE_KILL, pid, 0, 0); printf("ptrace(" XLAT_FMT ", %d) = %s\n", XLAT_ARGS(PTRACE_KILL), pid, errstr); do_ptrace(PTRACE_LISTEN, pid, 0, 0); printf("ptrace(" XLAT_FMT ", %d) = %s\n", XLAT_ARGS(PTRACE_LISTEN), pid, errstr); sigset_t libc_set; sigemptyset(&libc_set); sigaddset(&libc_set, SIGUSR1); memcpy(k_set, &libc_set, sigset_size); do_ptrace(PTRACE_SETSIGMASK, pid, sigset_size, (uintptr_t) k_set); printf("ptrace(" XLAT_FMT ", %d, %u, [" XLAT_FMT_U "]) = %s\n", XLAT_ARGS(PTRACE_SETSIGMASK), pid, sigset_size, XLAT_SEL(SIGUSR1, "USR1"), errstr); do_ptrace(PTRACE_GETSIGMASK, pid, sigset_size, (uintptr_t) k_set); printf("ptrace(" XLAT_FMT ", %d, %u, %p) = %s\n", XLAT_ARGS(PTRACE_GETSIGMASK), pid, sigset_size, k_set, errstr); do_ptrace(PTRACE_SECCOMP_GET_FILTER, pid, 42, 0); printf("ptrace(" XLAT_FMT ", %d, 42, NULL) = %s\n", XLAT_ARGS(PTRACE_SECCOMP_GET_FILTER), pid, errstr); do_ptrace(PTRACE_SECCOMP_GET_METADATA, pid, bad_data, 0); printf("ptrace(" XLAT_FMT ", %d, %lu, NULL) = %s\n", XLAT_ARGS(PTRACE_SECCOMP_GET_METADATA), pid, bad_data, errstr); do_ptrace(PTRACE_SECCOMP_GET_METADATA, pid, 7, (uintptr_t) filter_off); printf("ptrace(" XLAT_FMT ", %d, 7, %p) = %s\n", XLAT_ARGS(PTRACE_SECCOMP_GET_METADATA), pid, filter_off, errstr); *filter_off = 0xfacefeeddeadc0deULL; do_ptrace(PTRACE_SECCOMP_GET_METADATA, pid, bad_data, (uintptr_t) filter_off); printf("ptrace(" XLAT_FMT ", %d, %lu, {filter_off=%" PRIu64 "}) = %s\n", XLAT_ARGS(PTRACE_SECCOMP_GET_METADATA), pid, bad_data, *filter_off, errstr); do_ptrace(PTRACE_GETEVENTMSG, pid, bad_request, bad_data); printf("ptrace(" XLAT_FMT ", %d, %#lx, %#lx) = %s\n", XLAT_ARGS(PTRACE_GETEVENTMSG), pid, bad_request, bad_data, errstr); memset(sip, -1, sizeof(*sip)); sip->si_signo = SIGIO; sip->si_code = 1; sip->si_errno = ENOENT; sip->si_band = -2; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT ", si_errno=" XLAT_FMT_U ", si_band=-2}" ") = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGIO), XLAT_ARGS(POLL_IN), XLAT_ARGS(ENOENT), errstr); memset(sip, -1, sizeof(*sip)); sip->si_signo = SIGTRAP; sip->si_code = 1; sip->si_errno = ENOENT; sip->si_pid = 2; sip->si_uid = 3; sip->si_ptr = (void *) bad_request; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT ", si_errno=" XLAT_FMT_U ", si_pid=2" ", si_uid=3, si_int=%d, si_ptr=%p}) = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGTRAP), XLAT_ARGS(TRAP_BRKPT), XLAT_ARGS(ENOENT), sip->si_int, sip->si_ptr, errstr); memset(sip, -1, sizeof(*sip)); sip->si_signo = SIGILL; sip->si_code = 1; sip->si_errno = ENOENT; sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT ", si_errno=" XLAT_FMT_U ", si_addr=%p}" ") = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGILL), XLAT_ARGS(ILL_ILLOPC), XLAT_ARGS(ENOENT), sip->si_addr, errstr); memset(sip, -1, sizeof(*sip)); sip->si_signo = SIGFPE; sip->si_code = 1; sip->si_errno = ENOENT; sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT ", si_errno=" XLAT_FMT_U ", si_addr=%p}" ") = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGFPE), XLAT_ARGS(FPE_INTDIV), XLAT_ARGS(ENOENT), sip->si_addr, errstr); memset(sip, -1, sizeof(*sip)); sip->si_signo = SIGBUS; sip->si_code = 1; sip->si_errno = -2; sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT ", si_errno=%u, si_addr=%p}) = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGBUS), XLAT_ARGS(BUS_ADRALN), sip->si_errno, sip->si_addr, errstr); memset(sip, -1, sizeof(*sip)); sip->si_signo = SIGPROF; sip->si_code = 0xbadc0ded; sip->si_errno = -2; sip->si_pid = 0; sip->si_uid = 3; sip->si_ptr = 0; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=%#x, si_errno=%u, si_pid=0, si_uid=3}) = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGPROF), sip->si_code, sip->si_errno, errstr); #ifdef HAVE_SIGINFO_T_SI_SYSCALL memset(sip, -1, sizeof(*sip)); sip->si_signo = SIGSYS; sip->si_code = 1; sip->si_errno = ENOENT; sip->si_call_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL; sip->si_syscall = -1U; sip->si_arch = AUDIT_ARCH_X86_64; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno=" XLAT_FMT_U ", si_call_addr=%p, si_syscall=%u, si_arch=" XLAT_FMT "}) = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGSYS), XLAT_ARGS(ENOENT), sip->si_call_addr, sip->si_syscall, XLAT_ARGS(AUDIT_ARCH_X86_64), errstr); sip->si_errno = 3141592653U; sip->si_call_addr = NULL; sip->si_syscall = __NR_read; sip->si_arch = 0xda7a1057; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno=%u" ", si_call_addr=NULL, si_syscall=%u, si_arch=%#x" NRAW(" /* AUDIT_ARCH_??? */") "}) = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGSYS), sip->si_errno, sip->si_syscall, sip->si_arch, errstr); # ifdef CUR_AUDIT_ARCH sip->si_arch = CUR_AUDIT_ARCH; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno=%u" ", si_call_addr=NULL, si_syscall=" XLAT_FMT_U ", si_arch=%s}" ") = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGSYS), sip->si_errno, XLAT_ARGS(__NR_read), sprintxval(audit_arch, CUR_AUDIT_ARCH, "AUDIT_ARCH_???"), errstr); # endif # if defined(PERS0_AUDIT_ARCH) sip->si_arch = PERS0_AUDIT_ARCH; sip->si_syscall = PERS0__NR_gettid; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno=%u" ", si_call_addr=NULL, si_syscall=%u" NRAW(" /* gettid */") ", si_arch=%s}) = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGSYS), sip->si_errno, PERS0__NR_gettid, sprintxval(audit_arch, PERS0_AUDIT_ARCH, "AUDIT_ARCH_???"), errstr); # endif # if defined(M32_AUDIT_ARCH) sip->si_arch = M32_AUDIT_ARCH; sip->si_syscall = M32__NR_gettid; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno=%u" ", si_call_addr=NULL, si_syscall=%u" NRAW(" /* gettid */") ", si_arch=%s}) = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGSYS), sip->si_errno, M32__NR_gettid, sprintxval(audit_arch, M32_AUDIT_ARCH, "AUDIT_ARCH_???"), errstr); # endif # if defined(MX32_AUDIT_ARCH) sip->si_arch = MX32_AUDIT_ARCH; sip->si_syscall = MX32__NR_gettid; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno=%u" ", si_call_addr=NULL, si_syscall=%u" NRAW(" /* gettid */") ", si_arch=%s}) = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGSYS), sip->si_errno, MX32__NR_gettid, sprintxval(audit_arch, MX32_AUDIT_ARCH, "AUDIT_ARCH_???"), errstr); # endif #endif #if defined HAVE_SIGINFO_T_SI_TIMERID && defined HAVE_SIGINFO_T_SI_OVERRUN memset(sip, -1, sizeof(*sip)); sip->si_signo = SIGHUP; sip->si_code = SI_TIMER; sip->si_errno = ENOENT; sip->si_timerid = 0xdeadbeef; sip->si_overrun = -1; sip->si_ptr = (void *) (unsigned long) 0xfacefeeddeadbeefULL; do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT ", si_errno=" XLAT_FMT_U ", si_timerid=%#x" ", si_overrun=%d, si_int=%d, si_ptr=%p}) = %s\n", XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGHUP), XLAT_ARGS(SI_TIMER), XLAT_ARGS(ENOENT), sip->si_timerid, sip->si_overrun, sip->si_int, sip->si_ptr, errstr); #endif do_ptrace(PTRACE_GETSIGINFO, pid, bad_request, (uintptr_t) sip); printf("ptrace(" XLAT_FMT ", %d, %#lx, %p) = %s\n", XLAT_ARGS(PTRACE_GETSIGINFO), pid, bad_request, sip, errstr); do_ptrace(PTRACE_CONT, pid, 0, SIGUSR1); printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n", XLAT_ARGS(PTRACE_CONT), pid, XLAT_ARGS(SIGUSR1), errstr); do_ptrace(PTRACE_DETACH, pid, 0, SIGUSR2); printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n", XLAT_ARGS(PTRACE_DETACH), pid, XLAT_ARGS(SIGUSR2), errstr); do_ptrace(PTRACE_SYSCALL, pid, 0, SIGUSR1); printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n", XLAT_ARGS(PTRACE_SYSCALL), pid, XLAT_ARGS(SIGUSR1), errstr); #ifdef PTRACE_SINGLESTEP do_ptrace(PTRACE_SINGLESTEP, pid, 0, SIGUSR2); printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n", XLAT_ARGS(PTRACE_SINGLESTEP), pid, XLAT_ARGS(SIGUSR2), errstr); #endif #ifdef PTRACE_SINGLEBLOCK do_ptrace(PTRACE_SINGLEBLOCK, pid, 0, SIGUSR1); printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n", XLAT_ARGS(PTRACE_SINGLEBLOCK), pid, XLAT_ARGS(SIGUSR1), errstr); #endif #ifdef PTRACE_SYSEMU do_ptrace(PTRACE_SYSEMU, pid, 0, SIGUSR2); printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n", XLAT_ARGS(PTRACE_SYSEMU), pid, XLAT_ARGS(SIGUSR2), errstr); #endif #ifdef PTRACE_SYSEMU_SINGLESTEP do_ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, SIGUSR1); printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n", XLAT_ARGS(PTRACE_SYSEMU_SINGLESTEP), pid, XLAT_ARGS(SIGUSR1), errstr); #endif do_ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACEFORK|PTRACE_O_TRACECLONE); printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT ") = %s\n", XLAT_ARGS(PTRACE_SETOPTIONS), pid, XLAT_ARGS(PTRACE_O_TRACEFORK|PTRACE_O_TRACECLONE), errstr); do_ptrace(PTRACE_SEIZE, pid, bad_request, PTRACE_O_TRACESYSGOOD); printf("ptrace(" XLAT_FMT ", %d, %#lx, " XLAT_FMT ") = %s\n", XLAT_ARGS(PTRACE_SEIZE), pid, bad_request, XLAT_ARGS(PTRACE_O_TRACESYSGOOD), errstr); test_peeksiginfo(pid, bad_request); test_getregset_setregset(pid); test_compat_ptrace(pid); do_ptrace(PTRACE_TRACEME, 0, 0, 0); printf("ptrace(" XLAT_FMT ") = %s\n", XLAT_ARGS(PTRACE_TRACEME), errstr); puts("+++ exited with 0 +++"); return 0; }