(root)/
strace-6.5/
tests-m32/
ptrace.c
       1  /*
       2   * Check decoding of ptrace syscall.
       3   *
       4   * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2016-2023 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  #include "scno.h"
      13  #include "print_fields.h"
      14  
      15  #include <errno.h>
      16  #include "ptrace.h"
      17  #include <inttypes.h>
      18  #include <fcntl.h>
      19  #include <signal.h>
      20  #include <stdint.h>
      21  #include <stdio.h>
      22  #include <string.h>
      23  #include <sys/wait.h>
      24  #include <unistd.h>
      25  #include <linux/audit.h>
      26  #include <sys/uio.h>
      27  #include <sys/user.h>
      28  
      29  #include "cur_audit_arch.h"
      30  
      31  #include "xlat.h"
      32  #define XLAT_MACROS_ONLY
      33  # include "xlat/elf_em.h"
      34  #undef XLAT_MACROS_ONLY
      35  #include "xlat/audit_arch.h"
      36  
      37  #define NULL_FD 23
      38  #define NULL_STR "/dev/null"
      39  
      40  #ifndef NULL_FD_STR
      41  # define NULL_FD_STR ""
      42  #endif
      43  
      44  static const char null_path[] = "/dev/null";
      45  
      46  #if SIZEOF_LONG > 4
      47  # define UP64BIT(a_) a_
      48  #else
      49  # define UP64BIT(a_)
      50  #endif
      51  
      52  struct valstraux {
      53  	int val;
      54  	const char *str;
      55  	const char *aux;
      56  };
      57  
      58  static const char *errstr;
      59  
      60  static long
      61  do_ptrace(const unsigned long request,
      62  	  const unsigned int pid,
      63  	  const unsigned long addr,
      64  	  const unsigned long data)
      65  {
      66  	const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
      67  	const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
      68  	const kernel_ulong_t arg1 = request;
      69  	const kernel_ulong_t arg2 = fill | pid;
      70  	const kernel_ulong_t arg3 = addr;
      71  	const kernel_ulong_t arg4 = data;
      72  	long rc = syscall(__NR_ptrace, arg1, arg2, arg3, arg4, bad, bad);
      73  	errstr = sprintrc(rc);
      74  	return rc;
      75  }
      76  
      77  #if defined PTRACE_GETREGS || defined PTRACE_GETREGS64 || defined PTRACE_GETFPREGS
      78  static long
      79  do_ptrace_regs(const unsigned long request,
      80  	       const unsigned int pid,
      81  	       const unsigned long regs_addr)
      82  {
      83  	const unsigned long bad = (unsigned long) 0xdeadbeefdeadbeefULL;
      84  # ifdef __sparc__
      85  	const unsigned long arg_addr = regs_addr;
      86  	const unsigned long arg_data = bad;
      87  # else
      88  	const unsigned long arg_addr = bad;
      89  	const unsigned long arg_data = regs_addr;
      90  # endif
      91  	return do_ptrace(request, pid, arg_addr, arg_data);
      92  }
      93  #endif /* PTRACE_GETREGS || PTRACE_GETREGS64 || PTRACE_GETFPREGS */
      94  
      95  #ifndef PTRACE_PEEKSIGINFO_SHARED
      96  # define PTRACE_PEEKSIGINFO_SHARED   (1 << 0)
      97  #endif
      98  
      99  static void
     100  test_peeksiginfo(int pid, const unsigned long bad_request)
     101  {
     102  	do_ptrace(PTRACE_PEEKSIGINFO, pid, 0, bad_request);
     103  	printf("ptrace(" XLAT_FMT ", %d, NULL, %#lx) = %s\n",
     104  	       XLAT_ARGS(PTRACE_PEEKSIGINFO), pid, bad_request, errstr);
     105  
     106  	struct psi {
     107  		unsigned long long off;
     108  		unsigned int flags, nr;
     109  	};
     110  	TAIL_ALLOC_OBJECT_CONST_PTR(struct psi, psi);
     111  
     112  	psi->off = 0xdeadbeeffacefeedULL;
     113  	psi->flags = 1;
     114  	psi->nr = 42;
     115  
     116  	do_ptrace(PTRACE_PEEKSIGINFO, pid, (uintptr_t) psi, bad_request);
     117  	printf("ptrace(" XLAT_FMT ", %d, {off=%llu"
     118  	       ", flags=" XLAT_FMT ", nr=%u}, %#lx) = %s\n",
     119  	       XLAT_ARGS(PTRACE_PEEKSIGINFO), pid, psi->off,
     120  	       XLAT_ARGS(PTRACE_PEEKSIGINFO_SHARED),
     121  	       psi->nr, bad_request, errstr);
     122  
     123  	pid = fork();
     124  	if (pid < 0)
     125  		perror_msg_and_fail("fork");
     126  
     127  	if (!pid) {
     128  		sigset_t mask;
     129  		sigemptyset(&mask);
     130  		sigaddset(&mask, SIGUSR1);
     131  		sigaddset(&mask, SIGUSR2);
     132  		sigaddset(&mask, SIGALRM);
     133  
     134  		if (sigprocmask(SIG_BLOCK, &mask, NULL))
     135  			perror_msg_and_fail("sigprocmask");
     136  
     137  		raise(SIGUSR1);
     138  		raise(SIGUSR2);
     139  		raise(SIGALRM);
     140  
     141  		if (do_ptrace(PTRACE_TRACEME, 0, 0, 0))
     142  			perror_msg_and_fail("child: PTRACE_TRACEME");
     143  
     144  		raise(SIGSTOP);
     145  		_exit(0);
     146  	}
     147  
     148  	const unsigned int nsigs = 4;
     149  	const uid_t uid = geteuid();
     150  	siginfo_t *sigs = tail_alloc(sizeof(*sigs) * nsigs);
     151  
     152  	psi->off = 0;
     153  	psi->flags = 0;
     154  	psi->nr = nsigs;
     155  
     156  	for (;;) {
     157  		int status, tracee, saved;
     158  
     159  		errno = 0;
     160  		tracee = wait(&status);
     161  		if (tracee <= 0) {
     162  			if (errno == EINTR)
     163  				continue;
     164  			saved = errno;
     165  			kill(pid, SIGKILL);
     166  			errno = saved;
     167  			perror_msg_and_fail("wait");
     168  		}
     169  		if (WIFEXITED(status)) {
     170  			if (WEXITSTATUS(status) == 0)
     171  				break;
     172  			error_msg_and_fail("unexpected exit status %#x",
     173  					   WEXITSTATUS(status));
     174  		}
     175  		if (WIFSIGNALED(status))
     176  			error_msg_and_fail("unexpected signal %u",
     177  					   WTERMSIG(status));
     178  		if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
     179  			kill(pid, SIGKILL);
     180  			error_msg_and_fail("unexpected wait status %#x",
     181  					   status);
     182  		}
     183  
     184  		long rc = do_ptrace(PTRACE_PEEKSIGINFO, pid,
     185  				    (uintptr_t) psi, (uintptr_t) sigs);
     186  		if (rc < 0) {
     187  			printf("ptrace(" XLAT_FMT ", %d, {off=%llu, flags=0"
     188  			       ", nr=%u}, %p) = %s\n",
     189  			       XLAT_ARGS(PTRACE_PEEKSIGINFO),
     190  			       pid, psi->off, psi->nr, sigs, errstr);
     191  		} else {
     192  			printf("ptrace(" XLAT_FMT ", %d"
     193  			       ", {off=%llu, flags=0, nr=%u}"
     194  			       ", [{si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT
     195  			       ", si_pid=%d, si_uid=%d}"
     196  			       ", {si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT
     197  			       ", si_pid=%d, si_uid=%d}"
     198  			       ", {si_signo=" XLAT_FMT_U ", si_code=" XLAT_FMT
     199  			       ", si_pid=%d, si_uid=%d}"
     200  			       "]) = %s\n",
     201  			       XLAT_ARGS(PTRACE_PEEKSIGINFO),
     202  			       pid, psi->off, psi->nr,
     203  			       XLAT_ARGS(SIGUSR1), XLAT_ARGS(SI_TKILL),
     204  			       pid, (int) uid,
     205  			       XLAT_ARGS(SIGUSR2), XLAT_ARGS(SI_TKILL),
     206  			       pid, (int) uid,
     207  			       XLAT_ARGS(SIGALRM), XLAT_ARGS(SI_TKILL),
     208  			       pid, (int) uid,
     209  			       errstr);
     210  		}
     211  
     212  		if (do_ptrace(PTRACE_CONT, pid, 0, 0)) {
     213  			saved = errno;
     214  			kill(pid, SIGKILL);
     215  			errno = saved;
     216  			perror_msg_and_fail("ptrace");
     217  		}
     218  		printf("ptrace(" XLAT_FMT ", %d, NULL, 0) = 0\n",
     219  		       XLAT_ARGS(PTRACE_CONT), pid);
     220  	}
     221  }
     222  
     223  #undef TRACEE_REGS_STRUCT
     224  #if defined __x86_64__ || defined __i386__
     225  # define TRACEE_REGS_STRUCT struct user_regs_struct
     226  #elif defined __powerpc__ || defined __powerpc64__
     227  # define TRACEE_REGS_STRUCT struct pt_regs
     228  #elif defined __arm__
     229  # define TRACEE_REGS_STRUCT struct pt_regs
     230  #elif defined __arm64__ || defined __aarch64__ || defined __loongarch__
     231  # define TRACEE_REGS_STRUCT struct user_pt_regs
     232  #elif defined __s390__ || defined __s390x__
     233  # define TRACEE_REGS_STRUCT s390_regs
     234  #elif defined __sparc__
     235  # ifdef __arch64__
     236  typedef struct {
     237  	unsigned long g[8];
     238  	unsigned long o[8];
     239  	unsigned long l[8];
     240  	unsigned long i[8];
     241  	unsigned long tstate;
     242  	unsigned long tpc;
     243  	unsigned long tnpc;
     244  	unsigned long y;
     245  } sparc64_regs;
     246  #  define TRACEE_REGS_STRUCT sparc64_regs
     247  # else /* sparc32 */
     248  typedef struct {
     249  	unsigned int g[8];
     250  	unsigned int o[8];
     251  	unsigned int l[8];
     252  	unsigned int i[8];
     253  	unsigned int psr;
     254  	unsigned int pc;
     255  	unsigned int npc;
     256  	unsigned int y;
     257  	unsigned int wim;
     258  	unsigned int tbr;
     259  } sparc32_regs;
     260  #  define TRACEE_REGS_STRUCT sparc32_regs
     261  # endif
     262  #elif defined __riscv
     263  # define TRACEE_REGS_STRUCT struct user_regs_struct
     264  #elif defined __mips__
     265  typedef struct {
     266  # ifdef LINUX_MIPSO32
     267  	unsigned long unused[6];
     268  # endif
     269  	unsigned long regs[32];
     270  	unsigned long lo;
     271  	unsigned long hi;
     272  	unsigned long cp0_epc;
     273  	unsigned long cp0_badvaddr;
     274  	unsigned long cp0_status;
     275  	unsigned long cp0_cause;
     276  } mips_regs;
     277  # define TRACEE_REGS_STRUCT mips_regs
     278  #endif
     279  
     280  static void
     281  print_prstatus_regset(const void *const rs, const size_t size)
     282  {
     283  	if (!size || size % sizeof(kernel_ulong_t)) {
     284  		printf("%p", rs);
     285  		return;
     286  	}
     287  
     288  #ifdef TRACEE_REGS_STRUCT
     289  	const TRACEE_REGS_STRUCT *const regs = rs;
     290  
     291  	fputs("{", stdout);
     292  
     293  # if defined __x86_64__
     294  
     295  	PRINT_FIELD_X(*regs, r15);
     296  	if (size >= offsetofend(TRACEE_REGS_STRUCT, r14)) {
     297  		fputs(", ", stdout);
     298  		PRINT_FIELD_X(*regs, r14);
     299  	}
     300  	if (size >= offsetofend(TRACEE_REGS_STRUCT, r13)) {
     301  		fputs(", ", stdout);
     302  		PRINT_FIELD_X(*regs, r13);
     303  	}
     304  	if (size >= offsetofend(TRACEE_REGS_STRUCT, r12)) {
     305  		fputs(", ", stdout);
     306  		PRINT_FIELD_X(*regs, r12);
     307  	}
     308  	if (size >= offsetofend(TRACEE_REGS_STRUCT, rbp)) {
     309  		fputs(", ", stdout);
     310  		PRINT_FIELD_X(*regs, rbp);
     311  	}
     312  	if (size >= offsetofend(TRACEE_REGS_STRUCT, rbx)) {
     313  		fputs(", ", stdout);
     314  		PRINT_FIELD_X(*regs, rbx);
     315  	}
     316  	if (size >= offsetofend(TRACEE_REGS_STRUCT, r11)) {
     317  		fputs(", ", stdout);
     318  		PRINT_FIELD_X(*regs, r11);
     319  	}
     320  	if (size >= offsetofend(TRACEE_REGS_STRUCT, r10)) {
     321  		fputs(", ", stdout);
     322  		PRINT_FIELD_X(*regs, r10);
     323  	}
     324  	if (size >= offsetofend(TRACEE_REGS_STRUCT, r9)) {
     325  		fputs(", ", stdout);
     326  		PRINT_FIELD_X(*regs, r9);
     327  	}
     328  	if (size >= offsetofend(TRACEE_REGS_STRUCT, r8)) {
     329  		fputs(", ", stdout);
     330  		PRINT_FIELD_X(*regs, r8);
     331  	}
     332  	if (size >= offsetofend(TRACEE_REGS_STRUCT, rax)) {
     333  		fputs(", ", stdout);
     334  		PRINT_FIELD_X(*regs, rax);
     335  	}
     336  	if (size >= offsetofend(TRACEE_REGS_STRUCT, rcx)) {
     337  		fputs(", ", stdout);
     338  		PRINT_FIELD_X(*regs, rcx);
     339  	}
     340  	if (size >= offsetofend(TRACEE_REGS_STRUCT, rdx)) {
     341  		fputs(", ", stdout);
     342  		PRINT_FIELD_X(*regs, rdx);
     343  	}
     344  	if (size >= offsetofend(TRACEE_REGS_STRUCT, rsi)) {
     345  		fputs(", ", stdout);
     346  		PRINT_FIELD_X(*regs, rsi);
     347  	}
     348  	if (size >= offsetofend(TRACEE_REGS_STRUCT, rdi)) {
     349  		fputs(", ", stdout);
     350  		PRINT_FIELD_X(*regs, rdi);
     351  	}
     352  	if (size >= offsetofend(TRACEE_REGS_STRUCT, orig_rax)) {
     353  		fputs(", ", stdout);
     354  		PRINT_FIELD_X(*regs, orig_rax);
     355  	}
     356  	if (size >= offsetofend(TRACEE_REGS_STRUCT, rip)) {
     357  		fputs(", ", stdout);
     358  		PRINT_FIELD_X(*regs, rip);
     359  	}
     360  	if (size >= offsetofend(TRACEE_REGS_STRUCT, cs)) {
     361  		fputs(", ", stdout);
     362  		PRINT_FIELD_X(*regs, cs);
     363  	}
     364  	if (size >= offsetofend(TRACEE_REGS_STRUCT, eflags)) {
     365  		fputs(", ", stdout);
     366  		PRINT_FIELD_X(*regs, eflags);
     367  	}
     368  	if (size >= offsetofend(TRACEE_REGS_STRUCT, rsp)) {
     369  		fputs(", ", stdout);
     370  		PRINT_FIELD_X(*regs, rsp);
     371  	}
     372  	if (size >= offsetofend(TRACEE_REGS_STRUCT, ss)) {
     373  		fputs(", ", stdout);
     374  		PRINT_FIELD_X(*regs, ss);
     375  	}
     376  	if (size >= offsetofend(TRACEE_REGS_STRUCT, fs_base)) {
     377  		fputs(", ", stdout);
     378  		PRINT_FIELD_X(*regs, fs_base);
     379  	}
     380  	if (size >= offsetofend(TRACEE_REGS_STRUCT, gs_base)) {
     381  		fputs(", ", stdout);
     382  		PRINT_FIELD_X(*regs, gs_base);
     383  	}
     384  	if (size >= offsetofend(TRACEE_REGS_STRUCT, ds)) {
     385  		fputs(", ", stdout);
     386  		PRINT_FIELD_X(*regs, ds);
     387  	}
     388  	if (size >= offsetofend(TRACEE_REGS_STRUCT, es)) {
     389  		fputs(", ", stdout);
     390  		PRINT_FIELD_X(*regs, es);
     391  	}
     392  	if (size >= offsetofend(TRACEE_REGS_STRUCT, fs)) {
     393  		fputs(", ", stdout);
     394  		PRINT_FIELD_X(*regs, fs);
     395  	}
     396  	if (size >= offsetofend(TRACEE_REGS_STRUCT, gs)) {
     397  		fputs(", ", stdout);
     398  		PRINT_FIELD_X(*regs, gs);
     399  	}
     400  
     401  # elif defined __i386__
     402  
     403  	PRINT_FIELD_X(*regs, ebx);
     404  	if (size >= offsetofend(TRACEE_REGS_STRUCT, ecx)) {
     405  		fputs(", ", stdout);
     406  		PRINT_FIELD_X(*regs, ecx);
     407  	}
     408  	if (size >= offsetofend(TRACEE_REGS_STRUCT, edx)) {
     409  		fputs(", ", stdout);
     410  		PRINT_FIELD_X(*regs, edx);
     411  	}
     412  	if (size >= offsetofend(TRACEE_REGS_STRUCT, esi)) {
     413  		fputs(", ", stdout);
     414  		PRINT_FIELD_X(*regs, esi);
     415  	}
     416  	if (size >= offsetofend(TRACEE_REGS_STRUCT, edi)) {
     417  		fputs(", ", stdout);
     418  		PRINT_FIELD_X(*regs, edi);
     419  	}
     420  	if (size >= offsetofend(TRACEE_REGS_STRUCT, ebp)) {
     421  		fputs(", ", stdout);
     422  		PRINT_FIELD_X(*regs, ebp);
     423  	}
     424  	if (size >= offsetofend(TRACEE_REGS_STRUCT, eax)) {
     425  		fputs(", ", stdout);
     426  		PRINT_FIELD_X(*regs, eax);
     427  	}
     428  	if (size >= offsetofend(TRACEE_REGS_STRUCT, xds)) {
     429  		fputs(", ", stdout);
     430  		PRINT_FIELD_X(*regs, xds);
     431  	}
     432  	if (size >= offsetofend(TRACEE_REGS_STRUCT, xes)) {
     433  		fputs(", ", stdout);
     434  		PRINT_FIELD_X(*regs, xes);
     435  	}
     436  	if (size >= offsetofend(TRACEE_REGS_STRUCT, xfs)) {
     437  		fputs(", ", stdout);
     438  		PRINT_FIELD_X(*regs, xfs);
     439  	}
     440  	if (size >= offsetofend(TRACEE_REGS_STRUCT, xgs)) {
     441  		fputs(", ", stdout);
     442  		PRINT_FIELD_X(*regs, xgs);
     443  	}
     444  	if (size >= offsetofend(TRACEE_REGS_STRUCT, orig_eax)) {
     445  		fputs(", ", stdout);
     446  		PRINT_FIELD_X(*regs, orig_eax);
     447  	}
     448  	if (size >= offsetofend(TRACEE_REGS_STRUCT, eip)) {
     449  		fputs(", ", stdout);
     450  		PRINT_FIELD_X(*regs, eip);
     451  	}
     452  	if (size >= offsetofend(TRACEE_REGS_STRUCT, xcs)) {
     453  		fputs(", ", stdout);
     454  		PRINT_FIELD_X(*regs, xcs);
     455  	}
     456  	if (size >= offsetofend(TRACEE_REGS_STRUCT, eflags)) {
     457  		fputs(", ", stdout);
     458  		PRINT_FIELD_X(*regs, eflags);
     459  	}
     460  	if (size >= offsetofend(TRACEE_REGS_STRUCT, esp)) {
     461  		fputs(", ", stdout);
     462  		PRINT_FIELD_X(*regs, esp);
     463  	}
     464  	if (size >= offsetofend(TRACEE_REGS_STRUCT, xss)) {
     465  		fputs(", ", stdout);
     466  		PRINT_FIELD_X(*regs, xss);
     467  	}
     468  
     469  # elif defined __powerpc__ || defined __powerpc64__
     470  
     471  	fputs("gpr=[", stdout);
     472  	for (unsigned int i = 0; i < ARRAY_SIZE(regs->gpr); ++i) {
     473  		if (size > i * sizeof(regs->gpr[i])) {
     474  			if (i)
     475  				fputs(", ", stdout);
     476  			PRINT_VAL_X(regs->gpr[i]);
     477  		}
     478  	}
     479  	fputs("]", stdout);
     480  	if (size >= offsetofend(TRACEE_REGS_STRUCT, nip)) {
     481  		fputs(", ", stdout);
     482  		PRINT_FIELD_X(*regs, nip);
     483  	}
     484  	if (size >= offsetofend(TRACEE_REGS_STRUCT, msr)) {
     485  		fputs(", ", stdout);
     486  		PRINT_FIELD_X(*regs, msr);
     487  	}
     488  	if (size >= offsetofend(TRACEE_REGS_STRUCT, orig_gpr3)) {
     489  		fputs(", ", stdout);
     490  		PRINT_FIELD_X(*regs, orig_gpr3);
     491  	}
     492  	if (size >= offsetofend(TRACEE_REGS_STRUCT, ctr)) {
     493  		fputs(", ", stdout);
     494  		PRINT_FIELD_X(*regs, ctr);
     495  	}
     496  	if (size >= offsetofend(TRACEE_REGS_STRUCT, link)) {
     497  		fputs(", ", stdout);
     498  		PRINT_FIELD_X(*regs, link);
     499  	}
     500  	if (size >= offsetofend(TRACEE_REGS_STRUCT, xer)) {
     501  		fputs(", ", stdout);
     502  		PRINT_FIELD_X(*regs, xer);
     503  	}
     504  	if (size >= offsetofend(TRACEE_REGS_STRUCT, ccr)) {
     505  		fputs(", ", stdout);
     506  		PRINT_FIELD_X(*regs, ccr);
     507  	}
     508  #  ifdef __powerpc64__
     509  	if (size >= offsetofend(TRACEE_REGS_STRUCT, softe)) {
     510  		fputs(", ", stdout);
     511  		PRINT_FIELD_X(*regs, softe);
     512  	}
     513  #  else
     514  	if (size >= offsetofend(TRACEE_REGS_STRUCT, mq)) {
     515  		fputs(", ", stdout);
     516  		PRINT_FIELD_X(*regs, mq);
     517  	}
     518  #  endif
     519  	if (size >= offsetofend(TRACEE_REGS_STRUCT, trap)) {
     520  		fputs(", ", stdout);
     521  		PRINT_FIELD_X(*regs, trap);
     522  	}
     523  	if (size >= offsetofend(TRACEE_REGS_STRUCT, dar)) {
     524  		fputs(", ", stdout);
     525  		PRINT_FIELD_X(*regs, dar);
     526  	}
     527  	if (size >= offsetofend(TRACEE_REGS_STRUCT, dsisr)) {
     528  		fputs(", ", stdout);
     529  		PRINT_FIELD_X(*regs, dsisr);
     530  	}
     531  	if (size >= offsetofend(TRACEE_REGS_STRUCT, result)) {
     532  		fputs(", ", stdout);
     533  		PRINT_FIELD_X(*regs, result);
     534  	}
     535  
     536  # elif defined __arm__
     537  
     538  	fputs("uregs=[", stdout);
     539  	for (unsigned int i = 0; i < ARRAY_SIZE(regs->uregs); ++i) {
     540  		if (size > i * sizeof(regs->uregs[i])) {
     541  			if (i)
     542  				fputs(", ", stdout);
     543  			PRINT_VAL_X(regs->uregs[i]);
     544  		}
     545  	}
     546  	fputs("]", stdout);
     547  
     548  # elif defined __arm64__ || defined __aarch64__
     549  
     550  	fputs("regs=[", stdout);
     551  	for (unsigned int i = 0; i < ARRAY_SIZE(regs->regs); ++i) {
     552  		if (size > i * sizeof(regs->regs[i])) {
     553  			if (i)
     554  				fputs(", ", stdout);
     555  			PRINT_VAL_X(regs->regs[i]);
     556  		}
     557  	}
     558  	fputs("]", stdout);
     559  	if (size >= offsetofend(TRACEE_REGS_STRUCT, sp)) {
     560  		fputs(", ", stdout);
     561  		PRINT_FIELD_X(*regs, sp);
     562  	}
     563  	if (size >= offsetofend(TRACEE_REGS_STRUCT, pc)) {
     564  		fputs(", ", stdout);
     565  		PRINT_FIELD_X(*regs, pc);
     566  	}
     567  	if (size >= offsetofend(TRACEE_REGS_STRUCT, pstate)) {
     568  		fputs(", ", stdout);
     569  		PRINT_FIELD_X(*regs, pstate);
     570  	}
     571  
     572  # elif defined __s390__ || defined __s390x__
     573  
     574  	fputs("psw={", stdout);
     575  	PRINT_FIELD_X(regs->psw, mask);
     576  	if (size >= sizeof(regs->psw)) {
     577  		fputs(", ", stdout);
     578  		PRINT_FIELD_X(regs->psw, addr);
     579  	}
     580  	fputs("}", stdout);
     581  	if (size > offsetof(TRACEE_REGS_STRUCT, gprs)) {
     582  		const size_t len = size - offsetof(TRACEE_REGS_STRUCT, gprs);
     583  		fputs(", gprs=[", stdout);
     584  		for (unsigned int i = 0; i < ARRAY_SIZE(regs->gprs); ++i) {
     585  			if (len > i * sizeof(regs->gprs[i])) {
     586  				if (i)
     587  					fputs(", ", stdout);
     588  				PRINT_VAL_X(regs->gprs[i]);
     589  			}
     590  		}
     591  		fputs("]", stdout);
     592  	}
     593  	if (size > offsetof(TRACEE_REGS_STRUCT, acrs)) {
     594  		const size_t len = size - offsetof(TRACEE_REGS_STRUCT, acrs);
     595  		fputs(", acrs=[", stdout);
     596  		for (unsigned int i = 0; i < ARRAY_SIZE(regs->acrs); ++i) {
     597  			if (len > i * sizeof(regs->acrs[i])) {
     598  				if (i)
     599  					fputs(", ", stdout);
     600  				PRINT_VAL_X(regs->acrs[i]);
     601  			}
     602  		}
     603  		fputs("]", stdout);
     604  	}
     605  	if (size >= offsetofend(TRACEE_REGS_STRUCT, orig_gpr2)) {
     606  		fputs(", ", stdout);
     607  		PRINT_FIELD_X(*regs, orig_gpr2);
     608  	}
     609  
     610  # elif defined __sparc__
     611  
     612  	fputs("g=[", stdout);
     613  	for (unsigned int j = 0; j < ARRAY_SIZE(regs->g); ++j) {
     614  		if (size > j * sizeof(regs->g[j])) {
     615  			if (j)
     616  				fputs(", ", stdout);
     617  			PRINT_VAL_X(regs->g[j]);
     618  		}
     619  	}
     620  	fputs("]", stdout);
     621  	if (size > offsetof(TRACEE_REGS_STRUCT, o)) {
     622  		const size_t len = size - offsetof(TRACEE_REGS_STRUCT, o);
     623  		fputs(", o=[", stdout);
     624  		for (unsigned int j = 0; j < ARRAY_SIZE(regs->o); ++j) {
     625  			if (len > j * sizeof(regs->o[j])) {
     626  				if (j)
     627  					fputs(", ", stdout);
     628  				PRINT_VAL_X(regs->o[j]);
     629  			}
     630  		}
     631  		fputs("]", stdout);
     632  	}
     633  	if (size > offsetof(TRACEE_REGS_STRUCT, l)) {
     634  		const size_t len = size - offsetof(TRACEE_REGS_STRUCT, l);
     635  		fputs(", l=[", stdout);
     636  		for (unsigned int j = 0; j < ARRAY_SIZE(regs->l); ++j) {
     637  			if (len > j * sizeof(regs->l[j])) {
     638  				if (j)
     639  					fputs(", ", stdout);
     640  				PRINT_VAL_X(regs->l[j]);
     641  			}
     642  		}
     643  		fputs("]", stdout);
     644  	}
     645  	if (size > offsetof(TRACEE_REGS_STRUCT, i)) {
     646  		const size_t len = size - offsetof(TRACEE_REGS_STRUCT, i);
     647  		fputs(", i=[", stdout);
     648  		for (unsigned int j = 0; j < ARRAY_SIZE(regs->i); ++j) {
     649  			if (len > j * sizeof(regs->i[j])) {
     650  				if (j)
     651  					fputs(", ", stdout);
     652  				PRINT_VAL_X(regs->i[j]);
     653  			}
     654  		}
     655  		fputs("]", stdout);
     656  	}
     657  #  ifdef __arch64__
     658  	if (size >= offsetofend(TRACEE_REGS_STRUCT, tstate)) {
     659  		fputs(", ", stdout);
     660  		PRINT_FIELD_X(*regs, tstate);
     661  	}
     662  	if (size >= offsetofend(TRACEE_REGS_STRUCT, tpc)) {
     663  		fputs(", ", stdout);
     664  		PRINT_FIELD_X(*regs, tpc);
     665  	}
     666  	if (size >= offsetofend(TRACEE_REGS_STRUCT, tnpc)) {
     667  		fputs(", ", stdout);
     668  		PRINT_FIELD_X(*regs, tnpc);
     669  	}
     670  	if (size >= offsetofend(TRACEE_REGS_STRUCT, y)) {
     671  		fputs(", ", stdout);
     672  		PRINT_FIELD_X(*regs, y);
     673  	}
     674  #  else /* sparc32 */
     675  	if (size >= offsetofend(TRACEE_REGS_STRUCT, psr)) {
     676  		fputs(", ", stdout);
     677  		PRINT_FIELD_X(*regs, psr);
     678  	}
     679  	if (size >= offsetofend(TRACEE_REGS_STRUCT, pc)) {
     680  		fputs(", ", stdout);
     681  		PRINT_FIELD_X(*regs, pc);
     682  	}
     683  	if (size >= offsetofend(TRACEE_REGS_STRUCT, npc)) {
     684  		fputs(", ", stdout);
     685  		PRINT_FIELD_X(*regs, npc);
     686  	}
     687  	if (size >= offsetofend(TRACEE_REGS_STRUCT, y)) {
     688  		fputs(", ", stdout);
     689  		PRINT_FIELD_X(*regs, y);
     690  	}
     691  	if (size >= offsetofend(TRACEE_REGS_STRUCT, wim)) {
     692  		fputs(", ", stdout);
     693  		PRINT_FIELD_X(*regs, wim);
     694  	}
     695  	if (size >= offsetofend(TRACEE_REGS_STRUCT, tbr)) {
     696  		fputs(", ", stdout);
     697  		PRINT_FIELD_X(*regs, tbr);
     698  	}
     699  #  endif
     700  
     701  # elif defined __riscv
     702  
     703  	PRINT_FIELD_X(*regs, pc);
     704  	if (size >= offsetofend(TRACEE_REGS_STRUCT, ra)) {
     705  		fputs(", ", stdout);
     706  		PRINT_FIELD_X(*regs, ra);
     707  	}
     708  	if (size >= offsetofend(TRACEE_REGS_STRUCT, sp)) {
     709  		fputs(", ", stdout);
     710  		PRINT_FIELD_X(*regs, sp);
     711  	}
     712  	if (size >= offsetofend(TRACEE_REGS_STRUCT, gp)) {
     713  		fputs(", ", stdout);
     714  		PRINT_FIELD_X(*regs, gp);
     715  	}
     716  	if (size >= offsetofend(TRACEE_REGS_STRUCT, tp)) {
     717  		fputs(", ", stdout);
     718  		PRINT_FIELD_X(*regs, tp);
     719  	}
     720  	if (size >= offsetofend(TRACEE_REGS_STRUCT, t0)) {
     721  		fputs(", ", stdout);
     722  		PRINT_FIELD_X(*regs, t0);
     723  	}
     724  	if (size >= offsetofend(TRACEE_REGS_STRUCT, t1)) {
     725  		fputs(", ", stdout);
     726  		PRINT_FIELD_X(*regs, t1);
     727  	}
     728  	if (size >= offsetofend(TRACEE_REGS_STRUCT, t2)) {
     729  		fputs(", ", stdout);
     730  		PRINT_FIELD_X(*regs, t2);
     731  	}
     732  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s0)) {
     733  		fputs(", ", stdout);
     734  		PRINT_FIELD_X(*regs, s0);
     735  	}
     736  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s1)) {
     737  		fputs(", ", stdout);
     738  		PRINT_FIELD_X(*regs, s1);
     739  	}
     740  	if (size >= offsetofend(TRACEE_REGS_STRUCT, a0)) {
     741  		fputs(", ", stdout);
     742  		PRINT_FIELD_X(*regs, a0);
     743  	}
     744  	if (size >= offsetofend(TRACEE_REGS_STRUCT, a1)) {
     745  		fputs(", ", stdout);
     746  		PRINT_FIELD_X(*regs, a1);
     747  	}
     748  	if (size >= offsetofend(TRACEE_REGS_STRUCT, a2)) {
     749  		fputs(", ", stdout);
     750  		PRINT_FIELD_X(*regs, a2);
     751  	}
     752  	if (size >= offsetofend(TRACEE_REGS_STRUCT, a3)) {
     753  		fputs(", ", stdout);
     754  		PRINT_FIELD_X(*regs, a3);
     755  	}
     756  	if (size >= offsetofend(TRACEE_REGS_STRUCT, a4)) {
     757  		fputs(", ", stdout);
     758  		PRINT_FIELD_X(*regs, a4);
     759  	}
     760  	if (size >= offsetofend(TRACEE_REGS_STRUCT, a5)) {
     761  		fputs(", ", stdout);
     762  		PRINT_FIELD_X(*regs, a5);
     763  	}
     764  	if (size >= offsetofend(TRACEE_REGS_STRUCT, a6)) {
     765  		fputs(", ", stdout);
     766  		PRINT_FIELD_X(*regs, a6);
     767  	}
     768  	if (size >= offsetofend(TRACEE_REGS_STRUCT, a7)) {
     769  		fputs(", ", stdout);
     770  		PRINT_FIELD_X(*regs, a7);
     771  	}
     772  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s2)) {
     773  		fputs(", ", stdout);
     774  		PRINT_FIELD_X(*regs, s2);
     775  	}
     776  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s3)) {
     777  		fputs(", ", stdout);
     778  		PRINT_FIELD_X(*regs, s3);
     779  	}
     780  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s4)) {
     781  		fputs(", ", stdout);
     782  		PRINT_FIELD_X(*regs, s4);
     783  	}
     784  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s5)) {
     785  		fputs(", ", stdout);
     786  		PRINT_FIELD_X(*regs, s5);
     787  	}
     788  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s6)) {
     789  		fputs(", ", stdout);
     790  		PRINT_FIELD_X(*regs, s6);
     791  	}
     792  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s7)) {
     793  		fputs(", ", stdout);
     794  		PRINT_FIELD_X(*regs, s7);
     795  	}
     796  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s8)) {
     797  		fputs(", ", stdout);
     798  		PRINT_FIELD_X(*regs, s8);
     799  	}
     800  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s9)) {
     801  		fputs(", ", stdout);
     802  		PRINT_FIELD_X(*regs, s9);
     803  	}
     804  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s10)) {
     805  		fputs(", ", stdout);
     806  		PRINT_FIELD_X(*regs, s10);
     807  	}
     808  	if (size >= offsetofend(TRACEE_REGS_STRUCT, s11)) {
     809  		fputs(", ", stdout);
     810  		PRINT_FIELD_X(*regs, s11);
     811  	}
     812  	if (size >= offsetofend(TRACEE_REGS_STRUCT, t3)) {
     813  		fputs(", ", stdout);
     814  		PRINT_FIELD_X(*regs, t3);
     815  	}
     816  	if (size >= offsetofend(TRACEE_REGS_STRUCT, t4)) {
     817  		fputs(", ", stdout);
     818  		PRINT_FIELD_X(*regs, t4);
     819  	}
     820  	if (size >= offsetofend(TRACEE_REGS_STRUCT, t5)) {
     821  		fputs(", ", stdout);
     822  		PRINT_FIELD_X(*regs, t5);
     823  	}
     824  	if (size >= offsetofend(TRACEE_REGS_STRUCT, t6)) {
     825  		fputs(", ", stdout);
     826  		PRINT_FIELD_X(*regs, t6);
     827  	}
     828  
     829  # elif defined __mips__
     830  
     831  	if (size > offsetof(TRACEE_REGS_STRUCT, regs)) {
     832  		const size_t len = size - offsetof(TRACEE_REGS_STRUCT, regs);
     833  		fputs("regs=[", stdout);
     834  		for (unsigned int i = 0; i < ARRAY_SIZE(regs->regs); ++i) {
     835  			if (len > i * sizeof(regs->regs[i])) {
     836  				if (i)
     837  					fputs(", ", stdout);
     838  				PRINT_VAL_X(regs->regs[i]);
     839  			}
     840  		}
     841  		fputs("]", stdout);
     842  	}
     843  	if (size >= offsetofend(TRACEE_REGS_STRUCT, lo)) {
     844  		fputs(", ", stdout);
     845  		PRINT_FIELD_X(*regs, lo);
     846  	}
     847  	if (size >= offsetofend(TRACEE_REGS_STRUCT, hi)) {
     848  		fputs(", ", stdout);
     849  		PRINT_FIELD_X(*regs, hi);
     850  	}
     851  	if (size >= offsetofend(TRACEE_REGS_STRUCT, cp0_epc)) {
     852  		fputs(", ", stdout);
     853  		PRINT_FIELD_X(*regs, cp0_epc);
     854  	}
     855  	if (size >= offsetofend(TRACEE_REGS_STRUCT, cp0_badvaddr)) {
     856  		fputs(", ", stdout);
     857  		PRINT_FIELD_X(*regs, cp0_badvaddr);
     858  	}
     859  	if (size >= offsetofend(TRACEE_REGS_STRUCT, cp0_status)) {
     860  		fputs(", ", stdout);
     861  		PRINT_FIELD_X(*regs, cp0_status);
     862  	}
     863  	if (size >= offsetofend(TRACEE_REGS_STRUCT, cp0_cause)) {
     864  		fputs(", ", stdout);
     865  		PRINT_FIELD_X(*regs, cp0_cause);
     866  	}
     867  
     868  # elif defined __loongarch__
     869  
     870  	if (size > offsetof(TRACEE_REGS_STRUCT, regs)) {
     871  		const size_t len = size - offsetof(TRACEE_REGS_STRUCT, regs);
     872  		fputs("regs=[", stdout);
     873  		for (unsigned int i = 0; i < ARRAY_SIZE(regs->regs); ++i) {
     874  			if (len > i * sizeof(regs->regs[i])) {
     875  				if (i)
     876  					fputs(", ", stdout);
     877  				PRINT_VAL_X(regs->regs[i]);
     878  			}
     879  		}
     880  		fputs("]", stdout);
     881  	}
     882  	if (size >= offsetofend(TRACEE_REGS_STRUCT, orig_a0)) {
     883  		fputs(", ", stdout);
     884  		PRINT_FIELD_X(*regs, orig_a0);
     885  	}
     886  	if (size >= offsetofend(TRACEE_REGS_STRUCT, csr_era)) {
     887  		fputs(", ", stdout);
     888  		PRINT_FIELD_X(*regs, csr_era);
     889  	}
     890  	if (size >= offsetofend(TRACEE_REGS_STRUCT, csr_badv)) {
     891  		fputs(", ", stdout);
     892  		PRINT_FIELD_X(*regs, csr_badv);
     893  	}
     894  	if (size > offsetof(TRACEE_REGS_STRUCT, reserved)) {
     895  		const size_t len = size - offsetof(TRACEE_REGS_STRUCT, reserved);
     896  		fputs(", reserved=[", stdout);
     897  		for (unsigned int i = 0; i < ARRAY_SIZE(regs->reserved); ++i) {
     898  			if (len > i * sizeof(regs->reserved[i])) {
     899  				if (i)
     900  					fputs(", ", stdout);
     901  				PRINT_VAL_X(regs->reserved[i]);
     902  			}
     903  		}
     904  		fputs("]", stdout);
     905  	}
     906  
     907  # endif /*
     908  	   __aarch64__ ||
     909  	   __arm64__ ||
     910  	   __arm__ ||
     911  	   __i386__ ||
     912  	   __loongarch__ ||
     913  	   __mips__ ||
     914  	   __powerpc64__ ||
     915  	   __powerpc__ ||
     916  	   __riscv ||
     917  	   __s390__ ||
     918  	   __s390x__ ||
     919  	   __sparc__ ||
     920  	   __x86_64__
     921  	 */
     922  
     923  	if (size > sizeof(*regs))
     924  		fputs(", ...", stdout);
     925  	fputs("}", stdout);
     926  
     927  #else /* !TRACEE_REGS_STRUCT */
     928  
     929  	printf("%p", rs);
     930  
     931  #endif /* TRACEE_REGS_STRUCT */
     932  }
     933  
     934  #ifdef PTRACE_GETREGS
     935  static void
     936  print_pt_regs(const void *const rs, const size_t size)
     937  {
     938  # if defined __mips__
     939  
     940  	const struct pt_regs *const regs = rs;
     941  	if (size != sizeof(*regs))
     942  		error_msg_and_fail("expected size %zu, got size %zu",
     943  				   sizeof(*regs), size);
     944  	fputs("{regs=[", stdout);
     945  	for (unsigned int j = 0; j < ARRAY_SIZE(regs->regs); ++j) {
     946  		if (j)
     947  			fputs(", ", stdout);
     948  		printf("%#llx", (unsigned long long) regs->regs[j]);
     949  	}
     950  	fputs("], ", stdout);
     951  	PRINT_FIELD_X(*regs, lo);
     952  	fputs(", ", stdout);
     953  	PRINT_FIELD_X(*regs, hi);
     954  	fputs(", ", stdout);
     955  	PRINT_FIELD_X(*regs, cp0_epc);
     956  	fputs(", ", stdout);
     957  	PRINT_FIELD_X(*regs, cp0_badvaddr);
     958  	fputs(", ", stdout);
     959  	PRINT_FIELD_X(*regs, cp0_status);
     960  	fputs(", ", stdout);
     961  	PRINT_FIELD_X(*regs, cp0_cause);
     962  	fputs("}", stdout);
     963  
     964  # elif defined __sparc__
     965  
     966  #  ifdef __arch64__
     967  	printf("%p", rs);
     968  #  else
     969  	const struct {
     970  		unsigned int psr;
     971  		unsigned int pc;
     972  		unsigned int npc;
     973  		unsigned int y;
     974  		unsigned int u_regs[15];
     975  	} *const regs = rs;
     976  	if (size != sizeof(*regs))
     977  		error_msg_and_fail("expected size %zu, got size %zu",
     978  				   sizeof(*regs), size);
     979  	printf("{psr=%#x, pc=%#x, npc=%#x, y=%#x, u_regs=[",
     980  	       regs->psr, regs->pc, regs->npc, regs->y);
     981  	for (unsigned int j = 0; j < ARRAY_SIZE(regs->u_regs); ++j) {
     982  		if (j)
     983  			fputs(", ", stdout);
     984  		printf("%#x", regs->u_regs[j]);
     985  	}
     986  	fputs("]}", stdout);
     987  #  endif /* !__arch64__ */
     988  
     989  # elif defined TRACEE_REGS_STRUCT
     990  
     991  	if (size != sizeof(TRACEE_REGS_STRUCT))
     992  		error_msg_and_fail("expected size %zu, got size %zu",
     993  				   sizeof(TRACEE_REGS_STRUCT), size);
     994  	print_prstatus_regset(rs, size);
     995  
     996  # else /* !TRACEE_REGS_STRUCT */
     997  
     998  	printf("%p", rs);
     999  
    1000  # endif
    1001  }
    1002  
    1003  static void
    1004  do_getregs_setregs(const int pid,
    1005  		   void *const regbuf,
    1006  		   const unsigned int regsize,
    1007  		   unsigned int *const actual_size)
    1008  {
    1009  	if (do_ptrace_regs(PTRACE_GETREGS, pid, (uintptr_t) regbuf)) {
    1010  		printf("ptrace(" XLAT_FMT ", %d, %p) = %s\n",
    1011  		       XLAT_ARGS(PTRACE_GETREGS), pid, regbuf, errstr);
    1012  		return;	/* skip PTRACE_SETREGS */
    1013  	} else {
    1014  		printf("ptrace(" XLAT_FMT ", %d, ",
    1015  		       XLAT_ARGS(PTRACE_GETREGS), pid);
    1016  		print_pt_regs(regbuf, regsize);
    1017  		printf(") = %s\n", errstr);
    1018  		if (*actual_size)
    1019  			return;	/* skip PTRACE_SETREGS */
    1020  		else
    1021  			*actual_size = regsize;
    1022  	}
    1023  
    1024  # if defined __sparc__ && !defined __arch64__
    1025  	/*
    1026  	 * On sparc32 PTRACE_SETREGS of size greater than 120
    1027  	 * has interesting side effects.
    1028  	 */
    1029  	if (regsize > 120)
    1030  		return;
    1031  # endif /* __sparc__ && !__arch64__ */
    1032  
    1033  	do_ptrace_regs(PTRACE_SETREGS, pid, (uintptr_t) regbuf);
    1034  	printf("ptrace(" XLAT_FMT ", %d, ", XLAT_ARGS(PTRACE_SETREGS), pid);
    1035  	print_pt_regs(regbuf, regsize);
    1036  	printf(") = %s\n", errstr);
    1037  }
    1038  #endif /* PTRACE_GETREGS */
    1039  
    1040  #ifdef PTRACE_GETREGS64
    1041  static void
    1042  print_pt_regs64(const void *const rs, const size_t size)
    1043  {
    1044  # if defined __powerpc__ || defined __powerpc64__
    1045  #  ifdef __powerpc64__
    1046  	const struct pt_regs *const regs = rs;
    1047  #  else /* __powerpc__ */
    1048  	const struct {
    1049  		unsigned long long gpr[32];
    1050  		unsigned long long nip;
    1051  		unsigned long long msr;
    1052  		unsigned long long orig_gpr3;
    1053  		unsigned long long ctr;
    1054  		unsigned long long link;
    1055  		unsigned long long xer;
    1056  		unsigned long long ccr;
    1057  		unsigned long long softe;
    1058  		unsigned long long trap;
    1059  		unsigned long long dar;
    1060  		unsigned long long dsisr;
    1061  		unsigned long long result;
    1062  	} *const regs = rs;
    1063  #  endif /* __powerpc__ */
    1064  	if (size != sizeof(*regs))
    1065  		error_msg_and_fail("expected size %zu, got size %zu",
    1066  				   sizeof(*regs), size);
    1067  	for (unsigned int j = 0; j < ARRAY_SIZE(regs->gpr); ++j)
    1068  		printf("%s%#llx", j ? ", " : "{gpr=[",
    1069  		       (unsigned long long) regs->gpr[j]);
    1070  	printf("], nip=%#llx", (unsigned long long) regs->nip);
    1071  	printf(", msr=%#llx", (unsigned long long) regs->msr);
    1072  	printf(", orig_gpr3=%#llx", (unsigned long long) regs->orig_gpr3);
    1073  	printf(", ctr=%#llx", (unsigned long long) regs->ctr);
    1074  	printf(", link=%#llx", (unsigned long long) regs->link);
    1075  	printf(", xer=%#llx", (unsigned long long) regs->xer);
    1076  	printf(", ccr=%#llx", (unsigned long long) regs->ccr);
    1077  	printf(", softe=%#llx", (unsigned long long) regs->softe);
    1078  	printf(", trap=%#llx", (unsigned long long) regs->trap);
    1079  	printf(", dar=%#llx", (unsigned long long) regs->dar);
    1080  	printf(", dsisr=%#llx", (unsigned long long) regs->dsisr);
    1081  	printf(", result=%#llx}", (unsigned long long) regs->result);
    1082  
    1083  # elif defined __sparc__ && defined __arch64__
    1084  
    1085  	const struct {
    1086  		unsigned long u_regs[16];
    1087  		unsigned long tstate;
    1088  		unsigned long tpc;
    1089  		unsigned long tnpc;
    1090  	} *const regs = rs;
    1091  	if (size != sizeof(*regs))
    1092  		error_msg_and_fail("expected size %zu, got size %zu",
    1093  				   sizeof(*regs), size);
    1094  	for (unsigned int j = 0; j < ARRAY_SIZE(regs->u_regs); ++j)
    1095  		printf("%s%#lx", j ? ", " : "{u_regs=[", regs->u_regs[j]);
    1096  	printf("], tstate=%#lx", regs->tstate);
    1097  	printf(", tpc=%#lx", regs->tpc);
    1098  	printf(", tnpc=%#lx}", regs->tnpc);
    1099  
    1100  # else /* !(__powerpc__ || __powerpc64__ || (__sparc__ && __arch64__)) */
    1101  
    1102  	printf("%p", rs);
    1103  
    1104  # endif
    1105  }
    1106  
    1107  static void
    1108  do_getregs64_setregs64(const int pid,
    1109  		       void *const regbuf,
    1110  		       const unsigned int regsize,
    1111  		       unsigned int *const actual_size)
    1112  {
    1113  	if (do_ptrace_regs(PTRACE_GETREGS64, pid, (uintptr_t) regbuf)) {
    1114  		printf("ptrace(" XLAT_FMT ", %d, %p) = %s\n",
    1115  		       XLAT_ARGS(PTRACE_GETREGS64), pid, regbuf, errstr);
    1116  		return;	/* skip PTRACE_SETREGS64 */
    1117  	} else {
    1118  		printf("ptrace(" XLAT_FMT ", %d, ",
    1119  		       XLAT_ARGS(PTRACE_GETREGS64), pid);
    1120  		print_pt_regs64(regbuf, regsize);
    1121  		printf(") = %s\n", errstr);
    1122  		if (*actual_size)
    1123  			return;	/* skip PTRACE_SETREGS64 */
    1124  		else
    1125  			*actual_size = regsize;
    1126  	}
    1127  
    1128  	do_ptrace_regs(PTRACE_SETREGS64, pid, (uintptr_t) regbuf);
    1129  	printf("ptrace(" XLAT_FMT ", %d, ", XLAT_ARGS(PTRACE_SETREGS64), pid);
    1130  	print_pt_regs64(regbuf, regsize);
    1131  	printf(") = %s\n", errstr);
    1132  }
    1133  #endif /* PTRACE_GETREGS64 */
    1134  
    1135  #if defined __powerpc__ || defined __powerpc64__
    1136  # define FPREGSET_SLOT_SIZE sizeof(uint64_t)
    1137  #else
    1138  # define FPREGSET_SLOT_SIZE sizeof(kernel_ulong_t)
    1139  #endif
    1140  
    1141  #undef TRACEE_REGS_STRUCT
    1142  #if defined __x86_64__ || defined __i386__
    1143  # define TRACEE_REGS_STRUCT struct user_fpregs_struct
    1144  #elif defined __powerpc__ || defined __powerpc64__
    1145  typedef struct {
    1146  	uint64_t fpr[32];
    1147  	uint64_t fpscr;
    1148  } ppc_fpregs_struct;
    1149  # define TRACEE_REGS_STRUCT ppc_fpregs_struct
    1150  #elif defined __loongarch__
    1151  # define TRACEE_REGS_STRUCT struct user_fp_state
    1152  #endif
    1153  
    1154  static void
    1155  print_fpregset(const void *const rs, const size_t size)
    1156  {
    1157  	if (!size || size % FPREGSET_SLOT_SIZE) {
    1158  		printf("%p", rs);
    1159  		return;
    1160  	}
    1161  
    1162  #ifdef TRACEE_REGS_STRUCT
    1163  	const TRACEE_REGS_STRUCT *const regs = rs;
    1164  
    1165  	fputs("{", stdout);
    1166  
    1167  # if defined __i386__
    1168  
    1169  	PRINT_FIELD_X(*regs, cwd);
    1170  	if (size >= offsetofend(TRACEE_REGS_STRUCT, swd)) {
    1171  		fputs(", ", stdout);
    1172  		PRINT_FIELD_X(*regs, swd);
    1173  	}
    1174  	if (size >= offsetofend(TRACEE_REGS_STRUCT, twd)) {
    1175  		fputs(", ", stdout);
    1176  		PRINT_FIELD_X(*regs, twd);
    1177  	}
    1178  	if (size >= offsetofend(TRACEE_REGS_STRUCT, fip)) {
    1179  		fputs(", ", stdout);
    1180  		PRINT_FIELD_X(*regs, fip);
    1181  	}
    1182  	if (size >= offsetofend(TRACEE_REGS_STRUCT, fcs)) {
    1183  		fputs(", ", stdout);
    1184  		PRINT_FIELD_X(*regs, fcs);
    1185  	}
    1186  	if (size >= offsetofend(TRACEE_REGS_STRUCT, foo)) {
    1187  		fputs(", ", stdout);
    1188  		PRINT_FIELD_X(*regs, foo);
    1189  	}
    1190  	if (size >= offsetofend(TRACEE_REGS_STRUCT, fos)) {
    1191  		fputs(", ", stdout);
    1192  		PRINT_FIELD_X(*regs, fos);
    1193  	}
    1194  	if (size > offsetof(TRACEE_REGS_STRUCT, st_space)) {
    1195  		const size_t len =
    1196  			size - offsetof(TRACEE_REGS_STRUCT, st_space);
    1197  		fputs(", st_space=[", stdout);
    1198  		for (unsigned int i = 0; i < ARRAY_SIZE(regs->st_space); ++i) {
    1199  			if (len > i * sizeof(regs->st_space[i])) {
    1200  				if (i)
    1201  					fputs(", ", stdout);
    1202  				PRINT_VAL_X(regs->st_space[i]);
    1203  			}
    1204  		}
    1205  		fputs("]", stdout);
    1206  	}
    1207  
    1208  # elif defined __x86_64__
    1209  
    1210  	PRINT_FIELD_X(*regs, cwd);
    1211  	if (size >= offsetofend(TRACEE_REGS_STRUCT, swd)) {
    1212  		fputs(", ", stdout);
    1213  		PRINT_FIELD_X(*regs, swd);
    1214  	}
    1215  	if (size >= offsetofend(TRACEE_REGS_STRUCT, ftw)) {
    1216  		fputs(", ", stdout);
    1217  		PRINT_FIELD_X(*regs, ftw);
    1218  	}
    1219  	if (size >= offsetofend(TRACEE_REGS_STRUCT, fop)) {
    1220  		fputs(", ", stdout);
    1221  		PRINT_FIELD_X(*regs, fop);
    1222  	}
    1223  	if (size >= offsetofend(TRACEE_REGS_STRUCT, rip)) {
    1224  		fputs(", ", stdout);
    1225  		PRINT_FIELD_X(*regs, rip);
    1226  	}
    1227  	if (size >= offsetofend(TRACEE_REGS_STRUCT, rdp)) {
    1228  		fputs(", ", stdout);
    1229  		PRINT_FIELD_X(*regs, rdp);
    1230  	}
    1231  	if (size >= offsetofend(TRACEE_REGS_STRUCT, mxcsr)) {
    1232  		fputs(", ", stdout);
    1233  		PRINT_FIELD_X(*regs, mxcsr);
    1234  	}
    1235  	if (size >= offsetofend(TRACEE_REGS_STRUCT, mxcr_mask)) {
    1236  		fputs(", ", stdout);
    1237  		PRINT_FIELD_X(*regs, mxcr_mask);
    1238  	}
    1239  	if (size > offsetof(TRACEE_REGS_STRUCT, st_space)) {
    1240  		const size_t len =
    1241  			size - offsetof(TRACEE_REGS_STRUCT, st_space);
    1242  		fputs(", st_space=[", stdout);
    1243  		for (unsigned int i = 0; i < ARRAY_SIZE(regs->st_space); ++i) {
    1244  			if (len > i * sizeof(regs->st_space[i])) {
    1245  				if (i)
    1246  					fputs(", ", stdout);
    1247  				PRINT_VAL_X(regs->st_space[i]);
    1248  			}
    1249  		}
    1250  		fputs("]", stdout);
    1251  	}
    1252  	if (size > offsetof(TRACEE_REGS_STRUCT, xmm_space)) {
    1253  		const size_t len =
    1254  			size - offsetof(TRACEE_REGS_STRUCT, xmm_space);
    1255  		fputs(", xmm_space=[", stdout);
    1256  		for (unsigned int i = 0; i < ARRAY_SIZE(regs->xmm_space); ++i) {
    1257  			if (len > i * sizeof(regs->xmm_space[i])) {
    1258  				if (i)
    1259  					fputs(", ", stdout);
    1260  				PRINT_VAL_X(regs->xmm_space[i]);
    1261  			}
    1262  		}
    1263  		fputs("]", stdout);
    1264  	}
    1265  	if (size > offsetof(TRACEE_REGS_STRUCT, padding)) {
    1266  		const size_t len =
    1267  			size - offsetof(TRACEE_REGS_STRUCT, padding);
    1268  		fputs(", padding=[", stdout);
    1269  		for (unsigned int i = 0; i < ARRAY_SIZE(regs->padding); ++i) {
    1270  			if (len > i * sizeof(regs->padding[i])) {
    1271  				if (i)
    1272  					fputs(", ", stdout);
    1273  				PRINT_VAL_X(regs->padding[i]);
    1274  			}
    1275  		}
    1276  		fputs("]", stdout);
    1277  	}
    1278  
    1279  # elif defined __powerpc__ || defined __powerpc64__
    1280  
    1281  	fputs("fpr=[", stdout);
    1282  	for (unsigned int i = 0; i < ARRAY_SIZE(regs->fpr); ++i) {
    1283  		if (size > i * sizeof(regs->fpr[i])) {
    1284  			if (i)
    1285  				fputs(", ", stdout);
    1286  			PRINT_VAL_X(regs->fpr[i]);
    1287  		}
    1288  	}
    1289  	fputs("]", stdout);
    1290  	if (size >= offsetofend(TRACEE_REGS_STRUCT, fpscr)) {
    1291  		fputs(", ", stdout);
    1292  		PRINT_FIELD_X(*regs, fpscr);
    1293  	}
    1294  
    1295  # elif defined __loongarch__
    1296  
    1297  	fputs("fpr=[", stdout);
    1298  	for (unsigned int i = 0; i < ARRAY_SIZE(regs->fpr); ++i) {
    1299  		if (size > i * sizeof(regs->fpr[i])) {
    1300  			if (i)
    1301  				fputs(", ", stdout);
    1302  			PRINT_VAL_X(regs->fpr[i]);
    1303  		}
    1304  	}
    1305  	fputs("]", stdout);
    1306  	if (size >= offsetofend(TRACEE_REGS_STRUCT, fcc)) {
    1307  		fputs(", ", stdout);
    1308  		PRINT_FIELD_X(*regs, fcc);
    1309  	}
    1310  	if (size >= offsetofend(TRACEE_REGS_STRUCT, fcsr)) {
    1311  		fputs(", ", stdout);
    1312  		PRINT_FIELD_X(*regs, fcsr);
    1313  	}
    1314  
    1315  # endif /*
    1316  	   __i386__ ||
    1317  	   __loongarch__ ||
    1318  	   __powerpc64__ ||
    1319  	   __powerpc__ ||
    1320  	   __x86_64__
    1321  	 */
    1322  
    1323  	if (size > sizeof(*regs))
    1324  		fputs(", ...", stdout);
    1325  	fputs("}", stdout);
    1326  
    1327  #else /* !TRACEE_REGS_STRUCT */
    1328  
    1329  	printf("%p", rs);
    1330  
    1331  #endif /* TRACEE_REGS_STRUCT */
    1332  }
    1333  
    1334  #ifdef PTRACE_GETFPREGS
    1335  static void
    1336  print_pt_fpregs(const void *const rs, const size_t size)
    1337  {
    1338  # ifdef TRACEE_REGS_STRUCT
    1339  
    1340  	if (size != sizeof(TRACEE_REGS_STRUCT))
    1341  		error_msg_and_fail("expected size %zu, got size %zu",
    1342  				   sizeof(TRACEE_REGS_STRUCT), size);
    1343  	print_fpregset(rs, size);
    1344  
    1345  # else /* !TRACEE_REGS_STRUCT */
    1346  
    1347  	printf("%p", rs);
    1348  
    1349  # endif
    1350  }
    1351  
    1352  static void
    1353  do_getfpregs_setfpregs(const int pid,
    1354  		       void *const regbuf,
    1355  		       const unsigned int regsize,
    1356  		       unsigned int *const actual_size)
    1357  {
    1358  	if (do_ptrace_regs(PTRACE_GETFPREGS, pid, (uintptr_t) regbuf)) {
    1359  		printf("ptrace(" XLAT_FMT ", %d, %p) = %s\n",
    1360  		       XLAT_ARGS(PTRACE_GETFPREGS), pid, regbuf, errstr);
    1361  		return;	/* skip PTRACE_SETFPREGS */
    1362  	} else {
    1363  		printf("ptrace(" XLAT_FMT ", %d, ",
    1364  		       XLAT_ARGS(PTRACE_GETFPREGS), pid);
    1365  		print_pt_fpregs(regbuf, regsize);
    1366  		printf(") = %s\n", errstr);
    1367  		if (*actual_size)
    1368  			return;	/* skip PTRACE_SETFPREGS */
    1369  		else
    1370  			*actual_size = regsize;
    1371  	}
    1372  
    1373  	do_ptrace_regs(PTRACE_SETFPREGS, pid, (uintptr_t) regbuf);
    1374  	printf("ptrace(" XLAT_FMT ", %d, ", XLAT_ARGS(PTRACE_SETFPREGS), pid);
    1375  	print_pt_fpregs(regbuf, regsize);
    1376  	printf(") = %s\n", errstr);
    1377  }
    1378  #endif /* PTRACE_GETFPREGS */
    1379  
    1380  static void
    1381  do_getregset_setregset(const int pid,
    1382  		       const unsigned int nt,
    1383  		       const char *const nt_str,
    1384  		       void *const regbuf,
    1385  		       const unsigned int regsize,
    1386  		       unsigned int *actual_size,
    1387  		       struct iovec *const iov,
    1388  		       void (*print_regset_fn)(const void *, size_t))
    1389  {
    1390  	iov->iov_base = regbuf;
    1391  	iov->iov_len = regsize;
    1392  	do_ptrace(PTRACE_GETREGSET, pid, nt, (uintptr_t) iov);
    1393  	if (iov->iov_len == regsize) {
    1394  		printf("ptrace(" XLAT_FMT ", %d, " XLAT_FMT ", {iov_base=",
    1395  		       XLAT_ARGS(PTRACE_GETREGSET), pid, XLAT_SEL(nt, nt_str));
    1396  		print_regset_fn(iov->iov_base, iov->iov_len);
    1397  		printf(", iov_len=%lu}) = %s\n",
    1398  		       (unsigned long) iov->iov_len, errstr);
    1399  		if (*actual_size)
    1400  			return;	/* skip PTRACE_SETREGSET */
    1401  	} else {
    1402  		printf("ptrace(" XLAT_FMT ", %d, " XLAT_FMT ", {iov_base=",
    1403  		       XLAT_ARGS(PTRACE_GETREGSET), pid, XLAT_SEL(nt, nt_str));
    1404  		print_regset_fn(iov->iov_base, iov->iov_len);
    1405  		printf(", iov_len=%u => %lu}) = %s\n",
    1406  		       regsize, (unsigned long) iov->iov_len, errstr);
    1407  		if (*actual_size)
    1408  			error_msg_and_fail("iov_len changed again"
    1409  					   " from %u to %lu", regsize,
    1410  					   (unsigned long) iov->iov_len);
    1411  		*actual_size = iov->iov_len;
    1412  	}
    1413  
    1414  #if defined __sparc__ && !defined __arch64__
    1415  	/*
    1416  	 * On sparc32 PTRACE_SETREGSET NT_PRSTATUS of size greater than 120
    1417  	 * has interesting side effects.
    1418  	 */
    1419  	if (nt == 1 && regsize > 120)
    1420  		return;
    1421  #endif /* __sparc__ && !__arch64__ */
    1422  
    1423  	iov->iov_len = regsize;
    1424  	do_ptrace(PTRACE_SETREGSET, pid, nt, (uintptr_t) iov);
    1425  	if (iov->iov_len == regsize) {
    1426  		printf("ptrace(" XLAT_FMT ", %d, " XLAT_FMT ", {iov_base=",
    1427  		       XLAT_ARGS(PTRACE_SETREGSET), pid, XLAT_SEL(nt, nt_str));
    1428  		print_regset_fn(iov->iov_base, regsize);
    1429  		printf(", iov_len=%lu}) = %s\n",
    1430  		       (unsigned long) iov->iov_len, errstr);
    1431  	} else {
    1432  		printf("ptrace(" XLAT_FMT ", %d, " XLAT_FMT ", {iov_base=",
    1433  		       XLAT_ARGS(PTRACE_SETREGSET), pid, XLAT_SEL(nt, nt_str));
    1434  		print_regset_fn(iov->iov_base, regsize);
    1435  		printf(", iov_len=%u => %lu}) = %s\n",
    1436  		       regsize, (unsigned long) iov->iov_len, errstr);
    1437  	}
    1438  }
    1439  
    1440  static void
    1441  test_getregset_setregset(int pid)
    1442  {
    1443  	TAIL_ALLOC_OBJECT_CONST_PTR(struct iovec, iov);
    1444  	unsigned long addr = (uintptr_t) (iov + 1);
    1445  
    1446  	iov->iov_base = (void *) addr;
    1447  	iov->iov_len = sizeof(kernel_ulong_t);
    1448  
    1449  	do_ptrace(PTRACE_GETREGSET, pid, 1, (uintptr_t) iov);
    1450  	printf("ptrace(" XLAT_FMT ", %d, " XLAT_KNOWN(0x1, "NT_PRSTATUS")
    1451  	       ", {iov_base=%p, iov_len=%lu}) = %s\n",
    1452  	       XLAT_ARGS(PTRACE_GETREGSET), pid,
    1453  	       iov->iov_base, (unsigned long) iov->iov_len, errstr);
    1454  
    1455  	do_ptrace(PTRACE_SETREGSET, pid, 3, (uintptr_t) iov);
    1456  	printf("ptrace(" XLAT_FMT ", %d, " XLAT_KNOWN(0x3, "NT_PRPSINFO")
    1457  	       ", {iov_base=%p, iov_len=%lu}) = %s\n",
    1458  	       XLAT_ARGS(PTRACE_SETREGSET), pid,
    1459  	       iov->iov_base, (unsigned long) iov->iov_len, errstr);
    1460  
    1461  #ifdef PTRACE_GETREGS
    1462  	do_ptrace_regs(PTRACE_GETREGS, pid, addr);
    1463  	printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n",
    1464  	       XLAT_ARGS(PTRACE_GETREGS), pid, addr, errstr);
    1465  #endif
    1466  #ifdef PTRACE_SETREGS
    1467  	do_ptrace_regs(PTRACE_SETREGS, pid, addr);
    1468  	printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n",
    1469  	       XLAT_ARGS(PTRACE_SETREGS), pid, addr, errstr);
    1470  #endif
    1471  #ifdef PTRACE_GETFPREGS
    1472  	do_ptrace_regs(PTRACE_GETFPREGS, pid, addr);
    1473  	printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n",
    1474  	       XLAT_ARGS(PTRACE_GETFPREGS), pid, addr, errstr);
    1475  #endif
    1476  #ifdef PTRACE_SETFPREGS
    1477  	do_ptrace_regs(PTRACE_SETFPREGS, pid, addr);
    1478  	printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n",
    1479  	       XLAT_ARGS(PTRACE_SETFPREGS), pid, addr, errstr);
    1480  #endif
    1481  
    1482  	for (; addr > (uintptr_t) iov; --addr) {
    1483  		do_ptrace(PTRACE_GETREGSET, pid, 1, addr);
    1484  		printf("ptrace(" XLAT_FMT ", %d, "
    1485  		       XLAT_KNOWN(0x1, "NT_PRSTATUS") ", %#lx) = %s\n",
    1486  		       XLAT_ARGS(PTRACE_GETREGSET), pid, addr, errstr);
    1487  
    1488  		do_ptrace(PTRACE_SETREGSET, pid, 2, addr);
    1489  		printf("ptrace(" XLAT_FMT ", %d, "
    1490  		       XLAT_KNOWN(0x2, "NT_FPREGSET") ", %#lx) = %s\n",
    1491  		       XLAT_ARGS(PTRACE_SETREGSET), pid, addr, errstr);
    1492  	}
    1493  
    1494  	pid = fork();
    1495  	if (pid < 0)
    1496  		perror_msg_and_fail("fork");
    1497  
    1498  	if (!pid) {
    1499  		if (do_ptrace(PTRACE_TRACEME, 0, 0, 0))
    1500  			perror_msg_and_fail("child: PTRACE_TRACEME");
    1501  
    1502  		raise(SIGSTOP);
    1503  		if (chdir("")) {
    1504  			;
    1505  		}
    1506  		_exit(0);
    1507  	}
    1508  
    1509  	const unsigned int regset_buf_size = 4096 - 64;
    1510  	char *const regset_buf_endptr = midtail_alloc(0, regset_buf_size);
    1511  
    1512  	for (;;) {
    1513  		int status, tracee, saved;
    1514  
    1515  		errno = 0;
    1516  		tracee = wait(&status);
    1517  		if (tracee <= 0) {
    1518  			if (errno == EINTR)
    1519  				continue;
    1520  			saved = errno;
    1521  			kill(pid, SIGKILL);
    1522  			errno = saved;
    1523  			perror_msg_and_fail("wait");
    1524  		}
    1525  		if (WIFEXITED(status)) {
    1526  			if (WEXITSTATUS(status) == 0)
    1527  				break;
    1528  			error_msg_and_fail("unexpected exit status %#x",
    1529  					   WEXITSTATUS(status));
    1530  		}
    1531  		if (WIFSIGNALED(status))
    1532  			error_msg_and_fail("unexpected signal %u",
    1533  					   WTERMSIG(status));
    1534  		if (!WIFSTOPPED(status)) {
    1535  			kill(pid, SIGKILL);
    1536  			error_msg_and_fail("unexpected wait status %#x",
    1537  					   status);
    1538  		}
    1539  
    1540  		static unsigned int actual_prstatus_size;
    1541  		for (unsigned int i = actual_prstatus_size;
    1542  		     i <= regset_buf_size &&
    1543  		     (!actual_prstatus_size ||
    1544  		      actual_prstatus_size + 1 >= i);
    1545  		     ++i) {
    1546  			do_getregset_setregset(pid, 1, "NT_PRSTATUS",
    1547  					       regset_buf_endptr - i, i,
    1548  					       &actual_prstatus_size,
    1549  					       iov, print_prstatus_regset);
    1550  		}
    1551  		/*
    1552  		 * In an unlikely case NT_PRSTATUS is not supported,
    1553  		 * use regset_buf_size.
    1554  		 */
    1555  		if (!actual_prstatus_size)
    1556  			actual_prstatus_size = regset_buf_size;
    1557  
    1558  		static unsigned int actual_fpregset_size;
    1559  		for (unsigned int i = actual_fpregset_size;
    1560  		     i <= regset_buf_size &&
    1561  		     (!actual_fpregset_size ||
    1562  		      actual_fpregset_size + 1 >= i);
    1563  		     ++i) {
    1564  			do_getregset_setregset(pid, 2, "NT_FPREGSET",
    1565  					       regset_buf_endptr - i, i,
    1566  					       &actual_fpregset_size,
    1567  					       iov, print_fpregset);
    1568  		}
    1569  		/*
    1570  		 * In an unlikely case NT_FPREGSET is not supported,
    1571  		 * use regset_buf_size.
    1572  		 */
    1573  		if (!actual_fpregset_size)
    1574  			actual_fpregset_size = regset_buf_size;
    1575  
    1576  #ifdef PTRACE_GETREGS
    1577  		static unsigned int actual_pt_regs_size
    1578  # ifdef __mips__
    1579  			/*
    1580  			 * For some reason MIPS kernels do not report
    1581  			 * PTRACE_GETREGS EFAULT errors.
    1582  			 */
    1583  			= 38 * 8
    1584  # endif
    1585  			;
    1586  		for (unsigned int i = actual_pt_regs_size;
    1587  		     i <= (actual_pt_regs_size ?: regset_buf_size);
    1588  		     ++i) {
    1589  			do_getregs_setregs(pid, regset_buf_endptr - i, i,
    1590  					   &actual_pt_regs_size);
    1591  		}
    1592  		/*
    1593  		 * In an unlikely case PTRACE_GETREGS is not supported,
    1594  		 * use regset_buf_size.
    1595  		 */
    1596  		if (!actual_pt_regs_size)
    1597  			actual_pt_regs_size = regset_buf_size;
    1598  #endif
    1599  
    1600  #ifdef PTRACE_GETREGS64
    1601  		static unsigned int actual_pt_regs64_size;
    1602  		for (unsigned int i = actual_pt_regs64_size;
    1603  		     i <= (actual_pt_regs64_size ?: regset_buf_size);
    1604  		     ++i) {
    1605  			do_getregs64_setregs64(pid, regset_buf_endptr - i, i,
    1606  					       &actual_pt_regs64_size);
    1607  		}
    1608  		/*
    1609  		 * In an unlikely case PTRACE_GETREGS64 is not supported,
    1610  		 * use regset_buf_size.
    1611  		 */
    1612  		if (!actual_pt_regs64_size)
    1613  			actual_pt_regs64_size = regset_buf_size;
    1614  #endif
    1615  
    1616  #ifdef PTRACE_GETFPREGS
    1617  		static unsigned int actual_pt_fpregs_size
    1618  # ifdef __mips__
    1619  			/*
    1620  			 * For some reason MIPS kernels do not report
    1621  			 * PTRACE_GETFPREGS EFAULT errors.
    1622  			 */
    1623  			= 33 * 8
    1624  # endif
    1625  			;
    1626  		for (unsigned int i = actual_pt_fpregs_size;
    1627  		     i <= (actual_pt_fpregs_size ?: regset_buf_size);
    1628  		     ++i) {
    1629  			do_getfpregs_setfpregs(pid, regset_buf_endptr - i, i,
    1630  					       &actual_pt_fpregs_size);
    1631  		}
    1632  		/*
    1633  		 * In an unlikely case PTRACE_GETFPREGS is not supported,
    1634  		 * use regset_buf_size.
    1635  		 */
    1636  		if (!actual_pt_fpregs_size)
    1637  			actual_pt_fpregs_size = regset_buf_size;
    1638  #endif
    1639  
    1640  		if (WSTOPSIG(status) == SIGSTOP)
    1641  			kill(pid, SIGCONT);
    1642  
    1643  		if (do_ptrace(PTRACE_SYSCALL, pid, 0, 0)) {
    1644  			saved = errno;
    1645  			kill(pid, SIGKILL);
    1646  			errno = saved;
    1647  			perror_msg_and_fail("ptrace");
    1648  		}
    1649  		printf("ptrace(" XLAT_FMT ", %d, NULL, 0) = 0\n",
    1650  		       XLAT_ARGS(PTRACE_SYSCALL), pid);
    1651  	}
    1652  }
    1653  
    1654  #if defined __arm64__ || defined __aarch64__
    1655  static void
    1656  check_compat_ptrace_req(const unsigned int req, const char *const s,
    1657  			const int pid)
    1658  {
    1659  	do_ptrace(req, pid, 0, 0);
    1660  	printf("ptrace(%#x" NRAW(" /* ") "%s" NRAW(" */")
    1661  	       ", %d, NULL, NULL) = %s\n",
    1662  	       req, XLAT_RAW ? "" : s, pid, errstr);
    1663  
    1664  	do_ptrace(req, pid, 0xbadc0deddeadface, 0xfacefeeddecaffed);
    1665  	printf("ptrace(%#x" NRAW(" /* ") "%s" NRAW(" */")
    1666  	       ", %d, 0xbadc0deddeadface, 0xfacefeeddecaffed) = %s\n",
    1667  	       req, XLAT_RAW ? "" : s, pid, errstr);
    1668  }
    1669  
    1670  static void
    1671  test_compat_ptrace(const int pid)
    1672  {
    1673  	check_compat_ptrace_req(12, "COMPAT_PTRACE_GETREGS", pid);
    1674  	check_compat_ptrace_req(13, "COMPAT_PTRACE_SETREGS", pid);
    1675  	check_compat_ptrace_req(14, "COMPAT_PTRACE_GETFPREGS", pid);
    1676  	check_compat_ptrace_req(15, "COMPAT_PTRACE_SETFPREGS", pid);
    1677  	check_compat_ptrace_req(22, "COMPAT_PTRACE_GET_THREAD_AREA", pid);
    1678  	check_compat_ptrace_req(23, "COMPAT_PTRACE_SET_SYSCALL", pid);
    1679  	check_compat_ptrace_req(27, "COMPAT_PTRACE_GETVFPREGS", pid);
    1680  	check_compat_ptrace_req(28, "COMPAT_PTRACE_SETVFPREGS", pid);
    1681  	check_compat_ptrace_req(29, "COMPAT_PTRACE_GETHBPREGS", pid);
    1682  	check_compat_ptrace_req(30, "COMPAT_PTRACE_SETHBPREGS", pid);
    1683  }
    1684  #else /* !(__arm64__ || __aarch64__) */
    1685  static void test_compat_ptrace(const int pid) {}
    1686  #endif
    1687  
    1688  int
    1689  main(void)
    1690  {
    1691  	const unsigned long bad_request =
    1692  		(unsigned long) 0xdeadbeeffffffeedULL;
    1693  	const unsigned long bad_data =
    1694  		(unsigned long) 0xdeadcafefffff00dULL;
    1695  	const int pid = getpid();
    1696  
    1697  	int null_fd = open(null_path, O_RDONLY);
    1698  	if (null_fd < 0)
    1699  		perror_msg_and_fail("open(\"%s\")", null_path);
    1700  	if (null_fd != NULL_FD) {
    1701  		if (dup2(null_fd, NULL_FD) < 0)
    1702  			perror_msg_and_fail("dup2(%d, NULL_FD)", null_fd);
    1703  		close(null_fd);
    1704  	}
    1705  
    1706  	TAIL_ALLOC_OBJECT_CONST_PTR(uint64_t, filter_off);
    1707  
    1708  	const unsigned int sigset_size = get_sigset_size();
    1709  
    1710  	void *const k_set = tail_alloc(sigset_size);
    1711  	TAIL_ALLOC_OBJECT_CONST_PTR(siginfo_t, sip);
    1712  
    1713  	do_ptrace(bad_request, pid, 0, 0);
    1714  	printf("ptrace(%#lx" NRAW(" /* PTRACE_??? */")
    1715  	       ", %d, NULL, NULL) = %s\n",
    1716  	       bad_request, pid, errstr);
    1717  
    1718  	do_ptrace(PTRACE_PEEKDATA, pid, bad_request, bad_data);
    1719  #ifdef IA64
    1720  	printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n",
    1721  	       XLAT_ARGS(PTRACE_PEEKDATA), pid, bad_request, errstr);
    1722  #else
    1723  	printf("ptrace(" XLAT_FMT ", %d, %#lx, %#lx) = %s\n",
    1724  	       XLAT_ARGS(PTRACE_PEEKDATA), pid, bad_request, bad_data, errstr);
    1725  #endif
    1726  
    1727  	do_ptrace(PTRACE_PEEKTEXT, pid, bad_request, bad_data);
    1728  #ifdef IA64
    1729  	printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n",
    1730  	       XLAT_ARGS(PTRACE_PEEKTEXT), pid, bad_request, errstr);
    1731  #else
    1732  	printf("ptrace(" XLAT_FMT ", %d, %#lx, %#lx) = %s\n",
    1733  	       XLAT_ARGS(PTRACE_PEEKTEXT), pid, bad_request, bad_data, errstr);
    1734  #endif
    1735  
    1736  	do_ptrace(PTRACE_PEEKUSER, pid, bad_request, bad_data);
    1737  #ifdef IA64
    1738  	printf("ptrace(" XLAT_FMT ", %d, %#lx) = %s\n",
    1739  	       XLAT_ARGS(PTRACE_PEEKUSER), pid, bad_request, errstr);
    1740  #else
    1741  	printf("ptrace(" XLAT_FMT ", %d, %#lx, %#lx) = %s\n",
    1742  	       XLAT_ARGS(PTRACE_PEEKUSER), pid, bad_request, bad_data, errstr);
    1743  #endif
    1744  
    1745  	do_ptrace(PTRACE_POKEUSER, pid, bad_request, bad_data);
    1746  	printf("ptrace(" XLAT_FMT ", %d, %#lx, %#lx) = %s\n",
    1747  	       XLAT_ARGS(PTRACE_POKEUSER), pid, bad_request, bad_data, errstr);
    1748  
    1749  	do_ptrace(PTRACE_ATTACH, pid, 0, 0);
    1750  	printf("ptrace(" XLAT_FMT ", %d) = %s\n",
    1751  	       XLAT_ARGS(PTRACE_ATTACH), pid, errstr);
    1752  
    1753  	do_ptrace(PTRACE_INTERRUPT, pid, 0, 0);
    1754  	printf("ptrace(" XLAT_FMT ", %d) = %s\n",
    1755  	       XLAT_ARGS(PTRACE_INTERRUPT), pid, errstr);
    1756  
    1757  	do_ptrace(PTRACE_KILL, pid, 0, 0);
    1758  	printf("ptrace(" XLAT_FMT ", %d) = %s\n",
    1759  	       XLAT_ARGS(PTRACE_KILL), pid, errstr);
    1760  
    1761  	do_ptrace(PTRACE_LISTEN, pid, 0, 0);
    1762  	printf("ptrace(" XLAT_FMT ", %d) = %s\n",
    1763  	       XLAT_ARGS(PTRACE_LISTEN), pid, errstr);
    1764  
    1765  	sigset_t libc_set;
    1766  	sigemptyset(&libc_set);
    1767  	sigaddset(&libc_set, SIGUSR1);
    1768  	memcpy(k_set, &libc_set, sigset_size);
    1769  
    1770  	do_ptrace(PTRACE_SETSIGMASK, pid, sigset_size, (uintptr_t) k_set);
    1771  	printf("ptrace(" XLAT_FMT ", %d, %u, [" XLAT_FMT_U "]) = %s\n",
    1772  	       XLAT_ARGS(PTRACE_SETSIGMASK), pid, sigset_size,
    1773  	       XLAT_SEL(SIGUSR1, "USR1"), errstr);
    1774  
    1775  	do_ptrace(PTRACE_GETSIGMASK, pid, sigset_size, (uintptr_t) k_set);
    1776  	printf("ptrace(" XLAT_FMT ", %d, %u, %p) = %s\n",
    1777  	       XLAT_ARGS(PTRACE_GETSIGMASK), pid, sigset_size, k_set, errstr);
    1778  
    1779  	do_ptrace(PTRACE_SECCOMP_GET_FILTER, pid, 42, 0);
    1780  	printf("ptrace(" XLAT_FMT ", %d, 42, NULL) = %s\n",
    1781  	       XLAT_ARGS(PTRACE_SECCOMP_GET_FILTER), pid, errstr);
    1782  
    1783  	do_ptrace(PTRACE_SECCOMP_GET_METADATA, pid, bad_data, 0);
    1784  	printf("ptrace(" XLAT_FMT ", %d, %lu, NULL) = %s\n",
    1785  	       XLAT_ARGS(PTRACE_SECCOMP_GET_METADATA), pid, bad_data, errstr);
    1786  
    1787  	do_ptrace(PTRACE_SECCOMP_GET_METADATA, pid, 7,
    1788  		  (uintptr_t) filter_off);
    1789  	printf("ptrace(" XLAT_FMT ", %d, 7, %p) = %s\n",
    1790  	       XLAT_ARGS(PTRACE_SECCOMP_GET_METADATA), pid, filter_off, errstr);
    1791  
    1792  	*filter_off = 0xfacefeeddeadc0deULL;
    1793  	do_ptrace(PTRACE_SECCOMP_GET_METADATA, pid, bad_data,
    1794  		  (uintptr_t) filter_off);
    1795  	printf("ptrace(" XLAT_FMT ", %d, %lu, {filter_off=%" PRIu64 "}) = %s\n",
    1796  	       XLAT_ARGS(PTRACE_SECCOMP_GET_METADATA),
    1797  	       pid, bad_data, *filter_off, errstr);
    1798  
    1799  	do_ptrace(PTRACE_GETEVENTMSG, pid, bad_request, bad_data);
    1800  	printf("ptrace(" XLAT_FMT ", %d, %#lx, %#lx) = %s\n",
    1801  	       XLAT_ARGS(PTRACE_GETEVENTMSG),
    1802  	       pid, bad_request, bad_data, errstr);
    1803  
    1804  	/* SIGIO */
    1805  	memset(sip, -1, sizeof(*sip));
    1806  	sip->si_signo = SIGIO;
    1807  	sip->si_code = 1;
    1808  	sip->si_errno = ENOENT;
    1809  	sip->si_band = -2;
    1810  	sip->si_fd = NULL_FD;
    1811  
    1812  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    1813  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    1814  	       ", si_code=" XLAT_FMT ", si_errno=" XLAT_FMT_U ", si_band=-2"
    1815  	       ", si_fd=%d%s}) = %s\n",
    1816  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGIO),
    1817  	       XLAT_ARGS(POLL_IN), XLAT_ARGS(ENOENT), NULL_FD, NULL_FD_STR,
    1818  	       errstr);
    1819  
    1820  	/* SIGTRAP */
    1821  	struct valstraux trap_codes[] = {
    1822  		{ ARG_XLAT_KNOWN(0x1, "TRAP_BRKPT") },
    1823  #ifdef TRAP_TRACEFLOW
    1824  		{ ARG_XLAT_KNOWN(0x2, "TRAP_TRACEFLOW") },
    1825  #else
    1826  		{ ARG_XLAT_KNOWN(0x2, "TRAP_TRACE") },
    1827  #endif
    1828  #ifdef TRAP_WATCHPT
    1829  		{ ARG_XLAT_KNOWN(0x3, "TRAP_WATCHPT") },
    1830  #else
    1831  		{ ARG_XLAT_KNOWN(0x3, "TRAP_BRANCH") },
    1832  #endif
    1833  #ifdef TRAP_ILLTRAP
    1834  		{ ARG_XLAT_KNOWN(0x4, "TRAP_ILLTRAP") },
    1835  #else
    1836  		{ ARG_XLAT_KNOWN(0x4, "TRAP_HWBKPT") },
    1837  #endif
    1838  		{ ARG_XLAT_KNOWN(0x5, "TRAP_UNK"), ""
    1839  #if defined __alpha__ && defined HAVE_SIGINFO_T_SI_TRAPNO
    1840  		  ", si_trapno=0 /* GEN_??? */"
    1841  		},
    1842  		{ ARG_XLAT_KNOWN(0x5, "TRAP_UNK"),
    1843  		  ", si_trapno=" XLAT_KNOWN(-1, "GEN_INTOVF" },
    1844  		{ ARG_XLAT_KNOWN(0x5, "TRAP_UNK"),
    1845  		  ", si_trapno=" XLAT_KNOWN(-25, "GEN_SUBRNG7" },
    1846  		{ ARG_XLAT_KNOWN(0x5, "TRAP_UNK"), ""
    1847  		  ", si_trapno=-26 /* GEN_??? */" },
    1848  		{ ARG_XLAT_KNOWN(0x5, "TRAP_UNK"), ""
    1849  		  ", si_trapno=-1234567890 /* GEN_??? */"
    1850  #endif /* __alpha__ && HAVE_SIGINFO_T_SI_TRAPNO */
    1851  		},
    1852  		{ ARG_XLAT_KNOWN(0x6, "TRAP_PERF"), ""
    1853  #ifdef HAVE_SIGINFO_T_SI_PERF_DATA
    1854  		  ", si_perf_data=0"
    1855  # ifdef HAVE_SIGINFO_T_SI_PERF_TYPE
    1856  		  ", si_perf_type=" XLAT_KNOWN(0, "PERF_TYPE_HARDWARE")
    1857  # endif
    1858  # ifdef HAVE_SIGINFO_T_SI_PERF_FLAGS
    1859  		  ", si_perf_flags=0"
    1860  # endif
    1861  		},
    1862  		{ ARG_XLAT_KNOWN(0x6, "TRAP_PERF"), ""
    1863  		  ", si_perf_data=0x1"
    1864  # ifdef HAVE_SIGINFO_T_SI_PERF_TYPE
    1865  		  ", si_perf_type=" XLAT_KNOWN(0x1, "PERF_TYPE_SOFTWARE")
    1866  # endif
    1867  # ifdef HAVE_SIGINFO_T_SI_PERF_FLAGS
    1868  		  ", si_perf_flags=" XLAT_KNOWN(0x1, "TRAP_PERF_FLAG_ASYNC")
    1869  # endif
    1870  		},
    1871  		{ ARG_XLAT_KNOWN(0x6, "TRAP_PERF"), ""
    1872  		  ", si_perf_data=0x" UP64BIT("12345678") "90abcdef"
    1873  # ifdef HAVE_SIGINFO_T_SI_PERF_TYPE
    1874  		  ", si_perf_type=" XLAT_KNOWN(0x5, "PERF_TYPE_BREAKPOINT")
    1875  # endif
    1876  # ifdef HAVE_SIGINFO_T_SI_PERF_FLAGS
    1877  		  ", si_perf_flags="
    1878  		  XLAT_KNOWN(0xdeadbeef, "TRAP_PERF_FLAG_ASYNC|0xdeadbeee")
    1879  # endif
    1880  		},
    1881  		{ ARG_XLAT_KNOWN(0x6, "TRAP_PERF"), ""
    1882  		  ", si_perf_data=0x" UP64BIT("badc0ded") "deadface"
    1883  # ifdef HAVE_SIGINFO_T_SI_PERF_TYPE
    1884  		  ", si_perf_type=" XLAT_UNKNOWN(0x6, "PERF_TYPE_???")
    1885  # endif
    1886  # ifdef HAVE_SIGINFO_T_SI_PERF_FLAGS
    1887  		  ", si_perf_flags="
    1888  		  XLAT_UNKNOWN(0xcafec0de, "TRAP_PERF_FLAG_???")
    1889  # endif
    1890  #endif /* HAVE_SIGINFO_T_SI_PERF_DATA */
    1891  		},
    1892  		{ ARG_STR(0x7) },
    1893  		{ ARG_STR(0x499602d2) },
    1894  	};
    1895  	int trap_unk_vecs[] = { 0, 1234567890, -1234567890 };
    1896  	struct {
    1897  		unsigned long data;
    1898  		uint32_t type;
    1899  		uint32_t flags;
    1900  	} trap_perf_vecs[] = {
    1901  		{ 0, 0, 0 },
    1902  		{ 1, 1, 1 },
    1903  		{ (unsigned long) 0x1234567890abcdefULL, 5, 0xdeadbeef },
    1904  		{ (unsigned long) 0xbadc0deddeadfaceULL, 6, 0xcafec0de },
    1905  	};
    1906  	size_t trap_unk_pos = 0;
    1907  	size_t trap_perf_pos = 0;
    1908  
    1909  	memset(sip, -1, sizeof(*sip));
    1910  	sip->si_signo = SIGTRAP;
    1911  	sip->si_code = 1;
    1912  	sip->si_errno = ENOENT;
    1913  	sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL;
    1914  
    1915  	for (size_t i = 0; i < ARRAY_SIZE(trap_codes); i++) {
    1916  		sip->si_code = trap_codes[i].val;
    1917  
    1918  		switch (sip->si_code) {
    1919  		case 5: /* TRAP_UNK */
    1920  #if defined __alpha__ && defined HAVE_SIGINFO_T_SI_TRAPNO
    1921  			sip->si_trapno = trap_unk_vecs[trap_unk_pos];
    1922  #endif
    1923  			trap_unk_pos = (trap_unk_pos + 1)
    1924  				       % ARRAY_SIZE(trap_unk_vecs);
    1925  			break;
    1926  		case 6: /* TRAP_PERF */
    1927  #ifdef HAVE_SIGINFO_T_SI_PERF_DATA
    1928  			sip->si_perf_data = trap_perf_vecs[trap_perf_pos].data;
    1929  #endif
    1930  #ifdef HAVE_SIGINFO_T_SI_PERF_TYPE
    1931  			sip->si_perf_type = trap_perf_vecs[trap_perf_pos].type;
    1932  #endif
    1933  #ifdef HAVE_SIGINFO_T_SI_PERF_FLAGS
    1934  			sip->si_perf_flags = trap_perf_vecs[trap_perf_pos].flags;
    1935  #endif
    1936  			trap_perf_pos = (trap_perf_pos + 1)
    1937  					% ARRAY_SIZE(trap_perf_vecs);
    1938  			break;
    1939  		};
    1940  
    1941  		do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    1942  		printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    1943  		       ", si_code=%s, si_errno=" XLAT_FMT_U ", si_addr=%p%s}"
    1944  		       ") = %s\n",
    1945  		       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    1946  		       XLAT_ARGS(SIGTRAP), trap_codes[i].str, XLAT_ARGS(ENOENT),
    1947  		       sip->si_addr, trap_codes[i].aux ?: "", errstr);
    1948  	}
    1949  
    1950  	/* SIGILL */
    1951  	memset(sip, -1, sizeof(*sip));
    1952  	sip->si_signo = SIGILL;
    1953  	sip->si_code = 1;
    1954  	sip->si_errno = ENOENT;
    1955  	sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL;
    1956  #ifdef si_trapno
    1957  	sip->si_trapno = -12;
    1958  #endif
    1959  
    1960  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    1961  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    1962  	       ", si_code=" XLAT_FMT ", si_errno=" XLAT_FMT_U ", si_addr=%p"
    1963  #ifdef __sparc__
    1964  	       ", si_trapno=-12"
    1965  #endif
    1966  	       "}) = %s\n",
    1967  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    1968  	       XLAT_ARGS(SIGILL), XLAT_ARGS(ILL_ILLOPC), XLAT_ARGS(ENOENT),
    1969  	       sip->si_addr, errstr);
    1970  
    1971  	/* SIGFPE */
    1972  	memset(sip, -1, sizeof(*sip));
    1973  	sip->si_signo = SIGFPE;
    1974  	sip->si_code = 1;
    1975  	sip->si_errno = ENOENT;
    1976  	sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL;
    1977  #ifdef si_trapno
    1978  	sip->si_trapno = -7;
    1979  #endif
    1980  
    1981  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    1982  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    1983  	       ", si_code=" XLAT_FMT ", si_errno=" XLAT_FMT_U ", si_addr=%p"
    1984  #if defined __alpha__ && defined HAVE_SIGINFO_T_SI_TRAPNO
    1985  	       ", si_trapno=" XLAT_KNOWN(-7, "GEN_FLTINE")
    1986  #endif
    1987  	       "}) = %s\n",
    1988  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    1989  	       XLAT_ARGS(SIGFPE), XLAT_ARGS(FPE_INTDIV), XLAT_ARGS(ENOENT),
    1990  	       sip->si_addr, errstr);
    1991  
    1992  	/* SIGBUS */
    1993  	struct valstraux bus_codes[] = {
    1994  		{ ARG_XLAT_KNOWN(0x1, "BUS_ADRALN") },
    1995  		{ ARG_XLAT_KNOWN(0x2, "BUS_ADRERR") },
    1996  		{ ARG_XLAT_KNOWN(0x3, "BUS_OBJERR") },
    1997  #ifdef BUS_OPFETCH
    1998  		{ ARG_XLAT_KNOWN(0x4, "BUS_OPFETCH") },
    1999  #else
    2000  		{ ARG_XLAT_KNOWN(0x4, "BUS_MCEERR_AR"),
    2001  # ifdef HAVE_SIGINFO_T_SI_ADDR_LSB
    2002  		  ", si_addr_lsb=0xdead"
    2003  # endif
    2004  		},
    2005  #endif
    2006  		{ ARG_XLAT_KNOWN(0x5, "BUS_MCEERR_AO"),
    2007  #if !defined(BUS_OPFETCH) && defined(HAVE_SIGINFO_T_SI_ADDR_LSB)
    2008  		  ", si_addr_lsb=0xdead"
    2009  #endif
    2010  		},
    2011  		{ ARG_STR(0x6) },
    2012  		{ ARG_STR(0x499602d2) },
    2013  	};
    2014  
    2015  	memset(sip, -1, sizeof(*sip));
    2016  	sip->si_signo = SIGBUS;
    2017  	sip->si_code = 1;
    2018  	sip->si_errno = -2;
    2019  	sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL;
    2020  #ifdef HAVE_SIGINFO_T_SI_ADDR_LSB
    2021  	sip->si_addr_lsb = 0xdead;
    2022  #endif
    2023  	for (size_t i = 0; i < ARRAY_SIZE(bus_codes); i++) {
    2024  		sip->si_code = bus_codes[i].val;
    2025  
    2026  		do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2027  		printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    2028  		       ", si_code=%s, si_errno=%u, si_addr=%p%s}) = %s\n",
    2029  		       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    2030  		       XLAT_ARGS(SIGBUS), bus_codes[i].str,
    2031  		       sip->si_errno, sip->si_addr, bus_codes[i].aux ?: "",
    2032  		       errstr);
    2033  	}
    2034  
    2035  	/* SIGPROF */
    2036  	memset(sip, -1, sizeof(*sip));
    2037  	sip->si_signo = SIGPROF;
    2038  	sip->si_code = 0xbadc0ded;
    2039  	sip->si_errno = -2;
    2040  	sip->si_pid = 0;
    2041  	sip->si_uid = 3;
    2042  	sip->si_ptr = 0;
    2043  
    2044  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2045  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    2046  	       ", si_code=%#x, si_errno=%u, si_pid=0, si_uid=3}) = %s\n",
    2047  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    2048  	       XLAT_ARGS(SIGPROF), sip->si_code, sip->si_errno, errstr);
    2049  
    2050  	/* SIGSEGV */
    2051  	struct valstraux segv_codes[] = {
    2052  		{ ARG_XLAT_KNOWN(0x1, "SEGV_MAPERR") },
    2053  		{ ARG_XLAT_KNOWN(0x2, "SEGV_ACCERR") },
    2054  #ifdef SEGV_STACKFLOW
    2055  		{ ARG_XLAT_KNOWN(0x3, "SEGV_STACKFLOW") },
    2056  #else
    2057  		{ ARG_XLAT_KNOWN(0x3, "SEGV_BNDERR"), ""
    2058  # ifdef HAVE_SIGINFO_T_SI_LOWER
    2059  		  ", si_lower=NULL, si_upper=NULL"
    2060  		},
    2061  		{ ARG_XLAT_KNOWN(0x3, "SEGV_BNDERR"),
    2062  		  ", si_lower=NULL"
    2063  		  ", si_upper=0x" UP64BIT("deadc0de") "beadfeed" },
    2064  		{ ARG_XLAT_KNOWN(0x3, "SEGV_BNDERR"),
    2065  		  ", si_lower=0x" UP64BIT("facecafe") "befeeded"
    2066  		  ", si_upper=NULL" },
    2067  		{ ARG_XLAT_KNOWN(0x3, "SEGV_BNDERR"),
    2068  		  ", si_lower=0x" UP64BIT("beefface") "cafedead"
    2069  		  ", si_upper=0x" UP64BIT("badc0ded") "dadfaced",
    2070  # endif /* HAVE_SIGINFO_T_SI_LOWER */
    2071  		},
    2072  #endif /* SEGV_STACKFLOW */
    2073  #ifdef __SEGV_PSTKOVF
    2074  		{ ARG_XLAT_KNOWN(0x4, "__SEGV_PSTKOVF") },
    2075  #else
    2076  		{ ARG_XLAT_KNOWN(0x4, "SEGV_PKUERR"), ""
    2077  # ifdef HAVE_SIGINFO_T_SI_PKEY
    2078  		  ", si_pkey=0"
    2079  		},
    2080  		{ ARG_XLAT_KNOWN(0x4, "SEGV_PKUERR"), ", si_pkey=1234567890" },
    2081  		{ ARG_XLAT_KNOWN(0x4, "SEGV_PKUERR"), ", si_pkey=3141592653"
    2082  # endif /* HAVE_SIGINFO_T_SI_PKEY */
    2083  		},
    2084  #endif /* __SEGV_PSTKOVF */
    2085  		{ ARG_XLAT_KNOWN(0x5, "SEGV_ACCADI") },
    2086  		{ ARG_XLAT_KNOWN(0x6, "SEGV_ADIDERR") },
    2087  		{ ARG_XLAT_KNOWN(0x7, "SEGV_ADIPERR") },
    2088  		{ ARG_XLAT_KNOWN(0x8, "SEGV_MTEAERR") },
    2089  		{ ARG_XLAT_KNOWN(0x9, "SEGV_MTESERR") },
    2090  		{ ARG_STR(0xa) },
    2091  		{ ARG_STR(0x499602d2) },
    2092  	};
    2093  	uint32_t segv_pkey_vecs[] = { 0, 1234567890, 3141592653U };
    2094  	struct {
    2095  		void *lower;
    2096  		void *upper;
    2097  	} segv_bnd_vecs[] = {
    2098  		{ 0, 0 },
    2099  		{ 0, (void *) (uintptr_t) 0xdeadc0debeadfeedULL },
    2100  		{ (void *) (uintptr_t) 0xfacecafebefeededULL, 0 },
    2101  		{ (void *) (uintptr_t) 0xbeeffacecafedeadULL,
    2102  		  (void *) (uintptr_t) 0xbadc0deddadfacedULL },
    2103  	};
    2104  	size_t segv_pkey_pos = 0;
    2105  	size_t segv_bnd_pos = 0;
    2106  
    2107  	memset(sip, -1, sizeof(*sip));
    2108  	sip->si_signo = SIGSEGV;
    2109  	sip->si_errno = 0;
    2110  	sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL;
    2111  
    2112  	for (size_t i = 0; i < ARRAY_SIZE(segv_codes); i++) {
    2113  		sip->si_code = segv_codes[i].val;
    2114  
    2115  		switch (sip->si_code) {
    2116  		case 3: /* SEGV_BNDERR */
    2117  #ifdef HAVE_SIGINFO_T_SI_LOWER
    2118  			sip->si_lower = segv_bnd_vecs[segv_bnd_pos].lower;
    2119  			sip->si_upper = segv_bnd_vecs[segv_bnd_pos].upper;
    2120  #endif
    2121  			segv_bnd_pos = (segv_bnd_pos + 1)
    2122  				       % ARRAY_SIZE(segv_bnd_vecs);
    2123  			break;
    2124  		case 4: /* SEGV_PKUERR */
    2125  #ifdef HAVE_SIGINFO_T_SI_PKEY
    2126  			sip->si_pkey = segv_pkey_vecs[segv_pkey_pos];
    2127  #endif
    2128  			segv_pkey_pos = (segv_pkey_pos + 1)
    2129  					% ARRAY_SIZE(segv_pkey_vecs);
    2130  			break;
    2131  		};
    2132  
    2133  		do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2134  		printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    2135  		       ", si_code=%s, si_addr=%p%s}) = %s\n",
    2136  		       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    2137  		       XLAT_ARGS(SIGSEGV), segv_codes[i].str,
    2138  		       sip->si_addr, segv_codes[i].aux ?: "", errstr);
    2139  	}
    2140  
    2141  	/* SIGSYS */
    2142  #ifdef HAVE_SIGINFO_T_SI_SYSCALL
    2143  	memset(sip, -1, sizeof(*sip));
    2144  	sip->si_signo = SIGSYS;
    2145  	sip->si_code = 1;
    2146  	sip->si_errno = ENOENT;
    2147  	sip->si_call_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL;
    2148  	sip->si_syscall = -1U;
    2149  	sip->si_arch = AUDIT_ARCH_X86_64;
    2150  
    2151  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2152  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    2153  	       ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno="
    2154  	       XLAT_FMT_U ", si_call_addr=%p, si_syscall=%u, si_arch=" XLAT_FMT
    2155  	       "}) = %s\n",
    2156  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    2157  	       XLAT_ARGS(SIGSYS), XLAT_ARGS(ENOENT), sip->si_call_addr,
    2158  	       sip->si_syscall, XLAT_ARGS(AUDIT_ARCH_X86_64), errstr);
    2159  
    2160  	sip->si_errno = 3141592653U;
    2161  	sip->si_call_addr = NULL;
    2162  	sip->si_syscall = __NR_read;
    2163  	sip->si_arch = 0xda7a1057;
    2164  
    2165  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2166  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    2167  	       ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno=%u"
    2168  	       ", si_call_addr=NULL, si_syscall=%u, si_arch=%#x"
    2169  	       NRAW(" /* AUDIT_ARCH_??? */") "}) = %s\n",
    2170  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    2171  	       XLAT_ARGS(SIGSYS), sip->si_errno, sip->si_syscall, sip->si_arch,
    2172  	       errstr);
    2173  
    2174  # ifdef CUR_AUDIT_ARCH
    2175  	sip->si_arch = CUR_AUDIT_ARCH;
    2176  
    2177  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2178  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    2179  	       ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno=%u"
    2180  	       ", si_call_addr=NULL, si_syscall=" XLAT_FMT_U ", si_arch=%s}"
    2181  	       ") = %s\n",
    2182  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    2183  	       XLAT_ARGS(SIGSYS), sip->si_errno, XLAT_ARGS(__NR_read),
    2184  	       sprintxval(audit_arch, CUR_AUDIT_ARCH, "AUDIT_ARCH_???"),
    2185  	       errstr);
    2186  # endif
    2187  # if defined(PERS0_AUDIT_ARCH)
    2188  	sip->si_arch = PERS0_AUDIT_ARCH;
    2189  	sip->si_syscall = PERS0__NR_gettid;
    2190  
    2191  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2192  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    2193  	       ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno=%u"
    2194  	       ", si_call_addr=NULL, si_syscall=%u" NRAW(" /* gettid */")
    2195  	       ", si_arch=%s}) = %s\n",
    2196  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    2197  	       XLAT_ARGS(SIGSYS), sip->si_errno, PERS0__NR_gettid,
    2198  	       sprintxval(audit_arch, PERS0_AUDIT_ARCH, "AUDIT_ARCH_???"),
    2199  	       errstr);
    2200  # endif
    2201  # if defined(M32_AUDIT_ARCH)
    2202  	sip->si_arch = M32_AUDIT_ARCH;
    2203  	sip->si_syscall = M32__NR_gettid;
    2204  
    2205  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2206  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    2207  	       ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno=%u"
    2208  	       ", si_call_addr=NULL, si_syscall=%u" NRAW(" /* gettid */")
    2209  	       ", si_arch=%s}) = %s\n",
    2210  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    2211  	       XLAT_ARGS(SIGSYS), sip->si_errno, M32__NR_gettid,
    2212  	       sprintxval(audit_arch, M32_AUDIT_ARCH, "AUDIT_ARCH_???"),
    2213  	       errstr);
    2214  # endif
    2215  # if defined(MX32_AUDIT_ARCH)
    2216  	sip->si_arch = MX32_AUDIT_ARCH;
    2217  	sip->si_syscall = MX32__NR_gettid;
    2218  
    2219  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2220  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    2221  	       ", si_code=" XLAT_KNOWN(0x1, "SYS_SECCOMP") ", si_errno=%u"
    2222  	       ", si_call_addr=NULL, si_syscall=%u" NRAW(" /* gettid */")
    2223  	       ", si_arch=%s}) = %s\n",
    2224  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    2225  	       XLAT_ARGS(SIGSYS), sip->si_errno, MX32__NR_gettid,
    2226  	       sprintxval(audit_arch, MX32_AUDIT_ARCH, "AUDIT_ARCH_???"),
    2227  	       errstr);
    2228  # endif
    2229  #endif
    2230  
    2231  	/* SI_TIMER */
    2232  #if defined HAVE_SIGINFO_T_SI_TIMERID && defined HAVE_SIGINFO_T_SI_OVERRUN
    2233  	memset(sip, -1, sizeof(*sip));
    2234  	sip->si_signo = SIGHUP;
    2235  	sip->si_code = SI_TIMER;
    2236  	sip->si_errno = ENOENT;
    2237  	sip->si_timerid = 0xdeadbeef;
    2238  	sip->si_overrun = -1;
    2239  	sip->si_ptr = (void *) (unsigned long) 0xfacefeeddeadbeefULL;
    2240  
    2241  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2242  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    2243  	       ", si_code=" XLAT_FMT ", si_errno=" XLAT_FMT_U ", si_timerid=%#x"
    2244  	       ", si_overrun=%d, si_int=%d, si_ptr=%p}) = %s\n",
    2245  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    2246  	       XLAT_ARGS(SIGHUP), XLAT_ARGS(SI_TIMER), XLAT_ARGS(ENOENT),
    2247  	       sip->si_timerid, sip->si_overrun, sip->si_int, sip->si_ptr,
    2248  	       errstr);
    2249  #endif
    2250  
    2251  	/* SI_SIGIO */
    2252  	memset(sip, -1, sizeof(*sip));
    2253  	sip->si_signo = SIGSEGV;
    2254  	sip->si_code = SI_SIGIO;
    2255  	sip->si_errno = ENOENT;
    2256  	sip->si_band = -1234567890;
    2257  	sip->si_fd = NULL_FD;
    2258  
    2259  	do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2260  	printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
    2261  	       ", si_code=" XLAT_FMT ", si_errno=" XLAT_FMT_U
    2262  	       ", si_band=-1234567890, si_fd=%d%s}) = %s\n",
    2263  	       XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
    2264  	       XLAT_ARGS(SIGSEGV), XLAT_ARGS(SI_SIGIO), XLAT_ARGS(ENOENT),
    2265  	       NULL_FD, NULL_FD_STR, errstr);
    2266  
    2267  	do_ptrace(PTRACE_GETSIGINFO, pid, bad_request, (uintptr_t) sip);
    2268  	printf("ptrace(" XLAT_FMT ", %d, %#lx, %p) = %s\n",
    2269  	       XLAT_ARGS(PTRACE_GETSIGINFO), pid, bad_request, sip, errstr);
    2270  
    2271  	do_ptrace(PTRACE_CONT, pid, 0, SIGUSR1);
    2272  	printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n",
    2273  	       XLAT_ARGS(PTRACE_CONT), pid, XLAT_ARGS(SIGUSR1), errstr);
    2274  
    2275  	do_ptrace(PTRACE_DETACH, pid, 0, SIGUSR2);
    2276  	printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n",
    2277  	       XLAT_ARGS(PTRACE_DETACH), pid, XLAT_ARGS(SIGUSR2), errstr);
    2278  
    2279  	do_ptrace(PTRACE_SYSCALL, pid, 0, SIGUSR1);
    2280  	printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n",
    2281  	       XLAT_ARGS(PTRACE_SYSCALL), pid, XLAT_ARGS(SIGUSR1), errstr);
    2282  
    2283  #ifdef PTRACE_SINGLESTEP
    2284  	do_ptrace(PTRACE_SINGLESTEP, pid, 0, SIGUSR2);
    2285  	printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n",
    2286  	       XLAT_ARGS(PTRACE_SINGLESTEP), pid, XLAT_ARGS(SIGUSR2), errstr);
    2287  #endif
    2288  
    2289  #ifdef PTRACE_SINGLEBLOCK
    2290  	do_ptrace(PTRACE_SINGLEBLOCK, pid, 0, SIGUSR1);
    2291  	printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n",
    2292  	       XLAT_ARGS(PTRACE_SINGLEBLOCK), pid, XLAT_ARGS(SIGUSR1), errstr);
    2293  #endif
    2294  
    2295  #ifdef PTRACE_SYSEMU
    2296  	do_ptrace(PTRACE_SYSEMU, pid, 0, SIGUSR2);
    2297  	printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n",
    2298  	       XLAT_ARGS(PTRACE_SYSEMU), pid, XLAT_ARGS(SIGUSR2), errstr);
    2299  #endif
    2300  #ifdef PTRACE_SYSEMU_SINGLESTEP
    2301  	do_ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, SIGUSR1);
    2302  	printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT_U ") = %s\n",
    2303  	       XLAT_ARGS(PTRACE_SYSEMU_SINGLESTEP), pid, XLAT_ARGS(SIGUSR1),
    2304  	       errstr);
    2305  #endif
    2306  
    2307  	do_ptrace(PTRACE_SETOPTIONS,
    2308  		  pid, 0, PTRACE_O_TRACEFORK|PTRACE_O_TRACECLONE);
    2309  	printf("ptrace(" XLAT_FMT ", %d, NULL, " XLAT_FMT ") = %s\n",
    2310  	       XLAT_ARGS(PTRACE_SETOPTIONS), pid,
    2311  	       XLAT_ARGS(PTRACE_O_TRACEFORK|PTRACE_O_TRACECLONE), errstr);
    2312  
    2313  	do_ptrace(PTRACE_SEIZE, pid, bad_request, PTRACE_O_TRACESYSGOOD);
    2314  	printf("ptrace(" XLAT_FMT ", %d, %#lx, " XLAT_FMT ") = %s\n",
    2315  	       XLAT_ARGS(PTRACE_SEIZE), pid, bad_request,
    2316  	       XLAT_ARGS(PTRACE_O_TRACESYSGOOD), errstr);
    2317  
    2318  	test_peeksiginfo(pid, bad_request);
    2319  	test_getregset_setregset(pid);
    2320  	test_compat_ptrace(pid);
    2321  
    2322  	do_ptrace(PTRACE_TRACEME, 0, 0, 0);
    2323  	printf("ptrace(" XLAT_FMT ") = %s\n",
    2324  	       XLAT_ARGS(PTRACE_TRACEME), errstr);
    2325  
    2326  	puts("+++ exited with 0 +++");
    2327  	return 0;
    2328  }