trace.c revision f16fcff75f62d44a49ad9c020622956bd2b8df45
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 "common.h"
12
13/* If the system headers did not provide the constants, hard-code the normal
14   values.  */
15#ifndef PTRACE_EVENT_FORK
16
17#define PTRACE_OLDSETOPTIONS    21
18#define PTRACE_SETOPTIONS       0x4200
19#define PTRACE_GETEVENTMSG      0x4201
20
21/* options set using PTRACE_SETOPTIONS */
22#define PTRACE_O_TRACESYSGOOD   0x00000001
23#define PTRACE_O_TRACEFORK      0x00000002
24#define PTRACE_O_TRACEVFORK     0x00000004
25#define PTRACE_O_TRACECLONE     0x00000008
26#define PTRACE_O_TRACEEXEC      0x00000010
27#define PTRACE_O_TRACEVFORKDONE 0x00000020
28#define PTRACE_O_TRACEEXIT      0x00000040
29
30/* Wait extended result codes for the above trace options.  */
31#define PTRACE_EVENT_FORK       1
32#define PTRACE_EVENT_VFORK      2
33#define PTRACE_EVENT_CLONE      3
34#define PTRACE_EVENT_EXEC       4
35#define PTRACE_EVENT_VFORK_DONE 5
36#define PTRACE_EVENT_EXIT       6
37
38#endif /* PTRACE_EVENT_FORK */
39
40#ifdef ARCH_HAVE_UMOVELONG
41extern int arch_umovelong (Process *, void *, long *, arg_type_info *);
42int
43umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
44	return arch_umovelong (proc, addr, result, info);
45}
46#else
47/* Read a single long from the process's memory address 'addr' */
48int
49umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
50	long pointed_to;
51
52	errno = 0;
53	pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0);
54	if (pointed_to == -1 && errno)
55		return -errno;
56
57	*result = pointed_to;
58	if (info) {
59		switch(info->type) {
60			case ARGTYPE_INT:
61				*result &= 0x00000000ffffffffUL;
62			default:
63				break;
64		};
65	}
66	return 0;
67}
68#endif
69
70void
71trace_me(void) {
72	debug(DEBUG_PROCESS, "trace_me: pid=%d\n", getpid());
73	if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
74		perror("PTRACE_TRACEME");
75		exit(1);
76	}
77}
78
79int
80trace_pid(pid_t pid) {
81	debug(DEBUG_PROCESS, "trace_pid: pid=%d\n", pid);
82	if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
83		return -1;
84	}
85
86	/* man ptrace: PTRACE_ATTACH attaches to the process specified
87	   in pid.  The child is sent a SIGSTOP, but will not
88	   necessarily have stopped by the completion of this call;
89	   use wait() to wait for the child to stop. */
90	if (waitpid (pid, NULL, 0) != pid) {
91		perror ("trace_pid: waitpid");
92		exit (1);
93	}
94
95	return 0;
96}
97
98void
99trace_set_options(Process *proc, pid_t pid) {
100	if (proc->tracesysgood & 0x80)
101		return;
102
103	debug(DEBUG_PROCESS, "trace_set_options: pid=%d\n", pid);
104
105	long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK |
106		PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE |
107		PTRACE_O_TRACEEXEC;
108	if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 &&
109	    ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) {
110		perror("PTRACE_SETOPTIONS");
111		return;
112	}
113	proc->tracesysgood |= 0x80;
114}
115
116void
117untrace_pid(pid_t pid) {
118	debug(DEBUG_PROCESS, "untrace_pid: pid=%d\n", pid);
119	ptrace(PTRACE_DETACH, pid, 1, 0);
120}
121
122void
123continue_after_signal(pid_t pid, int signum) {
124	Process *proc;
125
126	debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum);
127
128	proc = pid2proc(pid);
129	if (proc && proc->breakpoint_being_enabled) {
130#if defined __sparc__  || defined __ia64___
131		ptrace(PTRACE_SYSCALL, pid, 0, signum);
132#else
133		ptrace(PTRACE_SINGLESTEP, pid, 0, signum);
134#endif
135	} else {
136		ptrace(PTRACE_SYSCALL, pid, 0, signum);
137	}
138}
139
140void
141continue_process(pid_t pid) {
142	/* We always trace syscalls to control fork(), clone(), execve()... */
143
144	debug(DEBUG_PROCESS, "continue_process: pid=%d", pid);
145
146	ptrace(PTRACE_SYSCALL, pid, 0, 0);
147}
148
149void
150continue_enabling_breakpoint(pid_t pid, Breakpoint *sbp) {
151	enable_breakpoint(pid, sbp);
152	continue_process(pid);
153}
154
155void
156continue_after_breakpoint(Process *proc, Breakpoint *sbp) {
157	if (sbp->enabled)
158		disable_breakpoint(proc->pid, sbp);
159	set_instruction_pointer(proc, sbp->addr);
160	if (sbp->enabled == 0) {
161		continue_process(proc->pid);
162	} else {
163		debug(DEBUG_PROCESS, "continue_after_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
164		proc->breakpoint_being_enabled = sbp;
165#if defined __sparc__  || defined __ia64___
166		/* we don't want to singlestep here */
167		continue_process(proc->pid);
168#else
169		ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
170#endif
171	}
172}
173
174/* Read a series of bytes starting at the process's memory address
175   'addr' and continuing until a NUL ('\0') is seen or 'len' bytes
176   have been read.
177*/
178int
179umovestr(Process *proc, void *addr, int len, void *laddr) {
180	union {
181		long a;
182		char c[sizeof(long)];
183	} a;
184	int i;
185	int offset = 0;
186
187	while (offset < len) {
188		a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0);
189		for (i = 0; i < sizeof(long); i++) {
190			if (a.c[i] && offset + (signed)i < len) {
191				*(char *)(laddr + offset + i) = a.c[i];
192			} else {
193				*(char *)(laddr + offset + i) = '\0';
194				return 0;
195			}
196		}
197		offset += sizeof(long);
198	}
199	*(char *)(laddr + offset) = '\0';
200	return 0;
201}
202