1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Spawn a child and set it up for ptrace()-ing
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/*
10f08c3bdfSopenharmony_ci * To use:
11f08c3bdfSopenharmony_ci *  - add this line after your normal includes:
12f08c3bdfSopenharmony_ci *       #include "spawn_ptrace_child.c"
13f08c3bdfSopenharmony_ci *  - add this line to the top of your main():
14f08c3bdfSopenharmony_ci *       make_a_baby(argc, argv);
15f08c3bdfSopenharmony_ci *  - access the child pid via the "pid" variable
16f08c3bdfSopenharmony_ci */
17f08c3bdfSopenharmony_ci
18f08c3bdfSopenharmony_ci#include <errno.h>      /* errno */
19f08c3bdfSopenharmony_ci#include <signal.h>     /* signal() */
20f08c3bdfSopenharmony_ci#include <stdbool.h>    /* true */
21f08c3bdfSopenharmony_ci#include <string.h>     /* strcmp() */
22f08c3bdfSopenharmony_ci#include <unistd.h>     /* execlp() sleep() vfork() */
23f08c3bdfSopenharmony_ci#include <sys/ptrace.h> /* ptrace() */
24f08c3bdfSopenharmony_ci#include <sys/wait.h>
25f08c3bdfSopenharmony_ci
26f08c3bdfSopenharmony_ci#include "test.h"
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_cistatic pid_t pid;
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_ci#ifdef __sparc__
31f08c3bdfSopenharmony_ci/* sparce swaps addr/data for get/set regs */
32f08c3bdfSopenharmony_ci# define maybe_swap(request, addr, data) \
33f08c3bdfSopenharmony_cido { \
34f08c3bdfSopenharmony_ci	if (request == PTRACE_GETREGS || request == PTRACE_SETREGS) { \
35f08c3bdfSopenharmony_ci		void *__s = addr; \
36f08c3bdfSopenharmony_ci		addr = data; \
37f08c3bdfSopenharmony_ci		data = __s; \
38f08c3bdfSopenharmony_ci	} \
39f08c3bdfSopenharmony_ci} while (0)
40f08c3bdfSopenharmony_ci#else
41f08c3bdfSopenharmony_ci# define maybe_swap(...)
42f08c3bdfSopenharmony_ci#endif
43f08c3bdfSopenharmony_ci#define vptrace(request, pid, addr, data) \
44f08c3bdfSopenharmony_ci({ \
45f08c3bdfSopenharmony_ci	errno = 0; \
46f08c3bdfSopenharmony_ci	long __ret; \
47f08c3bdfSopenharmony_ci	void *__addr = (void *)(addr); \
48f08c3bdfSopenharmony_ci	void *__data = (void *)(data); \
49f08c3bdfSopenharmony_ci	maybe_swap(request, __addr, __data); \
50f08c3bdfSopenharmony_ci	__ret = ptrace(request, pid, __addr, __data); \
51f08c3bdfSopenharmony_ci	if (__ret && errno) \
52f08c3bdfSopenharmony_ci		perror("ptrace(" #request ", " #pid ", " #addr ", " #data ")"); \
53f08c3bdfSopenharmony_ci	__ret; \
54f08c3bdfSopenharmony_ci})
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_cistatic void make_a_baby(int argc, char *argv[])
57f08c3bdfSopenharmony_ci{
58f08c3bdfSopenharmony_ci	if (argc > 1 && !strcmp(argv[1], "child")) {
59f08c3bdfSopenharmony_ci		/* if we're the child, just sit around doing nothing */
60f08c3bdfSopenharmony_ci		int i = 60;
61f08c3bdfSopenharmony_ci		while (i--) {
62f08c3bdfSopenharmony_ci			close(-100);
63f08c3bdfSopenharmony_ci			sleep(1);
64f08c3bdfSopenharmony_ci		}
65f08c3bdfSopenharmony_ci		exit(1);
66f08c3bdfSopenharmony_ci	}
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_ci	signal(SIGCHLD, SIG_IGN);
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_ci	pid = vfork();
71f08c3bdfSopenharmony_ci	if (pid == -1) {
72f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "vfork() failed");
73f08c3bdfSopenharmony_ci		tst_exit();
74f08c3bdfSopenharmony_ci	} else if (pid) {
75f08c3bdfSopenharmony_ci		int status;
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ci		if (wait(&status) != pid) {
78f08c3bdfSopenharmony_ci			tst_brkm(TBROK | TERRNO, NULL, "wait(%i) failed: %#x", pid, status);
79f08c3bdfSopenharmony_ci			kill(pid, SIGKILL);
80f08c3bdfSopenharmony_ci			exit(1);
81f08c3bdfSopenharmony_ci		}
82f08c3bdfSopenharmony_ci		if (!WIFSTOPPED(status)) {
83f08c3bdfSopenharmony_ci			tst_brkm(TBROK, NULL, "child status not stopped: %#x", status);
84f08c3bdfSopenharmony_ci			kill(pid, SIGKILL);
85f08c3bdfSopenharmony_ci			exit(1);
86f08c3bdfSopenharmony_ci		}
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ci		return;
89f08c3bdfSopenharmony_ci	}
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_ci	errno = 0;
92f08c3bdfSopenharmony_ci	long ret = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
93f08c3bdfSopenharmony_ci	if (ret && errno) {
94f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "PTRACE_TRACEME failed");
95f08c3bdfSopenharmony_ci		tst_exit();
96f08c3bdfSopenharmony_ci	}
97f08c3bdfSopenharmony_ci
98f08c3bdfSopenharmony_ci	execlp(argv[0], argv[0], "child", NULL);
99f08c3bdfSopenharmony_ci	tst_resm(TFAIL, "execlp() failed");
100f08c3bdfSopenharmony_ci	tst_exit();
101f08c3bdfSopenharmony_ci}
102f08c3bdfSopenharmony_ci
103f08c3bdfSopenharmony_ci#define SPT(x) [PTRACE_##x] = #x,
104f08c3bdfSopenharmony_cistatic char *strings[] = {
105f08c3bdfSopenharmony_ci	SPT(TRACEME)
106f08c3bdfSopenharmony_ci	SPT(PEEKTEXT)
107f08c3bdfSopenharmony_ci	SPT(PEEKDATA)
108f08c3bdfSopenharmony_ci	SPT(PEEKUSER)
109f08c3bdfSopenharmony_ci	SPT(POKETEXT)
110f08c3bdfSopenharmony_ci	SPT(POKEDATA)
111f08c3bdfSopenharmony_ci	SPT(POKEUSER)
112f08c3bdfSopenharmony_ci#ifdef PTRACE_GETREGS
113f08c3bdfSopenharmony_ci	SPT(GETREGS)
114f08c3bdfSopenharmony_ci#endif
115f08c3bdfSopenharmony_ci#ifdef PTRACE_SETREGS
116f08c3bdfSopenharmony_ci	SPT(SETREGS)
117f08c3bdfSopenharmony_ci#endif
118f08c3bdfSopenharmony_ci#ifdef PTRACE_GETSIGINFO
119f08c3bdfSopenharmony_ci	SPT(GETSIGINFO)
120f08c3bdfSopenharmony_ci#endif
121f08c3bdfSopenharmony_ci#ifdef PTRACE_SETSIGINFO
122f08c3bdfSopenharmony_ci	SPT(SETSIGINFO)
123f08c3bdfSopenharmony_ci#endif
124f08c3bdfSopenharmony_ci#ifdef PTRACE_GETFGREGS
125f08c3bdfSopenharmony_ci	SPT(GETFGREGS)
126f08c3bdfSopenharmony_ci#endif
127f08c3bdfSopenharmony_ci#ifdef PTRACE_SETFGREGS
128f08c3bdfSopenharmony_ci	SPT(SETFGREGS)
129f08c3bdfSopenharmony_ci#endif
130f08c3bdfSopenharmony_ci	SPT(KILL)
131f08c3bdfSopenharmony_ci	SPT(SINGLESTEP)
132f08c3bdfSopenharmony_ci};
133f08c3bdfSopenharmony_cistatic inline char *strptrace(int request)
134f08c3bdfSopenharmony_ci{
135f08c3bdfSopenharmony_ci	return strings[request];
136f08c3bdfSopenharmony_ci}
137