1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * make sure PEEKUSER matches GETREGS
3f08c3bdfSopenharmony_ci *
4f08c3bdfSopenharmony_ci * Copyright (c) 2008 Analog Devices Inc.
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci * Licensed under the GPL-2 or later
7f08c3bdfSopenharmony_ci */
8f08c3bdfSopenharmony_ci
9f08c3bdfSopenharmony_ci#define _GNU_SOURCE
10f08c3bdfSopenharmony_ci
11f08c3bdfSopenharmony_ci#include <errno.h>
12f08c3bdfSopenharmony_ci#include <stdbool.h>
13f08c3bdfSopenharmony_ci#include <stdio.h>
14f08c3bdfSopenharmony_ci#include <stdlib.h>
15f08c3bdfSopenharmony_ci#include <unistd.h>
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ci#include <config.h>
18f08c3bdfSopenharmony_ci#include "ptrace.h"
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ci#include "test.h"
21f08c3bdfSopenharmony_ci#include "spawn_ptrace_child.h"
22f08c3bdfSopenharmony_ci
23f08c3bdfSopenharmony_cichar *TCID = "ptrace04";
24f08c3bdfSopenharmony_ci
25f08c3bdfSopenharmony_cistatic void cleanup();
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_ci#define R(r) { .name = "PT_" #r, .off = PT_##r },
28f08c3bdfSopenharmony_cistatic struct {
29f08c3bdfSopenharmony_ci	const char *name;
30f08c3bdfSopenharmony_ci	long off;
31f08c3bdfSopenharmony_ci} regs[] = {
32f08c3bdfSopenharmony_ci#ifdef __bfin__
33f08c3bdfSopenharmony_ci	R(ORIG_R0) R(ORIG_P0)
34f08c3bdfSopenharmony_ci	    R(R0) R(R1) R(R2) R(R3) R(R4) R(R5) R(R6) R(R7)
35f08c3bdfSopenharmony_ci	    R(P0) R(P1) R(P2) R(P3) R(P4) R(P5) R(FP) R(USP)
36f08c3bdfSopenharmony_ci	    R(I0) R(I1) R(I2) R(I3)
37f08c3bdfSopenharmony_ci	    R(M0) R(M1) R(M2) R(M3)
38f08c3bdfSopenharmony_ci	    R(L0) R(L1) R(L2) R(L3)
39f08c3bdfSopenharmony_ci	    R(B0) R(B1) R(B2) R(B3)
40f08c3bdfSopenharmony_ci	    R(A0X) R(A0W) R(A1X) R(A1W)
41f08c3bdfSopenharmony_ci	    R(LC0) R(LC1) R(LT0) R(LT1) R(LB0) R(LB1)
42f08c3bdfSopenharmony_ci	    R(ASTAT)
43f08c3bdfSopenharmony_ci	    R(RETS) R(PC) R(RETX) R(RETN) R(RETE)
44f08c3bdfSopenharmony_ci	    R(SEQSTAT) R(IPEND) R(SYSCFG)
45f08c3bdfSopenharmony_ci#endif
46f08c3bdfSopenharmony_ci};
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_ciint TST_TOTAL = 2;
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_civoid compare_registers(unsigned char poison)
51f08c3bdfSopenharmony_ci{
52f08c3bdfSopenharmony_ci#ifdef HAVE_STRUCT_PTRACE_REGS
53f08c3bdfSopenharmony_ci	ptrace_regs _pt_regs;
54f08c3bdfSopenharmony_ci	size_t i;
55f08c3bdfSopenharmony_ci	long ret;
56f08c3bdfSopenharmony_ci	bool failed = false;
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_ci	memset(&_pt_regs, poison, sizeof(_pt_regs));
59f08c3bdfSopenharmony_ci	errno = 0;
60f08c3bdfSopenharmony_ci	ret = ptrace(PTRACE_GETREGS, pid, NULL, &_pt_regs);
61f08c3bdfSopenharmony_ci	if (ret && errno) {
62f08c3bdfSopenharmony_ci		tst_resm(TFAIL | TERRNO, "PTRACE_GETREGS failed");
63f08c3bdfSopenharmony_ci	} else {
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ci		for (i = 0; i < ARRAY_SIZE(regs); ++i) {
66f08c3bdfSopenharmony_ci			errno = 0;
67f08c3bdfSopenharmony_ci			ret = ptrace(PTRACE_PEEKUSER, pid,
68f08c3bdfSopenharmony_ci				     (void *)regs[i].off, NULL);
69f08c3bdfSopenharmony_ci			if (ret && errno) {
70f08c3bdfSopenharmony_ci				tst_resm(TFAIL | TERRNO,
71f08c3bdfSopenharmony_ci					 "PTRACE_PEEKUSER: register %s "
72f08c3bdfSopenharmony_ci					 "(offset %li) failed",
73f08c3bdfSopenharmony_ci					 regs[i].name, regs[i].off);
74f08c3bdfSopenharmony_ci				failed = true;
75f08c3bdfSopenharmony_ci				continue;
76f08c3bdfSopenharmony_ci			}
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci			long *pt_val = (void *)&_pt_regs + regs[i].off;
79f08c3bdfSopenharmony_ci			if (*pt_val != ret) {
80f08c3bdfSopenharmony_ci				tst_resm(TFAIL,
81f08c3bdfSopenharmony_ci					 "register %s (offset %li) did not "
82f08c3bdfSopenharmony_ci					 "match\n\tGETREGS: 0x%08lx "
83f08c3bdfSopenharmony_ci					 "PEEKUSER: 0x%08lx",
84f08c3bdfSopenharmony_ci					 regs[i].name, regs[i].off, *pt_val,
85f08c3bdfSopenharmony_ci					 ret);
86f08c3bdfSopenharmony_ci				failed = true;
87f08c3bdfSopenharmony_ci			}
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ci		}
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_ci	}
92f08c3bdfSopenharmony_ci
93f08c3bdfSopenharmony_ci	tst_resm((failed ? TFAIL : TPASS),
94f08c3bdfSopenharmony_ci		 "PTRACE PEEKUSER/GETREGS (poison 0x%02x)", poison);
95f08c3bdfSopenharmony_ci#else
96f08c3bdfSopenharmony_ci	tst_brkm(TCONF, cleanup, "System doesn't have ptrace_regs structure");
97f08c3bdfSopenharmony_ci#endif
98f08c3bdfSopenharmony_ci}
99f08c3bdfSopenharmony_ci
100f08c3bdfSopenharmony_ciint main(int argc, char *argv[])
101f08c3bdfSopenharmony_ci{
102f08c3bdfSopenharmony_ci	tst_parse_opts(argc, argv, NULL, NULL);
103f08c3bdfSopenharmony_ci
104f08c3bdfSopenharmony_ci	if (ARRAY_SIZE(regs) == 0)
105f08c3bdfSopenharmony_ci		tst_brkm(TCONF, NULL, "test not supported for your arch (yet)");
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	make_a_baby(argc, argv);
108f08c3bdfSopenharmony_ci
109f08c3bdfSopenharmony_ci	/* first compare register states when execl() syscall starts */
110f08c3bdfSopenharmony_ci	tst_resm(TINFO, "Before exec() in child");
111f08c3bdfSopenharmony_ci	compare_registers(0x00);
112f08c3bdfSopenharmony_ci	compare_registers(0xff);
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ci	/* then compare register states after execl() syscall finishes */
115f08c3bdfSopenharmony_ci	tst_resm(TINFO, "After exec() in child");
116f08c3bdfSopenharmony_ci	errno = 0;
117f08c3bdfSopenharmony_ci	if (ptrace(PTRACE_SYSCALL, pid, NULL, NULL) && errno) {
118f08c3bdfSopenharmony_ci		tst_brkm(TFAIL, NULL, "PTRACE_SYSCALL failed: %s",
119f08c3bdfSopenharmony_ci			 strerror(errno));
120f08c3bdfSopenharmony_ci	}
121f08c3bdfSopenharmony_ci	compare_registers(0x00);
122f08c3bdfSopenharmony_ci	compare_registers(0xff);
123f08c3bdfSopenharmony_ci
124f08c3bdfSopenharmony_ci	/* hopefully this worked */
125f08c3bdfSopenharmony_ci	ptrace(PTRACE_KILL, pid, NULL, NULL);
126f08c3bdfSopenharmony_ci
127f08c3bdfSopenharmony_ci	tst_exit();
128f08c3bdfSopenharmony_ci}
129f08c3bdfSopenharmony_ci
130f08c3bdfSopenharmony_cistatic void cleanup(void)
131f08c3bdfSopenharmony_ci{
132f08c3bdfSopenharmony_ci}
133