trace.c revision 2721e6adbc7399e1b621b896b4f5b864082fbf03
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <errno.h>
5#include <unistd.h>
6#include <sys/types.h>
7#include <sys/wait.h>
8#include "ptrace.h"
9#include <asm/unistd.h>
10
11#include "ltrace.h"
12#include "options.h"
13#include "sysdep.h"
14#include "debug.h"
15
16/* If the system headers did not provide the constants, hard-code the normal
17   values.  */
18#ifndef PTRACE_EVENT_FORK
19
20#define PTRACE_OLDSETOPTIONS    21
21#define PTRACE_SETOPTIONS       0x4200
22#define PTRACE_GETEVENTMSG      0x4201
23
24/* options set using PTRACE_SETOPTIONS */
25#define PTRACE_O_TRACESYSGOOD   0x00000001
26#define PTRACE_O_TRACEFORK      0x00000002
27#define PTRACE_O_TRACEVFORK     0x00000004
28#define PTRACE_O_TRACECLONE     0x00000008
29#define PTRACE_O_TRACEEXEC      0x00000010
30#define PTRACE_O_TRACEVFORKDONE 0x00000020
31#define PTRACE_O_TRACEEXIT      0x00000040
32
33/* Wait extended result codes for the above trace options.  */
34#define PTRACE_EVENT_FORK       1
35#define PTRACE_EVENT_VFORK      2
36#define PTRACE_EVENT_CLONE      3
37#define PTRACE_EVENT_EXEC       4
38#define PTRACE_EVENT_VFORK_DONE 5
39#define PTRACE_EVENT_EXIT       6
40
41#endif /* PTRACE_EVENT_FORK */
42
43static int fork_exec_syscalls[][5] = {
44	{
45#ifdef __NR_fork
46	 __NR_fork,
47#else
48	 -1,
49#endif
50#ifdef __NR_clone
51	 __NR_clone,
52#else
53	 -1,
54#endif
55#ifdef __NR_clone2
56	 __NR_clone2,
57#else
58	 -1,
59#endif
60#ifdef __NR_vfork
61	 __NR_vfork,
62#else
63	 -1,
64#endif
65#ifdef __NR_execve
66	 __NR_execve,
67#else
68	 -1,
69#endif
70	 }
71#ifdef FORK_EXEC_SYSCALLS
72	FORK_EXEC_SYSCALLS
73#endif
74};
75
76#ifdef ARCH_HAVE_UMOVELONG
77extern int arch_umovelong (Process *, void *, long *, arg_type_info *);
78int
79umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
80	return arch_umovelong (proc, addr, result, info);
81}
82#else
83/* Read a single long from the process's memory address 'addr' */
84int
85umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
86	long pointed_to;
87
88	errno = 0;
89	pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0);
90	if (pointed_to == -1 && errno)
91		return -errno;
92
93	*result = pointed_to;
94	return 0;
95}
96#endif
97
98/* Returns 1 if the sysnum may make the process exec other program
99 */
100int
101exec_p(Process *proc, int sysnum) {
102	int i;
103	if (proc->personality
104	    >= sizeof fork_exec_syscalls / sizeof(fork_exec_syscalls[0]))
105		return 0;
106	i = sizeof(fork_exec_syscalls[0]) / sizeof(int) - 1;
107	if (sysnum == fork_exec_syscalls[proc->personality][i])
108		return 1;
109	return 0;
110}
111
112/* Check that we just hit an exec.
113 */
114int
115was_exec(Process *proc, int status) {
116	if (!WIFSTOPPED (status))
117		return 0;
118
119	if (WSTOPSIG (status) == SIGTRAP
120	    && (status >> 16) == PTRACE_EVENT_EXEC) {
121		debug (1, "detected exec (PTRACE_EVENT_EXEC)");
122		return 1;
123	}
124
125	if (WSTOPSIG (status) == SIGTRAP
126	    && proc->callstack_depth > 0) {
127		/* Check whether this SIGTRAP is received just after
128		   execve is called for this process.  Ideally we'd
129		   like to check that the exec succeeded, but e.g. on
130		   s390 we have no way of knowing, because return
131		   value is not set to -1 (as it should).  Never mind,
132		   reseting breakpoints for current process doesn't
133		   hurt. */
134		struct callstack_element *elem;
135		elem = &proc->callstack[proc->callstack_depth - 1];
136		if (elem && elem->is_syscall &&  exec_p(proc, elem->c_un.syscall)) {
137			debug (1, "detected exec (callstack)");
138			return 1;
139		}
140	}
141
142	return 0;
143}
144
145void
146trace_me(void) {
147	debug(DEBUG_PROCESS, "trace_me: pid=%d\n", getpid());
148	if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
149		perror("PTRACE_TRACEME");
150		exit(1);
151	}
152}
153
154int
155trace_pid(pid_t pid) {
156	debug(DEBUG_PROCESS, "trace_pid: pid=%d\n", pid);
157	if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
158		return -1;
159	}
160
161	/* man ptrace: PTRACE_ATTACH attaches to the process specified
162	   in pid.  The child is sent a SIGSTOP, but will not
163	   necessarily have stopped by the completion of this call;
164	   use wait() to wait for the child to stop. */
165	if (waitpid (pid, NULL, 0) != pid) {
166		perror ("trace_pid: waitpid");
167		exit (1);
168	}
169
170	return 0;
171}
172
173void
174trace_set_options(Process *proc, pid_t pid) {
175	if (proc->tracesysgood & 0x80)
176		return;
177
178	debug(DEBUG_PROCESS, "trace_set_options: pid=%d\n", pid);
179
180	long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK |
181		PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE |
182		PTRACE_O_TRACEEXEC;
183	if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 &&
184	    ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) {
185		perror("PTRACE_SETOPTIONS");
186		return;
187	}
188	proc->tracesysgood |= 0x80;
189}
190
191void
192untrace_pid(pid_t pid) {
193	debug(DEBUG_PROCESS, "untrace_pid: pid=%d\n", pid);
194	ptrace(PTRACE_DETACH, pid, 1, 0);
195}
196
197void
198continue_after_signal(pid_t pid, int signum) {
199	Process *proc;
200
201	debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum);
202
203	proc = pid2proc(pid);
204	if (proc && proc->breakpoint_being_enabled) {
205#if defined __sparc__  || defined __ia64___
206		ptrace(PTRACE_SYSCALL, pid, 0, signum);
207#else
208		ptrace(PTRACE_SINGLESTEP, pid, 0, signum);
209#endif
210	} else {
211		ptrace(PTRACE_SYSCALL, pid, 0, signum);
212	}
213}
214
215void
216continue_process(pid_t pid) {
217	/* We always trace syscalls to control fork(), clone(), execve()... */
218
219	debug(DEBUG_PROCESS, "continue_process: pid=%d", pid);
220
221	ptrace(PTRACE_SYSCALL, pid, 0, 0);
222}
223
224void
225continue_enabling_breakpoint(pid_t pid, Breakpoint *sbp) {
226	enable_breakpoint(pid, sbp);
227	continue_process(pid);
228}
229
230void
231continue_after_breakpoint(Process *proc, Breakpoint *sbp) {
232	if (sbp->enabled)
233		disable_breakpoint(proc->pid, sbp);
234	set_instruction_pointer(proc, sbp->addr);
235	if (sbp->enabled == 0) {
236		continue_process(proc->pid);
237	} else {
238		debug(DEBUG_PROCESS, "continue_after_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
239		proc->breakpoint_being_enabled = sbp;
240#if defined __sparc__  || defined __ia64___
241		/* we don't want to singlestep here */
242		continue_process(proc->pid);
243#else
244		ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
245#endif
246	}
247}
248
249/* Read a series of bytes starting at the process's memory address
250   'addr' and continuing until a NUL ('\0') is seen or 'len' bytes
251   have been read.
252*/
253int
254umovestr(Process *proc, void *addr, int len, void *laddr) {
255	union {
256		long a;
257		char c[sizeof(long)];
258	} a;
259	int i;
260	int offset = 0;
261
262	while (offset < len) {
263		a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0);
264		for (i = 0; i < sizeof(long); i++) {
265			if (a.c[i] && offset + (signed)i < len) {
266				*(char *)(laddr + offset + i) = a.c[i];
267			} else {
268				*(char *)(laddr + offset + i) = '\0';
269				return 0;
270			}
271		}
272		offset += sizeof(long);
273	}
274	*(char *)(laddr + offset) = '\0';
275	return 0;
276}
277