trace.c revision 8d1b92ba755f6d6229f5e230fc43d958b13836f8
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	return 0;
59}
60#endif
61
62void
63trace_me(void) {
64	debug(DEBUG_PROCESS, "trace_me: pid=%d\n", getpid());
65	if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
66		perror("PTRACE_TRACEME");
67		exit(1);
68	}
69}
70
71int
72trace_pid(pid_t pid) {
73	debug(DEBUG_PROCESS, "trace_pid: pid=%d\n", pid);
74	if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
75		return -1;
76	}
77
78	/* man ptrace: PTRACE_ATTACH attaches to the process specified
79	   in pid.  The child is sent a SIGSTOP, but will not
80	   necessarily have stopped by the completion of this call;
81	   use wait() to wait for the child to stop. */
82	if (waitpid (pid, NULL, 0) != pid) {
83		perror ("trace_pid: waitpid");
84		exit (1);
85	}
86
87	return 0;
88}
89
90void
91trace_set_options(Process *proc, pid_t pid) {
92	if (proc->tracesysgood & 0x80)
93		return;
94
95	debug(DEBUG_PROCESS, "trace_set_options: pid=%d\n", pid);
96
97	long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK |
98		PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE |
99		PTRACE_O_TRACEEXEC;
100	if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 &&
101	    ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) {
102		perror("PTRACE_SETOPTIONS");
103		return;
104	}
105	proc->tracesysgood |= 0x80;
106}
107
108void
109untrace_pid(pid_t pid) {
110	debug(DEBUG_PROCESS, "untrace_pid: pid=%d\n", pid);
111	ptrace(PTRACE_DETACH, pid, 1, 0);
112}
113
114void
115continue_after_signal(pid_t pid, int signum) {
116	Process *proc;
117
118	debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum);
119
120	proc = pid2proc(pid);
121	if (proc && proc->breakpoint_being_enabled) {
122#if defined __sparc__  || defined __ia64___
123		ptrace(PTRACE_SYSCALL, pid, 0, signum);
124#else
125		ptrace(PTRACE_SINGLESTEP, pid, 0, signum);
126#endif
127	} else {
128		ptrace(PTRACE_SYSCALL, pid, 0, signum);
129	}
130}
131
132void
133continue_process(pid_t pid) {
134	/* We always trace syscalls to control fork(), clone(), execve()... */
135
136	debug(DEBUG_PROCESS, "continue_process: pid=%d", pid);
137
138	ptrace(PTRACE_SYSCALL, pid, 0, 0);
139}
140
141void
142continue_enabling_breakpoint(pid_t pid, Breakpoint *sbp) {
143	enable_breakpoint(pid, sbp);
144	continue_process(pid);
145}
146
147void
148continue_after_breakpoint(Process *proc, Breakpoint *sbp) {
149	if (sbp->enabled)
150		disable_breakpoint(proc->pid, sbp);
151	set_instruction_pointer(proc, sbp->addr);
152	if (sbp->enabled == 0) {
153		continue_process(proc->pid);
154	} else {
155		debug(DEBUG_PROCESS, "continue_after_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
156		proc->breakpoint_being_enabled = sbp;
157#if defined __sparc__  || defined __ia64___
158		/* we don't want to singlestep here */
159		continue_process(proc->pid);
160#else
161		ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
162#endif
163	}
164}
165
166/* Read a series of bytes starting at the process's memory address
167   'addr' and continuing until a NUL ('\0') is seen or 'len' bytes
168   have been read.
169*/
170int
171umovestr(Process *proc, void *addr, int len, void *laddr) {
172	union {
173		long a;
174		char c[sizeof(long)];
175	} a;
176	int i;
177	int offset = 0;
178
179	while (offset < len) {
180		a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0);
181		for (i = 0; i < sizeof(long); i++) {
182			if (a.c[i] && offset + (signed)i < len) {
183				*(char *)(laddr + offset + i) = a.c[i];
184			} else {
185				*(char *)(laddr + offset + i) = '\0';
186				return 0;
187			}
188		}
189		offset += sizeof(long);
190	}
191	*(char *)(laddr + offset) = '\0';
192	return 0;
193}
194