blob: 466c0c297f85def0a0886485582bf326afb10ae3 [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
Juan Cespedes81690ef1998-03-13 19:31:29 +010076/* Returns 1 if the sysnum may make a new child to be created
77 * (ie, with fork() or clone())
78 * Returns 0 otherwise.
79 */
Ian Wienand2d45b1a2006-02-20 22:48:07 +010080int fork_p(struct process *proc, int sysnum)
81{
Paul Gilliam3f1219f2006-04-24 18:25:38 +020082 unsigned int i;
Ian Wienand9a2ad352006-02-20 22:44:45 +010083 if (proc->personality
Ian Wienand2d45b1a2006-02-20 22:48:07 +010084 >= sizeof fork_exec_syscalls / sizeof(fork_exec_syscalls[0]))
85 return 0;
86 for (i = 0; i < sizeof(fork_exec_syscalls[0]) / sizeof(int) - 1; ++i)
Ian Wienand9a2ad352006-02-20 22:44:45 +010087 if (sysnum == fork_exec_syscalls[proc->personality][i])
88 return 1;
89 return 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +010090}
91
Juan Cespedes81690ef1998-03-13 19:31:29 +010092/* Returns 1 if the sysnum may make the process exec other program
93 */
Ian Wienand2d45b1a2006-02-20 22:48:07 +010094int exec_p(struct process *proc, int sysnum)
95{
Ian Wienand9a2ad352006-02-20 22:44:45 +010096 int i;
97 if (proc->personality
Ian Wienand2d45b1a2006-02-20 22:48:07 +010098 >= sizeof fork_exec_syscalls / sizeof(fork_exec_syscalls[0]))
99 return 0;
100 i = sizeof(fork_exec_syscalls[0]) / sizeof(int) - 1;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100101 if (sysnum == fork_exec_syscalls[proc->personality][i])
102 return 1;
103 return 0;
Juan Cespedes81690ef1998-03-13 19:31:29 +0100104}
105
Petr Machata55ed83b2007-05-17 16:24:15 +0200106/* Check that we just hit an exec.
107 */
108int was_exec(struct process *proc, int status)
109{
110 if (!WIFSTOPPED (status))
111 return 0;
112
113 if (WSTOPSIG (status) == SIGTRAP
114 && (status >> 16) == PTRACE_EVENT_EXEC) {
115 debug (1, "detected exec (PTRACE_EVENT_EXEC)");
116 return 1;
117 }
118
119 if (WSTOPSIG (status) == SIGTRAP
120 && proc->callstack_depth > 0) {
121 /* Check whether this SIGTRAP is received just after
122 execve is called for this process. Ideally we'd
123 like to check that the exec succeeded, but e.g. on
124 s390 we have no way of knowing, because return
125 value is not set to -1 (as it should). Never mind,
126 reseting breakpoints for current process doesn't
127 hurt. */
128 struct callstack_element *elem;
129 elem = &proc->callstack[proc->callstack_depth - 1];
130 if (elem && elem->is_syscall && exec_p(proc, elem->c_un.syscall)) {
131 debug (1, "detected exec (callstack)");
132 return 1;
133 }
134 }
135
136 return 0;
137}
138
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100139void trace_me(void)
140{
141 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100142 perror("PTRACE_TRACEME");
143 exit(1);
144 }
145}
146
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100147int trace_pid(pid_t pid)
148{
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100149 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100150 return -1;
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100151 }
Petr Machata89a53602007-01-25 18:05:44 +0100152
153 /* man ptrace: PTRACE_ATTACH attaches to the process specified
154 in pid. The child is sent a SIGSTOP, but will not
155 necessarily have stopped by the completion of this call;
156 use wait() to wait for the child to stop. */
157 if (waitpid (pid, NULL, 0) != pid) {
158 perror ("trace_pid: waitpid");
159 exit (1);
160 }
161
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100162 return 0;
163}
164
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100165void trace_set_options(struct process *proc, pid_t pid)
166{
Ian Wienand9a2ad352006-02-20 22:44:45 +0100167 if (proc->tracesysgood & 0x80)
168 return;
Petr Machata55ed83b2007-05-17 16:24:15 +0200169
170 long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
171 if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 &&
172 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100173 perror("PTRACE_SETOPTIONS");
174 return;
175 }
176 proc->tracesysgood |= 0x80;
177}
178
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100179void untrace_pid(pid_t pid)
180{
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100181 ptrace(PTRACE_DETACH, pid, 1, 0);
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100182}
183
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100184void continue_after_signal(pid_t pid, int signum)
185{
Juan Cespedes5e01f651998-03-08 22:31:44 +0100186 /* We should always trace syscalls to be able to control fork(), clone(), execve()... */
Juan Cespedes5916fda2002-02-25 00:19:21 +0100187 ptrace(PTRACE_SYSCALL, pid, 0, signum);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100188}
189
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100190void continue_process(pid_t pid)
191{
Juan Cespedes5e01f651998-03-08 22:31:44 +0100192 continue_after_signal(pid, 0);
193}
194
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100195void continue_enabling_breakpoint(pid_t pid, struct breakpoint *sbp)
196{
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200197 enable_breakpoint(pid, sbp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100198 continue_process(pid);
199}
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100200
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100201void continue_after_breakpoint(struct process *proc, struct breakpoint *sbp)
202{
203 if (sbp->enabled)
204 disable_breakpoint(proc->pid, sbp);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200205 set_instruction_pointer(proc, sbp->addr);
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100206 if (sbp->enabled == 0) {
207 continue_process(proc->pid);
208 } else {
209 proc->breakpoint_being_enabled = sbp;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100210#if defined __sparc__ || defined __ia64___
211 /* we don't want to singlestep here */
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200212 continue_process(proc->pid);
213#else
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100214 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200215#endif
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100216 }
217}
218
Steve Fink7bafff02006-08-07 04:50:42 +0200219/* Read a single long from the process's memory address 'addr' */
220int umovelong(struct process *proc, void *addr, long *result)
221{
222 long pointed_to;
223
224 errno = 0;
225 pointed_to = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
226 if (pointed_to == -1 && errno)
227 return -errno;
228
229 *result = pointed_to;
230 return 0;
231}
232
233/* 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*/
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100237int umovestr(struct process *proc, void *addr, int len, void *laddr)
238{
239 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}