blob: fc2780bffae60216c7ae739050829de5dfc124b3 [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
77extern int arch_umovelong (struct process *, void *, long *, arg_type_info *);
Juan Cespedesf1350522008-12-16 18:19:58 +010078int
79umovelong (struct 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
85umovelong (struct 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
104fork_p(struct 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
118exec_p(struct 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
132was_exec(struct 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) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100164 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100165 perror("PTRACE_TRACEME");
166 exit(1);
167 }
168}
169
Juan Cespedesf1350522008-12-16 18:19:58 +0100170int
171trace_pid(pid_t pid) {
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100172 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100173 return -1;
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100174 }
Petr Machata89a53602007-01-25 18:05:44 +0100175
Juan Cespedes714ee9d2009-04-07 13:28:54 +0200176 /* man ptrace: PTRACE_ATTACH attaches to the process specified
177 in pid. The child is sent a SIGSTOP, but will not
178 necessarily have stopped by the completion of this call;
179 use wait() to wait for the child to stop. */
180 if (waitpid (pid, NULL, 0) != pid) {
181 perror ("trace_pid: waitpid");
182 exit (1);
183 }
184
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100185 return 0;
186}
187
Juan Cespedesf1350522008-12-16 18:19:58 +0100188void
189trace_set_options(struct process *proc, pid_t pid) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100190 if (proc->tracesysgood & 0x80)
191 return;
Petr Machata55ed83b2007-05-17 16:24:15 +0200192
193 long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
194 if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 &&
195 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100196 perror("PTRACE_SETOPTIONS");
197 return;
198 }
199 proc->tracesysgood |= 0x80;
200}
201
Juan Cespedesf1350522008-12-16 18:19:58 +0100202void
203untrace_pid(pid_t pid) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100204 ptrace(PTRACE_DETACH, pid, 1, 0);
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100205}
206
Juan Cespedesf1350522008-12-16 18:19:58 +0100207void
208continue_after_signal(pid_t pid, int signum) {
Juan Cespedese74c80d2009-02-11 11:32:31 +0100209 struct process *proc;
210
211 proc = pid2proc(pid);
212 if (proc && proc->breakpoint_being_enabled) {
213#if defined __sparc__ || defined __ia64___
214 ptrace(PTRACE_SYSCALL, pid, 0, signum);
215#else
216 ptrace(PTRACE_SINGLESTEP, pid, 0, signum);
217#endif
218 } else {
219 ptrace(PTRACE_SYSCALL, pid, 0, signum);
220 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100221}
222
Juan Cespedesf1350522008-12-16 18:19:58 +0100223void
224continue_process(pid_t pid) {
Juan Cespedese74c80d2009-02-11 11:32:31 +0100225 /* We always trace syscalls to control fork(), clone(), execve()... */
226
227 ptrace(PTRACE_SYSCALL, pid, 0, 0);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100228}
229
Juan Cespedesf1350522008-12-16 18:19:58 +0100230void
231continue_enabling_breakpoint(pid_t pid, struct breakpoint *sbp) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200232 enable_breakpoint(pid, sbp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100233 continue_process(pid);
234}
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100235
Juan Cespedesf1350522008-12-16 18:19:58 +0100236void
237continue_after_breakpoint(struct process *proc, struct breakpoint *sbp) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100238 if (sbp->enabled)
239 disable_breakpoint(proc->pid, sbp);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200240 set_instruction_pointer(proc, sbp->addr);
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100241 if (sbp->enabled == 0) {
242 continue_process(proc->pid);
243 } else {
244 proc->breakpoint_being_enabled = sbp;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100245#if defined __sparc__ || defined __ia64___
246 /* we don't want to singlestep here */
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200247 continue_process(proc->pid);
248#else
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100249 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200250#endif
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100251 }
252}
253
Steve Fink7bafff02006-08-07 04:50:42 +0200254/* Read a series of bytes starting at the process's memory address
255 'addr' and continuing until a NUL ('\0') is seen or 'len' bytes
256 have been read.
257*/
Juan Cespedesf1350522008-12-16 18:19:58 +0100258int
259umovestr(struct process *proc, void *addr, int len, void *laddr) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100260 union {
261 long a;
262 char c[sizeof(long)];
263 } a;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100264 int i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100265 int offset = 0;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100266
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100267 while (offset < len) {
268 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0);
269 for (i = 0; i < sizeof(long); i++) {
Paul Gilliam3f1219f2006-04-24 18:25:38 +0200270 if (a.c[i] && offset + (signed)i < len) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100271 *(char *)(laddr + offset + i) = a.c[i];
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100272 } else {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100273 *(char *)(laddr + offset + i) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100274 return 0;
275 }
276 }
277 offset += sizeof(long);
278 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100279 *(char *)(laddr + offset) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100280 return 0;
281}