blob: cbcce4d062c5ed27b0a3fdfa918cc73f8ae6ba82 [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>
Juan Cespedes5c3fe062004-06-14 18:08:37 +02007#include "ptrace.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +01008#include <asm/unistd.h>
9
10#include "ltrace.h"
11#include "options.h"
Ian Wienand9a2ad352006-02-20 22:44:45 +010012#include "sysdep.h"
13
14static int fork_exec_syscalls[][5] = {
15{
16#ifdef __NR_fork
17 __NR_fork,
18#else
19 -1,
20#endif
21#ifdef __NR_clone
22 __NR_clone,
23#else
24 -1,
25#endif
26#ifdef __NR_clone2
27 __NR_clone2,
28#else
29 -1,
30#endif
31#ifdef __NR_vfork
32 __NR_vfork,
33#else
34 -1,
35#endif
36#ifdef __NR_execve
37 __NR_execve,
38#else
39 -1,
40#endif
41}
42#ifdef FORK_EXEC_SYSCALLS
43FORK_EXEC_SYSCALLS
44#endif
45};
Juan Cespedes5e01f651998-03-08 22:31:44 +010046
Juan Cespedes81690ef1998-03-13 19:31:29 +010047/* Returns 1 if the sysnum may make a new child to be created
48 * (ie, with fork() or clone())
49 * Returns 0 otherwise.
50 */
Ian Wienand9a2ad352006-02-20 22:44:45 +010051int
52fork_p(struct process * proc, int sysnum) {
53 int i;
54 if (proc->personality
55 >= sizeof fork_exec_syscalls / sizeof (fork_exec_syscalls [0]))
56 return 0;
57 for (i = 0; i < sizeof (fork_exec_syscalls[0]) / sizeof (int) - 1; ++i)
58 if (sysnum == fork_exec_syscalls[proc->personality][i])
59 return 1;
60 return 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +010061}
62
Juan Cespedes81690ef1998-03-13 19:31:29 +010063/* Returns 1 if the sysnum may make the process exec other program
64 */
Ian Wienand9a2ad352006-02-20 22:44:45 +010065int
66exec_p(struct process * proc, int sysnum) {
67 int i;
68 if (proc->personality
69 >= sizeof fork_exec_syscalls / sizeof (fork_exec_syscalls [0]))
70 return 0;
71 i = sizeof (fork_exec_syscalls[0]) / sizeof (int) - 1;
72 if (sysnum == fork_exec_syscalls[proc->personality][i])
73 return 1;
74 return 0;
Juan Cespedes81690ef1998-03-13 19:31:29 +010075}
76
Ian Wienand9a2ad352006-02-20 22:44:45 +010077void
78trace_me(void) {
79 if (ptrace(PTRACE_TRACEME, 0, 1, 0)<0) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010080 perror("PTRACE_TRACEME");
81 exit(1);
82 }
83}
84
Ian Wienand9a2ad352006-02-20 22:44:45 +010085int
86trace_pid(pid_t pid) {
Juan Cespedes1fe93d51998-03-13 00:29:21 +010087 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +010088 return -1;
Juan Cespedes1fe93d51998-03-13 00:29:21 +010089 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010090 return 0;
91}
92
Ian Wienand9a2ad352006-02-20 22:44:45 +010093void
94trace_set_options(struct process * proc, pid_t pid) {
95#ifndef PTRACE_SETOPTIONS
96 #define PTRACE_SETOPTIONS 0x4200
97#endif
98#ifndef PTRACE_OLDSETOPTIONS
99 #define PTRACE_OLDSETOPTIONS 21
100#endif
101#ifndef PTRACE_O_TRACESYSGOOD
102 #define PTRACE_O_TRACESYSGOOD 0x00000001
103#endif
104 if (proc->tracesysgood & 0x80)
105 return;
106 if (ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0 &&
107 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0) {
108 perror("PTRACE_SETOPTIONS");
109 return;
110 }
111 proc->tracesysgood |= 0x80;
112}
113
114void
115untrace_pid(pid_t pid) {
Juan Cespedes273ea6d1998-03-14 23:02:40 +0100116 ptrace(PTRACE_DETACH, pid, 1, 0);
Juan Cespedes1fe93d51998-03-13 00:29:21 +0100117}
118
Ian Wienand9a2ad352006-02-20 22:44:45 +0100119void
120continue_after_signal(pid_t pid, int signum) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100121 /* We should always trace syscalls to be able to control fork(), clone(), execve()... */
Juan Cespedes5916fda2002-02-25 00:19:21 +0100122 ptrace(PTRACE_SYSCALL, pid, 0, signum);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100123}
124
Ian Wienand9a2ad352006-02-20 22:44:45 +0100125void
126continue_process(pid_t pid) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100127 continue_after_signal(pid, 0);
128}
129
Ian Wienand9a2ad352006-02-20 22:44:45 +0100130void
131continue_enabling_breakpoint(pid_t pid, struct breakpoint * sbp) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200132 enable_breakpoint(pid, sbp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100133 continue_process(pid);
134}
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100135
Ian Wienand9a2ad352006-02-20 22:44:45 +0100136void
137continue_after_breakpoint(struct process *proc, struct breakpoint * sbp) {
138 if (sbp->enabled) disable_breakpoint(proc->pid, sbp);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200139 set_instruction_pointer(proc, sbp->addr);
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100140 if (sbp->enabled == 0) {
141 continue_process(proc->pid);
142 } else {
143 proc->breakpoint_being_enabled = sbp;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100144#if defined __sparc__ || defined __ia64___
145 /* we don't want to singlestep here */
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200146 continue_process(proc->pid);
147#else
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100148 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200149#endif
Juan Cespedes8f8282f2002-03-03 18:58:40 +0100150 }
151}
152
Ian Wienand9a2ad352006-02-20 22:44:45 +0100153int
154umovestr(struct process * proc, void * addr, int len, void * laddr) {
155 union { long a; char c[sizeof(long)]; } a;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100156 int i;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100157 int offset=0;
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100158
Ian Wienand9a2ad352006-02-20 22:44:45 +0100159 while(offset<len) {
160 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr+offset, 0);
161 for(i=0; i<sizeof(long); i++) {
162 if (a.c[i] && offset+i < len) {
163 *(char *)(laddr+offset+i) = a.c[i];
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100164 } else {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100165 *(char *)(laddr+offset+i) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100166 return 0;
167 }
168 }
169 offset += sizeof(long);
170 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100171 *(char *)(laddr+offset) = '\0';
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100172 return 0;
173}