blob: 0098c1e10f4bb27a2afd8eb978937b2f1621f6fb [file] [log] [blame]
Juan Cespedes5e01f651998-03-08 22:31:44 +01001#include <stdio.h>
Juan Cespedes504a3852003-02-04 23:24:38 +01002#include <stdlib.h>
Juan Cespedes1fe93d51998-03-13 00:29:21 +01003#include <string.h>
4#include <errno.h>
Juan Cespedes8f8282f2002-03-03 18:58:40 +01005#include <unistd.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +01006#include <sys/types.h>
Petr Machata89a53602007-01-25 18:05:44 +01007#include <sys/wait.h>
Juan Cespedes5c3fe062004-06-14 18:08:37 +02008#include "ptrace.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +01009#include <asm/unistd.h>
10
11#include "ltrace.h"
12#include "options.h"
Ian Wienand9a2ad352006-02-20 22:44:45 +010013#include "sysdep.h"
Petr Machata55ed83b2007-05-17 16:24:15 +020014#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 */
Ian Wienand9a2ad352006-02-20 22:44:45 +010042
43static int fork_exec_syscalls[][5] = {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010044 {
Ian Wienand9a2ad352006-02-20 22:44:45 +010045#ifdef __NR_fork
Ian Wienand2d45b1a2006-02-20 22:48:07 +010046 __NR_fork,
Ian Wienand9a2ad352006-02-20 22:44:45 +010047#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +010048 -1,
Ian Wienand9a2ad352006-02-20 22:44:45 +010049#endif
50#ifdef __NR_clone
Ian Wienand2d45b1a2006-02-20 22:48:07 +010051 __NR_clone,
Ian Wienand9a2ad352006-02-20 22:44:45 +010052#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +010053 -1,
Ian Wienand9a2ad352006-02-20 22:44:45 +010054#endif
55#ifdef __NR_clone2
Ian Wienand2d45b1a2006-02-20 22:48:07 +010056 __NR_clone2,
Ian Wienand9a2ad352006-02-20 22:44:45 +010057#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +010058 -1,
Ian Wienand9a2ad352006-02-20 22:44:45 +010059#endif
60#ifdef __NR_vfork
Ian Wienand2d45b1a2006-02-20 22:48:07 +010061 __NR_vfork,
Ian Wienand9a2ad352006-02-20 22:44:45 +010062#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +010063 -1,
Ian Wienand9a2ad352006-02-20 22:44:45 +010064#endif
65#ifdef __NR_execve
Ian Wienand2d45b1a2006-02-20 22:48:07 +010066 __NR_execve,
Ian Wienand9a2ad352006-02-20 22:44:45 +010067#else
Ian Wienand2d45b1a2006-02-20 22:48:07 +010068 -1,
Ian Wienand9a2ad352006-02-20 22:44:45 +010069#endif
Ian Wienand2d45b1a2006-02-20 22:48:07 +010070 }
Ian Wienand9a2ad352006-02-20 22:44:45 +010071#ifdef FORK_EXEC_SYSCALLS
Ian Wienand2d45b1a2006-02-20 22:48:07 +010072 FORK_EXEC_SYSCALLS
Ian Wienand9a2ad352006-02-20 22:44:45 +010073#endif
74};
Juan Cespedes5e01f651998-03-08 22:31:44 +010075
Luis Machado55c5feb2008-03-12 15:56:01 +010076#ifdef ARCH_HAVE_UMOVELONG
Juan Cespedesa8909f72009-04-28 20:02:41 +020077extern int arch_umovelong (Process *, void *, long *, arg_type_info *);
Juan Cespedesf1350522008-12-16 18:19:58 +010078int
Juan Cespedesa8909f72009-04-28 20:02:41 +020079umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
Luis Machado55c5feb2008-03-12 15:56:01 +010080 return arch_umovelong (proc, addr, result, info);
81}
82#else
83/* Read a single long from the process's memory address 'addr' */
Juan Cespedesf1350522008-12-16 18:19:58 +010084int
Juan Cespedesa8909f72009-04-28 20:02:41 +020085umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
Luis Machado55c5feb2008-03-12 15:56:01 +010086 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
Juan Cespedes81690ef1998-03-13 19:31:29 +010099/* Returns 1 if the sysnum may make a new child to be created
100 * (ie, with fork() or clone())
101 * Returns 0 otherwise.
102 */
Juan Cespedesf1350522008-12-16 18:19:58 +0100103int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200104fork_p(Process *proc, int sysnum) {
Paul Gilliam3f1219f2006-04-24 18:25:38 +0200105 unsigned int i;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100106 if (proc->personality
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100107 >= sizeof fork_exec_syscalls / sizeof(fork_exec_syscalls[0]))
108 return 0;
109 for (i = 0; i < sizeof(fork_exec_syscalls[0]) / sizeof(int) - 1; ++i)
Ian Wienand9a2ad352006-02-20 22:44:45 +0100110 if (sysnum == fork_exec_syscalls[proc->personality][i])
111 return 1;
112 return 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100113}
114
Juan Cespedes81690ef1998-03-13 19:31:29 +0100115/* Returns 1 if the sysnum may make the process exec other program
116 */
Juan Cespedesf1350522008-12-16 18:19:58 +0100117int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200118exec_p(Process *proc, int sysnum) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100119 int i;
120 if (proc->personality
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100121 >= sizeof fork_exec_syscalls / sizeof(fork_exec_syscalls[0]))
122 return 0;
123 i = sizeof(fork_exec_syscalls[0]) / sizeof(int) - 1;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100124 if (sysnum == fork_exec_syscalls[proc->personality][i])
125 return 1;
126 return 0;
Juan Cespedes81690ef1998-03-13 19:31:29 +0100127}
128
Petr Machata55ed83b2007-05-17 16:24:15 +0200129/* Check that we just hit an exec.
130 */
Juan Cespedesf1350522008-12-16 18:19:58 +0100131int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200132was_exec(Process *proc, int status) {
Petr Machata55ed83b2007-05-17 16:24:15 +0200133 if (!WIFSTOPPED (status))
134 return 0;
135
136 if (WSTOPSIG (status) == SIGTRAP
137 && (status >> 16) == PTRACE_EVENT_EXEC) {
138 debug (1, "detected exec (PTRACE_EVENT_EXEC)");
139 return 1;
140 }
141
142 if (WSTOPSIG (status) == SIGTRAP
143 && proc->callstack_depth > 0) {
144 /* Check whether this SIGTRAP is received just after
145 execve is called for this process. Ideally we'd
146 like to check that the exec succeeded, but e.g. on
147 s390 we have no way of knowing, because return
148 value is not set to -1 (as it should). Never mind,
149 reseting breakpoints for current process doesn't
150 hurt. */
151 struct callstack_element *elem;
152 elem = &proc->callstack[proc->callstack_depth - 1];
153 if (elem && elem->is_syscall && exec_p(proc, elem->c_un.syscall)) {
154 debug (1, "detected exec (callstack)");
155 return 1;
156 }
157 }
158
159 return 0;
160}
161
Juan Cespedesf1350522008-12-16 18:19:58 +0100162void
163trace_me(void) {
Juan Cespedescd8976d2009-05-14 13:47:58 +0200164 debug(DEBUG_PROCESS, "trace_me: pid=%d\n", getpid());
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100165 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100166 perror("PTRACE_TRACEME");
167 exit(1);
168 }
169}
170
Juan Cespedesf1350522008-12-16 18:19:58 +0100171int
172trace_pid(pid_t pid) {
Juan Cespedescd8976d2009-05-14 13:47:58 +0200173 debug(DEBUG_PROCESS, "trace_pid: pid=%d\n", pid);
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100174 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100175 return -1;
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100176 }
Petr Machata89a53602007-01-25 18:05:44 +0100177
Juan Cespedes714ee9d2009-04-07 13:28:54 +0200178 /* man ptrace: PTRACE_ATTACH attaches to the process specified
179 in pid. The child is sent a SIGSTOP, but will not
180 necessarily have stopped by the completion of this call;
181 use wait() to wait for the child to stop. */
182 if (waitpid (pid, NULL, 0) != pid) {
183 perror ("trace_pid: waitpid");
184 exit (1);
185 }
186
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100187 return 0;
188}
189
Juan Cespedesf1350522008-12-16 18:19:58 +0100190void
Juan Cespedesa8909f72009-04-28 20:02:41 +0200191trace_set_options(Process *proc, pid_t pid) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100192 if (proc->tracesysgood & 0x80)
193 return;
Petr Machata55ed83b2007-05-17 16:24:15 +0200194
Juan Cespedescd8976d2009-05-14 13:47:58 +0200195 debug(DEBUG_PROCESS, "trace_set_options: pid=%d\n", pid);
196
Juan Cespedes1e583132009-04-07 18:17:11 +0200197 long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK |
198 PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE |
199 PTRACE_O_TRACEEXEC;
Petr Machata55ed83b2007-05-17 16:24:15 +0200200 if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 &&
201 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100202 perror("PTRACE_SETOPTIONS");
203 return;
204 }
205 proc->tracesysgood |= 0x80;
206}
207
Juan Cespedesf1350522008-12-16 18:19:58 +0100208void
209untrace_pid(pid_t pid) {
Juan Cespedescd8976d2009-05-14 13:47:58 +0200210 debug(DEBUG_PROCESS, "untrace_pid: pid=%d\n", pid);
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100211 ptrace(PTRACE_DETACH, pid, 1, 0);
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100212}
213
Juan Cespedesf1350522008-12-16 18:19:58 +0100214void
215continue_after_signal(pid_t pid, int signum) {
Juan Cespedesa8909f72009-04-28 20:02:41 +0200216 Process *proc;
Juan Cespedese74c80d2009-02-11 11:32:31 +0100217
Juan Cespedescd8976d2009-05-14 13:47:58 +0200218 debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum);
219
Juan Cespedese74c80d2009-02-11 11:32:31 +0100220 proc = pid2proc(pid);
221 if (proc && proc->breakpoint_being_enabled) {
222#if defined __sparc__ || defined __ia64___
223 ptrace(PTRACE_SYSCALL, pid, 0, signum);
224#else
225 ptrace(PTRACE_SINGLESTEP, pid, 0, signum);
226#endif
227 } else {
228 ptrace(PTRACE_SYSCALL, pid, 0, signum);
229 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100230}
231
Juan Cespedesf1350522008-12-16 18:19:58 +0100232void
233continue_process(pid_t pid) {
Juan Cespedese74c80d2009-02-11 11:32:31 +0100234 /* We always trace syscalls to control fork(), clone(), execve()... */
235
Juan Cespedescd8976d2009-05-14 13:47:58 +0200236 debug(DEBUG_PROCESS, "continue_process: pid=%d", pid);
237
Juan Cespedese74c80d2009-02-11 11:32:31 +0100238 ptrace(PTRACE_SYSCALL, pid, 0, 0);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100239}
240
Juan Cespedesf1350522008-12-16 18:19:58 +0100241void
Juan Cespedes1dec2172009-05-07 10:12:10 +0200242continue_enabling_breakpoint(pid_t pid, Breakpoint *sbp) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200243 enable_breakpoint(pid, sbp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100244 continue_process(pid);
245}
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100246
Juan Cespedesf1350522008-12-16 18:19:58 +0100247void
Juan Cespedes1dec2172009-05-07 10:12:10 +0200248continue_after_breakpoint(Process *proc, Breakpoint *sbp) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100249 if (sbp->enabled)
250 disable_breakpoint(proc->pid, sbp);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200251 set_instruction_pointer(proc, sbp->addr);
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100252 if (sbp->enabled == 0) {
253 continue_process(proc->pid);
254 } else {
Juan Cespedes85f7d762009-05-14 13:53:59 +0200255 debug(DEBUG_PROCESS, "continue_after_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100256 proc->breakpoint_being_enabled = sbp;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100257#if defined __sparc__ || defined __ia64___
258 /* we don't want to singlestep here */
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200259 continue_process(proc->pid);
260#else
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100261 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200262#endif
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100263 }
264}
265
Steve Fink7bafff02006-08-07 04:50:42 +0200266/* Read a series of bytes starting at the process's memory address
267 'addr' and continuing until a NUL ('\0') is seen or 'len' bytes
268 have been read.
269*/
Juan Cespedesf1350522008-12-16 18:19:58 +0100270int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200271umovestr(Process *proc, void *addr, int len, void *laddr) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100272 union {
273 long a;
274 char c[sizeof(long)];
275 } a;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100276 int i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100277 int offset = 0;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100278
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100279 while (offset < len) {
280 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0);
281 for (i = 0; i < sizeof(long); i++) {
Paul Gilliam3f1219f2006-04-24 18:25:38 +0200282 if (a.c[i] && offset + (signed)i < len) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100283 *(char *)(laddr + offset + i) = a.c[i];
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100284 } else {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100285 *(char *)(laddr + offset + i) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100286 return 0;
287 }
288 }
289 offset += sizeof(long);
290 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100291 *(char *)(laddr + offset) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100292 return 0;
293}