blob: ae538e900729923a9a3adc4f43b9a2205750dc38 [file] [log] [blame]
vapierfeaa8202008-09-24 04:57:32 +00001/*
2 * Spawn a child and set it up for ptrace()-ing
3 *
4 * Copyright (c) 2008 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later
7 */
8
9/*
10 * To use:
11 * - add this line after your normal includes:
12 * #include "spawn_ptrace_child.c"
13 * - add this line to the top of your main():
14 * make_a_baby(argc, argv);
15 * - access the child pid via the "pid" variable
16 */
17
18#include <errno.h> /* errno */
19#include <signal.h> /* signal() */
vapier8747e0a2008-11-02 06:06:00 +000020#include <stdbool.h> /* true */
vapierfeaa8202008-09-24 04:57:32 +000021#include <string.h> /* strcmp() */
22#include <unistd.h> /* execlp() sleep() vfork() */
23#include <sys/ptrace.h> /* ptrace() */
24#include <sys/wait.h>
25
26#include "test.h"
vapierfeaa8202008-09-24 04:57:32 +000027
28static pid_t pid;
29
vapier0dadde12009-11-14 05:17:50 +000030#ifdef __sparc__
31/* sparce swaps addr/data for get/set regs */
32# define maybe_swap(request, addr, data) \
33do { \
34 if (request == PTRACE_GETREGS || request == PTRACE_SETREGS) { \
35 void *__s = addr; \
36 addr = data; \
37 data = __s; \
38 } \
39} while (0)
40#else
41# define maybe_swap(...)
42#endif
vapier971c9e82009-10-07 08:21:17 +000043#define vptrace(request, pid, addr, data) \
44({ \
45 errno = 0; \
vapier0dadde12009-11-14 05:17:50 +000046 long __ret; \
47 void *__addr = (void *)(addr); \
48 void *__data = (void *)(data); \
49 maybe_swap(request, __addr, __data); \
50 __ret = ptrace(request, pid, __addr, __data); \
vapier971c9e82009-10-07 08:21:17 +000051 if (__ret && errno) \
52 perror("ptrace(" #request ", " #pid ", " #addr ", " #data ")"); \
53 __ret; \
54})
55
vapierfeaa8202008-09-24 04:57:32 +000056static void make_a_baby(int argc, char *argv[])
57{
58 if (argc > 1 && !strcmp(argv[1], "child")) {
59 /* if we're the child, just sit around doing nothing */
vapier971c9e82009-10-07 08:21:17 +000060 int i = 60;
61 while (i--) {
62 close(-100);
63 sleep(1);
64 }
vapier8747e0a2008-11-02 06:06:00 +000065 exit(1);
vapierfeaa8202008-09-24 04:57:32 +000066 }
67
Mike Frysinger343b13f2011-12-19 18:57:26 -050068 signal(SIGCHLD, SIG_IGN);
vapierfeaa8202008-09-24 04:57:32 +000069
70 pid = vfork();
71 if (pid == -1) {
72 tst_resm(TFAIL, "vfork() failed");
73 tst_exit();
vapier8747e0a2008-11-02 06:06:00 +000074 } else if (pid) {
Mike Frysinger343b13f2011-12-19 18:57:26 -050075 int status;
76
77 if (wait(&status) != pid) {
78 tst_brkm(TBROK | TERRNO, NULL, "wait(%i) failed: %#x", pid, status);
79 kill(pid, SIGKILL);
80 exit(1);
81 }
82 if (!WIFSTOPPED(status)) {
83 tst_brkm(TBROK, NULL, "child status not stopped: %#x", status);
84 kill(pid, SIGKILL);
85 exit(1);
86 }
87
vapierfeaa8202008-09-24 04:57:32 +000088 return;
vapier8747e0a2008-11-02 06:06:00 +000089 }
vapierfeaa8202008-09-24 04:57:32 +000090
91 errno = 0;
92 long ret = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
93 if (ret && errno) {
94 tst_resm(TFAIL, "PTRACE_TRACEME failed");
95 tst_exit();
96 }
97
98 execlp(argv[0], argv[0], "child", NULL);
99 tst_resm(TFAIL, "execlp() failed");
100 tst_exit();
101}
vapierc665df72008-09-26 23:00:24 +0000102
103#define SPT(x) [PTRACE_##x] = #x,
104static char *strings[] = {
105 SPT(TRACEME)
106 SPT(PEEKTEXT)
107 SPT(PEEKDATA)
108 SPT(PEEKUSER)
109 SPT(POKETEXT)
110 SPT(POKEDATA)
111 SPT(POKEUSER)
subrata_modaka6e0aa52008-10-15 14:17:03 +0000112#ifdef PTRACE_GETREGS
vapierc665df72008-09-26 23:00:24 +0000113 SPT(GETREGS)
subrata_modaka6e0aa52008-10-15 14:17:03 +0000114#endif
115#ifdef PTRACE_SETREGS
vapierc665df72008-09-26 23:00:24 +0000116 SPT(SETREGS)
subrata_modaka6e0aa52008-10-15 14:17:03 +0000117#endif
yaberauneya91a53d32009-10-13 06:29:45 +0000118#ifdef PTRACE_GETSIGINFO
vapierc665df72008-09-26 23:00:24 +0000119 SPT(GETSIGINFO)
yaberauneya91a53d32009-10-13 06:29:45 +0000120#endif
121#ifdef PTRACE_SETSIGINFO
vapierc665df72008-09-26 23:00:24 +0000122 SPT(SETSIGINFO)
yaberauneya91a53d32009-10-13 06:29:45 +0000123#endif
vapierc665df72008-09-26 23:00:24 +0000124#ifdef PTRACE_GETFGREGS
125 SPT(GETFGREGS)
126#endif
127#ifdef PTRACE_SETFGREGS
128 SPT(SETFGREGS)
129#endif
130 SPT(KILL)
131 SPT(SINGLESTEP)
132};
vapierc444d052009-10-07 06:22:02 +0000133static inline char *strptrace(enum __ptrace_request request)
vapierc665df72008-09-26 23:00:24 +0000134{
135 return strings[request];
136}