blob: f348fc8af2665782a3501a8627d5cee6cd526fe0 [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 Cespedes273ea6d1998-03-14 23:02:40 +0100176 return 0;
177}
178
Juan Cespedesf1350522008-12-16 18:19:58 +0100179void
180trace_set_options(struct process *proc, pid_t pid) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100181 if (proc->tracesysgood & 0x80)
182 return;
Petr Machata55ed83b2007-05-17 16:24:15 +0200183
184 long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
185 if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 &&
186 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100187 perror("PTRACE_SETOPTIONS");
188 return;
189 }
190 proc->tracesysgood |= 0x80;
191}
192
Juan Cespedesf1350522008-12-16 18:19:58 +0100193void
194untrace_pid(pid_t pid) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100195 ptrace(PTRACE_DETACH, pid, 1, 0);
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100196}
197
Juan Cespedesf1350522008-12-16 18:19:58 +0100198void
199continue_after_signal(pid_t pid, int signum) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100200 /* We should always trace syscalls to be able to control fork(), clone(), execve()... */
Juan Cespedes5916fda2002-02-25 00:19:21 +0100201 ptrace(PTRACE_SYSCALL, pid, 0, signum);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100202}
203
Juan Cespedesf1350522008-12-16 18:19:58 +0100204void
205continue_process(pid_t pid) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100206 continue_after_signal(pid, 0);
207}
208
Juan Cespedesf1350522008-12-16 18:19:58 +0100209void
210continue_enabling_breakpoint(pid_t pid, struct breakpoint *sbp) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200211 enable_breakpoint(pid, sbp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100212 continue_process(pid);
213}
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100214
Juan Cespedesf1350522008-12-16 18:19:58 +0100215void
216continue_after_breakpoint(struct process *proc, struct breakpoint *sbp) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100217 if (sbp->enabled)
218 disable_breakpoint(proc->pid, sbp);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200219 set_instruction_pointer(proc, sbp->addr);
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100220 if (sbp->enabled == 0) {
221 continue_process(proc->pid);
222 } else {
223 proc->breakpoint_being_enabled = sbp;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100224#if defined __sparc__ || defined __ia64___
225 /* we don't want to singlestep here */
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200226 continue_process(proc->pid);
227#else
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100228 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200229#endif
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100230 }
231}
232
Steve Fink7bafff02006-08-07 04:50:42 +0200233/* Read a series of bytes starting at the process's memory address
234 'addr' and continuing until a NUL ('\0') is seen or 'len' bytes
235 have been read.
236*/
Juan Cespedesf1350522008-12-16 18:19:58 +0100237int
238umovestr(struct process *proc, void *addr, int len, void *laddr) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100239 union {
240 long a;
241 char c[sizeof(long)];
242 } a;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100243 int i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100244 int offset = 0;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100245
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100246 while (offset < len) {
247 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0);
248 for (i = 0; i < sizeof(long); i++) {
Paul Gilliam3f1219f2006-04-24 18:25:38 +0200249 if (a.c[i] && offset + (signed)i < len) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100250 *(char *)(laddr + offset + i) = a.c[i];
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100251 } else {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100252 *(char *)(laddr + offset + i) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100253 return 0;
254 }
255 }
256 offset += sizeof(long);
257 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100258 *(char *)(laddr + offset) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100259 return 0;
260}